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
;
51 guint config_frame_flash_delay
;
52 guint config_frame_flash_duration
;
54 gchar
*config_title_layout
;
56 gboolean config_animate_iconify
;
58 RrFont
*config_font_activewindow
;
59 RrFont
*config_font_inactivewindow
;
60 RrFont
*config_font_menuitem
;
61 RrFont
*config_font_menutitle
;
62 RrFont
*config_font_activeosd
;
63 RrFont
*config_font_inactiveosd
;
65 guint config_desktops_num
;
66 GSList
*config_desktops_names
;
67 guint config_screen_firstdesk
;
68 guint config_desktop_popup_time
;
70 gboolean config_resize_redraw
;
71 gint config_resize_popup_show
;
72 ObResizePopupPos config_resize_popup_pos
;
73 GravityPoint config_resize_popup_fixed
;
75 ObStackingLayer config_dock_layer
;
76 gboolean config_dock_floating
;
77 gboolean config_dock_nostrut
;
78 ObDirection config_dock_pos
;
81 ObOrientation config_dock_orient
;
82 gboolean config_dock_hide
;
83 guint config_dock_hide_delay
;
84 guint config_dock_show_delay
;
85 guint config_dock_app_move_button
;
86 guint config_dock_app_move_modifiers
;
88 guint config_keyboard_reset_keycode
;
89 guint config_keyboard_reset_state
;
91 gint config_mouse_threshold
;
92 gint config_mouse_dclicktime
;
93 gint config_mouse_screenedgetime
;
94 gboolean config_mouse_screenedgewarp
;
96 guint config_menu_hide_delay
;
97 gboolean config_menu_middle
;
98 guint config_submenu_show_delay
;
99 guint config_submenu_hide_delay
;
100 gboolean config_menu_manage_desktops
;
101 gboolean config_menu_show_icons
;
103 GSList
*config_menu_files
;
105 gint config_resist_win
;
106 gint config_resist_edge
;
108 GSList
*config_per_app_settings
;
110 ObAppSettings
* config_create_app_settings(void)
112 ObAppSettings
*settings
= g_slice_new0(ObAppSettings
);
114 settings
->decor
= -1;
115 settings
->shade
= -1;
116 settings
->monitor_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;
127 settings
->opacity
= -1;
131 #define copy_if(setting, default) \
132 if (src->setting != default) dst->setting = src->setting
133 void config_app_settings_copy_non_defaults(const ObAppSettings
*src
,
136 g_assert(src
!= NULL
);
137 g_assert(dst
!= NULL
);
139 copy_if(type
, (ObClientType
)-1);
142 copy_if(monitor_type
, OB_PLACE_MONITOR_ANY
);
143 copy_if(monitor
, -1);
148 copy_if(skip_pager
, -1);
149 copy_if(skip_taskbar
, -1);
150 copy_if(fullscreen
, -1);
151 copy_if(max_horz
, -1);
152 copy_if(max_vert
, -1);
153 copy_if(opacity
, -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
);
350 if ((n
= obt_xml_find_node(app
->children
, "opacity")))
351 if (!obt_xml_node_contains(n
, "default"))
352 settings
->opacity
= obt_xml_node_int(n
);
355 /* Manages settings for individual applications.
356 Some notes: monitor is the screen number in a multi monitor
357 (Xinerama) setup (starting from 0), or mouse: the monitor the pointer
358 is on, active: the active monitor, primary: the primary monitor.
359 Layer can be three values, above (Always on top), below
360 (Always on bottom) and everything else (normal behaviour).
361 Positions can be an integer value or center, which will
362 center the window in the specified axis. Position is within
363 the monitor, so <position><x>center</x></position><monitor>2</monitor>
364 will center the window on the second monitor.
366 static void parse_per_app_settings(xmlNodePtr node
, gpointer d
)
368 xmlNodePtr app
= obt_xml_find_node(node
->children
, "application");
369 for (; app
; app
= obt_xml_find_node(app
->next
, "application")) {
370 ObAppSettings
*settings
;
372 gboolean name_set
, class_set
, role_set
, title_set
,
373 type_set
, group_name_set
, group_class_set
;
374 gchar
*name
= NULL
, *class = NULL
, *role
= NULL
, *title
= NULL
,
375 *type_str
= NULL
, *group_name
= NULL
, *group_class
= NULL
;
378 class_set
= obt_xml_attr_string(app
, "class", &class);
379 name_set
= obt_xml_attr_string(app
, "name", &name
);
380 group_class_set
= obt_xml_attr_string(app
, "groupclass", &group_class
);
381 group_name_set
= obt_xml_attr_string(app
, "groupname", &group_name
);
382 type_set
= obt_xml_attr_string(app
, "type", &type_str
);
383 role_set
= obt_xml_attr_string(app
, "role", &role
);
384 title_set
= obt_xml_attr_string(app
, "title", &title
);
386 /* validate the type tho */
388 if (!g_ascii_strcasecmp(type_str
, "normal"))
389 type
= OB_CLIENT_TYPE_NORMAL
;
390 else if (!g_ascii_strcasecmp(type_str
, "dialog"))
391 type
= OB_CLIENT_TYPE_DIALOG
;
392 else if (!g_ascii_strcasecmp(type_str
, "splash"))
393 type
= OB_CLIENT_TYPE_SPLASH
;
394 else if (!g_ascii_strcasecmp(type_str
, "utility"))
395 type
= OB_CLIENT_TYPE_UTILITY
;
396 else if (!g_ascii_strcasecmp(type_str
, "menu"))
397 type
= OB_CLIENT_TYPE_MENU
;
398 else if (!g_ascii_strcasecmp(type_str
, "toolbar"))
399 type
= OB_CLIENT_TYPE_TOOLBAR
;
400 else if (!g_ascii_strcasecmp(type_str
, "dock"))
401 type
= OB_CLIENT_TYPE_DOCK
;
402 else if (!g_ascii_strcasecmp(type_str
, "desktop"))
403 type
= OB_CLIENT_TYPE_DESKTOP
;
405 type_set
= FALSE
; /* not valid! */
408 if (!(class_set
|| name_set
|| role_set
|| title_set
||
409 type_set
|| group_class_set
|| group_name_set
))
412 settings
= config_create_app_settings();
415 settings
->name
= g_pattern_spec_new(name
);
417 settings
->class = g_pattern_spec_new(class);
419 settings
->group_name
= g_pattern_spec_new(group_name
);
421 settings
->group_class
= g_pattern_spec_new(group_class
);
423 settings
->role
= g_pattern_spec_new(role
);
425 settings
->title
= g_pattern_spec_new(title
);
427 settings
->type
= type
;
437 parse_single_per_app_settings(app
, settings
);
438 config_per_app_settings
= g_slist_append(config_per_app_settings
,
446 <action name="ChangeDesktop">
453 static void parse_key(xmlNodePtr node
, GList
*keylist
)
455 gchar
*keystring
, **keys
, **key
;
457 gboolean is_chroot
= FALSE
;
459 if (!obt_xml_attr_string(node
, "key", &keystring
))
462 obt_xml_attr_bool(node
, "chroot", &is_chroot
);
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
);
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");
518 <context name="Titlebar">
519 <mousebind button="Left" action="Press">
520 <action name="Raise"></action>
526 static void parse_mouse(xmlNodePtr node
, gpointer d
)
528 xmlNodePtr n
, nbut
, nact
;
535 node
= node
->children
;
537 if ((n
= obt_xml_find_node(node
, "dragThreshold")))
538 config_mouse_threshold
= obt_xml_node_int(n
);
539 if ((n
= obt_xml_find_node(node
, "doubleClickTime")))
540 config_mouse_dclicktime
= obt_xml_node_int(n
);
541 if ((n
= obt_xml_find_node(node
, "screenEdgeWarpTime"))) {
542 config_mouse_screenedgetime
= obt_xml_node_int(n
);
543 /* minimum value of 25 for this property, when it is 1 and you hit the
544 edge it basically never stops */
545 if (config_mouse_screenedgetime
&& config_mouse_screenedgetime
< 25)
546 config_mouse_screenedgetime
= 25;
548 if ((n
= obt_xml_find_node(node
, "screenEdgeWarpMouse")))
549 config_mouse_screenedgewarp
= obt_xml_node_bool(n
);
551 n
= obt_xml_find_node(node
, "context");
556 if (!obt_xml_attr_string(n
, "name", &cxstr
))
559 modcxstr
= g_strdup(cxstr
); /* make a copy to mutilate */
560 while (frame_next_context_from_string(modcxstr
, &cx
)) {
562 gchar
*s
= strchr(modcxstr
, ' ');
565 g_message(_("Invalid context \"%s\" in mouse binding"),
572 nbut
= obt_xml_find_node(n
->children
, "mousebind");
574 if (!obt_xml_attr_string(nbut
, "button", &buttonstr
))
576 if (obt_xml_attr_contains(nbut
, "action", "press"))
577 mact
= OB_MOUSE_ACTION_PRESS
;
578 else if (obt_xml_attr_contains(nbut
, "action", "release"))
579 mact
= OB_MOUSE_ACTION_RELEASE
;
580 else if (obt_xml_attr_contains(nbut
, "action", "click"))
581 mact
= OB_MOUSE_ACTION_CLICK
;
582 else if (obt_xml_attr_contains(nbut
, "action","doubleclick"))
583 mact
= OB_MOUSE_ACTION_DOUBLE_CLICK
;
584 else if (obt_xml_attr_contains(nbut
, "action", "drag"))
585 mact
= OB_MOUSE_ACTION_MOTION
;
589 nact
= obt_xml_find_node(nbut
->children
, "action");
591 ObActionsAct
*action
;
593 if ((action
= actions_parse(nact
)))
594 mouse_bind(buttonstr
, cx
, mact
, action
);
595 nact
= obt_xml_find_node(nact
->next
, "action");
599 nbut
= obt_xml_find_node(nbut
->next
, "mousebind");
605 n
= obt_xml_find_node(n
->next
, "context");
609 static void parse_focus(xmlNodePtr node
, gpointer d
)
613 node
= node
->children
;
615 if ((n
= obt_xml_find_node(node
, "focusNew")))
616 config_focus_new
= obt_xml_node_bool(n
);
617 if ((n
= obt_xml_find_node(node
, "followMouse")))
618 config_focus_follow
= obt_xml_node_bool(n
);
619 if ((n
= obt_xml_find_node(node
, "focusDelay")))
620 config_focus_delay
= obt_xml_node_int(n
);
621 if ((n
= obt_xml_find_node(node
, "raiseOnFocus")))
622 config_focus_raise
= obt_xml_node_bool(n
);
623 if ((n
= obt_xml_find_node(node
, "focusLast")))
624 config_focus_last
= obt_xml_node_bool(n
);
625 if ((n
= obt_xml_find_node(node
, "underMouse")))
626 config_focus_under_mouse
= obt_xml_node_bool(n
);
627 if ((n
= obt_xml_find_node(node
, "unfocusOnLeave")))
628 config_unfocus_leave
= obt_xml_node_bool(n
);
631 static void parse_placement(xmlNodePtr node
, gpointer d
)
635 node
= node
->children
;
637 if ((n
= obt_xml_find_node(node
, "policy"))) {
638 if (obt_xml_node_contains(n
, "UnderMouse"))
639 config_place_policy
= OB_PLACE_POLICY_MOUSE
;
641 if ((n
= obt_xml_find_node(node
, "center"))) {
642 config_place_center
= obt_xml_node_bool(n
);
644 if ((n
= obt_xml_find_node(node
, "monitor"))) {
645 if (obt_xml_node_contains(n
, "active"))
646 config_place_monitor
= OB_PLACE_MONITOR_ACTIVE
;
647 else if (obt_xml_node_contains(n
, "mouse"))
648 config_place_monitor
= OB_PLACE_MONITOR_MOUSE
;
649 else if (obt_xml_node_contains(n
, "any"))
650 config_place_monitor
= OB_PLACE_MONITOR_ANY
;
652 if ((n
= obt_xml_find_node(node
, "primaryMonitor"))) {
653 config_primary_monitor_index
= obt_xml_node_int(n
);
654 if (!config_primary_monitor_index
) {
655 if (obt_xml_node_contains(n
, "mouse"))
656 config_primary_monitor
= OB_PLACE_MONITOR_MOUSE
;
661 static void parse_margins(xmlNodePtr node
, gpointer d
)
665 node
= node
->children
;
667 if ((n
= obt_xml_find_node(node
, "top")))
668 config_margins
.top
= MAX(0, obt_xml_node_int(n
));
669 if ((n
= obt_xml_find_node(node
, "left")))
670 config_margins
.left
= MAX(0, obt_xml_node_int(n
));
671 if ((n
= obt_xml_find_node(node
, "right")))
672 config_margins
.right
= MAX(0, obt_xml_node_int(n
));
673 if ((n
= obt_xml_find_node(node
, "bottom")))
674 config_margins
.bottom
= MAX(0, obt_xml_node_int(n
));
677 static void parse_theme(xmlNodePtr node
, gpointer d
)
681 node
= node
->children
;
683 if ((n
= obt_xml_find_node(node
, "name"))) {
686 g_free(config_theme
);
687 c
= obt_xml_node_string(n
);
688 config_theme
= obt_paths_expand_tilde(c
);
691 if ((n
= obt_xml_find_node(node
, "titleLayout"))) {
694 g_free(config_title_layout
);
695 config_title_layout
= obt_xml_node_string(n
);
697 /* replace duplicates with spaces */
698 for (c
= config_title_layout
; *c
!= '\0'; ++c
)
699 for (d
= c
+1; *d
!= '\0'; ++d
)
700 if (*c
== *d
) *d
= ' ';
702 if ((n
= obt_xml_find_node(node
, "keepBorder")))
703 config_theme_keepborder
= obt_xml_node_bool(n
);
704 if ((n
= obt_xml_find_node(node
, "animateIconify")))
705 config_animate_iconify
= obt_xml_node_bool(n
);
706 if ((n
= obt_xml_find_node(node
, "windowListIconSize"))) {
707 config_theme_window_list_icon_size
= obt_xml_node_int(n
);
708 if (config_theme_window_list_icon_size
< 16)
709 config_theme_window_list_icon_size
= 16;
710 else if (config_theme_window_list_icon_size
> 96)
711 config_theme_window_list_icon_size
= 96;
713 if ((n
= obt_xml_find_node(node
, "flashFrameDelay")))
714 config_frame_flash_delay
= obt_xml_node_int(n
);
715 if ((n
= obt_xml_find_node(node
, "flashFrameDuration")))
716 config_frame_flash_duration
= obt_xml_node_int(n
);
718 n
= obt_xml_find_node(node
, "font");
722 gchar
*name
= g_strdup(RrDefaultFontFamily
);
723 gint size
= RrDefaultFontSize
;
724 RrFontWeight weight
= RrDefaultFontWeight
;
725 RrFontSlant slant
= RrDefaultFontSlant
;
727 if (obt_xml_attr_contains(n
, "place", "ActiveWindow"))
728 font
= &config_font_activewindow
;
729 else if (obt_xml_attr_contains(n
, "place", "InactiveWindow"))
730 font
= &config_font_inactivewindow
;
731 else if (obt_xml_attr_contains(n
, "place", "MenuHeader"))
732 font
= &config_font_menutitle
;
733 else if (obt_xml_attr_contains(n
, "place", "MenuItem"))
734 font
= &config_font_menuitem
;
735 else if (obt_xml_attr_contains(n
, "place", "ActiveOnScreenDisplay"))
736 font
= &config_font_activeosd
;
737 else if (obt_xml_attr_contains(n
, "place", "OnScreenDisplay"))
738 font
= &config_font_activeosd
;
739 else if (obt_xml_attr_contains(n
, "place","InactiveOnScreenDisplay"))
740 font
= &config_font_inactiveosd
;
744 if ((fnode
= obt_xml_find_node(n
->children
, "name"))) {
746 name
= obt_xml_node_string(fnode
);
748 if ((fnode
= obt_xml_find_node(n
->children
, "size"))) {
749 int s
= obt_xml_node_int(fnode
);
752 if ((fnode
= obt_xml_find_node(n
->children
, "weight"))) {
753 gchar
*w
= obt_xml_node_string(fnode
);
754 if (!g_ascii_strcasecmp(w
, "Bold"))
755 weight
= RR_FONTWEIGHT_BOLD
;
758 if ((fnode
= obt_xml_find_node(n
->children
, "slant"))) {
759 gchar
*s
= obt_xml_node_string(fnode
);
760 if (!g_ascii_strcasecmp(s
, "Italic"))
761 slant
= RR_FONTSLANT_ITALIC
;
762 if (!g_ascii_strcasecmp(s
, "Oblique"))
763 slant
= RR_FONTSLANT_OBLIQUE
;
767 *font
= RrFontOpen(ob_rr_inst
, name
, size
, weight
, slant
);
770 n
= obt_xml_find_node(n
->next
, "font");
774 static void parse_desktops(xmlNodePtr node
, gpointer d
)
778 node
= node
->children
;
780 if ((n
= obt_xml_find_node(node
, "number"))) {
781 gint d
= obt_xml_node_int(n
);
783 config_desktops_num
= (unsigned) d
;
785 if ((n
= obt_xml_find_node(node
, "firstdesk"))) {
786 gint d
= obt_xml_node_int(n
);
788 config_screen_firstdesk
= (unsigned) d
;
790 if ((n
= obt_xml_find_node(node
, "names"))) {
794 for (it
= config_desktops_names
; it
; it
= it
->next
)
796 g_slist_free(config_desktops_names
);
797 config_desktops_names
= NULL
;
799 nname
= obt_xml_find_node(n
->children
, "name");
801 config_desktops_names
=
802 g_slist_append(config_desktops_names
,
803 obt_xml_node_string(nname
));
804 nname
= obt_xml_find_node(nname
->next
, "name");
807 if ((n
= obt_xml_find_node(node
, "popupTime")))
808 config_desktop_popup_time
= obt_xml_node_int(n
);
811 static void parse_resize(xmlNodePtr node
, gpointer d
)
815 node
= node
->children
;
817 if ((n
= obt_xml_find_node(node
, "drawContents")))
818 config_resize_redraw
= obt_xml_node_bool(n
);
819 if ((n
= obt_xml_find_node(node
, "popupShow"))) {
820 config_resize_popup_show
= obt_xml_node_int(n
);
821 if (obt_xml_node_contains(n
, "Always"))
822 config_resize_popup_show
= 2;
823 else if (obt_xml_node_contains(n
, "Never"))
824 config_resize_popup_show
= 0;
825 else if (obt_xml_node_contains(n
, "Nonpixel"))
826 config_resize_popup_show
= 1;
828 if ((n
= obt_xml_find_node(node
, "popupPosition"))) {
829 if (obt_xml_node_contains(n
, "Top"))
830 config_resize_popup_pos
= OB_RESIZE_POS_TOP
;
831 else if (obt_xml_node_contains(n
, "Center"))
832 config_resize_popup_pos
= OB_RESIZE_POS_CENTER
;
833 else if (obt_xml_node_contains(n
, "Fixed")) {
834 config_resize_popup_pos
= OB_RESIZE_POS_FIXED
;
836 if ((n
= obt_xml_find_node(node
, "popupFixedPosition"))) {
839 if ((n2
= obt_xml_find_node(n
->children
, "x")))
840 config_parse_gravity_coord(n2
,
841 &config_resize_popup_fixed
.x
);
842 if ((n2
= obt_xml_find_node(n
->children
, "y")))
843 config_parse_gravity_coord(n2
,
844 &config_resize_popup_fixed
.y
);
846 config_resize_popup_fixed
.x
.pos
=
847 MAX(config_resize_popup_fixed
.x
.pos
, 0);
848 config_resize_popup_fixed
.y
.pos
=
849 MAX(config_resize_popup_fixed
.y
.pos
, 0);
855 static void parse_dock(xmlNodePtr node
, gpointer d
)
859 node
= node
->children
;
861 if ((n
= obt_xml_find_node(node
, "position"))) {
862 if (obt_xml_node_contains(n
, "TopLeft"))
863 config_dock_floating
= FALSE
,
864 config_dock_pos
= OB_DIRECTION_NORTHWEST
;
865 else if (obt_xml_node_contains(n
, "Top"))
866 config_dock_floating
= FALSE
,
867 config_dock_pos
= OB_DIRECTION_NORTH
;
868 else if (obt_xml_node_contains(n
, "TopRight"))
869 config_dock_floating
= FALSE
,
870 config_dock_pos
= OB_DIRECTION_NORTHEAST
;
871 else if (obt_xml_node_contains(n
, "Right"))
872 config_dock_floating
= FALSE
,
873 config_dock_pos
= OB_DIRECTION_EAST
;
874 else if (obt_xml_node_contains(n
, "BottomRight"))
875 config_dock_floating
= FALSE
,
876 config_dock_pos
= OB_DIRECTION_SOUTHEAST
;
877 else if (obt_xml_node_contains(n
, "Bottom"))
878 config_dock_floating
= FALSE
,
879 config_dock_pos
= OB_DIRECTION_SOUTH
;
880 else if (obt_xml_node_contains(n
, "BottomLeft"))
881 config_dock_floating
= FALSE
,
882 config_dock_pos
= OB_DIRECTION_SOUTHWEST
;
883 else if (obt_xml_node_contains(n
, "Left"))
884 config_dock_floating
= FALSE
,
885 config_dock_pos
= OB_DIRECTION_WEST
;
886 else if (obt_xml_node_contains(n
, "Floating"))
887 config_dock_floating
= TRUE
;
889 if (config_dock_floating
) {
890 if ((n
= obt_xml_find_node(node
, "floatingX")))
891 config_dock_x
= obt_xml_node_int(n
);
892 if ((n
= obt_xml_find_node(node
, "floatingY")))
893 config_dock_y
= obt_xml_node_int(n
);
895 if ((n
= obt_xml_find_node(node
, "noStrut")))
896 config_dock_nostrut
= obt_xml_node_bool(n
);
898 if ((n
= obt_xml_find_node(node
, "stacking"))) {
899 if (obt_xml_node_contains(n
, "normal"))
900 config_dock_layer
= OB_STACKING_LAYER_NORMAL
;
901 else if (obt_xml_node_contains(n
, "below"))
902 config_dock_layer
= OB_STACKING_LAYER_BELOW
;
903 else if (obt_xml_node_contains(n
, "above"))
904 config_dock_layer
= OB_STACKING_LAYER_ABOVE
;
906 if ((n
= obt_xml_find_node(node
, "direction"))) {
907 if (obt_xml_node_contains(n
, "horizontal"))
908 config_dock_orient
= OB_ORIENTATION_HORZ
;
909 else if (obt_xml_node_contains(n
, "vertical"))
910 config_dock_orient
= OB_ORIENTATION_VERT
;
912 if ((n
= obt_xml_find_node(node
, "autoHide")))
913 config_dock_hide
= obt_xml_node_bool(n
);
914 if ((n
= obt_xml_find_node(node
, "hideDelay")))
915 config_dock_hide_delay
= obt_xml_node_int(n
);
916 if ((n
= obt_xml_find_node(node
, "showDelay")))
917 config_dock_show_delay
= obt_xml_node_int(n
);
918 if ((n
= obt_xml_find_node(node
, "moveButton"))) {
919 gchar
*str
= obt_xml_node_string(n
);
921 if (translate_button(str
, &s
, &b
)) {
922 config_dock_app_move_button
= b
;
923 config_dock_app_move_modifiers
= s
;
925 g_message(_("Invalid button \"%s\" specified in config file"), str
);
931 static void parse_menu(xmlNodePtr node
, gpointer d
)
934 node
= node
->children
;
936 if ((n
= obt_xml_find_node(node
, "hideDelay")))
937 config_menu_hide_delay
= obt_xml_node_int(n
);
938 if ((n
= obt_xml_find_node(node
, "middle")))
939 config_menu_middle
= obt_xml_node_bool(n
);
940 if ((n
= obt_xml_find_node(node
, "submenuShowDelay")))
941 config_submenu_show_delay
= obt_xml_node_int(n
);
942 if ((n
= obt_xml_find_node(node
, "submenuHideDelay")))
943 config_submenu_hide_delay
= obt_xml_node_int(n
);
944 if ((n
= obt_xml_find_node(node
, "manageDesktops")))
945 config_menu_manage_desktops
= obt_xml_node_bool(n
);
946 if ((n
= obt_xml_find_node(node
, "showIcons"))) {
947 config_menu_show_icons
= obt_xml_node_bool(n
);
948 #if !defined(USE_IMLIB2) && !defined(USE_LIBRSVG)
949 if (config_menu_show_icons
)
950 g_message(_("Openbox was compiled without image loading support. Icons in menus will not be loaded."));
954 while ((node
= obt_xml_find_node(node
, "file"))) {
955 gchar
*c
= obt_xml_node_string(node
);
956 config_menu_files
= g_slist_append(config_menu_files
,
957 obt_paths_expand_tilde(c
));
963 static void parse_resistance(xmlNodePtr node
, gpointer d
)
967 node
= node
->children
;
968 if ((n
= obt_xml_find_node(node
, "strength")))
969 config_resist_win
= obt_xml_node_int(n
);
970 if ((n
= obt_xml_find_node(node
, "screen_edge_strength")))
971 config_resist_edge
= obt_xml_node_int(n
);
977 const gchar
*actname
;
980 static void bind_default_keyboard(void)
983 ObDefKeyBind binds
[] = {
984 { "A-Tab", "NextWindow" },
985 { "S-A-Tab", "PreviousWindow" },
989 for (it
= binds
; it
->key
; ++it
) {
990 GList
*l
= g_list_append(NULL
, g_strdup(it
->key
));
991 keyboard_bind(l
, actions_parse_string(it
->actname
));
998 const gchar
*context
;
999 const ObMouseAction mact
;
1000 const gchar
*actname
;
1003 static void bind_default_mouse(void)
1006 ObDefMouseBind binds
[] = {
1007 { "Left", "Client", OB_MOUSE_ACTION_PRESS
, "Focus" },
1008 { "Middle", "Client", OB_MOUSE_ACTION_PRESS
, "Focus" },
1009 { "Right", "Client", OB_MOUSE_ACTION_PRESS
, "Focus" },
1010 { "Left", "Desktop", OB_MOUSE_ACTION_PRESS
, "Focus" },
1011 { "Middle", "Desktop", OB_MOUSE_ACTION_PRESS
, "Focus" },
1012 { "Right", "Desktop", OB_MOUSE_ACTION_PRESS
, "Focus" },
1013 { "Left", "Titlebar", OB_MOUSE_ACTION_PRESS
, "Focus" },
1014 { "Left", "Bottom", OB_MOUSE_ACTION_PRESS
, "Focus" },
1015 { "Left", "BLCorner", OB_MOUSE_ACTION_PRESS
, "Focus" },
1016 { "Left", "BRCorner", OB_MOUSE_ACTION_PRESS
, "Focus" },
1017 { "Left", "TLCorner", OB_MOUSE_ACTION_PRESS
, "Focus" },
1018 { "Left", "TRCorner", OB_MOUSE_ACTION_PRESS
, "Focus" },
1019 { "Left", "Close", OB_MOUSE_ACTION_PRESS
, "Focus" },
1020 { "Left", "Maximize", OB_MOUSE_ACTION_PRESS
, "Focus" },
1021 { "Left", "Iconify", OB_MOUSE_ACTION_PRESS
, "Focus" },
1022 { "Left", "Icon", OB_MOUSE_ACTION_PRESS
, "Focus" },
1023 { "Left", "AllDesktops", OB_MOUSE_ACTION_PRESS
, "Focus" },
1024 { "Left", "Shade", OB_MOUSE_ACTION_PRESS
, "Focus" },
1025 { "Left", "Client", OB_MOUSE_ACTION_CLICK
, "Raise" },
1026 { "Left", "Titlebar", OB_MOUSE_ACTION_CLICK
, "Raise" },
1027 { "Middle", "Titlebar", OB_MOUSE_ACTION_CLICK
, "Lower" },
1028 { "Left", "BLCorner", OB_MOUSE_ACTION_CLICK
, "Raise" },
1029 { "Left", "BRCorner", OB_MOUSE_ACTION_CLICK
, "Raise" },
1030 { "Left", "TLCorner", OB_MOUSE_ACTION_CLICK
, "Raise" },
1031 { "Left", "TRCorner", OB_MOUSE_ACTION_CLICK
, "Raise" },
1032 { "Left", "Close", OB_MOUSE_ACTION_CLICK
, "Raise" },
1033 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK
, "Raise" },
1034 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK
, "Raise" },
1035 { "Left", "Icon", OB_MOUSE_ACTION_CLICK
, "Raise" },
1036 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK
, "Raise" },
1037 { "Left", "Shade", OB_MOUSE_ACTION_CLICK
, "Raise" },
1038 { "Left", "Close", OB_MOUSE_ACTION_CLICK
, "Close" },
1039 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK
, "ToggleMaximize" },
1040 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK
, "Iconify" },
1041 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK
, "ToggleOmnipresent" },
1042 { "Left", "Shade", OB_MOUSE_ACTION_CLICK
, "ToggleShade" },
1043 { "Left", "TLCorner", OB_MOUSE_ACTION_MOTION
, "Resize" },
1044 { "Left", "TRCorner", OB_MOUSE_ACTION_MOTION
, "Resize" },
1045 { "Left", "BLCorner", OB_MOUSE_ACTION_MOTION
, "Resize" },
1046 { "Left", "BRCorner", OB_MOUSE_ACTION_MOTION
, "Resize" },
1047 { "Left", "Top", OB_MOUSE_ACTION_MOTION
, "Resize" },
1048 { "Left", "Bottom", OB_MOUSE_ACTION_MOTION
, "Resize" },
1049 { "Left", "Left", OB_MOUSE_ACTION_MOTION
, "Resize" },
1050 { "Left", "Right", OB_MOUSE_ACTION_MOTION
, "Resize" },
1051 { "Left", "Titlebar", OB_MOUSE_ACTION_MOTION
, "Move" },
1052 { "A-Left", "Frame", OB_MOUSE_ACTION_MOTION
, "Move" },
1053 { "A-Middle", "Frame", OB_MOUSE_ACTION_MOTION
, "Resize" },
1054 { NULL
, NULL
, 0, NULL
}
1057 for (it
= binds
; it
->button
; ++it
)
1058 mouse_bind(it
->button
, frame_context_from_string(it
->context
),
1059 it
->mact
, actions_parse_string(it
->actname
));
1062 void config_startup(ObtXmlInst
*i
)
1064 config_focus_new
= TRUE
;
1065 config_focus_follow
= FALSE
;
1066 config_focus_delay
= 0;
1067 config_focus_raise
= FALSE
;
1068 config_focus_last
= TRUE
;
1069 config_focus_under_mouse
= FALSE
;
1070 config_unfocus_leave
= FALSE
;
1072 obt_xml_register(i
, "focus", parse_focus
, NULL
);
1074 config_place_policy
= OB_PLACE_POLICY_SMART
;
1075 config_place_center
= TRUE
;
1076 config_place_monitor
= OB_PLACE_MONITOR_PRIMARY
;
1078 config_primary_monitor_index
= 1;
1079 config_primary_monitor
= OB_PLACE_MONITOR_ACTIVE
;
1081 obt_xml_register(i
, "placement", parse_placement
, NULL
);
1083 STRUT_PARTIAL_SET(config_margins
, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1085 obt_xml_register(i
, "margins", parse_margins
, NULL
);
1087 config_theme
= NULL
;
1089 config_animate_iconify
= TRUE
;
1090 config_title_layout
= g_strdup("NLIMC");
1091 config_theme_keepborder
= TRUE
;
1092 config_theme_window_list_icon_size
= 36;
1093 config_frame_flash_delay
= 600;
1094 config_frame_flash_duration
= 5000;
1096 config_font_activewindow
= NULL
;
1097 config_font_inactivewindow
= NULL
;
1098 config_font_menuitem
= NULL
;
1099 config_font_menutitle
= NULL
;
1100 config_font_activeosd
= NULL
;
1101 config_font_inactiveosd
= NULL
;
1103 obt_xml_register(i
, "theme", parse_theme
, NULL
);
1105 config_desktops_num
= 4;
1106 config_screen_firstdesk
= 1;
1107 config_desktops_names
= NULL
;
1108 config_desktop_popup_time
= 875;
1110 obt_xml_register(i
, "desktops", parse_desktops
, NULL
);
1112 config_resize_redraw
= TRUE
;
1113 config_resize_popup_show
= 1; /* nonpixel increments */
1114 config_resize_popup_pos
= OB_RESIZE_POS_CENTER
;
1115 GRAVITY_COORD_SET(config_resize_popup_fixed
.x
, 0, FALSE
, FALSE
);
1116 GRAVITY_COORD_SET(config_resize_popup_fixed
.y
, 0, FALSE
, FALSE
);
1118 obt_xml_register(i
, "resize", parse_resize
, NULL
);
1120 config_dock_layer
= OB_STACKING_LAYER_ABOVE
;
1121 config_dock_pos
= OB_DIRECTION_NORTHEAST
;
1122 config_dock_floating
= FALSE
;
1123 config_dock_nostrut
= FALSE
;
1126 config_dock_orient
= OB_ORIENTATION_VERT
;
1127 config_dock_hide
= FALSE
;
1128 config_dock_hide_delay
= 300;
1129 config_dock_show_delay
= 300;
1130 config_dock_app_move_button
= 2; /* middle */
1131 config_dock_app_move_modifiers
= 0;
1133 obt_xml_register(i
, "dock", parse_dock
, NULL
);
1135 translate_key("C-g", &config_keyboard_reset_state
,
1136 &config_keyboard_reset_keycode
);
1138 bind_default_keyboard();
1140 obt_xml_register(i
, "keyboard", parse_keyboard
, NULL
);
1142 config_mouse_threshold
= 8;
1143 config_mouse_dclicktime
= 500;
1144 config_mouse_screenedgetime
= 400;
1145 config_mouse_screenedgewarp
= FALSE
;
1147 bind_default_mouse();
1149 obt_xml_register(i
, "mouse", parse_mouse
, NULL
);
1151 config_resist_win
= 10;
1152 config_resist_edge
= 20;
1154 obt_xml_register(i
, "resistance", parse_resistance
, NULL
);
1156 config_menu_hide_delay
= 250;
1157 config_menu_middle
= FALSE
;
1158 config_submenu_show_delay
= 100;
1159 config_submenu_hide_delay
= 400;
1160 config_menu_manage_desktops
= TRUE
;
1161 config_menu_files
= NULL
;
1162 config_menu_show_icons
= TRUE
;
1164 obt_xml_register(i
, "menu", parse_menu
, NULL
);
1166 config_per_app_settings
= NULL
;
1168 obt_xml_register(i
, "applications", parse_per_app_settings
, NULL
);
1171 void config_shutdown(void)
1175 g_free(config_theme
);
1177 g_free(config_title_layout
);
1179 RrFontClose(config_font_activewindow
);
1180 RrFontClose(config_font_inactivewindow
);
1181 RrFontClose(config_font_menuitem
);
1182 RrFontClose(config_font_menutitle
);
1183 RrFontClose(config_font_activeosd
);
1184 RrFontClose(config_font_inactiveosd
);
1186 for (it
= config_desktops_names
; it
; it
= g_slist_next(it
))
1188 g_slist_free(config_desktops_names
);
1190 for (it
= config_menu_files
; it
; it
= g_slist_next(it
))
1192 g_slist_free(config_menu_files
);
1194 for (it
= config_per_app_settings
; it
; it
= g_slist_next(it
)) {
1195 ObAppSettings
*itd
= (ObAppSettings
*)it
->data
;
1196 if (itd
->name
) g_pattern_spec_free(itd
->name
);
1197 if (itd
->role
) g_pattern_spec_free(itd
->role
);
1198 if (itd
->title
) g_pattern_spec_free(itd
->title
);
1199 if (itd
->class) g_pattern_spec_free(itd
->class);
1200 if (itd
->group_name
) g_pattern_spec_free(itd
->group_name
);
1201 if (itd
->group_class
) g_pattern_spec_free(itd
->group_class
);
1202 g_slice_free(ObAppSettings
, it
->data
);
1204 g_slist_free(config_per_app_settings
);