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.
24 #include "translate.h"
29 #include "obt/paths.h"
31 gboolean config_focus_new;
32 gboolean config_focus_follow;
33 guint config_focus_delay;
34 gboolean config_focus_raise;
35 gboolean config_focus_last;
36 gboolean config_focus_under_mouse;
37 gboolean config_unfocus_leave;
39 ObPlacePolicy config_place_policy;
40 gboolean config_place_center;
41 ObPlaceMonitor config_place_monitor;
43 guint config_primary_monitor_index;
44 ObPlaceMonitor config_primary_monitor;
46 StrutPartial config_margins;
49 gboolean config_theme_keepborder;
50 guint config_theme_window_list_icon_size;
52 gchar *config_title_layout;
54 gboolean config_animate_iconify;
56 RrFont *config_font_activewindow;
57 RrFont *config_font_inactivewindow;
58 RrFont *config_font_menuitem;
59 RrFont *config_font_menutitle;
60 RrFont *config_font_activeosd;
61 RrFont *config_font_inactiveosd;
63 guint config_desktops_num;
64 GSList *config_desktops_names;
65 guint config_screen_firstdesk;
66 guint config_desktop_popup_time;
68 gboolean config_resize_redraw;
69 gint config_resize_popup_show;
70 ObResizePopupPos config_resize_popup_pos;
71 GravityPoint config_resize_popup_fixed;
73 ObStackingLayer config_dock_layer;
74 gboolean config_dock_floating;
75 gboolean config_dock_nostrut;
76 ObDirection config_dock_pos;
79 ObOrientation config_dock_orient;
80 gboolean config_dock_hide;
81 guint config_dock_hide_delay;
82 guint config_dock_show_delay;
83 guint config_dock_app_move_button;
84 guint config_dock_app_move_modifiers;
86 guint config_keyboard_reset_keycode;
87 guint config_keyboard_reset_state;
88 gboolean config_keyboard_rebind_on_mapping_notify;
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_type = OB_PLACE_MONITOR_ANY;
116 settings->monitor = -1;
117 settings->focus = -1;
118 settings->desktop = 0;
119 settings->layer = -2;
120 settings->iconic = -1;
121 settings->skip_pager = -1;
122 settings->skip_taskbar = -1;
123 settings->fullscreen = -1;
124 settings->max_horz = -1;
125 settings->max_vert = -1;
129 #define copy_if(setting, default) \
130 if (src->setting != default) dst->setting = src->setting
131 void config_app_settings_copy_non_defaults(const ObAppSettings *src,
134 g_assert(src != NULL);
135 g_assert(dst != NULL);
137 copy_if(type, (ObClientType)-1);
140 copy_if(monitor_type, OB_PLACE_MONITOR_ANY);
141 copy_if(monitor, -1);
146 copy_if(skip_pager, -1);
147 copy_if(skip_taskbar, -1);
148 copy_if(fullscreen, -1);
149 copy_if(max_horz, -1);
150 copy_if(max_vert, -1);
152 if (src->pos_given) {
153 dst->pos_given = TRUE;
154 dst->pos_force = src->pos_force;
155 dst->position = src->position;
156 /* monitor is copied above */
159 dst->width_num = src->width_num;
160 dst->width_denom = src->width_denom;
161 dst->height_num = src->height_num;
162 dst->height_denom = src->height_denom;
165 void config_parse_relative_number(gchar *s, gint *num, gint *denom)
167 *num = strtol(s, &s, 10);
171 } else if (*s == '/') {
176 void config_parse_gravity_coord(xmlNodePtr node, GravityCoord *c)
178 gchar *s = obt_xml_node_string(node);
179 if (!g_ascii_strcasecmp(s, "center"))
185 if (s[0] == '-' || s[0] == '+')
187 config_parse_relative_number(ps, &c->pos, &c->denom);
194 <application name="aterm">
197 <application name="Rhythmbox">
204 .. there is a lot more settings available
209 static void parse_single_per_app_settings(xmlNodePtr app,
210 ObAppSettings *settings)
213 gboolean x_pos_given = FALSE;
215 if ((n = obt_xml_find_node(app->children, "decor")))
216 if (!obt_xml_node_contains(n, "default"))
217 settings->decor = obt_xml_node_bool(n);
219 if ((n = obt_xml_find_node(app->children, "shade")))
220 if (!obt_xml_node_contains(n, "default"))
221 settings->shade = obt_xml_node_bool(n);
223 if ((n = obt_xml_find_node(app->children, "position"))) {
224 if ((c = obt_xml_find_node(n->children, "x"))) {
225 if (!obt_xml_node_contains(c, "default")) {
226 config_parse_gravity_coord(c, &settings->position.x);
231 if (x_pos_given && (c = obt_xml_find_node(n->children, "y"))) {
232 if (!obt_xml_node_contains(c, "default")) {
233 config_parse_gravity_coord(c, &settings->position.y);
234 settings->pos_given = TRUE;
238 /* monitor can be set without setting x or y */
239 if ((c = obt_xml_find_node(n->children, "monitor"))) {
240 if (!obt_xml_node_contains(c, "default")) {
241 gchar *s = obt_xml_node_string(c);
242 if (!g_ascii_strcasecmp(s, "mouse"))
243 settings->monitor_type = OB_PLACE_MONITOR_MOUSE;
244 else if (!g_ascii_strcasecmp(s, "active"))
245 settings->monitor_type = OB_PLACE_MONITOR_ACTIVE;
246 else if (!g_ascii_strcasecmp(s, "primary"))
247 settings->monitor_type = OB_PLACE_MONITOR_PRIMARY;
249 settings->monitor = obt_xml_node_int(c);
254 obt_xml_attr_bool(n, "force", &settings->pos_force);
257 if ((n = obt_xml_find_node(app->children, "size"))) {
258 if ((c = obt_xml_find_node(n->children, "width"))) {
259 if (!obt_xml_node_contains(c, "default")) {
260 gchar *s = obt_xml_node_string(c);
261 config_parse_relative_number(s,
262 &settings->width_num,
263 &settings->width_denom);
264 if (settings->width_num <= 0 || settings->width_denom < 0)
265 settings->width_num = settings->width_denom = 0;
270 if ((c = obt_xml_find_node(n->children, "height"))) {
271 if (!obt_xml_node_contains(c, "default")) {
272 gchar *s = obt_xml_node_string(c);
273 config_parse_relative_number(s,
274 &settings->height_num,
275 &settings->height_denom);
276 if (settings->height_num <= 0 || settings->height_denom < 0)
277 settings->height_num = settings->height_denom = 0;
283 if ((n = obt_xml_find_node(app->children, "focus"))) {
284 if (!obt_xml_node_contains(n, "default"))
285 settings->focus = obt_xml_node_bool(n);
288 if ((n = obt_xml_find_node(app->children, "desktop"))) {
289 if (!obt_xml_node_contains(n, "default")) {
290 gchar *s = obt_xml_node_string(n);
291 if (!g_ascii_strcasecmp(s, "all"))
292 settings->desktop = DESKTOP_ALL;
294 gint i = obt_xml_node_int(n);
296 settings->desktop = i;
302 if ((n = obt_xml_find_node(app->children, "layer"))) {
303 if (!obt_xml_node_contains(n, "default")) {
304 gchar *s = obt_xml_node_string(n);
305 if (!g_ascii_strcasecmp(s, "above"))
307 else if (!g_ascii_strcasecmp(s, "below"))
308 settings->layer = -1;
315 if ((n = obt_xml_find_node(app->children, "iconic")))
316 if (!obt_xml_node_contains(n, "default"))
317 settings->iconic = obt_xml_node_bool(n);
319 if ((n = obt_xml_find_node(app->children, "skip_pager")))
320 if (!obt_xml_node_contains(n, "default"))
321 settings->skip_pager = obt_xml_node_bool(n);
323 if ((n = obt_xml_find_node(app->children, "skip_taskbar")))
324 if (!obt_xml_node_contains(n, "default"))
325 settings->skip_taskbar = obt_xml_node_bool(n);
327 if ((n = obt_xml_find_node(app->children, "fullscreen")))
328 if (!obt_xml_node_contains(n, "default"))
329 settings->fullscreen = obt_xml_node_bool(n);
331 if ((n = obt_xml_find_node(app->children, "maximized"))) {
332 if (!obt_xml_node_contains(n, "default")) {
333 gchar *s = obt_xml_node_string(n);
334 if (!g_ascii_strcasecmp(s, "horizontal")) {
335 settings->max_horz = TRUE;
336 settings->max_vert = FALSE;
337 } else if (!g_ascii_strcasecmp(s, "vertical")) {
338 settings->max_horz = FALSE;
339 settings->max_vert = TRUE;
341 settings->max_horz = settings->max_vert =
342 obt_xml_node_bool(n);
348 /* Manages settings for individual applications.
349 Some notes: monitor is the screen number in a multi monitor
350 (Xinerama) setup (starting from 0), or mouse: the monitor the pointer
351 is on, active: the active monitor, primary: the primary monitor.
352 Layer can be three values, above (Always on top), below
353 (Always on bottom) and everything else (normal behaviour).
354 Positions can be an integer value or center, which will
355 center the window in the specified axis. Position is within
356 the monitor, so <position><x>center</x></position><monitor>2</monitor>
357 will center the window on the second monitor.
359 static void parse_per_app_settings(xmlNodePtr node, gpointer d)
361 xmlNodePtr app = obt_xml_find_node(node->children, "application");
362 for (; app; app = obt_xml_find_node(app->next, "application")) {
363 ObAppSettings *settings;
365 gboolean name_set, class_set, role_set, title_set,
366 type_set, group_name_set, group_class_set;
367 gchar *name = NULL, *class = NULL, *role = NULL, *title = NULL,
368 *type_str = NULL, *group_name = NULL, *group_class = NULL;
371 class_set = obt_xml_attr_string(app, "class", &class);
372 name_set = obt_xml_attr_string(app, "name", &name);
373 group_class_set = obt_xml_attr_string(app, "groupclass", &group_class);
374 group_name_set = obt_xml_attr_string(app, "groupname", &group_name);
375 type_set = obt_xml_attr_string(app, "type", &type_str);
376 role_set = obt_xml_attr_string(app, "role", &role);
377 title_set = obt_xml_attr_string(app, "title", &title);
379 /* validate the type tho */
381 if (!g_ascii_strcasecmp(type_str, "normal"))
382 type = OB_CLIENT_TYPE_NORMAL;
383 else if (!g_ascii_strcasecmp(type_str, "dialog"))
384 type = OB_CLIENT_TYPE_DIALOG;
385 else if (!g_ascii_strcasecmp(type_str, "splash"))
386 type = OB_CLIENT_TYPE_SPLASH;
387 else if (!g_ascii_strcasecmp(type_str, "utility"))
388 type = OB_CLIENT_TYPE_UTILITY;
389 else if (!g_ascii_strcasecmp(type_str, "menu"))
390 type = OB_CLIENT_TYPE_MENU;
391 else if (!g_ascii_strcasecmp(type_str, "toolbar"))
392 type = OB_CLIENT_TYPE_TOOLBAR;
393 else if (!g_ascii_strcasecmp(type_str, "dock"))
394 type = OB_CLIENT_TYPE_DOCK;
395 else if (!g_ascii_strcasecmp(type_str, "desktop"))
396 type = OB_CLIENT_TYPE_DESKTOP;
398 type_set = FALSE; /* not valid! */
401 if (!(class_set || name_set || role_set || title_set ||
402 type_set || group_class_set || group_name_set))
405 settings = config_create_app_settings();
408 settings->name = g_pattern_spec_new(name);
410 settings->class = g_pattern_spec_new(class);
412 settings->group_name = g_pattern_spec_new(group_name);
414 settings->group_class = g_pattern_spec_new(group_class);
416 settings->role = g_pattern_spec_new(role);
418 settings->title = g_pattern_spec_new(title);
420 settings->type = type;
430 parse_single_per_app_settings(app, settings);
431 config_per_app_settings = g_slist_append(config_per_app_settings,
439 <action name="ChangeDesktop">
446 static void parse_key(xmlNodePtr node, GList *keylist)
448 gchar *keystring, **keys, **key;
450 gboolean is_chroot = FALSE;
452 if (!obt_xml_attr_string(node, "key", &keystring))
455 obt_xml_attr_bool(node, "chroot", &is_chroot);
457 keys = g_strsplit(keystring, " ", 0);
458 for (key = keys; *key; ++key) {
459 keylist = g_list_append(keylist, *key);
461 if ((n = obt_xml_find_node(node->children, "keybind"))) {
463 parse_key(n, keylist);
464 n = obt_xml_find_node(n->next, "keybind");
467 else if ((n = obt_xml_find_node(node->children, "action"))) {
469 ObActionsAct *action;
471 action = actions_parse(n);
473 keyboard_bind(keylist, action);
474 n = obt_xml_find_node(n->next, "action");
480 keyboard_chroot(keylist);
481 keylist = g_list_delete_link(keylist, g_list_last(keylist));
488 static void parse_keyboard(xmlNodePtr node, gpointer d)
493 keyboard_unbind_all();
495 if ((n = obt_xml_find_node(node->children, "chainQuitKey"))) {
496 key = obt_xml_node_string(n);
497 translate_key(key, &config_keyboard_reset_state,
498 &config_keyboard_reset_keycode);
502 if ((n = obt_xml_find_node(node->children, "keybind")))
505 n = obt_xml_find_node(n->next, "keybind");
508 if ((n = obt_xml_find_node(node->children, "rebindOnMappingNotify")))
509 config_keyboard_rebind_on_mapping_notify = obt_xml_node_bool(n);
514 <context name="Titlebar">
515 <mousebind button="Left" action="Press">
516 <action name="Raise"></action>
522 static void parse_mouse(xmlNodePtr node, gpointer d)
524 xmlNodePtr n, nbut, nact;
531 node = node->children;
533 if ((n = obt_xml_find_node(node, "dragThreshold")))
534 config_mouse_threshold = obt_xml_node_int(n);
535 if ((n = obt_xml_find_node(node, "doubleClickTime")))
536 config_mouse_dclicktime = obt_xml_node_int(n);
537 if ((n = obt_xml_find_node(node, "screenEdgeWarpTime"))) {
538 config_mouse_screenedgetime = obt_xml_node_int(n);
539 /* minimum value of 25 for this property, when it is 1 and you hit the
540 edge it basically never stops */
541 if (config_mouse_screenedgetime && config_mouse_screenedgetime < 25)
542 config_mouse_screenedgetime = 25;
544 if ((n = obt_xml_find_node(node, "screenEdgeWarpMouse")))
545 config_mouse_screenedgewarp = obt_xml_node_bool(n);
547 n = obt_xml_find_node(node, "context");
552 if (!obt_xml_attr_string(n, "name", &cxstr))
555 modcxstr = g_strdup(cxstr); /* make a copy to mutilate */
556 while (frame_next_context_from_string(modcxstr, &cx)) {
558 gchar *s = strchr(modcxstr, ' ');
561 g_message(_("Invalid context \"%s\" in mouse binding"),
568 nbut = obt_xml_find_node(n->children, "mousebind");
570 if (!obt_xml_attr_string(nbut, "button", &buttonstr))
572 if (obt_xml_attr_contains(nbut, "action", "press"))
573 mact = OB_MOUSE_ACTION_PRESS;
574 else if (obt_xml_attr_contains(nbut, "action", "release"))
575 mact = OB_MOUSE_ACTION_RELEASE;
576 else if (obt_xml_attr_contains(nbut, "action", "click"))
577 mact = OB_MOUSE_ACTION_CLICK;
578 else if (obt_xml_attr_contains(nbut, "action","doubleclick"))
579 mact = OB_MOUSE_ACTION_DOUBLE_CLICK;
580 else if (obt_xml_attr_contains(nbut, "action", "drag"))
581 mact = OB_MOUSE_ACTION_MOTION;
585 nact = obt_xml_find_node(nbut->children, "action");
587 ObActionsAct *action;
589 if ((action = actions_parse(nact)))
590 mouse_bind(buttonstr, cx, mact, action);
591 nact = obt_xml_find_node(nact->next, "action");
595 nbut = obt_xml_find_node(nbut->next, "mousebind");
601 n = obt_xml_find_node(n->next, "context");
605 static void parse_focus(xmlNodePtr node, gpointer d)
609 node = node->children;
611 if ((n = obt_xml_find_node(node, "focusNew")))
612 config_focus_new = obt_xml_node_bool(n);
613 if ((n = obt_xml_find_node(node, "followMouse")))
614 config_focus_follow = obt_xml_node_bool(n);
615 if ((n = obt_xml_find_node(node, "focusDelay")))
616 config_focus_delay = obt_xml_node_int(n);
617 if ((n = obt_xml_find_node(node, "raiseOnFocus")))
618 config_focus_raise = obt_xml_node_bool(n);
619 if ((n = obt_xml_find_node(node, "focusLast")))
620 config_focus_last = obt_xml_node_bool(n);
621 if ((n = obt_xml_find_node(node, "underMouse")))
622 config_focus_under_mouse = obt_xml_node_bool(n);
623 if ((n = obt_xml_find_node(node, "unfocusOnLeave")))
624 config_unfocus_leave = obt_xml_node_bool(n);
627 static void parse_placement(xmlNodePtr node, gpointer d)
631 node = node->children;
633 if ((n = obt_xml_find_node(node, "policy"))) {
634 if (obt_xml_node_contains(n, "UnderMouse"))
635 config_place_policy = OB_PLACE_POLICY_MOUSE;
637 if ((n = obt_xml_find_node(node, "center"))) {
638 config_place_center = obt_xml_node_bool(n);
640 if ((n = obt_xml_find_node(node, "monitor"))) {
641 if (obt_xml_node_contains(n, "active"))
642 config_place_monitor = OB_PLACE_MONITOR_ACTIVE;
643 else if (obt_xml_node_contains(n, "mouse"))
644 config_place_monitor = OB_PLACE_MONITOR_MOUSE;
645 else if (obt_xml_node_contains(n, "any"))
646 config_place_monitor = OB_PLACE_MONITOR_ANY;
648 if ((n = obt_xml_find_node(node, "primaryMonitor"))) {
649 config_primary_monitor_index = obt_xml_node_int(n);
650 if (!config_primary_monitor_index) {
651 if (obt_xml_node_contains(n, "mouse"))
652 config_primary_monitor = OB_PLACE_MONITOR_MOUSE;
657 static void parse_margins(xmlNodePtr node, gpointer d)
661 node = node->children;
663 if ((n = obt_xml_find_node(node, "top")))
664 config_margins.top = MAX(0, obt_xml_node_int(n));
665 if ((n = obt_xml_find_node(node, "left")))
666 config_margins.left = MAX(0, obt_xml_node_int(n));
667 if ((n = obt_xml_find_node(node, "right")))
668 config_margins.right = MAX(0, obt_xml_node_int(n));
669 if ((n = obt_xml_find_node(node, "bottom")))
670 config_margins.bottom = MAX(0, obt_xml_node_int(n));
673 static void parse_theme(xmlNodePtr node, gpointer d)
677 node = node->children;
679 if ((n = obt_xml_find_node(node, "name"))) {
682 g_free(config_theme);
683 c = obt_xml_node_string(n);
684 config_theme = obt_paths_expand_tilde(c);
687 if ((n = obt_xml_find_node(node, "titleLayout"))) {
690 g_free(config_title_layout);
691 config_title_layout = obt_xml_node_string(n);
693 /* replace duplicates with spaces */
694 for (c = config_title_layout; *c != '\0'; ++c)
695 for (d = c+1; *d != '\0'; ++d)
696 if (*c == *d) *d = ' ';
698 if ((n = obt_xml_find_node(node, "keepBorder")))
699 config_theme_keepborder = obt_xml_node_bool(n);
700 if ((n = obt_xml_find_node(node, "animateIconify")))
701 config_animate_iconify = obt_xml_node_bool(n);
702 if ((n = obt_xml_find_node(node, "windowListIconSize"))) {
703 config_theme_window_list_icon_size = obt_xml_node_int(n);
704 if (config_theme_window_list_icon_size < 16)
705 config_theme_window_list_icon_size = 16;
706 else if (config_theme_window_list_icon_size > 96)
707 config_theme_window_list_icon_size = 96;
710 n = obt_xml_find_node(node, "font");
714 gchar *name = g_strdup(RrDefaultFontFamily);
715 gint size = RrDefaultFontSize;
716 RrFontWeight weight = RrDefaultFontWeight;
717 RrFontSlant slant = RrDefaultFontSlant;
719 if (obt_xml_attr_contains(n, "place", "ActiveWindow"))
720 font = &config_font_activewindow;
721 else if (obt_xml_attr_contains(n, "place", "InactiveWindow"))
722 font = &config_font_inactivewindow;
723 else if (obt_xml_attr_contains(n, "place", "MenuHeader"))
724 font = &config_font_menutitle;
725 else if (obt_xml_attr_contains(n, "place", "MenuItem"))
726 font = &config_font_menuitem;
727 else if (obt_xml_attr_contains(n, "place", "ActiveOnScreenDisplay"))
728 font = &config_font_activeosd;
729 else if (obt_xml_attr_contains(n, "place", "OnScreenDisplay"))
730 font = &config_font_activeosd;
731 else if (obt_xml_attr_contains(n, "place","InactiveOnScreenDisplay"))
732 font = &config_font_inactiveosd;
736 if ((fnode = obt_xml_find_node(n->children, "name"))) {
738 name = obt_xml_node_string(fnode);
740 if ((fnode = obt_xml_find_node(n->children, "size"))) {
741 int s = obt_xml_node_int(fnode);
744 if ((fnode = obt_xml_find_node(n->children, "weight"))) {
745 gchar *w = obt_xml_node_string(fnode);
746 if (!g_ascii_strcasecmp(w, "Bold"))
747 weight = RR_FONTWEIGHT_BOLD;
750 if ((fnode = obt_xml_find_node(n->children, "slant"))) {
751 gchar *s = obt_xml_node_string(fnode);
752 if (!g_ascii_strcasecmp(s, "Italic"))
753 slant = RR_FONTSLANT_ITALIC;
754 if (!g_ascii_strcasecmp(s, "Oblique"))
755 slant = RR_FONTSLANT_OBLIQUE;
759 *font = RrFontOpen(ob_rr_inst, name, size, weight, slant);
762 n = obt_xml_find_node(n->next, "font");
766 static void parse_desktops(xmlNodePtr node, gpointer d)
770 node = node->children;
772 if ((n = obt_xml_find_node(node, "number"))) {
773 gint d = obt_xml_node_int(n);
775 config_desktops_num = (unsigned) d;
777 if ((n = obt_xml_find_node(node, "firstdesk"))) {
778 gint d = obt_xml_node_int(n);
780 config_screen_firstdesk = (unsigned) d;
782 if ((n = obt_xml_find_node(node, "names"))) {
786 for (it = config_desktops_names; it; it = it->next)
788 g_slist_free(config_desktops_names);
789 config_desktops_names = NULL;
791 nname = obt_xml_find_node(n->children, "name");
793 config_desktops_names =
794 g_slist_append(config_desktops_names,
795 obt_xml_node_string(nname));
796 nname = obt_xml_find_node(nname->next, "name");
799 if ((n = obt_xml_find_node(node, "popupTime")))
800 config_desktop_popup_time = obt_xml_node_int(n);
803 static void parse_resize(xmlNodePtr node, gpointer d)
807 node = node->children;
809 if ((n = obt_xml_find_node(node, "drawContents")))
810 config_resize_redraw = obt_xml_node_bool(n);
811 if ((n = obt_xml_find_node(node, "popupShow"))) {
812 config_resize_popup_show = obt_xml_node_int(n);
813 if (obt_xml_node_contains(n, "Always"))
814 config_resize_popup_show = 2;
815 else if (obt_xml_node_contains(n, "Never"))
816 config_resize_popup_show = 0;
817 else if (obt_xml_node_contains(n, "Nonpixel"))
818 config_resize_popup_show = 1;
820 if ((n = obt_xml_find_node(node, "popupPosition"))) {
821 if (obt_xml_node_contains(n, "Top"))
822 config_resize_popup_pos = OB_RESIZE_POS_TOP;
823 else if (obt_xml_node_contains(n, "Center"))
824 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
825 else if (obt_xml_node_contains(n, "Fixed")) {
826 config_resize_popup_pos = OB_RESIZE_POS_FIXED;
828 if ((n = obt_xml_find_node(node, "popupFixedPosition"))) {
831 if ((n2 = obt_xml_find_node(n->children, "x")))
832 config_parse_gravity_coord(n2,
833 &config_resize_popup_fixed.x);
834 if ((n2 = obt_xml_find_node(n->children, "y")))
835 config_parse_gravity_coord(n2,
836 &config_resize_popup_fixed.y);
838 config_resize_popup_fixed.x.pos =
839 MAX(config_resize_popup_fixed.x.pos, 0);
840 config_resize_popup_fixed.y.pos =
841 MAX(config_resize_popup_fixed.y.pos, 0);
847 static void parse_dock(xmlNodePtr node, gpointer d)
851 node = node->children;
853 if ((n = obt_xml_find_node(node, "position"))) {
854 if (obt_xml_node_contains(n, "TopLeft"))
855 config_dock_floating = FALSE,
856 config_dock_pos = OB_DIRECTION_NORTHWEST;
857 else if (obt_xml_node_contains(n, "Top"))
858 config_dock_floating = FALSE,
859 config_dock_pos = OB_DIRECTION_NORTH;
860 else if (obt_xml_node_contains(n, "TopRight"))
861 config_dock_floating = FALSE,
862 config_dock_pos = OB_DIRECTION_NORTHEAST;
863 else if (obt_xml_node_contains(n, "Right"))
864 config_dock_floating = FALSE,
865 config_dock_pos = OB_DIRECTION_EAST;
866 else if (obt_xml_node_contains(n, "BottomRight"))
867 config_dock_floating = FALSE,
868 config_dock_pos = OB_DIRECTION_SOUTHEAST;
869 else if (obt_xml_node_contains(n, "Bottom"))
870 config_dock_floating = FALSE,
871 config_dock_pos = OB_DIRECTION_SOUTH;
872 else if (obt_xml_node_contains(n, "BottomLeft"))
873 config_dock_floating = FALSE,
874 config_dock_pos = OB_DIRECTION_SOUTHWEST;
875 else if (obt_xml_node_contains(n, "Left"))
876 config_dock_floating = FALSE,
877 config_dock_pos = OB_DIRECTION_WEST;
878 else if (obt_xml_node_contains(n, "Floating"))
879 config_dock_floating = TRUE;
881 if (config_dock_floating) {
882 if ((n = obt_xml_find_node(node, "floatingX")))
883 config_dock_x = obt_xml_node_int(n);
884 if ((n = obt_xml_find_node(node, "floatingY")))
885 config_dock_y = obt_xml_node_int(n);
887 if ((n = obt_xml_find_node(node, "noStrut")))
888 config_dock_nostrut = obt_xml_node_bool(n);
890 if ((n = obt_xml_find_node(node, "stacking"))) {
891 if (obt_xml_node_contains(n, "normal"))
892 config_dock_layer = OB_STACKING_LAYER_NORMAL;
893 else if (obt_xml_node_contains(n, "below"))
894 config_dock_layer = OB_STACKING_LAYER_BELOW;
895 else if (obt_xml_node_contains(n, "above"))
896 config_dock_layer = OB_STACKING_LAYER_ABOVE;
898 if ((n = obt_xml_find_node(node, "direction"))) {
899 if (obt_xml_node_contains(n, "horizontal"))
900 config_dock_orient = OB_ORIENTATION_HORZ;
901 else if (obt_xml_node_contains(n, "vertical"))
902 config_dock_orient = OB_ORIENTATION_VERT;
904 if ((n = obt_xml_find_node(node, "autoHide")))
905 config_dock_hide = obt_xml_node_bool(n);
906 if ((n = obt_xml_find_node(node, "hideDelay")))
907 config_dock_hide_delay = obt_xml_node_int(n);
908 if ((n = obt_xml_find_node(node, "showDelay")))
909 config_dock_show_delay = obt_xml_node_int(n);
910 if ((n = obt_xml_find_node(node, "moveButton"))) {
911 gchar *str = obt_xml_node_string(n);
913 if (translate_button(str, &s, &b)) {
914 config_dock_app_move_button = b;
915 config_dock_app_move_modifiers = s;
917 g_message(_("Invalid button \"%s\" specified in config file"), str);
923 static void parse_menu(xmlNodePtr node, gpointer d)
926 node = node->children;
928 if ((n = obt_xml_find_node(node, "hideDelay")))
929 config_menu_hide_delay = obt_xml_node_int(n);
930 if ((n = obt_xml_find_node(node, "middle")))
931 config_menu_middle = obt_xml_node_bool(n);
932 if ((n = obt_xml_find_node(node, "submenuShowDelay")))
933 config_submenu_show_delay = obt_xml_node_int(n);
934 if ((n = obt_xml_find_node(node, "submenuHideDelay")))
935 config_submenu_hide_delay = obt_xml_node_int(n);
936 if ((n = obt_xml_find_node(node, "manageDesktops")))
937 config_menu_manage_desktops = obt_xml_node_bool(n);
938 if ((n = obt_xml_find_node(node, "showIcons"))) {
939 config_menu_show_icons = obt_xml_node_bool(n);
940 #if !defined(USE_IMLIB2) && !defined(USE_LIBRSVG)
941 if (config_menu_show_icons)
942 g_message(_("Openbox was compiled without image loading support. Icons in menus will not be loaded."));
946 while ((node = obt_xml_find_node(node, "file"))) {
947 gchar *c = obt_xml_node_string(node);
948 config_menu_files = g_slist_append(config_menu_files,
949 obt_paths_expand_tilde(c));
955 static void parse_resistance(xmlNodePtr node, gpointer d)
959 node = node->children;
960 if ((n = obt_xml_find_node(node, "strength")))
961 config_resist_win = obt_xml_node_int(n);
962 if ((n = obt_xml_find_node(node, "screen_edge_strength")))
963 config_resist_edge = obt_xml_node_int(n);
969 const gchar *actname;
972 static void bind_default_keyboard(void)
975 ObDefKeyBind binds[] = {
976 { "A-Tab", "NextWindow" },
977 { "S-A-Tab", "PreviousWindow" },
981 for (it = binds; it->key; ++it) {
982 GList *l = g_list_append(NULL, g_strdup(it->key));
983 keyboard_bind(l, actions_parse_string(it->actname));
990 const gchar *context;
991 const ObMouseAction mact;
992 const gchar *actname;
995 static void bind_default_mouse(void)
998 ObDefMouseBind binds[] = {
999 { "Left", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
1000 { "Middle", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
1001 { "Right", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
1002 { "Left", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
1003 { "Middle", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
1004 { "Right", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
1005 { "Left", "Titlebar", OB_MOUSE_ACTION_PRESS, "Focus" },
1006 { "Left", "Bottom", OB_MOUSE_ACTION_PRESS, "Focus" },
1007 { "Left", "BLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
1008 { "Left", "BRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
1009 { "Left", "TLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
1010 { "Left", "TRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
1011 { "Left", "Close", OB_MOUSE_ACTION_PRESS, "Focus" },
1012 { "Left", "Maximize", OB_MOUSE_ACTION_PRESS, "Focus" },
1013 { "Left", "Iconify", OB_MOUSE_ACTION_PRESS, "Focus" },
1014 { "Left", "Icon", OB_MOUSE_ACTION_PRESS, "Focus" },
1015 { "Left", "AllDesktops", OB_MOUSE_ACTION_PRESS, "Focus" },
1016 { "Left", "Shade", OB_MOUSE_ACTION_PRESS, "Focus" },
1017 { "Left", "Client", OB_MOUSE_ACTION_CLICK, "Raise" },
1018 { "Left", "Titlebar", OB_MOUSE_ACTION_CLICK, "Raise" },
1019 { "Middle", "Titlebar", OB_MOUSE_ACTION_CLICK, "Lower" },
1020 { "Left", "BLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
1021 { "Left", "BRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
1022 { "Left", "TLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
1023 { "Left", "TRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
1024 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Raise" },
1025 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "Raise" },
1026 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Raise" },
1027 { "Left", "Icon", OB_MOUSE_ACTION_CLICK, "Raise" },
1028 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "Raise" },
1029 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "Raise" },
1030 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Close" },
1031 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "ToggleMaximize" },
1032 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Iconify" },
1033 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "ToggleOmnipresent" },
1034 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "ToggleShade" },
1035 { "Left", "TLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
1036 { "Left", "TRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
1037 { "Left", "BLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
1038 { "Left", "BRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
1039 { "Left", "Top", OB_MOUSE_ACTION_MOTION, "Resize" },
1040 { "Left", "Bottom", OB_MOUSE_ACTION_MOTION, "Resize" },
1041 { "Left", "Left", OB_MOUSE_ACTION_MOTION, "Resize" },
1042 { "Left", "Right", OB_MOUSE_ACTION_MOTION, "Resize" },
1043 { "Left", "Titlebar", OB_MOUSE_ACTION_MOTION, "Move" },
1044 { "A-Left", "Frame", OB_MOUSE_ACTION_MOTION, "Move" },
1045 { "A-Middle", "Frame", OB_MOUSE_ACTION_MOTION, "Resize" },
1046 { NULL, NULL, 0, NULL }
1049 for (it = binds; it->button; ++it)
1050 mouse_bind(it->button, frame_context_from_string(it->context),
1051 it->mact, actions_parse_string(it->actname));
1054 void config_startup(ObtXmlInst *i)
1056 config_focus_new = TRUE;
1057 config_focus_follow = FALSE;
1058 config_focus_delay = 0;
1059 config_focus_raise = FALSE;
1060 config_focus_last = TRUE;
1061 config_focus_under_mouse = FALSE;
1062 config_unfocus_leave = FALSE;
1064 obt_xml_register(i, "focus", parse_focus, NULL);
1066 config_place_policy = OB_PLACE_POLICY_SMART;
1067 config_place_center = TRUE;
1068 config_place_monitor = OB_PLACE_MONITOR_PRIMARY;
1070 config_primary_monitor_index = 1;
1071 config_primary_monitor = OB_PLACE_MONITOR_ACTIVE;
1073 obt_xml_register(i, "placement", parse_placement, NULL);
1075 STRUT_PARTIAL_SET(config_margins, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1077 obt_xml_register(i, "margins", parse_margins, NULL);
1079 config_theme = NULL;
1081 config_animate_iconify = TRUE;
1082 config_title_layout = g_strdup("NLIMC");
1083 config_theme_keepborder = TRUE;
1084 config_theme_window_list_icon_size = 36;
1086 config_font_activewindow = NULL;
1087 config_font_inactivewindow = NULL;
1088 config_font_menuitem = NULL;
1089 config_font_menutitle = NULL;
1090 config_font_activeosd = NULL;
1091 config_font_inactiveosd = NULL;
1093 obt_xml_register(i, "theme", parse_theme, NULL);
1095 config_desktops_num = 4;
1096 config_screen_firstdesk = 1;
1097 config_desktops_names = NULL;
1098 config_desktop_popup_time = 875;
1100 obt_xml_register(i, "desktops", parse_desktops, NULL);
1102 config_resize_redraw = TRUE;
1103 config_resize_popup_show = 1; /* nonpixel increments */
1104 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
1105 GRAVITY_COORD_SET(config_resize_popup_fixed.x, 0, FALSE, FALSE);
1106 GRAVITY_COORD_SET(config_resize_popup_fixed.y, 0, FALSE, FALSE);
1108 obt_xml_register(i, "resize", parse_resize, NULL);
1110 config_dock_layer = OB_STACKING_LAYER_ABOVE;
1111 config_dock_pos = OB_DIRECTION_NORTHEAST;
1112 config_dock_floating = FALSE;
1113 config_dock_nostrut = FALSE;
1116 config_dock_orient = OB_ORIENTATION_VERT;
1117 config_dock_hide = FALSE;
1118 config_dock_hide_delay = 300;
1119 config_dock_show_delay = 300;
1120 config_dock_app_move_button = 2; /* middle */
1121 config_dock_app_move_modifiers = 0;
1123 obt_xml_register(i, "dock", parse_dock, NULL);
1125 translate_key("C-g", &config_keyboard_reset_state,
1126 &config_keyboard_reset_keycode);
1127 config_keyboard_rebind_on_mapping_notify = TRUE;
1129 bind_default_keyboard();
1131 obt_xml_register(i, "keyboard", parse_keyboard, NULL);
1133 config_mouse_threshold = 8;
1134 config_mouse_dclicktime = 500;
1135 config_mouse_screenedgetime = 400;
1136 config_mouse_screenedgewarp = FALSE;
1138 bind_default_mouse();
1140 obt_xml_register(i, "mouse", parse_mouse, NULL);
1142 config_resist_win = 10;
1143 config_resist_edge = 20;
1145 obt_xml_register(i, "resistance", parse_resistance, NULL);
1147 config_menu_hide_delay = 250;
1148 config_menu_middle = FALSE;
1149 config_submenu_show_delay = 100;
1150 config_submenu_hide_delay = 400;
1151 config_menu_manage_desktops = TRUE;
1152 config_menu_files = NULL;
1153 config_menu_show_icons = TRUE;
1155 obt_xml_register(i, "menu", parse_menu, NULL);
1157 config_per_app_settings = NULL;
1159 obt_xml_register(i, "applications", parse_per_app_settings, NULL);
1162 void config_shutdown(void)
1166 g_free(config_theme);
1168 g_free(config_title_layout);
1170 RrFontClose(config_font_activewindow);
1171 RrFontClose(config_font_inactivewindow);
1172 RrFontClose(config_font_menuitem);
1173 RrFontClose(config_font_menutitle);
1174 RrFontClose(config_font_activeosd);
1175 RrFontClose(config_font_inactiveosd);
1177 for (it = config_desktops_names; it; it = g_slist_next(it))
1179 g_slist_free(config_desktops_names);
1181 for (it = config_menu_files; it; it = g_slist_next(it))
1183 g_slist_free(config_menu_files);
1185 for (it = config_per_app_settings; it; it = g_slist_next(it)) {
1186 ObAppSettings *itd = (ObAppSettings *)it->data;
1187 if (itd->name) g_pattern_spec_free(itd->name);
1188 if (itd->role) g_pattern_spec_free(itd->role);
1189 if (itd->title) g_pattern_spec_free(itd->title);
1190 if (itd->class) g_pattern_spec_free(itd->class);
1191 if (itd->group_name) g_pattern_spec_free(itd->group_name);
1192 if (itd->group_class) g_pattern_spec_free(itd->group_class);
1193 g_slice_free(ObAppSettings, it->data);
1195 g_slist_free(config_per_app_settings);