1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
3 config.c for the Openbox window manager
4 Copyright (c) 2006 Mikael Magnusson
5 Copyright (c) 2003-2007 Dana Jansens
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 See the COPYING file for a copy of the GNU General Public License.
24 #include "translate.h"
29 #include "obt/paths.h"
31 gboolean config_focus_new
;
32 gboolean config_focus_follow
;
33 guint config_focus_delay
;
34 gboolean config_focus_raise
;
35 gboolean config_focus_last
;
36 gboolean config_focus_under_mouse
;
37 gboolean config_unfocus_leave
;
39 ObPlacePolicy config_place_policy
;
40 gboolean config_place_center
;
41 ObPlaceMonitor config_place_monitor
;
43 guint config_primary_monitor_index
;
44 ObPlaceMonitor config_primary_monitor
;
46 StrutPartial config_margins
;
49 gboolean config_theme_keepborder
;
50 guint config_theme_window_list_icon_size
;
52 gchar
*config_title_layout
;
54 gboolean config_animate_iconify
;
56 RrFont
*config_font_activewindow
;
57 RrFont
*config_font_inactivewindow
;
58 RrFont
*config_font_menuitem
;
59 RrFont
*config_font_menutitle
;
60 RrFont
*config_font_activeosd
;
61 RrFont
*config_font_inactiveosd
;
63 guint config_desktops_num
;
64 GSList
*config_desktops_names
;
65 guint config_screen_firstdesk
;
66 guint config_desktop_popup_time
;
68 gboolean config_resize_redraw
;
69 gint config_resize_popup_show
;
70 ObResizePopupPos config_resize_popup_pos
;
71 GravityPoint config_resize_popup_fixed
;
73 ObStackingLayer config_dock_layer
;
74 gboolean config_dock_floating
;
75 gboolean config_dock_nostrut
;
76 ObDirection config_dock_pos
;
79 ObOrientation config_dock_orient
;
80 gboolean config_dock_hide
;
81 guint config_dock_hide_delay
;
82 guint config_dock_show_delay
;
83 guint config_dock_app_move_button
;
84 guint config_dock_app_move_modifiers
;
86 guint config_keyboard_reset_keycode
;
87 guint config_keyboard_reset_state
;
89 gint config_mouse_threshold
;
90 gint config_mouse_dclicktime
;
91 gint config_mouse_screenedgetime
;
92 gboolean config_mouse_screenedgewarp
;
94 guint config_menu_hide_delay
;
95 gboolean config_menu_middle
;
96 guint config_submenu_show_delay
;
97 guint config_submenu_hide_delay
;
98 gboolean config_menu_manage_desktops
;
99 gboolean config_menu_show_icons
;
101 GSList
*config_menu_files
;
103 gint config_resist_win
;
104 gint config_resist_edge
;
106 GSList
*config_per_app_settings
;
108 ObAppSettings
* config_create_app_settings(void)
110 ObAppSettings
*settings
= g_slice_new0(ObAppSettings
);
112 settings
->decor
= -1;
113 settings
->shade
= -1;
114 settings
->monitor
= -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
, -1);
143 copy_if(skip_pager
, -1);
144 copy_if(skip_taskbar
, -1);
145 copy_if(fullscreen
, -1);
146 copy_if(max_horz
, -1);
147 copy_if(max_vert
, -1);
149 if (src
->pos_given
) {
150 dst
->pos_given
= TRUE
;
151 dst
->pos_force
= src
->pos_force
;
152 dst
->position
= src
->position
;
153 /* monitor is copied above */
157 void config_parse_relative_number(gchar
*s
, gint
*num
, gint
*denom
)
159 *num
= strtol(s
, &s
, 10);
163 } else if (*s
== '/') {
168 void config_parse_gravity_coord(xmlNodePtr node
, GravityCoord
*c
)
170 gchar
*s
= obt_xml_node_string(node
);
171 if (!g_ascii_strcasecmp(s
, "center"))
177 if (s
[0] == '-' || s
[0] == '+')
179 config_parse_relative_number(ps
, &c
->pos
, &c
->denom
);
186 <application name="aterm">
189 <application name="Rhythmbox">
196 .. there is a lot more settings available
201 /* Manages settings for individual applications.
202 Some notes: monitor is the screen number in a multi monitor
203 (Xinerama) setup (starting from 0) or mouse, meaning the
204 monitor the pointer is on. Default: mouse.
205 Layer can be three values, above (Always on top), below
206 (Always on bottom) and everything else (normal behaviour).
207 Positions can be an integer value or center, which will
208 center the window in the specified axis. Position is within
209 the monitor, so <position><x>center</x></position><monitor>2</monitor>
210 will center the window on the second monitor.
212 static void parse_per_app_settings(xmlNodePtr node
, gpointer d
)
214 xmlNodePtr app
= obt_xml_find_node(node
->children
, "application");
215 gchar
*name
= NULL
, *class = NULL
, *role
= NULL
, *title
= NULL
,
217 gboolean name_set
, class_set
, type_set
, role_set
, title_set
;
219 gboolean x_pos_given
;
224 class_set
= obt_xml_attr_string(app
, "class", &class);
225 name_set
= obt_xml_attr_string(app
, "name", &name
);
226 type_set
= obt_xml_attr_string(app
, "type", &type_str
);
227 role_set
= obt_xml_attr_string(app
, "role", &role
);
228 title_set
= obt_xml_attr_string(app
, "title", &title
);
230 /* validate the type tho */
232 if (!g_ascii_strcasecmp(type_str
, "normal"))
233 type
= OB_CLIENT_TYPE_NORMAL
;
234 else if (!g_ascii_strcasecmp(type_str
, "dialog"))
235 type
= OB_CLIENT_TYPE_DIALOG
;
236 else if (!g_ascii_strcasecmp(type_str
, "splash"))
237 type
= OB_CLIENT_TYPE_SPLASH
;
238 else if (!g_ascii_strcasecmp(type_str
, "utility"))
239 type
= OB_CLIENT_TYPE_UTILITY
;
240 else if (!g_ascii_strcasecmp(type_str
, "menu"))
241 type
= OB_CLIENT_TYPE_MENU
;
242 else if (!g_ascii_strcasecmp(type_str
, "toolbar"))
243 type
= OB_CLIENT_TYPE_TOOLBAR
;
244 else if (!g_ascii_strcasecmp(type_str
, "dock"))
245 type
= OB_CLIENT_TYPE_DOCK
;
246 else if (!g_ascii_strcasecmp(type_str
, "desktop"))
247 type
= OB_CLIENT_TYPE_DESKTOP
;
249 type_set
= FALSE
; /* not valid! */
252 if (class_set
|| name_set
|| role_set
|| title_set
|| type_set
) {
254 ObAppSettings
*settings
= config_create_app_settings();
257 settings
->name
= g_pattern_spec_new(name
);
260 settings
->class = g_pattern_spec_new(class);
263 settings
->role
= g_pattern_spec_new(role
);
266 settings
->title
= g_pattern_spec_new(title
);
269 settings
->type
= type
;
271 if ((n
= obt_xml_find_node(app
->children
, "decor")))
272 if (!obt_xml_node_contains(n
, "default"))
273 settings
->decor
= obt_xml_node_bool(n
);
275 if ((n
= obt_xml_find_node(app
->children
, "shade")))
276 if (!obt_xml_node_contains(n
, "default"))
277 settings
->shade
= obt_xml_node_bool(n
);
279 if ((n
= obt_xml_find_node(app
->children
, "position"))) {
280 if ((c
= obt_xml_find_node(n
->children
, "x")))
281 if (!obt_xml_node_contains(c
, "default")) {
282 config_parse_gravity_coord(c
, &settings
->position
.x
);
286 if (x_pos_given
&& (c
= obt_xml_find_node(n
->children
, "y")))
287 if (!obt_xml_node_contains(c
, "default")) {
288 config_parse_gravity_coord(c
, &settings
->position
.y
);
289 settings
->pos_given
= TRUE
;
292 if (settings
->pos_given
&&
293 (c
= obt_xml_find_node(n
->children
, "monitor")))
294 if (!obt_xml_node_contains(c
, "default")) {
295 gchar
*s
= obt_xml_node_string(c
);
296 if (!g_ascii_strcasecmp(s
, "mouse"))
297 settings
->monitor
= 0;
299 settings
->monitor
= obt_xml_node_int(c
);
303 obt_xml_attr_bool(n
, "force", &settings
->pos_force
);
306 if ((n
= obt_xml_find_node(app
->children
, "focus")))
307 if (!obt_xml_node_contains(n
, "default"))
308 settings
->focus
= obt_xml_node_bool(n
);
310 if ((n
= obt_xml_find_node(app
->children
, "desktop"))) {
311 if (!obt_xml_node_contains(n
, "default")) {
312 gchar
*s
= obt_xml_node_string(n
);
313 if (!g_ascii_strcasecmp(s
, "all"))
314 settings
->desktop
= DESKTOP_ALL
;
316 gint i
= obt_xml_node_int(n
);
318 settings
->desktop
= i
;
324 if ((n
= obt_xml_find_node(app
->children
, "layer")))
325 if (!obt_xml_node_contains(n
, "default")) {
326 gchar
*s
= obt_xml_node_string(n
);
327 if (!g_ascii_strcasecmp(s
, "above"))
329 else if (!g_ascii_strcasecmp(s
, "below"))
330 settings
->layer
= -1;
336 if ((n
= obt_xml_find_node(app
->children
, "iconic")))
337 if (!obt_xml_node_contains(n
, "default"))
338 settings
->iconic
= obt_xml_node_bool(n
);
340 if ((n
= obt_xml_find_node(app
->children
, "skip_pager")))
341 if (!obt_xml_node_contains(n
, "default"))
342 settings
->skip_pager
= obt_xml_node_bool(n
);
344 if ((n
= obt_xml_find_node(app
->children
, "skip_taskbar")))
345 if (!obt_xml_node_contains(n
, "default"))
346 settings
->skip_taskbar
= obt_xml_node_bool(n
);
348 if ((n
= obt_xml_find_node(app
->children
, "fullscreen")))
349 if (!obt_xml_node_contains(n
, "default"))
350 settings
->fullscreen
= obt_xml_node_bool(n
);
352 if ((n
= obt_xml_find_node(app
->children
, "maximized")))
353 if (!obt_xml_node_contains(n
, "default")) {
354 gchar
*s
= obt_xml_node_string(n
);
355 if (!g_ascii_strcasecmp(s
, "horizontal")) {
356 settings
->max_horz
= TRUE
;
357 settings
->max_vert
= FALSE
;
358 } else if (!g_ascii_strcasecmp(s
, "vertical")) {
359 settings
->max_horz
= FALSE
;
360 settings
->max_vert
= TRUE
;
362 settings
->max_horz
= settings
->max_vert
=
363 obt_xml_node_bool(n
);
367 config_per_app_settings
= g_slist_append(config_per_app_settings
,
368 (gpointer
) settings
);
373 name
= class = role
= title
= NULL
;
376 app
= obt_xml_find_node(app
->next
, "application");
383 <action name="ChangeDesktop">
390 static void parse_key(xmlNodePtr node
, GList
*keylist
)
394 gboolean is_chroot
= FALSE
;
396 if (!obt_xml_attr_string(node
, "key", &key
))
399 obt_xml_attr_bool(node
, "chroot", &is_chroot
);
401 keylist
= g_list_append(keylist
, key
);
403 if ((n
= obt_xml_find_node(node
->children
, "keybind"))) {
405 parse_key(n
, keylist
);
406 n
= obt_xml_find_node(n
->next
, "keybind");
409 else if ((n
= obt_xml_find_node(node
->children
, "action"))) {
411 ObActionsAct
*action
;
413 action
= actions_parse(n
);
415 keyboard_bind(keylist
, action
);
416 n
= obt_xml_find_node(n
->next
, "action");
421 keyboard_chroot(keylist
);
424 keylist
= g_list_delete_link(keylist
, g_list_last(keylist
));
427 static void parse_keyboard(xmlNodePtr node
, gpointer d
)
432 keyboard_unbind_all();
434 if ((n
= obt_xml_find_node(node
->children
, "chainQuitKey"))) {
435 key
= obt_xml_node_string(n
);
436 translate_key(key
, &config_keyboard_reset_state
,
437 &config_keyboard_reset_keycode
);
441 if ((n
= obt_xml_find_node(node
->children
, "keybind")))
444 n
= obt_xml_find_node(n
->next
, "keybind");
450 <context name="Titlebar">
451 <mousebind button="Left" action="Press">
452 <action name="Raise"></action>
458 static void parse_mouse(xmlNodePtr node
, gpointer d
)
460 xmlNodePtr n
, nbut
, nact
;
467 node
= node
->children
;
469 if ((n
= obt_xml_find_node(node
, "dragThreshold")))
470 config_mouse_threshold
= obt_xml_node_int(n
);
471 if ((n
= obt_xml_find_node(node
, "doubleClickTime")))
472 config_mouse_dclicktime
= obt_xml_node_int(n
);
473 if ((n
= obt_xml_find_node(node
, "screenEdgeWarpTime"))) {
474 config_mouse_screenedgetime
= obt_xml_node_int(n
);
475 /* minimum value of 25 for this property, when it is 1 and you hit the
476 edge it basically never stops */
477 if (config_mouse_screenedgetime
&& config_mouse_screenedgetime
< 25)
478 config_mouse_screenedgetime
= 25;
480 if ((n
= obt_xml_find_node(node
, "screenEdgeWarpMouse")))
481 config_mouse_screenedgewarp
= obt_xml_node_bool(n
);
483 n
= obt_xml_find_node(node
, "context");
488 if (!obt_xml_attr_string(n
, "name", &cxstr
))
491 modcxstr
= g_strdup(cxstr
); /* make a copy to mutilate */
492 while (frame_next_context_from_string(modcxstr
, &cx
)) {
494 gchar
*s
= strchr(modcxstr
, ' ');
497 g_message(_("Invalid context \"%s\" in mouse binding"),
504 nbut
= obt_xml_find_node(n
->children
, "mousebind");
506 if (!obt_xml_attr_string(nbut
, "button", &buttonstr
))
508 if (obt_xml_attr_contains(nbut
, "action", "press"))
509 mact
= OB_MOUSE_ACTION_PRESS
;
510 else if (obt_xml_attr_contains(nbut
, "action", "release"))
511 mact
= OB_MOUSE_ACTION_RELEASE
;
512 else if (obt_xml_attr_contains(nbut
, "action", "click"))
513 mact
= OB_MOUSE_ACTION_CLICK
;
514 else if (obt_xml_attr_contains(nbut
, "action","doubleclick"))
515 mact
= OB_MOUSE_ACTION_DOUBLE_CLICK
;
516 else if (obt_xml_attr_contains(nbut
, "action", "drag"))
517 mact
= OB_MOUSE_ACTION_MOTION
;
521 nact
= obt_xml_find_node(nbut
->children
, "action");
523 ObActionsAct
*action
;
525 if ((action
= actions_parse(nact
)))
526 mouse_bind(buttonstr
, cx
, mact
, action
);
527 nact
= obt_xml_find_node(nact
->next
, "action");
531 nbut
= obt_xml_find_node(nbut
->next
, "mousebind");
537 n
= obt_xml_find_node(n
->next
, "context");
541 static void parse_focus(xmlNodePtr node
, gpointer d
)
545 node
= node
->children
;
547 if ((n
= obt_xml_find_node(node
, "focusNew")))
548 config_focus_new
= obt_xml_node_bool(n
);
549 if ((n
= obt_xml_find_node(node
, "followMouse")))
550 config_focus_follow
= obt_xml_node_bool(n
);
551 if ((n
= obt_xml_find_node(node
, "focusDelay")))
552 config_focus_delay
= obt_xml_node_int(n
);
553 if ((n
= obt_xml_find_node(node
, "raiseOnFocus")))
554 config_focus_raise
= obt_xml_node_bool(n
);
555 if ((n
= obt_xml_find_node(node
, "focusLast")))
556 config_focus_last
= obt_xml_node_bool(n
);
557 if ((n
= obt_xml_find_node(node
, "underMouse")))
558 config_focus_under_mouse
= obt_xml_node_bool(n
);
559 if ((n
= obt_xml_find_node(node
, "unfocusOnLeave")))
560 config_unfocus_leave
= obt_xml_node_bool(n
);
563 static void parse_placement(xmlNodePtr node
, gpointer d
)
567 node
= node
->children
;
569 if ((n
= obt_xml_find_node(node
, "policy")))
570 if (obt_xml_node_contains(n
, "UnderMouse"))
571 config_place_policy
= OB_PLACE_POLICY_MOUSE
;
572 if ((n
= obt_xml_find_node(node
, "center")))
573 config_place_center
= obt_xml_node_bool(n
);
574 if ((n
= obt_xml_find_node(node
, "monitor"))) {
575 if (obt_xml_node_contains(n
, "active"))
576 config_place_monitor
= OB_PLACE_MONITOR_ACTIVE
;
577 else if (obt_xml_node_contains(n
, "mouse"))
578 config_place_monitor
= OB_PLACE_MONITOR_MOUSE
;
580 if ((n
= obt_xml_find_node(node
, "primaryMonitor"))) {
581 config_primary_monitor_index
= obt_xml_node_int(n
);
582 if (!config_primary_monitor_index
) {
583 if (obt_xml_node_contains(n
, "mouse"))
584 config_primary_monitor
= OB_PLACE_MONITOR_MOUSE
;
589 static void parse_margins(xmlNodePtr node
, gpointer d
)
593 node
= node
->children
;
595 if ((n
= obt_xml_find_node(node
, "top")))
596 config_margins
.top
= MAX(0, obt_xml_node_int(n
));
597 if ((n
= obt_xml_find_node(node
, "left")))
598 config_margins
.left
= MAX(0, obt_xml_node_int(n
));
599 if ((n
= obt_xml_find_node(node
, "right")))
600 config_margins
.right
= MAX(0, obt_xml_node_int(n
));
601 if ((n
= obt_xml_find_node(node
, "bottom")))
602 config_margins
.bottom
= MAX(0, obt_xml_node_int(n
));
605 static void parse_theme(xmlNodePtr node
, gpointer d
)
609 node
= node
->children
;
611 if ((n
= obt_xml_find_node(node
, "name"))) {
614 g_free(config_theme
);
615 c
= obt_xml_node_string(n
);
616 config_theme
= obt_paths_expand_tilde(c
);
619 if ((n
= obt_xml_find_node(node
, "titleLayout"))) {
622 g_free(config_title_layout
);
623 config_title_layout
= obt_xml_node_string(n
);
625 /* replace duplicates with spaces */
626 for (c
= config_title_layout
; *c
!= '\0'; ++c
)
627 for (d
= c
+1; *d
!= '\0'; ++d
)
628 if (*c
== *d
) *d
= ' ';
630 if ((n
= obt_xml_find_node(node
, "keepBorder")))
631 config_theme_keepborder
= obt_xml_node_bool(n
);
632 if ((n
= obt_xml_find_node(node
, "animateIconify")))
633 config_animate_iconify
= obt_xml_node_bool(n
);
634 if ((n
= obt_xml_find_node(node
, "windowListIconSize"))) {
635 config_theme_window_list_icon_size
= obt_xml_node_int(n
);
636 if (config_theme_window_list_icon_size
< 16)
637 config_theme_window_list_icon_size
= 16;
638 else if (config_theme_window_list_icon_size
> 96)
639 config_theme_window_list_icon_size
= 96;
642 n
= obt_xml_find_node(node
, "font");
646 gchar
*name
= g_strdup(RrDefaultFontFamily
);
647 gint size
= RrDefaultFontSize
;
648 RrFontWeight weight
= RrDefaultFontWeight
;
649 RrFontSlant slant
= RrDefaultFontSlant
;
651 if (obt_xml_attr_contains(n
, "place", "ActiveWindow"))
652 font
= &config_font_activewindow
;
653 else if (obt_xml_attr_contains(n
, "place", "InactiveWindow"))
654 font
= &config_font_inactivewindow
;
655 else if (obt_xml_attr_contains(n
, "place", "MenuHeader"))
656 font
= &config_font_menutitle
;
657 else if (obt_xml_attr_contains(n
, "place", "MenuItem"))
658 font
= &config_font_menuitem
;
659 else if (obt_xml_attr_contains(n
, "place", "ActiveOnScreenDisplay"))
660 font
= &config_font_activeosd
;
661 else if (obt_xml_attr_contains(n
, "place", "OnScreenDisplay"))
662 font
= &config_font_activeosd
;
663 else if (obt_xml_attr_contains(n
, "place","InactiveOnScreenDisplay"))
664 font
= &config_font_inactiveosd
;
668 if ((fnode
= obt_xml_find_node(n
->children
, "name"))) {
670 name
= obt_xml_node_string(fnode
);
672 if ((fnode
= obt_xml_find_node(n
->children
, "size"))) {
673 int s
= obt_xml_node_int(fnode
);
676 if ((fnode
= obt_xml_find_node(n
->children
, "weight"))) {
677 gchar
*w
= obt_xml_node_string(fnode
);
678 if (!g_ascii_strcasecmp(w
, "Bold"))
679 weight
= RR_FONTWEIGHT_BOLD
;
682 if ((fnode
= obt_xml_find_node(n
->children
, "slant"))) {
683 gchar
*s
= obt_xml_node_string(fnode
);
684 if (!g_ascii_strcasecmp(s
, "Italic"))
685 slant
= RR_FONTSLANT_ITALIC
;
686 if (!g_ascii_strcasecmp(s
, "Oblique"))
687 slant
= RR_FONTSLANT_OBLIQUE
;
691 *font
= RrFontOpen(ob_rr_inst
, name
, size
, weight
, slant
);
694 n
= obt_xml_find_node(n
->next
, "font");
698 static void parse_desktops(xmlNodePtr node
, gpointer d
)
702 node
= node
->children
;
704 if ((n
= obt_xml_find_node(node
, "number"))) {
705 gint d
= obt_xml_node_int(n
);
707 config_desktops_num
= (unsigned) d
;
709 if ((n
= obt_xml_find_node(node
, "firstdesk"))) {
710 gint d
= obt_xml_node_int(n
);
712 config_screen_firstdesk
= (unsigned) d
;
714 if ((n
= obt_xml_find_node(node
, "names"))) {
718 for (it
= config_desktops_names
; it
; it
= it
->next
)
720 g_slist_free(config_desktops_names
);
721 config_desktops_names
= NULL
;
723 nname
= obt_xml_find_node(n
->children
, "name");
725 config_desktops_names
=
726 g_slist_append(config_desktops_names
,
727 obt_xml_node_string(nname
));
728 nname
= obt_xml_find_node(nname
->next
, "name");
731 if ((n
= obt_xml_find_node(node
, "popupTime")))
732 config_desktop_popup_time
= obt_xml_node_int(n
);
735 static void parse_resize(xmlNodePtr node
, gpointer d
)
739 node
= node
->children
;
741 if ((n
= obt_xml_find_node(node
, "drawContents")))
742 config_resize_redraw
= obt_xml_node_bool(n
);
743 if ((n
= obt_xml_find_node(node
, "popupShow"))) {
744 config_resize_popup_show
= obt_xml_node_int(n
);
745 if (obt_xml_node_contains(n
, "Always"))
746 config_resize_popup_show
= 2;
747 else if (obt_xml_node_contains(n
, "Never"))
748 config_resize_popup_show
= 0;
749 else if (obt_xml_node_contains(n
, "Nonpixel"))
750 config_resize_popup_show
= 1;
752 if ((n
= obt_xml_find_node(node
, "popupPosition"))) {
753 if (obt_xml_node_contains(n
, "Top"))
754 config_resize_popup_pos
= OB_RESIZE_POS_TOP
;
755 else if (obt_xml_node_contains(n
, "Center"))
756 config_resize_popup_pos
= OB_RESIZE_POS_CENTER
;
757 else if (obt_xml_node_contains(n
, "Fixed")) {
758 config_resize_popup_pos
= OB_RESIZE_POS_FIXED
;
760 if ((n
= obt_xml_find_node(node
, "popupFixedPosition"))) {
763 if ((n2
= obt_xml_find_node(n
->children
, "x")))
764 config_parse_gravity_coord(n2
,
765 &config_resize_popup_fixed
.x
);
766 if ((n2
= obt_xml_find_node(n
->children
, "y")))
767 config_parse_gravity_coord(n2
,
768 &config_resize_popup_fixed
.y
);
770 config_resize_popup_fixed
.x
.pos
=
771 MAX(config_resize_popup_fixed
.x
.pos
, 0);
772 config_resize_popup_fixed
.y
.pos
=
773 MAX(config_resize_popup_fixed
.y
.pos
, 0);
779 static void parse_dock(xmlNodePtr node
, gpointer d
)
783 node
= node
->children
;
785 if ((n
= obt_xml_find_node(node
, "position"))) {
786 if (obt_xml_node_contains(n
, "TopLeft"))
787 config_dock_floating
= FALSE
,
788 config_dock_pos
= OB_DIRECTION_NORTHWEST
;
789 else if (obt_xml_node_contains(n
, "Top"))
790 config_dock_floating
= FALSE
,
791 config_dock_pos
= OB_DIRECTION_NORTH
;
792 else if (obt_xml_node_contains(n
, "TopRight"))
793 config_dock_floating
= FALSE
,
794 config_dock_pos
= OB_DIRECTION_NORTHEAST
;
795 else if (obt_xml_node_contains(n
, "Right"))
796 config_dock_floating
= FALSE
,
797 config_dock_pos
= OB_DIRECTION_EAST
;
798 else if (obt_xml_node_contains(n
, "BottomRight"))
799 config_dock_floating
= FALSE
,
800 config_dock_pos
= OB_DIRECTION_SOUTHEAST
;
801 else if (obt_xml_node_contains(n
, "Bottom"))
802 config_dock_floating
= FALSE
,
803 config_dock_pos
= OB_DIRECTION_SOUTH
;
804 else if (obt_xml_node_contains(n
, "BottomLeft"))
805 config_dock_floating
= FALSE
,
806 config_dock_pos
= OB_DIRECTION_SOUTHWEST
;
807 else if (obt_xml_node_contains(n
, "Left"))
808 config_dock_floating
= FALSE
,
809 config_dock_pos
= OB_DIRECTION_WEST
;
810 else if (obt_xml_node_contains(n
, "Floating"))
811 config_dock_floating
= TRUE
;
813 if (config_dock_floating
) {
814 if ((n
= obt_xml_find_node(node
, "floatingX")))
815 config_dock_x
= obt_xml_node_int(n
);
816 if ((n
= obt_xml_find_node(node
, "floatingY")))
817 config_dock_y
= obt_xml_node_int(n
);
819 if ((n
= obt_xml_find_node(node
, "noStrut")))
820 config_dock_nostrut
= obt_xml_node_bool(n
);
822 if ((n
= obt_xml_find_node(node
, "stacking"))) {
823 if (obt_xml_node_contains(n
, "normal"))
824 config_dock_layer
= OB_STACKING_LAYER_NORMAL
;
825 else if (obt_xml_node_contains(n
, "below"))
826 config_dock_layer
= OB_STACKING_LAYER_BELOW
;
827 else if (obt_xml_node_contains(n
, "above"))
828 config_dock_layer
= OB_STACKING_LAYER_ABOVE
;
830 if ((n
= obt_xml_find_node(node
, "direction"))) {
831 if (obt_xml_node_contains(n
, "horizontal"))
832 config_dock_orient
= OB_ORIENTATION_HORZ
;
833 else if (obt_xml_node_contains(n
, "vertical"))
834 config_dock_orient
= OB_ORIENTATION_VERT
;
836 if ((n
= obt_xml_find_node(node
, "autoHide")))
837 config_dock_hide
= obt_xml_node_bool(n
);
838 if ((n
= obt_xml_find_node(node
, "hideDelay")))
839 config_dock_hide_delay
= obt_xml_node_int(n
);
840 if ((n
= obt_xml_find_node(node
, "showDelay")))
841 config_dock_show_delay
= obt_xml_node_int(n
);
842 if ((n
= obt_xml_find_node(node
, "moveButton"))) {
843 gchar
*str
= obt_xml_node_string(n
);
845 if (translate_button(str
, &s
, &b
)) {
846 config_dock_app_move_button
= b
;
847 config_dock_app_move_modifiers
= s
;
849 g_message(_("Invalid button \"%s\" specified in config file"), str
);
855 static void parse_menu(xmlNodePtr node
, gpointer d
)
858 node
= node
->children
;
860 if ((n
= obt_xml_find_node(node
, "hideDelay")))
861 config_menu_hide_delay
= obt_xml_node_int(n
);
862 if ((n
= obt_xml_find_node(node
, "middle")))
863 config_menu_middle
= obt_xml_node_bool(n
);
864 if ((n
= obt_xml_find_node(node
, "submenuShowDelay")))
865 config_submenu_show_delay
= obt_xml_node_int(n
);
866 if ((n
= obt_xml_find_node(node
, "submenuHideDelay")))
867 config_submenu_hide_delay
= obt_xml_node_int(n
);
868 if ((n
= obt_xml_find_node(node
, "manageDesktops")))
869 config_menu_manage_desktops
= obt_xml_node_bool(n
);
870 if ((n
= obt_xml_find_node(node
, "showIcons"))) {
871 config_menu_show_icons
= obt_xml_node_bool(n
);
873 if (config_menu_show_icons
)
874 g_message(_("Openbox was compiled without Imlib2 image loading support. Icons in menus will not be loaded."));
878 while ((node
= obt_xml_find_node(node
, "file"))) {
879 gchar
*c
= obt_xml_node_string(node
);
880 config_menu_files
= g_slist_append(config_menu_files
,
881 obt_paths_expand_tilde(c
));
887 static void parse_resistance(xmlNodePtr node
, gpointer d
)
891 node
= node
->children
;
892 if ((n
= obt_xml_find_node(node
, "strength")))
893 config_resist_win
= obt_xml_node_int(n
);
894 if ((n
= obt_xml_find_node(node
, "screen_edge_strength")))
895 config_resist_edge
= obt_xml_node_int(n
);
901 const gchar
*actname
;
904 static void bind_default_keyboard(void)
907 ObDefKeyBind binds
[] = {
908 { "A-Tab", "NextWindow" },
909 { "S-A-Tab", "PreviousWindow" },
913 for (it
= binds
; it
->key
; ++it
) {
914 GList
*l
= g_list_append(NULL
, g_strdup(it
->key
));
915 keyboard_bind(l
, actions_parse_string(it
->actname
));
922 const gchar
*context
;
923 const ObMouseAction mact
;
924 const gchar
*actname
;
927 static void bind_default_mouse(void)
930 ObDefMouseBind binds
[] = {
931 { "Left", "Client", OB_MOUSE_ACTION_PRESS
, "Focus" },
932 { "Middle", "Client", OB_MOUSE_ACTION_PRESS
, "Focus" },
933 { "Right", "Client", OB_MOUSE_ACTION_PRESS
, "Focus" },
934 { "Left", "Desktop", OB_MOUSE_ACTION_PRESS
, "Focus" },
935 { "Middle", "Desktop", OB_MOUSE_ACTION_PRESS
, "Focus" },
936 { "Right", "Desktop", OB_MOUSE_ACTION_PRESS
, "Focus" },
937 { "Left", "Titlebar", OB_MOUSE_ACTION_PRESS
, "Focus" },
938 { "Left", "Bottom", OB_MOUSE_ACTION_PRESS
, "Focus" },
939 { "Left", "BLCorner", OB_MOUSE_ACTION_PRESS
, "Focus" },
940 { "Left", "BRCorner", OB_MOUSE_ACTION_PRESS
, "Focus" },
941 { "Left", "TLCorner", OB_MOUSE_ACTION_PRESS
, "Focus" },
942 { "Left", "TRCorner", OB_MOUSE_ACTION_PRESS
, "Focus" },
943 { "Left", "Close", OB_MOUSE_ACTION_PRESS
, "Focus" },
944 { "Left", "Maximize", OB_MOUSE_ACTION_PRESS
, "Focus" },
945 { "Left", "Iconify", OB_MOUSE_ACTION_PRESS
, "Focus" },
946 { "Left", "Icon", OB_MOUSE_ACTION_PRESS
, "Focus" },
947 { "Left", "AllDesktops", OB_MOUSE_ACTION_PRESS
, "Focus" },
948 { "Left", "Shade", OB_MOUSE_ACTION_PRESS
, "Focus" },
949 { "Left", "Client", OB_MOUSE_ACTION_CLICK
, "Raise" },
950 { "Left", "Titlebar", OB_MOUSE_ACTION_CLICK
, "Raise" },
951 { "Middle", "Titlebar", OB_MOUSE_ACTION_CLICK
, "Lower" },
952 { "Left", "BLCorner", OB_MOUSE_ACTION_CLICK
, "Raise" },
953 { "Left", "BRCorner", OB_MOUSE_ACTION_CLICK
, "Raise" },
954 { "Left", "TLCorner", OB_MOUSE_ACTION_CLICK
, "Raise" },
955 { "Left", "TRCorner", OB_MOUSE_ACTION_CLICK
, "Raise" },
956 { "Left", "Close", OB_MOUSE_ACTION_CLICK
, "Raise" },
957 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK
, "Raise" },
958 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK
, "Raise" },
959 { "Left", "Icon", OB_MOUSE_ACTION_CLICK
, "Raise" },
960 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK
, "Raise" },
961 { "Left", "Shade", OB_MOUSE_ACTION_CLICK
, "Raise" },
962 { "Left", "Close", OB_MOUSE_ACTION_CLICK
, "Close" },
963 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK
, "ToggleMaximize" },
964 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK
, "Iconify" },
965 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK
, "ToggleOmnipresent" },
966 { "Left", "Shade", OB_MOUSE_ACTION_CLICK
, "ToggleShade" },
967 { "Left", "TLCorner", OB_MOUSE_ACTION_MOTION
, "Resize" },
968 { "Left", "TRCorner", OB_MOUSE_ACTION_MOTION
, "Resize" },
969 { "Left", "BLCorner", OB_MOUSE_ACTION_MOTION
, "Resize" },
970 { "Left", "BRCorner", OB_MOUSE_ACTION_MOTION
, "Resize" },
971 { "Left", "Top", OB_MOUSE_ACTION_MOTION
, "Resize" },
972 { "Left", "Bottom", OB_MOUSE_ACTION_MOTION
, "Resize" },
973 { "Left", "Left", OB_MOUSE_ACTION_MOTION
, "Resize" },
974 { "Left", "Right", OB_MOUSE_ACTION_MOTION
, "Resize" },
975 { "Left", "Titlebar", OB_MOUSE_ACTION_MOTION
, "Move" },
976 { "A-Left", "Frame", OB_MOUSE_ACTION_MOTION
, "Move" },
977 { "A-Middle", "Frame", OB_MOUSE_ACTION_MOTION
, "Resize" },
978 { NULL
, NULL
, 0, NULL
}
981 for (it
= binds
; it
->button
; ++it
)
982 mouse_bind(it
->button
, frame_context_from_string(it
->context
),
983 it
->mact
, actions_parse_string(it
->actname
));
986 void config_startup(ObtXmlInst
*i
)
988 config_focus_new
= TRUE
;
989 config_focus_follow
= FALSE
;
990 config_focus_delay
= 0;
991 config_focus_raise
= FALSE
;
992 config_focus_last
= TRUE
;
993 config_focus_under_mouse
= FALSE
;
994 config_unfocus_leave
= FALSE
;
996 obt_xml_register(i
, "focus", parse_focus
, NULL
);
998 config_place_policy
= OB_PLACE_POLICY_SMART
;
999 config_place_center
= TRUE
;
1000 config_place_monitor
= OB_PLACE_MONITOR_ANY
;
1002 config_primary_monitor_index
= 1;
1003 config_primary_monitor
= OB_PLACE_MONITOR_ACTIVE
;
1005 obt_xml_register(i
, "placement", parse_placement
, NULL
);
1007 STRUT_PARTIAL_SET(config_margins
, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1009 obt_xml_register(i
, "margins", parse_margins
, NULL
);
1011 config_theme
= NULL
;
1013 config_animate_iconify
= TRUE
;
1014 config_title_layout
= g_strdup("NLIMC");
1015 config_theme_keepborder
= TRUE
;
1016 config_theme_window_list_icon_size
= 36;
1018 config_font_activewindow
= NULL
;
1019 config_font_inactivewindow
= NULL
;
1020 config_font_menuitem
= NULL
;
1021 config_font_menutitle
= NULL
;
1022 config_font_activeosd
= NULL
;
1023 config_font_inactiveosd
= NULL
;
1025 obt_xml_register(i
, "theme", parse_theme
, NULL
);
1027 config_desktops_num
= 4;
1028 config_screen_firstdesk
= 1;
1029 config_desktops_names
= NULL
;
1030 config_desktop_popup_time
= 875;
1032 obt_xml_register(i
, "desktops", parse_desktops
, NULL
);
1034 config_resize_redraw
= TRUE
;
1035 config_resize_popup_show
= 1; /* nonpixel increments */
1036 config_resize_popup_pos
= OB_RESIZE_POS_CENTER
;
1037 GRAVITY_COORD_SET(config_resize_popup_fixed
.x
, 0, FALSE
, FALSE
);
1038 GRAVITY_COORD_SET(config_resize_popup_fixed
.y
, 0, FALSE
, FALSE
);
1040 obt_xml_register(i
, "resize", parse_resize
, NULL
);
1042 config_dock_layer
= OB_STACKING_LAYER_ABOVE
;
1043 config_dock_pos
= OB_DIRECTION_NORTHEAST
;
1044 config_dock_floating
= FALSE
;
1045 config_dock_nostrut
= FALSE
;
1048 config_dock_orient
= OB_ORIENTATION_VERT
;
1049 config_dock_hide
= FALSE
;
1050 config_dock_hide_delay
= 300;
1051 config_dock_show_delay
= 300;
1052 config_dock_app_move_button
= 2; /* middle */
1053 config_dock_app_move_modifiers
= 0;
1055 obt_xml_register(i
, "dock", parse_dock
, NULL
);
1057 translate_key("C-g", &config_keyboard_reset_state
,
1058 &config_keyboard_reset_keycode
);
1060 bind_default_keyboard();
1062 obt_xml_register(i
, "keyboard", parse_keyboard
, NULL
);
1064 config_mouse_threshold
= 8;
1065 config_mouse_dclicktime
= 200;
1066 config_mouse_screenedgetime
= 400;
1067 config_mouse_screenedgewarp
= FALSE
;
1069 bind_default_mouse();
1071 obt_xml_register(i
, "mouse", parse_mouse
, NULL
);
1073 config_resist_win
= 10;
1074 config_resist_edge
= 20;
1076 obt_xml_register(i
, "resistance", parse_resistance
, NULL
);
1078 config_menu_hide_delay
= 250;
1079 config_menu_middle
= FALSE
;
1080 config_submenu_show_delay
= 100;
1081 config_submenu_hide_delay
= 400;
1082 config_menu_manage_desktops
= TRUE
;
1083 config_menu_files
= NULL
;
1084 config_menu_show_icons
= TRUE
;
1086 obt_xml_register(i
, "menu", parse_menu
, NULL
);
1088 config_per_app_settings
= NULL
;
1090 obt_xml_register(i
, "applications", parse_per_app_settings
, NULL
);
1093 void config_shutdown(void)
1097 g_free(config_theme
);
1099 g_free(config_title_layout
);
1101 RrFontClose(config_font_activewindow
);
1102 RrFontClose(config_font_inactivewindow
);
1103 RrFontClose(config_font_menuitem
);
1104 RrFontClose(config_font_menutitle
);
1105 RrFontClose(config_font_activeosd
);
1106 RrFontClose(config_font_inactiveosd
);
1108 for (it
= config_desktops_names
; it
; it
= g_slist_next(it
))
1110 g_slist_free(config_desktops_names
);
1112 for (it
= config_menu_files
; it
; it
= g_slist_next(it
))
1114 g_slist_free(config_menu_files
);
1116 for (it
= config_per_app_settings
; it
; it
= g_slist_next(it
)) {
1117 ObAppSettings
*itd
= (ObAppSettings
*)it
->data
;
1118 if (itd
->name
) g_pattern_spec_free(itd
->name
);
1119 if (itd
->role
) g_pattern_spec_free(itd
->role
);
1120 if (itd
->title
) g_pattern_spec_free(itd
->title
);
1121 if (itd
->class) g_pattern_spec_free(itd
->class);
1122 g_slice_free(ObAppSettings
, it
->data
);
1124 g_slist_free(config_per_app_settings
);