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 g_message(_("Invalid context \"%s\" in mouse binding"),
499 nbut
= obt_xml_find_node(n
->children
, "mousebind");
501 if (!obt_xml_attr_string(nbut
, "button", &buttonstr
))
503 if (obt_xml_attr_contains(nbut
, "action", "press"))
504 mact
= OB_MOUSE_ACTION_PRESS
;
505 else if (obt_xml_attr_contains(nbut
, "action", "release"))
506 mact
= OB_MOUSE_ACTION_RELEASE
;
507 else if (obt_xml_attr_contains(nbut
, "action", "click"))
508 mact
= OB_MOUSE_ACTION_CLICK
;
509 else if (obt_xml_attr_contains(nbut
, "action","doubleclick"))
510 mact
= OB_MOUSE_ACTION_DOUBLE_CLICK
;
511 else if (obt_xml_attr_contains(nbut
, "action", "drag"))
512 mact
= OB_MOUSE_ACTION_MOTION
;
516 nact
= obt_xml_find_node(nbut
->children
, "action");
518 ObActionsAct
*action
;
520 if ((action
= actions_parse(nact
)))
521 mouse_bind(buttonstr
, cx
, mact
, action
);
522 nact
= obt_xml_find_node(nact
->next
, "action");
526 nbut
= obt_xml_find_node(nbut
->next
, "mousebind");
532 n
= obt_xml_find_node(n
->next
, "context");
536 static void parse_focus(xmlNodePtr node
, gpointer d
)
540 node
= node
->children
;
542 if ((n
= obt_xml_find_node(node
, "focusNew")))
543 config_focus_new
= obt_xml_node_bool(n
);
544 if ((n
= obt_xml_find_node(node
, "followMouse")))
545 config_focus_follow
= obt_xml_node_bool(n
);
546 if ((n
= obt_xml_find_node(node
, "focusDelay")))
547 config_focus_delay
= obt_xml_node_int(n
);
548 if ((n
= obt_xml_find_node(node
, "raiseOnFocus")))
549 config_focus_raise
= obt_xml_node_bool(n
);
550 if ((n
= obt_xml_find_node(node
, "focusLast")))
551 config_focus_last
= obt_xml_node_bool(n
);
552 if ((n
= obt_xml_find_node(node
, "underMouse")))
553 config_focus_under_mouse
= obt_xml_node_bool(n
);
554 if ((n
= obt_xml_find_node(node
, "unfocusOnLeave")))
555 config_unfocus_leave
= obt_xml_node_bool(n
);
558 static void parse_placement(xmlNodePtr node
, gpointer d
)
562 node
= node
->children
;
564 if ((n
= obt_xml_find_node(node
, "policy")))
565 if (obt_xml_node_contains(n
, "UnderMouse"))
566 config_place_policy
= OB_PLACE_POLICY_MOUSE
;
567 if ((n
= obt_xml_find_node(node
, "center")))
568 config_place_center
= obt_xml_node_bool(n
);
569 if ((n
= obt_xml_find_node(node
, "monitor"))) {
570 if (obt_xml_node_contains(n
, "active"))
571 config_place_monitor
= OB_PLACE_MONITOR_ACTIVE
;
572 else if (obt_xml_node_contains(n
, "mouse"))
573 config_place_monitor
= OB_PLACE_MONITOR_MOUSE
;
575 if ((n
= obt_xml_find_node(node
, "primaryMonitor"))) {
576 config_primary_monitor_index
= obt_xml_node_int(n
);
577 if (!config_primary_monitor_index
) {
578 if (obt_xml_node_contains(n
, "mouse"))
579 config_primary_monitor
= OB_PLACE_MONITOR_MOUSE
;
584 static void parse_margins(xmlNodePtr node
, gpointer d
)
588 node
= node
->children
;
590 if ((n
= obt_xml_find_node(node
, "top")))
591 config_margins
.top
= MAX(0, obt_xml_node_int(n
));
592 if ((n
= obt_xml_find_node(node
, "left")))
593 config_margins
.left
= MAX(0, obt_xml_node_int(n
));
594 if ((n
= obt_xml_find_node(node
, "right")))
595 config_margins
.right
= MAX(0, obt_xml_node_int(n
));
596 if ((n
= obt_xml_find_node(node
, "bottom")))
597 config_margins
.bottom
= MAX(0, obt_xml_node_int(n
));
600 static void parse_theme(xmlNodePtr node
, gpointer d
)
604 node
= node
->children
;
606 if ((n
= obt_xml_find_node(node
, "name"))) {
609 g_free(config_theme
);
610 c
= obt_xml_node_string(n
);
611 config_theme
= obt_paths_expand_tilde(c
);
614 if ((n
= obt_xml_find_node(node
, "titleLayout"))) {
617 g_free(config_title_layout
);
618 config_title_layout
= obt_xml_node_string(n
);
620 /* replace duplicates with spaces */
621 for (c
= config_title_layout
; *c
!= '\0'; ++c
)
622 for (d
= c
+1; *d
!= '\0'; ++d
)
623 if (*c
== *d
) *d
= ' ';
625 if ((n
= obt_xml_find_node(node
, "keepBorder")))
626 config_theme_keepborder
= obt_xml_node_bool(n
);
627 if ((n
= obt_xml_find_node(node
, "animateIconify")))
628 config_animate_iconify
= obt_xml_node_bool(n
);
629 if ((n
= obt_xml_find_node(node
, "windowListIconSize"))) {
630 config_theme_window_list_icon_size
= obt_xml_node_int(n
);
631 if (config_theme_window_list_icon_size
< 16)
632 config_theme_window_list_icon_size
= 16;
633 else if (config_theme_window_list_icon_size
> 96)
634 config_theme_window_list_icon_size
= 96;
637 n
= obt_xml_find_node(node
, "font");
641 gchar
*name
= g_strdup(RrDefaultFontFamily
);
642 gint size
= RrDefaultFontSize
;
643 RrFontWeight weight
= RrDefaultFontWeight
;
644 RrFontSlant slant
= RrDefaultFontSlant
;
646 if (obt_xml_attr_contains(n
, "place", "ActiveWindow"))
647 font
= &config_font_activewindow
;
648 else if (obt_xml_attr_contains(n
, "place", "InactiveWindow"))
649 font
= &config_font_inactivewindow
;
650 else if (obt_xml_attr_contains(n
, "place", "MenuHeader"))
651 font
= &config_font_menutitle
;
652 else if (obt_xml_attr_contains(n
, "place", "MenuItem"))
653 font
= &config_font_menuitem
;
654 else if (obt_xml_attr_contains(n
, "place", "ActiveOnScreenDisplay"))
655 font
= &config_font_activeosd
;
656 else if (obt_xml_attr_contains(n
, "place", "OnScreenDisplay"))
657 font
= &config_font_activeosd
;
658 else if (obt_xml_attr_contains(n
, "place","InactiveOnScreenDisplay"))
659 font
= &config_font_inactiveosd
;
663 if ((fnode
= obt_xml_find_node(n
->children
, "name"))) {
665 name
= obt_xml_node_string(fnode
);
667 if ((fnode
= obt_xml_find_node(n
->children
, "size"))) {
668 int s
= obt_xml_node_int(fnode
);
671 if ((fnode
= obt_xml_find_node(n
->children
, "weight"))) {
672 gchar
*w
= obt_xml_node_string(fnode
);
673 if (!g_ascii_strcasecmp(w
, "Bold"))
674 weight
= RR_FONTWEIGHT_BOLD
;
677 if ((fnode
= obt_xml_find_node(n
->children
, "slant"))) {
678 gchar
*s
= obt_xml_node_string(fnode
);
679 if (!g_ascii_strcasecmp(s
, "Italic"))
680 slant
= RR_FONTSLANT_ITALIC
;
681 if (!g_ascii_strcasecmp(s
, "Oblique"))
682 slant
= RR_FONTSLANT_OBLIQUE
;
686 *font
= RrFontOpen(ob_rr_inst
, name
, size
, weight
, slant
);
689 n
= obt_xml_find_node(n
->next
, "font");
693 static void parse_desktops(xmlNodePtr node
, gpointer d
)
697 node
= node
->children
;
699 if ((n
= obt_xml_find_node(node
, "number"))) {
700 gint d
= obt_xml_node_int(n
);
702 config_desktops_num
= (unsigned) d
;
704 if ((n
= obt_xml_find_node(node
, "firstdesk"))) {
705 gint d
= obt_xml_node_int(n
);
707 config_screen_firstdesk
= (unsigned) d
;
709 if ((n
= obt_xml_find_node(node
, "names"))) {
713 for (it
= config_desktops_names
; it
; it
= it
->next
)
715 g_slist_free(config_desktops_names
);
716 config_desktops_names
= NULL
;
718 nname
= obt_xml_find_node(n
->children
, "name");
720 config_desktops_names
=
721 g_slist_append(config_desktops_names
,
722 obt_xml_node_string(nname
));
723 nname
= obt_xml_find_node(nname
->next
, "name");
726 if ((n
= obt_xml_find_node(node
, "popupTime")))
727 config_desktop_popup_time
= obt_xml_node_int(n
);
730 static void parse_resize(xmlNodePtr node
, gpointer d
)
734 node
= node
->children
;
736 if ((n
= obt_xml_find_node(node
, "drawContents")))
737 config_resize_redraw
= obt_xml_node_bool(n
);
738 if ((n
= obt_xml_find_node(node
, "popupShow"))) {
739 config_resize_popup_show
= obt_xml_node_int(n
);
740 if (obt_xml_node_contains(n
, "Always"))
741 config_resize_popup_show
= 2;
742 else if (obt_xml_node_contains(n
, "Never"))
743 config_resize_popup_show
= 0;
744 else if (obt_xml_node_contains(n
, "Nonpixel"))
745 config_resize_popup_show
= 1;
747 if ((n
= obt_xml_find_node(node
, "popupPosition"))) {
748 if (obt_xml_node_contains(n
, "Top"))
749 config_resize_popup_pos
= OB_RESIZE_POS_TOP
;
750 else if (obt_xml_node_contains(n
, "Center"))
751 config_resize_popup_pos
= OB_RESIZE_POS_CENTER
;
752 else if (obt_xml_node_contains(n
, "Fixed")) {
753 config_resize_popup_pos
= OB_RESIZE_POS_FIXED
;
755 if ((n
= obt_xml_find_node(node
, "popupFixedPosition"))) {
758 if ((n2
= obt_xml_find_node(n
->children
, "x")))
759 config_parse_gravity_coord(n2
,
760 &config_resize_popup_fixed
.x
);
761 if ((n2
= obt_xml_find_node(n
->children
, "y")))
762 config_parse_gravity_coord(n2
,
763 &config_resize_popup_fixed
.y
);
765 config_resize_popup_fixed
.x
.pos
=
766 MAX(config_resize_popup_fixed
.x
.pos
, 0);
767 config_resize_popup_fixed
.y
.pos
=
768 MAX(config_resize_popup_fixed
.y
.pos
, 0);
774 static void parse_dock(xmlNodePtr node
, gpointer d
)
778 node
= node
->children
;
780 if ((n
= obt_xml_find_node(node
, "position"))) {
781 if (obt_xml_node_contains(n
, "TopLeft"))
782 config_dock_floating
= FALSE
,
783 config_dock_pos
= OB_DIRECTION_NORTHWEST
;
784 else if (obt_xml_node_contains(n
, "Top"))
785 config_dock_floating
= FALSE
,
786 config_dock_pos
= OB_DIRECTION_NORTH
;
787 else if (obt_xml_node_contains(n
, "TopRight"))
788 config_dock_floating
= FALSE
,
789 config_dock_pos
= OB_DIRECTION_NORTHEAST
;
790 else if (obt_xml_node_contains(n
, "Right"))
791 config_dock_floating
= FALSE
,
792 config_dock_pos
= OB_DIRECTION_EAST
;
793 else if (obt_xml_node_contains(n
, "BottomRight"))
794 config_dock_floating
= FALSE
,
795 config_dock_pos
= OB_DIRECTION_SOUTHEAST
;
796 else if (obt_xml_node_contains(n
, "Bottom"))
797 config_dock_floating
= FALSE
,
798 config_dock_pos
= OB_DIRECTION_SOUTH
;
799 else if (obt_xml_node_contains(n
, "BottomLeft"))
800 config_dock_floating
= FALSE
,
801 config_dock_pos
= OB_DIRECTION_SOUTHWEST
;
802 else if (obt_xml_node_contains(n
, "Left"))
803 config_dock_floating
= FALSE
,
804 config_dock_pos
= OB_DIRECTION_WEST
;
805 else if (obt_xml_node_contains(n
, "Floating"))
806 config_dock_floating
= TRUE
;
808 if (config_dock_floating
) {
809 if ((n
= obt_xml_find_node(node
, "floatingX")))
810 config_dock_x
= obt_xml_node_int(n
);
811 if ((n
= obt_xml_find_node(node
, "floatingY")))
812 config_dock_y
= obt_xml_node_int(n
);
814 if ((n
= obt_xml_find_node(node
, "noStrut")))
815 config_dock_nostrut
= obt_xml_node_bool(n
);
817 if ((n
= obt_xml_find_node(node
, "stacking"))) {
818 if (obt_xml_node_contains(n
, "normal"))
819 config_dock_layer
= OB_STACKING_LAYER_NORMAL
;
820 else if (obt_xml_node_contains(n
, "below"))
821 config_dock_layer
= OB_STACKING_LAYER_BELOW
;
822 else if (obt_xml_node_contains(n
, "above"))
823 config_dock_layer
= OB_STACKING_LAYER_ABOVE
;
825 if ((n
= obt_xml_find_node(node
, "direction"))) {
826 if (obt_xml_node_contains(n
, "horizontal"))
827 config_dock_orient
= OB_ORIENTATION_HORZ
;
828 else if (obt_xml_node_contains(n
, "vertical"))
829 config_dock_orient
= OB_ORIENTATION_VERT
;
831 if ((n
= obt_xml_find_node(node
, "autoHide")))
832 config_dock_hide
= obt_xml_node_bool(n
);
833 if ((n
= obt_xml_find_node(node
, "hideDelay")))
834 config_dock_hide_delay
= obt_xml_node_int(n
);
835 if ((n
= obt_xml_find_node(node
, "showDelay")))
836 config_dock_show_delay
= obt_xml_node_int(n
);
837 if ((n
= obt_xml_find_node(node
, "moveButton"))) {
838 gchar
*str
= obt_xml_node_string(n
);
840 if (translate_button(str
, &s
, &b
)) {
841 config_dock_app_move_button
= b
;
842 config_dock_app_move_modifiers
= s
;
844 g_message(_("Invalid button \"%s\" specified in config file"), str
);
850 static void parse_menu(xmlNodePtr node
, gpointer d
)
853 node
= node
->children
;
855 if ((n
= obt_xml_find_node(node
, "hideDelay")))
856 config_menu_hide_delay
= obt_xml_node_int(n
);
857 if ((n
= obt_xml_find_node(node
, "middle")))
858 config_menu_middle
= obt_xml_node_bool(n
);
859 if ((n
= obt_xml_find_node(node
, "submenuShowDelay")))
860 config_submenu_show_delay
= obt_xml_node_int(n
);
861 if ((n
= obt_xml_find_node(node
, "submenuHideDelay")))
862 config_submenu_hide_delay
= obt_xml_node_int(n
);
863 if ((n
= obt_xml_find_node(node
, "manageDesktops")))
864 config_menu_manage_desktops
= obt_xml_node_bool(n
);
865 if ((n
= obt_xml_find_node(node
, "showIcons"))) {
866 config_menu_show_icons
= obt_xml_node_bool(n
);
868 if (config_menu_show_icons
)
869 g_message(_("Openbox was compiled without Imlib2 image loading support. Icons in menus will not be loaded."));
873 while ((node
= obt_xml_find_node(node
, "file"))) {
874 gchar
*c
= obt_xml_node_string(node
);
875 config_menu_files
= g_slist_append(config_menu_files
,
876 obt_paths_expand_tilde(c
));
882 static void parse_resistance(xmlNodePtr node
, gpointer d
)
886 node
= node
->children
;
887 if ((n
= obt_xml_find_node(node
, "strength")))
888 config_resist_win
= obt_xml_node_int(n
);
889 if ((n
= obt_xml_find_node(node
, "screen_edge_strength")))
890 config_resist_edge
= obt_xml_node_int(n
);
896 const gchar
*actname
;
899 static void bind_default_keyboard(void)
902 ObDefKeyBind binds
[] = {
903 { "A-Tab", "NextWindow" },
904 { "S-A-Tab", "PreviousWindow" },
908 for (it
= binds
; it
->key
; ++it
) {
909 GList
*l
= g_list_append(NULL
, g_strdup(it
->key
));
910 keyboard_bind(l
, actions_parse_string(it
->actname
));
917 const gchar
*context
;
918 const ObMouseAction mact
;
919 const gchar
*actname
;
922 static void bind_default_mouse(void)
925 ObDefMouseBind binds
[] = {
926 { "Left", "Client", OB_MOUSE_ACTION_PRESS
, "Focus" },
927 { "Middle", "Client", OB_MOUSE_ACTION_PRESS
, "Focus" },
928 { "Right", "Client", OB_MOUSE_ACTION_PRESS
, "Focus" },
929 { "Left", "Desktop", OB_MOUSE_ACTION_PRESS
, "Focus" },
930 { "Middle", "Desktop", OB_MOUSE_ACTION_PRESS
, "Focus" },
931 { "Right", "Desktop", OB_MOUSE_ACTION_PRESS
, "Focus" },
932 { "Left", "Titlebar", OB_MOUSE_ACTION_PRESS
, "Focus" },
933 { "Left", "Bottom", OB_MOUSE_ACTION_PRESS
, "Focus" },
934 { "Left", "BLCorner", OB_MOUSE_ACTION_PRESS
, "Focus" },
935 { "Left", "BRCorner", OB_MOUSE_ACTION_PRESS
, "Focus" },
936 { "Left", "TLCorner", OB_MOUSE_ACTION_PRESS
, "Focus" },
937 { "Left", "TRCorner", OB_MOUSE_ACTION_PRESS
, "Focus" },
938 { "Left", "Close", OB_MOUSE_ACTION_PRESS
, "Focus" },
939 { "Left", "Maximize", OB_MOUSE_ACTION_PRESS
, "Focus" },
940 { "Left", "Iconify", OB_MOUSE_ACTION_PRESS
, "Focus" },
941 { "Left", "Icon", OB_MOUSE_ACTION_PRESS
, "Focus" },
942 { "Left", "AllDesktops", OB_MOUSE_ACTION_PRESS
, "Focus" },
943 { "Left", "Shade", OB_MOUSE_ACTION_PRESS
, "Focus" },
944 { "Left", "Client", OB_MOUSE_ACTION_CLICK
, "Raise" },
945 { "Left", "Titlebar", OB_MOUSE_ACTION_CLICK
, "Raise" },
946 { "Middle", "Titlebar", OB_MOUSE_ACTION_CLICK
, "Lower" },
947 { "Left", "BLCorner", OB_MOUSE_ACTION_CLICK
, "Raise" },
948 { "Left", "BRCorner", OB_MOUSE_ACTION_CLICK
, "Raise" },
949 { "Left", "TLCorner", OB_MOUSE_ACTION_CLICK
, "Raise" },
950 { "Left", "TRCorner", OB_MOUSE_ACTION_CLICK
, "Raise" },
951 { "Left", "Close", OB_MOUSE_ACTION_CLICK
, "Raise" },
952 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK
, "Raise" },
953 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK
, "Raise" },
954 { "Left", "Icon", OB_MOUSE_ACTION_CLICK
, "Raise" },
955 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK
, "Raise" },
956 { "Left", "Shade", OB_MOUSE_ACTION_CLICK
, "Raise" },
957 { "Left", "Close", OB_MOUSE_ACTION_CLICK
, "Close" },
958 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK
, "ToggleMaximize" },
959 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK
, "Iconify" },
960 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK
, "ToggleOmnipresent" },
961 { "Left", "Shade", OB_MOUSE_ACTION_CLICK
, "ToggleShade" },
962 { "Left", "TLCorner", OB_MOUSE_ACTION_MOTION
, "Resize" },
963 { "Left", "TRCorner", OB_MOUSE_ACTION_MOTION
, "Resize" },
964 { "Left", "BLCorner", OB_MOUSE_ACTION_MOTION
, "Resize" },
965 { "Left", "BRCorner", OB_MOUSE_ACTION_MOTION
, "Resize" },
966 { "Left", "Top", OB_MOUSE_ACTION_MOTION
, "Resize" },
967 { "Left", "Bottom", OB_MOUSE_ACTION_MOTION
, "Resize" },
968 { "Left", "Left", OB_MOUSE_ACTION_MOTION
, "Resize" },
969 { "Left", "Right", OB_MOUSE_ACTION_MOTION
, "Resize" },
970 { "Left", "Titlebar", OB_MOUSE_ACTION_MOTION
, "Move" },
971 { "A-Left", "Frame", OB_MOUSE_ACTION_MOTION
, "Move" },
972 { "A-Middle", "Frame", OB_MOUSE_ACTION_MOTION
, "Resize" },
973 { NULL
, NULL
, 0, NULL
}
976 for (it
= binds
; it
->button
; ++it
)
977 mouse_bind(it
->button
, frame_context_from_string(it
->context
),
978 it
->mact
, actions_parse_string(it
->actname
));
981 void config_startup(ObtXmlInst
*i
)
983 config_focus_new
= TRUE
;
984 config_focus_follow
= FALSE
;
985 config_focus_delay
= 0;
986 config_focus_raise
= FALSE
;
987 config_focus_last
= TRUE
;
988 config_focus_under_mouse
= FALSE
;
989 config_unfocus_leave
= FALSE
;
991 obt_xml_register(i
, "focus", parse_focus
, NULL
);
993 config_place_policy
= OB_PLACE_POLICY_SMART
;
994 config_place_center
= TRUE
;
995 config_place_monitor
= OB_PLACE_MONITOR_ANY
;
997 config_primary_monitor_index
= 1;
998 config_primary_monitor
= OB_PLACE_MONITOR_ACTIVE
;
1000 obt_xml_register(i
, "placement", parse_placement
, NULL
);
1002 STRUT_PARTIAL_SET(config_margins
, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1004 obt_xml_register(i
, "margins", parse_margins
, NULL
);
1006 config_theme
= NULL
;
1008 config_animate_iconify
= TRUE
;
1009 config_title_layout
= g_strdup("NLIMC");
1010 config_theme_keepborder
= TRUE
;
1011 config_theme_window_list_icon_size
= 36;
1013 config_font_activewindow
= NULL
;
1014 config_font_inactivewindow
= NULL
;
1015 config_font_menuitem
= NULL
;
1016 config_font_menutitle
= NULL
;
1017 config_font_activeosd
= NULL
;
1018 config_font_inactiveosd
= NULL
;
1020 obt_xml_register(i
, "theme", parse_theme
, NULL
);
1022 config_desktops_num
= 4;
1023 config_screen_firstdesk
= 1;
1024 config_desktops_names
= NULL
;
1025 config_desktop_popup_time
= 875;
1027 obt_xml_register(i
, "desktops", parse_desktops
, NULL
);
1029 config_resize_redraw
= TRUE
;
1030 config_resize_popup_show
= 1; /* nonpixel increments */
1031 config_resize_popup_pos
= OB_RESIZE_POS_CENTER
;
1032 GRAVITY_COORD_SET(config_resize_popup_fixed
.x
, 0, FALSE
, FALSE
);
1033 GRAVITY_COORD_SET(config_resize_popup_fixed
.y
, 0, FALSE
, FALSE
);
1035 obt_xml_register(i
, "resize", parse_resize
, NULL
);
1037 config_dock_layer
= OB_STACKING_LAYER_ABOVE
;
1038 config_dock_pos
= OB_DIRECTION_NORTHEAST
;
1039 config_dock_floating
= FALSE
;
1040 config_dock_nostrut
= FALSE
;
1043 config_dock_orient
= OB_ORIENTATION_VERT
;
1044 config_dock_hide
= FALSE
;
1045 config_dock_hide_delay
= 300;
1046 config_dock_show_delay
= 300;
1047 config_dock_app_move_button
= 2; /* middle */
1048 config_dock_app_move_modifiers
= 0;
1050 obt_xml_register(i
, "dock", parse_dock
, NULL
);
1052 translate_key("C-g", &config_keyboard_reset_state
,
1053 &config_keyboard_reset_keycode
);
1055 bind_default_keyboard();
1057 obt_xml_register(i
, "keyboard", parse_keyboard
, NULL
);
1059 config_mouse_threshold
= 8;
1060 config_mouse_dclicktime
= 200;
1061 config_mouse_screenedgetime
= 400;
1062 config_mouse_screenedgewarp
= FALSE
;
1064 bind_default_mouse();
1066 obt_xml_register(i
, "mouse", parse_mouse
, NULL
);
1068 config_resist_win
= 10;
1069 config_resist_edge
= 20;
1071 obt_xml_register(i
, "resistance", parse_resistance
, NULL
);
1073 config_menu_hide_delay
= 250;
1074 config_menu_middle
= FALSE
;
1075 config_submenu_show_delay
= 100;
1076 config_submenu_hide_delay
= 400;
1077 config_menu_manage_desktops
= TRUE
;
1078 config_menu_files
= NULL
;
1079 config_menu_show_icons
= TRUE
;
1081 obt_xml_register(i
, "menu", parse_menu
, NULL
);
1083 config_per_app_settings
= NULL
;
1085 obt_xml_register(i
, "applications", parse_per_app_settings
, NULL
);
1088 void config_shutdown(void)
1092 g_free(config_theme
);
1094 g_free(config_title_layout
);
1096 RrFontClose(config_font_activewindow
);
1097 RrFontClose(config_font_inactivewindow
);
1098 RrFontClose(config_font_menuitem
);
1099 RrFontClose(config_font_menutitle
);
1100 RrFontClose(config_font_activeosd
);
1101 RrFontClose(config_font_inactiveosd
);
1103 for (it
= config_desktops_names
; it
; it
= g_slist_next(it
))
1105 g_slist_free(config_desktops_names
);
1107 for (it
= config_menu_files
; it
; it
= g_slist_next(it
))
1109 g_slist_free(config_menu_files
);
1111 for (it
= config_per_app_settings
; it
; it
= g_slist_next(it
)) {
1112 ObAppSettings
*itd
= (ObAppSettings
*)it
->data
;
1113 if (itd
->name
) g_pattern_spec_free(itd
->name
);
1114 if (itd
->role
) g_pattern_spec_free(itd
->role
);
1115 if (itd
->title
) g_pattern_spec_free(itd
->title
);
1116 if (itd
->class) g_pattern_spec_free(itd
->class);
1117 g_slice_free(ObAppSettings
, it
->data
);
1119 g_slist_free(config_per_app_settings
);