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 "action_list.h"
25 #include "action_parser.h"
26 #include "translate.h"
31 #include "obt/paths.h"
33 gboolean config_focus_new;
34 gboolean config_focus_follow;
35 guint config_focus_delay;
36 gboolean config_focus_raise;
37 gboolean config_focus_last;
38 gboolean config_focus_under_mouse;
39 gboolean config_unfocus_leave;
41 ObPlacePolicy config_place_policy;
42 gboolean config_place_center;
43 ObPlaceMonitor config_place_monitor;
45 guint config_primary_monitor_index;
46 ObPlaceMonitor config_primary_monitor;
48 StrutPartial config_margins;
51 gboolean config_theme_keepborder;
52 guint config_theme_window_list_icon_size;
54 gchar *config_title_layout;
56 gboolean config_animate_iconify;
58 RrFont *config_font_activewindow;
59 RrFont *config_font_inactivewindow;
60 RrFont *config_font_menuitem;
61 RrFont *config_font_menutitle;
62 RrFont *config_font_activeosd;
63 RrFont *config_font_inactiveosd;
65 guint config_desktops_num;
66 GSList *config_desktops_names;
67 guint config_screen_firstdesk;
68 guint config_desktop_popup_time;
70 gboolean config_resize_redraw;
71 gint config_resize_popup_show;
72 ObResizePopupPos config_resize_popup_pos;
73 GravityPoint config_resize_popup_fixed;
75 ObStackingLayer config_dock_layer;
76 gboolean config_dock_floating;
77 gboolean config_dock_nostrut;
78 ObDirection config_dock_pos;
81 ObOrientation config_dock_orient;
82 gboolean config_dock_hide;
83 guint config_dock_hide_delay;
84 guint config_dock_show_delay;
85 guint config_dock_app_move_button;
86 guint config_dock_app_move_modifiers;
88 guint config_keyboard_reset_keycode;
89 guint config_keyboard_reset_state;
91 gint config_mouse_threshold;
92 gint config_mouse_dclicktime;
93 gint config_mouse_screenedgetime;
94 gboolean config_mouse_screenedgewarp;
96 guint config_menu_hide_delay;
97 gboolean config_menu_middle;
98 guint config_submenu_show_delay;
99 guint config_submenu_hide_delay;
100 gboolean config_menu_manage_desktops;
101 gboolean config_menu_show_icons;
103 GSList *config_menu_files;
105 gint config_resist_win;
106 gint config_resist_edge;
108 GSList *config_per_app_settings;
110 ObAppSettings* config_create_app_settings(void)
112 ObAppSettings *settings = g_slice_new0(ObAppSettings);
114 settings->decor = -1;
115 settings->shade = -1;
116 settings->monitor_type = OB_PLACE_MONITOR_ANY;
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_type, OB_PLACE_MONITOR_ANY);
142 copy_if(monitor, -1);
147 copy_if(skip_pager, -1);
148 copy_if(skip_taskbar, -1);
149 copy_if(fullscreen, -1);
150 copy_if(max_horz, -1);
151 copy_if(max_vert, -1);
153 if (src->pos_given) {
154 dst->pos_given = TRUE;
155 dst->pos_force = src->pos_force;
156 dst->position = src->position;
157 /* monitor is copied above */
161 void config_parse_relative_number(gchar *s, gint *num, gint *denom)
163 *num = strtol(s, &s, 10);
167 } else if (*s == '/') {
172 void config_parse_gravity_coord(xmlNodePtr node, GravityCoord *c)
174 gchar *s = obt_xml_node_string(node);
175 if (!g_ascii_strcasecmp(s, "center"))
181 if (s[0] == '-' || s[0] == '+')
183 config_parse_relative_number(ps, &c->pos, &c->denom);
190 <application name="aterm">
193 <application name="Rhythmbox">
200 .. there is a lot more settings available
205 /* Manages settings for individual applications.
206 Some notes: monitor is the screen number in a multi monitor
207 (Xinerama) setup (starting from 0), or mouse: the monitor the pointer
208 is on, active: the active monitor, primary: the primary monitor.
209 Layer can be three values, above (Always on top), below
210 (Always on bottom) and everything else (normal behaviour).
211 Positions can be an integer value or center, which will
212 center the window in the specified axis. Position is within
213 the monitor, so <position><x>center</x></position><monitor>2</monitor>
214 will center the window on the second monitor.
216 static void parse_per_app_settings(xmlNodePtr node, gpointer d)
218 xmlNodePtr app = obt_xml_find_node(node->children, "application");
219 gchar *name = NULL, *class = NULL, *role = NULL, *title = NULL,
221 gboolean name_set, class_set, type_set, role_set, title_set;
223 gboolean x_pos_given;
228 class_set = obt_xml_attr_string(app, "class", &class);
229 name_set = obt_xml_attr_string(app, "name", &name);
230 type_set = obt_xml_attr_string(app, "type", &type_str);
231 role_set = obt_xml_attr_string(app, "role", &role);
232 title_set = obt_xml_attr_string(app, "title", &title);
234 /* validate the type tho */
236 if (!g_ascii_strcasecmp(type_str, "normal"))
237 type = OB_CLIENT_TYPE_NORMAL;
238 else if (!g_ascii_strcasecmp(type_str, "dialog"))
239 type = OB_CLIENT_TYPE_DIALOG;
240 else if (!g_ascii_strcasecmp(type_str, "splash"))
241 type = OB_CLIENT_TYPE_SPLASH;
242 else if (!g_ascii_strcasecmp(type_str, "utility"))
243 type = OB_CLIENT_TYPE_UTILITY;
244 else if (!g_ascii_strcasecmp(type_str, "menu"))
245 type = OB_CLIENT_TYPE_MENU;
246 else if (!g_ascii_strcasecmp(type_str, "toolbar"))
247 type = OB_CLIENT_TYPE_TOOLBAR;
248 else if (!g_ascii_strcasecmp(type_str, "dock"))
249 type = OB_CLIENT_TYPE_DOCK;
250 else if (!g_ascii_strcasecmp(type_str, "desktop"))
251 type = OB_CLIENT_TYPE_DESKTOP;
253 type_set = FALSE; /* not valid! */
256 if (class_set || name_set || role_set || title_set || type_set) {
258 ObAppSettings *settings = config_create_app_settings();
261 settings->name = g_pattern_spec_new(name);
264 settings->class = g_pattern_spec_new(class);
267 settings->role = g_pattern_spec_new(role);
270 settings->title = g_pattern_spec_new(title);
273 settings->type = type;
275 if ((n = obt_xml_find_node(app->children, "decor")))
276 if (!obt_xml_node_contains(n, "default"))
277 settings->decor = obt_xml_node_bool(n);
279 if ((n = obt_xml_find_node(app->children, "shade")))
280 if (!obt_xml_node_contains(n, "default"))
281 settings->shade = obt_xml_node_bool(n);
283 if ((n = obt_xml_find_node(app->children, "position"))) {
284 if ((c = obt_xml_find_node(n->children, "x")))
285 if (!obt_xml_node_contains(c, "default")) {
286 config_parse_gravity_coord(c, &settings->position.x);
290 if (x_pos_given && (c = obt_xml_find_node(n->children, "y")))
291 if (!obt_xml_node_contains(c, "default")) {
292 config_parse_gravity_coord(c, &settings->position.y);
293 settings->pos_given = TRUE;
296 /* monitor can be set without setting x or y */
297 if ((c = obt_xml_find_node(n->children, "monitor")))
298 if (!obt_xml_node_contains(c, "default")) {
299 gchar *s = obt_xml_node_string(c);
300 if (!g_ascii_strcasecmp(s, "mouse"))
301 settings->monitor_type =
302 OB_PLACE_MONITOR_MOUSE;
303 else if (!g_ascii_strcasecmp(s, "active"))
304 settings->monitor_type =
305 OB_PLACE_MONITOR_ACTIVE;
306 else if (!g_ascii_strcasecmp(s, "primary"))
307 settings->monitor_type =
308 OB_PLACE_MONITOR_PRIMARY;
310 settings->monitor = obt_xml_node_int(c);
314 obt_xml_attr_bool(n, "force", &settings->pos_force);
317 if ((n = obt_xml_find_node(app->children, "focus")))
318 if (!obt_xml_node_contains(n, "default"))
319 settings->focus = obt_xml_node_bool(n);
321 if ((n = obt_xml_find_node(app->children, "desktop"))) {
322 if (!obt_xml_node_contains(n, "default")) {
323 gchar *s = obt_xml_node_string(n);
324 if (!g_ascii_strcasecmp(s, "all"))
325 settings->desktop = DESKTOP_ALL;
327 gint i = obt_xml_node_int(n);
329 settings->desktop = i;
335 if ((n = obt_xml_find_node(app->children, "layer")))
336 if (!obt_xml_node_contains(n, "default")) {
337 gchar *s = obt_xml_node_string(n);
338 if (!g_ascii_strcasecmp(s, "above"))
340 else if (!g_ascii_strcasecmp(s, "below"))
341 settings->layer = -1;
347 if ((n = obt_xml_find_node(app->children, "iconic")))
348 if (!obt_xml_node_contains(n, "default"))
349 settings->iconic = obt_xml_node_bool(n);
351 if ((n = obt_xml_find_node(app->children, "skip_pager")))
352 if (!obt_xml_node_contains(n, "default"))
353 settings->skip_pager = obt_xml_node_bool(n);
355 if ((n = obt_xml_find_node(app->children, "skip_taskbar")))
356 if (!obt_xml_node_contains(n, "default"))
357 settings->skip_taskbar = obt_xml_node_bool(n);
359 if ((n = obt_xml_find_node(app->children, "fullscreen")))
360 if (!obt_xml_node_contains(n, "default"))
361 settings->fullscreen = obt_xml_node_bool(n);
363 if ((n = obt_xml_find_node(app->children, "maximized")))
364 if (!obt_xml_node_contains(n, "default")) {
365 gchar *s = obt_xml_node_string(n);
366 if (!g_ascii_strcasecmp(s, "horizontal")) {
367 settings->max_horz = TRUE;
368 settings->max_vert = FALSE;
369 } else if (!g_ascii_strcasecmp(s, "vertical")) {
370 settings->max_horz = FALSE;
371 settings->max_vert = TRUE;
373 settings->max_horz = settings->max_vert =
374 obt_xml_node_bool(n);
378 config_per_app_settings = g_slist_append(config_per_app_settings,
379 (gpointer) settings);
385 name = class = role = title = type_str = NULL;
388 app = obt_xml_find_node(app->next, "application");
395 <action name="ChangeDesktop">
402 static void parse_key(xmlNodePtr node, GList *keylist)
404 gchar *keystring, **keys, **key;
406 gboolean is_chroot = FALSE;
408 if (!obt_xml_attr_string(node, "key", &keystring))
411 obt_xml_attr_bool(node, "chroot", &is_chroot);
413 keys = g_strsplit(keystring, " ", 0);
414 for (key = keys; *key; ++key) {
415 keylist = g_list_append(keylist, *key);
417 if ((n = obt_xml_find_node(node->children, "keybind"))) {
419 parse_key(n, keylist);
420 n = obt_xml_find_node(n->next, "keybind");
423 else if ((n = obt_xml_find_node(node->children, "action"))) {
426 ObActionList *actions;
429 c = xmlNodeGetContent(node);
430 p = action_parser_new();
431 actions = action_parser_read_string(p, (gchar*)c);
433 action_parser_unref(p);
436 keyboard_bind(keylist, actions);
438 action_list_unref(actions);
439 n = obt_xml_find_node(n->next, "action");
445 keyboard_chroot(keylist);
446 keylist = g_list_delete_link(keylist, g_list_last(keylist));
453 static void parse_keyboard(xmlNodePtr node, gpointer d)
458 keyboard_unbind_all();
460 if ((n = obt_xml_find_node(node->children, "chainQuitKey"))) {
461 key = obt_xml_node_string(n);
462 translate_key(key, &config_keyboard_reset_state,
463 &config_keyboard_reset_keycode);
467 if ((n = obt_xml_find_node(node->children, "keybind")))
470 n = obt_xml_find_node(n->next, "keybind");
476 <context name="Titlebar">
477 <mousebind button="Left" action="Press">
478 <action name="Raise"></action>
484 static void parse_mouse(xmlNodePtr node, gpointer d)
486 xmlNodePtr n, nbut, nact;
493 node = node->children;
495 if ((n = obt_xml_find_node(node, "dragThreshold")))
496 config_mouse_threshold = obt_xml_node_int(n);
497 if ((n = obt_xml_find_node(node, "doubleClickTime")))
498 config_mouse_dclicktime = obt_xml_node_int(n);
499 if ((n = obt_xml_find_node(node, "screenEdgeWarpTime"))) {
500 config_mouse_screenedgetime = obt_xml_node_int(n);
501 /* minimum value of 25 for this property, when it is 1 and you hit the
502 edge it basically never stops */
503 if (config_mouse_screenedgetime && config_mouse_screenedgetime < 25)
504 config_mouse_screenedgetime = 25;
506 if ((n = obt_xml_find_node(node, "screenEdgeWarpMouse")))
507 config_mouse_screenedgewarp = obt_xml_node_bool(n);
509 n = obt_xml_find_node(node, "context");
514 if (!obt_xml_attr_string(n, "name", &cxstr))
517 modcxstr = g_strdup(cxstr); /* make a copy to mutilate */
518 while (frame_next_context_from_string(modcxstr, &cx)) {
520 gchar *s = strchr(modcxstr, ' ');
523 g_message(_("Invalid context \"%s\" in mouse binding"),
530 nbut = obt_xml_find_node(n->children, "mousebind");
532 if (!obt_xml_attr_string(nbut, "button", &buttonstr))
534 if (obt_xml_attr_contains(nbut, "action", "press"))
535 mact = OB_MOUSE_ACTION_PRESS;
536 else if (obt_xml_attr_contains(nbut, "action", "release"))
537 mact = OB_MOUSE_ACTION_RELEASE;
538 else if (obt_xml_attr_contains(nbut, "action", "click"))
539 mact = OB_MOUSE_ACTION_CLICK;
540 else if (obt_xml_attr_contains(nbut, "action","doubleclick"))
541 mact = OB_MOUSE_ACTION_DOUBLE_CLICK;
542 else if (obt_xml_attr_contains(nbut, "action", "drag"))
543 mact = OB_MOUSE_ACTION_MOTION;
547 nact = obt_xml_find_node(nbut->children, "action");
549 ObActionList *actions;
553 c = xmlNodeGetContent(nact);
554 p = action_parser_new();
555 if ((actions = action_parser_read_string(p, (gchar*)c)))
556 mouse_bind(buttonstr, cx, mact, actions);
557 nact = obt_xml_find_node(nact->next, "action");
558 action_list_unref(actions);
560 action_parser_unref(p);
564 nbut = obt_xml_find_node(nbut->next, "mousebind");
570 n = obt_xml_find_node(n->next, "context");
574 static void parse_focus(xmlNodePtr node, gpointer d)
578 node = node->children;
580 if ((n = obt_xml_find_node(node, "focusNew")))
581 config_focus_new = obt_xml_node_bool(n);
582 if ((n = obt_xml_find_node(node, "followMouse")))
583 config_focus_follow = obt_xml_node_bool(n);
584 if ((n = obt_xml_find_node(node, "focusDelay")))
585 config_focus_delay = obt_xml_node_int(n);
586 if ((n = obt_xml_find_node(node, "raiseOnFocus")))
587 config_focus_raise = obt_xml_node_bool(n);
588 if ((n = obt_xml_find_node(node, "focusLast")))
589 config_focus_last = obt_xml_node_bool(n);
590 if ((n = obt_xml_find_node(node, "underMouse")))
591 config_focus_under_mouse = obt_xml_node_bool(n);
592 if ((n = obt_xml_find_node(node, "unfocusOnLeave")))
593 config_unfocus_leave = obt_xml_node_bool(n);
596 static void parse_placement(xmlNodePtr node, gpointer d)
600 node = node->children;
602 if ((n = obt_xml_find_node(node, "policy")))
603 if (obt_xml_node_contains(n, "UnderMouse"))
604 config_place_policy = OB_PLACE_POLICY_MOUSE;
605 if ((n = obt_xml_find_node(node, "center")))
606 config_place_center = obt_xml_node_bool(n);
607 if ((n = obt_xml_find_node(node, "monitor"))) {
608 if (obt_xml_node_contains(n, "active"))
609 config_place_monitor = OB_PLACE_MONITOR_ACTIVE;
610 else if (obt_xml_node_contains(n, "mouse"))
611 config_place_monitor = OB_PLACE_MONITOR_MOUSE;
612 else if (obt_xml_node_contains(n, "any"))
613 config_place_monitor = OB_PLACE_MONITOR_ANY;
615 if ((n = obt_xml_find_node(node, "primaryMonitor"))) {
616 config_primary_monitor_index = obt_xml_node_int(n);
617 if (!config_primary_monitor_index) {
618 if (obt_xml_node_contains(n, "mouse"))
619 config_primary_monitor = OB_PLACE_MONITOR_MOUSE;
624 static void parse_margins(xmlNodePtr node, gpointer d)
628 node = node->children;
630 if ((n = obt_xml_find_node(node, "top")))
631 config_margins.top = MAX(0, obt_xml_node_int(n));
632 if ((n = obt_xml_find_node(node, "left")))
633 config_margins.left = MAX(0, obt_xml_node_int(n));
634 if ((n = obt_xml_find_node(node, "right")))
635 config_margins.right = MAX(0, obt_xml_node_int(n));
636 if ((n = obt_xml_find_node(node, "bottom")))
637 config_margins.bottom = MAX(0, obt_xml_node_int(n));
640 static void parse_theme(xmlNodePtr node, gpointer d)
644 node = node->children;
646 if ((n = obt_xml_find_node(node, "name"))) {
649 g_free(config_theme);
650 c = obt_xml_node_string(n);
651 config_theme = obt_paths_expand_tilde(c);
654 if ((n = obt_xml_find_node(node, "titleLayout"))) {
657 g_free(config_title_layout);
658 config_title_layout = obt_xml_node_string(n);
660 /* replace duplicates with spaces */
661 for (c = config_title_layout; *c != '\0'; ++c)
662 for (d = c+1; *d != '\0'; ++d)
663 if (*c == *d) *d = ' ';
665 if ((n = obt_xml_find_node(node, "keepBorder")))
666 config_theme_keepborder = obt_xml_node_bool(n);
667 if ((n = obt_xml_find_node(node, "animateIconify")))
668 config_animate_iconify = obt_xml_node_bool(n);
669 if ((n = obt_xml_find_node(node, "windowListIconSize"))) {
670 config_theme_window_list_icon_size = obt_xml_node_int(n);
671 if (config_theme_window_list_icon_size < 16)
672 config_theme_window_list_icon_size = 16;
673 else if (config_theme_window_list_icon_size > 96)
674 config_theme_window_list_icon_size = 96;
677 n = obt_xml_find_node(node, "font");
681 gchar *name = g_strdup(RrDefaultFontFamily);
682 gint size = RrDefaultFontSize;
683 RrFontWeight weight = RrDefaultFontWeight;
684 RrFontSlant slant = RrDefaultFontSlant;
686 if (obt_xml_attr_contains(n, "place", "ActiveWindow"))
687 font = &config_font_activewindow;
688 else if (obt_xml_attr_contains(n, "place", "InactiveWindow"))
689 font = &config_font_inactivewindow;
690 else if (obt_xml_attr_contains(n, "place", "MenuHeader"))
691 font = &config_font_menutitle;
692 else if (obt_xml_attr_contains(n, "place", "MenuItem"))
693 font = &config_font_menuitem;
694 else if (obt_xml_attr_contains(n, "place", "ActiveOnScreenDisplay"))
695 font = &config_font_activeosd;
696 else if (obt_xml_attr_contains(n, "place", "OnScreenDisplay"))
697 font = &config_font_activeosd;
698 else if (obt_xml_attr_contains(n, "place","InactiveOnScreenDisplay"))
699 font = &config_font_inactiveosd;
703 if ((fnode = obt_xml_find_node(n->children, "name"))) {
705 name = obt_xml_node_string(fnode);
707 if ((fnode = obt_xml_find_node(n->children, "size"))) {
708 int s = obt_xml_node_int(fnode);
711 if ((fnode = obt_xml_find_node(n->children, "weight"))) {
712 gchar *w = obt_xml_node_string(fnode);
713 if (!g_ascii_strcasecmp(w, "Bold"))
714 weight = RR_FONTWEIGHT_BOLD;
717 if ((fnode = obt_xml_find_node(n->children, "slant"))) {
718 gchar *s = obt_xml_node_string(fnode);
719 if (!g_ascii_strcasecmp(s, "Italic"))
720 slant = RR_FONTSLANT_ITALIC;
721 if (!g_ascii_strcasecmp(s, "Oblique"))
722 slant = RR_FONTSLANT_OBLIQUE;
726 *font = RrFontOpen(ob_rr_inst, name, size, weight, slant);
729 n = obt_xml_find_node(n->next, "font");
733 static void parse_desktops(xmlNodePtr node, gpointer d)
737 node = node->children;
739 if ((n = obt_xml_find_node(node, "number"))) {
740 gint d = obt_xml_node_int(n);
742 config_desktops_num = (unsigned) d;
744 if ((n = obt_xml_find_node(node, "firstdesk"))) {
745 gint d = obt_xml_node_int(n);
747 config_screen_firstdesk = (unsigned) d;
749 if ((n = obt_xml_find_node(node, "names"))) {
753 for (it = config_desktops_names; it; it = it->next)
755 g_slist_free(config_desktops_names);
756 config_desktops_names = NULL;
758 nname = obt_xml_find_node(n->children, "name");
760 config_desktops_names =
761 g_slist_append(config_desktops_names,
762 obt_xml_node_string(nname));
763 nname = obt_xml_find_node(nname->next, "name");
766 if ((n = obt_xml_find_node(node, "popupTime")))
767 config_desktop_popup_time = obt_xml_node_int(n);
770 static void parse_resize(xmlNodePtr node, gpointer d)
774 node = node->children;
776 if ((n = obt_xml_find_node(node, "drawContents")))
777 config_resize_redraw = obt_xml_node_bool(n);
778 if ((n = obt_xml_find_node(node, "popupShow"))) {
779 config_resize_popup_show = obt_xml_node_int(n);
780 if (obt_xml_node_contains(n, "Always"))
781 config_resize_popup_show = 2;
782 else if (obt_xml_node_contains(n, "Never"))
783 config_resize_popup_show = 0;
784 else if (obt_xml_node_contains(n, "Nonpixel"))
785 config_resize_popup_show = 1;
787 if ((n = obt_xml_find_node(node, "popupPosition"))) {
788 if (obt_xml_node_contains(n, "Top"))
789 config_resize_popup_pos = OB_RESIZE_POS_TOP;
790 else if (obt_xml_node_contains(n, "Center"))
791 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
792 else if (obt_xml_node_contains(n, "Fixed")) {
793 config_resize_popup_pos = OB_RESIZE_POS_FIXED;
795 if ((n = obt_xml_find_node(node, "popupFixedPosition"))) {
798 if ((n2 = obt_xml_find_node(n->children, "x")))
799 config_parse_gravity_coord(n2,
800 &config_resize_popup_fixed.x);
801 if ((n2 = obt_xml_find_node(n->children, "y")))
802 config_parse_gravity_coord(n2,
803 &config_resize_popup_fixed.y);
805 config_resize_popup_fixed.x.pos =
806 MAX(config_resize_popup_fixed.x.pos, 0);
807 config_resize_popup_fixed.y.pos =
808 MAX(config_resize_popup_fixed.y.pos, 0);
814 static void parse_dock(xmlNodePtr node, gpointer d)
818 node = node->children;
820 if ((n = obt_xml_find_node(node, "position"))) {
821 if (obt_xml_node_contains(n, "TopLeft"))
822 config_dock_floating = FALSE,
823 config_dock_pos = OB_DIRECTION_NORTHWEST;
824 else if (obt_xml_node_contains(n, "Top"))
825 config_dock_floating = FALSE,
826 config_dock_pos = OB_DIRECTION_NORTH;
827 else if (obt_xml_node_contains(n, "TopRight"))
828 config_dock_floating = FALSE,
829 config_dock_pos = OB_DIRECTION_NORTHEAST;
830 else if (obt_xml_node_contains(n, "Right"))
831 config_dock_floating = FALSE,
832 config_dock_pos = OB_DIRECTION_EAST;
833 else if (obt_xml_node_contains(n, "BottomRight"))
834 config_dock_floating = FALSE,
835 config_dock_pos = OB_DIRECTION_SOUTHEAST;
836 else if (obt_xml_node_contains(n, "Bottom"))
837 config_dock_floating = FALSE,
838 config_dock_pos = OB_DIRECTION_SOUTH;
839 else if (obt_xml_node_contains(n, "BottomLeft"))
840 config_dock_floating = FALSE,
841 config_dock_pos = OB_DIRECTION_SOUTHWEST;
842 else if (obt_xml_node_contains(n, "Left"))
843 config_dock_floating = FALSE,
844 config_dock_pos = OB_DIRECTION_WEST;
845 else if (obt_xml_node_contains(n, "Floating"))
846 config_dock_floating = TRUE;
848 if (config_dock_floating) {
849 if ((n = obt_xml_find_node(node, "floatingX")))
850 config_dock_x = obt_xml_node_int(n);
851 if ((n = obt_xml_find_node(node, "floatingY")))
852 config_dock_y = obt_xml_node_int(n);
854 if ((n = obt_xml_find_node(node, "noStrut")))
855 config_dock_nostrut = obt_xml_node_bool(n);
857 if ((n = obt_xml_find_node(node, "stacking"))) {
858 if (obt_xml_node_contains(n, "normal"))
859 config_dock_layer = OB_STACKING_LAYER_NORMAL;
860 else if (obt_xml_node_contains(n, "below"))
861 config_dock_layer = OB_STACKING_LAYER_BELOW;
862 else if (obt_xml_node_contains(n, "above"))
863 config_dock_layer = OB_STACKING_LAYER_ABOVE;
865 if ((n = obt_xml_find_node(node, "direction"))) {
866 if (obt_xml_node_contains(n, "horizontal"))
867 config_dock_orient = OB_ORIENTATION_HORZ;
868 else if (obt_xml_node_contains(n, "vertical"))
869 config_dock_orient = OB_ORIENTATION_VERT;
871 if ((n = obt_xml_find_node(node, "autoHide")))
872 config_dock_hide = obt_xml_node_bool(n);
873 if ((n = obt_xml_find_node(node, "hideDelay")))
874 config_dock_hide_delay = obt_xml_node_int(n);
875 if ((n = obt_xml_find_node(node, "showDelay")))
876 config_dock_show_delay = obt_xml_node_int(n);
877 if ((n = obt_xml_find_node(node, "moveButton"))) {
878 gchar *str = obt_xml_node_string(n);
880 if (translate_button(str, &s, &b)) {
881 config_dock_app_move_button = b;
882 config_dock_app_move_modifiers = s;
884 g_message(_("Invalid button \"%s\" specified in config file"), str);
890 static void parse_menu(xmlNodePtr node, gpointer d)
893 node = node->children;
895 if ((n = obt_xml_find_node(node, "hideDelay")))
896 config_menu_hide_delay = obt_xml_node_int(n);
897 if ((n = obt_xml_find_node(node, "middle")))
898 config_menu_middle = obt_xml_node_bool(n);
899 if ((n = obt_xml_find_node(node, "submenuShowDelay")))
900 config_submenu_show_delay = obt_xml_node_int(n);
901 if ((n = obt_xml_find_node(node, "submenuHideDelay")))
902 config_submenu_hide_delay = obt_xml_node_int(n);
903 if ((n = obt_xml_find_node(node, "manageDesktops")))
904 config_menu_manage_desktops = obt_xml_node_bool(n);
905 if ((n = obt_xml_find_node(node, "showIcons"))) {
906 config_menu_show_icons = obt_xml_node_bool(n);
908 if (config_menu_show_icons)
909 g_message(_("Openbox was compiled without Imlib2 image loading support. Icons in menus will not be loaded."));
913 while ((node = obt_xml_find_node(node, "file"))) {
914 gchar *c = obt_xml_node_string(node);
915 config_menu_files = g_slist_append(config_menu_files,
916 obt_paths_expand_tilde(c));
922 static void parse_resistance(xmlNodePtr node, gpointer d)
926 node = node->children;
927 if ((n = obt_xml_find_node(node, "strength")))
928 config_resist_win = obt_xml_node_int(n);
929 if ((n = obt_xml_find_node(node, "screen_edge_strength")))
930 config_resist_edge = obt_xml_node_int(n);
936 const gchar *actiontext;
939 static void bind_default_keyboard(void)
942 ObDefKeyBind binds[] = {
944 "Execute startupnotify:yes name:Konqueror \\\n"
945 " command:(kfmclient openProfile filemanagement)" },
946 { "A-Tab", "NextWindow" },
947 { "S-A-Tab", "PreviousWindow" },
953 p = action_parser_new();
954 for (it = binds; it->key; ++it) {
955 GList *l = g_list_append(NULL, g_strdup(it->key));
956 ObActionList *actions = action_parser_read_string(p, it->actiontext);
957 keyboard_bind(l, actions);
958 action_list_unref(actions);
960 action_parser_unref(p);
966 const gchar *context;
967 const ObMouseAction mact;
968 const gchar *actname;
971 static void bind_default_mouse(void)
974 ObDefMouseBind binds[] = {
975 { "Left", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
976 { "Middle", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
977 { "Right", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
978 { "Left", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
979 { "Middle", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
980 { "Right", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
981 { "Left", "Titlebar", OB_MOUSE_ACTION_PRESS, "Focus" },
982 { "Left", "Bottom", OB_MOUSE_ACTION_PRESS, "Focus" },
983 { "Left", "BLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
984 { "Left", "BRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
985 { "Left", "TLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
986 { "Left", "TRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
987 { "Left", "Close", OB_MOUSE_ACTION_PRESS, "Focus" },
988 { "Left", "Maximize", OB_MOUSE_ACTION_PRESS, "Focus" },
989 { "Left", "Iconify", OB_MOUSE_ACTION_PRESS, "Focus" },
990 { "Left", "Icon", OB_MOUSE_ACTION_PRESS, "Focus" },
991 { "Left", "AllDesktops", OB_MOUSE_ACTION_PRESS, "Focus" },
992 { "Left", "Shade", OB_MOUSE_ACTION_PRESS, "Focus" },
993 { "Left", "Client", OB_MOUSE_ACTION_CLICK, "Raise" },
994 { "Left", "Titlebar", OB_MOUSE_ACTION_CLICK, "Raise" },
995 { "Middle", "Titlebar", OB_MOUSE_ACTION_CLICK, "Lower" },
996 { "Left", "BLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
997 { "Left", "BRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
998 { "Left", "TLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
999 { "Left", "TRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
1000 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Raise" },
1001 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "Raise" },
1002 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Raise" },
1003 { "Left", "Icon", OB_MOUSE_ACTION_CLICK, "Raise" },
1004 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "Raise" },
1005 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "Raise" },
1006 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Close" },
1007 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "ToggleMaximize" },
1008 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Iconify" },
1009 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "ToggleOmnipresent" },
1010 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "ToggleShade" },
1011 { "Left", "TLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
1012 { "Left", "TRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
1013 { "Left", "BLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
1014 { "Left", "BRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
1015 { "Left", "Top", OB_MOUSE_ACTION_MOTION, "Resize" },
1016 { "Left", "Bottom", OB_MOUSE_ACTION_MOTION, "Resize" },
1017 { "Left", "Left", OB_MOUSE_ACTION_MOTION, "Resize" },
1018 { "Left", "Right", OB_MOUSE_ACTION_MOTION, "Resize" },
1019 { "Left", "Titlebar", OB_MOUSE_ACTION_MOTION, "Move" },
1020 { "A-Left", "Frame", OB_MOUSE_ACTION_MOTION, "Move" },
1021 { "A-Middle", "Frame", OB_MOUSE_ACTION_MOTION, "Resize" },
1022 { NULL, NULL, 0, NULL }
1025 ObActionList *actions;
1027 p = action_parser_new();
1028 for (it = binds; it->button; ++it) {
1029 actions = action_parser_read_string(p, it->actname);
1030 mouse_bind(it->button, frame_context_from_string(it->context),
1032 action_list_unref(actions);
1034 action_parser_unref(p);
1037 void config_startup(ObtXmlInst *i)
1039 config_focus_new = TRUE;
1040 config_focus_follow = FALSE;
1041 config_focus_delay = 0;
1042 config_focus_raise = FALSE;
1043 config_focus_last = TRUE;
1044 config_focus_under_mouse = FALSE;
1045 config_unfocus_leave = FALSE;
1047 obt_xml_register(i, "focus", parse_focus, NULL);
1049 config_place_policy = OB_PLACE_POLICY_SMART;
1050 config_place_center = TRUE;
1051 config_place_monitor = OB_PLACE_MONITOR_PRIMARY;
1053 config_primary_monitor_index = 1;
1054 config_primary_monitor = OB_PLACE_MONITOR_ACTIVE;
1056 obt_xml_register(i, "placement", parse_placement, NULL);
1058 STRUT_PARTIAL_SET(config_margins, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1060 obt_xml_register(i, "margins", parse_margins, NULL);
1062 config_theme = NULL;
1064 config_animate_iconify = TRUE;
1065 config_title_layout = g_strdup("NLIMC");
1066 config_theme_keepborder = TRUE;
1067 config_theme_window_list_icon_size = 36;
1069 config_font_activewindow = NULL;
1070 config_font_inactivewindow = NULL;
1071 config_font_menuitem = NULL;
1072 config_font_menutitle = NULL;
1073 config_font_activeosd = NULL;
1074 config_font_inactiveosd = NULL;
1076 obt_xml_register(i, "theme", parse_theme, NULL);
1078 config_desktops_num = 4;
1079 config_screen_firstdesk = 1;
1080 config_desktops_names = NULL;
1081 config_desktop_popup_time = 875;
1083 obt_xml_register(i, "desktops", parse_desktops, NULL);
1085 config_resize_redraw = TRUE;
1086 config_resize_popup_show = 1; /* nonpixel increments */
1087 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
1088 GRAVITY_COORD_SET(config_resize_popup_fixed.x, 0, FALSE, FALSE);
1089 GRAVITY_COORD_SET(config_resize_popup_fixed.y, 0, FALSE, FALSE);
1091 obt_xml_register(i, "resize", parse_resize, NULL);
1093 config_dock_layer = OB_STACKING_LAYER_ABOVE;
1094 config_dock_pos = OB_DIRECTION_NORTHEAST;
1095 config_dock_floating = FALSE;
1096 config_dock_nostrut = FALSE;
1099 config_dock_orient = OB_ORIENTATION_VERT;
1100 config_dock_hide = FALSE;
1101 config_dock_hide_delay = 300;
1102 config_dock_show_delay = 300;
1103 config_dock_app_move_button = 2; /* middle */
1104 config_dock_app_move_modifiers = 0;
1106 obt_xml_register(i, "dock", parse_dock, NULL);
1108 translate_key("C-g", &config_keyboard_reset_state,
1109 &config_keyboard_reset_keycode);
1111 bind_default_keyboard();
1113 obt_xml_register(i, "keyboard", parse_keyboard, NULL);
1115 config_mouse_threshold = 8;
1116 config_mouse_dclicktime = 500;
1117 config_mouse_screenedgetime = 400;
1118 config_mouse_screenedgewarp = FALSE;
1120 bind_default_mouse();
1122 obt_xml_register(i, "mouse", parse_mouse, NULL);
1124 config_resist_win = 10;
1125 config_resist_edge = 20;
1127 obt_xml_register(i, "resistance", parse_resistance, NULL);
1129 config_menu_hide_delay = 250;
1130 config_menu_middle = FALSE;
1131 config_submenu_show_delay = 100;
1132 config_submenu_hide_delay = 400;
1133 config_menu_manage_desktops = TRUE;
1134 config_menu_files = NULL;
1135 config_menu_show_icons = TRUE;
1137 obt_xml_register(i, "menu", parse_menu, NULL);
1139 config_per_app_settings = NULL;
1141 obt_xml_register(i, "applications", parse_per_app_settings, NULL);
1144 void config_shutdown(void)
1148 g_free(config_theme);
1150 g_free(config_title_layout);
1152 RrFontClose(config_font_activewindow);
1153 RrFontClose(config_font_inactivewindow);
1154 RrFontClose(config_font_menuitem);
1155 RrFontClose(config_font_menutitle);
1156 RrFontClose(config_font_activeosd);
1157 RrFontClose(config_font_inactiveosd);
1159 for (it = config_desktops_names; it; it = g_slist_next(it))
1161 g_slist_free(config_desktops_names);
1163 for (it = config_menu_files; it; it = g_slist_next(it))
1165 g_slist_free(config_menu_files);
1167 for (it = config_per_app_settings; it; it = g_slist_next(it)) {
1168 ObAppSettings *itd = (ObAppSettings *)it->data;
1169 if (itd->name) g_pattern_spec_free(itd->name);
1170 if (itd->role) g_pattern_spec_free(itd->role);
1171 if (itd->title) g_pattern_spec_free(itd->title);
1172 if (itd->class) g_pattern_spec_free(itd->class);
1173 g_slice_free(ObAppSettings, it->data);
1175 g_slist_free(config_per_app_settings);