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;
39 ObPlacePolicy config_place_policy;
40 gboolean config_place_center;
41 ObPlaceMonitor config_place_monitor;
43 StrutPartial config_margins;
46 gboolean config_theme_keepborder;
48 gchar *config_title_layout;
50 gboolean config_animate_iconify;
52 RrFont *config_font_activewindow;
53 RrFont *config_font_inactivewindow;
54 RrFont *config_font_menuitem;
55 RrFont *config_font_menutitle;
56 RrFont *config_font_osd;
58 guint config_desktops_num;
59 GSList *config_desktops_names;
60 guint config_screen_firstdesk;
61 guint config_desktop_popup_time;
63 gboolean config_resize_redraw;
64 gint config_resize_popup_show;
65 ObResizePopupPos config_resize_popup_pos;
66 GravityPoint config_resize_popup_fixed;
68 ObStackingLayer config_dock_layer;
69 gboolean config_dock_floating;
70 gboolean config_dock_nostrut;
71 ObDirection config_dock_pos;
74 ObOrientation config_dock_orient;
75 gboolean config_dock_hide;
76 guint config_dock_hide_delay;
77 guint config_dock_show_delay;
78 guint config_dock_app_move_button;
79 guint config_dock_app_move_modifiers;
81 guint config_keyboard_reset_keycode;
82 guint config_keyboard_reset_state;
84 gint config_mouse_threshold;
85 gint config_mouse_dclicktime;
86 gint config_mouse_screenedgetime;
88 guint config_menu_hide_delay;
89 gboolean config_menu_middle;
90 guint config_submenu_show_delay;
91 gboolean config_menu_client_list_icons;
92 gboolean config_menu_manage_desktops;
94 GSList *config_menu_files;
96 gint config_resist_win;
97 gint config_resist_edge;
99 GSList *config_per_app_settings;
101 ObAppSettings* config_create_app_settings(void)
103 ObAppSettings *settings = g_new0(ObAppSettings, 1);
105 settings->decor = -1;
106 settings->shade = -1;
107 settings->monitor = -1;
108 settings->focus = -1;
109 settings->desktop = 0;
110 settings->layer = -2;
111 settings->iconic = -1;
112 settings->skip_pager = -1;
113 settings->skip_taskbar = -1;
114 settings->fullscreen = -1;
115 settings->max_horz = -1;
116 settings->max_vert = -1;
120 #define copy_if(setting, default) \
121 if (src->setting != default) dst->setting = src->setting
122 void config_app_settings_copy_non_defaults(const ObAppSettings *src,
125 g_assert(src != NULL);
126 g_assert(dst != NULL);
128 copy_if(type, (ObClientType)-1);
135 copy_if(skip_pager, -1);
136 copy_if(skip_taskbar, -1);
137 copy_if(fullscreen, -1);
138 copy_if(max_horz, -1);
139 copy_if(max_vert, -1);
141 if (src->pos_given) {
142 dst->pos_given = TRUE;
143 dst->pos_force = src->pos_force;
144 dst->position = src->position;
145 dst->monitor = src->monitor;
149 static void config_parse_gravity_coord(xmlNodePtr node, GravityCoord *c)
151 gchar *s = obt_parse_node_string(node);
152 if (!g_ascii_strcasecmp(s, "center"))
157 if (s[0] == '-' || s[0] == '+')
167 <application name="aterm">
170 <application name="Rhythmbox">
177 .. there is a lot more settings available
182 /* Manages settings for individual applications.
183 Some notes: monitor is the screen number in a multi monitor
184 (Xinerama) setup (starting from 0) or mouse, meaning the
185 monitor the pointer is on. Default: mouse.
186 Layer can be three values, above (Always on top), below
187 (Always on bottom) and everything else (normal behaviour).
188 Positions can be an integer value or center, which will
189 center the window in the specified axis. Position is within
190 the monitor, so <position><x>center</x></position><monitor>2</monitor>
191 will center the window on the second monitor.
193 static void parse_per_app_settings(xmlNodePtr node, gpointer d)
195 xmlNodePtr app = obt_parse_find_node(node->children, "application");
196 gchar *name = NULL, *class = NULL, *role = NULL, *type = NULL;
197 gboolean name_set, class_set, type_set;
198 gboolean x_pos_given;
201 name_set = class_set = type_set = x_pos_given = FALSE;
203 class_set = obt_parse_attr_string(app, "class", &class);
204 name_set = obt_parse_attr_string(app, "name", &name);
205 type_set = obt_parse_attr_string(app, "type", &type);
206 if (class_set || name_set) {
208 ObAppSettings *settings = config_create_app_settings();;
211 settings->name = g_pattern_spec_new(name);
214 settings->class = g_pattern_spec_new(class);
217 if (!g_ascii_strcasecmp(type, "normal"))
218 settings->type = OB_CLIENT_TYPE_NORMAL;
219 else if (!g_ascii_strcasecmp(type, "dialog"))
220 settings->type = OB_CLIENT_TYPE_DIALOG;
221 else if (!g_ascii_strcasecmp(type, "splash"))
222 settings->type = OB_CLIENT_TYPE_SPLASH;
223 else if (!g_ascii_strcasecmp(type, "utility"))
224 settings->type = OB_CLIENT_TYPE_UTILITY;
225 else if (!g_ascii_strcasecmp(type, "menu"))
226 settings->type = OB_CLIENT_TYPE_MENU;
227 else if (!g_ascii_strcasecmp(type, "toolbar"))
228 settings->type = OB_CLIENT_TYPE_TOOLBAR;
229 else if (!g_ascii_strcasecmp(type, "dock"))
230 settings->type = OB_CLIENT_TYPE_DOCK;
231 else if (!g_ascii_strcasecmp(type, "desktop"))
232 settings->type = OB_CLIENT_TYPE_DESKTOP;
235 if (obt_parse_attr_string(app, "role", &role))
236 settings->role = g_pattern_spec_new(role);
238 if ((n = obt_parse_find_node(app->children, "decor")))
239 if (!obt_parse_node_contains(n, "default"))
240 settings->decor = obt_parse_node_bool(n);
242 if ((n = obt_parse_find_node(app->children, "shade")))
243 if (!obt_parse_node_contains(n, "default"))
244 settings->shade = obt_parse_node_bool(n);
246 if ((n = obt_parse_find_node(app->children, "position"))) {
247 if ((c = obt_parse_find_node(n->children, "x")))
248 if (!obt_parse_node_contains(c, "default")) {
249 config_parse_gravity_coord(c, &settings->position.x);
253 if (x_pos_given && (c = obt_parse_find_node(n->children, "y")))
254 if (!obt_parse_node_contains(c, "default")) {
255 config_parse_gravity_coord(c, &settings->position.y);
256 settings->pos_given = TRUE;
259 if (settings->pos_given &&
260 (c = obt_parse_find_node(n->children, "monitor")))
261 if (!obt_parse_node_contains(c, "default")) {
262 gchar *s = obt_parse_node_string(c);
263 if (!g_ascii_strcasecmp(s, "mouse"))
264 settings->monitor = 0;
266 settings->monitor = obt_parse_node_int(c) + 1;
270 obt_parse_attr_bool(n, "force", &settings->pos_force);
273 if ((n = obt_parse_find_node(app->children, "focus")))
274 if (!obt_parse_node_contains(n, "default"))
275 settings->focus = obt_parse_node_bool(n);
277 if ((n = obt_parse_find_node(app->children, "desktop"))) {
278 if (!obt_parse_node_contains(n, "default")) {
279 gchar *s = obt_parse_node_string(n);
280 if (!g_ascii_strcasecmp(s, "all"))
281 settings->desktop = DESKTOP_ALL;
283 gint i = obt_parse_node_int(n);
285 settings->desktop = i;
291 if ((n = obt_parse_find_node(app->children, "layer")))
292 if (!obt_parse_node_contains(n, "default")) {
293 gchar *s = obt_parse_node_string(n);
294 if (!g_ascii_strcasecmp(s, "above"))
296 else if (!g_ascii_strcasecmp(s, "below"))
297 settings->layer = -1;
303 if ((n = obt_parse_find_node(app->children, "iconic")))
304 if (!obt_parse_node_contains(n, "default"))
305 settings->iconic = obt_parse_node_bool(n);
307 if ((n = obt_parse_find_node(app->children, "skip_pager")))
308 if (!obt_parse_node_contains(n, "default"))
309 settings->skip_pager = obt_parse_node_bool(n);
311 if ((n = obt_parse_find_node(app->children, "skip_taskbar")))
312 if (!obt_parse_node_contains(n, "default"))
313 settings->skip_taskbar = obt_parse_node_bool(n);
315 if ((n = obt_parse_find_node(app->children, "fullscreen")))
316 if (!obt_parse_node_contains(n, "default"))
317 settings->fullscreen = obt_parse_node_bool(n);
319 if ((n = obt_parse_find_node(app->children, "maximized")))
320 if (!obt_parse_node_contains(n, "default")) {
321 gchar *s = obt_parse_node_string(n);
322 if (!g_ascii_strcasecmp(s, "horizontal")) {
323 settings->max_horz = TRUE;
324 settings->max_vert = FALSE;
325 } else if (!g_ascii_strcasecmp(s, "vertical")) {
326 settings->max_horz = FALSE;
327 settings->max_vert = TRUE;
329 settings->max_horz = settings->max_vert =
330 obt_parse_node_bool(n);
334 config_per_app_settings = g_slist_append(config_per_app_settings,
335 (gpointer) settings);
339 name = class = role = NULL;
342 app = obt_parse_find_node(app->next, "application");
346 static void parse_hook(xmlNodePtr node, gpointer d)
353 if (!obt_parse_attr_string(node, "name", &name)) {
354 g_message(_("Hook in config file is missing a name"));
358 hook = hooks_hook_from_name(name);
360 g_message(_("Unknown hook \"%s\" in config file"), name);
362 if ((n = obt_parse_find_node(node->children, "action")))
364 ObActionsAct *action;
366 action = actions_parse(n);
368 hooks_add(hook, action);
369 n = obt_parse_find_node(n->next, "action");
376 static void parse_hooks(xmlNodePtr node, gpointer d)
380 if ((n = obt_parse_find_node(node->children, "hook")))
383 n = obt_parse_find_node(n->next, "hook");
390 <action name="ChangeDesktop">
397 static void parse_key(xmlNodePtr node, GList *keylist)
401 gboolean is_chroot = FALSE;
402 gboolean grab = TRUE;
404 if (!obt_parse_attr_string(node, "key", &key))
407 obt_parse_attr_bool(node, "chroot", &is_chroot);
408 obt_parse_attr_bool(node, "grab", &grab);
410 keylist = g_list_append(keylist, key);
412 if ((n = obt_parse_find_node(node->children, "keybind"))) {
414 parse_key(n, keylist);
415 n = obt_parse_find_node(n->next, "keybind");
418 else if ((n = obt_parse_find_node(node->children, "action"))) {
420 ObActionsAct *action;
422 action = actions_parse(n);
424 keyboard_bind(keylist, action, grab);
425 n = obt_parse_find_node(n->next, "action");
430 keyboard_chroot(keylist);
433 keylist = g_list_delete_link(keylist, g_list_last(keylist));
436 static void parse_keyboard(xmlNodePtr node, gpointer d)
441 keyboard_unbind_all();
443 if ((n = obt_parse_find_node(node->children, "chainQuitKey"))) {
444 key = obt_parse_node_string(n);
445 translate_key(key, &config_keyboard_reset_state,
446 &config_keyboard_reset_keycode);
450 if ((n = obt_parse_find_node(node->children, "keybind")))
453 n = obt_parse_find_node(n->next, "keybind");
459 <context name="Titlebar">
460 <mousebind button="Left" action="Press">
461 <action name="Raise"></action>
467 static void parse_mouse(xmlNodePtr node, gpointer d)
469 xmlNodePtr n, nbut, nact;
476 node = node->children;
478 if ((n = obt_parse_find_node(node, "dragThreshold")))
479 config_mouse_threshold = obt_parse_node_int(n);
480 if ((n = obt_parse_find_node(node, "doubleClickTime")))
481 config_mouse_dclicktime = obt_parse_node_int(n);
482 if ((n = obt_parse_find_node(node, "screenEdgeWarpTime")))
483 config_mouse_screenedgetime = obt_parse_node_int(n);
485 n = obt_parse_find_node(node, "context");
487 if (!obt_parse_attr_string(n, "name", &contextstr))
489 nbut = obt_parse_find_node(n->children, "mousebind");
491 if (!obt_parse_attr_string(nbut, "button", &buttonstr))
493 if (obt_parse_attr_contains(nbut, "action", "press")) {
494 mact = OB_MOUSE_ACTION_PRESS;
495 } else if (obt_parse_attr_contains(nbut, "action", "release")) {
496 mact = OB_MOUSE_ACTION_RELEASE;
497 } else if (obt_parse_attr_contains(nbut, "action", "click")) {
498 mact = OB_MOUSE_ACTION_CLICK;
499 } else if (obt_parse_attr_contains(nbut, "action","doubleclick")) {
500 mact = OB_MOUSE_ACTION_DOUBLE_CLICK;
501 } else if (obt_parse_attr_contains(nbut, "action", "drag")) {
502 mact = OB_MOUSE_ACTION_MOTION;
505 nact = obt_parse_find_node(nbut->children, "action");
507 ObActionsAct *action;
509 if ((action = actions_parse(nact)))
510 mouse_bind(buttonstr, contextstr, mact, action);
511 nact = obt_parse_find_node(nact->next, "action");
515 nbut = obt_parse_find_node(nbut->next, "mousebind");
519 n = obt_parse_find_node(n->next, "context");
523 static void parse_focus(xmlNodePtr node, gpointer d)
527 node = node->children;
529 if ((n = obt_parse_find_node(node, "focusNew")))
530 config_focus_new = obt_parse_node_bool(n);
531 if ((n = obt_parse_find_node(node, "followMouse")))
532 config_focus_follow = obt_parse_node_bool(n);
533 if ((n = obt_parse_find_node(node, "focusDelay")))
534 config_focus_delay = obt_parse_node_int(n);
535 if ((n = obt_parse_find_node(node, "raiseOnFocus")))
536 config_focus_raise = obt_parse_node_bool(n);
537 if ((n = obt_parse_find_node(node, "focusLast")))
538 config_focus_last = obt_parse_node_bool(n);
539 if ((n = obt_parse_find_node(node, "underMouse")))
540 config_focus_under_mouse = obt_parse_node_bool(n);
543 static void parse_placement(xmlNodePtr node, gpointer d)
547 node = node->children;
549 if ((n = obt_parse_find_node(node, "policy")))
550 if (obt_parse_node_contains(n, "UnderMouse"))
551 config_place_policy = OB_PLACE_POLICY_MOUSE;
552 if ((n = obt_parse_find_node(node, "center")))
553 config_place_center = obt_parse_node_bool(n);
554 if ((n = obt_parse_find_node(node, "monitor"))) {
555 if (obt_parse_node_contains(n, "active"))
556 config_place_monitor = OB_PLACE_MONITOR_ACTIVE;
557 else if (obt_parse_node_contains(n, "mouse"))
558 config_place_monitor = OB_PLACE_MONITOR_MOUSE;
562 static void parse_margins(xmlNodePtr node, gpointer d)
566 node = node->children;
568 if ((n = obt_parse_find_node(node, "top")))
569 config_margins.top = MAX(0, obt_parse_node_int(n));
570 if ((n = obt_parse_find_node(node, "left")))
571 config_margins.left = MAX(0, obt_parse_node_int(n));
572 if ((n = obt_parse_find_node(node, "right")))
573 config_margins.right = MAX(0, obt_parse_node_int(n));
574 if ((n = obt_parse_find_node(node, "bottom")))
575 config_margins.bottom = MAX(0, obt_parse_node_int(n));
578 static void parse_theme(xmlNodePtr node, gpointer d)
582 node = node->children;
584 if ((n = obt_parse_find_node(node, "name"))) {
587 g_free(config_theme);
588 c = obt_parse_node_string(n);
589 config_theme = obt_paths_expand_tilde(c);
592 if ((n = obt_parse_find_node(node, "titleLayout"))) {
595 g_free(config_title_layout);
596 config_title_layout = obt_parse_node_string(n);
598 /* replace duplicates with spaces */
599 for (c = config_title_layout; *c != '\0'; ++c)
600 for (d = c+1; *d != '\0'; ++d)
601 if (*c == *d) *d = ' ';
603 if ((n = obt_parse_find_node(node, "keepBorder")))
604 config_theme_keepborder = obt_parse_node_bool(n);
605 if ((n = obt_parse_find_node(node, "animateIconify")))
606 config_animate_iconify = obt_parse_node_bool(n);
608 n = obt_parse_find_node(node, "font");
612 gchar *name = g_strdup(RrDefaultFontFamily);
613 gint size = RrDefaultFontSize;
614 RrFontWeight weight = RrDefaultFontWeight;
615 RrFontSlant slant = RrDefaultFontSlant;
617 if (obt_parse_attr_contains(n, "place", "ActiveWindow"))
618 font = &config_font_activewindow;
619 else if (obt_parse_attr_contains(n, "place", "InactiveWindow"))
620 font = &config_font_inactivewindow;
621 else if (obt_parse_attr_contains(n, "place", "MenuHeader"))
622 font = &config_font_menutitle;
623 else if (obt_parse_attr_contains(n, "place", "MenuItem"))
624 font = &config_font_menuitem;
625 else if (obt_parse_attr_contains(n, "place", "OnScreenDisplay"))
626 font = &config_font_osd;
630 if ((fnode = obt_parse_find_node(n->children, "name"))) {
632 name = obt_parse_node_string(fnode);
634 if ((fnode = obt_parse_find_node(n->children, "size"))) {
635 int s = obt_parse_node_int(fnode);
638 if ((fnode = obt_parse_find_node(n->children, "weight"))) {
639 gchar *w = obt_parse_node_string(fnode);
640 if (!g_ascii_strcasecmp(w, "Bold"))
641 weight = RR_FONTWEIGHT_BOLD;
644 if ((fnode = obt_parse_find_node(n->children, "slant"))) {
645 gchar *s = obt_parse_node_string(fnode);
646 if (!g_ascii_strcasecmp(s, "Italic"))
647 slant = RR_FONTSLANT_ITALIC;
648 if (!g_ascii_strcasecmp(s, "Oblique"))
649 slant = RR_FONTSLANT_OBLIQUE;
653 *font = RrFontOpen(ob_rr_inst, name, size, weight, slant);
656 n = obt_parse_find_node(n->next, "font");
660 static void parse_desktops(xmlNodePtr node, gpointer d)
664 node = node->children;
666 if ((n = obt_parse_find_node(node, "number"))) {
667 gint d = obt_parse_node_int(n);
669 config_desktops_num = (unsigned) d;
671 if ((n = obt_parse_find_node(node, "firstdesk"))) {
672 gint d = obt_parse_node_int(n);
674 config_screen_firstdesk = (unsigned) d;
676 if ((n = obt_parse_find_node(node, "names"))) {
680 for (it = config_desktops_names; it; it = it->next)
682 g_slist_free(config_desktops_names);
683 config_desktops_names = NULL;
685 nname = obt_parse_find_node(n->children, "name");
687 config_desktops_names =
688 g_slist_append(config_desktops_names,
689 obt_parse_node_string(nname));
690 nname = obt_parse_find_node(nname->next, "name");
693 if ((n = obt_parse_find_node(node, "popupTime")))
694 config_desktop_popup_time = obt_parse_node_int(n);
697 static void parse_resize(xmlNodePtr node, gpointer d)
701 node = node->children;
703 if ((n = obt_parse_find_node(node, "drawContents")))
704 config_resize_redraw = obt_parse_node_bool(n);
705 if ((n = obt_parse_find_node(node, "popupShow"))) {
706 config_resize_popup_show = obt_parse_node_int(n);
707 if (obt_parse_node_contains(n, "Always"))
708 config_resize_popup_show = 2;
709 else if (obt_parse_node_contains(n, "Never"))
710 config_resize_popup_show = 0;
711 else if (obt_parse_node_contains(n, "Nonpixel"))
712 config_resize_popup_show = 1;
714 if ((n = obt_parse_find_node(node, "popupPosition"))) {
715 if (obt_parse_node_contains(n, "Top"))
716 config_resize_popup_pos = OB_RESIZE_POS_TOP;
717 else if (obt_parse_node_contains(n, "Center"))
718 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
719 else if (obt_parse_node_contains(n, "Fixed")) {
720 config_resize_popup_pos = OB_RESIZE_POS_FIXED;
722 if ((n = obt_parse_find_node(node, "popupFixedPosition"))) {
725 if ((n2 = obt_parse_find_node(n->children, "x")))
726 config_parse_gravity_coord(n2,
727 &config_resize_popup_fixed.x);
728 if ((n2 = obt_parse_find_node(n->children, "y")))
729 config_parse_gravity_coord(n2,
730 &config_resize_popup_fixed.y);
732 config_resize_popup_fixed.x.pos =
733 MAX(config_resize_popup_fixed.x.pos, 0);
734 config_resize_popup_fixed.y.pos =
735 MAX(config_resize_popup_fixed.y.pos, 0);
741 static void parse_dock(xmlNodePtr node, gpointer d)
745 node = node->children;
747 if ((n = obt_parse_find_node(node, "position"))) {
748 if (obt_parse_node_contains(n, "TopLeft"))
749 config_dock_floating = FALSE,
750 config_dock_pos = OB_DIRECTION_NORTHWEST;
751 else if (obt_parse_node_contains(n, "Top"))
752 config_dock_floating = FALSE,
753 config_dock_pos = OB_DIRECTION_NORTH;
754 else if (obt_parse_node_contains(n, "TopRight"))
755 config_dock_floating = FALSE,
756 config_dock_pos = OB_DIRECTION_NORTHEAST;
757 else if (obt_parse_node_contains(n, "Right"))
758 config_dock_floating = FALSE,
759 config_dock_pos = OB_DIRECTION_EAST;
760 else if (obt_parse_node_contains(n, "BottomRight"))
761 config_dock_floating = FALSE,
762 config_dock_pos = OB_DIRECTION_SOUTHEAST;
763 else if (obt_parse_node_contains(n, "Bottom"))
764 config_dock_floating = FALSE,
765 config_dock_pos = OB_DIRECTION_SOUTH;
766 else if (obt_parse_node_contains(n, "BottomLeft"))
767 config_dock_floating = FALSE,
768 config_dock_pos = OB_DIRECTION_SOUTHWEST;
769 else if (obt_parse_node_contains(n, "Left"))
770 config_dock_floating = FALSE,
771 config_dock_pos = OB_DIRECTION_WEST;
772 else if (obt_parse_node_contains(n, "Floating"))
773 config_dock_floating = TRUE;
775 if (config_dock_floating) {
776 if ((n = obt_parse_find_node(node, "floatingX")))
777 config_dock_x = obt_parse_node_int(n);
778 if ((n = obt_parse_find_node(node, "floatingY")))
779 config_dock_y = obt_parse_node_int(n);
781 if ((n = obt_parse_find_node(node, "noStrut")))
782 config_dock_nostrut = obt_parse_node_bool(n);
784 if ((n = obt_parse_find_node(node, "stacking"))) {
785 if (obt_parse_node_contains(n, "normal"))
786 config_dock_layer = OB_STACKING_LAYER_NORMAL;
787 else if (obt_parse_node_contains(n, "below"))
788 config_dock_layer = OB_STACKING_LAYER_BELOW;
789 else if (obt_parse_node_contains(n, "above"))
790 config_dock_layer = OB_STACKING_LAYER_ABOVE;
792 if ((n = obt_parse_find_node(node, "direction"))) {
793 if (obt_parse_node_contains(n, "horizontal"))
794 config_dock_orient = OB_ORIENTATION_HORZ;
795 else if (obt_parse_node_contains(n, "vertical"))
796 config_dock_orient = OB_ORIENTATION_VERT;
798 if ((n = obt_parse_find_node(node, "autoHide")))
799 config_dock_hide = obt_parse_node_bool(n);
800 if ((n = obt_parse_find_node(node, "hideDelay")))
801 config_dock_hide_delay = obt_parse_node_int(n);
802 if ((n = obt_parse_find_node(node, "showDelay")))
803 config_dock_show_delay = obt_parse_node_int(n);
804 if ((n = obt_parse_find_node(node, "moveButton"))) {
805 gchar *str = obt_parse_node_string(n);
807 if (translate_button(str, &s, &b)) {
808 config_dock_app_move_button = b;
809 config_dock_app_move_modifiers = s;
811 g_message(_("Invalid button \"%s\" specified in config file"), str);
817 static void parse_menu(xmlNodePtr node, gpointer d)
820 for (node = node->children; node; node = node->next) {
821 if (!xmlStrcasecmp(node->name, (const xmlChar*) "file")) {
824 c = obt_parse_node_string(node);
825 config_menu_files = g_slist_append(config_menu_files,
826 obt_paths_expand_tilde(c));
829 if ((n = obt_parse_find_node(node, "hideDelay")))
830 config_menu_hide_delay = obt_parse_node_int(n);
831 if ((n = obt_parse_find_node(node, "middle")))
832 config_menu_middle = obt_parse_node_bool(n);
833 if ((n = obt_parse_find_node(node, "submenuShowDelay")))
834 config_submenu_show_delay = obt_parse_node_int(n);
835 if ((n = obt_parse_find_node(node, "applicationIcons")))
836 config_menu_client_list_icons = obt_parse_node_bool(n);
837 if ((n = obt_parse_find_node(node, "manageDesktops")))
838 config_menu_manage_desktops = obt_parse_node_bool(n);
842 static void parse_resistance(xmlNodePtr node, gpointer d)
846 node = node->children;
847 if ((n = obt_parse_find_node(node, "strength")))
848 config_resist_win = obt_parse_node_int(n);
849 if ((n = obt_parse_find_node(node, "screen_edge_strength")))
850 config_resist_edge = obt_parse_node_int(n);
856 const gchar *actname;
859 static void bind_default_keyboard(void)
862 ObDefKeyBind binds[] = {
863 { "A-Tab", "NextWindow" },
864 { "S-A-Tab", "PreviousWindow" },
868 for (it = binds; it->key; ++it) {
869 GList *l = g_list_append(NULL, g_strdup(it->key));
870 keyboard_bind(l, actions_parse_string(it->actname), TRUE);
877 const gchar *context;
878 const ObMouseAction mact;
879 const gchar *actname;
882 static void bind_default_mouse(void)
885 ObDefMouseBind binds[] = {
886 { "Left", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
887 { "Middle", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
888 { "Right", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
889 { "Left", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
890 { "Middle", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
891 { "Right", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
892 { "Left", "Titlebar", OB_MOUSE_ACTION_PRESS, "Focus" },
893 { "Left", "Bottom", OB_MOUSE_ACTION_PRESS, "Focus" },
894 { "Left", "BLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
895 { "Left", "BRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
896 { "Left", "TLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
897 { "Left", "TRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
898 { "Left", "Close", OB_MOUSE_ACTION_PRESS, "Focus" },
899 { "Left", "Maximize", OB_MOUSE_ACTION_PRESS, "Focus" },
900 { "Left", "Iconify", OB_MOUSE_ACTION_PRESS, "Focus" },
901 { "Left", "Icon", OB_MOUSE_ACTION_PRESS, "Focus" },
902 { "Left", "AllDesktops", OB_MOUSE_ACTION_PRESS, "Focus" },
903 { "Left", "Shade", OB_MOUSE_ACTION_PRESS, "Focus" },
904 { "Left", "Client", OB_MOUSE_ACTION_CLICK, "Raise" },
905 { "Left", "Titlebar", OB_MOUSE_ACTION_CLICK, "Raise" },
906 { "Middle", "Titlebar", OB_MOUSE_ACTION_CLICK, "Lower" },
907 { "Left", "BLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
908 { "Left", "BRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
909 { "Left", "TLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
910 { "Left", "TRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
911 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Raise" },
912 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "Raise" },
913 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Raise" },
914 { "Left", "Icon", OB_MOUSE_ACTION_CLICK, "Raise" },
915 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "Raise" },
916 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "Raise" },
917 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Close" },
918 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "ToggleMaximize" },
919 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Iconify" },
920 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "ToggleOmnipresent" },
921 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "ToggleShade" },
922 { "Left", "TLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
923 { "Left", "TRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
924 { "Left", "BLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
925 { "Left", "BRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
926 { "Left", "Top", OB_MOUSE_ACTION_MOTION, "Resize" },
927 { "Left", "Bottom", OB_MOUSE_ACTION_MOTION, "Resize" },
928 { "Left", "Left", OB_MOUSE_ACTION_MOTION, "Resize" },
929 { "Left", "Right", OB_MOUSE_ACTION_MOTION, "Resize" },
930 { "Left", "Titlebar", OB_MOUSE_ACTION_MOTION, "Move" },
931 { "A-Left", "Frame", OB_MOUSE_ACTION_MOTION, "Move" },
932 { "A-Middle", "Frame", OB_MOUSE_ACTION_MOTION, "Resize" },
933 { NULL, NULL, 0, NULL }
936 for (it = binds; it->button; ++it)
937 mouse_bind(it->button, it->context, it->mact,
938 actions_parse_string(it->actname));
941 void config_startup(ObtParseInst *i)
943 config_focus_new = TRUE;
944 config_focus_follow = FALSE;
945 config_focus_delay = 0;
946 config_focus_raise = FALSE;
947 config_focus_last = TRUE;
948 config_focus_under_mouse = FALSE;
950 obt_parse_register(i, "focus", parse_focus, NULL);
952 config_place_policy = OB_PLACE_POLICY_SMART;
953 config_place_center = TRUE;
954 config_place_monitor = OB_PLACE_MONITOR_ANY;
956 obt_parse_register(i, "placement", parse_placement, NULL);
958 STRUT_PARTIAL_SET(config_margins, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
960 obt_parse_register(i, "margins", parse_margins, NULL);
964 config_animate_iconify = TRUE;
965 config_title_layout = g_strdup("NLIMC");
966 config_theme_keepborder = TRUE;
968 config_font_activewindow = NULL;
969 config_font_inactivewindow = NULL;
970 config_font_menuitem = NULL;
971 config_font_menutitle = NULL;
973 obt_parse_register(i, "theme", parse_theme, NULL);
975 config_desktops_num = 4;
976 config_screen_firstdesk = 1;
977 config_desktops_names = NULL;
978 config_desktop_popup_time = 875;
980 obt_parse_register(i, "desktops", parse_desktops, NULL);
982 config_resize_redraw = TRUE;
983 config_resize_popup_show = 1; /* nonpixel increments */
984 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
985 GRAVITY_COORD_SET(config_resize_popup_fixed.x, 0, FALSE, FALSE);
986 GRAVITY_COORD_SET(config_resize_popup_fixed.y, 0, FALSE, FALSE);
988 obt_parse_register(i, "resize", parse_resize, NULL);
990 config_dock_layer = OB_STACKING_LAYER_ABOVE;
991 config_dock_pos = OB_DIRECTION_NORTHEAST;
992 config_dock_floating = FALSE;
993 config_dock_nostrut = FALSE;
996 config_dock_orient = OB_ORIENTATION_VERT;
997 config_dock_hide = FALSE;
998 config_dock_hide_delay = 300;
999 config_dock_show_delay = 300;
1000 config_dock_app_move_button = 2; /* middle */
1001 config_dock_app_move_modifiers = 0;
1003 obt_parse_register(i, "dock", parse_dock, NULL);
1005 translate_key("C-g", &config_keyboard_reset_state,
1006 &config_keyboard_reset_keycode);
1008 bind_default_keyboard();
1010 obt_parse_register(i, "keyboard", parse_keyboard, NULL);
1012 config_mouse_threshold = 8;
1013 config_mouse_dclicktime = 200;
1014 config_mouse_screenedgetime = 400;
1016 bind_default_mouse();
1018 obt_parse_register(i, "mouse", parse_mouse, NULL);
1020 config_resist_win = 10;
1021 config_resist_edge = 20;
1023 obt_parse_register(i, "resistance", parse_resistance, NULL);
1025 config_menu_hide_delay = 250;
1026 config_menu_middle = FALSE;
1027 config_submenu_show_delay = 0;
1028 config_menu_client_list_icons = TRUE;
1029 config_menu_manage_desktops = TRUE;
1030 config_menu_files = NULL;
1032 obt_parse_register(i, "menu", parse_menu, NULL);
1034 obt_parse_register(i, "hooks", parse_hooks, NULL);
1036 config_per_app_settings = NULL;
1038 obt_parse_register(i, "applications", parse_per_app_settings, NULL);
1041 void config_shutdown(void)
1045 g_free(config_theme);
1047 g_free(config_title_layout);
1049 RrFontClose(config_font_activewindow);
1050 RrFontClose(config_font_inactivewindow);
1051 RrFontClose(config_font_menuitem);
1052 RrFontClose(config_font_menutitle);
1053 RrFontClose(config_font_osd);
1055 for (it = config_desktops_names; it; it = g_slist_next(it))
1057 g_slist_free(config_desktops_names);
1059 for (it = config_menu_files; it; it = g_slist_next(it))
1061 g_slist_free(config_menu_files);
1063 for (it = config_per_app_settings; it; it = g_slist_next(it)) {
1064 ObAppSettings *itd = (ObAppSettings *)it->data;
1065 if (itd->name) g_pattern_spec_free(itd->name);
1066 if (itd->role) g_pattern_spec_free(itd->role);
1067 if (itd->class) g_pattern_spec_free(itd->class);
1070 g_slist_free(config_per_app_settings);