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
)
392 gchar
*keystring
, **keys
, **key
;
394 gboolean is_chroot
= FALSE
;
396 if (!obt_xml_attr_string(node
, "key", &keystring
))
399 obt_xml_attr_bool(node
, "chroot", &is_chroot
);
401 keys
= g_strsplit(keystring
, " ", 0);
402 for (key
= keys
; *key
; ++key
) {
403 keylist
= g_list_append(keylist
, *key
);
405 if ((n
= obt_xml_find_node(node
->children
, "keybind"))) {
407 parse_key(n
, keylist
);
408 n
= obt_xml_find_node(n
->next
, "keybind");
411 else if ((n
= obt_xml_find_node(node
->children
, "action"))) {
413 ObActionsAct
*action
;
415 action
= actions_parse(n
);
417 keyboard_bind(keylist
, action
);
418 n
= obt_xml_find_node(n
->next
, "action");
424 keyboard_chroot(keylist
);
425 keylist
= g_list_delete_link(keylist
, g_list_last(keylist
));
432 static void parse_keyboard(xmlNodePtr node
, gpointer d
)
437 keyboard_unbind_all();
439 if ((n
= obt_xml_find_node(node
->children
, "chainQuitKey"))) {
440 key
= obt_xml_node_string(n
);
441 translate_key(key
, &config_keyboard_reset_state
,
442 &config_keyboard_reset_keycode
);
446 if ((n
= obt_xml_find_node(node
->children
, "keybind")))
449 n
= obt_xml_find_node(n
->next
, "keybind");
455 <context name="Titlebar">
456 <mousebind button="Left" action="Press">
457 <action name="Raise"></action>
463 static void parse_mouse(xmlNodePtr node
, gpointer d
)
465 xmlNodePtr n
, nbut
, nact
;
472 node
= node
->children
;
474 if ((n
= obt_xml_find_node(node
, "dragThreshold")))
475 config_mouse_threshold
= obt_xml_node_int(n
);
476 if ((n
= obt_xml_find_node(node
, "doubleClickTime")))
477 config_mouse_dclicktime
= obt_xml_node_int(n
);
478 if ((n
= obt_xml_find_node(node
, "screenEdgeWarpTime"))) {
479 config_mouse_screenedgetime
= obt_xml_node_int(n
);
480 /* minimum value of 25 for this property, when it is 1 and you hit the
481 edge it basically never stops */
482 if (config_mouse_screenedgetime
&& config_mouse_screenedgetime
< 25)
483 config_mouse_screenedgetime
= 25;
485 if ((n
= obt_xml_find_node(node
, "screenEdgeWarpMouse")))
486 config_mouse_screenedgewarp
= obt_xml_node_bool(n
);
488 n
= obt_xml_find_node(node
, "context");
493 if (!obt_xml_attr_string(n
, "name", &cxstr
))
496 modcxstr
= g_strdup(cxstr
); /* make a copy to mutilate */
497 while (frame_next_context_from_string(modcxstr
, &cx
)) {
499 gchar
*s
= strchr(modcxstr
, ' ');
502 g_message(_("Invalid context \"%s\" in mouse binding"),
509 nbut
= obt_xml_find_node(n
->children
, "mousebind");
511 if (!obt_xml_attr_string(nbut
, "button", &buttonstr
))
513 if (obt_xml_attr_contains(nbut
, "action", "press"))
514 mact
= OB_MOUSE_ACTION_PRESS
;
515 else if (obt_xml_attr_contains(nbut
, "action", "release"))
516 mact
= OB_MOUSE_ACTION_RELEASE
;
517 else if (obt_xml_attr_contains(nbut
, "action", "click"))
518 mact
= OB_MOUSE_ACTION_CLICK
;
519 else if (obt_xml_attr_contains(nbut
, "action","doubleclick"))
520 mact
= OB_MOUSE_ACTION_DOUBLE_CLICK
;
521 else if (obt_xml_attr_contains(nbut
, "action", "drag"))
522 mact
= OB_MOUSE_ACTION_MOTION
;
526 nact
= obt_xml_find_node(nbut
->children
, "action");
528 ObActionsAct
*action
;
530 if ((action
= actions_parse(nact
)))
531 mouse_bind(buttonstr
, cx
, mact
, action
);
532 nact
= obt_xml_find_node(nact
->next
, "action");
536 nbut
= obt_xml_find_node(nbut
->next
, "mousebind");
542 n
= obt_xml_find_node(n
->next
, "context");
546 static void parse_focus(xmlNodePtr node
, gpointer d
)
550 node
= node
->children
;
552 if ((n
= obt_xml_find_node(node
, "focusNew")))
553 config_focus_new
= obt_xml_node_bool(n
);
554 if ((n
= obt_xml_find_node(node
, "followMouse")))
555 config_focus_follow
= obt_xml_node_bool(n
);
556 if ((n
= obt_xml_find_node(node
, "focusDelay")))
557 config_focus_delay
= obt_xml_node_int(n
);
558 if ((n
= obt_xml_find_node(node
, "raiseOnFocus")))
559 config_focus_raise
= obt_xml_node_bool(n
);
560 if ((n
= obt_xml_find_node(node
, "focusLast")))
561 config_focus_last
= obt_xml_node_bool(n
);
562 if ((n
= obt_xml_find_node(node
, "underMouse")))
563 config_focus_under_mouse
= obt_xml_node_bool(n
);
564 if ((n
= obt_xml_find_node(node
, "unfocusOnLeave")))
565 config_unfocus_leave
= obt_xml_node_bool(n
);
568 static void parse_placement(xmlNodePtr node
, gpointer d
)
572 node
= node
->children
;
574 if ((n
= obt_xml_find_node(node
, "policy")))
575 if (obt_xml_node_contains(n
, "UnderMouse"))
576 config_place_policy
= OB_PLACE_POLICY_MOUSE
;
577 if ((n
= obt_xml_find_node(node
, "center")))
578 config_place_center
= obt_xml_node_bool(n
);
579 if ((n
= obt_xml_find_node(node
, "monitor"))) {
580 if (obt_xml_node_contains(n
, "active"))
581 config_place_monitor
= OB_PLACE_MONITOR_ACTIVE
;
582 else if (obt_xml_node_contains(n
, "mouse"))
583 config_place_monitor
= OB_PLACE_MONITOR_MOUSE
;
585 if ((n
= obt_xml_find_node(node
, "primaryMonitor"))) {
586 config_primary_monitor_index
= obt_xml_node_int(n
);
587 if (!config_primary_monitor_index
) {
588 if (obt_xml_node_contains(n
, "mouse"))
589 config_primary_monitor
= OB_PLACE_MONITOR_MOUSE
;
594 static void parse_margins(xmlNodePtr node
, gpointer d
)
598 node
= node
->children
;
600 if ((n
= obt_xml_find_node(node
, "top")))
601 config_margins
.top
= MAX(0, obt_xml_node_int(n
));
602 if ((n
= obt_xml_find_node(node
, "left")))
603 config_margins
.left
= MAX(0, obt_xml_node_int(n
));
604 if ((n
= obt_xml_find_node(node
, "right")))
605 config_margins
.right
= MAX(0, obt_xml_node_int(n
));
606 if ((n
= obt_xml_find_node(node
, "bottom")))
607 config_margins
.bottom
= MAX(0, obt_xml_node_int(n
));
610 static void parse_theme(xmlNodePtr node
, gpointer d
)
614 node
= node
->children
;
616 if ((n
= obt_xml_find_node(node
, "name"))) {
619 g_free(config_theme
);
620 c
= obt_xml_node_string(n
);
621 config_theme
= obt_paths_expand_tilde(c
);
624 if ((n
= obt_xml_find_node(node
, "titleLayout"))) {
627 g_free(config_title_layout
);
628 config_title_layout
= obt_xml_node_string(n
);
630 /* replace duplicates with spaces */
631 for (c
= config_title_layout
; *c
!= '\0'; ++c
)
632 for (d
= c
+1; *d
!= '\0'; ++d
)
633 if (*c
== *d
) *d
= ' ';
635 if ((n
= obt_xml_find_node(node
, "keepBorder")))
636 config_theme_keepborder
= obt_xml_node_bool(n
);
637 if ((n
= obt_xml_find_node(node
, "animateIconify")))
638 config_animate_iconify
= obt_xml_node_bool(n
);
639 if ((n
= obt_xml_find_node(node
, "windowListIconSize"))) {
640 config_theme_window_list_icon_size
= obt_xml_node_int(n
);
641 if (config_theme_window_list_icon_size
< 16)
642 config_theme_window_list_icon_size
= 16;
643 else if (config_theme_window_list_icon_size
> 96)
644 config_theme_window_list_icon_size
= 96;
647 n
= obt_xml_find_node(node
, "font");
651 gchar
*name
= g_strdup(RrDefaultFontFamily
);
652 gint size
= RrDefaultFontSize
;
653 RrFontWeight weight
= RrDefaultFontWeight
;
654 RrFontSlant slant
= RrDefaultFontSlant
;
656 if (obt_xml_attr_contains(n
, "place", "ActiveWindow"))
657 font
= &config_font_activewindow
;
658 else if (obt_xml_attr_contains(n
, "place", "InactiveWindow"))
659 font
= &config_font_inactivewindow
;
660 else if (obt_xml_attr_contains(n
, "place", "MenuHeader"))
661 font
= &config_font_menutitle
;
662 else if (obt_xml_attr_contains(n
, "place", "MenuItem"))
663 font
= &config_font_menuitem
;
664 else if (obt_xml_attr_contains(n
, "place", "ActiveOnScreenDisplay"))
665 font
= &config_font_activeosd
;
666 else if (obt_xml_attr_contains(n
, "place", "OnScreenDisplay"))
667 font
= &config_font_activeosd
;
668 else if (obt_xml_attr_contains(n
, "place","InactiveOnScreenDisplay"))
669 font
= &config_font_inactiveosd
;
673 if ((fnode
= obt_xml_find_node(n
->children
, "name"))) {
675 name
= obt_xml_node_string(fnode
);
677 if ((fnode
= obt_xml_find_node(n
->children
, "size"))) {
678 int s
= obt_xml_node_int(fnode
);
681 if ((fnode
= obt_xml_find_node(n
->children
, "weight"))) {
682 gchar
*w
= obt_xml_node_string(fnode
);
683 if (!g_ascii_strcasecmp(w
, "Bold"))
684 weight
= RR_FONTWEIGHT_BOLD
;
687 if ((fnode
= obt_xml_find_node(n
->children
, "slant"))) {
688 gchar
*s
= obt_xml_node_string(fnode
);
689 if (!g_ascii_strcasecmp(s
, "Italic"))
690 slant
= RR_FONTSLANT_ITALIC
;
691 if (!g_ascii_strcasecmp(s
, "Oblique"))
692 slant
= RR_FONTSLANT_OBLIQUE
;
696 *font
= RrFontOpen(ob_rr_inst
, name
, size
, weight
, slant
);
699 n
= obt_xml_find_node(n
->next
, "font");
703 static void parse_desktops(xmlNodePtr node
, gpointer d
)
707 node
= node
->children
;
709 if ((n
= obt_xml_find_node(node
, "number"))) {
710 gint d
= obt_xml_node_int(n
);
712 config_desktops_num
= (unsigned) d
;
714 if ((n
= obt_xml_find_node(node
, "firstdesk"))) {
715 gint d
= obt_xml_node_int(n
);
717 config_screen_firstdesk
= (unsigned) d
;
719 if ((n
= obt_xml_find_node(node
, "names"))) {
723 for (it
= config_desktops_names
; it
; it
= it
->next
)
725 g_slist_free(config_desktops_names
);
726 config_desktops_names
= NULL
;
728 nname
= obt_xml_find_node(n
->children
, "name");
730 config_desktops_names
=
731 g_slist_append(config_desktops_names
,
732 obt_xml_node_string(nname
));
733 nname
= obt_xml_find_node(nname
->next
, "name");
736 if ((n
= obt_xml_find_node(node
, "popupTime")))
737 config_desktop_popup_time
= obt_xml_node_int(n
);
740 static void parse_resize(xmlNodePtr node
, gpointer d
)
744 node
= node
->children
;
746 if ((n
= obt_xml_find_node(node
, "drawContents")))
747 config_resize_redraw
= obt_xml_node_bool(n
);
748 if ((n
= obt_xml_find_node(node
, "popupShow"))) {
749 config_resize_popup_show
= obt_xml_node_int(n
);
750 if (obt_xml_node_contains(n
, "Always"))
751 config_resize_popup_show
= 2;
752 else if (obt_xml_node_contains(n
, "Never"))
753 config_resize_popup_show
= 0;
754 else if (obt_xml_node_contains(n
, "Nonpixel"))
755 config_resize_popup_show
= 1;
757 if ((n
= obt_xml_find_node(node
, "popupPosition"))) {
758 if (obt_xml_node_contains(n
, "Top"))
759 config_resize_popup_pos
= OB_RESIZE_POS_TOP
;
760 else if (obt_xml_node_contains(n
, "Center"))
761 config_resize_popup_pos
= OB_RESIZE_POS_CENTER
;
762 else if (obt_xml_node_contains(n
, "Fixed")) {
763 config_resize_popup_pos
= OB_RESIZE_POS_FIXED
;
765 if ((n
= obt_xml_find_node(node
, "popupFixedPosition"))) {
768 if ((n2
= obt_xml_find_node(n
->children
, "x")))
769 config_parse_gravity_coord(n2
,
770 &config_resize_popup_fixed
.x
);
771 if ((n2
= obt_xml_find_node(n
->children
, "y")))
772 config_parse_gravity_coord(n2
,
773 &config_resize_popup_fixed
.y
);
775 config_resize_popup_fixed
.x
.pos
=
776 MAX(config_resize_popup_fixed
.x
.pos
, 0);
777 config_resize_popup_fixed
.y
.pos
=
778 MAX(config_resize_popup_fixed
.y
.pos
, 0);
784 static void parse_dock(xmlNodePtr node
, gpointer d
)
788 node
= node
->children
;
790 if ((n
= obt_xml_find_node(node
, "position"))) {
791 if (obt_xml_node_contains(n
, "TopLeft"))
792 config_dock_floating
= FALSE
,
793 config_dock_pos
= OB_DIRECTION_NORTHWEST
;
794 else if (obt_xml_node_contains(n
, "Top"))
795 config_dock_floating
= FALSE
,
796 config_dock_pos
= OB_DIRECTION_NORTH
;
797 else if (obt_xml_node_contains(n
, "TopRight"))
798 config_dock_floating
= FALSE
,
799 config_dock_pos
= OB_DIRECTION_NORTHEAST
;
800 else if (obt_xml_node_contains(n
, "Right"))
801 config_dock_floating
= FALSE
,
802 config_dock_pos
= OB_DIRECTION_EAST
;
803 else if (obt_xml_node_contains(n
, "BottomRight"))
804 config_dock_floating
= FALSE
,
805 config_dock_pos
= OB_DIRECTION_SOUTHEAST
;
806 else if (obt_xml_node_contains(n
, "Bottom"))
807 config_dock_floating
= FALSE
,
808 config_dock_pos
= OB_DIRECTION_SOUTH
;
809 else if (obt_xml_node_contains(n
, "BottomLeft"))
810 config_dock_floating
= FALSE
,
811 config_dock_pos
= OB_DIRECTION_SOUTHWEST
;
812 else if (obt_xml_node_contains(n
, "Left"))
813 config_dock_floating
= FALSE
,
814 config_dock_pos
= OB_DIRECTION_WEST
;
815 else if (obt_xml_node_contains(n
, "Floating"))
816 config_dock_floating
= TRUE
;
818 if (config_dock_floating
) {
819 if ((n
= obt_xml_find_node(node
, "floatingX")))
820 config_dock_x
= obt_xml_node_int(n
);
821 if ((n
= obt_xml_find_node(node
, "floatingY")))
822 config_dock_y
= obt_xml_node_int(n
);
824 if ((n
= obt_xml_find_node(node
, "noStrut")))
825 config_dock_nostrut
= obt_xml_node_bool(n
);
827 if ((n
= obt_xml_find_node(node
, "stacking"))) {
828 if (obt_xml_node_contains(n
, "normal"))
829 config_dock_layer
= OB_STACKING_LAYER_NORMAL
;
830 else if (obt_xml_node_contains(n
, "below"))
831 config_dock_layer
= OB_STACKING_LAYER_BELOW
;
832 else if (obt_xml_node_contains(n
, "above"))
833 config_dock_layer
= OB_STACKING_LAYER_ABOVE
;
835 if ((n
= obt_xml_find_node(node
, "direction"))) {
836 if (obt_xml_node_contains(n
, "horizontal"))
837 config_dock_orient
= OB_ORIENTATION_HORZ
;
838 else if (obt_xml_node_contains(n
, "vertical"))
839 config_dock_orient
= OB_ORIENTATION_VERT
;
841 if ((n
= obt_xml_find_node(node
, "autoHide")))
842 config_dock_hide
= obt_xml_node_bool(n
);
843 if ((n
= obt_xml_find_node(node
, "hideDelay")))
844 config_dock_hide_delay
= obt_xml_node_int(n
);
845 if ((n
= obt_xml_find_node(node
, "showDelay")))
846 config_dock_show_delay
= obt_xml_node_int(n
);
847 if ((n
= obt_xml_find_node(node
, "moveButton"))) {
848 gchar
*str
= obt_xml_node_string(n
);
850 if (translate_button(str
, &s
, &b
)) {
851 config_dock_app_move_button
= b
;
852 config_dock_app_move_modifiers
= s
;
854 g_message(_("Invalid button \"%s\" specified in config file"), str
);
860 static void parse_menu(xmlNodePtr node
, gpointer d
)
863 node
= node
->children
;
865 if ((n
= obt_xml_find_node(node
, "hideDelay")))
866 config_menu_hide_delay
= obt_xml_node_int(n
);
867 if ((n
= obt_xml_find_node(node
, "middle")))
868 config_menu_middle
= obt_xml_node_bool(n
);
869 if ((n
= obt_xml_find_node(node
, "submenuShowDelay")))
870 config_submenu_show_delay
= obt_xml_node_int(n
);
871 if ((n
= obt_xml_find_node(node
, "submenuHideDelay")))
872 config_submenu_hide_delay
= obt_xml_node_int(n
);
873 if ((n
= obt_xml_find_node(node
, "manageDesktops")))
874 config_menu_manage_desktops
= obt_xml_node_bool(n
);
875 if ((n
= obt_xml_find_node(node
, "showIcons"))) {
876 config_menu_show_icons
= obt_xml_node_bool(n
);
878 if (config_menu_show_icons
)
879 g_message(_("Openbox was compiled without Imlib2 image loading support. Icons in menus will not be loaded."));
883 while ((node
= obt_xml_find_node(node
, "file"))) {
884 gchar
*c
= obt_xml_node_string(node
);
885 config_menu_files
= g_slist_append(config_menu_files
,
886 obt_paths_expand_tilde(c
));
892 static void parse_resistance(xmlNodePtr node
, gpointer d
)
896 node
= node
->children
;
897 if ((n
= obt_xml_find_node(node
, "strength")))
898 config_resist_win
= obt_xml_node_int(n
);
899 if ((n
= obt_xml_find_node(node
, "screen_edge_strength")))
900 config_resist_edge
= obt_xml_node_int(n
);
906 const gchar
*actname
;
909 static void bind_default_keyboard(void)
912 ObDefKeyBind binds
[] = {
913 { "A-Tab", "NextWindow" },
914 { "S-A-Tab", "PreviousWindow" },
918 for (it
= binds
; it
->key
; ++it
) {
919 GList
*l
= g_list_append(NULL
, g_strdup(it
->key
));
920 keyboard_bind(l
, actions_parse_string(it
->actname
));
927 const gchar
*context
;
928 const ObMouseAction mact
;
929 const gchar
*actname
;
932 static void bind_default_mouse(void)
935 ObDefMouseBind binds
[] = {
936 { "Left", "Client", OB_MOUSE_ACTION_PRESS
, "Focus" },
937 { "Middle", "Client", OB_MOUSE_ACTION_PRESS
, "Focus" },
938 { "Right", "Client", OB_MOUSE_ACTION_PRESS
, "Focus" },
939 { "Left", "Desktop", OB_MOUSE_ACTION_PRESS
, "Focus" },
940 { "Middle", "Desktop", OB_MOUSE_ACTION_PRESS
, "Focus" },
941 { "Right", "Desktop", OB_MOUSE_ACTION_PRESS
, "Focus" },
942 { "Left", "Titlebar", OB_MOUSE_ACTION_PRESS
, "Focus" },
943 { "Left", "Bottom", OB_MOUSE_ACTION_PRESS
, "Focus" },
944 { "Left", "BLCorner", OB_MOUSE_ACTION_PRESS
, "Focus" },
945 { "Left", "BRCorner", OB_MOUSE_ACTION_PRESS
, "Focus" },
946 { "Left", "TLCorner", OB_MOUSE_ACTION_PRESS
, "Focus" },
947 { "Left", "TRCorner", OB_MOUSE_ACTION_PRESS
, "Focus" },
948 { "Left", "Close", OB_MOUSE_ACTION_PRESS
, "Focus" },
949 { "Left", "Maximize", OB_MOUSE_ACTION_PRESS
, "Focus" },
950 { "Left", "Iconify", OB_MOUSE_ACTION_PRESS
, "Focus" },
951 { "Left", "Icon", OB_MOUSE_ACTION_PRESS
, "Focus" },
952 { "Left", "AllDesktops", OB_MOUSE_ACTION_PRESS
, "Focus" },
953 { "Left", "Shade", OB_MOUSE_ACTION_PRESS
, "Focus" },
954 { "Left", "Client", OB_MOUSE_ACTION_CLICK
, "Raise" },
955 { "Left", "Titlebar", OB_MOUSE_ACTION_CLICK
, "Raise" },
956 { "Middle", "Titlebar", OB_MOUSE_ACTION_CLICK
, "Lower" },
957 { "Left", "BLCorner", OB_MOUSE_ACTION_CLICK
, "Raise" },
958 { "Left", "BRCorner", OB_MOUSE_ACTION_CLICK
, "Raise" },
959 { "Left", "TLCorner", OB_MOUSE_ACTION_CLICK
, "Raise" },
960 { "Left", "TRCorner", OB_MOUSE_ACTION_CLICK
, "Raise" },
961 { "Left", "Close", OB_MOUSE_ACTION_CLICK
, "Raise" },
962 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK
, "Raise" },
963 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK
, "Raise" },
964 { "Left", "Icon", OB_MOUSE_ACTION_CLICK
, "Raise" },
965 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK
, "Raise" },
966 { "Left", "Shade", OB_MOUSE_ACTION_CLICK
, "Raise" },
967 { "Left", "Close", OB_MOUSE_ACTION_CLICK
, "Close" },
968 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK
, "ToggleMaximize" },
969 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK
, "Iconify" },
970 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK
, "ToggleOmnipresent" },
971 { "Left", "Shade", OB_MOUSE_ACTION_CLICK
, "ToggleShade" },
972 { "Left", "TLCorner", OB_MOUSE_ACTION_MOTION
, "Resize" },
973 { "Left", "TRCorner", OB_MOUSE_ACTION_MOTION
, "Resize" },
974 { "Left", "BLCorner", OB_MOUSE_ACTION_MOTION
, "Resize" },
975 { "Left", "BRCorner", OB_MOUSE_ACTION_MOTION
, "Resize" },
976 { "Left", "Top", OB_MOUSE_ACTION_MOTION
, "Resize" },
977 { "Left", "Bottom", OB_MOUSE_ACTION_MOTION
, "Resize" },
978 { "Left", "Left", OB_MOUSE_ACTION_MOTION
, "Resize" },
979 { "Left", "Right", OB_MOUSE_ACTION_MOTION
, "Resize" },
980 { "Left", "Titlebar", OB_MOUSE_ACTION_MOTION
, "Move" },
981 { "A-Left", "Frame", OB_MOUSE_ACTION_MOTION
, "Move" },
982 { "A-Middle", "Frame", OB_MOUSE_ACTION_MOTION
, "Resize" },
983 { NULL
, NULL
, 0, NULL
}
986 for (it
= binds
; it
->button
; ++it
)
987 mouse_bind(it
->button
, frame_context_from_string(it
->context
),
988 it
->mact
, actions_parse_string(it
->actname
));
991 void config_startup(ObtXmlInst
*i
)
993 config_focus_new
= TRUE
;
994 config_focus_follow
= FALSE
;
995 config_focus_delay
= 0;
996 config_focus_raise
= FALSE
;
997 config_focus_last
= TRUE
;
998 config_focus_under_mouse
= FALSE
;
999 config_unfocus_leave
= FALSE
;
1001 obt_xml_register(i
, "focus", parse_focus
, NULL
);
1003 config_place_policy
= OB_PLACE_POLICY_SMART
;
1004 config_place_center
= TRUE
;
1005 config_place_monitor
= OB_PLACE_MONITOR_ANY
;
1007 config_primary_monitor_index
= 1;
1008 config_primary_monitor
= OB_PLACE_MONITOR_ACTIVE
;
1010 obt_xml_register(i
, "placement", parse_placement
, NULL
);
1012 STRUT_PARTIAL_SET(config_margins
, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1014 obt_xml_register(i
, "margins", parse_margins
, NULL
);
1016 config_theme
= NULL
;
1018 config_animate_iconify
= TRUE
;
1019 config_title_layout
= g_strdup("NLIMC");
1020 config_theme_keepborder
= TRUE
;
1021 config_theme_window_list_icon_size
= 36;
1023 config_font_activewindow
= NULL
;
1024 config_font_inactivewindow
= NULL
;
1025 config_font_menuitem
= NULL
;
1026 config_font_menutitle
= NULL
;
1027 config_font_activeosd
= NULL
;
1028 config_font_inactiveosd
= NULL
;
1030 obt_xml_register(i
, "theme", parse_theme
, NULL
);
1032 config_desktops_num
= 4;
1033 config_screen_firstdesk
= 1;
1034 config_desktops_names
= NULL
;
1035 config_desktop_popup_time
= 875;
1037 obt_xml_register(i
, "desktops", parse_desktops
, NULL
);
1039 config_resize_redraw
= TRUE
;
1040 config_resize_popup_show
= 1; /* nonpixel increments */
1041 config_resize_popup_pos
= OB_RESIZE_POS_CENTER
;
1042 GRAVITY_COORD_SET(config_resize_popup_fixed
.x
, 0, FALSE
, FALSE
);
1043 GRAVITY_COORD_SET(config_resize_popup_fixed
.y
, 0, FALSE
, FALSE
);
1045 obt_xml_register(i
, "resize", parse_resize
, NULL
);
1047 config_dock_layer
= OB_STACKING_LAYER_ABOVE
;
1048 config_dock_pos
= OB_DIRECTION_NORTHEAST
;
1049 config_dock_floating
= FALSE
;
1050 config_dock_nostrut
= FALSE
;
1053 config_dock_orient
= OB_ORIENTATION_VERT
;
1054 config_dock_hide
= FALSE
;
1055 config_dock_hide_delay
= 300;
1056 config_dock_show_delay
= 300;
1057 config_dock_app_move_button
= 2; /* middle */
1058 config_dock_app_move_modifiers
= 0;
1060 obt_xml_register(i
, "dock", parse_dock
, NULL
);
1062 translate_key("C-g", &config_keyboard_reset_state
,
1063 &config_keyboard_reset_keycode
);
1065 bind_default_keyboard();
1067 obt_xml_register(i
, "keyboard", parse_keyboard
, NULL
);
1069 config_mouse_threshold
= 8;
1070 config_mouse_dclicktime
= 200;
1071 config_mouse_screenedgetime
= 400;
1072 config_mouse_screenedgewarp
= FALSE
;
1074 bind_default_mouse();
1076 obt_xml_register(i
, "mouse", parse_mouse
, NULL
);
1078 config_resist_win
= 10;
1079 config_resist_edge
= 20;
1081 obt_xml_register(i
, "resistance", parse_resistance
, NULL
);
1083 config_menu_hide_delay
= 250;
1084 config_menu_middle
= FALSE
;
1085 config_submenu_show_delay
= 100;
1086 config_submenu_hide_delay
= 400;
1087 config_menu_manage_desktops
= TRUE
;
1088 config_menu_files
= NULL
;
1089 config_menu_show_icons
= TRUE
;
1091 obt_xml_register(i
, "menu", parse_menu
, NULL
);
1093 config_per_app_settings
= NULL
;
1095 obt_xml_register(i
, "applications", parse_per_app_settings
, NULL
);
1098 void config_shutdown(void)
1102 g_free(config_theme
);
1104 g_free(config_title_layout
);
1106 RrFontClose(config_font_activewindow
);
1107 RrFontClose(config_font_inactivewindow
);
1108 RrFontClose(config_font_menuitem
);
1109 RrFontClose(config_font_menutitle
);
1110 RrFontClose(config_font_activeosd
);
1111 RrFontClose(config_font_inactiveosd
);
1113 for (it
= config_desktops_names
; it
; it
= g_slist_next(it
))
1115 g_slist_free(config_desktops_names
);
1117 for (it
= config_menu_files
; it
; it
= g_slist_next(it
))
1119 g_slist_free(config_menu_files
);
1121 for (it
= config_per_app_settings
; it
; it
= g_slist_next(it
)) {
1122 ObAppSettings
*itd
= (ObAppSettings
*)it
->data
;
1123 if (itd
->name
) g_pattern_spec_free(itd
->name
);
1124 if (itd
->role
) g_pattern_spec_free(itd
->role
);
1125 if (itd
->title
) g_pattern_spec_free(itd
->title
);
1126 if (itd
->class) g_pattern_spec_free(itd
->class);
1127 g_slice_free(ObAppSettings
, it
->data
);
1129 g_slist_free(config_per_app_settings
);