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_type
= OB_PLACE_MONITOR_ANY
;
115 settings
->monitor
= -1;
116 settings
->focus
= -1;
117 settings
->desktop
= 0;
118 settings
->layer
= -2;
119 settings
->iconic
= -1;
120 settings
->skip_pager
= -1;
121 settings
->skip_taskbar
= -1;
122 settings
->fullscreen
= -1;
123 settings
->max_horz
= -1;
124 settings
->max_vert
= -1;
128 #define copy_if(setting, default) \
129 if (src->setting != default) dst->setting = src->setting
130 void config_app_settings_copy_non_defaults(const ObAppSettings
*src
,
133 g_assert(src
!= NULL
);
134 g_assert(dst
!= NULL
);
136 copy_if(type
, (ObClientType
)-1);
139 copy_if(monitor_type
, OB_PLACE_MONITOR_ANY
);
140 copy_if(monitor
, -1);
145 copy_if(skip_pager
, -1);
146 copy_if(skip_taskbar
, -1);
147 copy_if(fullscreen
, -1);
148 copy_if(max_horz
, -1);
149 copy_if(max_vert
, -1);
151 if (src
->pos_given
) {
152 dst
->pos_given
= TRUE
;
153 dst
->pos_force
= src
->pos_force
;
154 dst
->position
= src
->position
;
155 /* monitor is copied above */
159 void config_parse_relative_number(gchar
*s
, gint
*num
, gint
*denom
)
161 *num
= strtol(s
, &s
, 10);
165 } else if (*s
== '/') {
170 void config_parse_gravity_coord(xmlNodePtr node
, GravityCoord
*c
)
172 gchar
*s
= obt_xml_node_string(node
);
173 if (!g_ascii_strcasecmp(s
, "center"))
179 if (s
[0] == '-' || s
[0] == '+')
181 config_parse_relative_number(ps
, &c
->pos
, &c
->denom
);
188 <application name="aterm">
191 <application name="Rhythmbox">
198 .. there is a lot more settings available
203 /* Manages settings for individual applications.
204 Some notes: monitor is the screen number in a multi monitor
205 (Xinerama) setup (starting from 0), or mouse: the monitor the pointer
206 is on, active: the active monitor, primary: the primary monitor.
207 Layer can be three values, above (Always on top), below
208 (Always on bottom) and everything else (normal behaviour).
209 Positions can be an integer value or center, which will
210 center the window in the specified axis. Position is within
211 the monitor, so <position><x>center</x></position><monitor>2</monitor>
212 will center the window on the second monitor.
214 static void parse_per_app_settings(xmlNodePtr node
, gpointer d
)
216 xmlNodePtr app
= obt_xml_find_node(node
->children
, "application");
217 gchar
*name
= NULL
, *class = NULL
, *role
= NULL
, *title
= NULL
,
219 gboolean name_set
, class_set
, type_set
, role_set
, title_set
;
221 gboolean x_pos_given
;
226 class_set
= obt_xml_attr_string(app
, "class", &class);
227 name_set
= obt_xml_attr_string(app
, "name", &name
);
228 type_set
= obt_xml_attr_string(app
, "type", &type_str
);
229 role_set
= obt_xml_attr_string(app
, "role", &role
);
230 title_set
= obt_xml_attr_string(app
, "title", &title
);
232 /* validate the type tho */
234 if (!g_ascii_strcasecmp(type_str
, "normal"))
235 type
= OB_CLIENT_TYPE_NORMAL
;
236 else if (!g_ascii_strcasecmp(type_str
, "dialog"))
237 type
= OB_CLIENT_TYPE_DIALOG
;
238 else if (!g_ascii_strcasecmp(type_str
, "splash"))
239 type
= OB_CLIENT_TYPE_SPLASH
;
240 else if (!g_ascii_strcasecmp(type_str
, "utility"))
241 type
= OB_CLIENT_TYPE_UTILITY
;
242 else if (!g_ascii_strcasecmp(type_str
, "menu"))
243 type
= OB_CLIENT_TYPE_MENU
;
244 else if (!g_ascii_strcasecmp(type_str
, "toolbar"))
245 type
= OB_CLIENT_TYPE_TOOLBAR
;
246 else if (!g_ascii_strcasecmp(type_str
, "dock"))
247 type
= OB_CLIENT_TYPE_DOCK
;
248 else if (!g_ascii_strcasecmp(type_str
, "desktop"))
249 type
= OB_CLIENT_TYPE_DESKTOP
;
251 type_set
= FALSE
; /* not valid! */
254 if (class_set
|| name_set
|| role_set
|| title_set
|| type_set
) {
256 ObAppSettings
*settings
= config_create_app_settings();
259 settings
->name
= g_pattern_spec_new(name
);
262 settings
->class = g_pattern_spec_new(class);
265 settings
->role
= g_pattern_spec_new(role
);
268 settings
->title
= g_pattern_spec_new(title
);
271 settings
->type
= type
;
273 if ((n
= obt_xml_find_node(app
->children
, "decor")))
274 if (!obt_xml_node_contains(n
, "default"))
275 settings
->decor
= obt_xml_node_bool(n
);
277 if ((n
= obt_xml_find_node(app
->children
, "shade")))
278 if (!obt_xml_node_contains(n
, "default"))
279 settings
->shade
= obt_xml_node_bool(n
);
281 if ((n
= obt_xml_find_node(app
->children
, "position"))) {
282 if ((c
= obt_xml_find_node(n
->children
, "x")))
283 if (!obt_xml_node_contains(c
, "default")) {
284 config_parse_gravity_coord(c
, &settings
->position
.x
);
288 if (x_pos_given
&& (c
= obt_xml_find_node(n
->children
, "y")))
289 if (!obt_xml_node_contains(c
, "default")) {
290 config_parse_gravity_coord(c
, &settings
->position
.y
);
291 settings
->pos_given
= TRUE
;
294 /* monitor can be set without setting x or y */
295 if ((c
= obt_xml_find_node(n
->children
, "monitor")))
296 if (!obt_xml_node_contains(c
, "default")) {
297 gchar
*s
= obt_xml_node_string(c
);
298 if (!g_ascii_strcasecmp(s
, "mouse"))
299 settings
->monitor_type
=
300 OB_PLACE_MONITOR_MOUSE
;
301 else if (!g_ascii_strcasecmp(s
, "active"))
302 settings
->monitor_type
=
303 OB_PLACE_MONITOR_ACTIVE
;
304 else if (!g_ascii_strcasecmp(s
, "primary"))
305 settings
->monitor_type
=
306 OB_PLACE_MONITOR_PRIMARY
;
308 settings
->monitor
= obt_xml_node_int(c
);
312 obt_xml_attr_bool(n
, "force", &settings
->pos_force
);
315 if ((n
= obt_xml_find_node(app
->children
, "focus")))
316 if (!obt_xml_node_contains(n
, "default"))
317 settings
->focus
= obt_xml_node_bool(n
);
319 if ((n
= obt_xml_find_node(app
->children
, "desktop"))) {
320 if (!obt_xml_node_contains(n
, "default")) {
321 gchar
*s
= obt_xml_node_string(n
);
322 if (!g_ascii_strcasecmp(s
, "all"))
323 settings
->desktop
= DESKTOP_ALL
;
325 gint i
= obt_xml_node_int(n
);
327 settings
->desktop
= i
;
333 if ((n
= obt_xml_find_node(app
->children
, "layer")))
334 if (!obt_xml_node_contains(n
, "default")) {
335 gchar
*s
= obt_xml_node_string(n
);
336 if (!g_ascii_strcasecmp(s
, "above"))
338 else if (!g_ascii_strcasecmp(s
, "below"))
339 settings
->layer
= -1;
345 if ((n
= obt_xml_find_node(app
->children
, "iconic")))
346 if (!obt_xml_node_contains(n
, "default"))
347 settings
->iconic
= obt_xml_node_bool(n
);
349 if ((n
= obt_xml_find_node(app
->children
, "skip_pager")))
350 if (!obt_xml_node_contains(n
, "default"))
351 settings
->skip_pager
= obt_xml_node_bool(n
);
353 if ((n
= obt_xml_find_node(app
->children
, "skip_taskbar")))
354 if (!obt_xml_node_contains(n
, "default"))
355 settings
->skip_taskbar
= obt_xml_node_bool(n
);
357 if ((n
= obt_xml_find_node(app
->children
, "fullscreen")))
358 if (!obt_xml_node_contains(n
, "default"))
359 settings
->fullscreen
= obt_xml_node_bool(n
);
361 if ((n
= obt_xml_find_node(app
->children
, "maximized")))
362 if (!obt_xml_node_contains(n
, "default")) {
363 gchar
*s
= obt_xml_node_string(n
);
364 if (!g_ascii_strcasecmp(s
, "horizontal")) {
365 settings
->max_horz
= TRUE
;
366 settings
->max_vert
= FALSE
;
367 } else if (!g_ascii_strcasecmp(s
, "vertical")) {
368 settings
->max_horz
= FALSE
;
369 settings
->max_vert
= TRUE
;
371 settings
->max_horz
= settings
->max_vert
=
372 obt_xml_node_bool(n
);
376 config_per_app_settings
= g_slist_append(config_per_app_settings
,
377 (gpointer
) settings
);
383 name
= class = role
= title
= type_str
= NULL
;
386 app
= obt_xml_find_node(app
->next
, "application");
393 <action name="ChangeDesktop">
400 static void parse_key(xmlNodePtr node
, GList
*keylist
)
402 gchar
*keystring
, **keys
, **key
;
404 gboolean is_chroot
= FALSE
;
406 if (!obt_xml_attr_string(node
, "key", &keystring
))
409 obt_xml_attr_bool(node
, "chroot", &is_chroot
);
411 keys
= g_strsplit(keystring
, " ", 0);
412 for (key
= keys
; *key
; ++key
) {
413 keylist
= g_list_append(keylist
, *key
);
415 if ((n
= obt_xml_find_node(node
->children
, "keybind"))) {
417 parse_key(n
, keylist
);
418 n
= obt_xml_find_node(n
->next
, "keybind");
421 else if ((n
= obt_xml_find_node(node
->children
, "action"))) {
423 ObActionsAct
*action
;
425 action
= actions_parse(n
);
427 keyboard_bind(keylist
, action
);
428 n
= obt_xml_find_node(n
->next
, "action");
434 keyboard_chroot(keylist
);
435 keylist
= g_list_delete_link(keylist
, g_list_last(keylist
));
442 static void parse_keyboard(xmlNodePtr node
, gpointer d
)
447 keyboard_unbind_all();
449 if ((n
= obt_xml_find_node(node
->children
, "chainQuitKey"))) {
450 key
= obt_xml_node_string(n
);
451 translate_key(key
, &config_keyboard_reset_state
,
452 &config_keyboard_reset_keycode
);
456 if ((n
= obt_xml_find_node(node
->children
, "keybind")))
459 n
= obt_xml_find_node(n
->next
, "keybind");
465 <context name="Titlebar">
466 <mousebind button="Left" action="Press">
467 <action name="Raise"></action>
473 static void parse_mouse(xmlNodePtr node
, gpointer d
)
475 xmlNodePtr n
, nbut
, nact
;
482 node
= node
->children
;
484 if ((n
= obt_xml_find_node(node
, "dragThreshold")))
485 config_mouse_threshold
= obt_xml_node_int(n
);
486 if ((n
= obt_xml_find_node(node
, "doubleClickTime")))
487 config_mouse_dclicktime
= obt_xml_node_int(n
);
488 if ((n
= obt_xml_find_node(node
, "screenEdgeWarpTime"))) {
489 config_mouse_screenedgetime
= obt_xml_node_int(n
);
490 /* minimum value of 25 for this property, when it is 1 and you hit the
491 edge it basically never stops */
492 if (config_mouse_screenedgetime
&& config_mouse_screenedgetime
< 25)
493 config_mouse_screenedgetime
= 25;
495 if ((n
= obt_xml_find_node(node
, "screenEdgeWarpMouse")))
496 config_mouse_screenedgewarp
= obt_xml_node_bool(n
);
498 n
= obt_xml_find_node(node
, "context");
503 if (!obt_xml_attr_string(n
, "name", &cxstr
))
506 modcxstr
= g_strdup(cxstr
); /* make a copy to mutilate */
507 while (frame_next_context_from_string(modcxstr
, &cx
)) {
509 gchar
*s
= strchr(modcxstr
, ' ');
512 g_message(_("Invalid context \"%s\" in mouse binding"),
519 nbut
= obt_xml_find_node(n
->children
, "mousebind");
521 if (!obt_xml_attr_string(nbut
, "button", &buttonstr
))
523 if (obt_xml_attr_contains(nbut
, "action", "press"))
524 mact
= OB_MOUSE_ACTION_PRESS
;
525 else if (obt_xml_attr_contains(nbut
, "action", "release"))
526 mact
= OB_MOUSE_ACTION_RELEASE
;
527 else if (obt_xml_attr_contains(nbut
, "action", "click"))
528 mact
= OB_MOUSE_ACTION_CLICK
;
529 else if (obt_xml_attr_contains(nbut
, "action","doubleclick"))
530 mact
= OB_MOUSE_ACTION_DOUBLE_CLICK
;
531 else if (obt_xml_attr_contains(nbut
, "action", "drag"))
532 mact
= OB_MOUSE_ACTION_MOTION
;
536 nact
= obt_xml_find_node(nbut
->children
, "action");
538 ObActionsAct
*action
;
540 if ((action
= actions_parse(nact
)))
541 mouse_bind(buttonstr
, cx
, mact
, action
);
542 nact
= obt_xml_find_node(nact
->next
, "action");
546 nbut
= obt_xml_find_node(nbut
->next
, "mousebind");
552 n
= obt_xml_find_node(n
->next
, "context");
556 static void parse_focus(xmlNodePtr node
, gpointer d
)
560 node
= node
->children
;
562 if ((n
= obt_xml_find_node(node
, "focusNew")))
563 config_focus_new
= obt_xml_node_bool(n
);
564 if ((n
= obt_xml_find_node(node
, "followMouse")))
565 config_focus_follow
= obt_xml_node_bool(n
);
566 if ((n
= obt_xml_find_node(node
, "focusDelay")))
567 config_focus_delay
= obt_xml_node_int(n
);
568 if ((n
= obt_xml_find_node(node
, "raiseOnFocus")))
569 config_focus_raise
= obt_xml_node_bool(n
);
570 if ((n
= obt_xml_find_node(node
, "focusLast")))
571 config_focus_last
= obt_xml_node_bool(n
);
572 if ((n
= obt_xml_find_node(node
, "underMouse")))
573 config_focus_under_mouse
= obt_xml_node_bool(n
);
574 if ((n
= obt_xml_find_node(node
, "unfocusOnLeave")))
575 config_unfocus_leave
= obt_xml_node_bool(n
);
578 static void parse_placement(xmlNodePtr node
, gpointer d
)
582 node
= node
->children
;
584 if ((n
= obt_xml_find_node(node
, "policy")))
585 if (obt_xml_node_contains(n
, "UnderMouse"))
586 config_place_policy
= OB_PLACE_POLICY_MOUSE
;
587 if ((n
= obt_xml_find_node(node
, "center")))
588 config_place_center
= obt_xml_node_bool(n
);
589 if ((n
= obt_xml_find_node(node
, "monitor"))) {
590 if (obt_xml_node_contains(n
, "active"))
591 config_place_monitor
= OB_PLACE_MONITOR_ACTIVE
;
592 else if (obt_xml_node_contains(n
, "mouse"))
593 config_place_monitor
= OB_PLACE_MONITOR_MOUSE
;
594 else if (obt_xml_node_contains(n
, "any"))
595 config_place_monitor
= OB_PLACE_MONITOR_ANY
;
597 if ((n
= obt_xml_find_node(node
, "primaryMonitor"))) {
598 config_primary_monitor_index
= obt_xml_node_int(n
);
599 if (!config_primary_monitor_index
) {
600 if (obt_xml_node_contains(n
, "mouse"))
601 config_primary_monitor
= OB_PLACE_MONITOR_MOUSE
;
606 static void parse_margins(xmlNodePtr node
, gpointer d
)
610 node
= node
->children
;
612 if ((n
= obt_xml_find_node(node
, "top")))
613 config_margins
.top
= MAX(0, obt_xml_node_int(n
));
614 if ((n
= obt_xml_find_node(node
, "left")))
615 config_margins
.left
= MAX(0, obt_xml_node_int(n
));
616 if ((n
= obt_xml_find_node(node
, "right")))
617 config_margins
.right
= MAX(0, obt_xml_node_int(n
));
618 if ((n
= obt_xml_find_node(node
, "bottom")))
619 config_margins
.bottom
= MAX(0, obt_xml_node_int(n
));
622 static void parse_theme(xmlNodePtr node
, gpointer d
)
626 node
= node
->children
;
628 if ((n
= obt_xml_find_node(node
, "name"))) {
631 g_free(config_theme
);
632 c
= obt_xml_node_string(n
);
633 config_theme
= obt_paths_expand_tilde(c
);
636 if ((n
= obt_xml_find_node(node
, "titleLayout"))) {
639 g_free(config_title_layout
);
640 config_title_layout
= obt_xml_node_string(n
);
642 /* replace duplicates with spaces */
643 for (c
= config_title_layout
; *c
!= '\0'; ++c
)
644 for (d
= c
+1; *d
!= '\0'; ++d
)
645 if (*c
== *d
) *d
= ' ';
647 if ((n
= obt_xml_find_node(node
, "keepBorder")))
648 config_theme_keepborder
= obt_xml_node_bool(n
);
649 if ((n
= obt_xml_find_node(node
, "animateIconify")))
650 config_animate_iconify
= obt_xml_node_bool(n
);
651 if ((n
= obt_xml_find_node(node
, "windowListIconSize"))) {
652 config_theme_window_list_icon_size
= obt_xml_node_int(n
);
653 if (config_theme_window_list_icon_size
< 16)
654 config_theme_window_list_icon_size
= 16;
655 else if (config_theme_window_list_icon_size
> 96)
656 config_theme_window_list_icon_size
= 96;
659 n
= obt_xml_find_node(node
, "font");
663 gchar
*name
= g_strdup(RrDefaultFontFamily
);
664 gint size
= RrDefaultFontSize
;
665 RrFontWeight weight
= RrDefaultFontWeight
;
666 RrFontSlant slant
= RrDefaultFontSlant
;
668 if (obt_xml_attr_contains(n
, "place", "ActiveWindow"))
669 font
= &config_font_activewindow
;
670 else if (obt_xml_attr_contains(n
, "place", "InactiveWindow"))
671 font
= &config_font_inactivewindow
;
672 else if (obt_xml_attr_contains(n
, "place", "MenuHeader"))
673 font
= &config_font_menutitle
;
674 else if (obt_xml_attr_contains(n
, "place", "MenuItem"))
675 font
= &config_font_menuitem
;
676 else if (obt_xml_attr_contains(n
, "place", "ActiveOnScreenDisplay"))
677 font
= &config_font_activeosd
;
678 else if (obt_xml_attr_contains(n
, "place", "OnScreenDisplay"))
679 font
= &config_font_activeosd
;
680 else if (obt_xml_attr_contains(n
, "place","InactiveOnScreenDisplay"))
681 font
= &config_font_inactiveosd
;
685 if ((fnode
= obt_xml_find_node(n
->children
, "name"))) {
687 name
= obt_xml_node_string(fnode
);
689 if ((fnode
= obt_xml_find_node(n
->children
, "size"))) {
690 int s
= obt_xml_node_int(fnode
);
693 if ((fnode
= obt_xml_find_node(n
->children
, "weight"))) {
694 gchar
*w
= obt_xml_node_string(fnode
);
695 if (!g_ascii_strcasecmp(w
, "Bold"))
696 weight
= RR_FONTWEIGHT_BOLD
;
699 if ((fnode
= obt_xml_find_node(n
->children
, "slant"))) {
700 gchar
*s
= obt_xml_node_string(fnode
);
701 if (!g_ascii_strcasecmp(s
, "Italic"))
702 slant
= RR_FONTSLANT_ITALIC
;
703 if (!g_ascii_strcasecmp(s
, "Oblique"))
704 slant
= RR_FONTSLANT_OBLIQUE
;
708 *font
= RrFontOpen(ob_rr_inst
, name
, size
, weight
, slant
);
711 n
= obt_xml_find_node(n
->next
, "font");
715 static void parse_desktops(xmlNodePtr node
, gpointer d
)
719 node
= node
->children
;
721 if ((n
= obt_xml_find_node(node
, "number"))) {
722 gint d
= obt_xml_node_int(n
);
724 config_desktops_num
= (unsigned) d
;
726 if ((n
= obt_xml_find_node(node
, "firstdesk"))) {
727 gint d
= obt_xml_node_int(n
);
729 config_screen_firstdesk
= (unsigned) d
;
731 if ((n
= obt_xml_find_node(node
, "names"))) {
735 for (it
= config_desktops_names
; it
; it
= it
->next
)
737 g_slist_free(config_desktops_names
);
738 config_desktops_names
= NULL
;
740 nname
= obt_xml_find_node(n
->children
, "name");
742 config_desktops_names
=
743 g_slist_append(config_desktops_names
,
744 obt_xml_node_string(nname
));
745 nname
= obt_xml_find_node(nname
->next
, "name");
748 if ((n
= obt_xml_find_node(node
, "popupTime")))
749 config_desktop_popup_time
= obt_xml_node_int(n
);
752 static void parse_resize(xmlNodePtr node
, gpointer d
)
756 node
= node
->children
;
758 if ((n
= obt_xml_find_node(node
, "drawContents")))
759 config_resize_redraw
= obt_xml_node_bool(n
);
760 if ((n
= obt_xml_find_node(node
, "popupShow"))) {
761 config_resize_popup_show
= obt_xml_node_int(n
);
762 if (obt_xml_node_contains(n
, "Always"))
763 config_resize_popup_show
= 2;
764 else if (obt_xml_node_contains(n
, "Never"))
765 config_resize_popup_show
= 0;
766 else if (obt_xml_node_contains(n
, "Nonpixel"))
767 config_resize_popup_show
= 1;
769 if ((n
= obt_xml_find_node(node
, "popupPosition"))) {
770 if (obt_xml_node_contains(n
, "Top"))
771 config_resize_popup_pos
= OB_RESIZE_POS_TOP
;
772 else if (obt_xml_node_contains(n
, "Center"))
773 config_resize_popup_pos
= OB_RESIZE_POS_CENTER
;
774 else if (obt_xml_node_contains(n
, "Fixed")) {
775 config_resize_popup_pos
= OB_RESIZE_POS_FIXED
;
777 if ((n
= obt_xml_find_node(node
, "popupFixedPosition"))) {
780 if ((n2
= obt_xml_find_node(n
->children
, "x")))
781 config_parse_gravity_coord(n2
,
782 &config_resize_popup_fixed
.x
);
783 if ((n2
= obt_xml_find_node(n
->children
, "y")))
784 config_parse_gravity_coord(n2
,
785 &config_resize_popup_fixed
.y
);
787 config_resize_popup_fixed
.x
.pos
=
788 MAX(config_resize_popup_fixed
.x
.pos
, 0);
789 config_resize_popup_fixed
.y
.pos
=
790 MAX(config_resize_popup_fixed
.y
.pos
, 0);
796 static void parse_dock(xmlNodePtr node
, gpointer d
)
800 node
= node
->children
;
802 if ((n
= obt_xml_find_node(node
, "position"))) {
803 if (obt_xml_node_contains(n
, "TopLeft"))
804 config_dock_floating
= FALSE
,
805 config_dock_pos
= OB_DIRECTION_NORTHWEST
;
806 else if (obt_xml_node_contains(n
, "Top"))
807 config_dock_floating
= FALSE
,
808 config_dock_pos
= OB_DIRECTION_NORTH
;
809 else if (obt_xml_node_contains(n
, "TopRight"))
810 config_dock_floating
= FALSE
,
811 config_dock_pos
= OB_DIRECTION_NORTHEAST
;
812 else if (obt_xml_node_contains(n
, "Right"))
813 config_dock_floating
= FALSE
,
814 config_dock_pos
= OB_DIRECTION_EAST
;
815 else if (obt_xml_node_contains(n
, "BottomRight"))
816 config_dock_floating
= FALSE
,
817 config_dock_pos
= OB_DIRECTION_SOUTHEAST
;
818 else if (obt_xml_node_contains(n
, "Bottom"))
819 config_dock_floating
= FALSE
,
820 config_dock_pos
= OB_DIRECTION_SOUTH
;
821 else if (obt_xml_node_contains(n
, "BottomLeft"))
822 config_dock_floating
= FALSE
,
823 config_dock_pos
= OB_DIRECTION_SOUTHWEST
;
824 else if (obt_xml_node_contains(n
, "Left"))
825 config_dock_floating
= FALSE
,
826 config_dock_pos
= OB_DIRECTION_WEST
;
827 else if (obt_xml_node_contains(n
, "Floating"))
828 config_dock_floating
= TRUE
;
830 if (config_dock_floating
) {
831 if ((n
= obt_xml_find_node(node
, "floatingX")))
832 config_dock_x
= obt_xml_node_int(n
);
833 if ((n
= obt_xml_find_node(node
, "floatingY")))
834 config_dock_y
= obt_xml_node_int(n
);
836 if ((n
= obt_xml_find_node(node
, "noStrut")))
837 config_dock_nostrut
= obt_xml_node_bool(n
);
839 if ((n
= obt_xml_find_node(node
, "stacking"))) {
840 if (obt_xml_node_contains(n
, "normal"))
841 config_dock_layer
= OB_STACKING_LAYER_NORMAL
;
842 else if (obt_xml_node_contains(n
, "below"))
843 config_dock_layer
= OB_STACKING_LAYER_BELOW
;
844 else if (obt_xml_node_contains(n
, "above"))
845 config_dock_layer
= OB_STACKING_LAYER_ABOVE
;
847 if ((n
= obt_xml_find_node(node
, "direction"))) {
848 if (obt_xml_node_contains(n
, "horizontal"))
849 config_dock_orient
= OB_ORIENTATION_HORZ
;
850 else if (obt_xml_node_contains(n
, "vertical"))
851 config_dock_orient
= OB_ORIENTATION_VERT
;
853 if ((n
= obt_xml_find_node(node
, "autoHide")))
854 config_dock_hide
= obt_xml_node_bool(n
);
855 if ((n
= obt_xml_find_node(node
, "hideDelay")))
856 config_dock_hide_delay
= obt_xml_node_int(n
);
857 if ((n
= obt_xml_find_node(node
, "showDelay")))
858 config_dock_show_delay
= obt_xml_node_int(n
);
859 if ((n
= obt_xml_find_node(node
, "moveButton"))) {
860 gchar
*str
= obt_xml_node_string(n
);
862 if (translate_button(str
, &s
, &b
)) {
863 config_dock_app_move_button
= b
;
864 config_dock_app_move_modifiers
= s
;
866 g_message(_("Invalid button \"%s\" specified in config file"), str
);
872 static void parse_menu(xmlNodePtr node
, gpointer d
)
875 node
= node
->children
;
877 if ((n
= obt_xml_find_node(node
, "hideDelay")))
878 config_menu_hide_delay
= obt_xml_node_int(n
);
879 if ((n
= obt_xml_find_node(node
, "middle")))
880 config_menu_middle
= obt_xml_node_bool(n
);
881 if ((n
= obt_xml_find_node(node
, "submenuShowDelay")))
882 config_submenu_show_delay
= obt_xml_node_int(n
);
883 if ((n
= obt_xml_find_node(node
, "submenuHideDelay")))
884 config_submenu_hide_delay
= obt_xml_node_int(n
);
885 if ((n
= obt_xml_find_node(node
, "manageDesktops")))
886 config_menu_manage_desktops
= obt_xml_node_bool(n
);
887 if ((n
= obt_xml_find_node(node
, "showIcons"))) {
888 config_menu_show_icons
= obt_xml_node_bool(n
);
890 if (config_menu_show_icons
)
891 g_message(_("Openbox was compiled without Imlib2 image loading support. Icons in menus will not be loaded."));
895 while ((node
= obt_xml_find_node(node
, "file"))) {
896 gchar
*c
= obt_xml_node_string(node
);
897 config_menu_files
= g_slist_append(config_menu_files
,
898 obt_paths_expand_tilde(c
));
904 static void parse_resistance(xmlNodePtr node
, gpointer d
)
908 node
= node
->children
;
909 if ((n
= obt_xml_find_node(node
, "strength")))
910 config_resist_win
= obt_xml_node_int(n
);
911 if ((n
= obt_xml_find_node(node
, "screen_edge_strength")))
912 config_resist_edge
= obt_xml_node_int(n
);
918 const gchar
*actname
;
921 static void bind_default_keyboard(void)
924 ObDefKeyBind binds
[] = {
925 { "A-Tab", "NextWindow" },
926 { "S-A-Tab", "PreviousWindow" },
930 for (it
= binds
; it
->key
; ++it
) {
931 GList
*l
= g_list_append(NULL
, g_strdup(it
->key
));
932 keyboard_bind(l
, actions_parse_string(it
->actname
));
939 const gchar
*context
;
940 const ObMouseAction mact
;
941 const gchar
*actname
;
944 static void bind_default_mouse(void)
947 ObDefMouseBind binds
[] = {
948 { "Left", "Client", OB_MOUSE_ACTION_PRESS
, "Focus" },
949 { "Middle", "Client", OB_MOUSE_ACTION_PRESS
, "Focus" },
950 { "Right", "Client", OB_MOUSE_ACTION_PRESS
, "Focus" },
951 { "Left", "Desktop", OB_MOUSE_ACTION_PRESS
, "Focus" },
952 { "Middle", "Desktop", OB_MOUSE_ACTION_PRESS
, "Focus" },
953 { "Right", "Desktop", OB_MOUSE_ACTION_PRESS
, "Focus" },
954 { "Left", "Titlebar", OB_MOUSE_ACTION_PRESS
, "Focus" },
955 { "Left", "Bottom", OB_MOUSE_ACTION_PRESS
, "Focus" },
956 { "Left", "BLCorner", OB_MOUSE_ACTION_PRESS
, "Focus" },
957 { "Left", "BRCorner", OB_MOUSE_ACTION_PRESS
, "Focus" },
958 { "Left", "TLCorner", OB_MOUSE_ACTION_PRESS
, "Focus" },
959 { "Left", "TRCorner", OB_MOUSE_ACTION_PRESS
, "Focus" },
960 { "Left", "Close", OB_MOUSE_ACTION_PRESS
, "Focus" },
961 { "Left", "Maximize", OB_MOUSE_ACTION_PRESS
, "Focus" },
962 { "Left", "Iconify", OB_MOUSE_ACTION_PRESS
, "Focus" },
963 { "Left", "Icon", OB_MOUSE_ACTION_PRESS
, "Focus" },
964 { "Left", "AllDesktops", OB_MOUSE_ACTION_PRESS
, "Focus" },
965 { "Left", "Shade", OB_MOUSE_ACTION_PRESS
, "Focus" },
966 { "Left", "Client", OB_MOUSE_ACTION_CLICK
, "Raise" },
967 { "Left", "Titlebar", OB_MOUSE_ACTION_CLICK
, "Raise" },
968 { "Middle", "Titlebar", OB_MOUSE_ACTION_CLICK
, "Lower" },
969 { "Left", "BLCorner", OB_MOUSE_ACTION_CLICK
, "Raise" },
970 { "Left", "BRCorner", OB_MOUSE_ACTION_CLICK
, "Raise" },
971 { "Left", "TLCorner", OB_MOUSE_ACTION_CLICK
, "Raise" },
972 { "Left", "TRCorner", OB_MOUSE_ACTION_CLICK
, "Raise" },
973 { "Left", "Close", OB_MOUSE_ACTION_CLICK
, "Raise" },
974 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK
, "Raise" },
975 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK
, "Raise" },
976 { "Left", "Icon", OB_MOUSE_ACTION_CLICK
, "Raise" },
977 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK
, "Raise" },
978 { "Left", "Shade", OB_MOUSE_ACTION_CLICK
, "Raise" },
979 { "Left", "Close", OB_MOUSE_ACTION_CLICK
, "Close" },
980 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK
, "ToggleMaximize" },
981 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK
, "Iconify" },
982 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK
, "ToggleOmnipresent" },
983 { "Left", "Shade", OB_MOUSE_ACTION_CLICK
, "ToggleShade" },
984 { "Left", "TLCorner", OB_MOUSE_ACTION_MOTION
, "Resize" },
985 { "Left", "TRCorner", OB_MOUSE_ACTION_MOTION
, "Resize" },
986 { "Left", "BLCorner", OB_MOUSE_ACTION_MOTION
, "Resize" },
987 { "Left", "BRCorner", OB_MOUSE_ACTION_MOTION
, "Resize" },
988 { "Left", "Top", OB_MOUSE_ACTION_MOTION
, "Resize" },
989 { "Left", "Bottom", OB_MOUSE_ACTION_MOTION
, "Resize" },
990 { "Left", "Left", OB_MOUSE_ACTION_MOTION
, "Resize" },
991 { "Left", "Right", OB_MOUSE_ACTION_MOTION
, "Resize" },
992 { "Left", "Titlebar", OB_MOUSE_ACTION_MOTION
, "Move" },
993 { "A-Left", "Frame", OB_MOUSE_ACTION_MOTION
, "Move" },
994 { "A-Middle", "Frame", OB_MOUSE_ACTION_MOTION
, "Resize" },
995 { NULL
, NULL
, 0, NULL
}
998 for (it
= binds
; it
->button
; ++it
)
999 mouse_bind(it
->button
, frame_context_from_string(it
->context
),
1000 it
->mact
, actions_parse_string(it
->actname
));
1003 void config_startup(ObtXmlInst
*i
)
1005 config_focus_new
= TRUE
;
1006 config_focus_follow
= FALSE
;
1007 config_focus_delay
= 0;
1008 config_focus_raise
= FALSE
;
1009 config_focus_last
= TRUE
;
1010 config_focus_under_mouse
= FALSE
;
1011 config_unfocus_leave
= FALSE
;
1013 obt_xml_register(i
, "focus", parse_focus
, NULL
);
1015 config_place_policy
= OB_PLACE_POLICY_SMART
;
1016 config_place_center
= TRUE
;
1017 config_place_monitor
= OB_PLACE_MONITOR_PRIMARY
;
1019 config_primary_monitor_index
= 1;
1020 config_primary_monitor
= OB_PLACE_MONITOR_ACTIVE
;
1022 obt_xml_register(i
, "placement", parse_placement
, NULL
);
1024 STRUT_PARTIAL_SET(config_margins
, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1026 obt_xml_register(i
, "margins", parse_margins
, NULL
);
1028 config_theme
= NULL
;
1030 config_animate_iconify
= TRUE
;
1031 config_title_layout
= g_strdup("NLIMC");
1032 config_theme_keepborder
= TRUE
;
1033 config_theme_window_list_icon_size
= 36;
1035 config_font_activewindow
= NULL
;
1036 config_font_inactivewindow
= NULL
;
1037 config_font_menuitem
= NULL
;
1038 config_font_menutitle
= NULL
;
1039 config_font_activeosd
= NULL
;
1040 config_font_inactiveosd
= NULL
;
1042 obt_xml_register(i
, "theme", parse_theme
, NULL
);
1044 config_desktops_num
= 4;
1045 config_screen_firstdesk
= 1;
1046 config_desktops_names
= NULL
;
1047 config_desktop_popup_time
= 875;
1049 obt_xml_register(i
, "desktops", parse_desktops
, NULL
);
1051 config_resize_redraw
= TRUE
;
1052 config_resize_popup_show
= 1; /* nonpixel increments */
1053 config_resize_popup_pos
= OB_RESIZE_POS_CENTER
;
1054 GRAVITY_COORD_SET(config_resize_popup_fixed
.x
, 0, FALSE
, FALSE
);
1055 GRAVITY_COORD_SET(config_resize_popup_fixed
.y
, 0, FALSE
, FALSE
);
1057 obt_xml_register(i
, "resize", parse_resize
, NULL
);
1059 config_dock_layer
= OB_STACKING_LAYER_ABOVE
;
1060 config_dock_pos
= OB_DIRECTION_NORTHEAST
;
1061 config_dock_floating
= FALSE
;
1062 config_dock_nostrut
= FALSE
;
1065 config_dock_orient
= OB_ORIENTATION_VERT
;
1066 config_dock_hide
= FALSE
;
1067 config_dock_hide_delay
= 300;
1068 config_dock_show_delay
= 300;
1069 config_dock_app_move_button
= 2; /* middle */
1070 config_dock_app_move_modifiers
= 0;
1072 obt_xml_register(i
, "dock", parse_dock
, NULL
);
1074 translate_key("C-g", &config_keyboard_reset_state
,
1075 &config_keyboard_reset_keycode
);
1077 bind_default_keyboard();
1079 obt_xml_register(i
, "keyboard", parse_keyboard
, NULL
);
1081 config_mouse_threshold
= 8;
1082 config_mouse_dclicktime
= 500;
1083 config_mouse_screenedgetime
= 400;
1084 config_mouse_screenedgewarp
= FALSE
;
1086 bind_default_mouse();
1088 obt_xml_register(i
, "mouse", parse_mouse
, NULL
);
1090 config_resist_win
= 10;
1091 config_resist_edge
= 20;
1093 obt_xml_register(i
, "resistance", parse_resistance
, NULL
);
1095 config_menu_hide_delay
= 250;
1096 config_menu_middle
= FALSE
;
1097 config_submenu_show_delay
= 100;
1098 config_submenu_hide_delay
= 400;
1099 config_menu_manage_desktops
= TRUE
;
1100 config_menu_files
= NULL
;
1101 config_menu_show_icons
= TRUE
;
1103 obt_xml_register(i
, "menu", parse_menu
, NULL
);
1105 config_per_app_settings
= NULL
;
1107 obt_xml_register(i
, "applications", parse_per_app_settings
, NULL
);
1110 void config_shutdown(void)
1114 g_free(config_theme
);
1116 g_free(config_title_layout
);
1118 RrFontClose(config_font_activewindow
);
1119 RrFontClose(config_font_inactivewindow
);
1120 RrFontClose(config_font_menuitem
);
1121 RrFontClose(config_font_menutitle
);
1122 RrFontClose(config_font_activeosd
);
1123 RrFontClose(config_font_inactiveosd
);
1125 for (it
= config_desktops_names
; it
; it
= g_slist_next(it
))
1127 g_slist_free(config_desktops_names
);
1129 for (it
= config_menu_files
; it
; it
= g_slist_next(it
))
1131 g_slist_free(config_menu_files
);
1133 for (it
= config_per_app_settings
; it
; it
= g_slist_next(it
)) {
1134 ObAppSettings
*itd
= (ObAppSettings
*)it
->data
;
1135 if (itd
->name
) g_pattern_spec_free(itd
->name
);
1136 if (itd
->role
) g_pattern_spec_free(itd
->role
);
1137 if (itd
->title
) g_pattern_spec_free(itd
->title
);
1138 if (itd
->class) g_pattern_spec_free(itd
->class);
1139 g_slice_free(ObAppSettings
, it
->data
);
1141 g_slist_free(config_per_app_settings
);