1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
3 config.c for the Openbox window manager
4 Copyright (c) 2006 Mikael Magnusson
5 Copyright (c) 2003-2007 Dana Jansens
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 See the COPYING file for a copy of the GNU General Public License.
24 #include "translate.h"
29 #include "obt/paths.h"
31 gboolean config_focus_new
;
32 gboolean config_focus_follow
;
33 guint config_focus_delay
;
34 gboolean config_focus_raise
;
35 gboolean config_focus_last
;
36 gboolean config_focus_under_mouse
;
37 gboolean config_unfocus_leave
;
39 ObPlacePolicy config_place_policy
;
40 ObPlaceMonitor config_place_monitor
;
42 guint config_primary_monitor_index
;
43 ObPlaceMonitor config_primary_monitor
;
45 StrutPartial config_margins
;
48 gboolean config_theme_keepborder
;
49 guint config_theme_window_list_icon_size
;
51 gchar
*config_title_layout
;
53 gboolean config_animate_iconify
;
55 RrFont
*config_font_activewindow
;
56 RrFont
*config_font_inactivewindow
;
57 RrFont
*config_font_menuitem
;
58 RrFont
*config_font_menutitle
;
59 RrFont
*config_font_activeosd
;
60 RrFont
*config_font_inactiveosd
;
62 guint config_desktops_num
;
63 GSList
*config_desktops_names
;
64 guint config_screen_firstdesk
;
65 guint config_desktop_popup_time
;
67 gboolean config_resize_redraw
;
68 gint config_resize_popup_show
;
69 ObResizePopupPos config_resize_popup_pos
;
70 GravityPoint config_resize_popup_fixed
;
72 ObStackingLayer config_dock_layer
;
73 gboolean config_dock_floating
;
74 gboolean config_dock_nostrut
;
75 ObDirection config_dock_pos
;
78 ObOrientation config_dock_orient
;
79 gboolean config_dock_hide
;
80 guint config_dock_hide_delay
;
81 guint config_dock_show_delay
;
82 guint config_dock_app_move_button
;
83 guint config_dock_app_move_modifiers
;
85 guint config_keyboard_reset_keycode
;
86 guint config_keyboard_reset_state
;
88 gint config_mouse_threshold
;
89 gint config_mouse_dclicktime
;
90 gint config_mouse_screenedgetime
;
91 gboolean config_mouse_screenedgewarp
;
93 guint config_menu_hide_delay
;
94 gboolean config_menu_middle
;
95 guint config_submenu_show_delay
;
96 guint config_submenu_hide_delay
;
97 gboolean config_menu_manage_desktops
;
98 gboolean config_menu_show_icons
;
100 GSList
*config_menu_files
;
102 gint config_resist_win
;
103 gint config_resist_edge
;
105 GSList
*config_per_app_settings
;
107 ObAppSettings
* config_create_app_settings(void)
109 ObAppSettings
*settings
= g_slice_new0(ObAppSettings
);
111 settings
->decor
= -1;
112 settings
->shade
= -1;
113 settings
->monitor_type
= OB_PLACE_MONITOR_ANY
;
114 settings
->monitor
= -1;
115 settings
->focus
= -1;
116 settings
->desktop
= 0;
117 settings
->layer
= -2;
118 settings
->iconic
= -1;
119 settings
->skip_pager
= -1;
120 settings
->skip_taskbar
= -1;
121 settings
->fullscreen
= -1;
122 settings
->max_horz
= -1;
123 settings
->max_vert
= -1;
127 #define copy_if(setting, default) \
128 if (src->setting != default) dst->setting = src->setting
129 void config_app_settings_copy_non_defaults(const ObAppSettings
*src
,
132 g_assert(src
!= NULL
);
133 g_assert(dst
!= NULL
);
135 copy_if(type
, (ObClientType
)-1);
138 copy_if(monitor_type
, OB_PLACE_MONITOR_ANY
);
139 copy_if(monitor
, -1);
144 copy_if(skip_pager
, -1);
145 copy_if(skip_taskbar
, -1);
146 copy_if(fullscreen
, -1);
147 copy_if(max_horz
, -1);
148 copy_if(max_vert
, -1);
150 if (src
->pos_given
) {
151 dst
->pos_given
= TRUE
;
152 dst
->pos_force
= src
->pos_force
;
153 dst
->position
= src
->position
;
154 /* monitor is copied above */
157 if (src
->size_given
) {
158 dst
->size_given
= TRUE
;
159 dst
->width_num
= src
->width_num
;
160 dst
->width_denom
= src
->width_denom
;
161 dst
->height_num
= src
->height_num
;
162 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 /* Manages settings for individual applications.
211 Some notes: monitor is the screen number in a multi monitor
212 (Xinerama) setup (starting from 0), or mouse: the monitor the pointer
213 is on, active: the active monitor, primary: the primary monitor.
214 Layer can be three values, above (Always on top), below
215 (Always on bottom) and everything else (normal behaviour).
216 Positions can be an integer value or center, which will
217 center the window in the specified axis. Position is within
218 the monitor, so <position><x>center</x></position><monitor>2</monitor>
219 will center the window on the second monitor.
221 static void parse_per_app_settings(xmlNodePtr node
, gpointer d
)
223 xmlNodePtr app
= obt_xml_find_node(node
->children
, "application");
224 gchar
*name
= NULL
, *class = NULL
, *role
= NULL
, *title
= NULL
,
225 *type_str
= NULL
, *group_name
= NULL
, *group_class
= NULL
;
226 gboolean name_set
, class_set
, type_set
, role_set
, title_set
,
227 group_name_set
, group_class_set
;
229 gboolean x_pos_given
;
230 gboolean width_given
;
233 x_pos_given
= width_given
= FALSE
;
235 class_set
= obt_xml_attr_string(app
, "class", &class);
236 name_set
= obt_xml_attr_string(app
, "name", &name
);
237 group_class_set
= obt_xml_attr_string(app
, "groupclass", &group_class
);
238 group_name_set
= obt_xml_attr_string(app
, "groupname", &group_name
);
239 type_set
= obt_xml_attr_string(app
, "type", &type_str
);
240 role_set
= obt_xml_attr_string(app
, "role", &role
);
241 title_set
= obt_xml_attr_string(app
, "title", &title
);
243 /* validate the type tho */
245 if (!g_ascii_strcasecmp(type_str
, "normal"))
246 type
= OB_CLIENT_TYPE_NORMAL
;
247 else if (!g_ascii_strcasecmp(type_str
, "dialog"))
248 type
= OB_CLIENT_TYPE_DIALOG
;
249 else if (!g_ascii_strcasecmp(type_str
, "splash"))
250 type
= OB_CLIENT_TYPE_SPLASH
;
251 else if (!g_ascii_strcasecmp(type_str
, "utility"))
252 type
= OB_CLIENT_TYPE_UTILITY
;
253 else if (!g_ascii_strcasecmp(type_str
, "menu"))
254 type
= OB_CLIENT_TYPE_MENU
;
255 else if (!g_ascii_strcasecmp(type_str
, "toolbar"))
256 type
= OB_CLIENT_TYPE_TOOLBAR
;
257 else if (!g_ascii_strcasecmp(type_str
, "dock"))
258 type
= OB_CLIENT_TYPE_DOCK
;
259 else if (!g_ascii_strcasecmp(type_str
, "desktop"))
260 type
= OB_CLIENT_TYPE_DESKTOP
;
262 type_set
= FALSE
; /* not valid! */
265 if (class_set
|| name_set
|| role_set
|| title_set
|| type_set
||
266 group_class_set
|| group_name_set
)
269 ObAppSettings
*settings
= config_create_app_settings();
272 settings
->name
= g_pattern_spec_new(name
);
275 settings
->class = g_pattern_spec_new(class);
278 settings
->group_name
= g_pattern_spec_new(group_name
);
281 settings
->group_class
= g_pattern_spec_new(group_class
);
284 settings
->role
= g_pattern_spec_new(role
);
287 settings
->title
= g_pattern_spec_new(title
);
290 settings
->type
= type
;
292 if ((n
= obt_xml_find_node(app
->children
, "decor")))
293 if (!obt_xml_node_contains(n
, "default"))
294 settings
->decor
= obt_xml_node_bool(n
);
296 if ((n
= obt_xml_find_node(app
->children
, "shade")))
297 if (!obt_xml_node_contains(n
, "default"))
298 settings
->shade
= obt_xml_node_bool(n
);
300 if ((n
= obt_xml_find_node(app
->children
, "position"))) {
301 if ((c
= obt_xml_find_node(n
->children
, "x")))
302 if (!obt_xml_node_contains(c
, "default")) {
303 config_parse_gravity_coord(c
, &settings
->position
.x
);
307 if (x_pos_given
&& (c
= obt_xml_find_node(n
->children
, "y")))
308 if (!obt_xml_node_contains(c
, "default")) {
309 config_parse_gravity_coord(c
, &settings
->position
.y
);
310 settings
->pos_given
= TRUE
;
313 /* monitor can be set without setting x or y */
314 if ((c
= obt_xml_find_node(n
->children
, "monitor")))
315 if (!obt_xml_node_contains(c
, "default")) {
316 gchar
*s
= obt_xml_node_string(c
);
317 if (!g_ascii_strcasecmp(s
, "mouse"))
318 settings
->monitor_type
=
319 OB_PLACE_MONITOR_MOUSE
;
320 else if (!g_ascii_strcasecmp(s
, "active"))
321 settings
->monitor_type
=
322 OB_PLACE_MONITOR_ACTIVE
;
323 else if (!g_ascii_strcasecmp(s
, "primary"))
324 settings
->monitor_type
=
325 OB_PLACE_MONITOR_PRIMARY
;
327 settings
->monitor
= obt_xml_node_int(c
);
331 obt_xml_attr_bool(n
, "force", &settings
->pos_force
);
334 if ((n
= obt_xml_find_node(app
->children
, "size"))) {
335 if ((c
= obt_xml_find_node(n
->children
, "width"))) {
336 if (!obt_xml_node_contains(c
, "default")) {
337 gchar
*s
= obt_xml_node_string(c
);
338 config_parse_relative_number(
340 &settings
->width_num
,
341 &settings
->width_denom
);
342 if (settings
->width_num
> 0 &&
343 settings
->width_denom
>= 0)
352 (c
= obt_xml_find_node(n
->children
, "height")))
354 gchar
*s
= obt_xml_node_string(c
);
355 config_parse_relative_number(
357 &settings
->height_num
,
358 &settings
->height_denom
);
359 if (settings
->height_num
> 0 &&
360 settings
->height_denom
>= 0)
362 settings
->size_given
= TRUE
;
368 if ((n
= obt_xml_find_node(app
->children
, "focus")))
369 if (!obt_xml_node_contains(n
, "default"))
370 settings
->focus
= obt_xml_node_bool(n
);
372 if ((n
= obt_xml_find_node(app
->children
, "desktop"))) {
373 if (!obt_xml_node_contains(n
, "default")) {
374 gchar
*s
= obt_xml_node_string(n
);
375 if (!g_ascii_strcasecmp(s
, "all"))
376 settings
->desktop
= DESKTOP_ALL
;
378 gint i
= obt_xml_node_int(n
);
380 settings
->desktop
= i
;
386 if ((n
= obt_xml_find_node(app
->children
, "layer")))
387 if (!obt_xml_node_contains(n
, "default")) {
388 gchar
*s
= obt_xml_node_string(n
);
389 if (!g_ascii_strcasecmp(s
, "above"))
391 else if (!g_ascii_strcasecmp(s
, "below"))
392 settings
->layer
= -1;
398 if ((n
= obt_xml_find_node(app
->children
, "iconic")))
399 if (!obt_xml_node_contains(n
, "default"))
400 settings
->iconic
= obt_xml_node_bool(n
);
402 if ((n
= obt_xml_find_node(app
->children
, "skip_pager")))
403 if (!obt_xml_node_contains(n
, "default"))
404 settings
->skip_pager
= obt_xml_node_bool(n
);
406 if ((n
= obt_xml_find_node(app
->children
, "skip_taskbar")))
407 if (!obt_xml_node_contains(n
, "default"))
408 settings
->skip_taskbar
= obt_xml_node_bool(n
);
410 if ((n
= obt_xml_find_node(app
->children
, "fullscreen")))
411 if (!obt_xml_node_contains(n
, "default"))
412 settings
->fullscreen
= obt_xml_node_bool(n
);
414 if ((n
= obt_xml_find_node(app
->children
, "maximized")))
415 if (!obt_xml_node_contains(n
, "default")) {
416 gchar
*s
= obt_xml_node_string(n
);
417 if (!g_ascii_strcasecmp(s
, "horizontal")) {
418 settings
->max_horz
= TRUE
;
419 settings
->max_vert
= FALSE
;
420 } else if (!g_ascii_strcasecmp(s
, "vertical")) {
421 settings
->max_horz
= FALSE
;
422 settings
->max_vert
= TRUE
;
424 settings
->max_horz
= settings
->max_vert
=
425 obt_xml_node_bool(n
);
429 config_per_app_settings
= g_slist_append(config_per_app_settings
,
430 (gpointer
) settings
);
438 name
= class = group_name
= group_class
= role
= title
= type_str
=
442 app
= obt_xml_find_node(app
->next
, "application");
449 <action name="ChangeDesktop">
456 static void parse_key(xmlNodePtr node
, GList
*keylist
)
458 gchar
*keystring
, **keys
, **key
;
460 gboolean is_chroot
= FALSE
;
462 if (!obt_xml_attr_string(node
, "key", &keystring
))
465 obt_xml_attr_bool(node
, "chroot", &is_chroot
);
467 keys
= g_strsplit(keystring
, " ", 0);
468 for (key
= keys
; *key
; ++key
) {
469 keylist
= g_list_append(keylist
, *key
);
471 if ((n
= obt_xml_find_node(node
->children
, "keybind"))) {
473 parse_key(n
, keylist
);
474 n
= obt_xml_find_node(n
->next
, "keybind");
477 else if ((n
= obt_xml_find_node(node
->children
, "action"))) {
479 ObActionsAct
*action
;
481 action
= actions_parse(n
);
483 keyboard_bind(keylist
, action
);
484 n
= obt_xml_find_node(n
->next
, "action");
490 keyboard_chroot(keylist
);
491 keylist
= g_list_delete_link(keylist
, g_list_last(keylist
));
498 static void parse_keyboard(xmlNodePtr node
, gpointer d
)
503 keyboard_unbind_all();
505 if ((n
= obt_xml_find_node(node
->children
, "chainQuitKey"))) {
506 key
= obt_xml_node_string(n
);
507 translate_key(key
, &config_keyboard_reset_state
,
508 &config_keyboard_reset_keycode
);
512 if ((n
= obt_xml_find_node(node
->children
, "keybind")))
515 n
= obt_xml_find_node(n
->next
, "keybind");
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 n
= obt_xml_find_node(node
, "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 nbut
= obt_xml_find_node(n
->children
, "mousebind");
577 if (!obt_xml_attr_string(nbut
, "button", &buttonstr
))
579 if (obt_xml_attr_contains(nbut
, "action", "press"))
580 mact
= OB_MOUSE_ACTION_PRESS
;
581 else if (obt_xml_attr_contains(nbut
, "action", "release"))
582 mact
= OB_MOUSE_ACTION_RELEASE
;
583 else if (obt_xml_attr_contains(nbut
, "action", "click"))
584 mact
= OB_MOUSE_ACTION_CLICK
;
585 else if (obt_xml_attr_contains(nbut
, "action","doubleclick"))
586 mact
= OB_MOUSE_ACTION_DOUBLE_CLICK
;
587 else if (obt_xml_attr_contains(nbut
, "action", "drag"))
588 mact
= OB_MOUSE_ACTION_MOTION
;
592 nact
= obt_xml_find_node(nbut
->children
, "action");
594 ObActionsAct
*action
;
596 if ((action
= actions_parse(nact
)))
597 mouse_bind(buttonstr
, cx
, mact
, action
);
598 nact
= obt_xml_find_node(nact
->next
, "action");
602 nbut
= obt_xml_find_node(nbut
->next
, "mousebind");
608 n
= obt_xml_find_node(n
->next
, "context");
612 static void parse_focus(xmlNodePtr node
, gpointer d
)
616 node
= node
->children
;
618 if ((n
= obt_xml_find_node(node
, "focusNew")))
619 config_focus_new
= obt_xml_node_bool(n
);
620 if ((n
= obt_xml_find_node(node
, "followMouse")))
621 config_focus_follow
= obt_xml_node_bool(n
);
622 if ((n
= obt_xml_find_node(node
, "focusDelay")))
623 config_focus_delay
= obt_xml_node_int(n
);
624 if ((n
= obt_xml_find_node(node
, "raiseOnFocus")))
625 config_focus_raise
= obt_xml_node_bool(n
);
626 if ((n
= obt_xml_find_node(node
, "focusLast")))
627 config_focus_last
= obt_xml_node_bool(n
);
628 if ((n
= obt_xml_find_node(node
, "underMouse")))
629 config_focus_under_mouse
= obt_xml_node_bool(n
);
630 if ((n
= obt_xml_find_node(node
, "unfocusOnLeave")))
631 config_unfocus_leave
= obt_xml_node_bool(n
);
634 static void parse_placement(xmlNodePtr node
, gpointer d
)
638 node
= node
->children
;
640 if ((n
= obt_xml_find_node(node
, "policy")))
641 if (obt_xml_node_contains(n
, "UnderMouse"))
642 config_place_policy
= OB_PLACE_POLICY_MOUSE
;
643 if ((n
= obt_xml_find_node(node
, "monitor"))) {
644 if (obt_xml_node_contains(n
, "active"))
645 config_place_monitor
= OB_PLACE_MONITOR_ACTIVE
;
646 else if (obt_xml_node_contains(n
, "mouse"))
647 config_place_monitor
= OB_PLACE_MONITOR_MOUSE
;
648 else if (obt_xml_node_contains(n
, "any"))
649 config_place_monitor
= OB_PLACE_MONITOR_ANY
;
651 if ((n
= obt_xml_find_node(node
, "primaryMonitor"))) {
652 config_primary_monitor_index
= obt_xml_node_int(n
);
653 if (!config_primary_monitor_index
) {
654 if (obt_xml_node_contains(n
, "mouse"))
655 config_primary_monitor
= OB_PLACE_MONITOR_MOUSE
;
660 static void parse_margins(xmlNodePtr node
, gpointer d
)
664 node
= node
->children
;
666 if ((n
= obt_xml_find_node(node
, "top")))
667 config_margins
.top
= MAX(0, obt_xml_node_int(n
));
668 if ((n
= obt_xml_find_node(node
, "left")))
669 config_margins
.left
= MAX(0, obt_xml_node_int(n
));
670 if ((n
= obt_xml_find_node(node
, "right")))
671 config_margins
.right
= MAX(0, obt_xml_node_int(n
));
672 if ((n
= obt_xml_find_node(node
, "bottom")))
673 config_margins
.bottom
= MAX(0, obt_xml_node_int(n
));
676 static void parse_theme(xmlNodePtr node
, gpointer d
)
680 node
= node
->children
;
682 if ((n
= obt_xml_find_node(node
, "name"))) {
685 g_free(config_theme
);
686 c
= obt_xml_node_string(n
);
687 config_theme
= obt_paths_expand_tilde(c
);
690 if ((n
= obt_xml_find_node(node
, "titleLayout"))) {
693 g_free(config_title_layout
);
694 config_title_layout
= obt_xml_node_string(n
);
696 /* replace duplicates with spaces */
697 for (c
= config_title_layout
; *c
!= '\0'; ++c
)
698 for (d
= c
+1; *d
!= '\0'; ++d
)
699 if (*c
== *d
) *d
= ' ';
701 if ((n
= obt_xml_find_node(node
, "keepBorder")))
702 config_theme_keepborder
= obt_xml_node_bool(n
);
703 if ((n
= obt_xml_find_node(node
, "animateIconify")))
704 config_animate_iconify
= obt_xml_node_bool(n
);
705 if ((n
= obt_xml_find_node(node
, "windowListIconSize"))) {
706 config_theme_window_list_icon_size
= obt_xml_node_int(n
);
707 if (config_theme_window_list_icon_size
< 16)
708 config_theme_window_list_icon_size
= 16;
709 else if (config_theme_window_list_icon_size
> 96)
710 config_theme_window_list_icon_size
= 96;
713 n
= obt_xml_find_node(node
, "font");
717 gchar
*name
= g_strdup(RrDefaultFontFamily
);
718 gint size
= RrDefaultFontSize
;
719 RrFontWeight weight
= RrDefaultFontWeight
;
720 RrFontSlant slant
= RrDefaultFontSlant
;
722 if (obt_xml_attr_contains(n
, "place", "ActiveWindow"))
723 font
= &config_font_activewindow
;
724 else if (obt_xml_attr_contains(n
, "place", "InactiveWindow"))
725 font
= &config_font_inactivewindow
;
726 else if (obt_xml_attr_contains(n
, "place", "MenuHeader"))
727 font
= &config_font_menutitle
;
728 else if (obt_xml_attr_contains(n
, "place", "MenuItem"))
729 font
= &config_font_menuitem
;
730 else if (obt_xml_attr_contains(n
, "place", "ActiveOnScreenDisplay"))
731 font
= &config_font_activeosd
;
732 else if (obt_xml_attr_contains(n
, "place", "OnScreenDisplay"))
733 font
= &config_font_activeosd
;
734 else if (obt_xml_attr_contains(n
, "place","InactiveOnScreenDisplay"))
735 font
= &config_font_inactiveosd
;
739 if ((fnode
= obt_xml_find_node(n
->children
, "name"))) {
741 name
= obt_xml_node_string(fnode
);
743 if ((fnode
= obt_xml_find_node(n
->children
, "size"))) {
744 int s
= obt_xml_node_int(fnode
);
747 if ((fnode
= obt_xml_find_node(n
->children
, "weight"))) {
748 gchar
*w
= obt_xml_node_string(fnode
);
749 if (!g_ascii_strcasecmp(w
, "Bold"))
750 weight
= RR_FONTWEIGHT_BOLD
;
753 if ((fnode
= obt_xml_find_node(n
->children
, "slant"))) {
754 gchar
*s
= obt_xml_node_string(fnode
);
755 if (!g_ascii_strcasecmp(s
, "Italic"))
756 slant
= RR_FONTSLANT_ITALIC
;
757 if (!g_ascii_strcasecmp(s
, "Oblique"))
758 slant
= RR_FONTSLANT_OBLIQUE
;
762 *font
= RrFontOpen(ob_rr_inst
, name
, size
, weight
, slant
);
765 n
= obt_xml_find_node(n
->next
, "font");
769 static void parse_desktops(xmlNodePtr node
, gpointer d
)
773 node
= node
->children
;
775 if ((n
= obt_xml_find_node(node
, "number"))) {
776 gint d
= obt_xml_node_int(n
);
778 config_desktops_num
= (unsigned) d
;
780 if ((n
= obt_xml_find_node(node
, "firstdesk"))) {
781 gint d
= obt_xml_node_int(n
);
783 config_screen_firstdesk
= (unsigned) d
;
785 if ((n
= obt_xml_find_node(node
, "names"))) {
789 for (it
= config_desktops_names
; it
; it
= it
->next
)
791 g_slist_free(config_desktops_names
);
792 config_desktops_names
= NULL
;
794 nname
= obt_xml_find_node(n
->children
, "name");
796 config_desktops_names
=
797 g_slist_append(config_desktops_names
,
798 obt_xml_node_string(nname
));
799 nname
= obt_xml_find_node(nname
->next
, "name");
802 if ((n
= obt_xml_find_node(node
, "popupTime")))
803 config_desktop_popup_time
= obt_xml_node_int(n
);
806 static void parse_resize(xmlNodePtr node
, gpointer d
)
810 node
= node
->children
;
812 if ((n
= obt_xml_find_node(node
, "drawContents")))
813 config_resize_redraw
= obt_xml_node_bool(n
);
814 if ((n
= obt_xml_find_node(node
, "popupShow"))) {
815 config_resize_popup_show
= obt_xml_node_int(n
);
816 if (obt_xml_node_contains(n
, "Always"))
817 config_resize_popup_show
= 2;
818 else if (obt_xml_node_contains(n
, "Never"))
819 config_resize_popup_show
= 0;
820 else if (obt_xml_node_contains(n
, "Nonpixel"))
821 config_resize_popup_show
= 1;
823 if ((n
= obt_xml_find_node(node
, "popupPosition"))) {
824 if (obt_xml_node_contains(n
, "Top"))
825 config_resize_popup_pos
= OB_RESIZE_POS_TOP
;
826 else if (obt_xml_node_contains(n
, "Center"))
827 config_resize_popup_pos
= OB_RESIZE_POS_CENTER
;
828 else if (obt_xml_node_contains(n
, "Fixed")) {
829 config_resize_popup_pos
= OB_RESIZE_POS_FIXED
;
831 if ((n
= obt_xml_find_node(node
, "popupFixedPosition"))) {
834 if ((n2
= obt_xml_find_node(n
->children
, "x")))
835 config_parse_gravity_coord(n2
,
836 &config_resize_popup_fixed
.x
);
837 if ((n2
= obt_xml_find_node(n
->children
, "y")))
838 config_parse_gravity_coord(n2
,
839 &config_resize_popup_fixed
.y
);
841 config_resize_popup_fixed
.x
.pos
=
842 MAX(config_resize_popup_fixed
.x
.pos
, 0);
843 config_resize_popup_fixed
.y
.pos
=
844 MAX(config_resize_popup_fixed
.y
.pos
, 0);
850 static void parse_dock(xmlNodePtr node
, gpointer d
)
854 node
= node
->children
;
856 if ((n
= obt_xml_find_node(node
, "position"))) {
857 if (obt_xml_node_contains(n
, "TopLeft"))
858 config_dock_floating
= FALSE
,
859 config_dock_pos
= OB_DIRECTION_NORTHWEST
;
860 else if (obt_xml_node_contains(n
, "Top"))
861 config_dock_floating
= FALSE
,
862 config_dock_pos
= OB_DIRECTION_NORTH
;
863 else if (obt_xml_node_contains(n
, "TopRight"))
864 config_dock_floating
= FALSE
,
865 config_dock_pos
= OB_DIRECTION_NORTHEAST
;
866 else if (obt_xml_node_contains(n
, "Right"))
867 config_dock_floating
= FALSE
,
868 config_dock_pos
= OB_DIRECTION_EAST
;
869 else if (obt_xml_node_contains(n
, "BottomRight"))
870 config_dock_floating
= FALSE
,
871 config_dock_pos
= OB_DIRECTION_SOUTHEAST
;
872 else if (obt_xml_node_contains(n
, "Bottom"))
873 config_dock_floating
= FALSE
,
874 config_dock_pos
= OB_DIRECTION_SOUTH
;
875 else if (obt_xml_node_contains(n
, "BottomLeft"))
876 config_dock_floating
= FALSE
,
877 config_dock_pos
= OB_DIRECTION_SOUTHWEST
;
878 else if (obt_xml_node_contains(n
, "Left"))
879 config_dock_floating
= FALSE
,
880 config_dock_pos
= OB_DIRECTION_WEST
;
881 else if (obt_xml_node_contains(n
, "Floating"))
882 config_dock_floating
= TRUE
;
884 if (config_dock_floating
) {
885 if ((n
= obt_xml_find_node(node
, "floatingX")))
886 config_dock_x
= obt_xml_node_int(n
);
887 if ((n
= obt_xml_find_node(node
, "floatingY")))
888 config_dock_y
= obt_xml_node_int(n
);
890 if ((n
= obt_xml_find_node(node
, "noStrut")))
891 config_dock_nostrut
= obt_xml_node_bool(n
);
893 if ((n
= obt_xml_find_node(node
, "stacking"))) {
894 if (obt_xml_node_contains(n
, "normal"))
895 config_dock_layer
= OB_STACKING_LAYER_NORMAL
;
896 else if (obt_xml_node_contains(n
, "below"))
897 config_dock_layer
= OB_STACKING_LAYER_BELOW
;
898 else if (obt_xml_node_contains(n
, "above"))
899 config_dock_layer
= OB_STACKING_LAYER_ABOVE
;
901 if ((n
= obt_xml_find_node(node
, "direction"))) {
902 if (obt_xml_node_contains(n
, "horizontal"))
903 config_dock_orient
= OB_ORIENTATION_HORZ
;
904 else if (obt_xml_node_contains(n
, "vertical"))
905 config_dock_orient
= OB_ORIENTATION_VERT
;
907 if ((n
= obt_xml_find_node(node
, "autoHide")))
908 config_dock_hide
= obt_xml_node_bool(n
);
909 if ((n
= obt_xml_find_node(node
, "hideDelay")))
910 config_dock_hide_delay
= obt_xml_node_int(n
);
911 if ((n
= obt_xml_find_node(node
, "showDelay")))
912 config_dock_show_delay
= obt_xml_node_int(n
);
913 if ((n
= obt_xml_find_node(node
, "moveButton"))) {
914 gchar
*str
= obt_xml_node_string(n
);
916 if (translate_button(str
, &s
, &b
)) {
917 config_dock_app_move_button
= b
;
918 config_dock_app_move_modifiers
= s
;
920 g_message(_("Invalid button \"%s\" specified in config file"), str
);
926 static void parse_menu(xmlNodePtr node
, gpointer d
)
929 node
= node
->children
;
931 if ((n
= obt_xml_find_node(node
, "hideDelay")))
932 config_menu_hide_delay
= obt_xml_node_int(n
);
933 if ((n
= obt_xml_find_node(node
, "middle")))
934 config_menu_middle
= obt_xml_node_bool(n
);
935 if ((n
= obt_xml_find_node(node
, "submenuShowDelay")))
936 config_submenu_show_delay
= obt_xml_node_int(n
);
937 if ((n
= obt_xml_find_node(node
, "submenuHideDelay")))
938 config_submenu_hide_delay
= obt_xml_node_int(n
);
939 if ((n
= obt_xml_find_node(node
, "manageDesktops")))
940 config_menu_manage_desktops
= obt_xml_node_bool(n
);
941 if ((n
= obt_xml_find_node(node
, "showIcons"))) {
942 config_menu_show_icons
= obt_xml_node_bool(n
);
944 if (config_menu_show_icons
)
945 g_message(_("Openbox was compiled without Imlib2 image loading support. Icons in menus will not be loaded."));
949 while ((node
= obt_xml_find_node(node
, "file"))) {
950 gchar
*c
= obt_xml_node_string(node
);
951 config_menu_files
= g_slist_append(config_menu_files
,
952 obt_paths_expand_tilde(c
));
958 static void parse_resistance(xmlNodePtr node
, gpointer d
)
962 node
= node
->children
;
963 if ((n
= obt_xml_find_node(node
, "strength")))
964 config_resist_win
= obt_xml_node_int(n
);
965 if ((n
= obt_xml_find_node(node
, "screen_edge_strength")))
966 config_resist_edge
= obt_xml_node_int(n
);
972 const gchar
*actname
;
975 static void bind_default_keyboard(void)
978 ObDefKeyBind binds
[] = {
979 { "A-Tab", "NextWindow" },
980 { "S-A-Tab", "PreviousWindow" },
984 for (it
= binds
; it
->key
; ++it
) {
985 GList
*l
= g_list_append(NULL
, g_strdup(it
->key
));
986 keyboard_bind(l
, actions_parse_string(it
->actname
));
993 const gchar
*context
;
994 const ObMouseAction mact
;
995 const gchar
*actname
;
998 static void bind_default_mouse(void)
1001 ObDefMouseBind binds
[] = {
1002 { "Left", "Client", OB_MOUSE_ACTION_PRESS
, "Focus" },
1003 { "Middle", "Client", OB_MOUSE_ACTION_PRESS
, "Focus" },
1004 { "Right", "Client", OB_MOUSE_ACTION_PRESS
, "Focus" },
1005 { "Left", "Desktop", OB_MOUSE_ACTION_PRESS
, "Focus" },
1006 { "Middle", "Desktop", OB_MOUSE_ACTION_PRESS
, "Focus" },
1007 { "Right", "Desktop", OB_MOUSE_ACTION_PRESS
, "Focus" },
1008 { "Left", "Titlebar", OB_MOUSE_ACTION_PRESS
, "Focus" },
1009 { "Left", "Bottom", OB_MOUSE_ACTION_PRESS
, "Focus" },
1010 { "Left", "BLCorner", OB_MOUSE_ACTION_PRESS
, "Focus" },
1011 { "Left", "BRCorner", OB_MOUSE_ACTION_PRESS
, "Focus" },
1012 { "Left", "TLCorner", OB_MOUSE_ACTION_PRESS
, "Focus" },
1013 { "Left", "TRCorner", OB_MOUSE_ACTION_PRESS
, "Focus" },
1014 { "Left", "Close", OB_MOUSE_ACTION_PRESS
, "Focus" },
1015 { "Left", "Maximize", OB_MOUSE_ACTION_PRESS
, "Focus" },
1016 { "Left", "Iconify", OB_MOUSE_ACTION_PRESS
, "Focus" },
1017 { "Left", "Icon", OB_MOUSE_ACTION_PRESS
, "Focus" },
1018 { "Left", "AllDesktops", OB_MOUSE_ACTION_PRESS
, "Focus" },
1019 { "Left", "Shade", OB_MOUSE_ACTION_PRESS
, "Focus" },
1020 { "Left", "Client", OB_MOUSE_ACTION_CLICK
, "Raise" },
1021 { "Left", "Titlebar", OB_MOUSE_ACTION_CLICK
, "Raise" },
1022 { "Middle", "Titlebar", OB_MOUSE_ACTION_CLICK
, "Lower" },
1023 { "Left", "BLCorner", OB_MOUSE_ACTION_CLICK
, "Raise" },
1024 { "Left", "BRCorner", OB_MOUSE_ACTION_CLICK
, "Raise" },
1025 { "Left", "TLCorner", OB_MOUSE_ACTION_CLICK
, "Raise" },
1026 { "Left", "TRCorner", OB_MOUSE_ACTION_CLICK
, "Raise" },
1027 { "Left", "Close", OB_MOUSE_ACTION_CLICK
, "Raise" },
1028 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK
, "Raise" },
1029 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK
, "Raise" },
1030 { "Left", "Icon", OB_MOUSE_ACTION_CLICK
, "Raise" },
1031 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK
, "Raise" },
1032 { "Left", "Shade", OB_MOUSE_ACTION_CLICK
, "Raise" },
1033 { "Left", "Close", OB_MOUSE_ACTION_CLICK
, "Close" },
1034 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK
, "ToggleMaximize" },
1035 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK
, "Iconify" },
1036 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK
, "ToggleOmnipresent" },
1037 { "Left", "Shade", OB_MOUSE_ACTION_CLICK
, "ToggleShade" },
1038 { "Left", "TLCorner", OB_MOUSE_ACTION_MOTION
, "Resize" },
1039 { "Left", "TRCorner", OB_MOUSE_ACTION_MOTION
, "Resize" },
1040 { "Left", "BLCorner", OB_MOUSE_ACTION_MOTION
, "Resize" },
1041 { "Left", "BRCorner", OB_MOUSE_ACTION_MOTION
, "Resize" },
1042 { "Left", "Top", OB_MOUSE_ACTION_MOTION
, "Resize" },
1043 { "Left", "Bottom", OB_MOUSE_ACTION_MOTION
, "Resize" },
1044 { "Left", "Left", OB_MOUSE_ACTION_MOTION
, "Resize" },
1045 { "Left", "Right", OB_MOUSE_ACTION_MOTION
, "Resize" },
1046 { "Left", "Titlebar", OB_MOUSE_ACTION_MOTION
, "Move" },
1047 { "A-Left", "Frame", OB_MOUSE_ACTION_MOTION
, "Move" },
1048 { "A-Middle", "Frame", OB_MOUSE_ACTION_MOTION
, "Resize" },
1049 { NULL
, NULL
, 0, NULL
}
1052 for (it
= binds
; it
->button
; ++it
)
1053 mouse_bind(it
->button
, frame_context_from_string(it
->context
),
1054 it
->mact
, actions_parse_string(it
->actname
));
1057 void config_startup(ObtXmlInst
*i
)
1059 config_focus_new
= TRUE
;
1060 config_focus_follow
= FALSE
;
1061 config_focus_delay
= 0;
1062 config_focus_raise
= FALSE
;
1063 config_focus_last
= TRUE
;
1064 config_focus_under_mouse
= FALSE
;
1065 config_unfocus_leave
= FALSE
;
1067 obt_xml_register(i
, "focus", parse_focus
, NULL
);
1069 config_place_policy
= OB_PLACE_POLICY_SMART
;
1070 config_place_monitor
= OB_PLACE_MONITOR_PRIMARY
;
1072 config_primary_monitor_index
= 1;
1073 config_primary_monitor
= OB_PLACE_MONITOR_ACTIVE
;
1075 obt_xml_register(i
, "placement", parse_placement
, NULL
);
1077 STRUT_PARTIAL_SET(config_margins
, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1079 obt_xml_register(i
, "margins", parse_margins
, NULL
);
1081 config_theme
= NULL
;
1083 config_animate_iconify
= TRUE
;
1084 config_title_layout
= g_strdup("NLIMC");
1085 config_theme_keepborder
= TRUE
;
1086 config_theme_window_list_icon_size
= 36;
1088 config_font_activewindow
= NULL
;
1089 config_font_inactivewindow
= NULL
;
1090 config_font_menuitem
= NULL
;
1091 config_font_menutitle
= NULL
;
1092 config_font_activeosd
= NULL
;
1093 config_font_inactiveosd
= NULL
;
1095 obt_xml_register(i
, "theme", parse_theme
, NULL
);
1097 config_desktops_num
= 4;
1098 config_screen_firstdesk
= 1;
1099 config_desktops_names
= NULL
;
1100 config_desktop_popup_time
= 875;
1102 obt_xml_register(i
, "desktops", parse_desktops
, NULL
);
1104 config_resize_redraw
= TRUE
;
1105 config_resize_popup_show
= 1; /* nonpixel increments */
1106 config_resize_popup_pos
= OB_RESIZE_POS_CENTER
;
1107 GRAVITY_COORD_SET(config_resize_popup_fixed
.x
, 0, FALSE
, FALSE
);
1108 GRAVITY_COORD_SET(config_resize_popup_fixed
.y
, 0, FALSE
, FALSE
);
1110 obt_xml_register(i
, "resize", parse_resize
, NULL
);
1112 config_dock_layer
= OB_STACKING_LAYER_ABOVE
;
1113 config_dock_pos
= OB_DIRECTION_NORTHEAST
;
1114 config_dock_floating
= FALSE
;
1115 config_dock_nostrut
= FALSE
;
1118 config_dock_orient
= OB_ORIENTATION_VERT
;
1119 config_dock_hide
= FALSE
;
1120 config_dock_hide_delay
= 300;
1121 config_dock_show_delay
= 300;
1122 config_dock_app_move_button
= 2; /* middle */
1123 config_dock_app_move_modifiers
= 0;
1125 obt_xml_register(i
, "dock", parse_dock
, NULL
);
1127 translate_key("C-g", &config_keyboard_reset_state
,
1128 &config_keyboard_reset_keycode
);
1130 bind_default_keyboard();
1132 obt_xml_register(i
, "keyboard", parse_keyboard
, NULL
);
1134 config_mouse_threshold
= 8;
1135 config_mouse_dclicktime
= 500;
1136 config_mouse_screenedgetime
= 400;
1137 config_mouse_screenedgewarp
= FALSE
;
1139 bind_default_mouse();
1141 obt_xml_register(i
, "mouse", parse_mouse
, NULL
);
1143 config_resist_win
= 10;
1144 config_resist_edge
= 20;
1146 obt_xml_register(i
, "resistance", parse_resistance
, NULL
);
1148 config_menu_hide_delay
= 250;
1149 config_menu_middle
= FALSE
;
1150 config_submenu_show_delay
= 100;
1151 config_submenu_hide_delay
= 400;
1152 config_menu_manage_desktops
= TRUE
;
1153 config_menu_files
= NULL
;
1154 config_menu_show_icons
= TRUE
;
1156 obt_xml_register(i
, "menu", parse_menu
, NULL
);
1158 config_per_app_settings
= NULL
;
1160 obt_xml_register(i
, "applications", parse_per_app_settings
, NULL
);
1163 void config_shutdown(void)
1167 g_free(config_theme
);
1169 g_free(config_title_layout
);
1171 RrFontClose(config_font_activewindow
);
1172 RrFontClose(config_font_inactivewindow
);
1173 RrFontClose(config_font_menuitem
);
1174 RrFontClose(config_font_menutitle
);
1175 RrFontClose(config_font_activeosd
);
1176 RrFontClose(config_font_inactiveosd
);
1178 for (it
= config_desktops_names
; it
; it
= g_slist_next(it
))
1180 g_slist_free(config_desktops_names
);
1182 for (it
= config_menu_files
; it
; it
= g_slist_next(it
))
1184 g_slist_free(config_menu_files
);
1186 for (it
= config_per_app_settings
; it
; it
= g_slist_next(it
)) {
1187 ObAppSettings
*itd
= (ObAppSettings
*)it
->data
;
1188 if (itd
->name
) g_pattern_spec_free(itd
->name
);
1189 if (itd
->role
) g_pattern_spec_free(itd
->role
);
1190 if (itd
->title
) g_pattern_spec_free(itd
->title
);
1191 if (itd
->class) g_pattern_spec_free(itd
->class);
1192 if (itd
->group_name
) g_pattern_spec_free(itd
->group_name
);
1193 if (itd
->group_class
) g_pattern_spec_free(itd
->group_class
);
1194 g_slice_free(ObAppSettings
, it
->data
);
1196 g_slist_free(config_per_app_settings
);