1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
3 config.c for the Openbox window manager
4 Copyright (c) 2006 Mikael Magnusson
5 Copyright (c) 2003-2007 Dana Jansens
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 See the COPYING file for a copy of the GNU General Public License.
24 #include "translate.h"
29 #include "obt/paths.h"
31 gboolean config_focus_new;
32 gboolean config_focus_follow;
33 guint config_focus_delay;
34 gboolean config_focus_raise;
35 gboolean config_focus_last;
36 gboolean config_focus_under_mouse;
37 gboolean config_unfocus_leave;
39 ObPlacePolicy config_place_policy;
40 gboolean config_place_center;
41 ObPlaceMonitor config_place_monitor;
43 guint config_primary_monitor_index;
44 ObPlaceMonitor config_primary_monitor;
46 StrutPartial config_margins;
49 gboolean config_theme_keepborder;
50 guint config_theme_window_list_icon_size;
52 gchar *config_title_layout;
54 gboolean config_animate_iconify;
56 RrFont *config_font_activewindow;
57 RrFont *config_font_inactivewindow;
58 RrFont *config_font_menuitem;
59 RrFont *config_font_menutitle;
60 RrFont *config_font_activeosd;
61 RrFont *config_font_inactiveosd;
63 guint config_desktops_num;
64 GSList *config_desktops_names;
65 guint config_screen_firstdesk;
66 guint config_desktop_popup_time;
68 gboolean config_resize_redraw;
69 gint config_resize_popup_show;
70 ObResizePopupPos config_resize_popup_pos;
71 GravityPoint config_resize_popup_fixed;
73 ObStackingLayer config_dock_layer;
74 gboolean config_dock_floating;
75 gboolean config_dock_nostrut;
76 ObDirection config_dock_pos;
79 ObOrientation config_dock_orient;
80 gboolean config_dock_hide;
81 guint config_dock_hide_delay;
82 guint config_dock_show_delay;
83 guint config_dock_app_move_button;
84 guint config_dock_app_move_modifiers;
86 guint config_keyboard_reset_keycode;
87 guint config_keyboard_reset_state;
89 gint config_mouse_threshold;
90 gint config_mouse_dclicktime;
91 gint config_mouse_screenedgetime;
92 gboolean config_mouse_screenedgewarp;
94 guint config_menu_hide_delay;
95 gboolean config_menu_middle;
96 guint config_submenu_show_delay;
97 guint config_submenu_hide_delay;
98 gboolean config_menu_manage_desktops;
99 gboolean config_menu_show_icons;
101 GSList *config_menu_files;
103 gint config_resist_win;
104 gint config_resist_edge;
106 GSList *config_per_app_settings;
108 ObAppSettings* config_create_app_settings(void)
110 ObAppSettings *settings = g_slice_new0(ObAppSettings);
112 settings->decor = -1;
113 settings->shade = -1;
114 settings->monitor_type = OB_PLACE_MONITOR_ANY;
115 settings->monitor = -1;
116 settings->focus = -1;
117 settings->desktop = 0;
118 settings->layer = -2;
119 settings->iconic = -1;
120 settings->skip_pager = -1;
121 settings->skip_taskbar = -1;
122 settings->fullscreen = -1;
123 settings->max_horz = -1;
124 settings->max_vert = -1;
128 #define copy_if(setting, default) \
129 if (src->setting != default) dst->setting = src->setting
130 void config_app_settings_copy_non_defaults(const ObAppSettings *src,
133 g_assert(src != NULL);
134 g_assert(dst != NULL);
136 copy_if(type, (ObClientType)-1);
139 copy_if(monitor_type, OB_PLACE_MONITOR_ANY);
140 copy_if(monitor, -1);
145 copy_if(skip_pager, -1);
146 copy_if(skip_taskbar, -1);
147 copy_if(fullscreen, -1);
148 copy_if(max_horz, -1);
149 copy_if(max_vert, -1);
151 if (src->pos_given) {
152 dst->pos_given = TRUE;
153 dst->pos_force = src->pos_force;
154 dst->position = src->position;
155 /* monitor is copied above */
159 void config_parse_relative_number(gchar *s, gint *num, gint *denom)
161 *num = strtol(s, &s, 10);
165 } else if (*s == '/') {
170 void config_parse_gravity_coord(xmlNodePtr node, GravityCoord *c)
172 gchar *s = obt_xml_node_string(node);
173 if (!g_ascii_strcasecmp(s, "center"))
179 if (s[0] == '-' || s[0] == '+')
181 config_parse_relative_number(ps, &c->pos, &c->denom);
188 <application name="aterm">
191 <application name="Rhythmbox">
198 .. there is a lot more settings available
203 /* Manages settings for individual applications.
204 Some notes: monitor is the screen number in a multi monitor
205 (Xinerama) setup (starting from 0), or mouse: the monitor the pointer
206 is on, active: the active monitor, primary: the primary monitor.
207 Layer can be three values, above (Always on top), below
208 (Always on bottom) and everything else (normal behaviour).
209 Positions can be an integer value or center, which will
210 center the window in the specified axis. Position is within
211 the monitor, so <position><x>center</x></position><monitor>2</monitor>
212 will center the window on the second monitor.
214 static void parse_per_app_settings(xmlNodePtr node, gpointer d)
216 xmlNodePtr app = obt_xml_find_node(node->children, "application");
217 gchar *name = NULL, *class = NULL, *role = NULL, *title = NULL,
218 *type_str = NULL, *group_name = NULL, *group_class = NULL;
219 gboolean name_set, class_set, type_set, role_set, title_set,
220 group_name_set, group_class_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 group_class_set = obt_xml_attr_string(app, "groupclass", &group_class);
230 group_name_set = obt_xml_attr_string(app, "groupname", &group_name);
231 type_set = obt_xml_attr_string(app, "type", &type_str);
232 role_set = obt_xml_attr_string(app, "role", &role);
233 title_set = obt_xml_attr_string(app, "title", &title);
235 /* validate the type tho */
237 if (!g_ascii_strcasecmp(type_str, "normal"))
238 type = OB_CLIENT_TYPE_NORMAL;
239 else if (!g_ascii_strcasecmp(type_str, "dialog"))
240 type = OB_CLIENT_TYPE_DIALOG;
241 else if (!g_ascii_strcasecmp(type_str, "splash"))
242 type = OB_CLIENT_TYPE_SPLASH;
243 else if (!g_ascii_strcasecmp(type_str, "utility"))
244 type = OB_CLIENT_TYPE_UTILITY;
245 else if (!g_ascii_strcasecmp(type_str, "menu"))
246 type = OB_CLIENT_TYPE_MENU;
247 else if (!g_ascii_strcasecmp(type_str, "toolbar"))
248 type = OB_CLIENT_TYPE_TOOLBAR;
249 else if (!g_ascii_strcasecmp(type_str, "dock"))
250 type = OB_CLIENT_TYPE_DOCK;
251 else if (!g_ascii_strcasecmp(type_str, "desktop"))
252 type = OB_CLIENT_TYPE_DESKTOP;
254 type_set = FALSE; /* not valid! */
257 if (class_set || name_set || role_set || title_set || type_set ||
258 group_class_set || group_name_set)
261 ObAppSettings *settings = config_create_app_settings();
264 settings->name = g_pattern_spec_new(name);
267 settings->class = g_pattern_spec_new(class);
270 settings->group_name = g_pattern_spec_new(group_name);
273 settings->group_class = g_pattern_spec_new(group_class);
276 settings->role = g_pattern_spec_new(role);
279 settings->title = g_pattern_spec_new(title);
282 settings->type = type;
284 if ((n = obt_xml_find_node(app->children, "decor")))
285 if (!obt_xml_node_contains(n, "default"))
286 settings->decor = obt_xml_node_bool(n);
288 if ((n = obt_xml_find_node(app->children, "shade")))
289 if (!obt_xml_node_contains(n, "default"))
290 settings->shade = obt_xml_node_bool(n);
292 if ((n = obt_xml_find_node(app->children, "position"))) {
293 if ((c = obt_xml_find_node(n->children, "x")))
294 if (!obt_xml_node_contains(c, "default")) {
295 config_parse_gravity_coord(c, &settings->position.x);
299 if (x_pos_given && (c = obt_xml_find_node(n->children, "y")))
300 if (!obt_xml_node_contains(c, "default")) {
301 config_parse_gravity_coord(c, &settings->position.y);
302 settings->pos_given = TRUE;
305 /* monitor can be set without setting x or y */
306 if ((c = obt_xml_find_node(n->children, "monitor")))
307 if (!obt_xml_node_contains(c, "default")) {
308 gchar *s = obt_xml_node_string(c);
309 if (!g_ascii_strcasecmp(s, "mouse"))
310 settings->monitor_type =
311 OB_PLACE_MONITOR_MOUSE;
312 else if (!g_ascii_strcasecmp(s, "active"))
313 settings->monitor_type =
314 OB_PLACE_MONITOR_ACTIVE;
315 else if (!g_ascii_strcasecmp(s, "primary"))
316 settings->monitor_type =
317 OB_PLACE_MONITOR_PRIMARY;
319 settings->monitor = obt_xml_node_int(c);
323 obt_xml_attr_bool(n, "force", &settings->pos_force);
326 if ((n = obt_xml_find_node(app->children, "focus")))
327 if (!obt_xml_node_contains(n, "default"))
328 settings->focus = obt_xml_node_bool(n);
330 if ((n = obt_xml_find_node(app->children, "desktop"))) {
331 if (!obt_xml_node_contains(n, "default")) {
332 gchar *s = obt_xml_node_string(n);
333 if (!g_ascii_strcasecmp(s, "all"))
334 settings->desktop = DESKTOP_ALL;
336 gint i = obt_xml_node_int(n);
338 settings->desktop = i;
344 if ((n = obt_xml_find_node(app->children, "layer")))
345 if (!obt_xml_node_contains(n, "default")) {
346 gchar *s = obt_xml_node_string(n);
347 if (!g_ascii_strcasecmp(s, "above"))
349 else if (!g_ascii_strcasecmp(s, "below"))
350 settings->layer = -1;
356 if ((n = obt_xml_find_node(app->children, "iconic")))
357 if (!obt_xml_node_contains(n, "default"))
358 settings->iconic = obt_xml_node_bool(n);
360 if ((n = obt_xml_find_node(app->children, "skip_pager")))
361 if (!obt_xml_node_contains(n, "default"))
362 settings->skip_pager = obt_xml_node_bool(n);
364 if ((n = obt_xml_find_node(app->children, "skip_taskbar")))
365 if (!obt_xml_node_contains(n, "default"))
366 settings->skip_taskbar = obt_xml_node_bool(n);
368 if ((n = obt_xml_find_node(app->children, "fullscreen")))
369 if (!obt_xml_node_contains(n, "default"))
370 settings->fullscreen = obt_xml_node_bool(n);
372 if ((n = obt_xml_find_node(app->children, "maximized")))
373 if (!obt_xml_node_contains(n, "default")) {
374 gchar *s = obt_xml_node_string(n);
375 if (!g_ascii_strcasecmp(s, "horizontal")) {
376 settings->max_horz = TRUE;
377 settings->max_vert = FALSE;
378 } else if (!g_ascii_strcasecmp(s, "vertical")) {
379 settings->max_horz = FALSE;
380 settings->max_vert = TRUE;
382 settings->max_horz = settings->max_vert =
383 obt_xml_node_bool(n);
387 config_per_app_settings = g_slist_append(config_per_app_settings,
388 (gpointer) settings);
396 name = class = group_name = group_class = role = title = type_str =
400 app = obt_xml_find_node(app->next, "application");
407 <action name="ChangeDesktop">
414 static void parse_key(xmlNodePtr node, GList *keylist)
416 gchar *keystring, **keys, **key;
418 gboolean is_chroot = FALSE;
420 if (!obt_xml_attr_string(node, "key", &keystring))
423 obt_xml_attr_bool(node, "chroot", &is_chroot);
425 keys = g_strsplit(keystring, " ", 0);
426 for (key = keys; *key; ++key) {
427 keylist = g_list_append(keylist, *key);
429 if ((n = obt_xml_find_node(node->children, "keybind"))) {
431 parse_key(n, keylist);
432 n = obt_xml_find_node(n->next, "keybind");
435 else if ((n = obt_xml_find_node(node->children, "action"))) {
437 ObActionsAct *action;
439 action = actions_parse(n);
441 keyboard_bind(keylist, action);
442 n = obt_xml_find_node(n->next, "action");
448 keyboard_chroot(keylist);
449 keylist = g_list_delete_link(keylist, g_list_last(keylist));
456 static void parse_keyboard(xmlNodePtr node, gpointer d)
461 keyboard_unbind_all();
463 if ((n = obt_xml_find_node(node->children, "chainQuitKey"))) {
464 key = obt_xml_node_string(n);
465 translate_key(key, &config_keyboard_reset_state,
466 &config_keyboard_reset_keycode);
470 if ((n = obt_xml_find_node(node->children, "keybind")))
473 n = obt_xml_find_node(n->next, "keybind");
479 <context name="Titlebar">
480 <mousebind button="Left" action="Press">
481 <action name="Raise"></action>
487 static void parse_mouse(xmlNodePtr node, gpointer d)
489 xmlNodePtr n, nbut, nact;
496 node = node->children;
498 if ((n = obt_xml_find_node(node, "dragThreshold")))
499 config_mouse_threshold = obt_xml_node_int(n);
500 if ((n = obt_xml_find_node(node, "doubleClickTime")))
501 config_mouse_dclicktime = obt_xml_node_int(n);
502 if ((n = obt_xml_find_node(node, "screenEdgeWarpTime"))) {
503 config_mouse_screenedgetime = obt_xml_node_int(n);
504 /* minimum value of 25 for this property, when it is 1 and you hit the
505 edge it basically never stops */
506 if (config_mouse_screenedgetime && config_mouse_screenedgetime < 25)
507 config_mouse_screenedgetime = 25;
509 if ((n = obt_xml_find_node(node, "screenEdgeWarpMouse")))
510 config_mouse_screenedgewarp = obt_xml_node_bool(n);
512 n = obt_xml_find_node(node, "context");
517 if (!obt_xml_attr_string(n, "name", &cxstr))
520 modcxstr = g_strdup(cxstr); /* make a copy to mutilate */
521 while (frame_next_context_from_string(modcxstr, &cx)) {
523 gchar *s = strchr(modcxstr, ' ');
526 g_message(_("Invalid context \"%s\" in mouse binding"),
533 nbut = obt_xml_find_node(n->children, "mousebind");
535 if (!obt_xml_attr_string(nbut, "button", &buttonstr))
537 if (obt_xml_attr_contains(nbut, "action", "press"))
538 mact = OB_MOUSE_ACTION_PRESS;
539 else if (obt_xml_attr_contains(nbut, "action", "release"))
540 mact = OB_MOUSE_ACTION_RELEASE;
541 else if (obt_xml_attr_contains(nbut, "action", "click"))
542 mact = OB_MOUSE_ACTION_CLICK;
543 else if (obt_xml_attr_contains(nbut, "action","doubleclick"))
544 mact = OB_MOUSE_ACTION_DOUBLE_CLICK;
545 else if (obt_xml_attr_contains(nbut, "action", "drag"))
546 mact = OB_MOUSE_ACTION_MOTION;
550 nact = obt_xml_find_node(nbut->children, "action");
552 ObActionsAct *action;
554 if ((action = actions_parse(nact)))
555 mouse_bind(buttonstr, cx, mact, action);
556 nact = obt_xml_find_node(nact->next, "action");
560 nbut = obt_xml_find_node(nbut->next, "mousebind");
566 n = obt_xml_find_node(n->next, "context");
570 static void parse_focus(xmlNodePtr node, gpointer d)
574 node = node->children;
576 if ((n = obt_xml_find_node(node, "focusNew")))
577 config_focus_new = obt_xml_node_bool(n);
578 if ((n = obt_xml_find_node(node, "followMouse")))
579 config_focus_follow = obt_xml_node_bool(n);
580 if ((n = obt_xml_find_node(node, "focusDelay")))
581 config_focus_delay = obt_xml_node_int(n);
582 if ((n = obt_xml_find_node(node, "raiseOnFocus")))
583 config_focus_raise = obt_xml_node_bool(n);
584 if ((n = obt_xml_find_node(node, "focusLast")))
585 config_focus_last = obt_xml_node_bool(n);
586 if ((n = obt_xml_find_node(node, "underMouse")))
587 config_focus_under_mouse = obt_xml_node_bool(n);
588 if ((n = obt_xml_find_node(node, "unfocusOnLeave")))
589 config_unfocus_leave = obt_xml_node_bool(n);
592 static void parse_placement(xmlNodePtr node, gpointer d)
596 node = node->children;
598 if ((n = obt_xml_find_node(node, "policy")))
599 if (obt_xml_node_contains(n, "UnderMouse"))
600 config_place_policy = OB_PLACE_POLICY_MOUSE;
601 if ((n = obt_xml_find_node(node, "center")))
602 config_place_center = obt_xml_node_bool(n);
603 if ((n = obt_xml_find_node(node, "monitor"))) {
604 if (obt_xml_node_contains(n, "active"))
605 config_place_monitor = OB_PLACE_MONITOR_ACTIVE;
606 else if (obt_xml_node_contains(n, "mouse"))
607 config_place_monitor = OB_PLACE_MONITOR_MOUSE;
608 else if (obt_xml_node_contains(n, "any"))
609 config_place_monitor = OB_PLACE_MONITOR_ANY;
611 if ((n = obt_xml_find_node(node, "primaryMonitor"))) {
612 config_primary_monitor_index = obt_xml_node_int(n);
613 if (!config_primary_monitor_index) {
614 if (obt_xml_node_contains(n, "mouse"))
615 config_primary_monitor = OB_PLACE_MONITOR_MOUSE;
620 static void parse_margins(xmlNodePtr node, gpointer d)
624 node = node->children;
626 if ((n = obt_xml_find_node(node, "top")))
627 config_margins.top = MAX(0, obt_xml_node_int(n));
628 if ((n = obt_xml_find_node(node, "left")))
629 config_margins.left = MAX(0, obt_xml_node_int(n));
630 if ((n = obt_xml_find_node(node, "right")))
631 config_margins.right = MAX(0, obt_xml_node_int(n));
632 if ((n = obt_xml_find_node(node, "bottom")))
633 config_margins.bottom = MAX(0, obt_xml_node_int(n));
636 static void parse_theme(xmlNodePtr node, gpointer d)
640 node = node->children;
642 if ((n = obt_xml_find_node(node, "name"))) {
645 g_free(config_theme);
646 c = obt_xml_node_string(n);
647 config_theme = obt_paths_expand_tilde(c);
650 if ((n = obt_xml_find_node(node, "titleLayout"))) {
653 g_free(config_title_layout);
654 config_title_layout = obt_xml_node_string(n);
656 /* replace duplicates with spaces */
657 for (c = config_title_layout; *c != '\0'; ++c)
658 for (d = c+1; *d != '\0'; ++d)
659 if (*c == *d) *d = ' ';
661 if ((n = obt_xml_find_node(node, "keepBorder")))
662 config_theme_keepborder = obt_xml_node_bool(n);
663 if ((n = obt_xml_find_node(node, "animateIconify")))
664 config_animate_iconify = obt_xml_node_bool(n);
665 if ((n = obt_xml_find_node(node, "windowListIconSize"))) {
666 config_theme_window_list_icon_size = obt_xml_node_int(n);
667 if (config_theme_window_list_icon_size < 16)
668 config_theme_window_list_icon_size = 16;
669 else if (config_theme_window_list_icon_size > 96)
670 config_theme_window_list_icon_size = 96;
673 n = obt_xml_find_node(node, "font");
677 gchar *name = g_strdup(RrDefaultFontFamily);
678 gint size = RrDefaultFontSize;
679 RrFontWeight weight = RrDefaultFontWeight;
680 RrFontSlant slant = RrDefaultFontSlant;
682 if (obt_xml_attr_contains(n, "place", "ActiveWindow"))
683 font = &config_font_activewindow;
684 else if (obt_xml_attr_contains(n, "place", "InactiveWindow"))
685 font = &config_font_inactivewindow;
686 else if (obt_xml_attr_contains(n, "place", "MenuHeader"))
687 font = &config_font_menutitle;
688 else if (obt_xml_attr_contains(n, "place", "MenuItem"))
689 font = &config_font_menuitem;
690 else if (obt_xml_attr_contains(n, "place", "ActiveOnScreenDisplay"))
691 font = &config_font_activeosd;
692 else if (obt_xml_attr_contains(n, "place", "OnScreenDisplay"))
693 font = &config_font_activeosd;
694 else if (obt_xml_attr_contains(n, "place","InactiveOnScreenDisplay"))
695 font = &config_font_inactiveosd;
699 if ((fnode = obt_xml_find_node(n->children, "name"))) {
701 name = obt_xml_node_string(fnode);
703 if ((fnode = obt_xml_find_node(n->children, "size"))) {
704 int s = obt_xml_node_int(fnode);
707 if ((fnode = obt_xml_find_node(n->children, "weight"))) {
708 gchar *w = obt_xml_node_string(fnode);
709 if (!g_ascii_strcasecmp(w, "Bold"))
710 weight = RR_FONTWEIGHT_BOLD;
713 if ((fnode = obt_xml_find_node(n->children, "slant"))) {
714 gchar *s = obt_xml_node_string(fnode);
715 if (!g_ascii_strcasecmp(s, "Italic"))
716 slant = RR_FONTSLANT_ITALIC;
717 if (!g_ascii_strcasecmp(s, "Oblique"))
718 slant = RR_FONTSLANT_OBLIQUE;
722 *font = RrFontOpen(ob_rr_inst, name, size, weight, slant);
725 n = obt_xml_find_node(n->next, "font");
729 static void parse_desktops(xmlNodePtr node, gpointer d)
733 node = node->children;
735 if ((n = obt_xml_find_node(node, "number"))) {
736 gint d = obt_xml_node_int(n);
738 config_desktops_num = (unsigned) d;
740 if ((n = obt_xml_find_node(node, "firstdesk"))) {
741 gint d = obt_xml_node_int(n);
743 config_screen_firstdesk = (unsigned) d;
745 if ((n = obt_xml_find_node(node, "names"))) {
749 for (it = config_desktops_names; it; it = it->next)
751 g_slist_free(config_desktops_names);
752 config_desktops_names = NULL;
754 nname = obt_xml_find_node(n->children, "name");
756 config_desktops_names =
757 g_slist_append(config_desktops_names,
758 obt_xml_node_string(nname));
759 nname = obt_xml_find_node(nname->next, "name");
762 if ((n = obt_xml_find_node(node, "popupTime")))
763 config_desktop_popup_time = obt_xml_node_int(n);
766 static void parse_resize(xmlNodePtr node, gpointer d)
770 node = node->children;
772 if ((n = obt_xml_find_node(node, "drawContents")))
773 config_resize_redraw = obt_xml_node_bool(n);
774 if ((n = obt_xml_find_node(node, "popupShow"))) {
775 config_resize_popup_show = obt_xml_node_int(n);
776 if (obt_xml_node_contains(n, "Always"))
777 config_resize_popup_show = 2;
778 else if (obt_xml_node_contains(n, "Never"))
779 config_resize_popup_show = 0;
780 else if (obt_xml_node_contains(n, "Nonpixel"))
781 config_resize_popup_show = 1;
783 if ((n = obt_xml_find_node(node, "popupPosition"))) {
784 if (obt_xml_node_contains(n, "Top"))
785 config_resize_popup_pos = OB_RESIZE_POS_TOP;
786 else if (obt_xml_node_contains(n, "Center"))
787 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
788 else if (obt_xml_node_contains(n, "Fixed")) {
789 config_resize_popup_pos = OB_RESIZE_POS_FIXED;
791 if ((n = obt_xml_find_node(node, "popupFixedPosition"))) {
794 if ((n2 = obt_xml_find_node(n->children, "x")))
795 config_parse_gravity_coord(n2,
796 &config_resize_popup_fixed.x);
797 if ((n2 = obt_xml_find_node(n->children, "y")))
798 config_parse_gravity_coord(n2,
799 &config_resize_popup_fixed.y);
801 config_resize_popup_fixed.x.pos =
802 MAX(config_resize_popup_fixed.x.pos, 0);
803 config_resize_popup_fixed.y.pos =
804 MAX(config_resize_popup_fixed.y.pos, 0);
810 static void parse_dock(xmlNodePtr node, gpointer d)
814 node = node->children;
816 if ((n = obt_xml_find_node(node, "position"))) {
817 if (obt_xml_node_contains(n, "TopLeft"))
818 config_dock_floating = FALSE,
819 config_dock_pos = OB_DIRECTION_NORTHWEST;
820 else if (obt_xml_node_contains(n, "Top"))
821 config_dock_floating = FALSE,
822 config_dock_pos = OB_DIRECTION_NORTH;
823 else if (obt_xml_node_contains(n, "TopRight"))
824 config_dock_floating = FALSE,
825 config_dock_pos = OB_DIRECTION_NORTHEAST;
826 else if (obt_xml_node_contains(n, "Right"))
827 config_dock_floating = FALSE,
828 config_dock_pos = OB_DIRECTION_EAST;
829 else if (obt_xml_node_contains(n, "BottomRight"))
830 config_dock_floating = FALSE,
831 config_dock_pos = OB_DIRECTION_SOUTHEAST;
832 else if (obt_xml_node_contains(n, "Bottom"))
833 config_dock_floating = FALSE,
834 config_dock_pos = OB_DIRECTION_SOUTH;
835 else if (obt_xml_node_contains(n, "BottomLeft"))
836 config_dock_floating = FALSE,
837 config_dock_pos = OB_DIRECTION_SOUTHWEST;
838 else if (obt_xml_node_contains(n, "Left"))
839 config_dock_floating = FALSE,
840 config_dock_pos = OB_DIRECTION_WEST;
841 else if (obt_xml_node_contains(n, "Floating"))
842 config_dock_floating = TRUE;
844 if (config_dock_floating) {
845 if ((n = obt_xml_find_node(node, "floatingX")))
846 config_dock_x = obt_xml_node_int(n);
847 if ((n = obt_xml_find_node(node, "floatingY")))
848 config_dock_y = obt_xml_node_int(n);
850 if ((n = obt_xml_find_node(node, "noStrut")))
851 config_dock_nostrut = obt_xml_node_bool(n);
853 if ((n = obt_xml_find_node(node, "stacking"))) {
854 if (obt_xml_node_contains(n, "normal"))
855 config_dock_layer = OB_STACKING_LAYER_NORMAL;
856 else if (obt_xml_node_contains(n, "below"))
857 config_dock_layer = OB_STACKING_LAYER_BELOW;
858 else if (obt_xml_node_contains(n, "above"))
859 config_dock_layer = OB_STACKING_LAYER_ABOVE;
861 if ((n = obt_xml_find_node(node, "direction"))) {
862 if (obt_xml_node_contains(n, "horizontal"))
863 config_dock_orient = OB_ORIENTATION_HORZ;
864 else if (obt_xml_node_contains(n, "vertical"))
865 config_dock_orient = OB_ORIENTATION_VERT;
867 if ((n = obt_xml_find_node(node, "autoHide")))
868 config_dock_hide = obt_xml_node_bool(n);
869 if ((n = obt_xml_find_node(node, "hideDelay")))
870 config_dock_hide_delay = obt_xml_node_int(n);
871 if ((n = obt_xml_find_node(node, "showDelay")))
872 config_dock_show_delay = obt_xml_node_int(n);
873 if ((n = obt_xml_find_node(node, "moveButton"))) {
874 gchar *str = obt_xml_node_string(n);
876 if (translate_button(str, &s, &b)) {
877 config_dock_app_move_button = b;
878 config_dock_app_move_modifiers = s;
880 g_message(_("Invalid button \"%s\" specified in config file"), str);
886 static void parse_menu(xmlNodePtr node, gpointer d)
889 node = node->children;
891 if ((n = obt_xml_find_node(node, "hideDelay")))
892 config_menu_hide_delay = obt_xml_node_int(n);
893 if ((n = obt_xml_find_node(node, "middle")))
894 config_menu_middle = obt_xml_node_bool(n);
895 if ((n = obt_xml_find_node(node, "submenuShowDelay")))
896 config_submenu_show_delay = obt_xml_node_int(n);
897 if ((n = obt_xml_find_node(node, "submenuHideDelay")))
898 config_submenu_hide_delay = obt_xml_node_int(n);
899 if ((n = obt_xml_find_node(node, "manageDesktops")))
900 config_menu_manage_desktops = obt_xml_node_bool(n);
901 if ((n = obt_xml_find_node(node, "showIcons"))) {
902 config_menu_show_icons = obt_xml_node_bool(n);
904 if (config_menu_show_icons)
905 g_message(_("Openbox was compiled without Imlib2 image loading support. Icons in menus will not be loaded."));
909 while ((node = obt_xml_find_node(node, "file"))) {
910 gchar *c = obt_xml_node_string(node);
911 config_menu_files = g_slist_append(config_menu_files,
912 obt_paths_expand_tilde(c));
918 static void parse_resistance(xmlNodePtr node, gpointer d)
922 node = node->children;
923 if ((n = obt_xml_find_node(node, "strength")))
924 config_resist_win = obt_xml_node_int(n);
925 if ((n = obt_xml_find_node(node, "screen_edge_strength")))
926 config_resist_edge = obt_xml_node_int(n);
932 const gchar *actname;
935 static void bind_default_keyboard(void)
938 ObDefKeyBind binds[] = {
939 { "A-Tab", "NextWindow" },
940 { "S-A-Tab", "PreviousWindow" },
944 for (it = binds; it->key; ++it) {
945 GList *l = g_list_append(NULL, g_strdup(it->key));
946 keyboard_bind(l, actions_parse_string(it->actname));
953 const gchar *context;
954 const ObMouseAction mact;
955 const gchar *actname;
958 static void bind_default_mouse(void)
961 ObDefMouseBind binds[] = {
962 { "Left", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
963 { "Middle", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
964 { "Right", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
965 { "Left", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
966 { "Middle", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
967 { "Right", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
968 { "Left", "Titlebar", OB_MOUSE_ACTION_PRESS, "Focus" },
969 { "Left", "Bottom", OB_MOUSE_ACTION_PRESS, "Focus" },
970 { "Left", "BLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
971 { "Left", "BRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
972 { "Left", "TLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
973 { "Left", "TRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
974 { "Left", "Close", OB_MOUSE_ACTION_PRESS, "Focus" },
975 { "Left", "Maximize", OB_MOUSE_ACTION_PRESS, "Focus" },
976 { "Left", "Iconify", OB_MOUSE_ACTION_PRESS, "Focus" },
977 { "Left", "Icon", OB_MOUSE_ACTION_PRESS, "Focus" },
978 { "Left", "AllDesktops", OB_MOUSE_ACTION_PRESS, "Focus" },
979 { "Left", "Shade", OB_MOUSE_ACTION_PRESS, "Focus" },
980 { "Left", "Client", OB_MOUSE_ACTION_CLICK, "Raise" },
981 { "Left", "Titlebar", OB_MOUSE_ACTION_CLICK, "Raise" },
982 { "Middle", "Titlebar", OB_MOUSE_ACTION_CLICK, "Lower" },
983 { "Left", "BLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
984 { "Left", "BRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
985 { "Left", "TLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
986 { "Left", "TRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
987 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Raise" },
988 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "Raise" },
989 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Raise" },
990 { "Left", "Icon", OB_MOUSE_ACTION_CLICK, "Raise" },
991 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "Raise" },
992 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "Raise" },
993 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Close" },
994 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "ToggleMaximize" },
995 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Iconify" },
996 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "ToggleOmnipresent" },
997 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "ToggleShade" },
998 { "Left", "TLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
999 { "Left", "TRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
1000 { "Left", "BLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
1001 { "Left", "BRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
1002 { "Left", "Top", OB_MOUSE_ACTION_MOTION, "Resize" },
1003 { "Left", "Bottom", OB_MOUSE_ACTION_MOTION, "Resize" },
1004 { "Left", "Left", OB_MOUSE_ACTION_MOTION, "Resize" },
1005 { "Left", "Right", OB_MOUSE_ACTION_MOTION, "Resize" },
1006 { "Left", "Titlebar", OB_MOUSE_ACTION_MOTION, "Move" },
1007 { "A-Left", "Frame", OB_MOUSE_ACTION_MOTION, "Move" },
1008 { "A-Middle", "Frame", OB_MOUSE_ACTION_MOTION, "Resize" },
1009 { NULL, NULL, 0, NULL }
1012 for (it = binds; it->button; ++it)
1013 mouse_bind(it->button, frame_context_from_string(it->context),
1014 it->mact, actions_parse_string(it->actname));
1017 void config_startup(ObtXmlInst *i)
1019 config_focus_new = TRUE;
1020 config_focus_follow = FALSE;
1021 config_focus_delay = 0;
1022 config_focus_raise = FALSE;
1023 config_focus_last = TRUE;
1024 config_focus_under_mouse = FALSE;
1025 config_unfocus_leave = FALSE;
1027 obt_xml_register(i, "focus", parse_focus, NULL);
1029 config_place_policy = OB_PLACE_POLICY_SMART;
1030 config_place_center = TRUE;
1031 config_place_monitor = OB_PLACE_MONITOR_PRIMARY;
1033 config_primary_monitor_index = 1;
1034 config_primary_monitor = OB_PLACE_MONITOR_ACTIVE;
1036 obt_xml_register(i, "placement", parse_placement, NULL);
1038 STRUT_PARTIAL_SET(config_margins, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1040 obt_xml_register(i, "margins", parse_margins, NULL);
1042 config_theme = NULL;
1044 config_animate_iconify = TRUE;
1045 config_title_layout = g_strdup("NLIMC");
1046 config_theme_keepborder = TRUE;
1047 config_theme_window_list_icon_size = 36;
1049 config_font_activewindow = NULL;
1050 config_font_inactivewindow = NULL;
1051 config_font_menuitem = NULL;
1052 config_font_menutitle = NULL;
1053 config_font_activeosd = NULL;
1054 config_font_inactiveosd = NULL;
1056 obt_xml_register(i, "theme", parse_theme, NULL);
1058 config_desktops_num = 4;
1059 config_screen_firstdesk = 1;
1060 config_desktops_names = NULL;
1061 config_desktop_popup_time = 875;
1063 obt_xml_register(i, "desktops", parse_desktops, NULL);
1065 config_resize_redraw = TRUE;
1066 config_resize_popup_show = 1; /* nonpixel increments */
1067 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
1068 GRAVITY_COORD_SET(config_resize_popup_fixed.x, 0, FALSE, FALSE);
1069 GRAVITY_COORD_SET(config_resize_popup_fixed.y, 0, FALSE, FALSE);
1071 obt_xml_register(i, "resize", parse_resize, NULL);
1073 config_dock_layer = OB_STACKING_LAYER_ABOVE;
1074 config_dock_pos = OB_DIRECTION_NORTHEAST;
1075 config_dock_floating = FALSE;
1076 config_dock_nostrut = FALSE;
1079 config_dock_orient = OB_ORIENTATION_VERT;
1080 config_dock_hide = FALSE;
1081 config_dock_hide_delay = 300;
1082 config_dock_show_delay = 300;
1083 config_dock_app_move_button = 2; /* middle */
1084 config_dock_app_move_modifiers = 0;
1086 obt_xml_register(i, "dock", parse_dock, NULL);
1088 translate_key("C-g", &config_keyboard_reset_state,
1089 &config_keyboard_reset_keycode);
1091 bind_default_keyboard();
1093 obt_xml_register(i, "keyboard", parse_keyboard, NULL);
1095 config_mouse_threshold = 8;
1096 config_mouse_dclicktime = 500;
1097 config_mouse_screenedgetime = 400;
1098 config_mouse_screenedgewarp = FALSE;
1100 bind_default_mouse();
1102 obt_xml_register(i, "mouse", parse_mouse, NULL);
1104 config_resist_win = 10;
1105 config_resist_edge = 20;
1107 obt_xml_register(i, "resistance", parse_resistance, NULL);
1109 config_menu_hide_delay = 250;
1110 config_menu_middle = FALSE;
1111 config_submenu_show_delay = 100;
1112 config_submenu_hide_delay = 400;
1113 config_menu_manage_desktops = TRUE;
1114 config_menu_files = NULL;
1115 config_menu_show_icons = TRUE;
1117 obt_xml_register(i, "menu", parse_menu, NULL);
1119 config_per_app_settings = NULL;
1121 obt_xml_register(i, "applications", parse_per_app_settings, NULL);
1124 void config_shutdown(void)
1128 g_free(config_theme);
1130 g_free(config_title_layout);
1132 RrFontClose(config_font_activewindow);
1133 RrFontClose(config_font_inactivewindow);
1134 RrFontClose(config_font_menuitem);
1135 RrFontClose(config_font_menutitle);
1136 RrFontClose(config_font_activeosd);
1137 RrFontClose(config_font_inactiveosd);
1139 for (it = config_desktops_names; it; it = g_slist_next(it))
1141 g_slist_free(config_desktops_names);
1143 for (it = config_menu_files; it; it = g_slist_next(it))
1145 g_slist_free(config_menu_files);
1147 for (it = config_per_app_settings; it; it = g_slist_next(it)) {
1148 ObAppSettings *itd = (ObAppSettings *)it->data;
1149 if (itd->name) g_pattern_spec_free(itd->name);
1150 if (itd->role) g_pattern_spec_free(itd->role);
1151 if (itd->title) g_pattern_spec_free(itd->title);
1152 if (itd->class) g_pattern_spec_free(itd->class);
1153 if (itd->group_name) g_pattern_spec_free(itd->group_name);
1154 if (itd->group_class) g_pattern_spec_free(itd->group_class);
1155 g_slice_free(ObAppSettings, it->data);
1157 g_slist_free(config_per_app_settings);