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"
30 #include "obt/display.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_unfocus_leave;
40 ObPlacePolicy config_place_policy;
41 gboolean config_place_center;
42 ObPlaceMonitor config_place_monitor;
44 guint config_primary_monitor_index;
45 ObPlaceMonitor config_primary_monitor;
47 StrutPartial config_margins;
50 gboolean config_theme_keepborder;
51 guint config_theme_window_list_icon_size;
55 gchar *config_title_layout;
57 gboolean config_animate_iconify;
59 RrFont *config_font_activewindow;
60 RrFont *config_font_inactivewindow;
61 RrFont *config_font_menuitem;
62 RrFont *config_font_menutitle;
63 RrFont *config_font_activeosd;
64 RrFont *config_font_inactiveosd;
66 guint config_desktops_num;
67 GSList *config_desktops_names;
68 guint config_screen_firstdesk;
69 guint config_desktop_popup_time;
71 gboolean config_resize_redraw;
72 gint config_resize_popup_show;
73 ObResizePopupPos config_resize_popup_pos;
74 GravityPoint config_resize_popup_fixed;
76 ObStackingLayer config_dock_layer;
77 gboolean config_dock_floating;
78 gboolean config_dock_nostrut;
79 ObDirection config_dock_pos;
82 ObOrientation config_dock_orient;
83 gboolean config_dock_hide;
84 guint config_dock_hide_delay;
85 guint config_dock_show_delay;
86 guint config_dock_app_move_button;
87 guint config_dock_app_move_modifiers;
89 guint config_keyboard_reset_keycode;
90 guint config_keyboard_reset_state;
92 gint config_mouse_threshold;
93 gint config_mouse_dclicktime;
94 gint config_mouse_screenedgetime;
95 gboolean config_mouse_screenedgewarp;
97 guint config_menu_hide_delay;
98 gboolean config_menu_middle;
99 guint config_submenu_show_delay;
100 guint config_submenu_hide_delay;
101 gboolean config_menu_manage_desktops;
102 gboolean config_menu_show_icons;
104 GSList *config_menu_files;
106 gint config_resist_win;
107 gint config_resist_edge;
109 GSList *config_per_app_settings;
111 ObAppSettings* config_create_app_settings(void)
113 ObAppSettings *settings = g_slice_new0(ObAppSettings);
115 settings->decor = -1;
116 settings->shade = -1;
117 settings->monitor = -1;
118 settings->focus = -1;
119 settings->desktop = 0;
120 settings->layer = -2;
121 settings->iconic = -1;
122 settings->skip_pager = -1;
123 settings->skip_taskbar = -1;
124 settings->fullscreen = -1;
125 settings->max_horz = -1;
126 settings->max_vert = -1;
130 #define copy_if(setting, default) \
131 if (src->setting != default) dst->setting = src->setting
132 void config_app_settings_copy_non_defaults(const ObAppSettings *src,
135 g_assert(src != NULL);
136 g_assert(dst != NULL);
138 copy_if(type, (ObClientType)-1);
141 copy_if(monitor, -1);
146 copy_if(skip_pager, -1);
147 copy_if(skip_taskbar, -1);
148 copy_if(fullscreen, -1);
149 copy_if(max_horz, -1);
150 copy_if(max_vert, -1);
152 if (src->pos_given) {
153 dst->pos_given = TRUE;
154 dst->pos_force = src->pos_force;
155 dst->position = src->position;
156 /* monitor is copied above */
160 void config_parse_relative_number(gchar *s, gint *num, gint *denom)
162 *num = strtol(s, &s, 10);
166 } else if (*s == '/') {
171 void config_parse_gravity_coord(xmlNodePtr node, GravityCoord *c)
173 gchar *s = obt_xml_node_string(node);
174 if (!g_ascii_strcasecmp(s, "center"))
180 if (s[0] == '-' || s[0] == '+')
182 config_parse_relative_number(ps, &c->pos, &c->denom);
189 <application name="aterm">
192 <application name="Rhythmbox">
199 .. there is a lot more settings available
204 /* Manages settings for individual applications.
205 Some notes: monitor is the screen number in a multi monitor
206 (Xinerama) setup (starting from 0) or mouse, meaning the
207 monitor the pointer is on. Default: mouse.
208 Layer can be three values, above (Always on top), below
209 (Always on bottom) and everything else (normal behaviour).
210 Positions can be an integer value or center, which will
211 center the window in the specified axis. Position is within
212 the monitor, so <position><x>center</x></position><monitor>2</monitor>
213 will center the window on the second monitor.
215 static void parse_per_app_settings(xmlNodePtr node, gpointer d)
217 xmlNodePtr app = obt_xml_find_node(node->children, "application");
218 gchar *name = NULL, *class = NULL, *role = NULL, *title = NULL,
220 gboolean name_set, class_set, type_set, role_set, title_set;
222 gboolean x_pos_given;
227 class_set = obt_xml_attr_string(app, "class", &class);
228 name_set = obt_xml_attr_string(app, "name", &name);
229 type_set = obt_xml_attr_string(app, "type", &type_str);
230 role_set = obt_xml_attr_string(app, "role", &role);
231 title_set = obt_xml_attr_string(app, "title", &title);
233 /* validate the type tho */
235 if (!g_ascii_strcasecmp(type_str, "normal"))
236 type = OB_CLIENT_TYPE_NORMAL;
237 else if (!g_ascii_strcasecmp(type_str, "dialog"))
238 type = OB_CLIENT_TYPE_DIALOG;
239 else if (!g_ascii_strcasecmp(type_str, "splash"))
240 type = OB_CLIENT_TYPE_SPLASH;
241 else if (!g_ascii_strcasecmp(type_str, "utility"))
242 type = OB_CLIENT_TYPE_UTILITY;
243 else if (!g_ascii_strcasecmp(type_str, "menu"))
244 type = OB_CLIENT_TYPE_MENU;
245 else if (!g_ascii_strcasecmp(type_str, "toolbar"))
246 type = OB_CLIENT_TYPE_TOOLBAR;
247 else if (!g_ascii_strcasecmp(type_str, "dock"))
248 type = OB_CLIENT_TYPE_DOCK;
249 else if (!g_ascii_strcasecmp(type_str, "desktop"))
250 type = OB_CLIENT_TYPE_DESKTOP;
252 type_set = FALSE; /* not valid! */
255 if (class_set || name_set || role_set || title_set || type_set) {
257 ObAppSettings *settings = config_create_app_settings();
260 settings->name = g_pattern_spec_new(name);
263 settings->class = g_pattern_spec_new(class);
266 settings->role = g_pattern_spec_new(role);
269 settings->title = g_pattern_spec_new(title);
272 settings->type = type;
274 if ((n = obt_xml_find_node(app->children, "decor")))
275 if (!obt_xml_node_contains(n, "default"))
276 settings->decor = obt_xml_node_bool(n);
278 if ((n = obt_xml_find_node(app->children, "shade")))
279 if (!obt_xml_node_contains(n, "default"))
280 settings->shade = obt_xml_node_bool(n);
282 if ((n = obt_xml_find_node(app->children, "position"))) {
283 if ((c = obt_xml_find_node(n->children, "x")))
284 if (!obt_xml_node_contains(c, "default")) {
285 config_parse_gravity_coord(c, &settings->position.x);
289 if (x_pos_given && (c = obt_xml_find_node(n->children, "y")))
290 if (!obt_xml_node_contains(c, "default")) {
291 config_parse_gravity_coord(c, &settings->position.y);
292 settings->pos_given = TRUE;
295 if (settings->pos_given &&
296 (c = obt_xml_find_node(n->children, "monitor")))
297 if (!obt_xml_node_contains(c, "default")) {
298 gchar *s = obt_xml_node_string(c);
299 if (!g_ascii_strcasecmp(s, "mouse"))
300 settings->monitor = 0;
302 settings->monitor = obt_xml_node_int(c);
306 obt_xml_attr_bool(n, "force", &settings->pos_force);
309 if ((n = obt_xml_find_node(app->children, "focus")))
310 if (!obt_xml_node_contains(n, "default"))
311 settings->focus = obt_xml_node_bool(n);
313 if ((n = obt_xml_find_node(app->children, "desktop"))) {
314 if (!obt_xml_node_contains(n, "default")) {
315 gchar *s = obt_xml_node_string(n);
316 if (!g_ascii_strcasecmp(s, "all"))
317 settings->desktop = DESKTOP_ALL;
319 gint i = obt_xml_node_int(n);
321 settings->desktop = i;
327 if ((n = obt_xml_find_node(app->children, "layer")))
328 if (!obt_xml_node_contains(n, "default")) {
329 gchar *s = obt_xml_node_string(n);
330 if (!g_ascii_strcasecmp(s, "above"))
332 else if (!g_ascii_strcasecmp(s, "below"))
333 settings->layer = -1;
339 if ((n = obt_xml_find_node(app->children, "iconic")))
340 if (!obt_xml_node_contains(n, "default"))
341 settings->iconic = obt_xml_node_bool(n);
343 if ((n = obt_xml_find_node(app->children, "skip_pager")))
344 if (!obt_xml_node_contains(n, "default"))
345 settings->skip_pager = obt_xml_node_bool(n);
347 if ((n = obt_xml_find_node(app->children, "skip_taskbar")))
348 if (!obt_xml_node_contains(n, "default"))
349 settings->skip_taskbar = obt_xml_node_bool(n);
351 if ((n = obt_xml_find_node(app->children, "fullscreen")))
352 if (!obt_xml_node_contains(n, "default"))
353 settings->fullscreen = obt_xml_node_bool(n);
355 if ((n = obt_xml_find_node(app->children, "maximized")))
356 if (!obt_xml_node_contains(n, "default")) {
357 gchar *s = obt_xml_node_string(n);
358 if (!g_ascii_strcasecmp(s, "horizontal")) {
359 settings->max_horz = TRUE;
360 settings->max_vert = FALSE;
361 } else if (!g_ascii_strcasecmp(s, "vertical")) {
362 settings->max_horz = FALSE;
363 settings->max_vert = TRUE;
365 settings->max_horz = settings->max_vert =
366 obt_xml_node_bool(n);
370 config_per_app_settings = g_slist_append(config_per_app_settings,
371 (gpointer) settings);
377 name = class = role = title = NULL;
380 app = obt_xml_find_node(app->next, "application");
387 <action name="ChangeDesktop">
394 static void parse_key(xmlNodePtr node, GList *keylist)
398 gboolean is_chroot = FALSE;
400 if (!obt_xml_attr_string(node, "key", &key))
403 obt_xml_attr_bool(node, "chroot", &is_chroot);
405 keylist = g_list_append(keylist, key);
407 if ((n = obt_xml_find_node(node->children, "keybind"))) {
409 parse_key(n, keylist);
410 n = obt_xml_find_node(n->next, "keybind");
413 else if ((n = obt_xml_find_node(node->children, "action"))) {
415 ObActionsAct *action;
417 action = actions_parse(n);
419 keyboard_bind(keylist, action);
420 n = obt_xml_find_node(n->next, "action");
425 keyboard_chroot(keylist);
428 keylist = g_list_delete_link(keylist, g_list_last(keylist));
431 static void parse_keyboard(xmlNodePtr node, gpointer d)
436 keyboard_unbind_all();
438 if ((n = obt_xml_find_node(node->children, "chainQuitKey"))) {
439 key = obt_xml_node_string(n);
440 translate_key(key, &config_keyboard_reset_state,
441 &config_keyboard_reset_keycode);
445 if ((n = obt_xml_find_node(node->children, "keybind")))
448 n = obt_xml_find_node(n->next, "keybind");
454 <context name="Titlebar">
455 <mousebind button="Left" action="Press">
456 <action name="Raise"></action>
462 static void parse_mouse(xmlNodePtr node, gpointer d)
464 xmlNodePtr n, nbut, nact;
471 node = node->children;
473 if ((n = obt_xml_find_node(node, "dragThreshold")))
474 config_mouse_threshold = obt_xml_node_int(n);
475 if ((n = obt_xml_find_node(node, "doubleClickTime")))
476 config_mouse_dclicktime = obt_xml_node_int(n);
477 if ((n = obt_xml_find_node(node, "screenEdgeWarpTime"))) {
478 config_mouse_screenedgetime = obt_xml_node_int(n);
479 /* minimum value of 25 for this property, when it is 1 and you hit the
480 edge it basically never stops */
481 if (config_mouse_screenedgetime && config_mouse_screenedgetime < 25)
482 config_mouse_screenedgetime = 25;
484 if ((n = obt_xml_find_node(node, "screenEdgeWarpMouse")))
485 config_mouse_screenedgewarp = obt_xml_node_bool(n);
487 n = obt_xml_find_node(node, "context");
492 if (!obt_xml_attr_string(n, "name", &cxstr))
495 modcxstr = g_strdup(cxstr); /* make a copy to mutilate */
496 while (frame_next_context_from_string(modcxstr, &cx)) {
498 gchar *s = strchr(modcxstr, ' ');
501 g_message(_("Invalid context \"%s\" in mouse binding"),
508 nbut = obt_xml_find_node(n->children, "mousebind");
510 if (!obt_xml_attr_string(nbut, "button", &buttonstr))
512 if (obt_xml_attr_contains(nbut, "action", "press"))
513 mact = OB_MOUSE_ACTION_PRESS;
514 else if (obt_xml_attr_contains(nbut, "action", "release"))
515 mact = OB_MOUSE_ACTION_RELEASE;
516 else if (obt_xml_attr_contains(nbut, "action", "click"))
517 mact = OB_MOUSE_ACTION_CLICK;
518 else if (obt_xml_attr_contains(nbut, "action","doubleclick"))
519 mact = OB_MOUSE_ACTION_DOUBLE_CLICK;
520 else if (obt_xml_attr_contains(nbut, "action", "drag"))
521 mact = OB_MOUSE_ACTION_MOTION;
525 nact = obt_xml_find_node(nbut->children, "action");
527 ObActionsAct *action;
529 if ((action = actions_parse(nact)))
530 mouse_bind(buttonstr, cx, mact, action);
531 nact = obt_xml_find_node(nact->next, "action");
535 nbut = obt_xml_find_node(nbut->next, "mousebind");
541 n = obt_xml_find_node(n->next, "context");
545 static void parse_focus(xmlNodePtr node, gpointer d)
549 node = node->children;
551 if ((n = obt_xml_find_node(node, "focusNew")))
552 config_focus_new = obt_xml_node_bool(n);
553 if ((n = obt_xml_find_node(node, "followMouse")))
554 config_focus_follow = obt_xml_node_bool(n);
555 if ((n = obt_xml_find_node(node, "focusDelay")))
556 config_focus_delay = obt_xml_node_int(n);
557 if ((n = obt_xml_find_node(node, "raiseOnFocus")))
558 config_focus_raise = obt_xml_node_bool(n);
559 if ((n = obt_xml_find_node(node, "focusLast")))
560 config_focus_last = obt_xml_node_bool(n);
561 if ((n = obt_xml_find_node(node, "underMouse")))
562 config_focus_under_mouse = obt_xml_node_bool(n);
563 if ((n = obt_xml_find_node(node, "unfocusOnLeave")))
564 config_unfocus_leave = obt_xml_node_bool(n);
567 static void parse_placement(xmlNodePtr node, gpointer d)
571 node = node->children;
573 if ((n = obt_xml_find_node(node, "policy")))
574 if (obt_xml_node_contains(n, "UnderMouse"))
575 config_place_policy = OB_PLACE_POLICY_MOUSE;
576 if ((n = obt_xml_find_node(node, "center")))
577 config_place_center = obt_xml_node_bool(n);
578 if ((n = obt_xml_find_node(node, "monitor"))) {
579 if (obt_xml_node_contains(n, "active"))
580 config_place_monitor = OB_PLACE_MONITOR_ACTIVE;
581 else if (obt_xml_node_contains(n, "mouse"))
582 config_place_monitor = OB_PLACE_MONITOR_MOUSE;
584 if ((n = obt_xml_find_node(node, "primaryMonitor"))) {
585 config_primary_monitor_index = obt_xml_node_int(n);
586 if (!config_primary_monitor_index) {
587 if (obt_xml_node_contains(n, "mouse"))
588 config_primary_monitor = OB_PLACE_MONITOR_MOUSE;
593 static void parse_margins(xmlNodePtr node, gpointer d)
597 node = node->children;
599 if ((n = obt_xml_find_node(node, "top")))
600 config_margins.top = MAX(0, obt_xml_node_int(n));
601 if ((n = obt_xml_find_node(node, "left")))
602 config_margins.left = MAX(0, obt_xml_node_int(n));
603 if ((n = obt_xml_find_node(node, "right")))
604 config_margins.right = MAX(0, obt_xml_node_int(n));
605 if ((n = obt_xml_find_node(node, "bottom")))
606 config_margins.bottom = MAX(0, obt_xml_node_int(n));
609 static void parse_theme(xmlNodePtr node, gpointer d)
613 node = node->children;
615 if ((n = obt_xml_find_node(node, "name"))) {
618 g_free(config_theme);
619 c = obt_xml_node_string(n);
620 config_theme = obt_paths_expand_tilde(c);
623 if ((n = obt_xml_find_node(node, "titleLayout"))) {
626 g_free(config_title_layout);
627 config_title_layout = obt_xml_node_string(n);
629 /* replace duplicates with spaces */
630 for (c = config_title_layout; *c != '\0'; ++c)
631 for (d = c+1; *d != '\0'; ++d)
632 if (*c == *d) *d = ' ';
634 if ((n = obt_xml_find_node(node, "keepBorder")))
635 config_theme_keepborder = obt_xml_node_bool(n);
636 if ((n = obt_xml_find_node(node, "animateIconify")))
637 config_animate_iconify = obt_xml_node_bool(n);
638 if ((n = obt_xml_find_node(node, "windowListIconSize"))) {
639 config_theme_window_list_icon_size = obt_xml_node_int(n);
640 if (config_theme_window_list_icon_size < 16)
641 config_theme_window_list_icon_size = 16;
642 else if (config_theme_window_list_icon_size > 96)
643 config_theme_window_list_icon_size = 96;
646 n = obt_xml_find_node(node, "font");
650 gchar *name = g_strdup(RrDefaultFontFamily);
651 gint size = RrDefaultFontSize;
652 RrFontWeight weight = RrDefaultFontWeight;
653 RrFontSlant slant = RrDefaultFontSlant;
655 if (obt_xml_attr_contains(n, "place", "ActiveWindow"))
656 font = &config_font_activewindow;
657 else if (obt_xml_attr_contains(n, "place", "InactiveWindow"))
658 font = &config_font_inactivewindow;
659 else if (obt_xml_attr_contains(n, "place", "MenuHeader"))
660 font = &config_font_menutitle;
661 else if (obt_xml_attr_contains(n, "place", "MenuItem"))
662 font = &config_font_menuitem;
663 else if (obt_xml_attr_contains(n, "place", "ActiveOnScreenDisplay"))
664 font = &config_font_activeosd;
665 else if (obt_xml_attr_contains(n, "place", "OnScreenDisplay"))
666 font = &config_font_activeosd;
667 else if (obt_xml_attr_contains(n, "place","InactiveOnScreenDisplay"))
668 font = &config_font_inactiveosd;
672 if ((fnode = obt_xml_find_node(n->children, "name"))) {
674 name = obt_xml_node_string(fnode);
676 if ((fnode = obt_xml_find_node(n->children, "size"))) {
677 int s = obt_xml_node_int(fnode);
680 if ((fnode = obt_xml_find_node(n->children, "weight"))) {
681 gchar *w = obt_xml_node_string(fnode);
682 if (!g_ascii_strcasecmp(w, "Bold"))
683 weight = RR_FONTWEIGHT_BOLD;
686 if ((fnode = obt_xml_find_node(n->children, "slant"))) {
687 gchar *s = obt_xml_node_string(fnode);
688 if (!g_ascii_strcasecmp(s, "Italic"))
689 slant = RR_FONTSLANT_ITALIC;
690 if (!g_ascii_strcasecmp(s, "Oblique"))
691 slant = RR_FONTSLANT_OBLIQUE;
695 *font = RrFontOpen(ob_rr_inst, name, size, weight, slant);
698 n = obt_xml_find_node(n->next, "font");
702 static void parse_desktops(xmlNodePtr node, gpointer d)
706 node = node->children;
708 if ((n = obt_xml_find_node(node, "number"))) {
709 gint d = obt_xml_node_int(n);
711 config_desktops_num = (unsigned) d;
713 if ((n = obt_xml_find_node(node, "firstdesk"))) {
714 gint d = obt_xml_node_int(n);
716 config_screen_firstdesk = (unsigned) d;
718 if ((n = obt_xml_find_node(node, "names"))) {
722 for (it = config_desktops_names; it; it = it->next)
724 g_slist_free(config_desktops_names);
725 config_desktops_names = NULL;
727 nname = obt_xml_find_node(n->children, "name");
729 config_desktops_names =
730 g_slist_append(config_desktops_names,
731 obt_xml_node_string(nname));
732 nname = obt_xml_find_node(nname->next, "name");
735 if ((n = obt_xml_find_node(node, "popupTime")))
736 config_desktop_popup_time = obt_xml_node_int(n);
739 static void parse_resize(xmlNodePtr node, gpointer d)
743 node = node->children;
745 if ((n = obt_xml_find_node(node, "drawContents")))
746 config_resize_redraw = obt_xml_node_bool(n);
747 if ((n = obt_xml_find_node(node, "popupShow"))) {
748 config_resize_popup_show = obt_xml_node_int(n);
749 if (obt_xml_node_contains(n, "Always"))
750 config_resize_popup_show = 2;
751 else if (obt_xml_node_contains(n, "Never"))
752 config_resize_popup_show = 0;
753 else if (obt_xml_node_contains(n, "Nonpixel"))
754 config_resize_popup_show = 1;
756 if ((n = obt_xml_find_node(node, "popupPosition"))) {
757 if (obt_xml_node_contains(n, "Top"))
758 config_resize_popup_pos = OB_RESIZE_POS_TOP;
759 else if (obt_xml_node_contains(n, "Center"))
760 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
761 else if (obt_xml_node_contains(n, "Fixed")) {
762 config_resize_popup_pos = OB_RESIZE_POS_FIXED;
764 if ((n = obt_xml_find_node(node, "popupFixedPosition"))) {
767 if ((n2 = obt_xml_find_node(n->children, "x")))
768 config_parse_gravity_coord(n2,
769 &config_resize_popup_fixed.x);
770 if ((n2 = obt_xml_find_node(n->children, "y")))
771 config_parse_gravity_coord(n2,
772 &config_resize_popup_fixed.y);
774 config_resize_popup_fixed.x.pos =
775 MAX(config_resize_popup_fixed.x.pos, 0);
776 config_resize_popup_fixed.y.pos =
777 MAX(config_resize_popup_fixed.y.pos, 0);
783 static void parse_dock(xmlNodePtr node, gpointer d)
787 node = node->children;
789 if ((n = obt_xml_find_node(node, "position"))) {
790 if (obt_xml_node_contains(n, "TopLeft"))
791 config_dock_floating = FALSE,
792 config_dock_pos = OB_DIRECTION_NORTHWEST;
793 else if (obt_xml_node_contains(n, "Top"))
794 config_dock_floating = FALSE,
795 config_dock_pos = OB_DIRECTION_NORTH;
796 else if (obt_xml_node_contains(n, "TopRight"))
797 config_dock_floating = FALSE,
798 config_dock_pos = OB_DIRECTION_NORTHEAST;
799 else if (obt_xml_node_contains(n, "Right"))
800 config_dock_floating = FALSE,
801 config_dock_pos = OB_DIRECTION_EAST;
802 else if (obt_xml_node_contains(n, "BottomRight"))
803 config_dock_floating = FALSE,
804 config_dock_pos = OB_DIRECTION_SOUTHEAST;
805 else if (obt_xml_node_contains(n, "Bottom"))
806 config_dock_floating = FALSE,
807 config_dock_pos = OB_DIRECTION_SOUTH;
808 else if (obt_xml_node_contains(n, "BottomLeft"))
809 config_dock_floating = FALSE,
810 config_dock_pos = OB_DIRECTION_SOUTHWEST;
811 else if (obt_xml_node_contains(n, "Left"))
812 config_dock_floating = FALSE,
813 config_dock_pos = OB_DIRECTION_WEST;
814 else if (obt_xml_node_contains(n, "Floating"))
815 config_dock_floating = TRUE;
817 if (config_dock_floating) {
818 if ((n = obt_xml_find_node(node, "floatingX")))
819 config_dock_x = obt_xml_node_int(n);
820 if ((n = obt_xml_find_node(node, "floatingY")))
821 config_dock_y = obt_xml_node_int(n);
823 if ((n = obt_xml_find_node(node, "noStrut")))
824 config_dock_nostrut = obt_xml_node_bool(n);
826 if ((n = obt_xml_find_node(node, "stacking"))) {
827 if (obt_xml_node_contains(n, "normal"))
828 config_dock_layer = OB_STACKING_LAYER_NORMAL;
829 else if (obt_xml_node_contains(n, "below"))
830 config_dock_layer = OB_STACKING_LAYER_BELOW;
831 else if (obt_xml_node_contains(n, "above"))
832 config_dock_layer = OB_STACKING_LAYER_ABOVE;
834 if ((n = obt_xml_find_node(node, "direction"))) {
835 if (obt_xml_node_contains(n, "horizontal"))
836 config_dock_orient = OB_ORIENTATION_HORZ;
837 else if (obt_xml_node_contains(n, "vertical"))
838 config_dock_orient = OB_ORIENTATION_VERT;
840 if ((n = obt_xml_find_node(node, "autoHide")))
841 config_dock_hide = obt_xml_node_bool(n);
842 if ((n = obt_xml_find_node(node, "hideDelay")))
843 config_dock_hide_delay = obt_xml_node_int(n);
844 if ((n = obt_xml_find_node(node, "showDelay")))
845 config_dock_show_delay = obt_xml_node_int(n);
846 if ((n = obt_xml_find_node(node, "moveButton"))) {
847 gchar *str = obt_xml_node_string(n);
849 if (translate_button(str, &s, &b)) {
850 config_dock_app_move_button = b;
851 config_dock_app_move_modifiers = s;
853 g_message(_("Invalid button \"%s\" specified in config file"), str);
859 static void parse_menu(xmlNodePtr node, gpointer d)
862 node = node->children;
864 if ((n = obt_xml_find_node(node, "hideDelay")))
865 config_menu_hide_delay = obt_xml_node_int(n);
866 if ((n = obt_xml_find_node(node, "middle")))
867 config_menu_middle = obt_xml_node_bool(n);
868 if ((n = obt_xml_find_node(node, "submenuShowDelay")))
869 config_submenu_show_delay = obt_xml_node_int(n);
870 if ((n = obt_xml_find_node(node, "submenuHideDelay")))
871 config_submenu_hide_delay = obt_xml_node_int(n);
872 if ((n = obt_xml_find_node(node, "manageDesktops")))
873 config_menu_manage_desktops = obt_xml_node_bool(n);
874 if ((n = obt_xml_find_node(node, "showIcons"))) {
875 config_menu_show_icons = obt_xml_node_bool(n);
877 if (config_menu_show_icons)
878 g_message(_("Openbox was compiled without Imlib2 image loading support. Icons in menus will not be loaded."));
882 while ((node = obt_xml_find_node(node, "file"))) {
883 gchar *c = obt_xml_node_string(node);
884 config_menu_files = g_slist_append(config_menu_files,
885 obt_paths_expand_tilde(c));
891 static void parse_resistance(xmlNodePtr node, gpointer d)
895 node = node->children;
896 if ((n = obt_xml_find_node(node, "strength")))
897 config_resist_win = obt_xml_node_int(n);
898 if ((n = obt_xml_find_node(node, "screen_edge_strength")))
899 config_resist_edge = obt_xml_node_int(n);
905 const gchar *actname;
908 static void bind_default_keyboard(void)
911 ObDefKeyBind binds[] = {
912 { "A-Tab", "NextWindow" },
913 { "S-A-Tab", "PreviousWindow" },
917 for (it = binds; it->key; ++it) {
918 GList *l = g_list_append(NULL, g_strdup(it->key));
919 keyboard_bind(l, actions_parse_string(it->actname));
926 const gchar *context;
927 const ObMouseAction mact;
928 const gchar *actname;
931 static void bind_default_mouse(void)
934 ObDefMouseBind binds[] = {
935 { "Left", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
936 { "Middle", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
937 { "Right", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
938 { "Left", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
939 { "Middle", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
940 { "Right", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
941 { "Left", "Titlebar", OB_MOUSE_ACTION_PRESS, "Focus" },
942 { "Left", "Bottom", OB_MOUSE_ACTION_PRESS, "Focus" },
943 { "Left", "BLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
944 { "Left", "BRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
945 { "Left", "TLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
946 { "Left", "TRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
947 { "Left", "Close", OB_MOUSE_ACTION_PRESS, "Focus" },
948 { "Left", "Maximize", OB_MOUSE_ACTION_PRESS, "Focus" },
949 { "Left", "Iconify", OB_MOUSE_ACTION_PRESS, "Focus" },
950 { "Left", "Icon", OB_MOUSE_ACTION_PRESS, "Focus" },
951 { "Left", "AllDesktops", OB_MOUSE_ACTION_PRESS, "Focus" },
952 { "Left", "Shade", OB_MOUSE_ACTION_PRESS, "Focus" },
953 { "Left", "Client", OB_MOUSE_ACTION_CLICK, "Raise" },
954 { "Left", "Titlebar", OB_MOUSE_ACTION_CLICK, "Raise" },
955 { "Middle", "Titlebar", OB_MOUSE_ACTION_CLICK, "Lower" },
956 { "Left", "BLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
957 { "Left", "BRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
958 { "Left", "TLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
959 { "Left", "TRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
960 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Raise" },
961 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "Raise" },
962 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Raise" },
963 { "Left", "Icon", OB_MOUSE_ACTION_CLICK, "Raise" },
964 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "Raise" },
965 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "Raise" },
966 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Close" },
967 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "ToggleMaximize" },
968 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Iconify" },
969 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "ToggleOmnipresent" },
970 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "ToggleShade" },
971 { "Left", "TLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
972 { "Left", "TRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
973 { "Left", "BLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
974 { "Left", "BRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
975 { "Left", "Top", OB_MOUSE_ACTION_MOTION, "Resize" },
976 { "Left", "Bottom", OB_MOUSE_ACTION_MOTION, "Resize" },
977 { "Left", "Left", OB_MOUSE_ACTION_MOTION, "Resize" },
978 { "Left", "Right", OB_MOUSE_ACTION_MOTION, "Resize" },
979 { "Left", "Titlebar", OB_MOUSE_ACTION_MOTION, "Move" },
980 { "A-Left", "Frame", OB_MOUSE_ACTION_MOTION, "Move" },
981 { "A-Middle", "Frame", OB_MOUSE_ACTION_MOTION, "Resize" },
982 { NULL, NULL, 0, NULL }
985 for (it = binds; it->button; ++it)
986 mouse_bind(it->button, frame_context_from_string(it->context),
987 it->mact, actions_parse_string(it->actname));
990 void config_startup(ObtXmlInst *i)
992 config_focus_new = TRUE;
993 config_focus_follow = FALSE;
994 config_focus_delay = 0;
995 config_focus_raise = FALSE;
996 config_focus_last = TRUE;
997 config_focus_under_mouse = FALSE;
998 config_unfocus_leave = FALSE;
1000 obt_xml_register(i, "focus", parse_focus, NULL);
1002 config_place_policy = OB_PLACE_POLICY_SMART;
1003 config_place_center = TRUE;
1004 config_place_monitor = OB_PLACE_MONITOR_ANY;
1006 config_primary_monitor_index = 1;
1007 config_primary_monitor = OB_PLACE_MONITOR_ACTIVE;
1009 obt_xml_register(i, "placement", parse_placement, NULL);
1011 STRUT_PARTIAL_SET(config_margins, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1013 obt_xml_register(i, "margins", parse_margins, NULL);
1015 config_theme = NULL;
1019 config_animate_iconify = TRUE;
1020 config_title_layout = g_strdup("NLIMC");
1021 config_theme_keepborder = TRUE;
1022 config_theme_window_list_icon_size = 36;
1024 config_font_activewindow = NULL;
1025 config_font_inactivewindow = NULL;
1026 config_font_menuitem = NULL;
1027 config_font_menutitle = NULL;
1028 config_font_activeosd = NULL;
1029 config_font_inactiveosd = NULL;
1031 obt_xml_register(i, "theme", parse_theme, NULL);
1033 config_desktops_num = 4;
1034 config_screen_firstdesk = 1;
1035 config_desktops_names = NULL;
1036 config_desktop_popup_time = 875;
1038 obt_xml_register(i, "desktops", parse_desktops, NULL);
1040 config_resize_redraw = TRUE;
1041 config_resize_popup_show = 1; /* nonpixel increments */
1042 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
1043 GRAVITY_COORD_SET(config_resize_popup_fixed.x, 0, FALSE, FALSE);
1044 GRAVITY_COORD_SET(config_resize_popup_fixed.y, 0, FALSE, FALSE);
1046 obt_xml_register(i, "resize", parse_resize, NULL);
1048 config_dock_layer = OB_STACKING_LAYER_ABOVE;
1049 config_dock_pos = OB_DIRECTION_NORTHEAST;
1050 config_dock_floating = FALSE;
1051 config_dock_nostrut = FALSE;
1054 config_dock_orient = OB_ORIENTATION_VERT;
1055 config_dock_hide = FALSE;
1056 config_dock_hide_delay = 300;
1057 config_dock_show_delay = 300;
1058 config_dock_app_move_button = 2; /* middle */
1059 config_dock_app_move_modifiers = 0;
1061 obt_xml_register(i, "dock", parse_dock, NULL);
1063 translate_key("C-g", &config_keyboard_reset_state,
1064 &config_keyboard_reset_keycode);
1066 bind_default_keyboard();
1068 obt_xml_register(i, "keyboard", parse_keyboard, NULL);
1070 config_mouse_threshold = 8;
1071 config_mouse_dclicktime = 200;
1072 config_mouse_screenedgetime = 400;
1073 config_mouse_screenedgewarp = FALSE;
1075 bind_default_mouse();
1077 obt_xml_register(i, "mouse", parse_mouse, NULL);
1079 config_resist_win = 10;
1080 config_resist_edge = 20;
1082 obt_xml_register(i, "resistance", parse_resistance, NULL);
1084 config_menu_hide_delay = 250;
1085 config_menu_middle = FALSE;
1086 config_submenu_show_delay = 100;
1087 config_submenu_hide_delay = 400;
1088 config_menu_manage_desktops = TRUE;
1089 config_menu_files = NULL;
1090 config_menu_show_icons = TRUE;
1092 obt_xml_register(i, "menu", parse_menu, NULL);
1094 config_per_app_settings = NULL;
1096 obt_xml_register(i, "applications", parse_per_app_settings, NULL);
1099 void config_shutdown(void)
1103 g_free(config_theme);
1105 g_free(config_title_layout);
1107 RrFontClose(config_font_activewindow);
1108 RrFontClose(config_font_inactivewindow);
1109 RrFontClose(config_font_menuitem);
1110 RrFontClose(config_font_menutitle);
1111 RrFontClose(config_font_activeosd);
1112 RrFontClose(config_font_inactiveosd);
1114 for (it = config_desktops_names; it; it = g_slist_next(it))
1116 g_slist_free(config_desktops_names);
1118 for (it = config_menu_files; it; it = g_slist_next(it))
1120 g_slist_free(config_menu_files);
1122 for (it = config_per_app_settings; it; it = g_slist_next(it)) {
1123 ObAppSettings *itd = (ObAppSettings *)it->data;
1124 if (itd->name) g_pattern_spec_free(itd->name);
1125 if (itd->role) g_pattern_spec_free(itd->role);
1126 if (itd->title) g_pattern_spec_free(itd->title);
1127 if (itd->class) g_pattern_spec_free(itd->class);
1128 g_slice_free(ObAppSettings, it->data);
1130 g_slist_free(config_per_app_settings);