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.
21 #include "config_value.h"
25 #include "action_list.h"
26 #include "action_parser.h"
27 #include "translate.h"
32 #include "obt/paths.h"
34 gboolean config_focus_new;
35 gboolean config_focus_follow;
36 guint config_focus_delay;
37 gboolean config_focus_raise;
38 gboolean config_focus_last;
39 gboolean config_focus_under_mouse;
40 gboolean config_unfocus_leave;
42 ObPlacePolicy config_place_policy;
43 gboolean config_place_center;
44 ObPlaceMonitor config_place_monitor;
46 guint config_primary_monitor_index;
47 ObPlaceMonitor config_primary_monitor;
49 StrutPartial config_margins;
52 gboolean config_theme_keepborder;
53 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 */
162 <application name="aterm">
165 <application name="Rhythmbox">
172 .. there is a lot more settings available
177 /* Manages settings for individual applications.
178 Some notes: monitor is the screen number in a multi monitor
179 (Xinerama) setup (starting from 0) or mouse, meaning the
180 monitor the pointer is on. Default: mouse.
181 Layer can be three values, above (Always on top), below
182 (Always on bottom) and everything else (normal behaviour).
183 Positions can be an integer value or center, which will
184 center the window in the specified axis. Position is within
185 the monitor, so <position><x>center</x></position><monitor>2</monitor>
186 will center the window on the second monitor.
188 static void parse_per_app_settings(xmlNodePtr node, gpointer d)
190 xmlNodePtr app = obt_xml_find_sibling(node->children, "application");
191 gchar *name = NULL, *class = NULL, *role = NULL, *title = NULL,
193 gboolean name_set, class_set, type_set, role_set, title_set;
195 gboolean x_pos_given;
200 class_set = obt_xml_attr_string(app, "class", &class);
201 name_set = obt_xml_attr_string(app, "name", &name);
202 type_set = obt_xml_attr_string(app, "type", &type_str);
203 role_set = obt_xml_attr_string(app, "role", &role);
204 title_set = obt_xml_attr_string(app, "title", &title);
206 /* validate the type tho */
208 if (!g_ascii_strcasecmp(type_str, "normal"))
209 type = OB_CLIENT_TYPE_NORMAL;
210 else if (!g_ascii_strcasecmp(type_str, "dialog"))
211 type = OB_CLIENT_TYPE_DIALOG;
212 else if (!g_ascii_strcasecmp(type_str, "splash"))
213 type = OB_CLIENT_TYPE_SPLASH;
214 else if (!g_ascii_strcasecmp(type_str, "utility"))
215 type = OB_CLIENT_TYPE_UTILITY;
216 else if (!g_ascii_strcasecmp(type_str, "menu"))
217 type = OB_CLIENT_TYPE_MENU;
218 else if (!g_ascii_strcasecmp(type_str, "toolbar"))
219 type = OB_CLIENT_TYPE_TOOLBAR;
220 else if (!g_ascii_strcasecmp(type_str, "dock"))
221 type = OB_CLIENT_TYPE_DOCK;
222 else if (!g_ascii_strcasecmp(type_str, "desktop"))
223 type = OB_CLIENT_TYPE_DESKTOP;
225 type_set = FALSE; /* not valid! */
228 if (class_set || name_set || role_set || title_set || type_set) {
230 ObAppSettings *settings = config_create_app_settings();
233 settings->name = g_pattern_spec_new(name);
236 settings->class = g_pattern_spec_new(class);
239 settings->role = g_pattern_spec_new(role);
242 settings->title = g_pattern_spec_new(title);
245 settings->type = type;
247 if ((n = obt_xml_find_sibling(app->children, "decor")))
248 if (!obt_xml_node_contains(n, "default"))
249 settings->decor = obt_xml_node_bool(n);
251 if ((n = obt_xml_find_sibling(app->children, "shade")))
252 if (!obt_xml_node_contains(n, "default"))
253 settings->shade = obt_xml_node_bool(n);
255 if ((n = obt_xml_find_sibling(app->children, "position"))) {
256 if ((c = obt_xml_find_sibling(n->children, "x")))
257 if (!obt_xml_node_contains(c, "default")) {
258 ObConfigValue *v = config_value_new_string(
259 obt_xml_node_string(node));
260 config_value_gravity_coord(v, &settings->position.x);
261 config_value_unref(v);
265 if (x_pos_given && (c = obt_xml_find_sibling(n->children, "y")))
266 if (!obt_xml_node_contains(c, "default")) {
267 ObConfigValue *v = config_value_new_string(
268 obt_xml_node_string(node));
269 config_value_gravity_coord(v, &settings->position.y);
270 config_value_unref(v);
271 settings->pos_given = TRUE;
274 if (settings->pos_given &&
275 (c = obt_xml_find_sibling(n->children, "monitor")))
276 if (!obt_xml_node_contains(c, "default")) {
277 gchar *s = obt_xml_node_string(c);
278 if (!g_ascii_strcasecmp(s, "mouse"))
279 settings->monitor = 0;
281 settings->monitor = obt_xml_node_int(c);
285 obt_xml_attr_bool(n, "force", &settings->pos_force);
288 if ((n = obt_xml_find_sibling(app->children, "focus")))
289 if (!obt_xml_node_contains(n, "default"))
290 settings->focus = obt_xml_node_bool(n);
292 if ((n = obt_xml_find_sibling(app->children, "desktop"))) {
293 if (!obt_xml_node_contains(n, "default")) {
294 gchar *s = obt_xml_node_string(n);
295 if (!g_ascii_strcasecmp(s, "all"))
296 settings->desktop = DESKTOP_ALL;
298 gint i = obt_xml_node_int(n);
300 settings->desktop = i;
306 if ((n = obt_xml_find_sibling(app->children, "layer")))
307 if (!obt_xml_node_contains(n, "default")) {
308 gchar *s = obt_xml_node_string(n);
309 if (!g_ascii_strcasecmp(s, "above"))
311 else if (!g_ascii_strcasecmp(s, "below"))
312 settings->layer = -1;
318 if ((n = obt_xml_find_sibling(app->children, "iconic")))
319 if (!obt_xml_node_contains(n, "default"))
320 settings->iconic = obt_xml_node_bool(n);
322 if ((n = obt_xml_find_sibling(app->children, "skip_pager")))
323 if (!obt_xml_node_contains(n, "default"))
324 settings->skip_pager = obt_xml_node_bool(n);
326 if ((n = obt_xml_find_sibling(app->children, "skip_taskbar")))
327 if (!obt_xml_node_contains(n, "default"))
328 settings->skip_taskbar = obt_xml_node_bool(n);
330 if ((n = obt_xml_find_sibling(app->children, "fullscreen")))
331 if (!obt_xml_node_contains(n, "default"))
332 settings->fullscreen = obt_xml_node_bool(n);
334 if ((n = obt_xml_find_sibling(app->children, "maximized")))
335 if (!obt_xml_node_contains(n, "default")) {
336 gchar *s = obt_xml_node_string(n);
337 if (!g_ascii_strcasecmp(s, "horizontal")) {
338 settings->max_horz = TRUE;
339 settings->max_vert = FALSE;
340 } else if (!g_ascii_strcasecmp(s, "vertical")) {
341 settings->max_horz = FALSE;
342 settings->max_vert = TRUE;
344 settings->max_horz = settings->max_vert =
345 obt_xml_node_bool(n);
349 config_per_app_settings = g_slist_append(config_per_app_settings,
350 (gpointer) settings);
356 name = class = role = title = type_str = NULL;
359 app = obt_xml_find_sibling(app->next, "application");
366 <action name="ChangeDesktop">
373 static void parse_key(xmlNodePtr node, GList *keylist)
375 gchar *keystring, **keys, **key;
377 gboolean is_chroot = FALSE;
379 if (!obt_xml_attr_string(node, "key", &keystring))
382 obt_xml_attr_bool(node, "chroot", &is_chroot);
384 keys = g_strsplit(keystring, " ", 0);
385 for (key = keys; *key; ++key) {
386 keylist = g_list_append(keylist, *key);
388 if ((n = obt_xml_find_sibling(node->children, "keybind"))) {
390 parse_key(n, keylist);
391 n = obt_xml_find_sibling(n->next, "keybind");
394 else if ((n = obt_xml_find_sibling(node->children, "action"))) {
397 ObActionList *actions;
400 c = xmlNodeGetContent(node);
401 p = action_parser_new();
402 actions = action_parser_read_string(p, (gchar*)c);
404 action_parser_unref(p);
407 keyboard_bind(keylist, actions);
409 action_list_unref(actions);
410 n = obt_xml_find_sibling(n->next, "action");
416 keyboard_chroot(keylist);
417 keylist = g_list_delete_link(keylist, g_list_last(keylist));
424 static void parse_keyboard(xmlNodePtr node, gpointer d)
429 keyboard_unbind_all();
431 if ((n = obt_xml_find_sibling(node->children, "chainQuitKey"))) {
432 key = obt_xml_node_string(n);
433 translate_key(key, &config_keyboard_reset_state,
434 &config_keyboard_reset_keycode);
438 if ((n = obt_xml_find_sibling(node->children, "keybind")))
441 n = obt_xml_find_sibling(n->next, "keybind");
447 <context name="Titlebar">
448 <mousebind button="Left" action="Press">
449 <action name="Raise"></action>
455 static void parse_mouse(xmlNodePtr node, gpointer d)
457 xmlNodePtr n, nbut, nact;
464 node = node->children;
466 if ((n = obt_xml_find_sibling(node, "dragThreshold")))
467 config_mouse_threshold = obt_xml_node_int(n);
468 if ((n = obt_xml_find_sibling(node, "doubleClickTime")))
469 config_mouse_dclicktime = obt_xml_node_int(n);
470 if ((n = obt_xml_find_sibling(node, "screenEdgeWarpTime"))) {
471 config_mouse_screenedgetime = obt_xml_node_int(n);
472 /* minimum value of 25 for this property, when it is 1 and you hit the
473 edge it basically never stops */
474 if (config_mouse_screenedgetime && config_mouse_screenedgetime < 25)
475 config_mouse_screenedgetime = 25;
477 if ((n = obt_xml_find_sibling(node, "screenEdgeWarpMouse")))
478 config_mouse_screenedgewarp = obt_xml_node_bool(n);
480 n = obt_xml_find_sibling(node, "context");
485 if (!obt_xml_attr_string(n, "name", &cxstr))
488 modcxstr = g_strdup(cxstr); /* make a copy to mutilate */
489 while (frame_next_context_from_string(modcxstr, &cx)) {
491 gchar *s = strchr(modcxstr, ' ');
494 g_message(_("Invalid context \"%s\" in mouse binding"),
501 nbut = obt_xml_find_sibling(n->children, "mousebind");
503 if (!obt_xml_attr_string(nbut, "button", &buttonstr))
505 if (obt_xml_attr_contains(nbut, "action", "press"))
506 mact = OB_MOUSE_ACTION_PRESS;
507 else if (obt_xml_attr_contains(nbut, "action", "release"))
508 mact = OB_MOUSE_ACTION_RELEASE;
509 else if (obt_xml_attr_contains(nbut, "action", "click"))
510 mact = OB_MOUSE_ACTION_CLICK;
511 else if (obt_xml_attr_contains(nbut, "action","doubleclick"))
512 mact = OB_MOUSE_ACTION_DOUBLE_CLICK;
513 else if (obt_xml_attr_contains(nbut, "action", "drag"))
514 mact = OB_MOUSE_ACTION_MOTION;
518 nact = obt_xml_find_sibling(nbut->children, "action");
520 ObActionList *actions;
524 c = xmlNodeGetContent(nact);
525 p = action_parser_new();
526 if ((actions = action_parser_read_string(p, (gchar*)c)))
527 mouse_bind(buttonstr, cx, mact, actions);
528 nact = obt_xml_find_sibling(nact->next, "action");
529 action_list_unref(actions);
531 action_parser_unref(p);
535 nbut = obt_xml_find_sibling(nbut->next, "mousebind");
541 n = obt_xml_find_sibling(n->next, "context");
545 static void parse_focus(xmlNodePtr node, gpointer d)
549 node = node->children;
551 if ((n = obt_xml_find_sibling(node, "focusNew")))
552 config_focus_new = obt_xml_node_bool(n);
553 if ((n = obt_xml_find_sibling(node, "followMouse")))
554 config_focus_follow = obt_xml_node_bool(n);
555 if ((n = obt_xml_find_sibling(node, "focusDelay")))
556 config_focus_delay = obt_xml_node_int(n);
557 if ((n = obt_xml_find_sibling(node, "raiseOnFocus")))
558 config_focus_raise = obt_xml_node_bool(n);
559 if ((n = obt_xml_find_sibling(node, "focusLast")))
560 config_focus_last = obt_xml_node_bool(n);
561 if ((n = obt_xml_find_sibling(node, "underMouse")))
562 config_focus_under_mouse = obt_xml_node_bool(n);
563 if ((n = obt_xml_find_sibling(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_sibling(node, "policy")))
574 if (obt_xml_node_contains(n, "UnderMouse"))
575 config_place_policy = OB_PLACE_POLICY_MOUSE;
576 if ((n = obt_xml_find_sibling(node, "center")))
577 config_place_center = obt_xml_node_bool(n);
578 if ((n = obt_xml_find_sibling(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;
583 else if (obt_xml_node_contains(n, "any"))
584 config_place_monitor = OB_PLACE_MONITOR_ANY;
586 if ((n = obt_xml_find_sibling(node, "primaryMonitor"))) {
587 config_primary_monitor_index = obt_xml_node_int(n);
588 if (!config_primary_monitor_index) {
589 if (obt_xml_node_contains(n, "mouse"))
590 config_primary_monitor = OB_PLACE_MONITOR_MOUSE;
595 static void parse_margins(xmlNodePtr node, gpointer d)
599 node = node->children;
601 if ((n = obt_xml_find_sibling(node, "top")))
602 config_margins.top = MAX(0, obt_xml_node_int(n));
603 if ((n = obt_xml_find_sibling(node, "left")))
604 config_margins.left = MAX(0, obt_xml_node_int(n));
605 if ((n = obt_xml_find_sibling(node, "right")))
606 config_margins.right = MAX(0, obt_xml_node_int(n));
607 if ((n = obt_xml_find_sibling(node, "bottom")))
608 config_margins.bottom = MAX(0, obt_xml_node_int(n));
611 static void parse_theme(xmlNodePtr node, gpointer d)
615 node = node->children;
617 if ((n = obt_xml_find_sibling(node, "name"))) {
620 g_free(config_theme);
621 c = obt_xml_node_string(n);
622 config_theme = obt_paths_expand_tilde(c);
625 if ((n = obt_xml_find_sibling(node, "titleLayout"))) {
628 g_free(config_title_layout);
629 config_title_layout = obt_xml_node_string(n);
631 /* replace duplicates with spaces */
632 for (c = config_title_layout; *c != '\0'; ++c)
633 for (d = c+1; *d != '\0'; ++d)
634 if (*c == *d) *d = ' ';
636 if ((n = obt_xml_find_sibling(node, "keepBorder")))
637 config_theme_keepborder = obt_xml_node_bool(n);
638 if ((n = obt_xml_find_sibling(node, "animateIconify")))
639 config_animate_iconify = obt_xml_node_bool(n);
640 if ((n = obt_xml_find_sibling(node, "windowListIconSize"))) {
641 config_theme_window_list_icon_size = obt_xml_node_int(n);
642 if (config_theme_window_list_icon_size < 16)
643 config_theme_window_list_icon_size = 16;
644 else if (config_theme_window_list_icon_size > 96)
645 config_theme_window_list_icon_size = 96;
648 n = obt_xml_find_sibling(node, "font");
652 gchar *name = g_strdup(RrDefaultFontFamily);
653 gint size = RrDefaultFontSize;
654 RrFontWeight weight = RrDefaultFontWeight;
655 RrFontSlant slant = RrDefaultFontSlant;
657 if (obt_xml_attr_contains(n, "place", "ActiveWindow"))
658 font = &config_font_activewindow;
659 else if (obt_xml_attr_contains(n, "place", "InactiveWindow"))
660 font = &config_font_inactivewindow;
661 else if (obt_xml_attr_contains(n, "place", "MenuHeader"))
662 font = &config_font_menutitle;
663 else if (obt_xml_attr_contains(n, "place", "MenuItem"))
664 font = &config_font_menuitem;
665 else if (obt_xml_attr_contains(n, "place", "ActiveOnScreenDisplay"))
666 font = &config_font_activeosd;
667 else if (obt_xml_attr_contains(n, "place", "OnScreenDisplay"))
668 font = &config_font_activeosd;
669 else if (obt_xml_attr_contains(n, "place","InactiveOnScreenDisplay"))
670 font = &config_font_inactiveosd;
674 if ((fnode = obt_xml_find_sibling(n->children, "name"))) {
676 name = obt_xml_node_string(fnode);
678 if ((fnode = obt_xml_find_sibling(n->children, "size"))) {
679 int s = obt_xml_node_int(fnode);
682 if ((fnode = obt_xml_find_sibling(n->children, "weight"))) {
683 gchar *w = obt_xml_node_string(fnode);
684 if (!g_ascii_strcasecmp(w, "Bold"))
685 weight = RR_FONTWEIGHT_BOLD;
688 if ((fnode = obt_xml_find_sibling(n->children, "slant"))) {
689 gchar *s = obt_xml_node_string(fnode);
690 if (!g_ascii_strcasecmp(s, "Italic"))
691 slant = RR_FONTSLANT_ITALIC;
692 if (!g_ascii_strcasecmp(s, "Oblique"))
693 slant = RR_FONTSLANT_OBLIQUE;
697 *font = RrFontOpen(ob_rr_inst, name, size, weight, slant);
700 n = obt_xml_find_sibling(n->next, "font");
704 static void parse_desktops(xmlNodePtr node, gpointer d)
708 node = node->children;
710 if ((n = obt_xml_find_sibling(node, "number"))) {
711 gint d = obt_xml_node_int(n);
713 config_desktops_num = (unsigned) d;
715 if ((n = obt_xml_find_sibling(node, "firstdesk"))) {
716 gint d = obt_xml_node_int(n);
718 config_screen_firstdesk = (unsigned) d;
720 if ((n = obt_xml_find_sibling(node, "names"))) {
724 for (it = config_desktops_names; it; it = it->next)
726 g_slist_free(config_desktops_names);
727 config_desktops_names = NULL;
729 nname = obt_xml_find_sibling(n->children, "name");
731 config_desktops_names =
732 g_slist_append(config_desktops_names,
733 obt_xml_node_string(nname));
734 nname = obt_xml_find_sibling(nname->next, "name");
737 if ((n = obt_xml_find_sibling(node, "popupTime")))
738 config_desktop_popup_time = obt_xml_node_int(n);
741 static void parse_resize(xmlNodePtr node, gpointer d)
745 node = node->children;
747 if ((n = obt_xml_find_sibling(node, "drawContents")))
748 config_resize_redraw = obt_xml_node_bool(n);
749 if ((n = obt_xml_find_sibling(node, "popupShow"))) {
750 config_resize_popup_show = obt_xml_node_int(n);
751 if (obt_xml_node_contains(n, "Always"))
752 config_resize_popup_show = 2;
753 else if (obt_xml_node_contains(n, "Never"))
754 config_resize_popup_show = 0;
755 else if (obt_xml_node_contains(n, "Nonpixel"))
756 config_resize_popup_show = 1;
758 if ((n = obt_xml_find_sibling(node, "popupPosition"))) {
759 if (obt_xml_node_contains(n, "Top"))
760 config_resize_popup_pos = OB_RESIZE_POS_TOP;
761 else if (obt_xml_node_contains(n, "Center"))
762 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
763 else if (obt_xml_node_contains(n, "Fixed")) {
764 config_resize_popup_pos = OB_RESIZE_POS_FIXED;
766 if ((n = obt_xml_find_sibling(node, "popupFixedPosition"))) {
769 if ((n2 = obt_xml_find_sibling(n->children, "x"))) {
770 ObConfigValue *v = config_value_new_string(
771 obt_xml_node_string(n2));
772 config_value_gravity_coord(v,
773 &config_resize_popup_fixed.x);
774 config_value_unref(v);
776 if ((n2 = obt_xml_find_sibling(n->children, "y"))) {
777 ObConfigValue *v = config_value_new_string(
778 obt_xml_node_string(n2));
779 config_value_gravity_coord(v,
780 &config_resize_popup_fixed.y);
781 config_value_unref(v);
784 config_resize_popup_fixed.x.pos =
785 MAX(config_resize_popup_fixed.x.pos, 0);
786 config_resize_popup_fixed.y.pos =
787 MAX(config_resize_popup_fixed.y.pos, 0);
793 static void parse_dock(xmlNodePtr node, gpointer d)
797 node = node->children;
799 if ((n = obt_xml_find_sibling(node, "position"))) {
800 if (obt_xml_node_contains(n, "TopLeft"))
801 config_dock_floating = FALSE,
802 config_dock_pos = OB_DIRECTION_NORTHWEST;
803 else if (obt_xml_node_contains(n, "Top"))
804 config_dock_floating = FALSE,
805 config_dock_pos = OB_DIRECTION_NORTH;
806 else if (obt_xml_node_contains(n, "TopRight"))
807 config_dock_floating = FALSE,
808 config_dock_pos = OB_DIRECTION_NORTHEAST;
809 else if (obt_xml_node_contains(n, "Right"))
810 config_dock_floating = FALSE,
811 config_dock_pos = OB_DIRECTION_EAST;
812 else if (obt_xml_node_contains(n, "BottomRight"))
813 config_dock_floating = FALSE,
814 config_dock_pos = OB_DIRECTION_SOUTHEAST;
815 else if (obt_xml_node_contains(n, "Bottom"))
816 config_dock_floating = FALSE,
817 config_dock_pos = OB_DIRECTION_SOUTH;
818 else if (obt_xml_node_contains(n, "BottomLeft"))
819 config_dock_floating = FALSE,
820 config_dock_pos = OB_DIRECTION_SOUTHWEST;
821 else if (obt_xml_node_contains(n, "Left"))
822 config_dock_floating = FALSE,
823 config_dock_pos = OB_DIRECTION_WEST;
824 else if (obt_xml_node_contains(n, "Floating"))
825 config_dock_floating = TRUE;
827 if (config_dock_floating) {
828 if ((n = obt_xml_find_sibling(node, "floatingX")))
829 config_dock_x = obt_xml_node_int(n);
830 if ((n = obt_xml_find_sibling(node, "floatingY")))
831 config_dock_y = obt_xml_node_int(n);
833 if ((n = obt_xml_find_sibling(node, "noStrut")))
834 config_dock_nostrut = obt_xml_node_bool(n);
836 if ((n = obt_xml_find_sibling(node, "stacking"))) {
837 if (obt_xml_node_contains(n, "normal"))
838 config_dock_layer = OB_STACKING_LAYER_NORMAL;
839 else if (obt_xml_node_contains(n, "below"))
840 config_dock_layer = OB_STACKING_LAYER_BELOW;
841 else if (obt_xml_node_contains(n, "above"))
842 config_dock_layer = OB_STACKING_LAYER_ABOVE;
844 if ((n = obt_xml_find_sibling(node, "direction"))) {
845 if (obt_xml_node_contains(n, "horizontal"))
846 config_dock_orient = OB_ORIENTATION_HORZ;
847 else if (obt_xml_node_contains(n, "vertical"))
848 config_dock_orient = OB_ORIENTATION_VERT;
850 if ((n = obt_xml_find_sibling(node, "autoHide")))
851 config_dock_hide = obt_xml_node_bool(n);
852 if ((n = obt_xml_find_sibling(node, "hideDelay")))
853 config_dock_hide_delay = obt_xml_node_int(n);
854 if ((n = obt_xml_find_sibling(node, "showDelay")))
855 config_dock_show_delay = obt_xml_node_int(n);
856 if ((n = obt_xml_find_sibling(node, "moveButton"))) {
857 gchar *str = obt_xml_node_string(n);
859 if (translate_button(str, &s, &b)) {
860 config_dock_app_move_button = b;
861 config_dock_app_move_modifiers = s;
863 g_message(_("Invalid button \"%s\" specified in config file"), str);
869 static void parse_menu(xmlNodePtr node, gpointer d)
872 node = node->children;
874 if ((n = obt_xml_find_sibling(node, "hideDelay")))
875 config_menu_hide_delay = obt_xml_node_int(n);
876 if ((n = obt_xml_find_sibling(node, "middle")))
877 config_menu_middle = obt_xml_node_bool(n);
878 if ((n = obt_xml_find_sibling(node, "submenuShowDelay")))
879 config_submenu_show_delay = obt_xml_node_int(n);
880 if ((n = obt_xml_find_sibling(node, "submenuHideDelay")))
881 config_submenu_hide_delay = obt_xml_node_int(n);
882 if ((n = obt_xml_find_sibling(node, "manageDesktops")))
883 config_menu_manage_desktops = obt_xml_node_bool(n);
884 if ((n = obt_xml_find_sibling(node, "showIcons"))) {
885 config_menu_show_icons = obt_xml_node_bool(n);
887 if (config_menu_show_icons)
888 g_message(_("Openbox was compiled without Imlib2 image loading support. Icons in menus will not be loaded."));
892 while ((node = obt_xml_find_sibling(node, "file"))) {
893 gchar *c = obt_xml_node_string(node);
894 config_menu_files = g_slist_append(config_menu_files,
895 obt_paths_expand_tilde(c));
901 static void parse_resistance(xmlNodePtr node, gpointer d)
905 node = node->children;
906 if ((n = obt_xml_find_sibling(node, "strength")))
907 config_resist_win = obt_xml_node_int(n);
908 if ((n = obt_xml_find_sibling(node, "screen_edge_strength")))
909 config_resist_edge = obt_xml_node_int(n);
915 const gchar *actiontext;
918 static void bind_default_keyboard(void)
921 ObDefKeyBind binds[] = {
923 "Execute startupnotify:yes name:Konqueror \\\n"
924 " command:(kfmclient openProfile filemanagement)" },
925 { "A-Tab", "NextWindow" },
926 { "S-A-Tab", "PreviousWindow" },
932 p = action_parser_new();
933 for (it = binds; it->key; ++it) {
934 GList *l = g_list_append(NULL, g_strdup(it->key));
935 ObActionList *actions = action_parser_read_string(p, it->actiontext);
936 keyboard_bind(l, actions);
937 action_list_unref(actions);
939 action_parser_unref(p);
945 const gchar *context;
946 const ObMouseAction mact;
947 const gchar *actname;
950 static void bind_default_mouse(void)
953 ObDefMouseBind binds[] = {
954 { "Left", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
955 { "Middle", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
956 { "Right", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
957 { "Left", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
958 { "Middle", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
959 { "Right", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
960 { "Left", "Titlebar", OB_MOUSE_ACTION_PRESS, "Focus" },
961 { "Left", "Bottom", OB_MOUSE_ACTION_PRESS, "Focus" },
962 { "Left", "BLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
963 { "Left", "BRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
964 { "Left", "TLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
965 { "Left", "TRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
966 { "Left", "Close", OB_MOUSE_ACTION_PRESS, "Focus" },
967 { "Left", "Maximize", OB_MOUSE_ACTION_PRESS, "Focus" },
968 { "Left", "Iconify", OB_MOUSE_ACTION_PRESS, "Focus" },
969 { "Left", "Icon", OB_MOUSE_ACTION_PRESS, "Focus" },
970 { "Left", "AllDesktops", OB_MOUSE_ACTION_PRESS, "Focus" },
971 { "Left", "Shade", OB_MOUSE_ACTION_PRESS, "Focus" },
972 { "Left", "Client", OB_MOUSE_ACTION_CLICK, "Raise" },
973 { "Left", "Titlebar", OB_MOUSE_ACTION_CLICK, "Raise" },
974 { "Middle", "Titlebar", OB_MOUSE_ACTION_CLICK, "Lower" },
975 { "Left", "BLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
976 { "Left", "BRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
977 { "Left", "TLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
978 { "Left", "TRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
979 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Raise" },
980 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "Raise" },
981 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Raise" },
982 { "Left", "Icon", OB_MOUSE_ACTION_CLICK, "Raise" },
983 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "Raise" },
984 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "Raise" },
985 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Close" },
986 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "ToggleMaximize" },
987 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Iconify" },
988 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "ToggleOmnipresent" },
989 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "ToggleShade" },
990 { "Left", "TLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
991 { "Left", "TRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
992 { "Left", "BLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
993 { "Left", "BRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
994 { "Left", "Top", OB_MOUSE_ACTION_MOTION, "Resize" },
995 { "Left", "Bottom", OB_MOUSE_ACTION_MOTION, "Resize" },
996 { "Left", "Left", OB_MOUSE_ACTION_MOTION, "Resize" },
997 { "Left", "Right", OB_MOUSE_ACTION_MOTION, "Resize" },
998 { "Left", "Titlebar", OB_MOUSE_ACTION_MOTION, "Move" },
999 { "A-Left", "Frame", OB_MOUSE_ACTION_MOTION, "Move" },
1000 { "A-Middle", "Frame", OB_MOUSE_ACTION_MOTION, "Resize" },
1001 { NULL, NULL, 0, NULL }
1004 ObActionList *actions;
1006 p = action_parser_new();
1007 for (it = binds; it->button; ++it) {
1008 actions = action_parser_read_string(p, it->actname);
1009 mouse_bind(it->button, frame_context_from_string(it->context),
1011 action_list_unref(actions);
1013 action_parser_unref(p);
1016 void config_startup(ObtXmlInst *i)
1018 config_focus_new = TRUE;
1019 config_focus_follow = FALSE;
1020 config_focus_delay = 0;
1021 config_focus_raise = FALSE;
1022 config_focus_last = TRUE;
1023 config_focus_under_mouse = FALSE;
1024 config_unfocus_leave = FALSE;
1026 obt_xml_register(i, "focus", parse_focus, NULL);
1028 config_place_policy = OB_PLACE_POLICY_SMART;
1029 config_place_center = TRUE;
1030 config_place_monitor = OB_PLACE_MONITOR_PRIMARY;
1032 config_primary_monitor_index = 1;
1033 config_primary_monitor = OB_PLACE_MONITOR_ACTIVE;
1035 obt_xml_register(i, "placement", parse_placement, NULL);
1037 STRUT_PARTIAL_SET(config_margins, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1039 obt_xml_register(i, "margins", parse_margins, NULL);
1041 config_theme = NULL;
1043 config_animate_iconify = TRUE;
1044 config_title_layout = g_strdup("NLIMC");
1045 config_theme_keepborder = TRUE;
1046 config_theme_window_list_icon_size = 36;
1048 config_font_activewindow = NULL;
1049 config_font_inactivewindow = NULL;
1050 config_font_menuitem = NULL;
1051 config_font_menutitle = NULL;
1052 config_font_activeosd = NULL;
1053 config_font_inactiveosd = NULL;
1055 obt_xml_register(i, "theme", parse_theme, NULL);
1057 config_desktops_num = 4;
1058 config_screen_firstdesk = 1;
1059 config_desktops_names = NULL;
1060 config_desktop_popup_time = 875;
1062 obt_xml_register(i, "desktops", parse_desktops, NULL);
1064 config_resize_redraw = TRUE;
1065 config_resize_popup_show = 1; /* nonpixel increments */
1066 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
1067 GRAVITY_COORD_SET(config_resize_popup_fixed.x, 0, FALSE, FALSE);
1068 GRAVITY_COORD_SET(config_resize_popup_fixed.y, 0, FALSE, FALSE);
1070 obt_xml_register(i, "resize", parse_resize, NULL);
1072 config_dock_layer = OB_STACKING_LAYER_ABOVE;
1073 config_dock_pos = OB_DIRECTION_NORTHEAST;
1074 config_dock_floating = FALSE;
1075 config_dock_nostrut = FALSE;
1078 config_dock_orient = OB_ORIENTATION_VERT;
1079 config_dock_hide = FALSE;
1080 config_dock_hide_delay = 300;
1081 config_dock_show_delay = 300;
1082 config_dock_app_move_button = 2; /* middle */
1083 config_dock_app_move_modifiers = 0;
1085 obt_xml_register(i, "dock", parse_dock, NULL);
1087 translate_key("C-g", &config_keyboard_reset_state,
1088 &config_keyboard_reset_keycode);
1090 bind_default_keyboard();
1092 obt_xml_register(i, "keyboard", parse_keyboard, NULL);
1094 config_mouse_threshold = 8;
1095 config_mouse_dclicktime = 200;
1096 config_mouse_screenedgetime = 400;
1097 config_mouse_screenedgewarp = FALSE;
1099 bind_default_mouse();
1101 obt_xml_register(i, "mouse", parse_mouse, NULL);
1103 config_resist_win = 10;
1104 config_resist_edge = 20;
1106 obt_xml_register(i, "resistance", parse_resistance, NULL);
1108 config_menu_hide_delay = 250;
1109 config_menu_middle = FALSE;
1110 config_submenu_show_delay = 100;
1111 config_submenu_hide_delay = 400;
1112 config_menu_manage_desktops = TRUE;
1113 config_menu_files = NULL;
1114 config_menu_show_icons = TRUE;
1116 obt_xml_register(i, "menu", parse_menu, NULL);
1118 config_per_app_settings = NULL;
1120 obt_xml_register(i, "applications", parse_per_app_settings, NULL);
1123 void config_shutdown(void)
1127 g_free(config_theme);
1129 g_free(config_title_layout);
1131 RrFontClose(config_font_activewindow);
1132 RrFontClose(config_font_inactivewindow);
1133 RrFontClose(config_font_menuitem);
1134 RrFontClose(config_font_menutitle);
1135 RrFontClose(config_font_activeosd);
1136 RrFontClose(config_font_inactiveosd);
1138 for (it = config_desktops_names; it; it = g_slist_next(it))
1140 g_slist_free(config_desktops_names);
1142 for (it = config_menu_files; it; it = g_slist_next(it))
1144 g_slist_free(config_menu_files);
1146 for (it = config_per_app_settings; it; it = g_slist_next(it)) {
1147 ObAppSettings *itd = (ObAppSettings *)it->data;
1148 if (itd->name) g_pattern_spec_free(itd->name);
1149 if (itd->role) g_pattern_spec_free(itd->role);
1150 if (itd->title) g_pattern_spec_free(itd->title);
1151 if (itd->class) g_pattern_spec_free(itd->class);
1152 g_slice_free(ObAppSettings, it->data);
1154 g_slist_free(config_per_app_settings);