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"
30 #include "obt/paths.h"
32 gboolean config_focus_new;
33 gboolean config_focus_follow;
34 guint config_focus_delay;
35 gboolean config_focus_raise;
36 gboolean config_focus_last;
37 gboolean config_focus_under_mouse;
38 gboolean config_focus_dontstop;
40 ObPlacePolicy config_place_policy;
41 gboolean config_place_center;
42 ObPlaceMonitor config_place_monitor;
44 StrutPartial config_margins;
47 gboolean config_theme_keepborder;
48 guint config_theme_window_list_icon_size;
50 gchar *config_title_layout;
52 gboolean config_animate_iconify;
54 RrFont *config_font_activewindow;
55 RrFont *config_font_inactivewindow;
56 RrFont *config_font_menuitem;
57 RrFont *config_font_menutitle;
58 RrFont *config_font_osd;
60 guint config_desktops_num;
61 GSList *config_desktops_names;
62 guint config_screen_firstdesk;
63 guint config_desktop_popup_time;
65 gboolean config_resize_redraw;
66 gint config_resize_popup_show;
67 ObResizePopupPos config_resize_popup_pos;
68 GravityPoint config_resize_popup_fixed;
70 ObStackingLayer config_dock_layer;
71 gboolean config_dock_floating;
72 gboolean config_dock_nostrut;
73 ObDirection config_dock_pos;
76 ObOrientation config_dock_orient;
77 gboolean config_dock_hide;
78 guint config_dock_hide_delay;
79 guint config_dock_show_delay;
80 guint config_dock_app_move_button;
81 guint config_dock_app_move_modifiers;
83 guint config_keyboard_reset_keycode;
84 guint config_keyboard_reset_state;
86 gint config_mouse_threshold;
87 gint config_mouse_dclicktime;
88 gint config_mouse_screenedgetime;
90 guint config_menu_hide_delay;
91 gboolean config_menu_middle;
92 guint config_submenu_show_delay;
93 gboolean config_menu_client_list_icons;
94 gboolean config_menu_manage_desktops;
96 GSList *config_menu_files;
98 gint config_resist_win;
99 gint config_resist_edge;
101 GSList *config_per_app_settings;
103 ObAppSettings* config_create_app_settings(void)
105 ObAppSettings *settings = g_new0(ObAppSettings, 1);
107 settings->decor = -1;
108 settings->shade = -1;
109 settings->monitor = -1;
110 settings->focus = -1;
111 settings->desktop = 0;
112 settings->layer = -2;
113 settings->iconic = -1;
114 settings->skip_pager = -1;
115 settings->skip_taskbar = -1;
116 settings->fullscreen = -1;
117 settings->max_horz = -1;
118 settings->max_vert = -1;
122 #define copy_if(setting, default) \
123 if (src->setting != default) dst->setting = src->setting
124 void config_app_settings_copy_non_defaults(const ObAppSettings *src,
127 g_assert(src != NULL);
128 g_assert(dst != NULL);
130 copy_if(type, (ObClientType)-1);
137 copy_if(skip_pager, -1);
138 copy_if(skip_taskbar, -1);
139 copy_if(fullscreen, -1);
140 copy_if(max_horz, -1);
141 copy_if(max_vert, -1);
143 if (src->pos_given) {
144 dst->pos_given = TRUE;
145 dst->pos_force = src->pos_force;
146 dst->position = src->position;
147 dst->monitor = src->monitor;
151 static void config_parse_gravity_coord(xmlNodePtr node, GravityCoord *c)
153 gchar *s = obt_parse_node_string(node);
154 if (!g_ascii_strcasecmp(s, "center"))
159 if (s[0] == '-' || s[0] == '+')
169 <application name="aterm">
172 <application name="Rhythmbox">
179 .. there is a lot more settings available
184 /* Manages settings for individual applications.
185 Some notes: monitor is the screen number in a multi monitor
186 (Xinerama) setup (starting from 0) or mouse, meaning the
187 monitor the pointer is on. Default: mouse.
188 Layer can be three values, above (Always on top), below
189 (Always on bottom) and everything else (normal behaviour).
190 Positions can be an integer value or center, which will
191 center the window in the specified axis. Position is within
192 the monitor, so <position><x>center</x></position><monitor>2</monitor>
193 will center the window on the second monitor.
195 static void parse_per_app_settings(xmlNodePtr node, gpointer d)
197 xmlNodePtr app = obt_parse_find_node(node->children, "application");
198 gchar *name = NULL, *class = NULL, *role = NULL, *type = NULL;
199 gboolean name_set, class_set, type_set;
200 gboolean x_pos_given;
203 name_set = class_set = type_set = x_pos_given = FALSE;
205 class_set = obt_parse_attr_string(app, "class", &class);
206 name_set = obt_parse_attr_string(app, "name", &name);
207 type_set = obt_parse_attr_string(app, "type", &type);
208 if (class_set || name_set) {
210 ObAppSettings *settings = config_create_app_settings();;
213 settings->name = g_pattern_spec_new(name);
216 settings->class = g_pattern_spec_new(class);
219 if (!g_ascii_strcasecmp(type, "normal"))
220 settings->type = OB_CLIENT_TYPE_NORMAL;
221 else if (!g_ascii_strcasecmp(type, "dialog"))
222 settings->type = OB_CLIENT_TYPE_DIALOG;
223 else if (!g_ascii_strcasecmp(type, "splash"))
224 settings->type = OB_CLIENT_TYPE_SPLASH;
225 else if (!g_ascii_strcasecmp(type, "utility"))
226 settings->type = OB_CLIENT_TYPE_UTILITY;
227 else if (!g_ascii_strcasecmp(type, "menu"))
228 settings->type = OB_CLIENT_TYPE_MENU;
229 else if (!g_ascii_strcasecmp(type, "toolbar"))
230 settings->type = OB_CLIENT_TYPE_TOOLBAR;
231 else if (!g_ascii_strcasecmp(type, "dock"))
232 settings->type = OB_CLIENT_TYPE_DOCK;
233 else if (!g_ascii_strcasecmp(type, "desktop"))
234 settings->type = OB_CLIENT_TYPE_DESKTOP;
237 if (obt_parse_attr_string(app, "role", &role))
238 settings->role = g_pattern_spec_new(role);
240 if ((n = obt_parse_find_node(app->children, "decor")))
241 if (!obt_parse_node_contains(n, "default"))
242 settings->decor = obt_parse_node_bool(n);
244 if ((n = obt_parse_find_node(app->children, "shade")))
245 if (!obt_parse_node_contains(n, "default"))
246 settings->shade = obt_parse_node_bool(n);
248 if ((n = obt_parse_find_node(app->children, "position"))) {
249 if ((c = obt_parse_find_node(n->children, "x")))
250 if (!obt_parse_node_contains(c, "default")) {
251 config_parse_gravity_coord(c, &settings->position.x);
255 if (x_pos_given && (c = obt_parse_find_node(n->children, "y")))
256 if (!obt_parse_node_contains(c, "default")) {
257 config_parse_gravity_coord(c, &settings->position.y);
258 settings->pos_given = TRUE;
261 if (settings->pos_given &&
262 (c = obt_parse_find_node(n->children, "monitor")))
263 if (!obt_parse_node_contains(c, "default")) {
264 gchar *s = obt_parse_node_string(c);
265 if (!g_ascii_strcasecmp(s, "mouse"))
266 settings->monitor = 0;
268 settings->monitor = obt_parse_node_int(c) + 1;
272 obt_parse_attr_bool(n, "force", &settings->pos_force);
275 if ((n = obt_parse_find_node(app->children, "focus")))
276 if (!obt_parse_node_contains(n, "default"))
277 settings->focus = obt_parse_node_bool(n);
279 if ((n = obt_parse_find_node(app->children, "desktop"))) {
280 if (!obt_parse_node_contains(n, "default")) {
281 gchar *s = obt_parse_node_string(n);
282 if (!g_ascii_strcasecmp(s, "all"))
283 settings->desktop = DESKTOP_ALL;
285 gint i = obt_parse_node_int(n);
287 settings->desktop = i;
293 if ((n = obt_parse_find_node(app->children, "layer")))
294 if (!obt_parse_node_contains(n, "default")) {
295 gchar *s = obt_parse_node_string(n);
296 if (!g_ascii_strcasecmp(s, "above"))
298 else if (!g_ascii_strcasecmp(s, "below"))
299 settings->layer = -1;
305 if ((n = obt_parse_find_node(app->children, "iconic")))
306 if (!obt_parse_node_contains(n, "default"))
307 settings->iconic = obt_parse_node_bool(n);
309 if ((n = obt_parse_find_node(app->children, "skip_pager")))
310 if (!obt_parse_node_contains(n, "default"))
311 settings->skip_pager = obt_parse_node_bool(n);
313 if ((n = obt_parse_find_node(app->children, "skip_taskbar")))
314 if (!obt_parse_node_contains(n, "default"))
315 settings->skip_taskbar = obt_parse_node_bool(n);
317 if ((n = obt_parse_find_node(app->children, "fullscreen")))
318 if (!obt_parse_node_contains(n, "default"))
319 settings->fullscreen = obt_parse_node_bool(n);
321 if ((n = obt_parse_find_node(app->children, "maximized")))
322 if (!obt_parse_node_contains(n, "default")) {
323 gchar *s = obt_parse_node_string(n);
324 if (!g_ascii_strcasecmp(s, "horizontal")) {
325 settings->max_horz = TRUE;
326 settings->max_vert = FALSE;
327 } else if (!g_ascii_strcasecmp(s, "vertical")) {
328 settings->max_horz = FALSE;
329 settings->max_vert = TRUE;
331 settings->max_horz = settings->max_vert =
332 obt_parse_node_bool(n);
336 config_per_app_settings = g_slist_append(config_per_app_settings,
337 (gpointer) settings);
341 name = class = role = NULL;
344 app = obt_parse_find_node(app->next, "application");
348 static void parse_hook(xmlNodePtr node, gpointer d)
355 if (!obt_parse_attr_string(node, "name", &name)) {
356 g_message(_("Hook in config file is missing a name"));
360 hook = hooks_hook_from_name(name);
362 g_message(_("Unknown hook \"%s\" in config file"), name);
364 if ((n = obt_parse_find_node(node->children, "action")))
366 ObActionsAct *action;
368 action = actions_parse(n);
370 hooks_add(hook, action);
371 n = obt_parse_find_node(n->next, "action");
378 static void parse_hooks(xmlNodePtr node, gpointer d)
382 if ((n = obt_parse_find_node(node->children, "hook")))
385 n = obt_parse_find_node(n->next, "hook");
392 <action name="ChangeDesktop">
399 static void parse_key(xmlNodePtr node, GList *keylist)
403 gboolean is_chroot = FALSE;
404 gboolean grab = TRUE;
406 if (!obt_parse_attr_string(node, "key", &key))
409 obt_parse_attr_bool(node, "chroot", &is_chroot);
410 obt_parse_attr_bool(node, "grab", &grab);
412 keylist = g_list_append(keylist, key);
414 if ((n = obt_parse_find_node(node->children, "keybind"))) {
416 parse_key(n, keylist);
417 n = obt_parse_find_node(n->next, "keybind");
420 else if ((n = obt_parse_find_node(node->children, "action"))) {
422 ObActionsAct *action;
424 action = actions_parse(n);
426 keyboard_bind(keylist, action, grab);
427 n = obt_parse_find_node(n->next, "action");
432 keyboard_chroot(keylist);
435 keylist = g_list_delete_link(keylist, g_list_last(keylist));
438 static void parse_keyboard(xmlNodePtr node, gpointer d)
443 keyboard_unbind_all();
445 if ((n = obt_parse_find_node(node->children, "chainQuitKey"))) {
446 key = obt_parse_node_string(n);
447 translate_key(key, &config_keyboard_reset_state,
448 &config_keyboard_reset_keycode);
452 if ((n = obt_parse_find_node(node->children, "keybind")))
455 n = obt_parse_find_node(n->next, "keybind");
461 <context name="Titlebar">
462 <mousebind button="Left" action="Press">
463 <action name="Raise"></action>
469 static void parse_mouse(xmlNodePtr node, gpointer d)
471 xmlNodePtr n, nbut, nact;
478 node = node->children;
480 if ((n = obt_parse_find_node(node, "dragThreshold")))
481 config_mouse_threshold = obt_parse_node_int(n);
482 if ((n = obt_parse_find_node(node, "doubleClickTime")))
483 config_mouse_dclicktime = obt_parse_node_int(n);
484 if ((n = obt_parse_find_node(node, "screenEdgeWarpTime")))
485 config_mouse_screenedgetime = obt_parse_node_int(n);
487 n = obt_parse_find_node(node, "context");
489 if (!obt_parse_attr_string(n, "name", &contextstr))
491 nbut = obt_parse_find_node(n->children, "mousebind");
493 if (!obt_parse_attr_string(nbut, "button", &buttonstr))
495 if (obt_parse_attr_contains(nbut, "action", "press")) {
496 mact = OB_MOUSE_ACTION_PRESS;
497 } else if (obt_parse_attr_contains(nbut, "action", "release")) {
498 mact = OB_MOUSE_ACTION_RELEASE;
499 } else if (obt_parse_attr_contains(nbut, "action", "click")) {
500 mact = OB_MOUSE_ACTION_CLICK;
501 } else if (obt_parse_attr_contains(nbut, "action","doubleclick")) {
502 mact = OB_MOUSE_ACTION_DOUBLE_CLICK;
503 } else if (obt_parse_attr_contains(nbut, "action", "drag")) {
504 mact = OB_MOUSE_ACTION_MOTION;
507 nact = obt_parse_find_node(nbut->children, "action");
509 ObActionsAct *action;
511 if ((action = actions_parse(nact)))
512 mouse_bind(buttonstr, contextstr, mact, action);
513 nact = obt_parse_find_node(nact->next, "action");
517 nbut = obt_parse_find_node(nbut->next, "mousebind");
521 n = obt_parse_find_node(n->next, "context");
525 static void parse_focus(xmlNodePtr node, gpointer d)
529 node = node->children;
531 if ((n = obt_parse_find_node(node, "focusNew")))
532 config_focus_new = obt_parse_node_bool(n);
533 if ((n = obt_parse_find_node(node, "followMouse")))
534 config_focus_follow = obt_parse_node_bool(n);
535 if ((n = obt_parse_find_node(node, "focusDelay")))
536 config_focus_delay = obt_parse_node_int(n);
537 if ((n = obt_parse_find_node(node, "raiseOnFocus")))
538 config_focus_raise = obt_parse_node_bool(n);
539 if ((n = obt_parse_find_node(node, "focusLast")))
540 config_focus_last = obt_parse_node_bool(n);
541 if ((n = obt_parse_find_node(node, "underMouse")))
542 config_focus_under_mouse = obt_parse_node_bool(n);
543 if ((n = obt_parse_find_node(node, "dontStop")))
544 config_focus_dontstop = obt_parse_node_bool(n);
547 static void parse_placement(xmlNodePtr node, gpointer d)
551 node = node->children;
553 if ((n = obt_parse_find_node(node, "policy")))
554 if (obt_parse_node_contains(n, "UnderMouse"))
555 config_place_policy = OB_PLACE_POLICY_MOUSE;
556 if ((n = obt_parse_find_node(node, "center")))
557 config_place_center = obt_parse_node_bool(n);
558 if ((n = obt_parse_find_node(node, "monitor"))) {
559 if (obt_parse_node_contains(n, "active"))
560 config_place_monitor = OB_PLACE_MONITOR_ACTIVE;
561 else if (obt_parse_node_contains(n, "mouse"))
562 config_place_monitor = OB_PLACE_MONITOR_MOUSE;
566 static void parse_margins(xmlNodePtr node, gpointer d)
570 node = node->children;
572 if ((n = obt_parse_find_node(node, "top")))
573 config_margins.top = MAX(0, obt_parse_node_int(n));
574 if ((n = obt_parse_find_node(node, "left")))
575 config_margins.left = MAX(0, obt_parse_node_int(n));
576 if ((n = obt_parse_find_node(node, "right")))
577 config_margins.right = MAX(0, obt_parse_node_int(n));
578 if ((n = obt_parse_find_node(node, "bottom")))
579 config_margins.bottom = MAX(0, obt_parse_node_int(n));
582 static void parse_theme(xmlNodePtr node, gpointer d)
586 node = node->children;
588 if ((n = obt_parse_find_node(node, "name"))) {
591 g_free(config_theme);
592 c = obt_parse_node_string(n);
593 config_theme = obt_paths_expand_tilde(c);
596 if ((n = obt_parse_find_node(node, "titleLayout"))) {
599 g_free(config_title_layout);
600 config_title_layout = obt_parse_node_string(n);
602 /* replace duplicates with spaces */
603 for (c = config_title_layout; *c != '\0'; ++c)
604 for (d = c+1; *d != '\0'; ++d)
605 if (*c == *d) *d = ' ';
607 if ((n = obt_parse_find_node(node, "keepBorder")))
608 config_theme_keepborder = obt_parse_node_bool(n);
609 if ((n = obt_parse_find_node(node, "animateIconify")))
610 config_animate_iconify = obt_parse_node_bool(n);
611 if ((n = obt_parse_find_node(node, "windowListIconSize"))) {
612 config_theme_window_list_icon_size = obt_parse_node_int(n);
613 if (config_theme_window_list_icon_size < 16)
614 config_theme_window_list_icon_size = 16;
615 else if (config_theme_window_list_icon_size > 96)
616 config_theme_window_list_icon_size = 96;
619 n = obt_parse_find_node(node, "font");
623 gchar *name = g_strdup(RrDefaultFontFamily);
624 gint size = RrDefaultFontSize;
625 RrFontWeight weight = RrDefaultFontWeight;
626 RrFontSlant slant = RrDefaultFontSlant;
628 if (obt_parse_attr_contains(n, "place", "ActiveWindow"))
629 font = &config_font_activewindow;
630 else if (obt_parse_attr_contains(n, "place", "InactiveWindow"))
631 font = &config_font_inactivewindow;
632 else if (obt_parse_attr_contains(n, "place", "MenuHeader"))
633 font = &config_font_menutitle;
634 else if (obt_parse_attr_contains(n, "place", "MenuItem"))
635 font = &config_font_menuitem;
636 else if (obt_parse_attr_contains(n, "place", "OnScreenDisplay"))
637 font = &config_font_osd;
641 if ((fnode = obt_parse_find_node(n->children, "name"))) {
643 name = obt_parse_node_string(fnode);
645 if ((fnode = obt_parse_find_node(n->children, "size"))) {
646 int s = obt_parse_node_int(fnode);
649 if ((fnode = obt_parse_find_node(n->children, "weight"))) {
650 gchar *w = obt_parse_node_string(fnode);
651 if (!g_ascii_strcasecmp(w, "Bold"))
652 weight = RR_FONTWEIGHT_BOLD;
655 if ((fnode = obt_parse_find_node(n->children, "slant"))) {
656 gchar *s = obt_parse_node_string(fnode);
657 if (!g_ascii_strcasecmp(s, "Italic"))
658 slant = RR_FONTSLANT_ITALIC;
659 if (!g_ascii_strcasecmp(s, "Oblique"))
660 slant = RR_FONTSLANT_OBLIQUE;
664 *font = RrFontOpen(ob_rr_inst, name, size, weight, slant);
667 n = obt_parse_find_node(n->next, "font");
671 static void parse_desktops(xmlNodePtr node, gpointer d)
675 node = node->children;
677 if ((n = obt_parse_find_node(node, "number"))) {
678 gint d = obt_parse_node_int(n);
680 config_desktops_num = (unsigned) d;
682 if ((n = obt_parse_find_node(node, "firstdesk"))) {
683 gint d = obt_parse_node_int(n);
685 config_screen_firstdesk = (unsigned) d;
687 if ((n = obt_parse_find_node(node, "names"))) {
691 for (it = config_desktops_names; it; it = it->next)
693 g_slist_free(config_desktops_names);
694 config_desktops_names = NULL;
696 nname = obt_parse_find_node(n->children, "name");
698 config_desktops_names =
699 g_slist_append(config_desktops_names,
700 obt_parse_node_string(nname));
701 nname = obt_parse_find_node(nname->next, "name");
704 if ((n = obt_parse_find_node(node, "popupTime")))
705 config_desktop_popup_time = obt_parse_node_int(n);
708 static void parse_resize(xmlNodePtr node, gpointer d)
712 node = node->children;
714 if ((n = obt_parse_find_node(node, "drawContents")))
715 config_resize_redraw = obt_parse_node_bool(n);
716 if ((n = obt_parse_find_node(node, "popupShow"))) {
717 config_resize_popup_show = obt_parse_node_int(n);
718 if (obt_parse_node_contains(n, "Always"))
719 config_resize_popup_show = 2;
720 else if (obt_parse_node_contains(n, "Never"))
721 config_resize_popup_show = 0;
722 else if (obt_parse_node_contains(n, "Nonpixel"))
723 config_resize_popup_show = 1;
725 if ((n = obt_parse_find_node(node, "popupPosition"))) {
726 if (obt_parse_node_contains(n, "Top"))
727 config_resize_popup_pos = OB_RESIZE_POS_TOP;
728 else if (obt_parse_node_contains(n, "Center"))
729 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
730 else if (obt_parse_node_contains(n, "Fixed")) {
731 config_resize_popup_pos = OB_RESIZE_POS_FIXED;
733 if ((n = obt_parse_find_node(node, "popupFixedPosition"))) {
736 if ((n2 = obt_parse_find_node(n->children, "x")))
737 config_parse_gravity_coord(n2,
738 &config_resize_popup_fixed.x);
739 if ((n2 = obt_parse_find_node(n->children, "y")))
740 config_parse_gravity_coord(n2,
741 &config_resize_popup_fixed.y);
743 config_resize_popup_fixed.x.pos =
744 MAX(config_resize_popup_fixed.x.pos, 0);
745 config_resize_popup_fixed.y.pos =
746 MAX(config_resize_popup_fixed.y.pos, 0);
752 static void parse_dock(xmlNodePtr node, gpointer d)
756 node = node->children;
758 if ((n = obt_parse_find_node(node, "position"))) {
759 if (obt_parse_node_contains(n, "TopLeft"))
760 config_dock_floating = FALSE,
761 config_dock_pos = OB_DIRECTION_NORTHWEST;
762 else if (obt_parse_node_contains(n, "Top"))
763 config_dock_floating = FALSE,
764 config_dock_pos = OB_DIRECTION_NORTH;
765 else if (obt_parse_node_contains(n, "TopRight"))
766 config_dock_floating = FALSE,
767 config_dock_pos = OB_DIRECTION_NORTHEAST;
768 else if (obt_parse_node_contains(n, "Right"))
769 config_dock_floating = FALSE,
770 config_dock_pos = OB_DIRECTION_EAST;
771 else if (obt_parse_node_contains(n, "BottomRight"))
772 config_dock_floating = FALSE,
773 config_dock_pos = OB_DIRECTION_SOUTHEAST;
774 else if (obt_parse_node_contains(n, "Bottom"))
775 config_dock_floating = FALSE,
776 config_dock_pos = OB_DIRECTION_SOUTH;
777 else if (obt_parse_node_contains(n, "BottomLeft"))
778 config_dock_floating = FALSE,
779 config_dock_pos = OB_DIRECTION_SOUTHWEST;
780 else if (obt_parse_node_contains(n, "Left"))
781 config_dock_floating = FALSE,
782 config_dock_pos = OB_DIRECTION_WEST;
783 else if (obt_parse_node_contains(n, "Floating"))
784 config_dock_floating = TRUE;
786 if (config_dock_floating) {
787 if ((n = obt_parse_find_node(node, "floatingX")))
788 config_dock_x = obt_parse_node_int(n);
789 if ((n = obt_parse_find_node(node, "floatingY")))
790 config_dock_y = obt_parse_node_int(n);
792 if ((n = obt_parse_find_node(node, "noStrut")))
793 config_dock_nostrut = obt_parse_node_bool(n);
795 if ((n = obt_parse_find_node(node, "stacking"))) {
796 if (obt_parse_node_contains(n, "normal"))
797 config_dock_layer = OB_STACKING_LAYER_NORMAL;
798 else if (obt_parse_node_contains(n, "below"))
799 config_dock_layer = OB_STACKING_LAYER_BELOW;
800 else if (obt_parse_node_contains(n, "above"))
801 config_dock_layer = OB_STACKING_LAYER_ABOVE;
803 if ((n = obt_parse_find_node(node, "direction"))) {
804 if (obt_parse_node_contains(n, "horizontal"))
805 config_dock_orient = OB_ORIENTATION_HORZ;
806 else if (obt_parse_node_contains(n, "vertical"))
807 config_dock_orient = OB_ORIENTATION_VERT;
809 if ((n = obt_parse_find_node(node, "autoHide")))
810 config_dock_hide = obt_parse_node_bool(n);
811 if ((n = obt_parse_find_node(node, "hideDelay")))
812 config_dock_hide_delay = obt_parse_node_int(n);
813 if ((n = obt_parse_find_node(node, "showDelay")))
814 config_dock_show_delay = obt_parse_node_int(n);
815 if ((n = obt_parse_find_node(node, "moveButton"))) {
816 gchar *str = obt_parse_node_string(n);
818 if (translate_button(str, &s, &b)) {
819 config_dock_app_move_button = b;
820 config_dock_app_move_modifiers = s;
822 g_message(_("Invalid button \"%s\" specified in config file"), str);
828 static void parse_menu(xmlNodePtr node, gpointer d)
831 node = node->children;
833 if ((n = obt_parse_find_node(node, "hideDelay")))
834 config_menu_hide_delay = obt_parse_node_int(n);
835 if ((n = obt_parse_find_node(node, "middle")))
836 config_menu_middle = obt_parse_node_bool(n);
837 if ((n = obt_parse_find_node(node, "submenuShowDelay")))
838 config_submenu_show_delay = obt_parse_node_int(n);
839 if ((n = obt_parse_find_node(node, "applicationIcons")))
840 config_menu_client_list_icons = obt_parse_node_bool(n);
841 if ((n = obt_parse_find_node(node, "manageDesktops")))
842 config_menu_manage_desktops = obt_parse_node_bool(n);
844 while ((node = obt_parse_find_node(node, "file"))) {
845 gchar *c = obt_parse_node_string(node);
846 config_menu_files = g_slist_append(config_menu_files,
847 obt_paths_expand_tilde(c));
853 static void parse_resistance(xmlNodePtr node, gpointer d)
857 node = node->children;
858 if ((n = obt_parse_find_node(node, "strength")))
859 config_resist_win = obt_parse_node_int(n);
860 if ((n = obt_parse_find_node(node, "screen_edge_strength")))
861 config_resist_edge = obt_parse_node_int(n);
867 const gchar *actname;
870 static void bind_default_keyboard(void)
873 ObDefKeyBind binds[] = {
874 { "A-Tab", "NextWindow" },
875 { "S-A-Tab", "PreviousWindow" },
879 for (it = binds; it->key; ++it) {
880 GList *l = g_list_append(NULL, g_strdup(it->key));
881 keyboard_bind(l, actions_parse_string(it->actname), TRUE);
888 const gchar *context;
889 const ObMouseAction mact;
890 const gchar *actname;
893 static void bind_default_mouse(void)
896 ObDefMouseBind binds[] = {
897 { "Left", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
898 { "Middle", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
899 { "Right", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
900 { "Left", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
901 { "Middle", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
902 { "Right", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
903 { "Left", "Titlebar", OB_MOUSE_ACTION_PRESS, "Focus" },
904 { "Left", "Bottom", OB_MOUSE_ACTION_PRESS, "Focus" },
905 { "Left", "BLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
906 { "Left", "BRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
907 { "Left", "TLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
908 { "Left", "TRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
909 { "Left", "Close", OB_MOUSE_ACTION_PRESS, "Focus" },
910 { "Left", "Maximize", OB_MOUSE_ACTION_PRESS, "Focus" },
911 { "Left", "Iconify", OB_MOUSE_ACTION_PRESS, "Focus" },
912 { "Left", "Icon", OB_MOUSE_ACTION_PRESS, "Focus" },
913 { "Left", "AllDesktops", OB_MOUSE_ACTION_PRESS, "Focus" },
914 { "Left", "Shade", OB_MOUSE_ACTION_PRESS, "Focus" },
915 { "Left", "Client", OB_MOUSE_ACTION_CLICK, "Raise" },
916 { "Left", "Titlebar", OB_MOUSE_ACTION_CLICK, "Raise" },
917 { "Middle", "Titlebar", OB_MOUSE_ACTION_CLICK, "Lower" },
918 { "Left", "BLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
919 { "Left", "BRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
920 { "Left", "TLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
921 { "Left", "TRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
922 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Raise" },
923 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "Raise" },
924 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Raise" },
925 { "Left", "Icon", OB_MOUSE_ACTION_CLICK, "Raise" },
926 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "Raise" },
927 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "Raise" },
928 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Close" },
929 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "ToggleMaximize" },
930 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Iconify" },
931 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "ToggleOmnipresent" },
932 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "ToggleShade" },
933 { "Left", "TLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
934 { "Left", "TRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
935 { "Left", "BLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
936 { "Left", "BRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
937 { "Left", "Top", OB_MOUSE_ACTION_MOTION, "Resize" },
938 { "Left", "Bottom", OB_MOUSE_ACTION_MOTION, "Resize" },
939 { "Left", "Left", OB_MOUSE_ACTION_MOTION, "Resize" },
940 { "Left", "Right", OB_MOUSE_ACTION_MOTION, "Resize" },
941 { "Left", "Titlebar", OB_MOUSE_ACTION_MOTION, "Move" },
942 { "A-Left", "Frame", OB_MOUSE_ACTION_MOTION, "Move" },
943 { "A-Middle", "Frame", OB_MOUSE_ACTION_MOTION, "Resize" },
944 { NULL, NULL, 0, NULL }
947 for (it = binds; it->button; ++it)
948 mouse_bind(it->button, it->context, it->mact,
949 actions_parse_string(it->actname));
952 void config_startup(ObtParseInst *i)
954 config_focus_new = TRUE;
955 config_focus_follow = FALSE;
956 config_focus_delay = 0;
957 config_focus_raise = FALSE;
958 config_focus_last = TRUE;
959 config_focus_under_mouse = FALSE;
960 config_focus_dontstop = FALSE;
962 obt_parse_register(i, "focus", parse_focus, NULL);
964 config_place_policy = OB_PLACE_POLICY_SMART;
965 config_place_center = TRUE;
966 config_place_monitor = OB_PLACE_MONITOR_ANY;
968 obt_parse_register(i, "placement", parse_placement, NULL);
970 STRUT_PARTIAL_SET(config_margins, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
972 obt_parse_register(i, "margins", parse_margins, NULL);
976 config_animate_iconify = TRUE;
977 config_title_layout = g_strdup("NLIMC");
978 config_theme_keepborder = TRUE;
979 config_theme_window_list_icon_size = 36;
981 config_font_activewindow = NULL;
982 config_font_inactivewindow = NULL;
983 config_font_menuitem = NULL;
984 config_font_menutitle = NULL;
986 obt_parse_register(i, "theme", parse_theme, NULL);
988 config_desktops_num = 4;
989 config_screen_firstdesk = 1;
990 config_desktops_names = NULL;
991 config_desktop_popup_time = 875;
993 obt_parse_register(i, "desktops", parse_desktops, NULL);
995 config_resize_redraw = TRUE;
996 config_resize_popup_show = 1; /* nonpixel increments */
997 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
998 GRAVITY_COORD_SET(config_resize_popup_fixed.x, 0, FALSE, FALSE);
999 GRAVITY_COORD_SET(config_resize_popup_fixed.y, 0, FALSE, FALSE);
1001 obt_parse_register(i, "resize", parse_resize, NULL);
1003 config_dock_layer = OB_STACKING_LAYER_ABOVE;
1004 config_dock_pos = OB_DIRECTION_NORTHEAST;
1005 config_dock_floating = FALSE;
1006 config_dock_nostrut = FALSE;
1009 config_dock_orient = OB_ORIENTATION_VERT;
1010 config_dock_hide = FALSE;
1011 config_dock_hide_delay = 300;
1012 config_dock_show_delay = 300;
1013 config_dock_app_move_button = 2; /* middle */
1014 config_dock_app_move_modifiers = 0;
1016 obt_parse_register(i, "dock", parse_dock, NULL);
1018 translate_key("C-g", &config_keyboard_reset_state,
1019 &config_keyboard_reset_keycode);
1021 bind_default_keyboard();
1023 obt_parse_register(i, "keyboard", parse_keyboard, NULL);
1025 config_mouse_threshold = 8;
1026 config_mouse_dclicktime = 200;
1027 config_mouse_screenedgetime = 400;
1029 bind_default_mouse();
1031 obt_parse_register(i, "mouse", parse_mouse, NULL);
1033 config_resist_win = 10;
1034 config_resist_edge = 20;
1036 obt_parse_register(i, "resistance", parse_resistance, NULL);
1038 config_menu_hide_delay = 250;
1039 config_menu_middle = FALSE;
1040 config_submenu_show_delay = 0;
1041 config_menu_client_list_icons = TRUE;
1042 config_menu_manage_desktops = TRUE;
1043 config_menu_files = NULL;
1045 obt_parse_register(i, "menu", parse_menu, NULL);
1047 obt_parse_register(i, "hooks", parse_hooks, NULL);
1049 config_per_app_settings = NULL;
1051 obt_parse_register(i, "applications", parse_per_app_settings, NULL);
1054 void config_shutdown(void)
1058 g_free(config_theme);
1060 g_free(config_title_layout);
1062 RrFontClose(config_font_activewindow);
1063 RrFontClose(config_font_inactivewindow);
1064 RrFontClose(config_font_menuitem);
1065 RrFontClose(config_font_menutitle);
1066 RrFontClose(config_font_osd);
1068 for (it = config_desktops_names; it; it = g_slist_next(it))
1070 g_slist_free(config_desktops_names);
1072 for (it = config_menu_files; it; it = g_slist_next(it))
1074 g_slist_free(config_menu_files);
1076 for (it = config_per_app_settings; it; it = g_slist_next(it)) {
1077 ObAppSettings *itd = (ObAppSettings *)it->data;
1078 if (itd->name) g_pattern_spec_free(itd->name);
1079 if (itd->role) g_pattern_spec_free(itd->role);
1080 if (itd->class) g_pattern_spec_free(itd->class);
1083 g_slist_free(config_per_app_settings);