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 = -1;
117 settings->focus = -1;
118 settings->desktop = 0;
119 settings->layer = -2;
120 settings->iconic = -1;
121 settings->skip_pager = -1;
122 settings->skip_taskbar = -1;
123 settings->fullscreen = -1;
124 settings->max_horz = -1;
125 settings->max_vert = -1;
129 #define copy_if(setting, default) \
130 if (src->setting != default) dst->setting = src->setting
131 void config_app_settings_copy_non_defaults(const ObAppSettings *src,
134 g_assert(src != NULL);
135 g_assert(dst != NULL);
137 copy_if(type, (ObClientType)-1);
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, meaning the
206 monitor the pointer is on. Default: mouse.
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,
219 gboolean name_set, class_set, type_set, role_set, title_set;
221 gboolean x_pos_given;
226 class_set = obt_xml_attr_string(app, "class", &class);
227 name_set = obt_xml_attr_string(app, "name", &name);
228 type_set = obt_xml_attr_string(app, "type", &type_str);
229 role_set = obt_xml_attr_string(app, "role", &role);
230 title_set = obt_xml_attr_string(app, "title", &title);
232 /* validate the type tho */
234 if (!g_ascii_strcasecmp(type_str, "normal"))
235 type = OB_CLIENT_TYPE_NORMAL;
236 else if (!g_ascii_strcasecmp(type_str, "dialog"))
237 type = OB_CLIENT_TYPE_DIALOG;
238 else if (!g_ascii_strcasecmp(type_str, "splash"))
239 type = OB_CLIENT_TYPE_SPLASH;
240 else if (!g_ascii_strcasecmp(type_str, "utility"))
241 type = OB_CLIENT_TYPE_UTILITY;
242 else if (!g_ascii_strcasecmp(type_str, "menu"))
243 type = OB_CLIENT_TYPE_MENU;
244 else if (!g_ascii_strcasecmp(type_str, "toolbar"))
245 type = OB_CLIENT_TYPE_TOOLBAR;
246 else if (!g_ascii_strcasecmp(type_str, "dock"))
247 type = OB_CLIENT_TYPE_DOCK;
248 else if (!g_ascii_strcasecmp(type_str, "desktop"))
249 type = OB_CLIENT_TYPE_DESKTOP;
251 type_set = FALSE; /* not valid! */
254 if (class_set || name_set || role_set || title_set || type_set) {
256 ObAppSettings *settings = config_create_app_settings();
259 settings->name = g_pattern_spec_new(name);
262 settings->class = g_pattern_spec_new(class);
265 settings->role = g_pattern_spec_new(role);
268 settings->title = g_pattern_spec_new(title);
271 settings->type = type;
273 if ((n = obt_xml_find_node(app->children, "decor")))
274 if (!obt_xml_node_contains(n, "default"))
275 settings->decor = obt_xml_node_bool(n);
277 if ((n = obt_xml_find_node(app->children, "shade")))
278 if (!obt_xml_node_contains(n, "default"))
279 settings->shade = obt_xml_node_bool(n);
281 if ((n = obt_xml_find_node(app->children, "position"))) {
282 if ((c = obt_xml_find_node(n->children, "x")))
283 if (!obt_xml_node_contains(c, "default")) {
284 config_parse_gravity_coord(c, &settings->position.x);
288 if (x_pos_given && (c = obt_xml_find_node(n->children, "y")))
289 if (!obt_xml_node_contains(c, "default")) {
290 config_parse_gravity_coord(c, &settings->position.y);
291 settings->pos_given = TRUE;
294 if (settings->pos_given &&
295 (c = obt_xml_find_node(n->children, "monitor")))
296 if (!obt_xml_node_contains(c, "default")) {
297 gchar *s = obt_xml_node_string(c);
298 if (!g_ascii_strcasecmp(s, "mouse"))
299 settings->monitor = 0;
301 settings->monitor = obt_xml_node_int(c);
305 obt_xml_attr_bool(n, "force", &settings->pos_force);
308 if ((n = obt_xml_find_node(app->children, "focus")))
309 if (!obt_xml_node_contains(n, "default"))
310 settings->focus = obt_xml_node_bool(n);
312 if ((n = obt_xml_find_node(app->children, "desktop"))) {
313 if (!obt_xml_node_contains(n, "default")) {
314 gchar *s = obt_xml_node_string(n);
315 if (!g_ascii_strcasecmp(s, "all"))
316 settings->desktop = DESKTOP_ALL;
318 gint i = obt_xml_node_int(n);
320 settings->desktop = i;
326 if ((n = obt_xml_find_node(app->children, "layer")))
327 if (!obt_xml_node_contains(n, "default")) {
328 gchar *s = obt_xml_node_string(n);
329 if (!g_ascii_strcasecmp(s, "above"))
331 else if (!g_ascii_strcasecmp(s, "below"))
332 settings->layer = -1;
338 if ((n = obt_xml_find_node(app->children, "iconic")))
339 if (!obt_xml_node_contains(n, "default"))
340 settings->iconic = obt_xml_node_bool(n);
342 if ((n = obt_xml_find_node(app->children, "skip_pager")))
343 if (!obt_xml_node_contains(n, "default"))
344 settings->skip_pager = obt_xml_node_bool(n);
346 if ((n = obt_xml_find_node(app->children, "skip_taskbar")))
347 if (!obt_xml_node_contains(n, "default"))
348 settings->skip_taskbar = obt_xml_node_bool(n);
350 if ((n = obt_xml_find_node(app->children, "fullscreen")))
351 if (!obt_xml_node_contains(n, "default"))
352 settings->fullscreen = obt_xml_node_bool(n);
354 if ((n = obt_xml_find_node(app->children, "maximized")))
355 if (!obt_xml_node_contains(n, "default")) {
356 gchar *s = obt_xml_node_string(n);
357 if (!g_ascii_strcasecmp(s, "horizontal")) {
358 settings->max_horz = TRUE;
359 settings->max_vert = FALSE;
360 } else if (!g_ascii_strcasecmp(s, "vertical")) {
361 settings->max_horz = FALSE;
362 settings->max_vert = TRUE;
364 settings->max_horz = settings->max_vert =
365 obt_xml_node_bool(n);
369 config_per_app_settings = g_slist_append(config_per_app_settings,
370 (gpointer) settings);
376 name = class = role = title = type_str = NULL;
379 app = obt_xml_find_node(app->next, "application");
386 <action name="ChangeDesktop">
393 static void parse_key(xmlNodePtr node, GList *keylist)
395 gchar *keystring, **keys, **key;
397 gboolean is_chroot = FALSE;
399 if (!obt_xml_attr_string(node, "key", &keystring))
402 obt_xml_attr_bool(node, "chroot", &is_chroot);
404 keys = g_strsplit(keystring, " ", 0);
405 for (key = keys; *key; ++key) {
406 keylist = g_list_append(keylist, *key);
408 if ((n = obt_xml_find_node(node->children, "keybind"))) {
410 parse_key(n, keylist);
411 n = obt_xml_find_node(n->next, "keybind");
414 else if ((n = obt_xml_find_node(node->children, "action"))) {
417 ObActionList *actions;
420 c = xmlNodeGetContent(node);
421 p = action_parser_new();
422 actions = action_parser_read_string(p, (gchar*)c);
424 action_parser_unref(p);
427 keyboard_bind(keylist, actions);
429 action_list_unref(actions);
430 n = obt_xml_find_node(n->next, "action");
436 keyboard_chroot(keylist);
437 keylist = g_list_delete_link(keylist, g_list_last(keylist));
444 static void parse_keyboard(xmlNodePtr node, gpointer d)
449 keyboard_unbind_all();
451 if ((n = obt_xml_find_node(node->children, "chainQuitKey"))) {
452 key = obt_xml_node_string(n);
453 translate_key(key, &config_keyboard_reset_state,
454 &config_keyboard_reset_keycode);
458 if ((n = obt_xml_find_node(node->children, "keybind")))
461 n = obt_xml_find_node(n->next, "keybind");
467 <context name="Titlebar">
468 <mousebind button="Left" action="Press">
469 <action name="Raise"></action>
475 static void parse_mouse(xmlNodePtr node, gpointer d)
477 xmlNodePtr n, nbut, nact;
484 node = node->children;
486 if ((n = obt_xml_find_node(node, "dragThreshold")))
487 config_mouse_threshold = obt_xml_node_int(n);
488 if ((n = obt_xml_find_node(node, "doubleClickTime")))
489 config_mouse_dclicktime = obt_xml_node_int(n);
490 if ((n = obt_xml_find_node(node, "screenEdgeWarpTime"))) {
491 config_mouse_screenedgetime = obt_xml_node_int(n);
492 /* minimum value of 25 for this property, when it is 1 and you hit the
493 edge it basically never stops */
494 if (config_mouse_screenedgetime && config_mouse_screenedgetime < 25)
495 config_mouse_screenedgetime = 25;
497 if ((n = obt_xml_find_node(node, "screenEdgeWarpMouse")))
498 config_mouse_screenedgewarp = obt_xml_node_bool(n);
500 n = obt_xml_find_node(node, "context");
505 if (!obt_xml_attr_string(n, "name", &cxstr))
508 modcxstr = g_strdup(cxstr); /* make a copy to mutilate */
509 while (frame_next_context_from_string(modcxstr, &cx)) {
511 gchar *s = strchr(modcxstr, ' ');
514 g_message(_("Invalid context \"%s\" in mouse binding"),
521 nbut = obt_xml_find_node(n->children, "mousebind");
523 if (!obt_xml_attr_string(nbut, "button", &buttonstr))
525 if (obt_xml_attr_contains(nbut, "action", "press"))
526 mact = OB_MOUSE_ACTION_PRESS;
527 else if (obt_xml_attr_contains(nbut, "action", "release"))
528 mact = OB_MOUSE_ACTION_RELEASE;
529 else if (obt_xml_attr_contains(nbut, "action", "click"))
530 mact = OB_MOUSE_ACTION_CLICK;
531 else if (obt_xml_attr_contains(nbut, "action","doubleclick"))
532 mact = OB_MOUSE_ACTION_DOUBLE_CLICK;
533 else if (obt_xml_attr_contains(nbut, "action", "drag"))
534 mact = OB_MOUSE_ACTION_MOTION;
538 nact = obt_xml_find_node(nbut->children, "action");
540 ObActionList *actions;
544 c = xmlNodeGetContent(nact);
545 p = action_parser_new();
546 if ((actions = action_parser_read_string(p, (gchar*)c)))
547 mouse_bind(buttonstr, cx, mact, actions);
548 nact = obt_xml_find_node(nact->next, "action");
549 action_list_unref(actions);
551 action_parser_unref(p);
555 nbut = obt_xml_find_node(nbut->next, "mousebind");
561 n = obt_xml_find_node(n->next, "context");
565 static void parse_focus(xmlNodePtr node, gpointer d)
569 node = node->children;
571 if ((n = obt_xml_find_node(node, "focusNew")))
572 config_focus_new = obt_xml_node_bool(n);
573 if ((n = obt_xml_find_node(node, "followMouse")))
574 config_focus_follow = obt_xml_node_bool(n);
575 if ((n = obt_xml_find_node(node, "focusDelay")))
576 config_focus_delay = obt_xml_node_int(n);
577 if ((n = obt_xml_find_node(node, "raiseOnFocus")))
578 config_focus_raise = obt_xml_node_bool(n);
579 if ((n = obt_xml_find_node(node, "focusLast")))
580 config_focus_last = obt_xml_node_bool(n);
581 if ((n = obt_xml_find_node(node, "underMouse")))
582 config_focus_under_mouse = obt_xml_node_bool(n);
583 if ((n = obt_xml_find_node(node, "unfocusOnLeave")))
584 config_unfocus_leave = obt_xml_node_bool(n);
587 static void parse_placement(xmlNodePtr node, gpointer d)
591 node = node->children;
593 if ((n = obt_xml_find_node(node, "policy")))
594 if (obt_xml_node_contains(n, "UnderMouse"))
595 config_place_policy = OB_PLACE_POLICY_MOUSE;
596 if ((n = obt_xml_find_node(node, "center")))
597 config_place_center = obt_xml_node_bool(n);
598 if ((n = obt_xml_find_node(node, "monitor"))) {
599 if (obt_xml_node_contains(n, "active"))
600 config_place_monitor = OB_PLACE_MONITOR_ACTIVE;
601 else if (obt_xml_node_contains(n, "mouse"))
602 config_place_monitor = OB_PLACE_MONITOR_MOUSE;
603 else if (obt_xml_node_contains(n, "any"))
604 config_place_monitor = OB_PLACE_MONITOR_ANY;
606 if ((n = obt_xml_find_node(node, "primaryMonitor"))) {
607 config_primary_monitor_index = obt_xml_node_int(n);
608 if (!config_primary_monitor_index) {
609 if (obt_xml_node_contains(n, "mouse"))
610 config_primary_monitor = OB_PLACE_MONITOR_MOUSE;
615 static void parse_margins(xmlNodePtr node, gpointer d)
619 node = node->children;
621 if ((n = obt_xml_find_node(node, "top")))
622 config_margins.top = MAX(0, obt_xml_node_int(n));
623 if ((n = obt_xml_find_node(node, "left")))
624 config_margins.left = MAX(0, obt_xml_node_int(n));
625 if ((n = obt_xml_find_node(node, "right")))
626 config_margins.right = MAX(0, obt_xml_node_int(n));
627 if ((n = obt_xml_find_node(node, "bottom")))
628 config_margins.bottom = MAX(0, obt_xml_node_int(n));
631 static void parse_theme(xmlNodePtr node, gpointer d)
635 node = node->children;
637 if ((n = obt_xml_find_node(node, "name"))) {
640 g_free(config_theme);
641 c = obt_xml_node_string(n);
642 config_theme = obt_paths_expand_tilde(c);
645 if ((n = obt_xml_find_node(node, "titleLayout"))) {
648 g_free(config_title_layout);
649 config_title_layout = obt_xml_node_string(n);
651 /* replace duplicates with spaces */
652 for (c = config_title_layout; *c != '\0'; ++c)
653 for (d = c+1; *d != '\0'; ++d)
654 if (*c == *d) *d = ' ';
656 if ((n = obt_xml_find_node(node, "keepBorder")))
657 config_theme_keepborder = obt_xml_node_bool(n);
658 if ((n = obt_xml_find_node(node, "animateIconify")))
659 config_animate_iconify = obt_xml_node_bool(n);
660 if ((n = obt_xml_find_node(node, "windowListIconSize"))) {
661 config_theme_window_list_icon_size = obt_xml_node_int(n);
662 if (config_theme_window_list_icon_size < 16)
663 config_theme_window_list_icon_size = 16;
664 else if (config_theme_window_list_icon_size > 96)
665 config_theme_window_list_icon_size = 96;
668 n = obt_xml_find_node(node, "font");
672 gchar *name = g_strdup(RrDefaultFontFamily);
673 gint size = RrDefaultFontSize;
674 RrFontWeight weight = RrDefaultFontWeight;
675 RrFontSlant slant = RrDefaultFontSlant;
677 if (obt_xml_attr_contains(n, "place", "ActiveWindow"))
678 font = &config_font_activewindow;
679 else if (obt_xml_attr_contains(n, "place", "InactiveWindow"))
680 font = &config_font_inactivewindow;
681 else if (obt_xml_attr_contains(n, "place", "MenuHeader"))
682 font = &config_font_menutitle;
683 else if (obt_xml_attr_contains(n, "place", "MenuItem"))
684 font = &config_font_menuitem;
685 else if (obt_xml_attr_contains(n, "place", "ActiveOnScreenDisplay"))
686 font = &config_font_activeosd;
687 else if (obt_xml_attr_contains(n, "place", "OnScreenDisplay"))
688 font = &config_font_activeosd;
689 else if (obt_xml_attr_contains(n, "place","InactiveOnScreenDisplay"))
690 font = &config_font_inactiveosd;
694 if ((fnode = obt_xml_find_node(n->children, "name"))) {
696 name = obt_xml_node_string(fnode);
698 if ((fnode = obt_xml_find_node(n->children, "size"))) {
699 int s = obt_xml_node_int(fnode);
702 if ((fnode = obt_xml_find_node(n->children, "weight"))) {
703 gchar *w = obt_xml_node_string(fnode);
704 if (!g_ascii_strcasecmp(w, "Bold"))
705 weight = RR_FONTWEIGHT_BOLD;
708 if ((fnode = obt_xml_find_node(n->children, "slant"))) {
709 gchar *s = obt_xml_node_string(fnode);
710 if (!g_ascii_strcasecmp(s, "Italic"))
711 slant = RR_FONTSLANT_ITALIC;
712 if (!g_ascii_strcasecmp(s, "Oblique"))
713 slant = RR_FONTSLANT_OBLIQUE;
717 *font = RrFontOpen(ob_rr_inst, name, size, weight, slant);
720 n = obt_xml_find_node(n->next, "font");
724 static void parse_desktops(xmlNodePtr node, gpointer d)
728 node = node->children;
730 if ((n = obt_xml_find_node(node, "number"))) {
731 gint d = obt_xml_node_int(n);
733 config_desktops_num = (unsigned) d;
735 if ((n = obt_xml_find_node(node, "firstdesk"))) {
736 gint d = obt_xml_node_int(n);
738 config_screen_firstdesk = (unsigned) d;
740 if ((n = obt_xml_find_node(node, "names"))) {
744 for (it = config_desktops_names; it; it = it->next)
746 g_slist_free(config_desktops_names);
747 config_desktops_names = NULL;
749 nname = obt_xml_find_node(n->children, "name");
751 config_desktops_names =
752 g_slist_append(config_desktops_names,
753 obt_xml_node_string(nname));
754 nname = obt_xml_find_node(nname->next, "name");
757 if ((n = obt_xml_find_node(node, "popupTime")))
758 config_desktop_popup_time = obt_xml_node_int(n);
761 static void parse_resize(xmlNodePtr node, gpointer d)
765 node = node->children;
767 if ((n = obt_xml_find_node(node, "drawContents")))
768 config_resize_redraw = obt_xml_node_bool(n);
769 if ((n = obt_xml_find_node(node, "popupShow"))) {
770 config_resize_popup_show = obt_xml_node_int(n);
771 if (obt_xml_node_contains(n, "Always"))
772 config_resize_popup_show = 2;
773 else if (obt_xml_node_contains(n, "Never"))
774 config_resize_popup_show = 0;
775 else if (obt_xml_node_contains(n, "Nonpixel"))
776 config_resize_popup_show = 1;
778 if ((n = obt_xml_find_node(node, "popupPosition"))) {
779 if (obt_xml_node_contains(n, "Top"))
780 config_resize_popup_pos = OB_RESIZE_POS_TOP;
781 else if (obt_xml_node_contains(n, "Center"))
782 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
783 else if (obt_xml_node_contains(n, "Fixed")) {
784 config_resize_popup_pos = OB_RESIZE_POS_FIXED;
786 if ((n = obt_xml_find_node(node, "popupFixedPosition"))) {
789 if ((n2 = obt_xml_find_node(n->children, "x")))
790 config_parse_gravity_coord(n2,
791 &config_resize_popup_fixed.x);
792 if ((n2 = obt_xml_find_node(n->children, "y")))
793 config_parse_gravity_coord(n2,
794 &config_resize_popup_fixed.y);
796 config_resize_popup_fixed.x.pos =
797 MAX(config_resize_popup_fixed.x.pos, 0);
798 config_resize_popup_fixed.y.pos =
799 MAX(config_resize_popup_fixed.y.pos, 0);
805 static void parse_dock(xmlNodePtr node, gpointer d)
809 node = node->children;
811 if ((n = obt_xml_find_node(node, "position"))) {
812 if (obt_xml_node_contains(n, "TopLeft"))
813 config_dock_floating = FALSE,
814 config_dock_pos = OB_DIRECTION_NORTHWEST;
815 else if (obt_xml_node_contains(n, "Top"))
816 config_dock_floating = FALSE,
817 config_dock_pos = OB_DIRECTION_NORTH;
818 else if (obt_xml_node_contains(n, "TopRight"))
819 config_dock_floating = FALSE,
820 config_dock_pos = OB_DIRECTION_NORTHEAST;
821 else if (obt_xml_node_contains(n, "Right"))
822 config_dock_floating = FALSE,
823 config_dock_pos = OB_DIRECTION_EAST;
824 else if (obt_xml_node_contains(n, "BottomRight"))
825 config_dock_floating = FALSE,
826 config_dock_pos = OB_DIRECTION_SOUTHEAST;
827 else if (obt_xml_node_contains(n, "Bottom"))
828 config_dock_floating = FALSE,
829 config_dock_pos = OB_DIRECTION_SOUTH;
830 else if (obt_xml_node_contains(n, "BottomLeft"))
831 config_dock_floating = FALSE,
832 config_dock_pos = OB_DIRECTION_SOUTHWEST;
833 else if (obt_xml_node_contains(n, "Left"))
834 config_dock_floating = FALSE,
835 config_dock_pos = OB_DIRECTION_WEST;
836 else if (obt_xml_node_contains(n, "Floating"))
837 config_dock_floating = TRUE;
839 if (config_dock_floating) {
840 if ((n = obt_xml_find_node(node, "floatingX")))
841 config_dock_x = obt_xml_node_int(n);
842 if ((n = obt_xml_find_node(node, "floatingY")))
843 config_dock_y = obt_xml_node_int(n);
845 if ((n = obt_xml_find_node(node, "noStrut")))
846 config_dock_nostrut = obt_xml_node_bool(n);
848 if ((n = obt_xml_find_node(node, "stacking"))) {
849 if (obt_xml_node_contains(n, "normal"))
850 config_dock_layer = OB_STACKING_LAYER_NORMAL;
851 else if (obt_xml_node_contains(n, "below"))
852 config_dock_layer = OB_STACKING_LAYER_BELOW;
853 else if (obt_xml_node_contains(n, "above"))
854 config_dock_layer = OB_STACKING_LAYER_ABOVE;
856 if ((n = obt_xml_find_node(node, "direction"))) {
857 if (obt_xml_node_contains(n, "horizontal"))
858 config_dock_orient = OB_ORIENTATION_HORZ;
859 else if (obt_xml_node_contains(n, "vertical"))
860 config_dock_orient = OB_ORIENTATION_VERT;
862 if ((n = obt_xml_find_node(node, "autoHide")))
863 config_dock_hide = obt_xml_node_bool(n);
864 if ((n = obt_xml_find_node(node, "hideDelay")))
865 config_dock_hide_delay = obt_xml_node_int(n);
866 if ((n = obt_xml_find_node(node, "showDelay")))
867 config_dock_show_delay = obt_xml_node_int(n);
868 if ((n = obt_xml_find_node(node, "moveButton"))) {
869 gchar *str = obt_xml_node_string(n);
871 if (translate_button(str, &s, &b)) {
872 config_dock_app_move_button = b;
873 config_dock_app_move_modifiers = s;
875 g_message(_("Invalid button \"%s\" specified in config file"), str);
881 static void parse_menu(xmlNodePtr node, gpointer d)
884 node = node->children;
886 if ((n = obt_xml_find_node(node, "hideDelay")))
887 config_menu_hide_delay = obt_xml_node_int(n);
888 if ((n = obt_xml_find_node(node, "middle")))
889 config_menu_middle = obt_xml_node_bool(n);
890 if ((n = obt_xml_find_node(node, "submenuShowDelay")))
891 config_submenu_show_delay = obt_xml_node_int(n);
892 if ((n = obt_xml_find_node(node, "submenuHideDelay")))
893 config_submenu_hide_delay = obt_xml_node_int(n);
894 if ((n = obt_xml_find_node(node, "manageDesktops")))
895 config_menu_manage_desktops = obt_xml_node_bool(n);
896 if ((n = obt_xml_find_node(node, "showIcons"))) {
897 config_menu_show_icons = obt_xml_node_bool(n);
899 if (config_menu_show_icons)
900 g_message(_("Openbox was compiled without Imlib2 image loading support. Icons in menus will not be loaded."));
904 while ((node = obt_xml_find_node(node, "file"))) {
905 gchar *c = obt_xml_node_string(node);
906 config_menu_files = g_slist_append(config_menu_files,
907 obt_paths_expand_tilde(c));
913 static void parse_resistance(xmlNodePtr node, gpointer d)
917 node = node->children;
918 if ((n = obt_xml_find_node(node, "strength")))
919 config_resist_win = obt_xml_node_int(n);
920 if ((n = obt_xml_find_node(node, "screen_edge_strength")))
921 config_resist_edge = obt_xml_node_int(n);
927 const gchar *actiontext;
930 static void bind_default_keyboard(void)
933 ObDefKeyBind binds[] = {
935 "Execute startupnotify:yes name:Konqueror \\\n"
936 " command:(kfmclient openProfile filemanagement)" },
937 { "A-Tab", "NextWindow" },
938 { "S-A-Tab", "PreviousWindow" },
944 p = action_parser_new();
945 for (it = binds; it->key; ++it) {
946 GList *l = g_list_append(NULL, g_strdup(it->key));
947 ObActionList *actions = action_parser_read_string(p, it->actiontext);
948 keyboard_bind(l, actions);
949 action_list_unref(actions);
951 action_parser_unref(p);
957 const gchar *context;
958 const ObMouseAction mact;
959 const gchar *actname;
962 static void bind_default_mouse(void)
965 ObDefMouseBind binds[] = {
966 { "Left", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
967 { "Middle", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
968 { "Right", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
969 { "Left", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
970 { "Middle", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
971 { "Right", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
972 { "Left", "Titlebar", OB_MOUSE_ACTION_PRESS, "Focus" },
973 { "Left", "Bottom", OB_MOUSE_ACTION_PRESS, "Focus" },
974 { "Left", "BLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
975 { "Left", "BRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
976 { "Left", "TLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
977 { "Left", "TRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
978 { "Left", "Close", OB_MOUSE_ACTION_PRESS, "Focus" },
979 { "Left", "Maximize", OB_MOUSE_ACTION_PRESS, "Focus" },
980 { "Left", "Iconify", OB_MOUSE_ACTION_PRESS, "Focus" },
981 { "Left", "Icon", OB_MOUSE_ACTION_PRESS, "Focus" },
982 { "Left", "AllDesktops", OB_MOUSE_ACTION_PRESS, "Focus" },
983 { "Left", "Shade", OB_MOUSE_ACTION_PRESS, "Focus" },
984 { "Left", "Client", OB_MOUSE_ACTION_CLICK, "Raise" },
985 { "Left", "Titlebar", OB_MOUSE_ACTION_CLICK, "Raise" },
986 { "Middle", "Titlebar", OB_MOUSE_ACTION_CLICK, "Lower" },
987 { "Left", "BLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
988 { "Left", "BRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
989 { "Left", "TLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
990 { "Left", "TRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
991 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Raise" },
992 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "Raise" },
993 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Raise" },
994 { "Left", "Icon", OB_MOUSE_ACTION_CLICK, "Raise" },
995 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "Raise" },
996 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "Raise" },
997 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Close" },
998 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "ToggleMaximize" },
999 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Iconify" },
1000 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "ToggleOmnipresent" },
1001 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "ToggleShade" },
1002 { "Left", "TLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
1003 { "Left", "TRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
1004 { "Left", "BLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
1005 { "Left", "BRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
1006 { "Left", "Top", OB_MOUSE_ACTION_MOTION, "Resize" },
1007 { "Left", "Bottom", OB_MOUSE_ACTION_MOTION, "Resize" },
1008 { "Left", "Left", OB_MOUSE_ACTION_MOTION, "Resize" },
1009 { "Left", "Right", OB_MOUSE_ACTION_MOTION, "Resize" },
1010 { "Left", "Titlebar", OB_MOUSE_ACTION_MOTION, "Move" },
1011 { "A-Left", "Frame", OB_MOUSE_ACTION_MOTION, "Move" },
1012 { "A-Middle", "Frame", OB_MOUSE_ACTION_MOTION, "Resize" },
1013 { NULL, NULL, 0, NULL }
1016 ObActionList *actions;
1018 p = action_parser_new();
1019 for (it = binds; it->button; ++it) {
1020 actions = action_parser_read_string(p, it->actname);
1021 mouse_bind(it->button, frame_context_from_string(it->context),
1023 action_list_unref(actions);
1025 action_parser_unref(p);
1028 void config_startup(ObtXmlInst *i)
1030 config_focus_new = TRUE;
1031 config_focus_follow = FALSE;
1032 config_focus_delay = 0;
1033 config_focus_raise = FALSE;
1034 config_focus_last = TRUE;
1035 config_focus_under_mouse = FALSE;
1036 config_unfocus_leave = FALSE;
1038 obt_xml_register(i, "focus", parse_focus, NULL);
1040 config_place_policy = OB_PLACE_POLICY_SMART;
1041 config_place_center = TRUE;
1042 config_place_monitor = OB_PLACE_MONITOR_PRIMARY;
1044 config_primary_monitor_index = 1;
1045 config_primary_monitor = OB_PLACE_MONITOR_ACTIVE;
1047 obt_xml_register(i, "placement", parse_placement, NULL);
1049 STRUT_PARTIAL_SET(config_margins, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1051 obt_xml_register(i, "margins", parse_margins, NULL);
1053 config_theme = NULL;
1055 config_animate_iconify = TRUE;
1056 config_title_layout = g_strdup("NLIMC");
1057 config_theme_keepborder = TRUE;
1058 config_theme_window_list_icon_size = 36;
1060 config_font_activewindow = NULL;
1061 config_font_inactivewindow = NULL;
1062 config_font_menuitem = NULL;
1063 config_font_menutitle = NULL;
1064 config_font_activeosd = NULL;
1065 config_font_inactiveosd = NULL;
1067 obt_xml_register(i, "theme", parse_theme, NULL);
1069 config_desktops_num = 4;
1070 config_screen_firstdesk = 1;
1071 config_desktops_names = NULL;
1072 config_desktop_popup_time = 875;
1074 obt_xml_register(i, "desktops", parse_desktops, NULL);
1076 config_resize_redraw = TRUE;
1077 config_resize_popup_show = 1; /* nonpixel increments */
1078 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
1079 GRAVITY_COORD_SET(config_resize_popup_fixed.x, 0, FALSE, FALSE);
1080 GRAVITY_COORD_SET(config_resize_popup_fixed.y, 0, FALSE, FALSE);
1082 obt_xml_register(i, "resize", parse_resize, NULL);
1084 config_dock_layer = OB_STACKING_LAYER_ABOVE;
1085 config_dock_pos = OB_DIRECTION_NORTHEAST;
1086 config_dock_floating = FALSE;
1087 config_dock_nostrut = FALSE;
1090 config_dock_orient = OB_ORIENTATION_VERT;
1091 config_dock_hide = FALSE;
1092 config_dock_hide_delay = 300;
1093 config_dock_show_delay = 300;
1094 config_dock_app_move_button = 2; /* middle */
1095 config_dock_app_move_modifiers = 0;
1097 obt_xml_register(i, "dock", parse_dock, NULL);
1099 translate_key("C-g", &config_keyboard_reset_state,
1100 &config_keyboard_reset_keycode);
1102 bind_default_keyboard();
1104 obt_xml_register(i, "keyboard", parse_keyboard, NULL);
1106 config_mouse_threshold = 8;
1107 config_mouse_dclicktime = 200;
1108 config_mouse_screenedgetime = 400;
1109 config_mouse_screenedgewarp = FALSE;
1111 bind_default_mouse();
1113 obt_xml_register(i, "mouse", parse_mouse, NULL);
1115 config_resist_win = 10;
1116 config_resist_edge = 20;
1118 obt_xml_register(i, "resistance", parse_resistance, NULL);
1120 config_menu_hide_delay = 250;
1121 config_menu_middle = FALSE;
1122 config_submenu_show_delay = 100;
1123 config_submenu_hide_delay = 400;
1124 config_menu_manage_desktops = TRUE;
1125 config_menu_files = NULL;
1126 config_menu_show_icons = TRUE;
1128 obt_xml_register(i, "menu", parse_menu, NULL);
1130 config_per_app_settings = NULL;
1132 obt_xml_register(i, "applications", parse_per_app_settings, NULL);
1135 void config_shutdown(void)
1139 g_free(config_theme);
1141 g_free(config_title_layout);
1143 RrFontClose(config_font_activewindow);
1144 RrFontClose(config_font_inactivewindow);
1145 RrFontClose(config_font_menuitem);
1146 RrFontClose(config_font_menutitle);
1147 RrFontClose(config_font_activeosd);
1148 RrFontClose(config_font_inactiveosd);
1150 for (it = config_desktops_names; it; it = g_slist_next(it))
1152 g_slist_free(config_desktops_names);
1154 for (it = config_menu_files; it; it = g_slist_next(it))
1156 g_slist_free(config_menu_files);
1158 for (it = config_per_app_settings; it; it = g_slist_next(it)) {
1159 ObAppSettings *itd = (ObAppSettings *)it->data;
1160 if (itd->name) g_pattern_spec_free(itd->name);
1161 if (itd->role) g_pattern_spec_free(itd->role);
1162 if (itd->title) g_pattern_spec_free(itd->title);
1163 if (itd->class) g_pattern_spec_free(itd->class);
1164 g_slice_free(ObAppSettings, it->data);
1166 g_slist_free(config_per_app_settings);