1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
3 config.c for the Openbox window manager
4 Copyright (c) 2006 Mikael Magnusson
5 Copyright (c) 2003-2007 Dana Jansens
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 See the COPYING file for a copy of the GNU General Public License.
21 #include "config_value.h"
25 #include "action_list.h"
26 #include "action_parser.h"
27 #include "translate.h"
32 #include "obt/paths.h"
34 gboolean config_focus_new;
35 gboolean config_focus_follow;
36 guint config_focus_delay;
37 gboolean config_focus_raise;
38 gboolean config_focus_last;
39 gboolean config_focus_under_mouse;
40 gboolean config_unfocus_leave;
42 ObPlacePolicy config_place_policy;
43 gboolean config_place_center;
44 ObPlaceMonitor config_place_monitor;
46 guint config_primary_monitor_index;
47 ObPlaceMonitor config_primary_monitor;
49 StrutPartial config_margins;
52 gboolean config_theme_keepborder;
53 guint config_theme_window_list_icon_size;
55 gchar *config_title_layout;
57 gboolean config_animate_iconify;
59 RrFont *config_font_activewindow;
60 RrFont *config_font_inactivewindow;
61 RrFont *config_font_menuitem;
62 RrFont *config_font_menutitle;
63 RrFont *config_font_activeosd;
64 RrFont *config_font_inactiveosd;
66 guint config_desktops_num;
67 GSList *config_desktops_names;
68 guint config_screen_firstdesk;
69 guint config_desktop_popup_time;
71 gboolean config_resize_redraw;
72 gint config_resize_popup_show;
73 ObResizePopupPos config_resize_popup_pos;
74 GravityPoint config_resize_popup_fixed;
76 ObStackingLayer config_dock_layer;
77 gboolean config_dock_floating;
78 gboolean config_dock_nostrut;
79 ObDirection config_dock_pos;
82 ObOrientation config_dock_orient;
83 gboolean config_dock_hide;
84 guint config_dock_hide_delay;
85 guint config_dock_show_delay;
86 ObMouseButton config_dock_app_move_button;
88 ObKeyboardKey config_keyboard_reset_key;
90 gint config_mouse_threshold;
91 gint config_mouse_dclicktime;
92 gint config_mouse_screenedgetime;
93 gboolean config_mouse_screenedgewarp;
95 guint config_menu_hide_delay;
96 gboolean config_menu_middle;
97 guint config_submenu_show_delay;
98 guint config_submenu_hide_delay;
99 gboolean config_menu_manage_desktops;
100 gboolean config_menu_show_icons;
102 GSList *config_menu_files;
104 gint config_resist_win;
105 gint config_resist_edge;
107 GSList *config_per_app_settings;
109 ObAppSettings* config_create_app_settings(void)
111 ObAppSettings *settings = g_slice_new0(ObAppSettings);
113 settings->decor = -1;
114 settings->shade = -1;
115 settings->monitor = -1;
116 settings->focus = -1;
117 settings->desktop = 0;
118 settings->layer = -2;
119 settings->iconic = -1;
120 settings->skip_pager = -1;
121 settings->skip_taskbar = -1;
122 settings->fullscreen = -1;
123 settings->max_horz = -1;
124 settings->max_vert = -1;
128 #define copy_if(setting, default) \
129 if (src->setting != default) dst->setting = src->setting
130 void config_app_settings_copy_non_defaults(const ObAppSettings *src,
133 g_assert(src != NULL);
134 g_assert(dst != NULL);
136 copy_if(type, (ObClientType)-1);
139 copy_if(monitor, -1);
144 copy_if(skip_pager, -1);
145 copy_if(skip_taskbar, -1);
146 copy_if(fullscreen, -1);
147 copy_if(max_horz, -1);
148 copy_if(max_vert, -1);
150 if (src->pos_given) {
151 dst->pos_given = TRUE;
152 dst->pos_force = src->pos_force;
153 dst->position = src->position;
154 /* monitor is copied above */
160 <application name="aterm">
163 <application name="Rhythmbox">
170 .. there is a lot more settings available
175 /* Manages settings for individual applications.
176 Some notes: monitor is the screen number in a multi monitor
177 (Xinerama) setup (starting from 0) or mouse, meaning the
178 monitor the pointer is on. Default: mouse.
179 Layer can be three values, above (Always on top), below
180 (Always on bottom) and everything else (normal behaviour).
181 Positions can be an integer value or center, which will
182 center the window in the specified axis. Position is within
183 the monitor, so <position><x>center</x></position><monitor>2</monitor>
184 will center the window on the second monitor.
186 static void parse_per_app_settings(xmlNodePtr node, gpointer d)
188 xmlNodePtr app = obt_xml_find_sibling(node->children, "application");
189 gchar *name = NULL, *class = NULL, *role = NULL, *title = NULL,
191 gboolean name_set, class_set, type_set, role_set, title_set;
193 gboolean x_pos_given;
198 class_set = obt_xml_attr_string(app, "class", &class);
199 name_set = obt_xml_attr_string(app, "name", &name);
200 type_set = obt_xml_attr_string(app, "type", &type_str);
201 role_set = obt_xml_attr_string(app, "role", &role);
202 title_set = obt_xml_attr_string(app, "title", &title);
204 /* validate the type tho */
206 if (!g_ascii_strcasecmp(type_str, "normal"))
207 type = OB_CLIENT_TYPE_NORMAL;
208 else if (!g_ascii_strcasecmp(type_str, "dialog"))
209 type = OB_CLIENT_TYPE_DIALOG;
210 else if (!g_ascii_strcasecmp(type_str, "splash"))
211 type = OB_CLIENT_TYPE_SPLASH;
212 else if (!g_ascii_strcasecmp(type_str, "utility"))
213 type = OB_CLIENT_TYPE_UTILITY;
214 else if (!g_ascii_strcasecmp(type_str, "menu"))
215 type = OB_CLIENT_TYPE_MENU;
216 else if (!g_ascii_strcasecmp(type_str, "toolbar"))
217 type = OB_CLIENT_TYPE_TOOLBAR;
218 else if (!g_ascii_strcasecmp(type_str, "dock"))
219 type = OB_CLIENT_TYPE_DOCK;
220 else if (!g_ascii_strcasecmp(type_str, "desktop"))
221 type = OB_CLIENT_TYPE_DESKTOP;
223 type_set = FALSE; /* not valid! */
226 if (class_set || name_set || role_set || title_set || type_set) {
228 ObAppSettings *settings = config_create_app_settings();
231 settings->name = g_pattern_spec_new(name);
234 settings->class = g_pattern_spec_new(class);
237 settings->role = g_pattern_spec_new(role);
240 settings->title = g_pattern_spec_new(title);
243 settings->type = type;
245 if ((n = obt_xml_find_sibling(app->children, "decor")))
246 if (!obt_xml_node_contains(n, "default"))
247 settings->decor = obt_xml_node_bool(n);
249 if ((n = obt_xml_find_sibling(app->children, "shade")))
250 if (!obt_xml_node_contains(n, "default"))
251 settings->shade = obt_xml_node_bool(n);
253 if ((n = obt_xml_find_sibling(app->children, "position"))) {
254 if ((c = obt_xml_find_sibling(n->children, "x")))
255 if (!obt_xml_node_contains(c, "default")) {
256 ObConfigValue *v = config_value_new_string(
257 obt_xml_node_string(node));
258 config_value_gravity_coord(v, &settings->position.x);
259 config_value_unref(v);
263 if (x_pos_given && (c = obt_xml_find_sibling(n->children, "y")))
264 if (!obt_xml_node_contains(c, "default")) {
265 ObConfigValue *v = config_value_new_string(
266 obt_xml_node_string(node));
267 config_value_gravity_coord(v, &settings->position.y);
268 config_value_unref(v);
269 settings->pos_given = TRUE;
272 if (settings->pos_given &&
273 (c = obt_xml_find_sibling(n->children, "monitor")))
274 if (!obt_xml_node_contains(c, "default")) {
275 gchar *s = obt_xml_node_string(c);
276 if (!g_ascii_strcasecmp(s, "mouse"))
277 settings->monitor = 0;
279 settings->monitor = obt_xml_node_int(c);
283 obt_xml_attr_bool(n, "force", &settings->pos_force);
286 if ((n = obt_xml_find_sibling(app->children, "focus")))
287 if (!obt_xml_node_contains(n, "default"))
288 settings->focus = obt_xml_node_bool(n);
290 if ((n = obt_xml_find_sibling(app->children, "desktop"))) {
291 if (!obt_xml_node_contains(n, "default")) {
292 gchar *s = obt_xml_node_string(n);
293 if (!g_ascii_strcasecmp(s, "all"))
294 settings->desktop = DESKTOP_ALL;
296 gint i = obt_xml_node_int(n);
298 settings->desktop = i;
304 if ((n = obt_xml_find_sibling(app->children, "layer")))
305 if (!obt_xml_node_contains(n, "default")) {
306 gchar *s = obt_xml_node_string(n);
307 if (!g_ascii_strcasecmp(s, "above"))
309 else if (!g_ascii_strcasecmp(s, "below"))
310 settings->layer = -1;
316 if ((n = obt_xml_find_sibling(app->children, "iconic")))
317 if (!obt_xml_node_contains(n, "default"))
318 settings->iconic = obt_xml_node_bool(n);
320 if ((n = obt_xml_find_sibling(app->children, "skip_pager")))
321 if (!obt_xml_node_contains(n, "default"))
322 settings->skip_pager = obt_xml_node_bool(n);
324 if ((n = obt_xml_find_sibling(app->children, "skip_taskbar")))
325 if (!obt_xml_node_contains(n, "default"))
326 settings->skip_taskbar = obt_xml_node_bool(n);
328 if ((n = obt_xml_find_sibling(app->children, "fullscreen")))
329 if (!obt_xml_node_contains(n, "default"))
330 settings->fullscreen = obt_xml_node_bool(n);
332 if ((n = obt_xml_find_sibling(app->children, "maximized")))
333 if (!obt_xml_node_contains(n, "default")) {
334 gchar *s = obt_xml_node_string(n);
335 if (!g_ascii_strcasecmp(s, "horizontal")) {
336 settings->max_horz = TRUE;
337 settings->max_vert = FALSE;
338 } else if (!g_ascii_strcasecmp(s, "vertical")) {
339 settings->max_horz = FALSE;
340 settings->max_vert = TRUE;
342 settings->max_horz = settings->max_vert =
343 obt_xml_node_bool(n);
347 config_per_app_settings = g_slist_append(config_per_app_settings,
348 (gpointer) settings);
354 name = class = role = title = type_str = NULL;
357 app = obt_xml_find_sibling(app->next, "application");
364 <action name="ChangeDesktop">
371 static void parse_key(xmlNodePtr node, GList *keylist)
373 gchar *keystring, **keys, **key;
375 gboolean is_chroot = FALSE;
377 if (!obt_xml_attr_string(node, "key", &keystring))
380 obt_xml_attr_bool(node, "chroot", &is_chroot);
382 keys = g_strsplit(keystring, " ", 0);
383 for (key = keys; *key; ++key) {
384 keylist = g_list_append(keylist, *key);
386 if ((n = obt_xml_find_sibling(node->children, "keybind"))) {
388 parse_key(n, keylist);
389 n = obt_xml_find_sibling(n->next, "keybind");
392 else if ((n = obt_xml_find_sibling(node->children, "action"))) {
395 ObActionList *actions;
398 c = xmlNodeGetContent(node);
399 p = action_parser_new();
400 actions = action_parser_read_string(p, (gchar*)c);
402 action_parser_unref(p);
405 keyboard_bind(keylist, actions);
407 action_list_unref(actions);
408 n = obt_xml_find_sibling(n->next, "action");
414 keyboard_chroot(keylist);
415 keylist = g_list_delete_link(keylist, g_list_last(keylist));
422 static void parse_keyboard(xmlNodePtr node, gpointer d)
427 keyboard_unbind_all();
429 if ((n = obt_xml_find_sibling(node->children, "chainQuitKey"))) {
430 key = obt_xml_node_string(n);
431 translate_key(key, &config_keyboard_reset_key.modifiers,
432 &config_keyboard_reset_key.keycode);
436 if ((n = obt_xml_find_sibling(node->children, "keybind")))
439 n = obt_xml_find_sibling(n->next, "keybind");
445 <context name="Titlebar">
446 <mousebind button="Left" action="Press">
447 <action name="Raise"></action>
453 static void parse_mouse(xmlNodePtr node, gpointer d)
455 xmlNodePtr n, nbut, nact;
462 node = node->children;
464 if ((n = obt_xml_find_sibling(node, "dragThreshold")))
465 config_mouse_threshold = obt_xml_node_int(n);
466 if ((n = obt_xml_find_sibling(node, "doubleClickTime")))
467 config_mouse_dclicktime = obt_xml_node_int(n);
468 if ((n = obt_xml_find_sibling(node, "screenEdgeWarpTime"))) {
469 config_mouse_screenedgetime = obt_xml_node_int(n);
470 /* minimum value of 25 for this property, when it is 1 and you hit the
471 edge it basically never stops */
472 if (config_mouse_screenedgetime && config_mouse_screenedgetime < 25)
473 config_mouse_screenedgetime = 25;
475 if ((n = obt_xml_find_sibling(node, "screenEdgeWarpMouse")))
476 config_mouse_screenedgewarp = obt_xml_node_bool(n);
478 n = obt_xml_find_sibling(node, "context");
483 if (!obt_xml_attr_string(n, "name", &cxstr))
486 modcxstr = g_strdup(cxstr); /* make a copy to mutilate */
487 while (frame_next_context_from_string(modcxstr, &cx)) {
489 gchar *s = strchr(modcxstr, ' ');
492 g_message(_("Invalid context \"%s\" in mouse binding"),
499 nbut = obt_xml_find_sibling(n->children, "mousebind");
501 if (!obt_xml_attr_string(nbut, "button", &buttonstr))
503 if (obt_xml_attr_contains(nbut, "action", "press"))
504 mact = OB_MOUSE_ACTION_PRESS;
505 else if (obt_xml_attr_contains(nbut, "action", "release"))
506 mact = OB_MOUSE_ACTION_RELEASE;
507 else if (obt_xml_attr_contains(nbut, "action", "click"))
508 mact = OB_MOUSE_ACTION_CLICK;
509 else if (obt_xml_attr_contains(nbut, "action","doubleclick"))
510 mact = OB_MOUSE_ACTION_DOUBLE_CLICK;
511 else if (obt_xml_attr_contains(nbut, "action", "drag"))
512 mact = OB_MOUSE_ACTION_MOTION;
516 nact = obt_xml_find_sibling(nbut->children, "action");
518 ObActionList *actions;
522 c = xmlNodeGetContent(nact);
523 p = action_parser_new();
524 if ((actions = action_parser_read_string(p, (gchar*)c)))
525 mouse_bind(buttonstr, cx, mact, actions);
526 nact = obt_xml_find_sibling(nact->next, "action");
527 action_list_unref(actions);
529 action_parser_unref(p);
533 nbut = obt_xml_find_sibling(nbut->next, "mousebind");
539 n = obt_xml_find_sibling(n->next, "context");
543 static void parse_focus(xmlNodePtr node, gpointer d)
547 node = node->children;
549 if ((n = obt_xml_find_sibling(node, "focusNew")))
550 config_focus_new = obt_xml_node_bool(n);
551 if ((n = obt_xml_find_sibling(node, "followMouse")))
552 config_focus_follow = obt_xml_node_bool(n);
553 if ((n = obt_xml_find_sibling(node, "focusDelay")))
554 config_focus_delay = obt_xml_node_int(n);
555 if ((n = obt_xml_find_sibling(node, "raiseOnFocus")))
556 config_focus_raise = obt_xml_node_bool(n);
557 if ((n = obt_xml_find_sibling(node, "focusLast")))
558 config_focus_last = obt_xml_node_bool(n);
559 if ((n = obt_xml_find_sibling(node, "underMouse")))
560 config_focus_under_mouse = obt_xml_node_bool(n);
561 if ((n = obt_xml_find_sibling(node, "unfocusOnLeave")))
562 config_unfocus_leave = obt_xml_node_bool(n);
565 static void parse_placement(xmlNodePtr node, gpointer d)
569 node = node->children;
571 if ((n = obt_xml_find_sibling(node, "policy")))
572 if (obt_xml_node_contains(n, "UnderMouse"))
573 config_place_policy = OB_PLACE_POLICY_MOUSE;
574 if ((n = obt_xml_find_sibling(node, "center")))
575 config_place_center = obt_xml_node_bool(n);
576 if ((n = obt_xml_find_sibling(node, "monitor"))) {
577 if (obt_xml_node_contains(n, "active"))
578 config_place_monitor = OB_PLACE_MONITOR_ACTIVE;
579 else if (obt_xml_node_contains(n, "mouse"))
580 config_place_monitor = OB_PLACE_MONITOR_MOUSE;
581 else if (obt_xml_node_contains(n, "any"))
582 config_place_monitor = OB_PLACE_MONITOR_ANY;
584 if ((n = obt_xml_find_sibling(node, "primaryMonitor"))) {
585 config_primary_monitor_index = obt_xml_node_int(n);
586 if (!config_primary_monitor_index) {
587 if (obt_xml_node_contains(n, "mouse"))
588 config_primary_monitor = OB_PLACE_MONITOR_MOUSE;
593 static void parse_margins(xmlNodePtr node, gpointer d)
597 node = node->children;
599 if ((n = obt_xml_find_sibling(node, "top")))
600 config_margins.top = MAX(0, obt_xml_node_int(n));
601 if ((n = obt_xml_find_sibling(node, "left")))
602 config_margins.left = MAX(0, obt_xml_node_int(n));
603 if ((n = obt_xml_find_sibling(node, "right")))
604 config_margins.right = MAX(0, obt_xml_node_int(n));
605 if ((n = obt_xml_find_sibling(node, "bottom")))
606 config_margins.bottom = MAX(0, obt_xml_node_int(n));
609 static void parse_theme(xmlNodePtr node, gpointer d)
613 node = node->children;
615 if ((n = obt_xml_find_sibling(node, "name"))) {
618 g_free(config_theme);
619 c = obt_xml_node_string(n);
620 config_theme = obt_paths_expand_tilde(c);
623 if ((n = obt_xml_find_sibling(node, "titleLayout"))) {
626 g_free(config_title_layout);
627 config_title_layout = obt_xml_node_string(n);
629 /* replace duplicates with spaces */
630 for (c = config_title_layout; *c != '\0'; ++c)
631 for (d = c+1; *d != '\0'; ++d)
632 if (*c == *d) *d = ' ';
634 if ((n = obt_xml_find_sibling(node, "keepBorder")))
635 config_theme_keepborder = obt_xml_node_bool(n);
636 if ((n = obt_xml_find_sibling(node, "animateIconify")))
637 config_animate_iconify = obt_xml_node_bool(n);
638 if ((n = obt_xml_find_sibling(node, "windowListIconSize"))) {
639 config_theme_window_list_icon_size = obt_xml_node_int(n);
640 if (config_theme_window_list_icon_size < 16)
641 config_theme_window_list_icon_size = 16;
642 else if (config_theme_window_list_icon_size > 96)
643 config_theme_window_list_icon_size = 96;
646 n = obt_xml_find_sibling(node, "font");
650 gchar *name = g_strdup(RrDefaultFontFamily);
651 gint size = RrDefaultFontSize;
652 RrFontWeight weight = RrDefaultFontWeight;
653 RrFontSlant slant = RrDefaultFontSlant;
655 if (obt_xml_attr_contains(n, "place", "ActiveWindow"))
656 font = &config_font_activewindow;
657 else if (obt_xml_attr_contains(n, "place", "InactiveWindow"))
658 font = &config_font_inactivewindow;
659 else if (obt_xml_attr_contains(n, "place", "MenuHeader"))
660 font = &config_font_menutitle;
661 else if (obt_xml_attr_contains(n, "place", "MenuItem"))
662 font = &config_font_menuitem;
663 else if (obt_xml_attr_contains(n, "place", "ActiveOnScreenDisplay"))
664 font = &config_font_activeosd;
665 else if (obt_xml_attr_contains(n, "place", "OnScreenDisplay"))
666 font = &config_font_activeosd;
667 else if (obt_xml_attr_contains(n, "place","InactiveOnScreenDisplay"))
668 font = &config_font_inactiveosd;
672 if ((fnode = obt_xml_find_sibling(n->children, "name"))) {
674 name = obt_xml_node_string(fnode);
676 if ((fnode = obt_xml_find_sibling(n->children, "size"))) {
677 int s = obt_xml_node_int(fnode);
680 if ((fnode = obt_xml_find_sibling(n->children, "weight"))) {
681 gchar *w = obt_xml_node_string(fnode);
682 if (!g_ascii_strcasecmp(w, "Bold"))
683 weight = RR_FONTWEIGHT_BOLD;
686 if ((fnode = obt_xml_find_sibling(n->children, "slant"))) {
687 gchar *s = obt_xml_node_string(fnode);
688 if (!g_ascii_strcasecmp(s, "Italic"))
689 slant = RR_FONTSLANT_ITALIC;
690 if (!g_ascii_strcasecmp(s, "Oblique"))
691 slant = RR_FONTSLANT_OBLIQUE;
695 *font = RrFontOpen(ob_rr_inst, name, size, weight, slant);
698 n = obt_xml_find_sibling(n->next, "font");
702 static void parse_desktops(xmlNodePtr node, gpointer d)
706 node = node->children;
708 if ((n = obt_xml_find_sibling(node, "number"))) {
709 gint d = obt_xml_node_int(n);
711 config_desktops_num = (unsigned) d;
713 if ((n = obt_xml_find_sibling(node, "firstdesk"))) {
714 gint d = obt_xml_node_int(n);
716 config_screen_firstdesk = (unsigned) d;
718 if ((n = obt_xml_find_sibling(node, "names"))) {
722 for (it = config_desktops_names; it; it = it->next)
724 g_slist_free(config_desktops_names);
725 config_desktops_names = NULL;
727 nname = obt_xml_find_sibling(n->children, "name");
729 config_desktops_names =
730 g_slist_append(config_desktops_names,
731 obt_xml_node_string(nname));
732 nname = obt_xml_find_sibling(nname->next, "name");
735 if ((n = obt_xml_find_sibling(node, "popupTime")))
736 config_desktop_popup_time = obt_xml_node_int(n);
739 static void parse_resize(xmlNodePtr node, gpointer d)
743 node = node->children;
745 if ((n = obt_xml_find_sibling(node, "drawContents")))
746 config_resize_redraw = obt_xml_node_bool(n);
747 if ((n = obt_xml_find_sibling(node, "popupShow"))) {
748 config_resize_popup_show = obt_xml_node_int(n);
749 if (obt_xml_node_contains(n, "Always"))
750 config_resize_popup_show = 2;
751 else if (obt_xml_node_contains(n, "Never"))
752 config_resize_popup_show = 0;
753 else if (obt_xml_node_contains(n, "Nonpixel"))
754 config_resize_popup_show = 1;
756 if ((n = obt_xml_find_sibling(node, "popupPosition"))) {
757 if (obt_xml_node_contains(n, "Top"))
758 config_resize_popup_pos = OB_RESIZE_POS_TOP;
759 else if (obt_xml_node_contains(n, "Center"))
760 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
761 else if (obt_xml_node_contains(n, "Fixed")) {
762 config_resize_popup_pos = OB_RESIZE_POS_FIXED;
764 if ((n = obt_xml_find_sibling(node, "popupFixedPosition"))) {
767 if ((n2 = obt_xml_find_sibling(n->children, "x"))) {
768 ObConfigValue *v = config_value_new_string(
769 obt_xml_node_string(n2));
770 config_value_gravity_coord(v,
771 &config_resize_popup_fixed.x);
772 config_value_unref(v);
774 if ((n2 = obt_xml_find_sibling(n->children, "y"))) {
775 ObConfigValue *v = config_value_new_string(
776 obt_xml_node_string(n2));
777 config_value_gravity_coord(v,
778 &config_resize_popup_fixed.y);
779 config_value_unref(v);
782 config_resize_popup_fixed.x.pos =
783 MAX(config_resize_popup_fixed.x.pos, 0);
784 config_resize_popup_fixed.y.pos =
785 MAX(config_resize_popup_fixed.y.pos, 0);
791 static void parse_dock(xmlNodePtr node, gpointer d)
795 node = node->children;
797 if ((n = obt_xml_find_sibling(node, "position"))) {
798 if (obt_xml_node_contains(n, "TopLeft"))
799 config_dock_floating = FALSE,
800 config_dock_pos = OB_DIRECTION_NORTHWEST;
801 else if (obt_xml_node_contains(n, "Top"))
802 config_dock_floating = FALSE,
803 config_dock_pos = OB_DIRECTION_NORTH;
804 else if (obt_xml_node_contains(n, "TopRight"))
805 config_dock_floating = FALSE,
806 config_dock_pos = OB_DIRECTION_NORTHEAST;
807 else if (obt_xml_node_contains(n, "Right"))
808 config_dock_floating = FALSE,
809 config_dock_pos = OB_DIRECTION_EAST;
810 else if (obt_xml_node_contains(n, "BottomRight"))
811 config_dock_floating = FALSE,
812 config_dock_pos = OB_DIRECTION_SOUTHEAST;
813 else if (obt_xml_node_contains(n, "Bottom"))
814 config_dock_floating = FALSE,
815 config_dock_pos = OB_DIRECTION_SOUTH;
816 else if (obt_xml_node_contains(n, "BottomLeft"))
817 config_dock_floating = FALSE,
818 config_dock_pos = OB_DIRECTION_SOUTHWEST;
819 else if (obt_xml_node_contains(n, "Left"))
820 config_dock_floating = FALSE,
821 config_dock_pos = OB_DIRECTION_WEST;
822 else if (obt_xml_node_contains(n, "Floating"))
823 config_dock_floating = TRUE;
825 if (config_dock_floating) {
826 if ((n = obt_xml_find_sibling(node, "floatingX")))
827 config_dock_x = obt_xml_node_int(n);
828 if ((n = obt_xml_find_sibling(node, "floatingY")))
829 config_dock_y = obt_xml_node_int(n);
831 if ((n = obt_xml_find_sibling(node, "noStrut")))
832 config_dock_nostrut = obt_xml_node_bool(n);
834 if ((n = obt_xml_find_sibling(node, "stacking"))) {
835 if (obt_xml_node_contains(n, "normal"))
836 config_dock_layer = OB_STACKING_LAYER_NORMAL;
837 else if (obt_xml_node_contains(n, "below"))
838 config_dock_layer = OB_STACKING_LAYER_BELOW;
839 else if (obt_xml_node_contains(n, "above"))
840 config_dock_layer = OB_STACKING_LAYER_ABOVE;
842 if ((n = obt_xml_find_sibling(node, "direction"))) {
843 if (obt_xml_node_contains(n, "horizontal"))
844 config_dock_orient = OB_ORIENTATION_HORZ;
845 else if (obt_xml_node_contains(n, "vertical"))
846 config_dock_orient = OB_ORIENTATION_VERT;
848 if ((n = obt_xml_find_sibling(node, "autoHide")))
849 config_dock_hide = obt_xml_node_bool(n);
850 if ((n = obt_xml_find_sibling(node, "hideDelay")))
851 config_dock_hide_delay = obt_xml_node_int(n);
852 if ((n = obt_xml_find_sibling(node, "showDelay")))
853 config_dock_show_delay = obt_xml_node_int(n);
854 if ((n = obt_xml_find_sibling(node, "moveButton"))) {
855 gchar *str = obt_xml_node_string(n);
857 if (translate_button(str, &s, &b)) {
858 config_dock_app_move_button.button = b;
859 config_dock_app_move_button.modifiers = s;
861 g_message(_("Invalid button \"%s\" specified in config file"), str);
867 static void parse_menu(xmlNodePtr node, gpointer d)
870 node = node->children;
872 if ((n = obt_xml_find_sibling(node, "hideDelay")))
873 config_menu_hide_delay = obt_xml_node_int(n);
874 if ((n = obt_xml_find_sibling(node, "middle")))
875 config_menu_middle = obt_xml_node_bool(n);
876 if ((n = obt_xml_find_sibling(node, "submenuShowDelay")))
877 config_submenu_show_delay = obt_xml_node_int(n);
878 if ((n = obt_xml_find_sibling(node, "submenuHideDelay")))
879 config_submenu_hide_delay = obt_xml_node_int(n);
880 if ((n = obt_xml_find_sibling(node, "manageDesktops")))
881 config_menu_manage_desktops = obt_xml_node_bool(n);
882 if ((n = obt_xml_find_sibling(node, "showIcons"))) {
883 config_menu_show_icons = obt_xml_node_bool(n);
885 if (config_menu_show_icons)
886 g_message(_("Openbox was compiled without Imlib2 image loading support. Icons in menus will not be loaded."));
890 while ((node = obt_xml_find_sibling(node, "file"))) {
891 gchar *c = obt_xml_node_string(node);
892 config_menu_files = g_slist_append(config_menu_files,
893 obt_paths_expand_tilde(c));
899 static void parse_resistance(xmlNodePtr node, gpointer d)
903 node = node->children;
904 if ((n = obt_xml_find_sibling(node, "strength")))
905 config_resist_win = obt_xml_node_int(n);
906 if ((n = obt_xml_find_sibling(node, "screen_edge_strength")))
907 config_resist_edge = obt_xml_node_int(n);
913 const gchar *actiontext;
916 static void bind_default_keyboard(void)
919 ObDefKeyBind binds[] = {
921 "Execute startupnotify:yes name:Konqueror \\\n"
922 " command:(kfmclient openProfile filemanagement)" },
923 { "A-Tab", "NextWindow" },
924 { "S-A-Tab", "PreviousWindow" },
930 p = action_parser_new();
931 for (it = binds; it->key; ++it) {
932 GList *l = g_list_append(NULL, g_strdup(it->key));
933 ObActionList *actions = action_parser_read_string(p, it->actiontext);
934 keyboard_bind(l, actions);
935 action_list_unref(actions);
937 action_parser_unref(p);
943 const gchar *context;
944 const ObMouseAction mact;
945 const gchar *actname;
948 static void bind_default_mouse(void)
951 ObDefMouseBind binds[] = {
952 { "Left", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
953 { "Middle", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
954 { "Right", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
955 { "Left", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
956 { "Middle", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
957 { "Right", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
958 { "Left", "Titlebar", OB_MOUSE_ACTION_PRESS, "Focus" },
959 { "Left", "Bottom", OB_MOUSE_ACTION_PRESS, "Focus" },
960 { "Left", "BLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
961 { "Left", "BRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
962 { "Left", "TLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
963 { "Left", "TRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
964 { "Left", "Close", OB_MOUSE_ACTION_PRESS, "Focus" },
965 { "Left", "Maximize", OB_MOUSE_ACTION_PRESS, "Focus" },
966 { "Left", "Iconify", OB_MOUSE_ACTION_PRESS, "Focus" },
967 { "Left", "Icon", OB_MOUSE_ACTION_PRESS, "Focus" },
968 { "Left", "AllDesktops", OB_MOUSE_ACTION_PRESS, "Focus" },
969 { "Left", "Shade", OB_MOUSE_ACTION_PRESS, "Focus" },
970 { "Left", "Client", OB_MOUSE_ACTION_CLICK, "Raise" },
971 { "Left", "Titlebar", OB_MOUSE_ACTION_CLICK, "Raise" },
972 { "Middle", "Titlebar", OB_MOUSE_ACTION_CLICK, "Lower" },
973 { "Left", "BLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
974 { "Left", "BRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
975 { "Left", "TLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
976 { "Left", "TRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
977 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Raise" },
978 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "Raise" },
979 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Raise" },
980 { "Left", "Icon", OB_MOUSE_ACTION_CLICK, "Raise" },
981 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "Raise" },
982 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "Raise" },
983 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Close" },
984 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "Maximize" },
985 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Iconify" },
986 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "Omnipresent" },
987 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "Shade" },
988 { "Left", "TLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
989 { "Left", "TRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
990 { "Left", "BLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
991 { "Left", "BRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
992 { "Left", "Top", OB_MOUSE_ACTION_MOTION, "Resize" },
993 { "Left", "Bottom", OB_MOUSE_ACTION_MOTION, "Resize" },
994 { "Left", "Left", OB_MOUSE_ACTION_MOTION, "Resize" },
995 { "Left", "Right", OB_MOUSE_ACTION_MOTION, "Resize" },
996 { "Left", "Titlebar", OB_MOUSE_ACTION_MOTION, "Move" },
997 { "A-Left", "Frame", OB_MOUSE_ACTION_MOTION, "Move" },
998 { "A-Middle", "Frame", OB_MOUSE_ACTION_MOTION, "Resize" },
999 { NULL, NULL, 0, NULL }
1002 ObActionList *actions;
1004 p = action_parser_new();
1005 for (it = binds; it->button; ++it) {
1006 actions = action_parser_read_string(p, it->actname);
1007 mouse_bind(it->button, frame_context_from_string(it->context),
1009 action_list_unref(actions);
1011 action_parser_unref(p);
1014 void config_startup(ObtXmlInst *i)
1016 config_focus_new = TRUE;
1017 config_focus_follow = FALSE;
1018 config_focus_delay = 0;
1019 config_focus_raise = FALSE;
1020 config_focus_last = TRUE;
1021 config_focus_under_mouse = FALSE;
1022 config_unfocus_leave = FALSE;
1024 obt_xml_register(i, "focus", parse_focus, NULL);
1026 config_place_policy = OB_PLACE_POLICY_SMART;
1027 config_place_center = TRUE;
1028 config_place_monitor = OB_PLACE_MONITOR_PRIMARY;
1030 config_primary_monitor_index = 1;
1031 config_primary_monitor = OB_PLACE_MONITOR_ACTIVE;
1033 obt_xml_register(i, "placement", parse_placement, NULL);
1035 STRUT_PARTIAL_SET(config_margins, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1037 obt_xml_register(i, "margins", parse_margins, NULL);
1039 config_theme = NULL;
1041 config_animate_iconify = TRUE;
1042 config_title_layout = g_strdup("NLIMC");
1043 config_theme_keepborder = TRUE;
1044 config_theme_window_list_icon_size = 36;
1046 config_font_activewindow = NULL;
1047 config_font_inactivewindow = NULL;
1048 config_font_menuitem = NULL;
1049 config_font_menutitle = NULL;
1050 config_font_activeosd = NULL;
1051 config_font_inactiveosd = NULL;
1053 obt_xml_register(i, "theme", parse_theme, NULL);
1055 config_desktops_num = 4;
1056 config_screen_firstdesk = 1;
1057 config_desktops_names = NULL;
1058 config_desktop_popup_time = 875;
1060 obt_xml_register(i, "desktops", parse_desktops, NULL);
1062 config_resize_redraw = TRUE;
1063 config_resize_popup_show = 1; /* nonpixel increments */
1064 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
1065 GRAVITY_COORD_SET(config_resize_popup_fixed.x, 0, FALSE, FALSE);
1066 GRAVITY_COORD_SET(config_resize_popup_fixed.y, 0, FALSE, FALSE);
1068 obt_xml_register(i, "resize", parse_resize, NULL);
1070 config_dock_layer = OB_STACKING_LAYER_ABOVE;
1071 config_dock_pos = OB_DIRECTION_NORTHEAST;
1072 config_dock_floating = FALSE;
1073 config_dock_nostrut = FALSE;
1076 config_dock_orient = OB_ORIENTATION_VERT;
1077 config_dock_hide = FALSE;
1078 config_dock_hide_delay = 300;
1079 config_dock_show_delay = 300;
1080 config_dock_app_move_button.button = 2; /* middle */
1081 config_dock_app_move_button.modifiers = 0;
1083 obt_xml_register(i, "dock", parse_dock, NULL);
1085 translate_key("C-g", &config_keyboard_reset_key.modifiers,
1086 &config_keyboard_reset_key.keycode);
1088 bind_default_keyboard();
1090 obt_xml_register(i, "keyboard", parse_keyboard, NULL);
1092 config_mouse_threshold = 8;
1093 config_mouse_dclicktime = 200;
1094 config_mouse_screenedgetime = 400;
1095 config_mouse_screenedgewarp = FALSE;
1097 bind_default_mouse();
1099 obt_xml_register(i, "mouse", parse_mouse, NULL);
1101 config_resist_win = 10;
1102 config_resist_edge = 20;
1104 obt_xml_register(i, "resistance", parse_resistance, NULL);
1106 config_menu_hide_delay = 250;
1107 config_menu_middle = FALSE;
1108 config_submenu_show_delay = 100;
1109 config_submenu_hide_delay = 400;
1110 config_menu_manage_desktops = TRUE;
1111 config_menu_files = NULL;
1112 config_menu_show_icons = TRUE;
1114 obt_xml_register(i, "menu", parse_menu, NULL);
1116 config_per_app_settings = NULL;
1118 obt_xml_register(i, "applications", parse_per_app_settings, NULL);
1121 void config_shutdown(void)
1125 g_free(config_theme);
1127 g_free(config_title_layout);
1129 RrFontClose(config_font_activewindow);
1130 RrFontClose(config_font_inactivewindow);
1131 RrFontClose(config_font_menuitem);
1132 RrFontClose(config_font_menutitle);
1133 RrFontClose(config_font_activeosd);
1134 RrFontClose(config_font_inactiveosd);
1136 for (it = config_desktops_names; it; it = g_slist_next(it))
1138 g_slist_free(config_desktops_names);
1140 for (it = config_menu_files; it; it = g_slist_next(it))
1142 g_slist_free(config_menu_files);
1144 for (it = config_per_app_settings; it; it = g_slist_next(it)) {
1145 ObAppSettings *itd = (ObAppSettings *)it->data;
1146 if (itd->name) g_pattern_spec_free(itd->name);
1147 if (itd->role) g_pattern_spec_free(itd->role);
1148 if (itd->title) g_pattern_spec_free(itd->title);
1149 if (itd->class) g_pattern_spec_free(itd->class);
1150 g_slice_free(ObAppSettings, it->data);
1152 g_slist_free(config_per_app_settings);