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;
38 ObPlacePolicy config_place_policy;
39 gboolean config_place_center;
40 ObPlaceMonitor config_place_monitor;
42 guint config_primary_monitor_index;
43 ObPlaceMonitor config_primary_monitor;
45 StrutPartial config_margins;
48 gboolean config_theme_keepborder;
49 guint config_theme_window_list_icon_size;
51 gchar *config_title_layout;
53 gboolean config_animate_iconify;
55 RrFont *config_font_activewindow;
56 RrFont *config_font_inactivewindow;
57 RrFont *config_font_menuitem;
58 RrFont *config_font_menutitle;
59 RrFont *config_font_osd;
61 guint config_desktops_num;
62 GSList *config_desktops_names;
63 guint config_screen_firstdesk;
64 guint config_desktop_popup_time;
66 gboolean config_resize_redraw;
67 gint config_resize_popup_show;
68 ObResizePopupPos config_resize_popup_pos;
69 GravityPoint config_resize_popup_fixed;
71 ObStackingLayer config_dock_layer;
72 gboolean config_dock_floating;
73 gboolean config_dock_nostrut;
74 ObDirection config_dock_pos;
77 ObOrientation config_dock_orient;
78 gboolean config_dock_hide;
79 guint config_dock_hide_delay;
80 guint config_dock_show_delay;
81 guint config_dock_app_move_button;
82 guint config_dock_app_move_modifiers;
84 guint config_keyboard_reset_keycode;
85 guint config_keyboard_reset_state;
87 gint config_mouse_threshold;
88 gint config_mouse_dclicktime;
89 gint config_mouse_screenedgetime;
91 guint config_menu_hide_delay;
92 gboolean config_menu_middle;
93 guint config_submenu_show_delay;
94 gboolean config_menu_client_list_icons;
95 gboolean config_menu_manage_desktops;
97 GSList *config_menu_files;
99 gint config_resist_win;
100 gint config_resist_edge;
102 GSList *config_per_app_settings;
104 ObAppSettings* config_create_app_settings(void)
106 ObAppSettings *settings = g_new0(ObAppSettings, 1);
108 settings->decor = -1;
109 settings->shade = -1;
110 settings->monitor = -1;
111 settings->focus = -1;
112 settings->desktop = 0;
113 settings->layer = -2;
114 settings->iconic = -1;
115 settings->skip_pager = -1;
116 settings->skip_taskbar = -1;
117 settings->fullscreen = -1;
118 settings->max_horz = -1;
119 settings->max_vert = -1;
123 #define copy_if(setting, default) \
124 if (src->setting != default) dst->setting = src->setting
125 void config_app_settings_copy_non_defaults(const ObAppSettings *src,
128 g_assert(src != NULL);
129 g_assert(dst != NULL);
131 copy_if(type, (ObClientType)-1);
134 copy_if(monitor, -1);
139 copy_if(skip_pager, -1);
140 copy_if(skip_taskbar, -1);
141 copy_if(fullscreen, -1);
142 copy_if(max_horz, -1);
143 copy_if(max_vert, -1);
145 if (src->pos_given) {
146 dst->pos_given = TRUE;
147 dst->pos_force = src->pos_force;
148 dst->position = src->position;
149 dst->monitor = src->monitor;
153 static void config_parse_gravity_coord(xmlNodePtr node, GravityCoord *c)
155 gchar *s = obt_parse_node_string(node);
156 if (!g_ascii_strcasecmp(s, "center"))
161 if (s[0] == '-' || s[0] == '+')
171 <application name="aterm">
174 <application name="Rhythmbox">
181 .. there is a lot more settings available
186 /* Manages settings for individual applications.
187 Some notes: monitor is the screen number in a multi monitor
188 (Xinerama) setup (starting from 0) or mouse, meaning the
189 monitor the pointer is on. Default: mouse.
190 Layer can be three values, above (Always on top), below
191 (Always on bottom) and everything else (normal behaviour).
192 Positions can be an integer value or center, which will
193 center the window in the specified axis. Position is within
194 the monitor, so <position><x>center</x></position><monitor>2</monitor>
195 will center the window on the second monitor.
197 static void parse_per_app_settings(xmlNodePtr node, gpointer d)
199 xmlNodePtr app = obt_parse_find_node(node->children, "application");
200 gchar *name = NULL, *class = NULL, *role = NULL, *type = NULL;
201 gboolean name_set, class_set, type_set;
202 gboolean x_pos_given;
207 class_set = obt_parse_attr_string(app, "class", &class);
208 name_set = obt_parse_attr_string(app, "name", &name);
209 type_set = obt_parse_attr_string(app, "type", &type);
210 if (class_set || name_set) {
212 ObAppSettings *settings = config_create_app_settings();;
215 settings->name = g_pattern_spec_new(name);
218 settings->class = g_pattern_spec_new(class);
221 if (!g_ascii_strcasecmp(type, "normal"))
222 settings->type = OB_CLIENT_TYPE_NORMAL;
223 else if (!g_ascii_strcasecmp(type, "dialog"))
224 settings->type = OB_CLIENT_TYPE_DIALOG;
225 else if (!g_ascii_strcasecmp(type, "splash"))
226 settings->type = OB_CLIENT_TYPE_SPLASH;
227 else if (!g_ascii_strcasecmp(type, "utility"))
228 settings->type = OB_CLIENT_TYPE_UTILITY;
229 else if (!g_ascii_strcasecmp(type, "menu"))
230 settings->type = OB_CLIENT_TYPE_MENU;
231 else if (!g_ascii_strcasecmp(type, "toolbar"))
232 settings->type = OB_CLIENT_TYPE_TOOLBAR;
233 else if (!g_ascii_strcasecmp(type, "dock"))
234 settings->type = OB_CLIENT_TYPE_DOCK;
235 else if (!g_ascii_strcasecmp(type, "desktop"))
236 settings->type = OB_CLIENT_TYPE_DESKTOP;
239 if (obt_parse_attr_string(app, "role", &role))
240 settings->role = g_pattern_spec_new(role);
242 if ((n = obt_parse_find_node(app->children, "decor")))
243 if (!obt_parse_node_contains(n, "default"))
244 settings->decor = obt_parse_node_bool(n);
246 if ((n = obt_parse_find_node(app->children, "shade")))
247 if (!obt_parse_node_contains(n, "default"))
248 settings->shade = obt_parse_node_bool(n);
250 if ((n = obt_parse_find_node(app->children, "position"))) {
251 if ((c = obt_parse_find_node(n->children, "x")))
252 if (!obt_parse_node_contains(c, "default")) {
253 config_parse_gravity_coord(c, &settings->position.x);
257 if (x_pos_given && (c = obt_parse_find_node(n->children, "y")))
258 if (!obt_parse_node_contains(c, "default")) {
259 config_parse_gravity_coord(c, &settings->position.y);
260 settings->pos_given = TRUE;
263 if (settings->pos_given &&
264 (c = obt_parse_find_node(n->children, "monitor")))
265 if (!obt_parse_node_contains(c, "default")) {
266 gchar *s = obt_parse_node_string(c);
267 if (!g_ascii_strcasecmp(s, "mouse"))
268 settings->monitor = 0;
270 settings->monitor = obt_parse_node_int(c);
274 obt_parse_attr_bool(n, "force", &settings->pos_force);
277 if ((n = obt_parse_find_node(app->children, "focus")))
278 if (!obt_parse_node_contains(n, "default"))
279 settings->focus = obt_parse_node_bool(n);
281 if ((n = obt_parse_find_node(app->children, "desktop"))) {
282 if (!obt_parse_node_contains(n, "default")) {
283 gchar *s = obt_parse_node_string(n);
284 if (!g_ascii_strcasecmp(s, "all"))
285 settings->desktop = DESKTOP_ALL;
287 gint i = obt_parse_node_int(n);
289 settings->desktop = i;
295 if ((n = obt_parse_find_node(app->children, "layer")))
296 if (!obt_parse_node_contains(n, "default")) {
297 gchar *s = obt_parse_node_string(n);
298 if (!g_ascii_strcasecmp(s, "above"))
300 else if (!g_ascii_strcasecmp(s, "below"))
301 settings->layer = -1;
307 if ((n = obt_parse_find_node(app->children, "iconic")))
308 if (!obt_parse_node_contains(n, "default"))
309 settings->iconic = obt_parse_node_bool(n);
311 if ((n = obt_parse_find_node(app->children, "skip_pager")))
312 if (!obt_parse_node_contains(n, "default"))
313 settings->skip_pager = obt_parse_node_bool(n);
315 if ((n = obt_parse_find_node(app->children, "skip_taskbar")))
316 if (!obt_parse_node_contains(n, "default"))
317 settings->skip_taskbar = obt_parse_node_bool(n);
319 if ((n = obt_parse_find_node(app->children, "fullscreen")))
320 if (!obt_parse_node_contains(n, "default"))
321 settings->fullscreen = obt_parse_node_bool(n);
323 if ((n = obt_parse_find_node(app->children, "maximized")))
324 if (!obt_parse_node_contains(n, "default")) {
325 gchar *s = obt_parse_node_string(n);
326 if (!g_ascii_strcasecmp(s, "horizontal")) {
327 settings->max_horz = TRUE;
328 settings->max_vert = FALSE;
329 } else if (!g_ascii_strcasecmp(s, "vertical")) {
330 settings->max_horz = FALSE;
331 settings->max_vert = TRUE;
333 settings->max_horz = settings->max_vert =
334 obt_parse_node_bool(n);
338 config_per_app_settings = g_slist_append(config_per_app_settings,
339 (gpointer) settings);
343 name = class = role = NULL;
346 app = obt_parse_find_node(app->next, "application");
353 <action name="ChangeDesktop">
360 static void parse_key(xmlNodePtr node, GList *keylist)
364 gboolean is_chroot = FALSE;
366 if (!obt_parse_attr_string(node, "key", &key))
369 obt_parse_attr_bool(node, "chroot", &is_chroot);
371 keylist = g_list_append(keylist, key);
373 if ((n = obt_parse_find_node(node->children, "keybind"))) {
375 parse_key(n, keylist);
376 n = obt_parse_find_node(n->next, "keybind");
379 else if ((n = obt_parse_find_node(node->children, "action"))) {
381 ObActionsAct *action;
383 action = actions_parse(n);
385 keyboard_bind(keylist, action);
386 n = obt_parse_find_node(n->next, "action");
391 keyboard_chroot(keylist);
394 keylist = g_list_delete_link(keylist, g_list_last(keylist));
397 static void parse_keyboard(xmlNodePtr node, gpointer d)
402 keyboard_unbind_all();
404 if ((n = obt_parse_find_node(node->children, "chainQuitKey"))) {
405 key = obt_parse_node_string(n);
406 translate_key(key, &config_keyboard_reset_state,
407 &config_keyboard_reset_keycode);
411 if ((n = obt_parse_find_node(node->children, "keybind")))
414 n = obt_parse_find_node(n->next, "keybind");
420 <context name="Titlebar">
421 <mousebind button="Left" action="Press">
422 <action name="Raise"></action>
428 static void parse_mouse(xmlNodePtr node, gpointer d)
430 xmlNodePtr n, nbut, nact;
437 node = node->children;
439 if ((n = obt_parse_find_node(node, "dragThreshold")))
440 config_mouse_threshold = obt_parse_node_int(n);
441 if ((n = obt_parse_find_node(node, "doubleClickTime")))
442 config_mouse_dclicktime = obt_parse_node_int(n);
443 if ((n = obt_parse_find_node(node, "screenEdgeWarpTime"))) {
444 config_mouse_screenedgetime = obt_parse_node_int(n);
445 /* minimum value of 25 for this property, when it is 1 and you hit the
446 edge it basically never stops */
447 if (config_mouse_screenedgetime && config_mouse_screenedgetime < 25)
448 config_mouse_screenedgetime = 25;
451 n = obt_parse_find_node(node, "context");
453 if (!obt_parse_attr_string(n, "name", &contextstr))
455 nbut = obt_parse_find_node(n->children, "mousebind");
457 if (!obt_parse_attr_string(nbut, "button", &buttonstr))
459 if (obt_parse_attr_contains(nbut, "action", "press")) {
460 mact = OB_MOUSE_ACTION_PRESS;
461 } else if (obt_parse_attr_contains(nbut, "action", "release")) {
462 mact = OB_MOUSE_ACTION_RELEASE;
463 } else if (obt_parse_attr_contains(nbut, "action", "click")) {
464 mact = OB_MOUSE_ACTION_CLICK;
465 } else if (obt_parse_attr_contains(nbut, "action","doubleclick")) {
466 mact = OB_MOUSE_ACTION_DOUBLE_CLICK;
467 } else if (obt_parse_attr_contains(nbut, "action", "drag")) {
468 mact = OB_MOUSE_ACTION_MOTION;
471 nact = obt_parse_find_node(nbut->children, "action");
473 ObActionsAct *action;
475 if ((action = actions_parse(nact)))
476 mouse_bind(buttonstr, contextstr, mact, action);
477 nact = obt_parse_find_node(nact->next, "action");
481 nbut = obt_parse_find_node(nbut->next, "mousebind");
485 n = obt_parse_find_node(n->next, "context");
489 static void parse_focus(xmlNodePtr node, gpointer d)
493 node = node->children;
495 if ((n = obt_parse_find_node(node, "focusNew")))
496 config_focus_new = obt_parse_node_bool(n);
497 if ((n = obt_parse_find_node(node, "followMouse")))
498 config_focus_follow = obt_parse_node_bool(n);
499 if ((n = obt_parse_find_node(node, "focusDelay")))
500 config_focus_delay = obt_parse_node_int(n);
501 if ((n = obt_parse_find_node(node, "raiseOnFocus")))
502 config_focus_raise = obt_parse_node_bool(n);
503 if ((n = obt_parse_find_node(node, "focusLast")))
504 config_focus_last = obt_parse_node_bool(n);
505 if ((n = obt_parse_find_node(node, "underMouse")))
506 config_focus_under_mouse = obt_parse_node_bool(n);
509 static void parse_placement(xmlNodePtr node, gpointer d)
513 node = node->children;
515 if ((n = obt_parse_find_node(node, "policy")))
516 if (obt_parse_node_contains(n, "UnderMouse"))
517 config_place_policy = OB_PLACE_POLICY_MOUSE;
518 if ((n = obt_parse_find_node(node, "center")))
519 config_place_center = obt_parse_node_bool(n);
520 if ((n = obt_parse_find_node(node, "monitor"))) {
521 if (obt_parse_node_contains(n, "active"))
522 config_place_monitor = OB_PLACE_MONITOR_ACTIVE;
523 else if (obt_parse_node_contains(n, "mouse"))
524 config_place_monitor = OB_PLACE_MONITOR_MOUSE;
526 if ((n = obt_parse_find_node(node, "primaryMonitor"))) {
527 config_primary_monitor_index = obt_parse_node_int(n);
528 if (!config_primary_monitor_index) {
529 if (obt_parse_node_contains(n, "mouse"))
530 config_primary_monitor = OB_PLACE_MONITOR_MOUSE;
535 static void parse_margins(xmlNodePtr node, gpointer d)
539 node = node->children;
541 if ((n = obt_parse_find_node(node, "top")))
542 config_margins.top = MAX(0, obt_parse_node_int(n));
543 if ((n = obt_parse_find_node(node, "left")))
544 config_margins.left = MAX(0, obt_parse_node_int(n));
545 if ((n = obt_parse_find_node(node, "right")))
546 config_margins.right = MAX(0, obt_parse_node_int(n));
547 if ((n = obt_parse_find_node(node, "bottom")))
548 config_margins.bottom = MAX(0, obt_parse_node_int(n));
551 static void parse_theme(xmlNodePtr node, gpointer d)
555 node = node->children;
557 if ((n = obt_parse_find_node(node, "name"))) {
560 g_free(config_theme);
561 c = obt_parse_node_string(n);
562 config_theme = obt_paths_expand_tilde(c);
565 if ((n = obt_parse_find_node(node, "titleLayout"))) {
568 g_free(config_title_layout);
569 config_title_layout = obt_parse_node_string(n);
571 /* replace duplicates with spaces */
572 for (c = config_title_layout; *c != '\0'; ++c)
573 for (d = c+1; *d != '\0'; ++d)
574 if (*c == *d) *d = ' ';
576 if ((n = obt_parse_find_node(node, "keepBorder")))
577 config_theme_keepborder = obt_parse_node_bool(n);
578 if ((n = obt_parse_find_node(node, "animateIconify")))
579 config_animate_iconify = obt_parse_node_bool(n);
580 if ((n = obt_parse_find_node(node, "windowListIconSize"))) {
581 config_theme_window_list_icon_size = obt_parse_node_int(n);
582 if (config_theme_window_list_icon_size < 16)
583 config_theme_window_list_icon_size = 16;
584 else if (config_theme_window_list_icon_size > 96)
585 config_theme_window_list_icon_size = 96;
588 n = obt_parse_find_node(node, "font");
592 gchar *name = g_strdup(RrDefaultFontFamily);
593 gint size = RrDefaultFontSize;
594 RrFontWeight weight = RrDefaultFontWeight;
595 RrFontSlant slant = RrDefaultFontSlant;
597 if (obt_parse_attr_contains(n, "place", "ActiveWindow"))
598 font = &config_font_activewindow;
599 else if (obt_parse_attr_contains(n, "place", "InactiveWindow"))
600 font = &config_font_inactivewindow;
601 else if (obt_parse_attr_contains(n, "place", "MenuHeader"))
602 font = &config_font_menutitle;
603 else if (obt_parse_attr_contains(n, "place", "MenuItem"))
604 font = &config_font_menuitem;
605 else if (obt_parse_attr_contains(n, "place", "OnScreenDisplay"))
606 font = &config_font_osd;
610 if ((fnode = obt_parse_find_node(n->children, "name"))) {
612 name = obt_parse_node_string(fnode);
614 if ((fnode = obt_parse_find_node(n->children, "size"))) {
615 int s = obt_parse_node_int(fnode);
618 if ((fnode = obt_parse_find_node(n->children, "weight"))) {
619 gchar *w = obt_parse_node_string(fnode);
620 if (!g_ascii_strcasecmp(w, "Bold"))
621 weight = RR_FONTWEIGHT_BOLD;
624 if ((fnode = obt_parse_find_node(n->children, "slant"))) {
625 gchar *s = obt_parse_node_string(fnode);
626 if (!g_ascii_strcasecmp(s, "Italic"))
627 slant = RR_FONTSLANT_ITALIC;
628 if (!g_ascii_strcasecmp(s, "Oblique"))
629 slant = RR_FONTSLANT_OBLIQUE;
633 *font = RrFontOpen(ob_rr_inst, name, size, weight, slant);
636 n = obt_parse_find_node(n->next, "font");
640 static void parse_desktops(xmlNodePtr node, gpointer d)
644 node = node->children;
646 if ((n = obt_parse_find_node(node, "number"))) {
647 gint d = obt_parse_node_int(n);
649 config_desktops_num = (unsigned) d;
651 if ((n = obt_parse_find_node(node, "firstdesk"))) {
652 gint d = obt_parse_node_int(n);
654 config_screen_firstdesk = (unsigned) d;
656 if ((n = obt_parse_find_node(node, "names"))) {
660 for (it = config_desktops_names; it; it = it->next)
662 g_slist_free(config_desktops_names);
663 config_desktops_names = NULL;
665 nname = obt_parse_find_node(n->children, "name");
667 config_desktops_names =
668 g_slist_append(config_desktops_names,
669 obt_parse_node_string(nname));
670 nname = obt_parse_find_node(nname->next, "name");
673 if ((n = obt_parse_find_node(node, "popupTime")))
674 config_desktop_popup_time = obt_parse_node_int(n);
677 static void parse_resize(xmlNodePtr node, gpointer d)
681 node = node->children;
683 if ((n = obt_parse_find_node(node, "drawContents")))
684 config_resize_redraw = obt_parse_node_bool(n);
685 if ((n = obt_parse_find_node(node, "popupShow"))) {
686 config_resize_popup_show = obt_parse_node_int(n);
687 if (obt_parse_node_contains(n, "Always"))
688 config_resize_popup_show = 2;
689 else if (obt_parse_node_contains(n, "Never"))
690 config_resize_popup_show = 0;
691 else if (obt_parse_node_contains(n, "Nonpixel"))
692 config_resize_popup_show = 1;
694 if ((n = obt_parse_find_node(node, "popupPosition"))) {
695 if (obt_parse_node_contains(n, "Top"))
696 config_resize_popup_pos = OB_RESIZE_POS_TOP;
697 else if (obt_parse_node_contains(n, "Center"))
698 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
699 else if (obt_parse_node_contains(n, "Fixed")) {
700 config_resize_popup_pos = OB_RESIZE_POS_FIXED;
702 if ((n = obt_parse_find_node(node, "popupFixedPosition"))) {
705 if ((n2 = obt_parse_find_node(n->children, "x")))
706 config_parse_gravity_coord(n2,
707 &config_resize_popup_fixed.x);
708 if ((n2 = obt_parse_find_node(n->children, "y")))
709 config_parse_gravity_coord(n2,
710 &config_resize_popup_fixed.y);
712 config_resize_popup_fixed.x.pos =
713 MAX(config_resize_popup_fixed.x.pos, 0);
714 config_resize_popup_fixed.y.pos =
715 MAX(config_resize_popup_fixed.y.pos, 0);
721 static void parse_dock(xmlNodePtr node, gpointer d)
725 node = node->children;
727 if ((n = obt_parse_find_node(node, "position"))) {
728 if (obt_parse_node_contains(n, "TopLeft"))
729 config_dock_floating = FALSE,
730 config_dock_pos = OB_DIRECTION_NORTHWEST;
731 else if (obt_parse_node_contains(n, "Top"))
732 config_dock_floating = FALSE,
733 config_dock_pos = OB_DIRECTION_NORTH;
734 else if (obt_parse_node_contains(n, "TopRight"))
735 config_dock_floating = FALSE,
736 config_dock_pos = OB_DIRECTION_NORTHEAST;
737 else if (obt_parse_node_contains(n, "Right"))
738 config_dock_floating = FALSE,
739 config_dock_pos = OB_DIRECTION_EAST;
740 else if (obt_parse_node_contains(n, "BottomRight"))
741 config_dock_floating = FALSE,
742 config_dock_pos = OB_DIRECTION_SOUTHEAST;
743 else if (obt_parse_node_contains(n, "Bottom"))
744 config_dock_floating = FALSE,
745 config_dock_pos = OB_DIRECTION_SOUTH;
746 else if (obt_parse_node_contains(n, "BottomLeft"))
747 config_dock_floating = FALSE,
748 config_dock_pos = OB_DIRECTION_SOUTHWEST;
749 else if (obt_parse_node_contains(n, "Left"))
750 config_dock_floating = FALSE,
751 config_dock_pos = OB_DIRECTION_WEST;
752 else if (obt_parse_node_contains(n, "Floating"))
753 config_dock_floating = TRUE;
755 if (config_dock_floating) {
756 if ((n = obt_parse_find_node(node, "floatingX")))
757 config_dock_x = obt_parse_node_int(n);
758 if ((n = obt_parse_find_node(node, "floatingY")))
759 config_dock_y = obt_parse_node_int(n);
761 if ((n = obt_parse_find_node(node, "noStrut")))
762 config_dock_nostrut = obt_parse_node_bool(n);
764 if ((n = obt_parse_find_node(node, "stacking"))) {
765 if (obt_parse_node_contains(n, "normal"))
766 config_dock_layer = OB_STACKING_LAYER_NORMAL;
767 else if (obt_parse_node_contains(n, "below"))
768 config_dock_layer = OB_STACKING_LAYER_BELOW;
769 else if (obt_parse_node_contains(n, "above"))
770 config_dock_layer = OB_STACKING_LAYER_ABOVE;
772 if ((n = obt_parse_find_node(node, "direction"))) {
773 if (obt_parse_node_contains(n, "horizontal"))
774 config_dock_orient = OB_ORIENTATION_HORZ;
775 else if (obt_parse_node_contains(n, "vertical"))
776 config_dock_orient = OB_ORIENTATION_VERT;
778 if ((n = obt_parse_find_node(node, "autoHide")))
779 config_dock_hide = obt_parse_node_bool(n);
780 if ((n = obt_parse_find_node(node, "hideDelay")))
781 config_dock_hide_delay = obt_parse_node_int(n);
782 if ((n = obt_parse_find_node(node, "showDelay")))
783 config_dock_show_delay = obt_parse_node_int(n);
784 if ((n = obt_parse_find_node(node, "moveButton"))) {
785 gchar *str = obt_parse_node_string(n);
787 if (translate_button(str, &s, &b)) {
788 config_dock_app_move_button = b;
789 config_dock_app_move_modifiers = s;
791 g_message(_("Invalid button \"%s\" specified in config file"), str);
797 static void parse_menu(xmlNodePtr node, gpointer d)
800 node = node->children;
802 if ((n = obt_parse_find_node(node, "hideDelay")))
803 config_menu_hide_delay = obt_parse_node_int(n);
804 if ((n = obt_parse_find_node(node, "middle")))
805 config_menu_middle = obt_parse_node_bool(n);
806 if ((n = obt_parse_find_node(node, "submenuShowDelay")))
807 config_submenu_show_delay = obt_parse_node_int(n);
808 if ((n = obt_parse_find_node(node, "applicationIcons")))
809 config_menu_client_list_icons = obt_parse_node_bool(n);
810 if ((n = obt_parse_find_node(node, "manageDesktops")))
811 config_menu_manage_desktops = obt_parse_node_bool(n);
813 while ((node = obt_parse_find_node(node, "file"))) {
814 gchar *c = obt_parse_node_string(node);
815 config_menu_files = g_slist_append(config_menu_files,
816 obt_paths_expand_tilde(c));
822 static void parse_resistance(xmlNodePtr node, gpointer d)
826 node = node->children;
827 if ((n = obt_parse_find_node(node, "strength")))
828 config_resist_win = obt_parse_node_int(n);
829 if ((n = obt_parse_find_node(node, "screen_edge_strength")))
830 config_resist_edge = obt_parse_node_int(n);
836 const gchar *actname;
839 static void bind_default_keyboard(void)
842 ObDefKeyBind binds[] = {
843 { "A-Tab", "NextWindow" },
844 { "S-A-Tab", "PreviousWindow" },
848 for (it = binds; it->key; ++it) {
849 GList *l = g_list_append(NULL, g_strdup(it->key));
850 keyboard_bind(l, actions_parse_string(it->actname));
857 const gchar *context;
858 const ObMouseAction mact;
859 const gchar *actname;
862 static void bind_default_mouse(void)
865 ObDefMouseBind binds[] = {
866 { "Left", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
867 { "Middle", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
868 { "Right", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
869 { "Left", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
870 { "Middle", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
871 { "Right", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
872 { "Left", "Titlebar", OB_MOUSE_ACTION_PRESS, "Focus" },
873 { "Left", "Bottom", OB_MOUSE_ACTION_PRESS, "Focus" },
874 { "Left", "BLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
875 { "Left", "BRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
876 { "Left", "TLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
877 { "Left", "TRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
878 { "Left", "Close", OB_MOUSE_ACTION_PRESS, "Focus" },
879 { "Left", "Maximize", OB_MOUSE_ACTION_PRESS, "Focus" },
880 { "Left", "Iconify", OB_MOUSE_ACTION_PRESS, "Focus" },
881 { "Left", "Icon", OB_MOUSE_ACTION_PRESS, "Focus" },
882 { "Left", "AllDesktops", OB_MOUSE_ACTION_PRESS, "Focus" },
883 { "Left", "Shade", OB_MOUSE_ACTION_PRESS, "Focus" },
884 { "Left", "Client", OB_MOUSE_ACTION_CLICK, "Raise" },
885 { "Left", "Titlebar", OB_MOUSE_ACTION_CLICK, "Raise" },
886 { "Middle", "Titlebar", OB_MOUSE_ACTION_CLICK, "Lower" },
887 { "Left", "BLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
888 { "Left", "BRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
889 { "Left", "TLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
890 { "Left", "TRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
891 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Raise" },
892 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "Raise" },
893 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Raise" },
894 { "Left", "Icon", OB_MOUSE_ACTION_CLICK, "Raise" },
895 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "Raise" },
896 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "Raise" },
897 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Close" },
898 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "ToggleMaximize" },
899 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Iconify" },
900 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "ToggleOmnipresent" },
901 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "ToggleShade" },
902 { "Left", "TLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
903 { "Left", "TRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
904 { "Left", "BLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
905 { "Left", "BRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
906 { "Left", "Top", OB_MOUSE_ACTION_MOTION, "Resize" },
907 { "Left", "Bottom", OB_MOUSE_ACTION_MOTION, "Resize" },
908 { "Left", "Left", OB_MOUSE_ACTION_MOTION, "Resize" },
909 { "Left", "Right", OB_MOUSE_ACTION_MOTION, "Resize" },
910 { "Left", "Titlebar", OB_MOUSE_ACTION_MOTION, "Move" },
911 { "A-Left", "Frame", OB_MOUSE_ACTION_MOTION, "Move" },
912 { "A-Middle", "Frame", OB_MOUSE_ACTION_MOTION, "Resize" },
913 { NULL, NULL, 0, NULL }
916 for (it = binds; it->button; ++it)
917 mouse_bind(it->button, it->context, it->mact,
918 actions_parse_string(it->actname));
921 void config_startup(ObtParseInst *i)
923 config_focus_new = TRUE;
924 config_focus_follow = FALSE;
925 config_focus_delay = 0;
926 config_focus_raise = FALSE;
927 config_focus_last = TRUE;
928 config_focus_under_mouse = FALSE;
930 obt_parse_register(i, "focus", parse_focus, NULL);
932 config_place_policy = OB_PLACE_POLICY_SMART;
933 config_place_center = TRUE;
934 config_place_monitor = OB_PLACE_MONITOR_ANY;
936 config_primary_monitor_index = 1;
937 config_primary_monitor = OB_PLACE_MONITOR_ACTIVE;
939 obt_parse_register(i, "placement", parse_placement, NULL);
941 STRUT_PARTIAL_SET(config_margins, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
943 obt_parse_register(i, "margins", parse_margins, NULL);
947 config_animate_iconify = TRUE;
948 config_title_layout = g_strdup("NLIMC");
949 config_theme_keepborder = TRUE;
950 config_theme_window_list_icon_size = 36;
952 config_font_activewindow = NULL;
953 config_font_inactivewindow = NULL;
954 config_font_menuitem = NULL;
955 config_font_menutitle = NULL;
957 obt_parse_register(i, "theme", parse_theme, NULL);
959 config_desktops_num = 4;
960 config_screen_firstdesk = 1;
961 config_desktops_names = NULL;
962 config_desktop_popup_time = 875;
964 obt_parse_register(i, "desktops", parse_desktops, NULL);
966 config_resize_redraw = TRUE;
967 config_resize_popup_show = 1; /* nonpixel increments */
968 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
969 GRAVITY_COORD_SET(config_resize_popup_fixed.x, 0, FALSE, FALSE);
970 GRAVITY_COORD_SET(config_resize_popup_fixed.y, 0, FALSE, FALSE);
972 obt_parse_register(i, "resize", parse_resize, NULL);
974 config_dock_layer = OB_STACKING_LAYER_ABOVE;
975 config_dock_pos = OB_DIRECTION_NORTHEAST;
976 config_dock_floating = FALSE;
977 config_dock_nostrut = FALSE;
980 config_dock_orient = OB_ORIENTATION_VERT;
981 config_dock_hide = FALSE;
982 config_dock_hide_delay = 300;
983 config_dock_show_delay = 300;
984 config_dock_app_move_button = 2; /* middle */
985 config_dock_app_move_modifiers = 0;
987 obt_parse_register(i, "dock", parse_dock, NULL);
989 translate_key("C-g", &config_keyboard_reset_state,
990 &config_keyboard_reset_keycode);
992 bind_default_keyboard();
994 obt_parse_register(i, "keyboard", parse_keyboard, NULL);
996 config_mouse_threshold = 8;
997 config_mouse_dclicktime = 200;
998 config_mouse_screenedgetime = 400;
1000 bind_default_mouse();
1002 obt_parse_register(i, "mouse", parse_mouse, NULL);
1004 config_resist_win = 10;
1005 config_resist_edge = 20;
1007 obt_parse_register(i, "resistance", parse_resistance, NULL);
1009 config_menu_hide_delay = 250;
1010 config_menu_middle = FALSE;
1011 config_submenu_show_delay = 0;
1012 config_menu_client_list_icons = TRUE;
1013 config_menu_manage_desktops = TRUE;
1014 config_menu_files = NULL;
1016 obt_parse_register(i, "menu", parse_menu, NULL);
1018 config_per_app_settings = NULL;
1020 obt_parse_register(i, "applications", parse_per_app_settings, NULL);
1023 void config_shutdown(void)
1027 g_free(config_theme);
1029 g_free(config_title_layout);
1031 RrFontClose(config_font_activewindow);
1032 RrFontClose(config_font_inactivewindow);
1033 RrFontClose(config_font_menuitem);
1034 RrFontClose(config_font_menutitle);
1035 RrFontClose(config_font_osd);
1037 for (it = config_desktops_names; it; it = g_slist_next(it))
1039 g_slist_free(config_desktops_names);
1041 for (it = config_menu_files; it; it = g_slist_next(it))
1043 g_slist_free(config_menu_files);
1045 for (it = config_per_app_settings; it; it = g_slist_next(it)) {
1046 ObAppSettings *itd = (ObAppSettings *)it->data;
1047 if (itd->name) g_pattern_spec_free(itd->name);
1048 if (itd->role) g_pattern_spec_free(itd->role);
1049 if (itd->class) g_pattern_spec_free(itd->class);
1052 g_slist_free(config_per_app_settings);