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;
67 gint config_emulate_xinerama;
69 gboolean config_resize_redraw;
70 gint config_resize_popup_show;
71 ObResizePopupPos config_resize_popup_pos;
72 GravityPoint config_resize_popup_fixed;
74 ObStackingLayer config_dock_layer;
75 gboolean config_dock_floating;
76 gboolean config_dock_nostrut;
77 ObDirection config_dock_pos;
80 ObOrientation config_dock_orient;
81 gboolean config_dock_hide;
82 guint config_dock_hide_delay;
83 guint config_dock_show_delay;
84 guint config_dock_app_move_button;
85 guint config_dock_app_move_modifiers;
87 guint config_keyboard_reset_keycode;
88 guint config_keyboard_reset_state;
89 gboolean config_keyboard_rebind_on_mapping_notify;
91 gint config_mouse_threshold;
92 gint config_mouse_dclicktime;
93 gint config_mouse_screenedgetime;
94 gboolean config_mouse_screenedgewarp;
96 guint config_menu_hide_delay;
97 gboolean config_menu_middle;
98 guint config_submenu_show_delay;
99 guint config_submenu_hide_delay;
100 gboolean config_menu_manage_desktops;
101 gboolean config_menu_show_icons;
103 GSList *config_menu_files;
105 gint config_resist_win;
106 gint config_resist_edge;
108 GSList *config_per_app_settings;
110 ObAppSettings* config_create_app_settings(void)
112 ObAppSettings *settings = g_slice_new0(ObAppSettings);
114 settings->decor = -1;
115 settings->shade = -1;
116 settings->monitor_type = OB_PLACE_MONITOR_ANY;
117 settings->monitor = -1;
118 settings->focus = -1;
119 settings->desktop = 0;
120 settings->layer = -2;
121 settings->iconic = -1;
122 settings->skip_pager = -1;
123 settings->skip_taskbar = -1;
124 settings->fullscreen = -1;
125 settings->max_horz = -1;
126 settings->max_vert = -1;
130 #define copy_if(setting, default) \
131 if (src->setting != default) dst->setting = src->setting
132 void config_app_settings_copy_non_defaults(const ObAppSettings *src,
135 g_assert(src != NULL);
136 g_assert(dst != NULL);
138 copy_if(type, (ObClientType)-1);
141 copy_if(monitor_type, OB_PLACE_MONITOR_ANY);
142 copy_if(monitor, -1);
147 copy_if(skip_pager, -1);
148 copy_if(skip_taskbar, -1);
149 copy_if(fullscreen, -1);
150 copy_if(max_horz, -1);
151 copy_if(max_vert, -1);
153 if (src->pos_given) {
154 dst->pos_given = TRUE;
155 dst->pos_force = src->pos_force;
156 dst->position = src->position;
157 /* monitor is copied above */
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;
166 void config_parse_relative_number(gchar *s, gint *num, gint *denom)
168 *num = strtol(s, &s, 10);
172 } else if (*s == '/') {
177 void config_parse_gravity_coord(xmlNodePtr node, GravityCoord *c)
179 gchar *s = obt_xml_node_string(node);
180 if (!g_ascii_strcasecmp(s, "center"))
186 if (s[0] == '-' || s[0] == '+')
188 config_parse_relative_number(ps, &c->pos, &c->denom);
195 <application name="aterm">
198 <application name="Rhythmbox">
205 .. there is a lot more settings available
210 static void parse_single_per_app_settings(xmlNodePtr app,
211 ObAppSettings *settings)
214 gboolean x_pos_given = FALSE;
216 if ((n = obt_xml_find_node(app->children, "decor")))
217 if (!obt_xml_node_contains(n, "default"))
218 settings->decor = obt_xml_node_bool(n);
220 if ((n = obt_xml_find_node(app->children, "shade")))
221 if (!obt_xml_node_contains(n, "default"))
222 settings->shade = obt_xml_node_bool(n);
224 if ((n = obt_xml_find_node(app->children, "position"))) {
225 if ((c = obt_xml_find_node(n->children, "x"))) {
226 if (!obt_xml_node_contains(c, "default")) {
227 config_parse_gravity_coord(c, &settings->position.x);
232 if (x_pos_given && (c = obt_xml_find_node(n->children, "y"))) {
233 if (!obt_xml_node_contains(c, "default")) {
234 config_parse_gravity_coord(c, &settings->position.y);
235 settings->pos_given = TRUE;
239 /* monitor can be set without setting x or y */
240 if ((c = obt_xml_find_node(n->children, "monitor"))) {
241 if (!obt_xml_node_contains(c, "default")) {
242 gchar *s = obt_xml_node_string(c);
243 if (!g_ascii_strcasecmp(s, "mouse"))
244 settings->monitor_type = OB_PLACE_MONITOR_MOUSE;
245 else if (!g_ascii_strcasecmp(s, "active"))
246 settings->monitor_type = OB_PLACE_MONITOR_ACTIVE;
247 else if (!g_ascii_strcasecmp(s, "primary"))
248 settings->monitor_type = OB_PLACE_MONITOR_PRIMARY;
250 settings->monitor = obt_xml_node_int(c);
255 obt_xml_attr_bool(n, "force", &settings->pos_force);
258 if ((n = obt_xml_find_node(app->children, "size"))) {
259 if ((c = obt_xml_find_node(n->children, "width"))) {
260 if (!obt_xml_node_contains(c, "default")) {
261 gchar *s = obt_xml_node_string(c);
262 config_parse_relative_number(s,
263 &settings->width_num,
264 &settings->width_denom);
265 if (settings->width_num <= 0 || settings->width_denom < 0)
266 settings->width_num = settings->width_denom = 0;
271 if ((c = obt_xml_find_node(n->children, "height"))) {
272 if (!obt_xml_node_contains(c, "default")) {
273 gchar *s = obt_xml_node_string(c);
274 config_parse_relative_number(s,
275 &settings->height_num,
276 &settings->height_denom);
277 if (settings->height_num <= 0 || settings->height_denom < 0)
278 settings->height_num = settings->height_denom = 0;
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;
453 gboolean repeat = FALSE;
455 if (!obt_xml_attr_string(node, "key", &keystring))
458 obt_xml_attr_bool(node, "chroot", &is_chroot);
459 obt_xml_attr_bool(node, "grab", &grab);
460 obt_xml_attr_bool(node, "repeat", &repeat);
462 keys = g_strsplit(keystring, " ", 0);
463 for (key = keys; *key; ++key) {
464 keylist = g_list_append(keylist, *key);
466 if ((n = obt_xml_find_node(node->children, "keybind"))) {
468 parse_key(n, keylist);
469 n = obt_xml_find_node(n->next, "keybind");
472 else if ((n = obt_xml_find_node(node->children, "action"))) {
474 ObActionsAct *action;
476 action = actions_parse(n);
478 keyboard_bind(keylist, action, grab, !repeat);
479 n = obt_xml_find_node(n->next, "action");
485 keyboard_chroot(keylist);
486 keylist = g_list_delete_link(keylist, g_list_last(keylist));
493 static void parse_keyboard(xmlNodePtr node, gpointer d)
498 keyboard_unbind_all();
500 if ((n = obt_xml_find_node(node->children, "chainQuitKey"))) {
501 key = obt_xml_node_string(n);
502 translate_key(key, &config_keyboard_reset_state,
503 &config_keyboard_reset_keycode);
507 if ((n = obt_xml_find_node(node->children, "keybind")))
510 n = obt_xml_find_node(n->next, "keybind");
513 if ((n = obt_xml_find_node(node->children, "rebindOnMappingNotify")))
514 config_keyboard_rebind_on_mapping_notify = obt_xml_node_bool(n);
519 <context name="Titlebar">
520 <mousebind button="Left" action="Press">
521 <action name="Raise"></action>
527 static void parse_mouse(xmlNodePtr node, gpointer d)
529 xmlNodePtr n, nbut, nact;
536 node = node->children;
538 if ((n = obt_xml_find_node(node, "dragThreshold")))
539 config_mouse_threshold = obt_xml_node_int(n);
540 if ((n = obt_xml_find_node(node, "doubleClickTime")))
541 config_mouse_dclicktime = obt_xml_node_int(n);
542 if ((n = obt_xml_find_node(node, "screenEdgeWarpTime"))) {
543 config_mouse_screenedgetime = obt_xml_node_int(n);
544 /* minimum value of 25 for this property, when it is 1 and you hit the
545 edge it basically never stops */
546 if (config_mouse_screenedgetime && config_mouse_screenedgetime < 25)
547 config_mouse_screenedgetime = 25;
549 if ((n = obt_xml_find_node(node, "screenEdgeWarpMouse")))
550 config_mouse_screenedgewarp = obt_xml_node_bool(n);
552 for (n = obt_xml_find_node(node, "context");
554 n = obt_xml_find_node(n->next, "context"))
559 if (!obt_xml_attr_string(n, "name", &cxstr))
562 modcxstr = g_strdup(cxstr); /* make a copy to mutilate */
563 while (frame_next_context_from_string(modcxstr, &cx)) {
565 gchar *s = strchr(modcxstr, ' ');
568 g_message(_("Invalid context \"%s\" in mouse binding"),
575 for (nbut = obt_xml_find_node(n->children, "mousebind");
577 nbut = obt_xml_find_node(nbut->next, "mousebind"))
580 gchar **button, **buttons;
582 if (!obt_xml_attr_string(nbut, "button", &buttonstr))
584 if (obt_xml_attr_contains(nbut, "action", "press"))
585 mact = OB_MOUSE_ACTION_PRESS;
586 else if (obt_xml_attr_contains(nbut, "action", "release"))
587 mact = OB_MOUSE_ACTION_RELEASE;
588 else if (obt_xml_attr_contains(nbut, "action", "click"))
589 mact = OB_MOUSE_ACTION_CLICK;
590 else if (obt_xml_attr_contains(nbut, "action","doubleclick"))
591 mact = OB_MOUSE_ACTION_DOUBLE_CLICK;
592 else if (obt_xml_attr_contains(nbut, "action", "drag"))
593 mact = OB_MOUSE_ACTION_MOTION;
597 buttons = g_strsplit(buttonstr, " ", 0);
598 for (nact = obt_xml_find_node(nbut->children, "action");
600 nact = obt_xml_find_node(nact->next, "action"))
602 ObActionsAct *action;
604 /* actions_parse() creates one ref to the action, but we need
605 * exactly one ref per binding we use it for. */
606 if ((action = actions_parse(nact))) {
607 for (button = buttons; *button; ++button) {
608 actions_act_ref(action);
609 mouse_bind(*button, cx, mact, action);
611 actions_act_unref(action);
623 static void parse_focus(xmlNodePtr node, gpointer d)
627 node = node->children;
629 if ((n = obt_xml_find_node(node, "focusNew")))
630 config_focus_new = obt_xml_node_bool(n);
631 if ((n = obt_xml_find_node(node, "followMouse")))
632 config_focus_follow = obt_xml_node_bool(n);
633 if ((n = obt_xml_find_node(node, "focusDelay")))
634 config_focus_delay = obt_xml_node_int(n);
635 if ((n = obt_xml_find_node(node, "raiseOnFocus")))
636 config_focus_raise = obt_xml_node_bool(n);
637 if ((n = obt_xml_find_node(node, "focusLast")))
638 config_focus_last = obt_xml_node_bool(n);
639 if ((n = obt_xml_find_node(node, "underMouse")))
640 config_focus_under_mouse = obt_xml_node_bool(n);
641 if ((n = obt_xml_find_node(node, "unfocusOnLeave")))
642 config_unfocus_leave = obt_xml_node_bool(n);
645 static void parse_placement(xmlNodePtr node, gpointer d)
649 node = node->children;
651 if ((n = obt_xml_find_node(node, "policy"))) {
652 if (obt_xml_node_contains(n, "UnderMouse"))
653 config_place_policy = OB_PLACE_POLICY_MOUSE;
654 if (obt_xml_node_contains(n, "Random"))
655 config_place_policy = OB_PLACE_POLICY_RANDOM;
657 if ((n = obt_xml_find_node(node, "center"))) {
658 config_place_center = obt_xml_node_bool(n);
660 if ((n = obt_xml_find_node(node, "monitor"))) {
661 if (obt_xml_node_contains(n, "active"))
662 config_place_monitor = OB_PLACE_MONITOR_ACTIVE;
663 else if (obt_xml_node_contains(n, "mouse"))
664 config_place_monitor = OB_PLACE_MONITOR_MOUSE;
665 else if (obt_xml_node_contains(n, "any"))
666 config_place_monitor = OB_PLACE_MONITOR_ANY;
668 if ((n = obt_xml_find_node(node, "primaryMonitor"))) {
669 config_primary_monitor_index = obt_xml_node_int(n);
670 if (!config_primary_monitor_index) {
671 if (obt_xml_node_contains(n, "mouse"))
672 config_primary_monitor = OB_PLACE_MONITOR_MOUSE;
677 static void parse_margins(xmlNodePtr node, gpointer d)
681 node = node->children;
683 if ((n = obt_xml_find_node(node, "top")))
684 config_margins.top = MAX(0, obt_xml_node_int(n));
685 if ((n = obt_xml_find_node(node, "left")))
686 config_margins.left = MAX(0, obt_xml_node_int(n));
687 if ((n = obt_xml_find_node(node, "right")))
688 config_margins.right = MAX(0, obt_xml_node_int(n));
689 if ((n = obt_xml_find_node(node, "bottom")))
690 config_margins.bottom = MAX(0, obt_xml_node_int(n));
693 static void parse_theme(xmlNodePtr node, gpointer d)
697 node = node->children;
699 if ((n = obt_xml_find_node(node, "name"))) {
702 g_free(config_theme);
703 c = obt_xml_node_string(n);
704 config_theme = obt_paths_expand_tilde(c);
707 if ((n = obt_xml_find_node(node, "titleLayout"))) {
710 g_free(config_title_layout);
711 config_title_layout = obt_xml_node_string(n);
713 /* replace duplicates with spaces */
714 for (c = config_title_layout; *c != '\0'; ++c)
715 for (d = c+1; *d != '\0'; ++d)
716 if (*c == *d) *d = ' ';
718 if ((n = obt_xml_find_node(node, "keepBorder")))
719 config_theme_keepborder = obt_xml_node_bool(n);
720 if ((n = obt_xml_find_node(node, "animateIconify")))
721 config_animate_iconify = obt_xml_node_bool(n);
722 if ((n = obt_xml_find_node(node, "windowListIconSize"))) {
723 config_theme_window_list_icon_size = obt_xml_node_int(n);
724 if (config_theme_window_list_icon_size < 16)
725 config_theme_window_list_icon_size = 16;
726 else if (config_theme_window_list_icon_size > 96)
727 config_theme_window_list_icon_size = 96;
730 for (n = obt_xml_find_node(node, "font");
732 n = obt_xml_find_node(n->next, "font"))
736 gchar *name = g_strdup(RrDefaultFontFamily);
737 gint size = RrDefaultFontSize;
738 RrFontWeight weight = RrDefaultFontWeight;
739 RrFontSlant slant = RrDefaultFontSlant;
741 if (obt_xml_attr_contains(n, "place", "ActiveWindow"))
742 font = &config_font_activewindow;
743 else if (obt_xml_attr_contains(n, "place", "InactiveWindow"))
744 font = &config_font_inactivewindow;
745 else if (obt_xml_attr_contains(n, "place", "MenuHeader"))
746 font = &config_font_menutitle;
747 else if (obt_xml_attr_contains(n, "place", "MenuItem"))
748 font = &config_font_menuitem;
749 else if (obt_xml_attr_contains(n, "place", "ActiveOnScreenDisplay"))
750 font = &config_font_activeosd;
751 else if (obt_xml_attr_contains(n, "place", "OnScreenDisplay"))
752 font = &config_font_activeosd;
753 else if (obt_xml_attr_contains(n, "place","InactiveOnScreenDisplay"))
754 font = &config_font_inactiveosd;
758 if ((fnode = obt_xml_find_node(n->children, "name"))) {
760 name = obt_xml_node_string(fnode);
762 if ((fnode = obt_xml_find_node(n->children, "size"))) {
763 int s = obt_xml_node_int(fnode);
766 if ((fnode = obt_xml_find_node(n->children, "weight"))) {
767 gchar *w = obt_xml_node_string(fnode);
768 if (!g_ascii_strcasecmp(w, "Bold"))
769 weight = RR_FONTWEIGHT_BOLD;
772 if ((fnode = obt_xml_find_node(n->children, "slant"))) {
773 gchar *s = obt_xml_node_string(fnode);
774 if (!g_ascii_strcasecmp(s, "Italic"))
775 slant = RR_FONTSLANT_ITALIC;
776 if (!g_ascii_strcasecmp(s, "Oblique"))
777 slant = RR_FONTSLANT_OBLIQUE;
781 *font = RrFontOpen(ob_rr_inst, name, size, weight, slant);
784 if ((fnode = obt_xml_find_node(n->children, "description"))) {
785 gchar *s = obt_xml_node_string(fnode);
786 RrFontDescriptionFromString(*font, s);
792 static void parse_desktops(xmlNodePtr node, gpointer d)
796 node = node->children;
798 if ((n = obt_xml_find_node(node, "number"))) {
799 gint d = obt_xml_node_int(n);
801 config_desktops_num = (unsigned) d;
803 if ((n = obt_xml_find_node(node, "firstdesk"))) {
804 gint d = obt_xml_node_int(n);
806 config_screen_firstdesk = (unsigned) d;
808 if ((n = obt_xml_find_node(node, "emulatexinerama")))
809 config_emulate_xinerama = obt_xml_node_bool(n);
810 if ((n = obt_xml_find_node(node, "names"))) {
814 for (it = config_desktops_names; it; it = it->next)
816 g_slist_free(config_desktops_names);
817 config_desktops_names = NULL;
819 for (nname = obt_xml_find_node(n->children, "name");
821 nname = obt_xml_find_node(nname->next, "name"))
823 config_desktops_names =
824 g_slist_append(config_desktops_names,
825 obt_xml_node_string(nname));
828 if ((n = obt_xml_find_node(node, "popupTime")))
829 config_desktop_popup_time = obt_xml_node_int(n);
832 static void parse_resize(xmlNodePtr node, gpointer d)
836 node = node->children;
838 if ((n = obt_xml_find_node(node, "drawContents")))
839 config_resize_redraw = obt_xml_node_bool(n);
840 if ((n = obt_xml_find_node(node, "popupShow"))) {
841 config_resize_popup_show = obt_xml_node_int(n);
842 if (obt_xml_node_contains(n, "Always"))
843 config_resize_popup_show = 2;
844 else if (obt_xml_node_contains(n, "Never"))
845 config_resize_popup_show = 0;
846 else if (obt_xml_node_contains(n, "Nonpixel"))
847 config_resize_popup_show = 1;
849 if ((n = obt_xml_find_node(node, "popupPosition"))) {
850 if (obt_xml_node_contains(n, "Top"))
851 config_resize_popup_pos = OB_RESIZE_POS_TOP;
852 else if (obt_xml_node_contains(n, "Center"))
853 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
854 else if (obt_xml_node_contains(n, "Fixed")) {
855 config_resize_popup_pos = OB_RESIZE_POS_FIXED;
857 if ((n = obt_xml_find_node(node, "popupFixedPosition"))) {
860 if ((n2 = obt_xml_find_node(n->children, "x")))
861 config_parse_gravity_coord(n2,
862 &config_resize_popup_fixed.x);
863 if ((n2 = obt_xml_find_node(n->children, "y")))
864 config_parse_gravity_coord(n2,
865 &config_resize_popup_fixed.y);
867 config_resize_popup_fixed.x.pos =
868 MAX(config_resize_popup_fixed.x.pos, 0);
869 config_resize_popup_fixed.y.pos =
870 MAX(config_resize_popup_fixed.y.pos, 0);
876 static void parse_dock(xmlNodePtr node, gpointer d)
880 node = node->children;
882 if ((n = obt_xml_find_node(node, "position"))) {
883 if (obt_xml_node_contains(n, "TopLeft"))
884 config_dock_floating = FALSE,
885 config_dock_pos = OB_DIRECTION_NORTHWEST;
886 else if (obt_xml_node_contains(n, "Top"))
887 config_dock_floating = FALSE,
888 config_dock_pos = OB_DIRECTION_NORTH;
889 else if (obt_xml_node_contains(n, "TopRight"))
890 config_dock_floating = FALSE,
891 config_dock_pos = OB_DIRECTION_NORTHEAST;
892 else if (obt_xml_node_contains(n, "Right"))
893 config_dock_floating = FALSE,
894 config_dock_pos = OB_DIRECTION_EAST;
895 else if (obt_xml_node_contains(n, "BottomRight"))
896 config_dock_floating = FALSE,
897 config_dock_pos = OB_DIRECTION_SOUTHEAST;
898 else if (obt_xml_node_contains(n, "Bottom"))
899 config_dock_floating = FALSE,
900 config_dock_pos = OB_DIRECTION_SOUTH;
901 else if (obt_xml_node_contains(n, "BottomLeft"))
902 config_dock_floating = FALSE,
903 config_dock_pos = OB_DIRECTION_SOUTHWEST;
904 else if (obt_xml_node_contains(n, "Left"))
905 config_dock_floating = FALSE,
906 config_dock_pos = OB_DIRECTION_WEST;
907 else if (obt_xml_node_contains(n, "Floating"))
908 config_dock_floating = TRUE;
910 if (config_dock_floating) {
911 if ((n = obt_xml_find_node(node, "floatingX")))
912 config_dock_x = obt_xml_node_int(n);
913 if ((n = obt_xml_find_node(node, "floatingY")))
914 config_dock_y = obt_xml_node_int(n);
916 if ((n = obt_xml_find_node(node, "noStrut")))
917 config_dock_nostrut = obt_xml_node_bool(n);
919 if ((n = obt_xml_find_node(node, "stacking"))) {
920 if (obt_xml_node_contains(n, "normal"))
921 config_dock_layer = OB_STACKING_LAYER_NORMAL;
922 else if (obt_xml_node_contains(n, "below"))
923 config_dock_layer = OB_STACKING_LAYER_BELOW;
924 else if (obt_xml_node_contains(n, "above"))
925 config_dock_layer = OB_STACKING_LAYER_ABOVE;
927 if ((n = obt_xml_find_node(node, "direction"))) {
928 if (obt_xml_node_contains(n, "horizontal"))
929 config_dock_orient = OB_ORIENTATION_HORZ;
930 else if (obt_xml_node_contains(n, "vertical"))
931 config_dock_orient = OB_ORIENTATION_VERT;
933 if ((n = obt_xml_find_node(node, "autoHide")))
934 config_dock_hide = obt_xml_node_bool(n);
935 if ((n = obt_xml_find_node(node, "hideDelay")))
936 config_dock_hide_delay = obt_xml_node_int(n);
937 if ((n = obt_xml_find_node(node, "showDelay")))
938 config_dock_show_delay = obt_xml_node_int(n);
939 if ((n = obt_xml_find_node(node, "moveButton"))) {
940 gchar *str = obt_xml_node_string(n);
942 if (translate_button(str, &s, &b)) {
943 config_dock_app_move_button = b;
944 config_dock_app_move_modifiers = s;
946 g_message(_("Invalid button \"%s\" specified in config file"), str);
952 static void parse_menu(xmlNodePtr node, gpointer d)
955 node = node->children;
957 if ((n = obt_xml_find_node(node, "hideDelay")))
958 config_menu_hide_delay = obt_xml_node_int(n);
959 if ((n = obt_xml_find_node(node, "middle")))
960 config_menu_middle = obt_xml_node_bool(n);
961 if ((n = obt_xml_find_node(node, "submenuShowDelay")))
962 config_submenu_show_delay = obt_xml_node_int(n);
963 if ((n = obt_xml_find_node(node, "submenuHideDelay")))
964 config_submenu_hide_delay = obt_xml_node_int(n);
965 if ((n = obt_xml_find_node(node, "manageDesktops")))
966 config_menu_manage_desktops = obt_xml_node_bool(n);
967 if ((n = obt_xml_find_node(node, "showIcons"))) {
968 config_menu_show_icons = obt_xml_node_bool(n);
969 #if !defined(USE_IMLIB2) && !defined(USE_LIBRSVG)
970 if (config_menu_show_icons)
971 g_message(_("Openbox was compiled without image loading support. Icons in menus will not be loaded."));
975 for (node = obt_xml_find_node(node, "file");
977 node = obt_xml_find_node(node->next, "file"))
979 gchar *c = obt_xml_node_string(node);
980 config_menu_files = g_slist_append(config_menu_files,
981 obt_paths_expand_tilde(c));
986 static void parse_resistance(xmlNodePtr node, gpointer d)
990 node = node->children;
991 if ((n = obt_xml_find_node(node, "strength")))
992 config_resist_win = obt_xml_node_int(n);
993 if ((n = obt_xml_find_node(node, "screen_edge_strength")))
994 config_resist_edge = obt_xml_node_int(n);
1000 const gchar *actname;
1003 static void bind_default_keyboard(void)
1006 ObDefKeyBind binds[] = {
1007 { "A-Tab", "NextWindow" },
1008 { "S-A-Tab", "PreviousWindow" },
1009 { "A-F4", "Close" },
1012 for (it = binds; it->key; ++it) {
1013 GList *l = g_list_append(NULL, g_strdup(it->key));
1014 keyboard_bind(l, actions_parse_string(it->actname), TRUE, TRUE);
1020 const gchar *button;
1021 const gchar *context;
1022 const ObMouseAction mact;
1023 const gchar *actname;
1026 static void bind_default_mouse(void)
1029 ObDefMouseBind binds[] = {
1030 { "Left", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
1031 { "Middle", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
1032 { "Right", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
1033 { "Left", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
1034 { "Middle", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
1035 { "Right", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
1036 { "Left", "Titlebar", OB_MOUSE_ACTION_PRESS, "Focus" },
1037 { "Left", "Bottom", OB_MOUSE_ACTION_PRESS, "Focus" },
1038 { "Left", "BLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
1039 { "Left", "BRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
1040 { "Left", "TLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
1041 { "Left", "TRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
1042 { "Left", "Close", OB_MOUSE_ACTION_PRESS, "Focus" },
1043 { "Left", "Maximize", OB_MOUSE_ACTION_PRESS, "Focus" },
1044 { "Left", "Iconify", OB_MOUSE_ACTION_PRESS, "Focus" },
1045 { "Left", "Icon", OB_MOUSE_ACTION_PRESS, "Focus" },
1046 { "Left", "AllDesktops", OB_MOUSE_ACTION_PRESS, "Focus" },
1047 { "Left", "Shade", OB_MOUSE_ACTION_PRESS, "Focus" },
1048 { "Left", "Client", OB_MOUSE_ACTION_CLICK, "Raise" },
1049 { "Left", "Titlebar", OB_MOUSE_ACTION_CLICK, "Raise" },
1050 { "Middle", "Titlebar", OB_MOUSE_ACTION_CLICK, "Lower" },
1051 { "Left", "BLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
1052 { "Left", "BRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
1053 { "Left", "TLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
1054 { "Left", "TRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
1055 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Raise" },
1056 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "Raise" },
1057 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Raise" },
1058 { "Left", "Icon", OB_MOUSE_ACTION_CLICK, "Raise" },
1059 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "Raise" },
1060 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "Raise" },
1061 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Close" },
1062 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "ToggleMaximize" },
1063 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Iconify" },
1064 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "ToggleOmnipresent" },
1065 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "ToggleShade" },
1066 { "Left", "TLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
1067 { "Left", "TRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
1068 { "Left", "BLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
1069 { "Left", "BRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
1070 { "Left", "Top", OB_MOUSE_ACTION_MOTION, "Resize" },
1071 { "Left", "Bottom", OB_MOUSE_ACTION_MOTION, "Resize" },
1072 { "Left", "Left", OB_MOUSE_ACTION_MOTION, "Resize" },
1073 { "Left", "Right", OB_MOUSE_ACTION_MOTION, "Resize" },
1074 { "Left", "Titlebar", OB_MOUSE_ACTION_MOTION, "Move" },
1075 { "A-Left", "Frame", OB_MOUSE_ACTION_MOTION, "Move" },
1076 { "A-Middle", "Frame", OB_MOUSE_ACTION_MOTION, "Resize" },
1077 { NULL, NULL, 0, NULL }
1080 for (it = binds; it->button; ++it)
1081 mouse_bind(it->button, frame_context_from_string(it->context),
1082 it->mact, actions_parse_string(it->actname));
1085 void config_startup(ObtXmlInst *i)
1087 config_focus_new = TRUE;
1088 config_focus_follow = FALSE;
1089 config_focus_delay = 0;
1090 config_focus_raise = FALSE;
1091 config_focus_last = TRUE;
1092 config_focus_under_mouse = FALSE;
1093 config_unfocus_leave = FALSE;
1095 obt_xml_register(i, "focus", parse_focus, NULL);
1097 config_place_policy = OB_PLACE_POLICY_SMART;
1098 config_place_center = TRUE;
1099 config_place_monitor = OB_PLACE_MONITOR_PRIMARY;
1101 config_primary_monitor_index = 1;
1102 config_primary_monitor = OB_PLACE_MONITOR_ACTIVE;
1104 obt_xml_register(i, "placement", parse_placement, NULL);
1106 STRUT_PARTIAL_SET(config_margins, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1108 obt_xml_register(i, "margins", parse_margins, NULL);
1110 config_theme = NULL;
1112 config_animate_iconify = TRUE;
1113 config_title_layout = g_strdup("NLIMC");
1114 config_theme_keepborder = TRUE;
1115 config_theme_window_list_icon_size = 36;
1117 config_font_activewindow = NULL;
1118 config_font_inactivewindow = NULL;
1119 config_font_menuitem = NULL;
1120 config_font_menutitle = NULL;
1121 config_font_activeosd = NULL;
1122 config_font_inactiveosd = NULL;
1124 obt_xml_register(i, "theme", parse_theme, NULL);
1126 config_desktops_num = 4;
1127 config_screen_firstdesk = 1;
1128 config_emulate_xinerama = FALSE;
1129 config_desktops_names = NULL;
1130 config_desktop_popup_time = 875;
1132 obt_xml_register(i, "desktops", parse_desktops, NULL);
1134 config_resize_redraw = TRUE;
1135 config_resize_popup_show = 1; /* nonpixel increments */
1136 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
1137 GRAVITY_COORD_SET(config_resize_popup_fixed.x, 0, FALSE, FALSE);
1138 GRAVITY_COORD_SET(config_resize_popup_fixed.y, 0, FALSE, FALSE);
1140 obt_xml_register(i, "resize", parse_resize, NULL);
1142 config_dock_layer = OB_STACKING_LAYER_ABOVE;
1143 config_dock_pos = OB_DIRECTION_NORTHEAST;
1144 config_dock_floating = FALSE;
1145 config_dock_nostrut = FALSE;
1148 config_dock_orient = OB_ORIENTATION_VERT;
1149 config_dock_hide = FALSE;
1150 config_dock_hide_delay = 300;
1151 config_dock_show_delay = 300;
1152 config_dock_app_move_button = 2; /* middle */
1153 config_dock_app_move_modifiers = 0;
1155 obt_xml_register(i, "dock", parse_dock, NULL);
1157 translate_key("C-g", &config_keyboard_reset_state,
1158 &config_keyboard_reset_keycode);
1159 config_keyboard_rebind_on_mapping_notify = TRUE;
1161 bind_default_keyboard();
1163 obt_xml_register(i, "keyboard", parse_keyboard, NULL);
1165 config_mouse_threshold = 8;
1166 config_mouse_dclicktime = 500;
1167 config_mouse_screenedgetime = 400;
1168 config_mouse_screenedgewarp = FALSE;
1170 bind_default_mouse();
1172 obt_xml_register(i, "mouse", parse_mouse, NULL);
1174 config_resist_win = 10;
1175 config_resist_edge = 20;
1177 obt_xml_register(i, "resistance", parse_resistance, NULL);
1179 config_menu_hide_delay = 250;
1180 config_menu_middle = FALSE;
1181 config_submenu_show_delay = 100;
1182 config_submenu_hide_delay = 400;
1183 config_menu_manage_desktops = TRUE;
1184 config_menu_files = NULL;
1185 config_menu_show_icons = TRUE;
1187 obt_xml_register(i, "menu", parse_menu, NULL);
1189 config_per_app_settings = NULL;
1191 obt_xml_register(i, "applications", parse_per_app_settings, NULL);
1194 void config_shutdown(void)
1198 g_free(config_theme);
1200 g_free(config_title_layout);
1202 RrFontClose(config_font_activewindow);
1203 RrFontClose(config_font_inactivewindow);
1204 RrFontClose(config_font_menuitem);
1205 RrFontClose(config_font_menutitle);
1206 RrFontClose(config_font_activeosd);
1207 RrFontClose(config_font_inactiveosd);
1209 for (it = config_desktops_names; it; it = g_slist_next(it))
1211 g_slist_free(config_desktops_names);
1213 for (it = config_menu_files; it; it = g_slist_next(it))
1215 g_slist_free(config_menu_files);
1217 for (it = config_per_app_settings; it; it = g_slist_next(it)) {
1218 ObAppSettings *itd = (ObAppSettings *)it->data;
1219 if (itd->name) g_pattern_spec_free(itd->name);
1220 if (itd->role) g_pattern_spec_free(itd->role);
1221 if (itd->title) g_pattern_spec_free(itd->title);
1222 if (itd->class) g_pattern_spec_free(itd->class);
1223 if (itd->group_name) g_pattern_spec_free(itd->group_name);
1224 if (itd->group_class) g_pattern_spec_free(itd->group_class);
1225 g_slice_free(ObAppSettings, it->data);
1227 g_slist_free(config_per_app_settings);