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_osd;
62 guint config_desktops_num;
63 GSList *config_desktops_names;
64 guint config_screen_firstdesk;
65 guint config_desktop_popup_time;
67 gboolean config_resize_redraw;
68 gint config_resize_popup_show;
69 ObResizePopupPos config_resize_popup_pos;
70 GravityPoint config_resize_popup_fixed;
72 ObStackingLayer config_dock_layer;
73 gboolean config_dock_floating;
74 gboolean config_dock_nostrut;
75 ObDirection config_dock_pos;
78 ObOrientation config_dock_orient;
79 gboolean config_dock_hide;
80 guint config_dock_hide_delay;
81 guint config_dock_show_delay;
82 guint config_dock_app_move_button;
83 guint config_dock_app_move_modifiers;
85 guint config_keyboard_reset_keycode;
86 guint config_keyboard_reset_state;
88 gint config_mouse_threshold;
89 gint config_mouse_dclicktime;
90 gint config_mouse_screenedgetime;
92 guint config_menu_hide_delay;
93 gboolean config_menu_middle;
94 guint config_submenu_show_delay;
95 gboolean config_menu_client_list_icons;
96 gboolean config_menu_manage_desktops;
98 GSList *config_menu_files;
100 gint config_resist_win;
101 gint config_resist_edge;
103 GSList *config_per_app_settings;
105 ObAppSettings* config_create_app_settings(void)
107 ObAppSettings *settings = g_new0(ObAppSettings, 1);
109 settings->decor = -1;
110 settings->shade = -1;
111 settings->monitor = -1;
112 settings->focus = -1;
113 settings->desktop = 0;
114 settings->layer = -2;
115 settings->iconic = -1;
116 settings->skip_pager = -1;
117 settings->skip_taskbar = -1;
118 settings->fullscreen = -1;
119 settings->max_horz = -1;
120 settings->max_vert = -1;
124 #define copy_if(setting, default) \
125 if (src->setting != default) dst->setting = src->setting
126 void config_app_settings_copy_non_defaults(const ObAppSettings *src,
129 g_assert(src != NULL);
130 g_assert(dst != NULL);
132 copy_if(type, (ObClientType)-1);
135 copy_if(monitor, -1);
140 copy_if(skip_pager, -1);
141 copy_if(skip_taskbar, -1);
142 copy_if(fullscreen, -1);
143 copy_if(max_horz, -1);
144 copy_if(max_vert, -1);
146 if (src->pos_given) {
147 dst->pos_given = TRUE;
148 dst->pos_force = src->pos_force;
149 dst->position = src->position;
150 dst->monitor = src->monitor;
154 static void config_parse_gravity_coord(xmlNodePtr node, GravityCoord *c)
156 gchar *s = obt_parse_node_string(node);
157 if (!g_ascii_strcasecmp(s, "center"))
162 if (s[0] == '-' || s[0] == '+')
172 <application name="aterm">
175 <application name="Rhythmbox">
182 .. there is a lot more settings available
187 /* Manages settings for individual applications.
188 Some notes: monitor is the screen number in a multi monitor
189 (Xinerama) setup (starting from 0) or mouse, meaning the
190 monitor the pointer is on. Default: mouse.
191 Layer can be three values, above (Always on top), below
192 (Always on bottom) and everything else (normal behaviour).
193 Positions can be an integer value or center, which will
194 center the window in the specified axis. Position is within
195 the monitor, so <position><x>center</x></position><monitor>2</monitor>
196 will center the window on the second monitor.
198 static void parse_per_app_settings(xmlNodePtr node, gpointer d)
200 xmlNodePtr app = obt_parse_find_node(node->children, "application");
201 gchar *name = NULL, *class = NULL, *role = NULL, *type = NULL;
202 gboolean name_set, class_set, type_set;
203 gboolean x_pos_given;
208 class_set = obt_parse_attr_string(app, "class", &class);
209 name_set = obt_parse_attr_string(app, "name", &name);
210 type_set = obt_parse_attr_string(app, "type", &type);
211 if (class_set || name_set) {
213 ObAppSettings *settings = config_create_app_settings();;
216 settings->name = g_pattern_spec_new(name);
219 settings->class = g_pattern_spec_new(class);
222 if (!g_ascii_strcasecmp(type, "normal"))
223 settings->type = OB_CLIENT_TYPE_NORMAL;
224 else if (!g_ascii_strcasecmp(type, "dialog"))
225 settings->type = OB_CLIENT_TYPE_DIALOG;
226 else if (!g_ascii_strcasecmp(type, "splash"))
227 settings->type = OB_CLIENT_TYPE_SPLASH;
228 else if (!g_ascii_strcasecmp(type, "utility"))
229 settings->type = OB_CLIENT_TYPE_UTILITY;
230 else if (!g_ascii_strcasecmp(type, "menu"))
231 settings->type = OB_CLIENT_TYPE_MENU;
232 else if (!g_ascii_strcasecmp(type, "toolbar"))
233 settings->type = OB_CLIENT_TYPE_TOOLBAR;
234 else if (!g_ascii_strcasecmp(type, "dock"))
235 settings->type = OB_CLIENT_TYPE_DOCK;
236 else if (!g_ascii_strcasecmp(type, "desktop"))
237 settings->type = OB_CLIENT_TYPE_DESKTOP;
240 if (obt_parse_attr_string(app, "role", &role))
241 settings->role = g_pattern_spec_new(role);
243 if ((n = obt_parse_find_node(app->children, "decor")))
244 if (!obt_parse_node_contains(n, "default"))
245 settings->decor = obt_parse_node_bool(n);
247 if ((n = obt_parse_find_node(app->children, "shade")))
248 if (!obt_parse_node_contains(n, "default"))
249 settings->shade = obt_parse_node_bool(n);
251 if ((n = obt_parse_find_node(app->children, "position"))) {
252 if ((c = obt_parse_find_node(n->children, "x")))
253 if (!obt_parse_node_contains(c, "default")) {
254 config_parse_gravity_coord(c, &settings->position.x);
258 if (x_pos_given && (c = obt_parse_find_node(n->children, "y")))
259 if (!obt_parse_node_contains(c, "default")) {
260 config_parse_gravity_coord(c, &settings->position.y);
261 settings->pos_given = TRUE;
264 if (settings->pos_given &&
265 (c = obt_parse_find_node(n->children, "monitor")))
266 if (!obt_parse_node_contains(c, "default")) {
267 gchar *s = obt_parse_node_string(c);
268 if (!g_ascii_strcasecmp(s, "mouse"))
269 settings->monitor = 0;
271 settings->monitor = obt_parse_node_int(c);
275 obt_parse_attr_bool(n, "force", &settings->pos_force);
278 if ((n = obt_parse_find_node(app->children, "focus")))
279 if (!obt_parse_node_contains(n, "default"))
280 settings->focus = obt_parse_node_bool(n);
282 if ((n = obt_parse_find_node(app->children, "desktop"))) {
283 if (!obt_parse_node_contains(n, "default")) {
284 gchar *s = obt_parse_node_string(n);
285 if (!g_ascii_strcasecmp(s, "all"))
286 settings->desktop = DESKTOP_ALL;
288 gint i = obt_parse_node_int(n);
290 settings->desktop = i;
296 if ((n = obt_parse_find_node(app->children, "layer")))
297 if (!obt_parse_node_contains(n, "default")) {
298 gchar *s = obt_parse_node_string(n);
299 if (!g_ascii_strcasecmp(s, "above"))
301 else if (!g_ascii_strcasecmp(s, "below"))
302 settings->layer = -1;
308 if ((n = obt_parse_find_node(app->children, "iconic")))
309 if (!obt_parse_node_contains(n, "default"))
310 settings->iconic = obt_parse_node_bool(n);
312 if ((n = obt_parse_find_node(app->children, "skip_pager")))
313 if (!obt_parse_node_contains(n, "default"))
314 settings->skip_pager = obt_parse_node_bool(n);
316 if ((n = obt_parse_find_node(app->children, "skip_taskbar")))
317 if (!obt_parse_node_contains(n, "default"))
318 settings->skip_taskbar = obt_parse_node_bool(n);
320 if ((n = obt_parse_find_node(app->children, "fullscreen")))
321 if (!obt_parse_node_contains(n, "default"))
322 settings->fullscreen = obt_parse_node_bool(n);
324 if ((n = obt_parse_find_node(app->children, "maximized")))
325 if (!obt_parse_node_contains(n, "default")) {
326 gchar *s = obt_parse_node_string(n);
327 if (!g_ascii_strcasecmp(s, "horizontal")) {
328 settings->max_horz = TRUE;
329 settings->max_vert = FALSE;
330 } else if (!g_ascii_strcasecmp(s, "vertical")) {
331 settings->max_horz = FALSE;
332 settings->max_vert = TRUE;
334 settings->max_horz = settings->max_vert =
335 obt_parse_node_bool(n);
339 config_per_app_settings = g_slist_append(config_per_app_settings,
340 (gpointer) settings);
344 name = class = role = NULL;
347 app = obt_parse_find_node(app->next, "application");
354 <action name="ChangeDesktop">
361 static void parse_key(xmlNodePtr node, GList *keylist)
365 gboolean is_chroot = FALSE;
367 if (!obt_parse_attr_string(node, "key", &key))
370 obt_parse_attr_bool(node, "chroot", &is_chroot);
372 keylist = g_list_append(keylist, key);
374 if ((n = obt_parse_find_node(node->children, "keybind"))) {
376 parse_key(n, keylist);
377 n = obt_parse_find_node(n->next, "keybind");
380 else if ((n = obt_parse_find_node(node->children, "action"))) {
382 ObActionsAct *action;
384 action = actions_parse(n);
386 keyboard_bind(keylist, action);
387 n = obt_parse_find_node(n->next, "action");
392 keyboard_chroot(keylist);
395 keylist = g_list_delete_link(keylist, g_list_last(keylist));
398 static void parse_keyboard(xmlNodePtr node, gpointer d)
403 keyboard_unbind_all();
405 if ((n = obt_parse_find_node(node->children, "chainQuitKey"))) {
406 key = obt_parse_node_string(n);
407 translate_key(key, &config_keyboard_reset_state,
408 &config_keyboard_reset_keycode);
412 if ((n = obt_parse_find_node(node->children, "keybind")))
415 n = obt_parse_find_node(n->next, "keybind");
421 <context name="Titlebar">
422 <mousebind button="Left" action="Press">
423 <action name="Raise"></action>
429 static void parse_mouse(xmlNodePtr node, gpointer d)
431 xmlNodePtr n, nbut, nact;
438 node = node->children;
440 if ((n = obt_parse_find_node(node, "dragThreshold")))
441 config_mouse_threshold = obt_parse_node_int(n);
442 if ((n = obt_parse_find_node(node, "doubleClickTime")))
443 config_mouse_dclicktime = obt_parse_node_int(n);
444 if ((n = obt_parse_find_node(node, "screenEdgeWarpTime"))) {
445 config_mouse_screenedgetime = obt_parse_node_int(n);
446 /* minimum value of 25 for this property, when it is 1 and you hit the
447 edge it basically never stops */
448 if (config_mouse_screenedgetime && config_mouse_screenedgetime < 25)
449 config_mouse_screenedgetime = 25;
452 n = obt_parse_find_node(node, "context");
454 if (!obt_parse_attr_string(n, "name", &contextstr))
456 nbut = obt_parse_find_node(n->children, "mousebind");
458 if (!obt_parse_attr_string(nbut, "button", &buttonstr))
460 if (obt_parse_attr_contains(nbut, "action", "press")) {
461 mact = OB_MOUSE_ACTION_PRESS;
462 } else if (obt_parse_attr_contains(nbut, "action", "release")) {
463 mact = OB_MOUSE_ACTION_RELEASE;
464 } else if (obt_parse_attr_contains(nbut, "action", "click")) {
465 mact = OB_MOUSE_ACTION_CLICK;
466 } else if (obt_parse_attr_contains(nbut, "action","doubleclick")) {
467 mact = OB_MOUSE_ACTION_DOUBLE_CLICK;
468 } else if (obt_parse_attr_contains(nbut, "action", "drag")) {
469 mact = OB_MOUSE_ACTION_MOTION;
472 nact = obt_parse_find_node(nbut->children, "action");
474 ObActionsAct *action;
476 if ((action = actions_parse(nact)))
477 mouse_bind(buttonstr, contextstr, mact, action);
478 nact = obt_parse_find_node(nact->next, "action");
482 nbut = obt_parse_find_node(nbut->next, "mousebind");
486 n = obt_parse_find_node(n->next, "context");
490 static void parse_focus(xmlNodePtr node, gpointer d)
494 node = node->children;
496 if ((n = obt_parse_find_node(node, "focusNew")))
497 config_focus_new = obt_parse_node_bool(n);
498 if ((n = obt_parse_find_node(node, "followMouse")))
499 config_focus_follow = obt_parse_node_bool(n);
500 if ((n = obt_parse_find_node(node, "focusDelay")))
501 config_focus_delay = obt_parse_node_int(n);
502 if ((n = obt_parse_find_node(node, "raiseOnFocus")))
503 config_focus_raise = obt_parse_node_bool(n);
504 if ((n = obt_parse_find_node(node, "focusLast")))
505 config_focus_last = obt_parse_node_bool(n);
506 if ((n = obt_parse_find_node(node, "underMouse")))
507 config_focus_under_mouse = obt_parse_node_bool(n);
508 if ((n = obt_parse_find_node(node, "unfocusOnLeave")))
509 config_unfocus_leave = obt_parse_node_bool(n);
512 static void parse_placement(xmlNodePtr node, gpointer d)
516 node = node->children;
518 if ((n = obt_parse_find_node(node, "policy")))
519 if (obt_parse_node_contains(n, "UnderMouse"))
520 config_place_policy = OB_PLACE_POLICY_MOUSE;
521 if ((n = obt_parse_find_node(node, "center")))
522 config_place_center = obt_parse_node_bool(n);
523 if ((n = obt_parse_find_node(node, "monitor"))) {
524 if (obt_parse_node_contains(n, "active"))
525 config_place_monitor = OB_PLACE_MONITOR_ACTIVE;
526 else if (obt_parse_node_contains(n, "mouse"))
527 config_place_monitor = OB_PLACE_MONITOR_MOUSE;
529 if ((n = obt_parse_find_node(node, "primaryMonitor"))) {
530 config_primary_monitor_index = obt_parse_node_int(n);
531 if (!config_primary_monitor_index) {
532 if (obt_parse_node_contains(n, "mouse"))
533 config_primary_monitor = OB_PLACE_MONITOR_MOUSE;
538 static void parse_margins(xmlNodePtr node, gpointer d)
542 node = node->children;
544 if ((n = obt_parse_find_node(node, "top")))
545 config_margins.top = MAX(0, obt_parse_node_int(n));
546 if ((n = obt_parse_find_node(node, "left")))
547 config_margins.left = MAX(0, obt_parse_node_int(n));
548 if ((n = obt_parse_find_node(node, "right")))
549 config_margins.right = MAX(0, obt_parse_node_int(n));
550 if ((n = obt_parse_find_node(node, "bottom")))
551 config_margins.bottom = MAX(0, obt_parse_node_int(n));
554 static void parse_theme(xmlNodePtr node, gpointer d)
558 node = node->children;
560 if ((n = obt_parse_find_node(node, "name"))) {
563 g_free(config_theme);
564 c = obt_parse_node_string(n);
565 config_theme = obt_paths_expand_tilde(c);
568 if ((n = obt_parse_find_node(node, "titleLayout"))) {
571 g_free(config_title_layout);
572 config_title_layout = obt_parse_node_string(n);
574 /* replace duplicates with spaces */
575 for (c = config_title_layout; *c != '\0'; ++c)
576 for (d = c+1; *d != '\0'; ++d)
577 if (*c == *d) *d = ' ';
579 if ((n = obt_parse_find_node(node, "keepBorder")))
580 config_theme_keepborder = obt_parse_node_bool(n);
581 if ((n = obt_parse_find_node(node, "animateIconify")))
582 config_animate_iconify = obt_parse_node_bool(n);
583 if ((n = obt_parse_find_node(node, "windowListIconSize"))) {
584 config_theme_window_list_icon_size = obt_parse_node_int(n);
585 if (config_theme_window_list_icon_size < 16)
586 config_theme_window_list_icon_size = 16;
587 else if (config_theme_window_list_icon_size > 96)
588 config_theme_window_list_icon_size = 96;
591 n = obt_parse_find_node(node, "font");
595 gchar *name = g_strdup(RrDefaultFontFamily);
596 gint size = RrDefaultFontSize;
597 RrFontWeight weight = RrDefaultFontWeight;
598 RrFontSlant slant = RrDefaultFontSlant;
600 if (obt_parse_attr_contains(n, "place", "ActiveWindow"))
601 font = &config_font_activewindow;
602 else if (obt_parse_attr_contains(n, "place", "InactiveWindow"))
603 font = &config_font_inactivewindow;
604 else if (obt_parse_attr_contains(n, "place", "MenuHeader"))
605 font = &config_font_menutitle;
606 else if (obt_parse_attr_contains(n, "place", "MenuItem"))
607 font = &config_font_menuitem;
608 else if (obt_parse_attr_contains(n, "place", "OnScreenDisplay"))
609 font = &config_font_osd;
613 if ((fnode = obt_parse_find_node(n->children, "name"))) {
615 name = obt_parse_node_string(fnode);
617 if ((fnode = obt_parse_find_node(n->children, "size"))) {
618 int s = obt_parse_node_int(fnode);
621 if ((fnode = obt_parse_find_node(n->children, "weight"))) {
622 gchar *w = obt_parse_node_string(fnode);
623 if (!g_ascii_strcasecmp(w, "Bold"))
624 weight = RR_FONTWEIGHT_BOLD;
627 if ((fnode = obt_parse_find_node(n->children, "slant"))) {
628 gchar *s = obt_parse_node_string(fnode);
629 if (!g_ascii_strcasecmp(s, "Italic"))
630 slant = RR_FONTSLANT_ITALIC;
631 if (!g_ascii_strcasecmp(s, "Oblique"))
632 slant = RR_FONTSLANT_OBLIQUE;
636 *font = RrFontOpen(ob_rr_inst, name, size, weight, slant);
639 n = obt_parse_find_node(n->next, "font");
643 static void parse_desktops(xmlNodePtr node, gpointer d)
647 node = node->children;
649 if ((n = obt_parse_find_node(node, "number"))) {
650 gint d = obt_parse_node_int(n);
652 config_desktops_num = (unsigned) d;
654 if ((n = obt_parse_find_node(node, "firstdesk"))) {
655 gint d = obt_parse_node_int(n);
657 config_screen_firstdesk = (unsigned) d;
659 if ((n = obt_parse_find_node(node, "names"))) {
663 for (it = config_desktops_names; it; it = it->next)
665 g_slist_free(config_desktops_names);
666 config_desktops_names = NULL;
668 nname = obt_parse_find_node(n->children, "name");
670 config_desktops_names =
671 g_slist_append(config_desktops_names,
672 obt_parse_node_string(nname));
673 nname = obt_parse_find_node(nname->next, "name");
676 if ((n = obt_parse_find_node(node, "popupTime")))
677 config_desktop_popup_time = obt_parse_node_int(n);
680 static void parse_resize(xmlNodePtr node, gpointer d)
684 node = node->children;
686 if ((n = obt_parse_find_node(node, "drawContents")))
687 config_resize_redraw = obt_parse_node_bool(n);
688 if ((n = obt_parse_find_node(node, "popupShow"))) {
689 config_resize_popup_show = obt_parse_node_int(n);
690 if (obt_parse_node_contains(n, "Always"))
691 config_resize_popup_show = 2;
692 else if (obt_parse_node_contains(n, "Never"))
693 config_resize_popup_show = 0;
694 else if (obt_parse_node_contains(n, "Nonpixel"))
695 config_resize_popup_show = 1;
697 if ((n = obt_parse_find_node(node, "popupPosition"))) {
698 if (obt_parse_node_contains(n, "Top"))
699 config_resize_popup_pos = OB_RESIZE_POS_TOP;
700 else if (obt_parse_node_contains(n, "Center"))
701 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
702 else if (obt_parse_node_contains(n, "Fixed")) {
703 config_resize_popup_pos = OB_RESIZE_POS_FIXED;
705 if ((n = obt_parse_find_node(node, "popupFixedPosition"))) {
708 if ((n2 = obt_parse_find_node(n->children, "x")))
709 config_parse_gravity_coord(n2,
710 &config_resize_popup_fixed.x);
711 if ((n2 = obt_parse_find_node(n->children, "y")))
712 config_parse_gravity_coord(n2,
713 &config_resize_popup_fixed.y);
715 config_resize_popup_fixed.x.pos =
716 MAX(config_resize_popup_fixed.x.pos, 0);
717 config_resize_popup_fixed.y.pos =
718 MAX(config_resize_popup_fixed.y.pos, 0);
724 static void parse_dock(xmlNodePtr node, gpointer d)
728 node = node->children;
730 if ((n = obt_parse_find_node(node, "position"))) {
731 if (obt_parse_node_contains(n, "TopLeft"))
732 config_dock_floating = FALSE,
733 config_dock_pos = OB_DIRECTION_NORTHWEST;
734 else if (obt_parse_node_contains(n, "Top"))
735 config_dock_floating = FALSE,
736 config_dock_pos = OB_DIRECTION_NORTH;
737 else if (obt_parse_node_contains(n, "TopRight"))
738 config_dock_floating = FALSE,
739 config_dock_pos = OB_DIRECTION_NORTHEAST;
740 else if (obt_parse_node_contains(n, "Right"))
741 config_dock_floating = FALSE,
742 config_dock_pos = OB_DIRECTION_EAST;
743 else if (obt_parse_node_contains(n, "BottomRight"))
744 config_dock_floating = FALSE,
745 config_dock_pos = OB_DIRECTION_SOUTHEAST;
746 else if (obt_parse_node_contains(n, "Bottom"))
747 config_dock_floating = FALSE,
748 config_dock_pos = OB_DIRECTION_SOUTH;
749 else if (obt_parse_node_contains(n, "BottomLeft"))
750 config_dock_floating = FALSE,
751 config_dock_pos = OB_DIRECTION_SOUTHWEST;
752 else if (obt_parse_node_contains(n, "Left"))
753 config_dock_floating = FALSE,
754 config_dock_pos = OB_DIRECTION_WEST;
755 else if (obt_parse_node_contains(n, "Floating"))
756 config_dock_floating = TRUE;
758 if (config_dock_floating) {
759 if ((n = obt_parse_find_node(node, "floatingX")))
760 config_dock_x = obt_parse_node_int(n);
761 if ((n = obt_parse_find_node(node, "floatingY")))
762 config_dock_y = obt_parse_node_int(n);
764 if ((n = obt_parse_find_node(node, "noStrut")))
765 config_dock_nostrut = obt_parse_node_bool(n);
767 if ((n = obt_parse_find_node(node, "stacking"))) {
768 if (obt_parse_node_contains(n, "normal"))
769 config_dock_layer = OB_STACKING_LAYER_NORMAL;
770 else if (obt_parse_node_contains(n, "below"))
771 config_dock_layer = OB_STACKING_LAYER_BELOW;
772 else if (obt_parse_node_contains(n, "above"))
773 config_dock_layer = OB_STACKING_LAYER_ABOVE;
775 if ((n = obt_parse_find_node(node, "direction"))) {
776 if (obt_parse_node_contains(n, "horizontal"))
777 config_dock_orient = OB_ORIENTATION_HORZ;
778 else if (obt_parse_node_contains(n, "vertical"))
779 config_dock_orient = OB_ORIENTATION_VERT;
781 if ((n = obt_parse_find_node(node, "autoHide")))
782 config_dock_hide = obt_parse_node_bool(n);
783 if ((n = obt_parse_find_node(node, "hideDelay")))
784 config_dock_hide_delay = obt_parse_node_int(n);
785 if ((n = obt_parse_find_node(node, "showDelay")))
786 config_dock_show_delay = obt_parse_node_int(n);
787 if ((n = obt_parse_find_node(node, "moveButton"))) {
788 gchar *str = obt_parse_node_string(n);
790 if (translate_button(str, &s, &b)) {
791 config_dock_app_move_button = b;
792 config_dock_app_move_modifiers = s;
794 g_message(_("Invalid button \"%s\" specified in config file"), str);
800 static void parse_menu(xmlNodePtr node, gpointer d)
803 node = node->children;
805 if ((n = obt_parse_find_node(node, "hideDelay")))
806 config_menu_hide_delay = obt_parse_node_int(n);
807 if ((n = obt_parse_find_node(node, "middle")))
808 config_menu_middle = obt_parse_node_bool(n);
809 if ((n = obt_parse_find_node(node, "submenuShowDelay")))
810 config_submenu_show_delay = obt_parse_node_int(n);
811 if ((n = obt_parse_find_node(node, "applicationIcons")))
812 config_menu_client_list_icons = obt_parse_node_bool(n);
813 if ((n = obt_parse_find_node(node, "manageDesktops")))
814 config_menu_manage_desktops = obt_parse_node_bool(n);
816 while ((node = obt_parse_find_node(node, "file"))) {
817 gchar *c = obt_parse_node_string(node);
818 config_menu_files = g_slist_append(config_menu_files,
819 obt_paths_expand_tilde(c));
825 static void parse_resistance(xmlNodePtr node, gpointer d)
829 node = node->children;
830 if ((n = obt_parse_find_node(node, "strength")))
831 config_resist_win = obt_parse_node_int(n);
832 if ((n = obt_parse_find_node(node, "screen_edge_strength")))
833 config_resist_edge = obt_parse_node_int(n);
839 const gchar *actname;
842 static void bind_default_keyboard(void)
845 ObDefKeyBind binds[] = {
846 { "A-Tab", "NextWindow" },
847 { "S-A-Tab", "PreviousWindow" },
851 for (it = binds; it->key; ++it) {
852 GList *l = g_list_append(NULL, g_strdup(it->key));
853 keyboard_bind(l, actions_parse_string(it->actname));
860 const gchar *context;
861 const ObMouseAction mact;
862 const gchar *actname;
865 static void bind_default_mouse(void)
868 ObDefMouseBind binds[] = {
869 { "Left", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
870 { "Middle", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
871 { "Right", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
872 { "Left", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
873 { "Middle", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
874 { "Right", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
875 { "Left", "Titlebar", OB_MOUSE_ACTION_PRESS, "Focus" },
876 { "Left", "Bottom", OB_MOUSE_ACTION_PRESS, "Focus" },
877 { "Left", "BLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
878 { "Left", "BRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
879 { "Left", "TLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
880 { "Left", "TRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
881 { "Left", "Close", OB_MOUSE_ACTION_PRESS, "Focus" },
882 { "Left", "Maximize", OB_MOUSE_ACTION_PRESS, "Focus" },
883 { "Left", "Iconify", OB_MOUSE_ACTION_PRESS, "Focus" },
884 { "Left", "Icon", OB_MOUSE_ACTION_PRESS, "Focus" },
885 { "Left", "AllDesktops", OB_MOUSE_ACTION_PRESS, "Focus" },
886 { "Left", "Shade", OB_MOUSE_ACTION_PRESS, "Focus" },
887 { "Left", "Client", OB_MOUSE_ACTION_CLICK, "Raise" },
888 { "Left", "Titlebar", OB_MOUSE_ACTION_CLICK, "Raise" },
889 { "Middle", "Titlebar", OB_MOUSE_ACTION_CLICK, "Lower" },
890 { "Left", "BLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
891 { "Left", "BRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
892 { "Left", "TLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
893 { "Left", "TRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
894 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Raise" },
895 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "Raise" },
896 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Raise" },
897 { "Left", "Icon", OB_MOUSE_ACTION_CLICK, "Raise" },
898 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "Raise" },
899 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "Raise" },
900 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Close" },
901 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "ToggleMaximize" },
902 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Iconify" },
903 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "ToggleOmnipresent" },
904 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "ToggleShade" },
905 { "Left", "TLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
906 { "Left", "TRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
907 { "Left", "BLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
908 { "Left", "BRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
909 { "Left", "Top", OB_MOUSE_ACTION_MOTION, "Resize" },
910 { "Left", "Bottom", OB_MOUSE_ACTION_MOTION, "Resize" },
911 { "Left", "Left", OB_MOUSE_ACTION_MOTION, "Resize" },
912 { "Left", "Right", OB_MOUSE_ACTION_MOTION, "Resize" },
913 { "Left", "Titlebar", OB_MOUSE_ACTION_MOTION, "Move" },
914 { "A-Left", "Frame", OB_MOUSE_ACTION_MOTION, "Move" },
915 { "A-Middle", "Frame", OB_MOUSE_ACTION_MOTION, "Resize" },
916 { NULL, NULL, 0, NULL }
919 for (it = binds; it->button; ++it)
920 mouse_bind(it->button, it->context, it->mact,
921 actions_parse_string(it->actname));
924 void config_startup(ObtParseInst *i)
926 config_focus_new = TRUE;
927 config_focus_follow = FALSE;
928 config_focus_delay = 0;
929 config_focus_raise = FALSE;
930 config_focus_last = TRUE;
931 config_focus_under_mouse = FALSE;
932 config_unfocus_leave = FALSE;
934 obt_parse_register(i, "focus", parse_focus, NULL);
936 config_place_policy = OB_PLACE_POLICY_SMART;
937 config_place_center = TRUE;
938 config_place_monitor = OB_PLACE_MONITOR_ANY;
940 config_primary_monitor_index = 1;
941 config_primary_monitor = OB_PLACE_MONITOR_ACTIVE;
943 obt_parse_register(i, "placement", parse_placement, NULL);
945 STRUT_PARTIAL_SET(config_margins, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
947 obt_parse_register(i, "margins", parse_margins, NULL);
951 config_animate_iconify = TRUE;
952 config_title_layout = g_strdup("NLIMC");
953 config_theme_keepborder = TRUE;
954 config_theme_window_list_icon_size = 36;
956 config_font_activewindow = NULL;
957 config_font_inactivewindow = NULL;
958 config_font_menuitem = NULL;
959 config_font_menutitle = NULL;
961 obt_parse_register(i, "theme", parse_theme, NULL);
963 config_desktops_num = 4;
964 config_screen_firstdesk = 1;
965 config_desktops_names = NULL;
966 config_desktop_popup_time = 875;
968 obt_parse_register(i, "desktops", parse_desktops, NULL);
970 config_resize_redraw = TRUE;
971 config_resize_popup_show = 1; /* nonpixel increments */
972 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
973 GRAVITY_COORD_SET(config_resize_popup_fixed.x, 0, FALSE, FALSE);
974 GRAVITY_COORD_SET(config_resize_popup_fixed.y, 0, FALSE, FALSE);
976 obt_parse_register(i, "resize", parse_resize, NULL);
978 config_dock_layer = OB_STACKING_LAYER_ABOVE;
979 config_dock_pos = OB_DIRECTION_NORTHEAST;
980 config_dock_floating = FALSE;
981 config_dock_nostrut = FALSE;
984 config_dock_orient = OB_ORIENTATION_VERT;
985 config_dock_hide = FALSE;
986 config_dock_hide_delay = 300;
987 config_dock_show_delay = 300;
988 config_dock_app_move_button = 2; /* middle */
989 config_dock_app_move_modifiers = 0;
991 obt_parse_register(i, "dock", parse_dock, NULL);
993 translate_key("C-g", &config_keyboard_reset_state,
994 &config_keyboard_reset_keycode);
996 bind_default_keyboard();
998 obt_parse_register(i, "keyboard", parse_keyboard, NULL);
1000 config_mouse_threshold = 8;
1001 config_mouse_dclicktime = 200;
1002 config_mouse_screenedgetime = 400;
1004 bind_default_mouse();
1006 obt_parse_register(i, "mouse", parse_mouse, NULL);
1008 config_resist_win = 10;
1009 config_resist_edge = 20;
1011 obt_parse_register(i, "resistance", parse_resistance, NULL);
1013 config_menu_hide_delay = 250;
1014 config_menu_middle = FALSE;
1015 config_submenu_show_delay = 0;
1016 config_menu_client_list_icons = TRUE;
1017 config_menu_manage_desktops = TRUE;
1018 config_menu_files = NULL;
1020 obt_parse_register(i, "menu", parse_menu, NULL);
1022 config_per_app_settings = NULL;
1024 obt_parse_register(i, "applications", parse_per_app_settings, NULL);
1027 void config_shutdown(void)
1031 g_free(config_theme);
1033 g_free(config_title_layout);
1035 RrFontClose(config_font_activewindow);
1036 RrFontClose(config_font_inactivewindow);
1037 RrFontClose(config_font_menuitem);
1038 RrFontClose(config_font_menutitle);
1039 RrFontClose(config_font_osd);
1041 for (it = config_desktops_names; it; it = g_slist_next(it))
1043 g_slist_free(config_desktops_names);
1045 for (it = config_menu_files; it; it = g_slist_next(it))
1047 g_slist_free(config_menu_files);
1049 for (it = config_per_app_settings; it; it = g_slist_next(it)) {
1050 ObAppSettings *itd = (ObAppSettings *)it->data;
1051 if (itd->name) g_pattern_spec_free(itd->name);
1052 if (itd->role) g_pattern_spec_free(itd->role);
1053 if (itd->class) g_pattern_spec_free(itd->class);
1056 g_slist_free(config_per_app_settings);