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 ObPlaceMonitor config_place_monitor;
42 guint config_primary_monitor_index;
43 ObPlaceMonitor config_primary_monitor;
45 StrutPartial config_margins;
48 gboolean config_theme_keepborder;
49 guint config_theme_window_list_icon_size;
51 gchar *config_title_layout;
53 gboolean config_animate_iconify;
55 RrFont *config_font_activewindow;
56 RrFont *config_font_inactivewindow;
57 RrFont *config_font_menuitem;
58 RrFont *config_font_menutitle;
59 RrFont *config_font_activeosd;
60 RrFont *config_font_inactiveosd;
62 guint config_desktops_num;
63 GSList *config_desktops_names;
64 guint config_screen_firstdesk;
65 guint config_desktop_popup_time;
66 gint config_emulate_xinerama;
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 */
158 if (src->size_given) {
159 dst->size_given = TRUE;
160 dst->width_num = src->width_num;
161 dst->width_denom = src->width_denom;
162 dst->height_num = src->height_num;
163 dst->height_denom = src->height_denom;
167 void config_parse_relative_number(gchar *s, gint *num, gint *denom)
169 *num = strtol(s, &s, 10);
173 } else if (*s == '/') {
178 void config_parse_gravity_coord(xmlNodePtr node, GravityCoord *c)
180 gchar *s = obt_xml_node_string(node);
181 if (!g_ascii_strcasecmp(s, "center"))
187 if (s[0] == '-' || s[0] == '+')
189 config_parse_relative_number(ps, &c->pos, &c->denom);
196 <application name="aterm">
199 <application name="Rhythmbox">
206 .. there is a lot more settings available
211 static void parse_single_per_app_settings(xmlNodePtr app,
212 ObAppSettings *settings)
215 gboolean x_pos_given = FALSE;
216 gboolean width_given = FALSE;
218 if ((n = obt_xml_find_node(app->children, "decor")))
219 if (!obt_xml_node_contains(n, "default"))
220 settings->decor = obt_xml_node_bool(n);
222 if ((n = obt_xml_find_node(app->children, "shade")))
223 if (!obt_xml_node_contains(n, "default"))
224 settings->shade = obt_xml_node_bool(n);
226 if ((n = obt_xml_find_node(app->children, "position"))) {
227 if ((c = obt_xml_find_node(n->children, "x"))) {
228 if (!obt_xml_node_contains(c, "default")) {
229 config_parse_gravity_coord(c, &settings->position.x);
234 if (x_pos_given && (c = obt_xml_find_node(n->children, "y"))) {
235 if (!obt_xml_node_contains(c, "default")) {
236 config_parse_gravity_coord(c, &settings->position.y);
237 settings->pos_given = TRUE;
241 /* monitor can be set without setting x or y */
242 if ((c = obt_xml_find_node(n->children, "monitor"))) {
243 if (!obt_xml_node_contains(c, "default")) {
244 gchar *s = obt_xml_node_string(c);
245 if (!g_ascii_strcasecmp(s, "mouse"))
246 settings->monitor_type = OB_PLACE_MONITOR_MOUSE;
247 else if (!g_ascii_strcasecmp(s, "active"))
248 settings->monitor_type = OB_PLACE_MONITOR_ACTIVE;
249 else if (!g_ascii_strcasecmp(s, "primary"))
250 settings->monitor_type = OB_PLACE_MONITOR_PRIMARY;
252 settings->monitor = obt_xml_node_int(c);
257 obt_xml_attr_bool(n, "force", &settings->pos_force);
260 if ((n = obt_xml_find_node(app->children, "size"))) {
261 if ((c = obt_xml_find_node(n->children, "width"))) {
262 if (!obt_xml_node_contains(c, "default")) {
263 gchar *s = obt_xml_node_string(c);
264 config_parse_relative_number(s,
265 &settings->width_num,
266 &settings->width_denom);
267 if (settings->width_num > 0 && settings->width_denom >= 0)
273 if (width_given && (c = obt_xml_find_node(n->children, "height"))) {
274 gchar *s = obt_xml_node_string(c);
275 config_parse_relative_number(s,
276 &settings->height_num,
277 &settings->height_denom);
278 if (settings->height_num > 0 && settings->height_denom >= 0)
279 settings->size_given = TRUE;
284 if ((n = obt_xml_find_node(app->children, "focus"))) {
285 if (!obt_xml_node_contains(n, "default"))
286 settings->focus = obt_xml_node_bool(n);
289 if ((n = obt_xml_find_node(app->children, "desktop"))) {
290 if (!obt_xml_node_contains(n, "default")) {
291 gchar *s = obt_xml_node_string(n);
292 if (!g_ascii_strcasecmp(s, "all"))
293 settings->desktop = DESKTOP_ALL;
295 gint i = obt_xml_node_int(n);
297 settings->desktop = i;
303 if ((n = obt_xml_find_node(app->children, "layer"))) {
304 if (!obt_xml_node_contains(n, "default")) {
305 gchar *s = obt_xml_node_string(n);
306 if (!g_ascii_strcasecmp(s, "above"))
308 else if (!g_ascii_strcasecmp(s, "below"))
309 settings->layer = -1;
316 if ((n = obt_xml_find_node(app->children, "iconic")))
317 if (!obt_xml_node_contains(n, "default"))
318 settings->iconic = obt_xml_node_bool(n);
320 if ((n = obt_xml_find_node(app->children, "skip_pager")))
321 if (!obt_xml_node_contains(n, "default"))
322 settings->skip_pager = obt_xml_node_bool(n);
324 if ((n = obt_xml_find_node(app->children, "skip_taskbar")))
325 if (!obt_xml_node_contains(n, "default"))
326 settings->skip_taskbar = obt_xml_node_bool(n);
328 if ((n = obt_xml_find_node(app->children, "fullscreen")))
329 if (!obt_xml_node_contains(n, "default"))
330 settings->fullscreen = obt_xml_node_bool(n);
332 if ((n = obt_xml_find_node(app->children, "maximized"))) {
333 if (!obt_xml_node_contains(n, "default")) {
334 gchar *s = obt_xml_node_string(n);
335 if (!g_ascii_strcasecmp(s, "horizontal")) {
336 settings->max_horz = TRUE;
337 settings->max_vert = FALSE;
338 } else if (!g_ascii_strcasecmp(s, "vertical")) {
339 settings->max_horz = FALSE;
340 settings->max_vert = TRUE;
342 settings->max_horz = settings->max_vert =
343 obt_xml_node_bool(n);
349 /* Manages settings for individual applications.
350 Some notes: monitor is the screen number in a multi monitor
351 (Xinerama) setup (starting from 0), or mouse: the monitor the pointer
352 is on, active: the active monitor, primary: the primary monitor.
353 Layer can be three values, above (Always on top), below
354 (Always on bottom) and everything else (normal behaviour).
355 Positions can be an integer value or center, which will
356 center the window in the specified axis. Position is within
357 the monitor, so <position><x>center</x></position><monitor>2</monitor>
358 will center the window on the second monitor.
360 static void parse_per_app_settings(xmlNodePtr node, gpointer d)
362 xmlNodePtr app = obt_xml_find_node(node->children, "application");
363 for (; app; app = obt_xml_find_node(app->next, "application")) {
364 ObAppSettings *settings;
366 gboolean name_set, class_set, role_set, title_set,
367 type_set, group_name_set, group_class_set;
368 gchar *name = NULL, *class = NULL, *role = NULL, *title = NULL,
369 *type_str = NULL, *group_name = NULL, *group_class = NULL;
372 class_set = obt_xml_attr_string(app, "class", &class);
373 name_set = obt_xml_attr_string(app, "name", &name);
374 group_class_set = obt_xml_attr_string(app, "groupclass", &group_class);
375 group_name_set = obt_xml_attr_string(app, "groupname", &group_name);
376 type_set = obt_xml_attr_string(app, "type", &type_str);
377 role_set = obt_xml_attr_string(app, "role", &role);
378 title_set = obt_xml_attr_string(app, "title", &title);
380 /* validate the type tho */
382 if (!g_ascii_strcasecmp(type_str, "normal"))
383 type = OB_CLIENT_TYPE_NORMAL;
384 else if (!g_ascii_strcasecmp(type_str, "dialog"))
385 type = OB_CLIENT_TYPE_DIALOG;
386 else if (!g_ascii_strcasecmp(type_str, "splash"))
387 type = OB_CLIENT_TYPE_SPLASH;
388 else if (!g_ascii_strcasecmp(type_str, "utility"))
389 type = OB_CLIENT_TYPE_UTILITY;
390 else if (!g_ascii_strcasecmp(type_str, "menu"))
391 type = OB_CLIENT_TYPE_MENU;
392 else if (!g_ascii_strcasecmp(type_str, "toolbar"))
393 type = OB_CLIENT_TYPE_TOOLBAR;
394 else if (!g_ascii_strcasecmp(type_str, "dock"))
395 type = OB_CLIENT_TYPE_DOCK;
396 else if (!g_ascii_strcasecmp(type_str, "desktop"))
397 type = OB_CLIENT_TYPE_DESKTOP;
399 type_set = FALSE; /* not valid! */
402 if (!(class_set || name_set || role_set || title_set ||
403 type_set || group_class_set || group_name_set))
406 settings = config_create_app_settings();
409 settings->name = g_pattern_spec_new(name);
411 settings->class = g_pattern_spec_new(class);
413 settings->group_name = g_pattern_spec_new(group_name);
415 settings->group_class = g_pattern_spec_new(group_class);
417 settings->role = g_pattern_spec_new(role);
419 settings->title = g_pattern_spec_new(title);
421 settings->type = type;
431 parse_single_per_app_settings(app, settings);
432 config_per_app_settings = g_slist_append(config_per_app_settings,
440 <action name="ChangeDesktop">
447 static void parse_key(xmlNodePtr node, GList *keylist)
449 gchar *keystring, **keys, **key;
451 gboolean is_chroot = FALSE;
452 gboolean grab = TRUE;
454 if (!obt_xml_attr_string(node, "key", &keystring))
457 obt_xml_attr_bool(node, "chroot", &is_chroot);
458 obt_xml_attr_bool(node, "grab", &grab);
460 keys = g_strsplit(keystring, " ", 0);
461 for (key = keys; *key; ++key) {
462 keylist = g_list_append(keylist, *key);
464 if ((n = obt_xml_find_node(node->children, "keybind"))) {
466 parse_key(n, keylist);
467 n = obt_xml_find_node(n->next, "keybind");
470 else if ((n = obt_xml_find_node(node->children, "action"))) {
472 ObActionsAct *action;
474 action = actions_parse(n);
476 keyboard_bind(keylist, action, grab);
477 n = obt_xml_find_node(n->next, "action");
483 keyboard_chroot(keylist);
484 keylist = g_list_delete_link(keylist, g_list_last(keylist));
491 static void parse_keyboard(xmlNodePtr node, gpointer d)
496 keyboard_unbind_all();
498 if ((n = obt_xml_find_node(node->children, "chainQuitKey"))) {
499 key = obt_xml_node_string(n);
500 translate_key(key, &config_keyboard_reset_state,
501 &config_keyboard_reset_keycode);
505 if ((n = obt_xml_find_node(node->children, "keybind")))
508 n = obt_xml_find_node(n->next, "keybind");
514 <context name="Titlebar">
515 <mousebind button="Left" action="Press">
516 <action name="Raise"></action>
522 static void parse_mouse(xmlNodePtr node, gpointer d)
524 xmlNodePtr n, nbut, nact;
531 node = node->children;
533 if ((n = obt_xml_find_node(node, "dragThreshold")))
534 config_mouse_threshold = obt_xml_node_int(n);
535 if ((n = obt_xml_find_node(node, "doubleClickTime")))
536 config_mouse_dclicktime = obt_xml_node_int(n);
537 if ((n = obt_xml_find_node(node, "screenEdgeWarpTime"))) {
538 config_mouse_screenedgetime = obt_xml_node_int(n);
539 /* minimum value of 25 for this property, when it is 1 and you hit the
540 edge it basically never stops */
541 if (config_mouse_screenedgetime && config_mouse_screenedgetime < 25)
542 config_mouse_screenedgetime = 25;
544 if ((n = obt_xml_find_node(node, "screenEdgeWarpMouse")))
545 config_mouse_screenedgewarp = obt_xml_node_bool(n);
547 n = obt_xml_find_node(node, "context");
552 if (!obt_xml_attr_string(n, "name", &cxstr))
555 modcxstr = g_strdup(cxstr); /* make a copy to mutilate */
556 while (frame_next_context_from_string(modcxstr, &cx)) {
558 gchar *s = strchr(modcxstr, ' ');
561 g_message(_("Invalid context \"%s\" in mouse binding"),
568 nbut = obt_xml_find_node(n->children, "mousebind");
570 if (!obt_xml_attr_string(nbut, "button", &buttonstr))
572 if (obt_xml_attr_contains(nbut, "action", "press"))
573 mact = OB_MOUSE_ACTION_PRESS;
574 else if (obt_xml_attr_contains(nbut, "action", "release"))
575 mact = OB_MOUSE_ACTION_RELEASE;
576 else if (obt_xml_attr_contains(nbut, "action", "click"))
577 mact = OB_MOUSE_ACTION_CLICK;
578 else if (obt_xml_attr_contains(nbut, "action","doubleclick"))
579 mact = OB_MOUSE_ACTION_DOUBLE_CLICK;
580 else if (obt_xml_attr_contains(nbut, "action", "drag"))
581 mact = OB_MOUSE_ACTION_MOTION;
585 nact = obt_xml_find_node(nbut->children, "action");
587 ObActionsAct *action;
589 if ((action = actions_parse(nact))) {
590 gchar *p = buttonstr;
592 gchar *s = strchr(p, ' ');
600 mouse_bind(p, cx, mact, action);
601 actions_act_ref(action); /* ref the action for each binding */
604 actions_act_unref(action); /* remove the extra ref */
606 nact = obt_xml_find_node(nact->next, "action");
610 nbut = obt_xml_find_node(nbut->next, "mousebind");
616 n = obt_xml_find_node(n->next, "context");
620 static void parse_focus(xmlNodePtr node, gpointer d)
624 node = node->children;
626 if ((n = obt_xml_find_node(node, "focusNew")))
627 config_focus_new = obt_xml_node_bool(n);
628 if ((n = obt_xml_find_node(node, "followMouse")))
629 config_focus_follow = obt_xml_node_bool(n);
630 if ((n = obt_xml_find_node(node, "focusDelay")))
631 config_focus_delay = obt_xml_node_int(n);
632 if ((n = obt_xml_find_node(node, "raiseOnFocus")))
633 config_focus_raise = obt_xml_node_bool(n);
634 if ((n = obt_xml_find_node(node, "focusLast")))
635 config_focus_last = obt_xml_node_bool(n);
636 if ((n = obt_xml_find_node(node, "underMouse")))
637 config_focus_under_mouse = obt_xml_node_bool(n);
638 if ((n = obt_xml_find_node(node, "unfocusOnLeave")))
639 config_unfocus_leave = obt_xml_node_bool(n);
642 static void parse_placement(xmlNodePtr node, gpointer d)
646 node = node->children;
648 if ((n = obt_xml_find_node(node, "policy")))
649 if (obt_xml_node_contains(n, "UnderMouse"))
650 config_place_policy = OB_PLACE_POLICY_MOUSE;
651 if (obt_xml_node_contains(n, "Random"))
652 config_place_policy = OB_PLACE_POLICY_RANDOM;
653 if ((n = obt_xml_find_node(node, "monitor"))) {
654 if (obt_xml_node_contains(n, "active"))
655 config_place_monitor = OB_PLACE_MONITOR_ACTIVE;
656 else if (obt_xml_node_contains(n, "mouse"))
657 config_place_monitor = OB_PLACE_MONITOR_MOUSE;
658 else if (obt_xml_node_contains(n, "any"))
659 config_place_monitor = OB_PLACE_MONITOR_ANY;
661 if ((n = obt_xml_find_node(node, "primaryMonitor"))) {
662 config_primary_monitor_index = obt_xml_node_int(n);
663 if (!config_primary_monitor_index) {
664 if (obt_xml_node_contains(n, "mouse"))
665 config_primary_monitor = OB_PLACE_MONITOR_MOUSE;
670 static void parse_margins(xmlNodePtr node, gpointer d)
674 node = node->children;
676 if ((n = obt_xml_find_node(node, "top")))
677 config_margins.top = MAX(0, obt_xml_node_int(n));
678 if ((n = obt_xml_find_node(node, "left")))
679 config_margins.left = MAX(0, obt_xml_node_int(n));
680 if ((n = obt_xml_find_node(node, "right")))
681 config_margins.right = MAX(0, obt_xml_node_int(n));
682 if ((n = obt_xml_find_node(node, "bottom")))
683 config_margins.bottom = MAX(0, obt_xml_node_int(n));
686 static void parse_theme(xmlNodePtr node, gpointer d)
690 node = node->children;
692 if ((n = obt_xml_find_node(node, "name"))) {
695 g_free(config_theme);
696 c = obt_xml_node_string(n);
697 config_theme = obt_paths_expand_tilde(c);
700 if ((n = obt_xml_find_node(node, "titleLayout"))) {
703 g_free(config_title_layout);
704 config_title_layout = obt_xml_node_string(n);
706 /* replace duplicates with spaces */
707 for (c = config_title_layout; *c != '\0'; ++c)
708 for (d = c+1; *d != '\0'; ++d)
709 if (*c == *d) *d = ' ';
711 if ((n = obt_xml_find_node(node, "keepBorder")))
712 config_theme_keepborder = obt_xml_node_bool(n);
713 if ((n = obt_xml_find_node(node, "animateIconify")))
714 config_animate_iconify = obt_xml_node_bool(n);
715 if ((n = obt_xml_find_node(node, "windowListIconSize"))) {
716 config_theme_window_list_icon_size = obt_xml_node_int(n);
717 if (config_theme_window_list_icon_size < 16)
718 config_theme_window_list_icon_size = 16;
719 else if (config_theme_window_list_icon_size > 96)
720 config_theme_window_list_icon_size = 96;
723 n = obt_xml_find_node(node, "font");
727 gchar *name = g_strdup(RrDefaultFontFamily);
728 gint size = RrDefaultFontSize;
729 RrFontWeight weight = RrDefaultFontWeight;
730 RrFontSlant slant = RrDefaultFontSlant;
732 if (obt_xml_attr_contains(n, "place", "ActiveWindow"))
733 font = &config_font_activewindow;
734 else if (obt_xml_attr_contains(n, "place", "InactiveWindow"))
735 font = &config_font_inactivewindow;
736 else if (obt_xml_attr_contains(n, "place", "MenuHeader"))
737 font = &config_font_menutitle;
738 else if (obt_xml_attr_contains(n, "place", "MenuItem"))
739 font = &config_font_menuitem;
740 else if (obt_xml_attr_contains(n, "place", "ActiveOnScreenDisplay"))
741 font = &config_font_activeosd;
742 else if (obt_xml_attr_contains(n, "place", "OnScreenDisplay"))
743 font = &config_font_activeosd;
744 else if (obt_xml_attr_contains(n, "place","InactiveOnScreenDisplay"))
745 font = &config_font_inactiveosd;
749 if ((fnode = obt_xml_find_node(n->children, "name"))) {
751 name = obt_xml_node_string(fnode);
753 if ((fnode = obt_xml_find_node(n->children, "size"))) {
754 int s = obt_xml_node_int(fnode);
757 if ((fnode = obt_xml_find_node(n->children, "weight"))) {
758 gchar *w = obt_xml_node_string(fnode);
759 if (!g_ascii_strcasecmp(w, "Bold"))
760 weight = RR_FONTWEIGHT_BOLD;
763 if ((fnode = obt_xml_find_node(n->children, "slant"))) {
764 gchar *s = obt_xml_node_string(fnode);
765 if (!g_ascii_strcasecmp(s, "Italic"))
766 slant = RR_FONTSLANT_ITALIC;
767 if (!g_ascii_strcasecmp(s, "Oblique"))
768 slant = RR_FONTSLANT_OBLIQUE;
772 *font = RrFontOpen(ob_rr_inst, name, size, weight, slant);
775 if ((fnode = obt_xml_find_node(n->children, "description"))) {
776 gchar *s = obt_xml_node_string(fnode);
777 RrFontDescriptionFromString(*font, s);
782 n = obt_xml_find_node(n->next, "font");
786 static void parse_desktops(xmlNodePtr node, gpointer d)
790 node = node->children;
792 if ((n = obt_xml_find_node(node, "number"))) {
793 gint d = obt_xml_node_int(n);
795 config_desktops_num = (unsigned) d;
797 if ((n = obt_xml_find_node(node, "firstdesk"))) {
798 gint d = obt_xml_node_int(n);
800 config_screen_firstdesk = (unsigned) d;
802 if ((n = obt_xml_find_node(node, "emulatexinerama")))
803 config_emulate_xinerama = obt_xml_node_bool(n);
804 if ((n = obt_xml_find_node(node, "names"))) {
808 for (it = config_desktops_names; it; it = it->next)
810 g_slist_free(config_desktops_names);
811 config_desktops_names = NULL;
813 nname = obt_xml_find_node(n->children, "name");
815 config_desktops_names =
816 g_slist_append(config_desktops_names,
817 obt_xml_node_string(nname));
818 nname = obt_xml_find_node(nname->next, "name");
821 if ((n = obt_xml_find_node(node, "popupTime")))
822 config_desktop_popup_time = obt_xml_node_int(n);
825 static void parse_resize(xmlNodePtr node, gpointer d)
829 node = node->children;
831 if ((n = obt_xml_find_node(node, "drawContents")))
832 config_resize_redraw = obt_xml_node_bool(n);
833 if ((n = obt_xml_find_node(node, "popupShow"))) {
834 config_resize_popup_show = obt_xml_node_int(n);
835 if (obt_xml_node_contains(n, "Always"))
836 config_resize_popup_show = 2;
837 else if (obt_xml_node_contains(n, "Never"))
838 config_resize_popup_show = 0;
839 else if (obt_xml_node_contains(n, "Nonpixel"))
840 config_resize_popup_show = 1;
842 if ((n = obt_xml_find_node(node, "popupPosition"))) {
843 if (obt_xml_node_contains(n, "Top"))
844 config_resize_popup_pos = OB_RESIZE_POS_TOP;
845 else if (obt_xml_node_contains(n, "Center"))
846 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
847 else if (obt_xml_node_contains(n, "Fixed")) {
848 config_resize_popup_pos = OB_RESIZE_POS_FIXED;
850 if ((n = obt_xml_find_node(node, "popupFixedPosition"))) {
853 if ((n2 = obt_xml_find_node(n->children, "x")))
854 config_parse_gravity_coord(n2,
855 &config_resize_popup_fixed.x);
856 if ((n2 = obt_xml_find_node(n->children, "y")))
857 config_parse_gravity_coord(n2,
858 &config_resize_popup_fixed.y);
860 config_resize_popup_fixed.x.pos =
861 MAX(config_resize_popup_fixed.x.pos, 0);
862 config_resize_popup_fixed.y.pos =
863 MAX(config_resize_popup_fixed.y.pos, 0);
869 static void parse_dock(xmlNodePtr node, gpointer d)
873 node = node->children;
875 if ((n = obt_xml_find_node(node, "position"))) {
876 if (obt_xml_node_contains(n, "TopLeft"))
877 config_dock_floating = FALSE,
878 config_dock_pos = OB_DIRECTION_NORTHWEST;
879 else if (obt_xml_node_contains(n, "Top"))
880 config_dock_floating = FALSE,
881 config_dock_pos = OB_DIRECTION_NORTH;
882 else if (obt_xml_node_contains(n, "TopRight"))
883 config_dock_floating = FALSE,
884 config_dock_pos = OB_DIRECTION_NORTHEAST;
885 else if (obt_xml_node_contains(n, "Right"))
886 config_dock_floating = FALSE,
887 config_dock_pos = OB_DIRECTION_EAST;
888 else if (obt_xml_node_contains(n, "BottomRight"))
889 config_dock_floating = FALSE,
890 config_dock_pos = OB_DIRECTION_SOUTHEAST;
891 else if (obt_xml_node_contains(n, "Bottom"))
892 config_dock_floating = FALSE,
893 config_dock_pos = OB_DIRECTION_SOUTH;
894 else if (obt_xml_node_contains(n, "BottomLeft"))
895 config_dock_floating = FALSE,
896 config_dock_pos = OB_DIRECTION_SOUTHWEST;
897 else if (obt_xml_node_contains(n, "Left"))
898 config_dock_floating = FALSE,
899 config_dock_pos = OB_DIRECTION_WEST;
900 else if (obt_xml_node_contains(n, "Floating"))
901 config_dock_floating = TRUE;
903 if (config_dock_floating) {
904 if ((n = obt_xml_find_node(node, "floatingX")))
905 config_dock_x = obt_xml_node_int(n);
906 if ((n = obt_xml_find_node(node, "floatingY")))
907 config_dock_y = obt_xml_node_int(n);
909 if ((n = obt_xml_find_node(node, "noStrut")))
910 config_dock_nostrut = obt_xml_node_bool(n);
912 if ((n = obt_xml_find_node(node, "stacking"))) {
913 if (obt_xml_node_contains(n, "normal"))
914 config_dock_layer = OB_STACKING_LAYER_NORMAL;
915 else if (obt_xml_node_contains(n, "below"))
916 config_dock_layer = OB_STACKING_LAYER_BELOW;
917 else if (obt_xml_node_contains(n, "above"))
918 config_dock_layer = OB_STACKING_LAYER_ABOVE;
920 if ((n = obt_xml_find_node(node, "direction"))) {
921 if (obt_xml_node_contains(n, "horizontal"))
922 config_dock_orient = OB_ORIENTATION_HORZ;
923 else if (obt_xml_node_contains(n, "vertical"))
924 config_dock_orient = OB_ORIENTATION_VERT;
926 if ((n = obt_xml_find_node(node, "autoHide")))
927 config_dock_hide = obt_xml_node_bool(n);
928 if ((n = obt_xml_find_node(node, "hideDelay")))
929 config_dock_hide_delay = obt_xml_node_int(n);
930 if ((n = obt_xml_find_node(node, "showDelay")))
931 config_dock_show_delay = obt_xml_node_int(n);
932 if ((n = obt_xml_find_node(node, "moveButton"))) {
933 gchar *str = obt_xml_node_string(n);
935 if (translate_button(str, &s, &b)) {
936 config_dock_app_move_button = b;
937 config_dock_app_move_modifiers = s;
939 g_message(_("Invalid button \"%s\" specified in config file"), str);
945 static void parse_menu(xmlNodePtr node, gpointer d)
948 node = node->children;
950 if ((n = obt_xml_find_node(node, "hideDelay")))
951 config_menu_hide_delay = obt_xml_node_int(n);
952 if ((n = obt_xml_find_node(node, "middle")))
953 config_menu_middle = obt_xml_node_bool(n);
954 if ((n = obt_xml_find_node(node, "submenuShowDelay")))
955 config_submenu_show_delay = obt_xml_node_int(n);
956 if ((n = obt_xml_find_node(node, "submenuHideDelay")))
957 config_submenu_hide_delay = obt_xml_node_int(n);
958 if ((n = obt_xml_find_node(node, "manageDesktops")))
959 config_menu_manage_desktops = obt_xml_node_bool(n);
960 if ((n = obt_xml_find_node(node, "showIcons"))) {
961 config_menu_show_icons = obt_xml_node_bool(n);
962 #if !defined(USE_IMLIB2) && !defined(USE_LIBRSVG)
963 if (config_menu_show_icons)
964 g_message(_("Openbox was compiled without image loading support. Icons in menus will not be loaded."));
968 while ((node = obt_xml_find_node(node, "file"))) {
969 gchar *c = obt_xml_node_string(node);
970 config_menu_files = g_slist_append(config_menu_files,
971 obt_paths_expand_tilde(c));
977 static void parse_resistance(xmlNodePtr node, gpointer d)
981 node = node->children;
982 if ((n = obt_xml_find_node(node, "strength")))
983 config_resist_win = obt_xml_node_int(n);
984 if ((n = obt_xml_find_node(node, "screen_edge_strength")))
985 config_resist_edge = obt_xml_node_int(n);
991 const gchar *actname;
994 static void bind_default_keyboard(void)
997 ObDefKeyBind binds[] = {
998 { "A-Tab", "NextWindow" },
999 { "S-A-Tab", "PreviousWindow" },
1000 { "A-F4", "Close" },
1003 for (it = binds; it->key; ++it) {
1004 GList *l = g_list_append(NULL, g_strdup(it->key));
1005 keyboard_bind(l, actions_parse_string(it->actname), TRUE);
1011 const gchar *button;
1012 const gchar *context;
1013 const ObMouseAction mact;
1014 const gchar *actname;
1017 static void bind_default_mouse(void)
1020 ObDefMouseBind binds[] = {
1021 { "Left", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
1022 { "Middle", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
1023 { "Right", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
1024 { "Left", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
1025 { "Middle", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
1026 { "Right", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
1027 { "Left", "Titlebar", OB_MOUSE_ACTION_PRESS, "Focus" },
1028 { "Left", "Bottom", OB_MOUSE_ACTION_PRESS, "Focus" },
1029 { "Left", "BLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
1030 { "Left", "BRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
1031 { "Left", "TLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
1032 { "Left", "TRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
1033 { "Left", "Close", OB_MOUSE_ACTION_PRESS, "Focus" },
1034 { "Left", "Maximize", OB_MOUSE_ACTION_PRESS, "Focus" },
1035 { "Left", "Iconify", OB_MOUSE_ACTION_PRESS, "Focus" },
1036 { "Left", "Icon", OB_MOUSE_ACTION_PRESS, "Focus" },
1037 { "Left", "AllDesktops", OB_MOUSE_ACTION_PRESS, "Focus" },
1038 { "Left", "Shade", OB_MOUSE_ACTION_PRESS, "Focus" },
1039 { "Left", "Client", OB_MOUSE_ACTION_CLICK, "Raise" },
1040 { "Left", "Titlebar", OB_MOUSE_ACTION_CLICK, "Raise" },
1041 { "Middle", "Titlebar", OB_MOUSE_ACTION_CLICK, "Lower" },
1042 { "Left", "BLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
1043 { "Left", "BRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
1044 { "Left", "TLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
1045 { "Left", "TRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
1046 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Raise" },
1047 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "Raise" },
1048 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Raise" },
1049 { "Left", "Icon", OB_MOUSE_ACTION_CLICK, "Raise" },
1050 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "Raise" },
1051 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "Raise" },
1052 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Close" },
1053 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "ToggleMaximize" },
1054 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Iconify" },
1055 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "ToggleOmnipresent" },
1056 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "ToggleShade" },
1057 { "Left", "TLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
1058 { "Left", "TRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
1059 { "Left", "BLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
1060 { "Left", "BRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
1061 { "Left", "Top", OB_MOUSE_ACTION_MOTION, "Resize" },
1062 { "Left", "Bottom", OB_MOUSE_ACTION_MOTION, "Resize" },
1063 { "Left", "Left", OB_MOUSE_ACTION_MOTION, "Resize" },
1064 { "Left", "Right", OB_MOUSE_ACTION_MOTION, "Resize" },
1065 { "Left", "Titlebar", OB_MOUSE_ACTION_MOTION, "Move" },
1066 { "A-Left", "Frame", OB_MOUSE_ACTION_MOTION, "Move" },
1067 { "A-Middle", "Frame", OB_MOUSE_ACTION_MOTION, "Resize" },
1068 { NULL, NULL, 0, NULL }
1071 for (it = binds; it->button; ++it)
1072 mouse_bind(it->button, frame_context_from_string(it->context),
1073 it->mact, actions_parse_string(it->actname));
1076 void config_startup(ObtXmlInst *i)
1078 config_focus_new = TRUE;
1079 config_focus_follow = FALSE;
1080 config_focus_delay = 0;
1081 config_focus_raise = FALSE;
1082 config_focus_last = TRUE;
1083 config_focus_under_mouse = FALSE;
1084 config_unfocus_leave = FALSE;
1086 obt_xml_register(i, "focus", parse_focus, NULL);
1088 config_place_policy = OB_PLACE_POLICY_SMART;
1089 config_place_monitor = OB_PLACE_MONITOR_PRIMARY;
1091 config_primary_monitor_index = 1;
1092 config_primary_monitor = OB_PLACE_MONITOR_ACTIVE;
1094 obt_xml_register(i, "placement", parse_placement, NULL);
1096 STRUT_PARTIAL_SET(config_margins, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1098 obt_xml_register(i, "margins", parse_margins, NULL);
1100 config_theme = NULL;
1102 config_animate_iconify = TRUE;
1103 config_title_layout = g_strdup("NLIMC");
1104 config_theme_keepborder = TRUE;
1105 config_theme_window_list_icon_size = 36;
1107 config_font_activewindow = NULL;
1108 config_font_inactivewindow = NULL;
1109 config_font_menuitem = NULL;
1110 config_font_menutitle = NULL;
1111 config_font_activeosd = NULL;
1112 config_font_inactiveosd = NULL;
1114 obt_xml_register(i, "theme", parse_theme, NULL);
1116 config_desktops_num = 4;
1117 config_screen_firstdesk = 1;
1118 config_emulate_xinerama = FALSE;
1119 config_desktops_names = NULL;
1120 config_desktop_popup_time = 875;
1122 obt_xml_register(i, "desktops", parse_desktops, NULL);
1124 config_resize_redraw = TRUE;
1125 config_resize_popup_show = 1; /* nonpixel increments */
1126 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
1127 GRAVITY_COORD_SET(config_resize_popup_fixed.x, 0, FALSE, FALSE);
1128 GRAVITY_COORD_SET(config_resize_popup_fixed.y, 0, FALSE, FALSE);
1130 obt_xml_register(i, "resize", parse_resize, NULL);
1132 config_dock_layer = OB_STACKING_LAYER_ABOVE;
1133 config_dock_pos = OB_DIRECTION_NORTHEAST;
1134 config_dock_floating = FALSE;
1135 config_dock_nostrut = FALSE;
1138 config_dock_orient = OB_ORIENTATION_VERT;
1139 config_dock_hide = FALSE;
1140 config_dock_hide_delay = 300;
1141 config_dock_show_delay = 300;
1142 config_dock_app_move_button = 2; /* middle */
1143 config_dock_app_move_modifiers = 0;
1145 obt_xml_register(i, "dock", parse_dock, NULL);
1147 translate_key("C-g", &config_keyboard_reset_state,
1148 &config_keyboard_reset_keycode);
1150 bind_default_keyboard();
1152 obt_xml_register(i, "keyboard", parse_keyboard, NULL);
1154 config_mouse_threshold = 8;
1155 config_mouse_dclicktime = 500;
1156 config_mouse_screenedgetime = 400;
1157 config_mouse_screenedgewarp = FALSE;
1159 bind_default_mouse();
1161 obt_xml_register(i, "mouse", parse_mouse, NULL);
1163 config_resist_win = 10;
1164 config_resist_edge = 20;
1166 obt_xml_register(i, "resistance", parse_resistance, NULL);
1168 config_menu_hide_delay = 250;
1169 config_menu_middle = FALSE;
1170 config_submenu_show_delay = 100;
1171 config_submenu_hide_delay = 400;
1172 config_menu_manage_desktops = TRUE;
1173 config_menu_files = NULL;
1174 config_menu_show_icons = TRUE;
1176 obt_xml_register(i, "menu", parse_menu, NULL);
1178 config_per_app_settings = NULL;
1180 obt_xml_register(i, "applications", parse_per_app_settings, NULL);
1183 void config_shutdown(void)
1187 g_free(config_theme);
1189 g_free(config_title_layout);
1191 RrFontClose(config_font_activewindow);
1192 RrFontClose(config_font_inactivewindow);
1193 RrFontClose(config_font_menuitem);
1194 RrFontClose(config_font_menutitle);
1195 RrFontClose(config_font_activeosd);
1196 RrFontClose(config_font_inactiveosd);
1198 for (it = config_desktops_names; it; it = g_slist_next(it))
1200 g_slist_free(config_desktops_names);
1202 for (it = config_menu_files; it; it = g_slist_next(it))
1204 g_slist_free(config_menu_files);
1206 for (it = config_per_app_settings; it; it = g_slist_next(it)) {
1207 ObAppSettings *itd = (ObAppSettings *)it->data;
1208 if (itd->name) g_pattern_spec_free(itd->name);
1209 if (itd->role) g_pattern_spec_free(itd->role);
1210 if (itd->title) g_pattern_spec_free(itd->title);
1211 if (itd->class) g_pattern_spec_free(itd->class);
1212 if (itd->group_name) g_pattern_spec_free(itd->group_name);
1213 if (itd->group_class) g_pattern_spec_free(itd->group_class);
1214 g_slice_free(ObAppSettings, it->data);
1216 g_slist_free(config_per_app_settings);