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 guint config_dock_app_move_button;
87 guint config_dock_app_move_modifiers;
89 guint config_keyboard_reset_keycode;
90 guint config_keyboard_reset_state;
92 gint config_mouse_threshold;
93 gint config_mouse_dclicktime;
94 gint config_mouse_screenedgetime;
95 gboolean config_mouse_screenedgewarp;
97 guint config_menu_hide_delay;
98 gboolean config_menu_middle;
99 guint config_submenu_show_delay;
100 guint config_submenu_hide_delay;
101 gboolean config_menu_manage_desktops;
102 gboolean config_menu_show_icons;
104 GSList *config_menu_files;
106 gint config_resist_win;
107 gint config_resist_edge;
109 GSList *config_per_app_settings;
111 ObAppSettings* config_create_app_settings(void)
113 ObAppSettings *settings = g_slice_new0(ObAppSettings);
115 settings->decor = -1;
116 settings->shade = -1;
117 settings->monitor_type = OB_PLACE_MONITOR_ANY;
118 settings->monitor = -1;
119 settings->focus = -1;
120 settings->desktop = 0;
121 settings->layer = -2;
122 settings->iconic = -1;
123 settings->skip_pager = -1;
124 settings->skip_taskbar = -1;
125 settings->fullscreen = -1;
126 settings->max_horz = -1;
127 settings->max_vert = -1;
131 #define copy_if(setting, default) \
132 if (src->setting != default) dst->setting = src->setting
133 void config_app_settings_copy_non_defaults(const ObAppSettings *src,
136 g_assert(src != NULL);
137 g_assert(dst != NULL);
139 copy_if(type, (ObClientType)-1);
142 copy_if(monitor_type, OB_PLACE_MONITOR_ANY);
143 copy_if(monitor, -1);
148 copy_if(skip_pager, -1);
149 copy_if(skip_taskbar, -1);
150 copy_if(fullscreen, -1);
151 copy_if(max_horz, -1);
152 copy_if(max_vert, -1);
154 if (src->pos_given) {
155 dst->pos_given = TRUE;
156 dst->pos_force = src->pos_force;
157 dst->position = src->position;
158 /* monitor is copied above */
164 <application name="aterm">
167 <application name="Rhythmbox">
174 .. there is a lot more settings available
179 /* Manages settings for individual applications.
180 Some notes: monitor is the screen number in a multi monitor
181 (Xinerama) setup (starting from 0), or mouse: the monitor the pointer
182 is on, active: the active monitor, primary: the primary monitor.
183 Layer can be three values, above (Always on top), below
184 (Always on bottom) and everything else (normal behaviour).
185 Positions can be an integer value or center, which will
186 center the window in the specified axis. Position is within
187 the monitor, so <position><x>center</x></position><monitor>2</monitor>
188 will center the window on the second monitor.
190 static void parse_per_app_settings(xmlNodePtr node, gpointer d)
192 xmlNodePtr app = obt_xml_find_sibling(node->children, "application");
193 gchar *name = NULL, *class = NULL, *role = NULL, *title = NULL,
195 gboolean name_set, class_set, type_set, role_set, title_set;
197 gboolean x_pos_given;
202 class_set = obt_xml_attr_string(app, "class", &class);
203 name_set = obt_xml_attr_string(app, "name", &name);
204 type_set = obt_xml_attr_string(app, "type", &type_str);
205 role_set = obt_xml_attr_string(app, "role", &role);
206 title_set = obt_xml_attr_string(app, "title", &title);
208 /* validate the type tho */
210 if (!g_ascii_strcasecmp(type_str, "normal"))
211 type = OB_CLIENT_TYPE_NORMAL;
212 else if (!g_ascii_strcasecmp(type_str, "dialog"))
213 type = OB_CLIENT_TYPE_DIALOG;
214 else if (!g_ascii_strcasecmp(type_str, "splash"))
215 type = OB_CLIENT_TYPE_SPLASH;
216 else if (!g_ascii_strcasecmp(type_str, "utility"))
217 type = OB_CLIENT_TYPE_UTILITY;
218 else if (!g_ascii_strcasecmp(type_str, "menu"))
219 type = OB_CLIENT_TYPE_MENU;
220 else if (!g_ascii_strcasecmp(type_str, "toolbar"))
221 type = OB_CLIENT_TYPE_TOOLBAR;
222 else if (!g_ascii_strcasecmp(type_str, "dock"))
223 type = OB_CLIENT_TYPE_DOCK;
224 else if (!g_ascii_strcasecmp(type_str, "desktop"))
225 type = OB_CLIENT_TYPE_DESKTOP;
227 type_set = FALSE; /* not valid! */
230 if (class_set || name_set || role_set || title_set || type_set) {
232 ObAppSettings *settings = config_create_app_settings();
235 settings->name = g_pattern_spec_new(name);
238 settings->class = g_pattern_spec_new(class);
241 settings->role = g_pattern_spec_new(role);
244 settings->title = g_pattern_spec_new(title);
247 settings->type = type;
249 if ((n = obt_xml_find_sibling(app->children, "decor")))
250 if (!obt_xml_node_contains(n, "default"))
251 settings->decor = obt_xml_node_bool(n);
253 if ((n = obt_xml_find_sibling(app->children, "shade")))
254 if (!obt_xml_node_contains(n, "default"))
255 settings->shade = obt_xml_node_bool(n);
257 if ((n = obt_xml_find_sibling(app->children, "position"))) {
258 if ((c = obt_xml_find_sibling(n->children, "x")))
259 if (!obt_xml_node_contains(c, "default")) {
260 ObConfigValue *v = config_value_new_string(
261 obt_xml_node_string(node));
262 config_value_gravity_coord(v, &settings->position.x);
263 config_value_unref(v);
267 if (x_pos_given && (c = obt_xml_find_sibling(n->children, "y")))
268 if (!obt_xml_node_contains(c, "default")) {
269 ObConfigValue *v = config_value_new_string(
270 obt_xml_node_string(node));
271 config_value_gravity_coord(v, &settings->position.y);
272 config_value_unref(v);
273 settings->pos_given = TRUE;
276 /* monitor can be set without setting x or y */
277 if ((c = obt_xml_find_sibling(n->children, "monitor")))
278 if (!obt_xml_node_contains(c, "default")) {
279 gchar *s = obt_xml_node_string(c);
280 if (!g_ascii_strcasecmp(s, "mouse"))
281 settings->monitor_type =
282 OB_PLACE_MONITOR_MOUSE;
283 else if (!g_ascii_strcasecmp(s, "active"))
284 settings->monitor_type =
285 OB_PLACE_MONITOR_ACTIVE;
286 else if (!g_ascii_strcasecmp(s, "primary"))
287 settings->monitor_type =
288 OB_PLACE_MONITOR_PRIMARY;
290 settings->monitor = obt_xml_node_int(c);
294 obt_xml_attr_bool(n, "force", &settings->pos_force);
297 if ((n = obt_xml_find_sibling(app->children, "focus")))
298 if (!obt_xml_node_contains(n, "default"))
299 settings->focus = obt_xml_node_bool(n);
301 if ((n = obt_xml_find_sibling(app->children, "desktop"))) {
302 if (!obt_xml_node_contains(n, "default")) {
303 gchar *s = obt_xml_node_string(n);
304 if (!g_ascii_strcasecmp(s, "all"))
305 settings->desktop = DESKTOP_ALL;
307 gint i = obt_xml_node_int(n);
309 settings->desktop = i;
315 if ((n = obt_xml_find_sibling(app->children, "layer")))
316 if (!obt_xml_node_contains(n, "default")) {
317 gchar *s = obt_xml_node_string(n);
318 if (!g_ascii_strcasecmp(s, "above"))
320 else if (!g_ascii_strcasecmp(s, "below"))
321 settings->layer = -1;
327 if ((n = obt_xml_find_sibling(app->children, "iconic")))
328 if (!obt_xml_node_contains(n, "default"))
329 settings->iconic = obt_xml_node_bool(n);
331 if ((n = obt_xml_find_sibling(app->children, "skip_pager")))
332 if (!obt_xml_node_contains(n, "default"))
333 settings->skip_pager = obt_xml_node_bool(n);
335 if ((n = obt_xml_find_sibling(app->children, "skip_taskbar")))
336 if (!obt_xml_node_contains(n, "default"))
337 settings->skip_taskbar = obt_xml_node_bool(n);
339 if ((n = obt_xml_find_sibling(app->children, "fullscreen")))
340 if (!obt_xml_node_contains(n, "default"))
341 settings->fullscreen = obt_xml_node_bool(n);
343 if ((n = obt_xml_find_sibling(app->children, "maximized")))
344 if (!obt_xml_node_contains(n, "default")) {
345 gchar *s = obt_xml_node_string(n);
346 if (!g_ascii_strcasecmp(s, "horizontal")) {
347 settings->max_horz = TRUE;
348 settings->max_vert = FALSE;
349 } else if (!g_ascii_strcasecmp(s, "vertical")) {
350 settings->max_horz = FALSE;
351 settings->max_vert = TRUE;
353 settings->max_horz = settings->max_vert =
354 obt_xml_node_bool(n);
358 config_per_app_settings = g_slist_append(config_per_app_settings,
359 (gpointer) settings);
365 name = class = role = title = type_str = NULL;
368 app = obt_xml_find_sibling(app->next, "application");
375 <action name="ChangeDesktop">
382 static void parse_key(xmlNodePtr node, GList *keylist)
384 gchar *keystring, **keys, **key;
386 gboolean is_chroot = FALSE;
388 if (!obt_xml_attr_string(node, "key", &keystring))
391 obt_xml_attr_bool(node, "chroot", &is_chroot);
393 keys = g_strsplit(keystring, " ", 0);
394 for (key = keys; *key; ++key) {
395 keylist = g_list_append(keylist, *key);
397 if ((n = obt_xml_find_sibling(node->children, "keybind"))) {
399 parse_key(n, keylist);
400 n = obt_xml_find_sibling(n->next, "keybind");
403 else if ((n = obt_xml_find_sibling(node->children, "action"))) {
406 ObActionList *actions;
409 c = xmlNodeGetContent(node);
410 p = action_parser_new();
411 actions = action_parser_read_string(p, (gchar*)c);
413 action_parser_unref(p);
416 keyboard_bind(keylist, actions);
418 action_list_unref(actions);
419 n = obt_xml_find_sibling(n->next, "action");
425 keyboard_chroot(keylist);
426 keylist = g_list_delete_link(keylist, g_list_last(keylist));
433 static void parse_keyboard(xmlNodePtr node, gpointer d)
438 keyboard_unbind_all();
440 if ((n = obt_xml_find_sibling(node->children, "chainQuitKey"))) {
441 key = obt_xml_node_string(n);
442 translate_key(key, &config_keyboard_reset_state,
443 &config_keyboard_reset_keycode);
447 if ((n = obt_xml_find_sibling(node->children, "keybind")))
450 n = obt_xml_find_sibling(n->next, "keybind");
456 <context name="Titlebar">
457 <mousebind button="Left" action="Press">
458 <action name="Raise"></action>
464 static void parse_mouse(xmlNodePtr node, gpointer d)
466 xmlNodePtr n, nbut, nact;
473 node = node->children;
475 if ((n = obt_xml_find_sibling(node, "dragThreshold")))
476 config_mouse_threshold = obt_xml_node_int(n);
477 if ((n = obt_xml_find_sibling(node, "doubleClickTime")))
478 config_mouse_dclicktime = obt_xml_node_int(n);
479 if ((n = obt_xml_find_sibling(node, "screenEdgeWarpTime"))) {
480 config_mouse_screenedgetime = obt_xml_node_int(n);
481 /* minimum value of 25 for this property, when it is 1 and you hit the
482 edge it basically never stops */
483 if (config_mouse_screenedgetime && config_mouse_screenedgetime < 25)
484 config_mouse_screenedgetime = 25;
486 if ((n = obt_xml_find_sibling(node, "screenEdgeWarpMouse")))
487 config_mouse_screenedgewarp = obt_xml_node_bool(n);
489 n = obt_xml_find_sibling(node, "context");
494 if (!obt_xml_attr_string(n, "name", &cxstr))
497 modcxstr = g_strdup(cxstr); /* make a copy to mutilate */
498 while (frame_next_context_from_string(modcxstr, &cx)) {
500 gchar *s = strchr(modcxstr, ' ');
503 g_message(_("Invalid context \"%s\" in mouse binding"),
510 nbut = obt_xml_find_sibling(n->children, "mousebind");
512 if (!obt_xml_attr_string(nbut, "button", &buttonstr))
514 if (obt_xml_attr_contains(nbut, "action", "press"))
515 mact = OB_MOUSE_ACTION_PRESS;
516 else if (obt_xml_attr_contains(nbut, "action", "release"))
517 mact = OB_MOUSE_ACTION_RELEASE;
518 else if (obt_xml_attr_contains(nbut, "action", "click"))
519 mact = OB_MOUSE_ACTION_CLICK;
520 else if (obt_xml_attr_contains(nbut, "action","doubleclick"))
521 mact = OB_MOUSE_ACTION_DOUBLE_CLICK;
522 else if (obt_xml_attr_contains(nbut, "action", "drag"))
523 mact = OB_MOUSE_ACTION_MOTION;
527 nact = obt_xml_find_sibling(nbut->children, "action");
529 ObActionList *actions;
533 c = xmlNodeGetContent(nact);
534 p = action_parser_new();
535 if ((actions = action_parser_read_string(p, (gchar*)c)))
536 mouse_bind(buttonstr, cx, mact, actions);
537 nact = obt_xml_find_sibling(nact->next, "action");
538 action_list_unref(actions);
540 action_parser_unref(p);
544 nbut = obt_xml_find_sibling(nbut->next, "mousebind");
550 n = obt_xml_find_sibling(n->next, "context");
554 static void parse_focus(xmlNodePtr node, gpointer d)
558 node = node->children;
560 if ((n = obt_xml_find_sibling(node, "focusNew")))
561 config_focus_new = obt_xml_node_bool(n);
562 if ((n = obt_xml_find_sibling(node, "followMouse")))
563 config_focus_follow = obt_xml_node_bool(n);
564 if ((n = obt_xml_find_sibling(node, "focusDelay")))
565 config_focus_delay = obt_xml_node_int(n);
566 if ((n = obt_xml_find_sibling(node, "raiseOnFocus")))
567 config_focus_raise = obt_xml_node_bool(n);
568 if ((n = obt_xml_find_sibling(node, "focusLast")))
569 config_focus_last = obt_xml_node_bool(n);
570 if ((n = obt_xml_find_sibling(node, "underMouse")))
571 config_focus_under_mouse = obt_xml_node_bool(n);
572 if ((n = obt_xml_find_sibling(node, "unfocusOnLeave")))
573 config_unfocus_leave = obt_xml_node_bool(n);
576 static void parse_placement(xmlNodePtr node, gpointer d)
580 node = node->children;
582 if ((n = obt_xml_find_sibling(node, "policy")))
583 if (obt_xml_node_contains(n, "UnderMouse"))
584 config_place_policy = OB_PLACE_POLICY_MOUSE;
585 if ((n = obt_xml_find_sibling(node, "center")))
586 config_place_center = obt_xml_node_bool(n);
587 if ((n = obt_xml_find_sibling(node, "monitor"))) {
588 if (obt_xml_node_contains(n, "active"))
589 config_place_monitor = OB_PLACE_MONITOR_ACTIVE;
590 else if (obt_xml_node_contains(n, "mouse"))
591 config_place_monitor = OB_PLACE_MONITOR_MOUSE;
592 else if (obt_xml_node_contains(n, "any"))
593 config_place_monitor = OB_PLACE_MONITOR_ANY;
595 if ((n = obt_xml_find_sibling(node, "primaryMonitor"))) {
596 config_primary_monitor_index = obt_xml_node_int(n);
597 if (!config_primary_monitor_index) {
598 if (obt_xml_node_contains(n, "mouse"))
599 config_primary_monitor = OB_PLACE_MONITOR_MOUSE;
604 static void parse_margins(xmlNodePtr node, gpointer d)
608 node = node->children;
610 if ((n = obt_xml_find_sibling(node, "top")))
611 config_margins.top = MAX(0, obt_xml_node_int(n));
612 if ((n = obt_xml_find_sibling(node, "left")))
613 config_margins.left = MAX(0, obt_xml_node_int(n));
614 if ((n = obt_xml_find_sibling(node, "right")))
615 config_margins.right = MAX(0, obt_xml_node_int(n));
616 if ((n = obt_xml_find_sibling(node, "bottom")))
617 config_margins.bottom = MAX(0, obt_xml_node_int(n));
620 static void parse_theme(xmlNodePtr node, gpointer d)
624 node = node->children;
626 if ((n = obt_xml_find_sibling(node, "name"))) {
629 g_free(config_theme);
630 c = obt_xml_node_string(n);
631 config_theme = obt_paths_expand_tilde(c);
634 if ((n = obt_xml_find_sibling(node, "titleLayout"))) {
637 g_free(config_title_layout);
638 config_title_layout = obt_xml_node_string(n);
640 /* replace duplicates with spaces */
641 for (c = config_title_layout; *c != '\0'; ++c)
642 for (d = c+1; *d != '\0'; ++d)
643 if (*c == *d) *d = ' ';
645 if ((n = obt_xml_find_sibling(node, "keepBorder")))
646 config_theme_keepborder = obt_xml_node_bool(n);
647 if ((n = obt_xml_find_sibling(node, "animateIconify")))
648 config_animate_iconify = obt_xml_node_bool(n);
649 if ((n = obt_xml_find_sibling(node, "windowListIconSize"))) {
650 config_theme_window_list_icon_size = obt_xml_node_int(n);
651 if (config_theme_window_list_icon_size < 16)
652 config_theme_window_list_icon_size = 16;
653 else if (config_theme_window_list_icon_size > 96)
654 config_theme_window_list_icon_size = 96;
657 n = obt_xml_find_sibling(node, "font");
661 gchar *name = g_strdup(RrDefaultFontFamily);
662 gint size = RrDefaultFontSize;
663 RrFontWeight weight = RrDefaultFontWeight;
664 RrFontSlant slant = RrDefaultFontSlant;
666 if (obt_xml_attr_contains(n, "place", "ActiveWindow"))
667 font = &config_font_activewindow;
668 else if (obt_xml_attr_contains(n, "place", "InactiveWindow"))
669 font = &config_font_inactivewindow;
670 else if (obt_xml_attr_contains(n, "place", "MenuHeader"))
671 font = &config_font_menutitle;
672 else if (obt_xml_attr_contains(n, "place", "MenuItem"))
673 font = &config_font_menuitem;
674 else if (obt_xml_attr_contains(n, "place", "ActiveOnScreenDisplay"))
675 font = &config_font_activeosd;
676 else if (obt_xml_attr_contains(n, "place", "OnScreenDisplay"))
677 font = &config_font_activeosd;
678 else if (obt_xml_attr_contains(n, "place","InactiveOnScreenDisplay"))
679 font = &config_font_inactiveosd;
683 if ((fnode = obt_xml_find_sibling(n->children, "name"))) {
685 name = obt_xml_node_string(fnode);
687 if ((fnode = obt_xml_find_sibling(n->children, "size"))) {
688 int s = obt_xml_node_int(fnode);
691 if ((fnode = obt_xml_find_sibling(n->children, "weight"))) {
692 gchar *w = obt_xml_node_string(fnode);
693 if (!g_ascii_strcasecmp(w, "Bold"))
694 weight = RR_FONTWEIGHT_BOLD;
697 if ((fnode = obt_xml_find_sibling(n->children, "slant"))) {
698 gchar *s = obt_xml_node_string(fnode);
699 if (!g_ascii_strcasecmp(s, "Italic"))
700 slant = RR_FONTSLANT_ITALIC;
701 if (!g_ascii_strcasecmp(s, "Oblique"))
702 slant = RR_FONTSLANT_OBLIQUE;
706 *font = RrFontOpen(ob_rr_inst, name, size, weight, slant);
709 n = obt_xml_find_sibling(n->next, "font");
713 static void parse_desktops(xmlNodePtr node, gpointer d)
717 node = node->children;
719 if ((n = obt_xml_find_sibling(node, "number"))) {
720 gint d = obt_xml_node_int(n);
722 config_desktops_num = (unsigned) d;
724 if ((n = obt_xml_find_sibling(node, "firstdesk"))) {
725 gint d = obt_xml_node_int(n);
727 config_screen_firstdesk = (unsigned) d;
729 if ((n = obt_xml_find_sibling(node, "names"))) {
733 for (it = config_desktops_names; it; it = it->next)
735 g_slist_free(config_desktops_names);
736 config_desktops_names = NULL;
738 nname = obt_xml_find_sibling(n->children, "name");
740 config_desktops_names =
741 g_slist_append(config_desktops_names,
742 obt_xml_node_string(nname));
743 nname = obt_xml_find_sibling(nname->next, "name");
746 if ((n = obt_xml_find_sibling(node, "popupTime")))
747 config_desktop_popup_time = obt_xml_node_int(n);
750 static void parse_resize(xmlNodePtr node, gpointer d)
754 node = node->children;
756 if ((n = obt_xml_find_sibling(node, "drawContents")))
757 config_resize_redraw = obt_xml_node_bool(n);
758 if ((n = obt_xml_find_sibling(node, "popupShow"))) {
759 config_resize_popup_show = obt_xml_node_int(n);
760 if (obt_xml_node_contains(n, "Always"))
761 config_resize_popup_show = 2;
762 else if (obt_xml_node_contains(n, "Never"))
763 config_resize_popup_show = 0;
764 else if (obt_xml_node_contains(n, "Nonpixel"))
765 config_resize_popup_show = 1;
767 if ((n = obt_xml_find_sibling(node, "popupPosition"))) {
768 if (obt_xml_node_contains(n, "Top"))
769 config_resize_popup_pos = OB_RESIZE_POS_TOP;
770 else if (obt_xml_node_contains(n, "Center"))
771 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
772 else if (obt_xml_node_contains(n, "Fixed")) {
773 config_resize_popup_pos = OB_RESIZE_POS_FIXED;
775 if ((n = obt_xml_find_sibling(node, "popupFixedPosition"))) {
778 if ((n2 = obt_xml_find_sibling(n->children, "x"))) {
779 ObConfigValue *v = config_value_new_string(
780 obt_xml_node_string(n2));
781 config_value_gravity_coord(v,
782 &config_resize_popup_fixed.x);
783 config_value_unref(v);
785 if ((n2 = obt_xml_find_sibling(n->children, "y"))) {
786 ObConfigValue *v = config_value_new_string(
787 obt_xml_node_string(n2));
788 config_value_gravity_coord(v,
789 &config_resize_popup_fixed.y);
790 config_value_unref(v);
793 config_resize_popup_fixed.x.pos =
794 MAX(config_resize_popup_fixed.x.pos, 0);
795 config_resize_popup_fixed.y.pos =
796 MAX(config_resize_popup_fixed.y.pos, 0);
802 static void parse_dock(xmlNodePtr node, gpointer d)
806 node = node->children;
808 if ((n = obt_xml_find_sibling(node, "position"))) {
809 if (obt_xml_node_contains(n, "TopLeft"))
810 config_dock_floating = FALSE,
811 config_dock_pos = OB_DIRECTION_NORTHWEST;
812 else if (obt_xml_node_contains(n, "Top"))
813 config_dock_floating = FALSE,
814 config_dock_pos = OB_DIRECTION_NORTH;
815 else if (obt_xml_node_contains(n, "TopRight"))
816 config_dock_floating = FALSE,
817 config_dock_pos = OB_DIRECTION_NORTHEAST;
818 else if (obt_xml_node_contains(n, "Right"))
819 config_dock_floating = FALSE,
820 config_dock_pos = OB_DIRECTION_EAST;
821 else if (obt_xml_node_contains(n, "BottomRight"))
822 config_dock_floating = FALSE,
823 config_dock_pos = OB_DIRECTION_SOUTHEAST;
824 else if (obt_xml_node_contains(n, "Bottom"))
825 config_dock_floating = FALSE,
826 config_dock_pos = OB_DIRECTION_SOUTH;
827 else if (obt_xml_node_contains(n, "BottomLeft"))
828 config_dock_floating = FALSE,
829 config_dock_pos = OB_DIRECTION_SOUTHWEST;
830 else if (obt_xml_node_contains(n, "Left"))
831 config_dock_floating = FALSE,
832 config_dock_pos = OB_DIRECTION_WEST;
833 else if (obt_xml_node_contains(n, "Floating"))
834 config_dock_floating = TRUE;
836 if (config_dock_floating) {
837 if ((n = obt_xml_find_sibling(node, "floatingX")))
838 config_dock_x = obt_xml_node_int(n);
839 if ((n = obt_xml_find_sibling(node, "floatingY")))
840 config_dock_y = obt_xml_node_int(n);
842 if ((n = obt_xml_find_sibling(node, "noStrut")))
843 config_dock_nostrut = obt_xml_node_bool(n);
845 if ((n = obt_xml_find_sibling(node, "stacking"))) {
846 if (obt_xml_node_contains(n, "normal"))
847 config_dock_layer = OB_STACKING_LAYER_NORMAL;
848 else if (obt_xml_node_contains(n, "below"))
849 config_dock_layer = OB_STACKING_LAYER_BELOW;
850 else if (obt_xml_node_contains(n, "above"))
851 config_dock_layer = OB_STACKING_LAYER_ABOVE;
853 if ((n = obt_xml_find_sibling(node, "direction"))) {
854 if (obt_xml_node_contains(n, "horizontal"))
855 config_dock_orient = OB_ORIENTATION_HORZ;
856 else if (obt_xml_node_contains(n, "vertical"))
857 config_dock_orient = OB_ORIENTATION_VERT;
859 if ((n = obt_xml_find_sibling(node, "autoHide")))
860 config_dock_hide = obt_xml_node_bool(n);
861 if ((n = obt_xml_find_sibling(node, "hideDelay")))
862 config_dock_hide_delay = obt_xml_node_int(n);
863 if ((n = obt_xml_find_sibling(node, "showDelay")))
864 config_dock_show_delay = obt_xml_node_int(n);
865 if ((n = obt_xml_find_sibling(node, "moveButton"))) {
866 gchar *str = obt_xml_node_string(n);
868 if (translate_button(str, &s, &b)) {
869 config_dock_app_move_button = b;
870 config_dock_app_move_modifiers = s;
872 g_message(_("Invalid button \"%s\" specified in config file"), str);
878 static void parse_menu(xmlNodePtr node, gpointer d)
881 node = node->children;
883 if ((n = obt_xml_find_sibling(node, "hideDelay")))
884 config_menu_hide_delay = obt_xml_node_int(n);
885 if ((n = obt_xml_find_sibling(node, "middle")))
886 config_menu_middle = obt_xml_node_bool(n);
887 if ((n = obt_xml_find_sibling(node, "submenuShowDelay")))
888 config_submenu_show_delay = obt_xml_node_int(n);
889 if ((n = obt_xml_find_sibling(node, "submenuHideDelay")))
890 config_submenu_hide_delay = obt_xml_node_int(n);
891 if ((n = obt_xml_find_sibling(node, "manageDesktops")))
892 config_menu_manage_desktops = obt_xml_node_bool(n);
893 if ((n = obt_xml_find_sibling(node, "showIcons"))) {
894 config_menu_show_icons = obt_xml_node_bool(n);
896 if (config_menu_show_icons)
897 g_message(_("Openbox was compiled without Imlib2 image loading support. Icons in menus will not be loaded."));
901 while ((node = obt_xml_find_sibling(node, "file"))) {
902 gchar *c = obt_xml_node_string(node);
903 config_menu_files = g_slist_append(config_menu_files,
904 obt_paths_expand_tilde(c));
910 static void parse_resistance(xmlNodePtr node, gpointer d)
914 node = node->children;
915 if ((n = obt_xml_find_sibling(node, "strength")))
916 config_resist_win = obt_xml_node_int(n);
917 if ((n = obt_xml_find_sibling(node, "screen_edge_strength")))
918 config_resist_edge = obt_xml_node_int(n);
924 const gchar *actiontext;
927 static void bind_default_keyboard(void)
930 ObDefKeyBind binds[] = {
932 "Execute startupnotify:yes name:Konqueror \\\n"
933 " command:(kfmclient openProfile filemanagement)" },
934 { "A-Tab", "NextWindow" },
935 { "S-A-Tab", "PreviousWindow" },
941 p = action_parser_new();
942 for (it = binds; it->key; ++it) {
943 GList *l = g_list_append(NULL, g_strdup(it->key));
944 ObActionList *actions = action_parser_read_string(p, it->actiontext);
945 keyboard_bind(l, actions);
946 action_list_unref(actions);
948 action_parser_unref(p);
954 const gchar *context;
955 const ObMouseAction mact;
956 const gchar *actname;
959 static void bind_default_mouse(void)
962 ObDefMouseBind binds[] = {
963 { "Left", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
964 { "Middle", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
965 { "Right", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
966 { "Left", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
967 { "Middle", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
968 { "Right", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
969 { "Left", "Titlebar", OB_MOUSE_ACTION_PRESS, "Focus" },
970 { "Left", "Bottom", OB_MOUSE_ACTION_PRESS, "Focus" },
971 { "Left", "BLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
972 { "Left", "BRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
973 { "Left", "TLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
974 { "Left", "TRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
975 { "Left", "Close", OB_MOUSE_ACTION_PRESS, "Focus" },
976 { "Left", "Maximize", OB_MOUSE_ACTION_PRESS, "Focus" },
977 { "Left", "Iconify", OB_MOUSE_ACTION_PRESS, "Focus" },
978 { "Left", "Icon", OB_MOUSE_ACTION_PRESS, "Focus" },
979 { "Left", "AllDesktops", OB_MOUSE_ACTION_PRESS, "Focus" },
980 { "Left", "Shade", OB_MOUSE_ACTION_PRESS, "Focus" },
981 { "Left", "Client", OB_MOUSE_ACTION_CLICK, "Raise" },
982 { "Left", "Titlebar", OB_MOUSE_ACTION_CLICK, "Raise" },
983 { "Middle", "Titlebar", OB_MOUSE_ACTION_CLICK, "Lower" },
984 { "Left", "BLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
985 { "Left", "BRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
986 { "Left", "TLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
987 { "Left", "TRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
988 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Raise" },
989 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "Raise" },
990 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Raise" },
991 { "Left", "Icon", OB_MOUSE_ACTION_CLICK, "Raise" },
992 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "Raise" },
993 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "Raise" },
994 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Close" },
995 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "ToggleMaximize" },
996 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Iconify" },
997 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "ToggleOmnipresent" },
998 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "ToggleShade" },
999 { "Left", "TLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
1000 { "Left", "TRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
1001 { "Left", "BLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
1002 { "Left", "BRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
1003 { "Left", "Top", OB_MOUSE_ACTION_MOTION, "Resize" },
1004 { "Left", "Bottom", OB_MOUSE_ACTION_MOTION, "Resize" },
1005 { "Left", "Left", OB_MOUSE_ACTION_MOTION, "Resize" },
1006 { "Left", "Right", OB_MOUSE_ACTION_MOTION, "Resize" },
1007 { "Left", "Titlebar", OB_MOUSE_ACTION_MOTION, "Move" },
1008 { "A-Left", "Frame", OB_MOUSE_ACTION_MOTION, "Move" },
1009 { "A-Middle", "Frame", OB_MOUSE_ACTION_MOTION, "Resize" },
1010 { NULL, NULL, 0, NULL }
1013 ObActionList *actions;
1015 p = action_parser_new();
1016 for (it = binds; it->button; ++it) {
1017 actions = action_parser_read_string(p, it->actname);
1018 mouse_bind(it->button, frame_context_from_string(it->context),
1020 action_list_unref(actions);
1022 action_parser_unref(p);
1025 void config_startup(ObtXmlInst *i)
1027 config_focus_new = TRUE;
1028 config_focus_follow = FALSE;
1029 config_focus_delay = 0;
1030 config_focus_raise = FALSE;
1031 config_focus_last = TRUE;
1032 config_focus_under_mouse = FALSE;
1033 config_unfocus_leave = FALSE;
1035 obt_xml_register(i, "focus", parse_focus, NULL);
1037 config_place_policy = OB_PLACE_POLICY_SMART;
1038 config_place_center = TRUE;
1039 config_place_monitor = OB_PLACE_MONITOR_PRIMARY;
1041 config_primary_monitor_index = 1;
1042 config_primary_monitor = OB_PLACE_MONITOR_ACTIVE;
1044 obt_xml_register(i, "placement", parse_placement, NULL);
1046 STRUT_PARTIAL_SET(config_margins, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1048 obt_xml_register(i, "margins", parse_margins, NULL);
1050 config_theme = NULL;
1052 config_animate_iconify = TRUE;
1053 config_title_layout = g_strdup("NLIMC");
1054 config_theme_keepborder = TRUE;
1055 config_theme_window_list_icon_size = 36;
1057 config_font_activewindow = NULL;
1058 config_font_inactivewindow = NULL;
1059 config_font_menuitem = NULL;
1060 config_font_menutitle = NULL;
1061 config_font_activeosd = NULL;
1062 config_font_inactiveosd = NULL;
1064 obt_xml_register(i, "theme", parse_theme, NULL);
1066 config_desktops_num = 4;
1067 config_screen_firstdesk = 1;
1068 config_desktops_names = NULL;
1069 config_desktop_popup_time = 875;
1071 obt_xml_register(i, "desktops", parse_desktops, NULL);
1073 config_resize_redraw = TRUE;
1074 config_resize_popup_show = 1; /* nonpixel increments */
1075 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
1076 GRAVITY_COORD_SET(config_resize_popup_fixed.x, 0, FALSE, FALSE);
1077 GRAVITY_COORD_SET(config_resize_popup_fixed.y, 0, FALSE, FALSE);
1079 obt_xml_register(i, "resize", parse_resize, NULL);
1081 config_dock_layer = OB_STACKING_LAYER_ABOVE;
1082 config_dock_pos = OB_DIRECTION_NORTHEAST;
1083 config_dock_floating = FALSE;
1084 config_dock_nostrut = FALSE;
1087 config_dock_orient = OB_ORIENTATION_VERT;
1088 config_dock_hide = FALSE;
1089 config_dock_hide_delay = 300;
1090 config_dock_show_delay = 300;
1091 config_dock_app_move_button = 2; /* middle */
1092 config_dock_app_move_modifiers = 0;
1094 obt_xml_register(i, "dock", parse_dock, NULL);
1096 translate_key("C-g", &config_keyboard_reset_state,
1097 &config_keyboard_reset_keycode);
1099 bind_default_keyboard();
1101 obt_xml_register(i, "keyboard", parse_keyboard, NULL);
1103 config_mouse_threshold = 8;
1104 config_mouse_dclicktime = 500;
1105 config_mouse_screenedgetime = 400;
1106 config_mouse_screenedgewarp = FALSE;
1108 bind_default_mouse();
1110 obt_xml_register(i, "mouse", parse_mouse, NULL);
1112 config_resist_win = 10;
1113 config_resist_edge = 20;
1115 obt_xml_register(i, "resistance", parse_resistance, NULL);
1117 config_menu_hide_delay = 250;
1118 config_menu_middle = FALSE;
1119 config_submenu_show_delay = 100;
1120 config_submenu_hide_delay = 400;
1121 config_menu_manage_desktops = TRUE;
1122 config_menu_files = NULL;
1123 config_menu_show_icons = TRUE;
1125 obt_xml_register(i, "menu", parse_menu, NULL);
1127 config_per_app_settings = NULL;
1129 obt_xml_register(i, "applications", parse_per_app_settings, NULL);
1132 void config_shutdown(void)
1136 g_free(config_theme);
1138 g_free(config_title_layout);
1140 RrFontClose(config_font_activewindow);
1141 RrFontClose(config_font_inactivewindow);
1142 RrFontClose(config_font_menuitem);
1143 RrFontClose(config_font_menutitle);
1144 RrFontClose(config_font_activeosd);
1145 RrFontClose(config_font_inactiveosd);
1147 for (it = config_desktops_names; it; it = g_slist_next(it))
1149 g_slist_free(config_desktops_names);
1151 for (it = config_menu_files; it; it = g_slist_next(it))
1153 g_slist_free(config_menu_files);
1155 for (it = config_per_app_settings; it; it = g_slist_next(it)) {
1156 ObAppSettings *itd = (ObAppSettings *)it->data;
1157 if (itd->name) g_pattern_spec_free(itd->name);
1158 if (itd->role) g_pattern_spec_free(itd->role);
1159 if (itd->title) g_pattern_spec_free(itd->title);
1160 if (itd->class) g_pattern_spec_free(itd->class);
1161 g_slice_free(ObAppSettings, it->data);
1163 g_slist_free(config_per_app_settings);