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;
38 guint config_directional_distance_weight;
39 guint config_directional_angle_weight;
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;
69 gint config_emulate_xinerama;
71 gboolean config_resize_redraw;
72 gint config_resize_popup_show;
73 ObResizePopupPos config_resize_popup_pos;
74 GravityPoint config_resize_popup_fixed;
76 ObStackingLayer config_dock_layer;
77 gboolean config_dock_floating;
78 gboolean config_dock_nostrut;
79 ObDirection config_dock_pos;
82 ObOrientation config_dock_orient;
83 gboolean config_dock_hide;
84 guint config_dock_hide_delay;
85 guint config_dock_show_delay;
86 guint config_dock_app_move_button;
87 guint config_dock_app_move_modifiers;
89 guint config_keyboard_reset_keycode;
90 guint config_keyboard_reset_state;
91 gboolean config_keyboard_rebind_on_mapping_notify;
93 gint config_mouse_threshold;
94 gint config_mouse_dclicktime;
95 gint config_mouse_screenedgetime;
96 gboolean config_mouse_screenedgewarp;
98 guint config_menu_hide_delay;
99 gboolean config_menu_middle;
100 guint config_submenu_show_delay;
101 guint config_submenu_hide_delay;
102 gboolean config_menu_manage_desktops;
103 gboolean config_menu_show_icons;
105 GSList *config_menu_files;
107 gint config_resist_win;
108 gint config_resist_edge;
110 GSList *config_per_app_settings;
112 ObAppSettings* config_create_app_settings(void)
114 ObAppSettings *settings = g_slice_new0(ObAppSettings);
116 settings->decor = -1;
117 settings->shade = -1;
118 settings->monitor_type = OB_PLACE_MONITOR_ANY;
119 settings->monitor = -1;
120 settings->focus = -1;
121 settings->desktop = 0;
122 settings->layer = -2;
123 settings->iconic = -1;
124 settings->skip_pager = -1;
125 settings->skip_taskbar = -1;
126 settings->fullscreen = -1;
127 settings->max_horz = -1;
128 settings->max_vert = -1;
132 #define copy_if(setting, default) \
133 if (src->setting != default) dst->setting = src->setting
134 void config_app_settings_copy_non_defaults(const ObAppSettings *src,
137 g_assert(src != NULL);
138 g_assert(dst != NULL);
140 copy_if(type, (ObClientType)-1);
143 copy_if(monitor_type, OB_PLACE_MONITOR_ANY);
144 copy_if(monitor, -1);
149 copy_if(skip_pager, -1);
150 copy_if(skip_taskbar, -1);
151 copy_if(fullscreen, -1);
152 copy_if(max_horz, -1);
153 copy_if(max_vert, -1);
155 if (src->pos_given) {
156 dst->pos_given = TRUE;
157 dst->pos_force = src->pos_force;
158 dst->position = src->position;
159 /* monitor is copied above */
162 dst->width_num = src->width_num;
163 dst->width_denom = src->width_denom;
164 dst->height_num = src->height_num;
165 dst->height_denom = src->height_denom;
168 void config_parse_relative_number(gchar *s, gint *num, gint *denom)
170 *num = strtol(s, &s, 10);
174 } else if (*s == '/') {
179 void config_parse_gravity_coord(xmlNodePtr node, GravityCoord *c)
181 gchar *s = obt_xml_node_string(node);
182 if (!g_ascii_strcasecmp(s, "center"))
188 if (s[0] == '-' || s[0] == '+')
190 config_parse_relative_number(ps, &c->pos, &c->denom);
197 <application name="aterm">
200 <application name="Rhythmbox">
207 .. there is a lot more settings available
212 static void parse_single_per_app_settings(xmlNodePtr app,
213 ObAppSettings *settings)
216 gboolean x_pos_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)
268 settings->width_num = settings->width_denom = 0;
273 if ((c = obt_xml_find_node(n->children, "height"))) {
274 if (!obt_xml_node_contains(c, "default")) {
275 gchar *s = obt_xml_node_string(c);
276 config_parse_relative_number(s,
277 &settings->height_num,
278 &settings->height_denom);
279 if (settings->height_num <= 0 || settings->height_denom < 0)
280 settings->height_num = settings->height_denom = 0;
286 if ((n = obt_xml_find_node(app->children, "focus"))) {
287 if (!obt_xml_node_contains(n, "default"))
288 settings->focus = obt_xml_node_bool(n);
291 if ((n = obt_xml_find_node(app->children, "desktop"))) {
292 if (!obt_xml_node_contains(n, "default")) {
293 gchar *s = obt_xml_node_string(n);
294 if (!g_ascii_strcasecmp(s, "all"))
295 settings->desktop = DESKTOP_ALL;
297 gint i = obt_xml_node_int(n);
299 settings->desktop = i;
305 if ((n = obt_xml_find_node(app->children, "layer"))) {
306 if (!obt_xml_node_contains(n, "default")) {
307 gchar *s = obt_xml_node_string(n);
308 if (!g_ascii_strcasecmp(s, "above"))
310 else if (!g_ascii_strcasecmp(s, "below"))
311 settings->layer = -1;
318 if ((n = obt_xml_find_node(app->children, "iconic")))
319 if (!obt_xml_node_contains(n, "default"))
320 settings->iconic = obt_xml_node_bool(n);
322 if ((n = obt_xml_find_node(app->children, "skip_pager")))
323 if (!obt_xml_node_contains(n, "default"))
324 settings->skip_pager = obt_xml_node_bool(n);
326 if ((n = obt_xml_find_node(app->children, "skip_taskbar")))
327 if (!obt_xml_node_contains(n, "default"))
328 settings->skip_taskbar = obt_xml_node_bool(n);
330 if ((n = obt_xml_find_node(app->children, "fullscreen")))
331 if (!obt_xml_node_contains(n, "default"))
332 settings->fullscreen = obt_xml_node_bool(n);
334 if ((n = obt_xml_find_node(app->children, "maximized"))) {
335 if (!obt_xml_node_contains(n, "default")) {
336 gchar *s = obt_xml_node_string(n);
337 if (!g_ascii_strcasecmp(s, "horizontal")) {
338 settings->max_horz = TRUE;
339 settings->max_vert = FALSE;
340 } else if (!g_ascii_strcasecmp(s, "vertical")) {
341 settings->max_horz = FALSE;
342 settings->max_vert = TRUE;
344 settings->max_horz = settings->max_vert =
345 obt_xml_node_bool(n);
351 /* Manages settings for individual applications.
352 Some notes: monitor is the screen number in a multi monitor
353 (Xinerama) setup (starting from 0), or mouse: the monitor the pointer
354 is on, active: the active monitor, primary: the primary monitor.
355 Layer can be three values, above (Always on top), below
356 (Always on bottom) and everything else (normal behaviour).
357 Positions can be an integer value or center, which will
358 center the window in the specified axis. Position is within
359 the monitor, so <position><x>center</x></position><monitor>2</monitor>
360 will center the window on the second monitor.
362 static void parse_per_app_settings(xmlNodePtr node, gpointer d)
364 xmlNodePtr app = obt_xml_find_node(node->children, "application");
365 for (; app; app = obt_xml_find_node(app->next, "application")) {
366 ObAppSettings *settings;
368 gboolean name_set, class_set, role_set, title_set,
369 type_set, group_name_set, group_class_set;
370 gchar *name = NULL, *class = NULL, *role = NULL, *title = NULL,
371 *type_str = NULL, *group_name = NULL, *group_class = NULL;
374 class_set = obt_xml_attr_string(app, "class", &class);
375 name_set = obt_xml_attr_string(app, "name", &name);
376 group_class_set = obt_xml_attr_string(app, "groupclass", &group_class);
377 group_name_set = obt_xml_attr_string(app, "groupname", &group_name);
378 type_set = obt_xml_attr_string(app, "type", &type_str);
379 role_set = obt_xml_attr_string(app, "role", &role);
380 title_set = obt_xml_attr_string(app, "title", &title);
382 /* validate the type tho */
384 if (!g_ascii_strcasecmp(type_str, "normal"))
385 type = OB_CLIENT_TYPE_NORMAL;
386 else if (!g_ascii_strcasecmp(type_str, "dialog"))
387 type = OB_CLIENT_TYPE_DIALOG;
388 else if (!g_ascii_strcasecmp(type_str, "splash"))
389 type = OB_CLIENT_TYPE_SPLASH;
390 else if (!g_ascii_strcasecmp(type_str, "utility"))
391 type = OB_CLIENT_TYPE_UTILITY;
392 else if (!g_ascii_strcasecmp(type_str, "menu"))
393 type = OB_CLIENT_TYPE_MENU;
394 else if (!g_ascii_strcasecmp(type_str, "toolbar"))
395 type = OB_CLIENT_TYPE_TOOLBAR;
396 else if (!g_ascii_strcasecmp(type_str, "dock"))
397 type = OB_CLIENT_TYPE_DOCK;
398 else if (!g_ascii_strcasecmp(type_str, "desktop"))
399 type = OB_CLIENT_TYPE_DESKTOP;
401 type_set = FALSE; /* not valid! */
404 if (!(class_set || name_set || role_set || title_set ||
405 type_set || group_class_set || group_name_set))
408 settings = config_create_app_settings();
411 settings->name = g_pattern_spec_new(name);
413 settings->class = g_pattern_spec_new(class);
415 settings->group_name = g_pattern_spec_new(group_name);
417 settings->group_class = g_pattern_spec_new(group_class);
419 settings->role = g_pattern_spec_new(role);
421 settings->title = g_pattern_spec_new(title);
423 settings->type = type;
433 parse_single_per_app_settings(app, settings);
434 config_per_app_settings = g_slist_append(config_per_app_settings,
442 <action name="ChangeDesktop">
449 static void parse_key(xmlNodePtr node, GList *keylist)
451 gchar *keystring, **keys, **key;
453 gboolean is_chroot = FALSE;
454 gboolean grab = TRUE;
455 gboolean repeat = FALSE;
457 if (!obt_xml_attr_string(node, "key", &keystring))
460 obt_xml_attr_bool(node, "chroot", &is_chroot);
461 obt_xml_attr_bool(node, "grab", &grab);
462 obt_xml_attr_bool(node, "repeat", &repeat);
464 keys = g_strsplit(keystring, " ", 0);
465 for (key = keys; *key; ++key) {
466 keylist = g_list_append(keylist, *key);
468 if ((n = obt_xml_find_node(node->children, "keybind"))) {
470 parse_key(n, keylist);
471 n = obt_xml_find_node(n->next, "keybind");
474 else if ((n = obt_xml_find_node(node->children, "action"))) {
476 ObActionsAct *action;
478 action = actions_parse(n);
480 keyboard_bind(keylist, action, grab, !repeat);
481 n = obt_xml_find_node(n->next, "action");
487 keyboard_chroot(keylist);
488 keylist = g_list_delete_link(keylist, g_list_last(keylist));
495 static void parse_keyboard(xmlNodePtr node, gpointer d)
500 keyboard_unbind_all();
502 if ((n = obt_xml_find_node(node->children, "chainQuitKey"))) {
503 key = obt_xml_node_string(n);
504 translate_key(key, &config_keyboard_reset_state,
505 &config_keyboard_reset_keycode);
509 if ((n = obt_xml_find_node(node->children, "keybind")))
512 n = obt_xml_find_node(n->next, "keybind");
515 if ((n = obt_xml_find_node(node->children, "rebindOnMappingNotify")))
516 config_keyboard_rebind_on_mapping_notify = obt_xml_node_bool(n);
521 <context name="Titlebar">
522 <mousebind button="Left" action="Press">
523 <action name="Raise"></action>
529 static void parse_mouse(xmlNodePtr node, gpointer d)
531 xmlNodePtr n, nbut, nact;
538 node = node->children;
540 if ((n = obt_xml_find_node(node, "dragThreshold")))
541 config_mouse_threshold = obt_xml_node_int(n);
542 if ((n = obt_xml_find_node(node, "doubleClickTime")))
543 config_mouse_dclicktime = obt_xml_node_int(n);
544 if ((n = obt_xml_find_node(node, "screenEdgeWarpTime"))) {
545 config_mouse_screenedgetime = obt_xml_node_int(n);
546 /* minimum value of 25 for this property, when it is 1 and you hit the
547 edge it basically never stops */
548 if (config_mouse_screenedgetime && config_mouse_screenedgetime < 25)
549 config_mouse_screenedgetime = 25;
551 if ((n = obt_xml_find_node(node, "screenEdgeWarpMouse")))
552 config_mouse_screenedgewarp = obt_xml_node_bool(n);
554 for (n = obt_xml_find_node(node, "context");
556 n = obt_xml_find_node(n->next, "context"))
561 if (!obt_xml_attr_string(n, "name", &cxstr))
564 modcxstr = g_strdup(cxstr); /* make a copy to mutilate */
565 while (frame_next_context_from_string(modcxstr, &cx)) {
567 gchar *s = strchr(modcxstr, ' ');
570 g_message(_("Invalid context \"%s\" in mouse binding"),
577 for (nbut = obt_xml_find_node(n->children, "mousebind");
579 nbut = obt_xml_find_node(nbut->next, "mousebind"))
582 gchar **button, **buttons;
584 if (!obt_xml_attr_string(nbut, "button", &buttonstr))
586 if (obt_xml_attr_contains(nbut, "action", "press"))
587 mact = OB_MOUSE_ACTION_PRESS;
588 else if (obt_xml_attr_contains(nbut, "action", "release"))
589 mact = OB_MOUSE_ACTION_RELEASE;
590 else if (obt_xml_attr_contains(nbut, "action", "click"))
591 mact = OB_MOUSE_ACTION_CLICK;
592 else if (obt_xml_attr_contains(nbut, "action","doubleclick"))
593 mact = OB_MOUSE_ACTION_DOUBLE_CLICK;
594 else if (obt_xml_attr_contains(nbut, "action", "drag"))
595 mact = OB_MOUSE_ACTION_MOTION;
599 buttons = g_strsplit(buttonstr, " ", 0);
600 for (nact = obt_xml_find_node(nbut->children, "action");
602 nact = obt_xml_find_node(nact->next, "action"))
604 ObActionsAct *action;
606 /* actions_parse() creates one ref to the action, but we need
607 * exactly one ref per binding we use it for. */
608 if ((action = actions_parse(nact))) {
609 for (button = buttons; *button; ++button) {
610 actions_act_ref(action);
611 mouse_bind(*button, cx, mact, action);
613 actions_act_unref(action);
625 static void parse_focus(xmlNodePtr node, gpointer d)
629 node = node->children;
631 if ((n = obt_xml_find_node(node, "focusNew")))
632 config_focus_new = obt_xml_node_bool(n);
633 if ((n = obt_xml_find_node(node, "followMouse")))
634 config_focus_follow = obt_xml_node_bool(n);
635 if ((n = obt_xml_find_node(node, "focusDelay")))
636 config_focus_delay = obt_xml_node_int(n);
637 if ((n = obt_xml_find_node(node, "raiseOnFocus")))
638 config_focus_raise = obt_xml_node_bool(n);
639 if ((n = obt_xml_find_node(node, "focusLast")))
640 config_focus_last = obt_xml_node_bool(n);
641 if ((n = obt_xml_find_node(node, "underMouse")))
642 config_focus_under_mouse = obt_xml_node_bool(n);
643 if ((n = obt_xml_find_node(node, "unfocusOnLeave")))
644 config_unfocus_leave = obt_xml_node_bool(n);
645 if ((n = obt_xml_find_node(node, "directionalDistanceWeight")))
646 config_directional_distance_weight = obt_xml_node_int(n);
648 config_directional_distance_weight = 1U;
649 if ((n = obt_xml_find_node(node, "directionalAngleWeight")))
650 config_directional_angle_weight = obt_xml_node_int(n);
652 config_directional_angle_weight = 1U;
655 static void parse_placement(xmlNodePtr node, gpointer d)
659 node = node->children;
661 if ((n = obt_xml_find_node(node, "policy"))) {
662 if (obt_xml_node_contains(n, "UnderMouse"))
663 config_place_policy = OB_PLACE_POLICY_MOUSE;
664 if (obt_xml_node_contains(n, "Random"))
665 config_place_policy = OB_PLACE_POLICY_RANDOM;
667 if ((n = obt_xml_find_node(node, "center"))) {
668 config_place_center = obt_xml_node_bool(n);
670 if ((n = obt_xml_find_node(node, "monitor"))) {
671 if (obt_xml_node_contains(n, "active"))
672 config_place_monitor = OB_PLACE_MONITOR_ACTIVE;
673 else if (obt_xml_node_contains(n, "mouse"))
674 config_place_monitor = OB_PLACE_MONITOR_MOUSE;
675 else if (obt_xml_node_contains(n, "any"))
676 config_place_monitor = OB_PLACE_MONITOR_ANY;
678 if ((n = obt_xml_find_node(node, "primaryMonitor"))) {
679 config_primary_monitor_index = obt_xml_node_int(n);
680 if (!config_primary_monitor_index) {
681 if (obt_xml_node_contains(n, "mouse"))
682 config_primary_monitor = OB_PLACE_MONITOR_MOUSE;
687 static void parse_margins(xmlNodePtr node, gpointer d)
691 node = node->children;
693 if ((n = obt_xml_find_node(node, "top")))
694 config_margins.top = MAX(0, obt_xml_node_int(n));
695 if ((n = obt_xml_find_node(node, "left")))
696 config_margins.left = MAX(0, obt_xml_node_int(n));
697 if ((n = obt_xml_find_node(node, "right")))
698 config_margins.right = MAX(0, obt_xml_node_int(n));
699 if ((n = obt_xml_find_node(node, "bottom")))
700 config_margins.bottom = MAX(0, obt_xml_node_int(n));
703 static void parse_theme(xmlNodePtr node, gpointer d)
707 node = node->children;
709 if ((n = obt_xml_find_node(node, "name"))) {
712 g_free(config_theme);
713 c = obt_xml_node_string(n);
714 config_theme = obt_paths_expand_tilde(c);
717 if ((n = obt_xml_find_node(node, "titleLayout"))) {
720 g_free(config_title_layout);
721 config_title_layout = obt_xml_node_string(n);
723 /* replace duplicates with spaces */
724 for (c = config_title_layout; *c != '\0'; ++c)
725 for (d = c+1; *d != '\0'; ++d)
726 if (*c == *d) *d = ' ';
728 if ((n = obt_xml_find_node(node, "keepBorder")))
729 config_theme_keepborder = obt_xml_node_bool(n);
730 if ((n = obt_xml_find_node(node, "animateIconify")))
731 config_animate_iconify = obt_xml_node_bool(n);
732 if ((n = obt_xml_find_node(node, "windowListIconSize"))) {
733 config_theme_window_list_icon_size = obt_xml_node_int(n);
734 if (config_theme_window_list_icon_size < 16)
735 config_theme_window_list_icon_size = 16;
736 else if (config_theme_window_list_icon_size > 96)
737 config_theme_window_list_icon_size = 96;
740 for (n = obt_xml_find_node(node, "font");
742 n = obt_xml_find_node(n->next, "font"))
746 gchar *name = g_strdup(RrDefaultFontFamily);
747 gint size = RrDefaultFontSize;
748 RrFontWeight weight = RrDefaultFontWeight;
749 RrFontSlant slant = RrDefaultFontSlant;
751 if (obt_xml_attr_contains(n, "place", "ActiveWindow"))
752 font = &config_font_activewindow;
753 else if (obt_xml_attr_contains(n, "place", "InactiveWindow"))
754 font = &config_font_inactivewindow;
755 else if (obt_xml_attr_contains(n, "place", "MenuHeader"))
756 font = &config_font_menutitle;
757 else if (obt_xml_attr_contains(n, "place", "MenuItem"))
758 font = &config_font_menuitem;
759 else if (obt_xml_attr_contains(n, "place", "ActiveOnScreenDisplay"))
760 font = &config_font_activeosd;
761 else if (obt_xml_attr_contains(n, "place", "OnScreenDisplay"))
762 font = &config_font_activeosd;
763 else if (obt_xml_attr_contains(n, "place","InactiveOnScreenDisplay"))
764 font = &config_font_inactiveosd;
768 if ((fnode = obt_xml_find_node(n->children, "name"))) {
770 name = obt_xml_node_string(fnode);
772 if ((fnode = obt_xml_find_node(n->children, "size"))) {
773 int s = obt_xml_node_int(fnode);
776 if (obt_xml_attr_contains(fnode, "type", "absolute"))
780 if ((fnode = obt_xml_find_node(n->children, "weight"))) {
781 gchar *w = obt_xml_node_string(fnode);
782 if (!g_ascii_strcasecmp(w, "Bold"))
783 weight = RR_FONTWEIGHT_BOLD;
786 if ((fnode = obt_xml_find_node(n->children, "slant"))) {
787 gchar *s = obt_xml_node_string(fnode);
788 if (!g_ascii_strcasecmp(s, "Italic"))
789 slant = RR_FONTSLANT_ITALIC;
790 if (!g_ascii_strcasecmp(s, "Oblique"))
791 slant = RR_FONTSLANT_OBLIQUE;
795 *font = RrFontOpen(ob_rr_inst, name, size, weight, slant);
798 if ((fnode = obt_xml_find_node(n->children, "description"))) {
799 gchar *s = obt_xml_node_string(fnode);
800 RrFontDescriptionFromString(*font, s);
806 static void parse_desktops(xmlNodePtr node, gpointer d)
810 node = node->children;
812 if ((n = obt_xml_find_node(node, "number"))) {
813 gint d = obt_xml_node_int(n);
815 config_desktops_num = (unsigned) d;
817 if ((n = obt_xml_find_node(node, "firstdesk"))) {
818 gint d = obt_xml_node_int(n);
820 config_screen_firstdesk = (unsigned) d;
822 if ((n = obt_xml_find_node(node, "emulatexinerama")))
823 config_emulate_xinerama = obt_xml_node_bool(n);
824 if ((n = obt_xml_find_node(node, "names"))) {
828 for (it = config_desktops_names; it; it = it->next)
830 g_slist_free(config_desktops_names);
831 config_desktops_names = NULL;
833 for (nname = obt_xml_find_node(n->children, "name");
835 nname = obt_xml_find_node(nname->next, "name"))
837 config_desktops_names =
838 g_slist_append(config_desktops_names,
839 obt_xml_node_string(nname));
842 if ((n = obt_xml_find_node(node, "popupTime")))
843 config_desktop_popup_time = obt_xml_node_int(n);
846 static void parse_resize(xmlNodePtr node, gpointer d)
850 node = node->children;
852 if ((n = obt_xml_find_node(node, "drawContents")))
853 config_resize_redraw = obt_xml_node_bool(n);
854 if ((n = obt_xml_find_node(node, "popupShow"))) {
855 config_resize_popup_show = obt_xml_node_int(n);
856 if (obt_xml_node_contains(n, "Always"))
857 config_resize_popup_show = 2;
858 else if (obt_xml_node_contains(n, "Never"))
859 config_resize_popup_show = 0;
860 else if (obt_xml_node_contains(n, "Nonpixel"))
861 config_resize_popup_show = 1;
863 if ((n = obt_xml_find_node(node, "popupPosition"))) {
864 if (obt_xml_node_contains(n, "Top"))
865 config_resize_popup_pos = OB_RESIZE_POS_TOP;
866 else if (obt_xml_node_contains(n, "Center"))
867 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
868 else if (obt_xml_node_contains(n, "Fixed")) {
869 config_resize_popup_pos = OB_RESIZE_POS_FIXED;
871 if ((n = obt_xml_find_node(node, "popupFixedPosition"))) {
874 if ((n2 = obt_xml_find_node(n->children, "x")))
875 config_parse_gravity_coord(n2,
876 &config_resize_popup_fixed.x);
877 if ((n2 = obt_xml_find_node(n->children, "y")))
878 config_parse_gravity_coord(n2,
879 &config_resize_popup_fixed.y);
881 config_resize_popup_fixed.x.pos =
882 MAX(config_resize_popup_fixed.x.pos, 0);
883 config_resize_popup_fixed.y.pos =
884 MAX(config_resize_popup_fixed.y.pos, 0);
890 static void parse_dock(xmlNodePtr node, gpointer d)
894 node = node->children;
896 if ((n = obt_xml_find_node(node, "position"))) {
897 if (obt_xml_node_contains(n, "TopLeft"))
898 config_dock_floating = FALSE,
899 config_dock_pos = OB_DIRECTION_NORTHWEST;
900 else if (obt_xml_node_contains(n, "Top"))
901 config_dock_floating = FALSE,
902 config_dock_pos = OB_DIRECTION_NORTH;
903 else if (obt_xml_node_contains(n, "TopRight"))
904 config_dock_floating = FALSE,
905 config_dock_pos = OB_DIRECTION_NORTHEAST;
906 else if (obt_xml_node_contains(n, "Right"))
907 config_dock_floating = FALSE,
908 config_dock_pos = OB_DIRECTION_EAST;
909 else if (obt_xml_node_contains(n, "BottomRight"))
910 config_dock_floating = FALSE,
911 config_dock_pos = OB_DIRECTION_SOUTHEAST;
912 else if (obt_xml_node_contains(n, "Bottom"))
913 config_dock_floating = FALSE,
914 config_dock_pos = OB_DIRECTION_SOUTH;
915 else if (obt_xml_node_contains(n, "BottomLeft"))
916 config_dock_floating = FALSE,
917 config_dock_pos = OB_DIRECTION_SOUTHWEST;
918 else if (obt_xml_node_contains(n, "Left"))
919 config_dock_floating = FALSE,
920 config_dock_pos = OB_DIRECTION_WEST;
921 else if (obt_xml_node_contains(n, "Floating"))
922 config_dock_floating = TRUE;
924 if (config_dock_floating) {
925 if ((n = obt_xml_find_node(node, "floatingX")))
926 config_dock_x = obt_xml_node_int(n);
927 if ((n = obt_xml_find_node(node, "floatingY")))
928 config_dock_y = obt_xml_node_int(n);
930 if ((n = obt_xml_find_node(node, "noStrut")))
931 config_dock_nostrut = obt_xml_node_bool(n);
933 if ((n = obt_xml_find_node(node, "stacking"))) {
934 if (obt_xml_node_contains(n, "normal"))
935 config_dock_layer = OB_STACKING_LAYER_NORMAL;
936 else if (obt_xml_node_contains(n, "below"))
937 config_dock_layer = OB_STACKING_LAYER_BELOW;
938 else if (obt_xml_node_contains(n, "above"))
939 config_dock_layer = OB_STACKING_LAYER_ABOVE;
941 if ((n = obt_xml_find_node(node, "direction"))) {
942 if (obt_xml_node_contains(n, "horizontal"))
943 config_dock_orient = OB_ORIENTATION_HORZ;
944 else if (obt_xml_node_contains(n, "vertical"))
945 config_dock_orient = OB_ORIENTATION_VERT;
947 if ((n = obt_xml_find_node(node, "autoHide")))
948 config_dock_hide = obt_xml_node_bool(n);
949 if ((n = obt_xml_find_node(node, "hideDelay")))
950 config_dock_hide_delay = obt_xml_node_int(n);
951 if ((n = obt_xml_find_node(node, "showDelay")))
952 config_dock_show_delay = obt_xml_node_int(n);
953 if ((n = obt_xml_find_node(node, "moveButton"))) {
954 gchar *str = obt_xml_node_string(n);
956 if (translate_button(str, &s, &b)) {
957 config_dock_app_move_button = b;
958 config_dock_app_move_modifiers = s;
960 g_message(_("Invalid button \"%s\" specified in config file"), str);
966 static void parse_menu(xmlNodePtr node, gpointer d)
969 node = node->children;
971 if ((n = obt_xml_find_node(node, "hideDelay")))
972 config_menu_hide_delay = obt_xml_node_int(n);
973 if ((n = obt_xml_find_node(node, "middle")))
974 config_menu_middle = obt_xml_node_bool(n);
975 if ((n = obt_xml_find_node(node, "submenuShowDelay")))
976 config_submenu_show_delay = obt_xml_node_int(n);
977 if ((n = obt_xml_find_node(node, "submenuHideDelay")))
978 config_submenu_hide_delay = obt_xml_node_int(n);
979 if ((n = obt_xml_find_node(node, "manageDesktops")))
980 config_menu_manage_desktops = obt_xml_node_bool(n);
981 if ((n = obt_xml_find_node(node, "showIcons"))) {
982 config_menu_show_icons = obt_xml_node_bool(n);
983 #if !defined(USE_IMLIB2) && !defined(USE_LIBRSVG)
984 if (config_menu_show_icons)
985 g_message(_("Openbox was compiled without image loading support. Icons in menus will not be loaded."));
989 for (node = obt_xml_find_node(node, "file");
991 node = obt_xml_find_node(node->next, "file"))
993 gchar *c = obt_xml_node_string(node);
994 config_menu_files = g_slist_append(config_menu_files,
995 obt_paths_expand_tilde(c));
1000 static void parse_resistance(xmlNodePtr node, gpointer d)
1004 node = node->children;
1005 if ((n = obt_xml_find_node(node, "strength")))
1006 config_resist_win = obt_xml_node_int(n);
1007 if ((n = obt_xml_find_node(node, "screen_edge_strength")))
1008 config_resist_edge = obt_xml_node_int(n);
1014 const gchar *actname;
1017 static void bind_default_keyboard(void)
1020 ObDefKeyBind binds[] = {
1021 { "A-Tab", "NextWindow" },
1022 { "S-A-Tab", "PreviousWindow" },
1023 { "A-F4", "Close" },
1026 for (it = binds; it->key; ++it) {
1027 GList *l = g_list_append(NULL, g_strdup(it->key));
1028 keyboard_bind(l, actions_parse_string(it->actname), TRUE, TRUE);
1034 const gchar *button;
1035 const gchar *context;
1036 const ObMouseAction mact;
1037 const gchar *actname;
1040 static void bind_default_mouse(void)
1043 ObDefMouseBind binds[] = {
1044 { "Left", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
1045 { "Middle", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
1046 { "Right", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
1047 { "Left", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
1048 { "Middle", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
1049 { "Right", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
1050 { "Left", "Titlebar", OB_MOUSE_ACTION_PRESS, "Focus" },
1051 { "Left", "Bottom", OB_MOUSE_ACTION_PRESS, "Focus" },
1052 { "Left", "BLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
1053 { "Left", "BRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
1054 { "Left", "TLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
1055 { "Left", "TRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
1056 { "Left", "Close", OB_MOUSE_ACTION_PRESS, "Focus" },
1057 { "Left", "Maximize", OB_MOUSE_ACTION_PRESS, "Focus" },
1058 { "Left", "Iconify", OB_MOUSE_ACTION_PRESS, "Focus" },
1059 { "Left", "Icon", OB_MOUSE_ACTION_PRESS, "Focus" },
1060 { "Left", "AllDesktops", OB_MOUSE_ACTION_PRESS, "Focus" },
1061 { "Left", "Shade", OB_MOUSE_ACTION_PRESS, "Focus" },
1062 { "Left", "Client", OB_MOUSE_ACTION_CLICK, "Raise" },
1063 { "Left", "Titlebar", OB_MOUSE_ACTION_CLICK, "Raise" },
1064 { "Middle", "Titlebar", OB_MOUSE_ACTION_CLICK, "Lower" },
1065 { "Left", "BLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
1066 { "Left", "BRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
1067 { "Left", "TLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
1068 { "Left", "TRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
1069 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Raise" },
1070 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "Raise" },
1071 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Raise" },
1072 { "Left", "Icon", OB_MOUSE_ACTION_CLICK, "Raise" },
1073 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "Raise" },
1074 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "Raise" },
1075 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Close" },
1076 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "ToggleMaximize" },
1077 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Iconify" },
1078 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "ToggleOmnipresent" },
1079 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "ToggleShade" },
1080 { "Left", "TLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
1081 { "Left", "TRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
1082 { "Left", "BLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
1083 { "Left", "BRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
1084 { "Left", "Top", OB_MOUSE_ACTION_MOTION, "Resize" },
1085 { "Left", "Bottom", OB_MOUSE_ACTION_MOTION, "Resize" },
1086 { "Left", "Left", OB_MOUSE_ACTION_MOTION, "Resize" },
1087 { "Left", "Right", OB_MOUSE_ACTION_MOTION, "Resize" },
1088 { "Left", "Titlebar", OB_MOUSE_ACTION_MOTION, "Move" },
1089 { "A-Left", "Frame", OB_MOUSE_ACTION_MOTION, "Move" },
1090 { "A-Middle", "Frame", OB_MOUSE_ACTION_MOTION, "Resize" },
1091 { NULL, NULL, 0, NULL }
1094 for (it = binds; it->button; ++it)
1095 mouse_bind(it->button, frame_context_from_string(it->context),
1096 it->mact, actions_parse_string(it->actname));
1099 void config_startup(ObtXmlInst *i)
1101 config_focus_new = TRUE;
1102 config_focus_follow = FALSE;
1103 config_focus_delay = 0;
1104 config_focus_raise = FALSE;
1105 config_focus_last = TRUE;
1106 config_focus_under_mouse = FALSE;
1107 config_unfocus_leave = FALSE;
1109 obt_xml_register(i, "focus", parse_focus, NULL);
1111 config_place_policy = OB_PLACE_POLICY_SMART;
1112 config_place_center = TRUE;
1113 config_place_monitor = OB_PLACE_MONITOR_PRIMARY;
1115 config_primary_monitor_index = 1;
1116 config_primary_monitor = OB_PLACE_MONITOR_ACTIVE;
1118 obt_xml_register(i, "placement", parse_placement, NULL);
1120 STRUT_PARTIAL_SET(config_margins, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1122 obt_xml_register(i, "margins", parse_margins, NULL);
1124 config_theme = NULL;
1126 config_animate_iconify = TRUE;
1127 config_title_layout = g_strdup("NLIMC");
1128 config_theme_keepborder = TRUE;
1129 config_theme_window_list_icon_size = 36;
1131 config_font_activewindow = NULL;
1132 config_font_inactivewindow = NULL;
1133 config_font_menuitem = NULL;
1134 config_font_menutitle = NULL;
1135 config_font_activeosd = NULL;
1136 config_font_inactiveosd = NULL;
1138 obt_xml_register(i, "theme", parse_theme, NULL);
1140 config_desktops_num = 4;
1141 config_screen_firstdesk = 1;
1142 config_emulate_xinerama = FALSE;
1143 config_desktops_names = NULL;
1144 config_desktop_popup_time = 875;
1146 obt_xml_register(i, "desktops", parse_desktops, NULL);
1148 config_resize_redraw = TRUE;
1149 config_resize_popup_show = 1; /* nonpixel increments */
1150 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
1151 GRAVITY_COORD_SET(config_resize_popup_fixed.x, 0, FALSE, FALSE);
1152 GRAVITY_COORD_SET(config_resize_popup_fixed.y, 0, FALSE, FALSE);
1154 obt_xml_register(i, "resize", parse_resize, NULL);
1156 config_dock_layer = OB_STACKING_LAYER_ABOVE;
1157 config_dock_pos = OB_DIRECTION_NORTHEAST;
1158 config_dock_floating = FALSE;
1159 config_dock_nostrut = FALSE;
1162 config_dock_orient = OB_ORIENTATION_VERT;
1163 config_dock_hide = FALSE;
1164 config_dock_hide_delay = 300;
1165 config_dock_show_delay = 300;
1166 config_dock_app_move_button = 2; /* middle */
1167 config_dock_app_move_modifiers = 0;
1169 obt_xml_register(i, "dock", parse_dock, NULL);
1171 translate_key("C-g", &config_keyboard_reset_state,
1172 &config_keyboard_reset_keycode);
1173 config_keyboard_rebind_on_mapping_notify = TRUE;
1175 bind_default_keyboard();
1177 obt_xml_register(i, "keyboard", parse_keyboard, NULL);
1179 config_mouse_threshold = 8;
1180 config_mouse_dclicktime = 500;
1181 config_mouse_screenedgetime = 400;
1182 config_mouse_screenedgewarp = FALSE;
1184 bind_default_mouse();
1186 obt_xml_register(i, "mouse", parse_mouse, NULL);
1188 config_resist_win = 10;
1189 config_resist_edge = 20;
1191 obt_xml_register(i, "resistance", parse_resistance, NULL);
1193 config_menu_hide_delay = 250;
1194 config_menu_middle = FALSE;
1195 config_submenu_show_delay = 100;
1196 config_submenu_hide_delay = 400;
1197 config_menu_manage_desktops = TRUE;
1198 config_menu_files = NULL;
1199 config_menu_show_icons = TRUE;
1201 obt_xml_register(i, "menu", parse_menu, NULL);
1203 config_per_app_settings = NULL;
1205 obt_xml_register(i, "applications", parse_per_app_settings, NULL);
1208 void config_shutdown(void)
1212 g_free(config_theme);
1214 g_free(config_title_layout);
1216 RrFontClose(config_font_activewindow);
1217 RrFontClose(config_font_inactivewindow);
1218 RrFontClose(config_font_menuitem);
1219 RrFontClose(config_font_menutitle);
1220 RrFontClose(config_font_activeosd);
1221 RrFontClose(config_font_inactiveosd);
1223 for (it = config_desktops_names; it; it = g_slist_next(it))
1225 g_slist_free(config_desktops_names);
1227 for (it = config_menu_files; it; it = g_slist_next(it))
1229 g_slist_free(config_menu_files);
1231 for (it = config_per_app_settings; it; it = g_slist_next(it)) {
1232 ObAppSettings *itd = (ObAppSettings *)it->data;
1233 if (itd->name) g_pattern_spec_free(itd->name);
1234 if (itd->role) g_pattern_spec_free(itd->role);
1235 if (itd->title) g_pattern_spec_free(itd->title);
1236 if (itd->class) g_pattern_spec_free(itd->class);
1237 if (itd->group_name) g_pattern_spec_free(itd->group_name);
1238 if (itd->group_class) g_pattern_spec_free(itd->group_class);
1239 g_slice_free(ObAppSettings, it->data);
1241 g_slist_free(config_per_app_settings);