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
);
374 name
= class = role
= title
= type_str
= NULL
;
377 app
= obt_xml_find_node(app
->next
, "application");
384 <action name="ChangeDesktop">
391 static void parse_key(xmlNodePtr node
, GList
*keylist
)
393 gchar
*keystring
, **keys
, **key
;
395 gboolean is_chroot
= FALSE
;
397 if (!obt_xml_attr_string(node
, "key", &keystring
))
400 obt_xml_attr_bool(node
, "chroot", &is_chroot
);
402 keys
= g_strsplit(keystring
, " ", 0);
403 for (key
= keys
; *key
; ++key
) {
404 keylist
= g_list_append(keylist
, *key
);
406 if ((n
= obt_xml_find_node(node
->children
, "keybind"))) {
408 parse_key(n
, keylist
);
409 n
= obt_xml_find_node(n
->next
, "keybind");
412 else if ((n
= obt_xml_find_node(node
->children
, "action"))) {
414 ObActionsAct
*action
;
416 action
= actions_parse(n
);
418 keyboard_bind(keylist
, action
);
419 n
= obt_xml_find_node(n
->next
, "action");
425 keyboard_chroot(keylist
);
426 keylist
= g_list_delete_link(keylist
, g_list_last(keylist
));
433 static void parse_keyboard(xmlNodePtr node
, gpointer d
)
438 keyboard_unbind_all();
440 if ((n
= obt_xml_find_node(node
->children
, "chainQuitKey"))) {
441 key
= obt_xml_node_string(n
);
442 translate_key(key
, &config_keyboard_reset_state
,
443 &config_keyboard_reset_keycode
);
447 if ((n
= obt_xml_find_node(node
->children
, "keybind")))
450 n
= obt_xml_find_node(n
->next
, "keybind");
456 <context name="Titlebar">
457 <mousebind button="Left" action="Press">
458 <action name="Raise"></action>
464 static void parse_mouse(xmlNodePtr node
, gpointer d
)
466 xmlNodePtr n
, nbut
, nact
;
473 node
= node
->children
;
475 if ((n
= obt_xml_find_node(node
, "dragThreshold")))
476 config_mouse_threshold
= obt_xml_node_int(n
);
477 if ((n
= obt_xml_find_node(node
, "doubleClickTime")))
478 config_mouse_dclicktime
= obt_xml_node_int(n
);
479 if ((n
= obt_xml_find_node(node
, "screenEdgeWarpTime"))) {
480 config_mouse_screenedgetime
= obt_xml_node_int(n
);
481 /* minimum value of 25 for this property, when it is 1 and you hit the
482 edge it basically never stops */
483 if (config_mouse_screenedgetime
&& config_mouse_screenedgetime
< 25)
484 config_mouse_screenedgetime
= 25;
486 if ((n
= obt_xml_find_node(node
, "screenEdgeWarpMouse")))
487 config_mouse_screenedgewarp
= obt_xml_node_bool(n
);
489 n
= obt_xml_find_node(node
, "context");
494 if (!obt_xml_attr_string(n
, "name", &cxstr
))
497 modcxstr
= g_strdup(cxstr
); /* make a copy to mutilate */
498 while (frame_next_context_from_string(modcxstr
, &cx
)) {
500 gchar
*s
= strchr(modcxstr
, ' ');
503 g_message(_("Invalid context \"%s\" in mouse binding"),
510 nbut
= obt_xml_find_node(n
->children
, "mousebind");
512 if (!obt_xml_attr_string(nbut
, "button", &buttonstr
))
514 if (obt_xml_attr_contains(nbut
, "action", "press"))
515 mact
= OB_MOUSE_ACTION_PRESS
;
516 else if (obt_xml_attr_contains(nbut
, "action", "release"))
517 mact
= OB_MOUSE_ACTION_RELEASE
;
518 else if (obt_xml_attr_contains(nbut
, "action", "click"))
519 mact
= OB_MOUSE_ACTION_CLICK
;
520 else if (obt_xml_attr_contains(nbut
, "action","doubleclick"))
521 mact
= OB_MOUSE_ACTION_DOUBLE_CLICK
;
522 else if (obt_xml_attr_contains(nbut
, "action", "drag"))
523 mact
= OB_MOUSE_ACTION_MOTION
;
527 nact
= obt_xml_find_node(nbut
->children
, "action");
529 ObActionsAct
*action
;
531 if ((action
= actions_parse(nact
)))
532 mouse_bind(buttonstr
, cx
, mact
, action
);
533 nact
= obt_xml_find_node(nact
->next
, "action");
537 nbut
= obt_xml_find_node(nbut
->next
, "mousebind");
543 n
= obt_xml_find_node(n
->next
, "context");
547 static void parse_focus(xmlNodePtr node
, gpointer d
)
551 node
= node
->children
;
553 if ((n
= obt_xml_find_node(node
, "focusNew")))
554 config_focus_new
= obt_xml_node_bool(n
);
555 if ((n
= obt_xml_find_node(node
, "followMouse")))
556 config_focus_follow
= obt_xml_node_bool(n
);
557 if ((n
= obt_xml_find_node(node
, "focusDelay")))
558 config_focus_delay
= obt_xml_node_int(n
);
559 if ((n
= obt_xml_find_node(node
, "raiseOnFocus")))
560 config_focus_raise
= obt_xml_node_bool(n
);
561 if ((n
= obt_xml_find_node(node
, "focusLast")))
562 config_focus_last
= obt_xml_node_bool(n
);
563 if ((n
= obt_xml_find_node(node
, "underMouse")))
564 config_focus_under_mouse
= obt_xml_node_bool(n
);
565 if ((n
= obt_xml_find_node(node
, "unfocusOnLeave")))
566 config_unfocus_leave
= obt_xml_node_bool(n
);
569 static void parse_placement(xmlNodePtr node
, gpointer d
)
573 node
= node
->children
;
575 if ((n
= obt_xml_find_node(node
, "policy")))
576 if (obt_xml_node_contains(n
, "UnderMouse"))
577 config_place_policy
= OB_PLACE_POLICY_MOUSE
;
578 if ((n
= obt_xml_find_node(node
, "center")))
579 config_place_center
= obt_xml_node_bool(n
);
580 if ((n
= obt_xml_find_node(node
, "monitor"))) {
581 if (obt_xml_node_contains(n
, "active"))
582 config_place_monitor
= OB_PLACE_MONITOR_ACTIVE
;
583 else if (obt_xml_node_contains(n
, "mouse"))
584 config_place_monitor
= OB_PLACE_MONITOR_MOUSE
;
585 else if (obt_xml_node_contains(n
, "any"))
586 config_place_monitor
= OB_PLACE_MONITOR_ANY
;
588 if ((n
= obt_xml_find_node(node
, "primaryMonitor"))) {
589 config_primary_monitor_index
= obt_xml_node_int(n
);
590 if (!config_primary_monitor_index
) {
591 if (obt_xml_node_contains(n
, "mouse"))
592 config_primary_monitor
= OB_PLACE_MONITOR_MOUSE
;
597 static void parse_margins(xmlNodePtr node
, gpointer d
)
601 node
= node
->children
;
603 if ((n
= obt_xml_find_node(node
, "top")))
604 config_margins
.top
= MAX(0, obt_xml_node_int(n
));
605 if ((n
= obt_xml_find_node(node
, "left")))
606 config_margins
.left
= MAX(0, obt_xml_node_int(n
));
607 if ((n
= obt_xml_find_node(node
, "right")))
608 config_margins
.right
= MAX(0, obt_xml_node_int(n
));
609 if ((n
= obt_xml_find_node(node
, "bottom")))
610 config_margins
.bottom
= MAX(0, obt_xml_node_int(n
));
613 static void parse_theme(xmlNodePtr node
, gpointer d
)
617 node
= node
->children
;
619 if ((n
= obt_xml_find_node(node
, "name"))) {
622 g_free(config_theme
);
623 c
= obt_xml_node_string(n
);
624 config_theme
= obt_paths_expand_tilde(c
);
627 if ((n
= obt_xml_find_node(node
, "titleLayout"))) {
630 g_free(config_title_layout
);
631 config_title_layout
= obt_xml_node_string(n
);
633 /* replace duplicates with spaces */
634 for (c
= config_title_layout
; *c
!= '\0'; ++c
)
635 for (d
= c
+1; *d
!= '\0'; ++d
)
636 if (*c
== *d
) *d
= ' ';
638 if ((n
= obt_xml_find_node(node
, "keepBorder")))
639 config_theme_keepborder
= obt_xml_node_bool(n
);
640 if ((n
= obt_xml_find_node(node
, "animateIconify")))
641 config_animate_iconify
= obt_xml_node_bool(n
);
642 if ((n
= obt_xml_find_node(node
, "windowListIconSize"))) {
643 config_theme_window_list_icon_size
= obt_xml_node_int(n
);
644 if (config_theme_window_list_icon_size
< 16)
645 config_theme_window_list_icon_size
= 16;
646 else if (config_theme_window_list_icon_size
> 96)
647 config_theme_window_list_icon_size
= 96;
650 n
= obt_xml_find_node(node
, "font");
654 gchar
*name
= g_strdup(RrDefaultFontFamily
);
655 gint size
= RrDefaultFontSize
;
656 RrFontWeight weight
= RrDefaultFontWeight
;
657 RrFontSlant slant
= RrDefaultFontSlant
;
659 if (obt_xml_attr_contains(n
, "place", "ActiveWindow"))
660 font
= &config_font_activewindow
;
661 else if (obt_xml_attr_contains(n
, "place", "InactiveWindow"))
662 font
= &config_font_inactivewindow
;
663 else if (obt_xml_attr_contains(n
, "place", "MenuHeader"))
664 font
= &config_font_menutitle
;
665 else if (obt_xml_attr_contains(n
, "place", "MenuItem"))
666 font
= &config_font_menuitem
;
667 else if (obt_xml_attr_contains(n
, "place", "ActiveOnScreenDisplay"))
668 font
= &config_font_activeosd
;
669 else if (obt_xml_attr_contains(n
, "place", "OnScreenDisplay"))
670 font
= &config_font_activeosd
;
671 else if (obt_xml_attr_contains(n
, "place","InactiveOnScreenDisplay"))
672 font
= &config_font_inactiveosd
;
676 if ((fnode
= obt_xml_find_node(n
->children
, "name"))) {
678 name
= obt_xml_node_string(fnode
);
680 if ((fnode
= obt_xml_find_node(n
->children
, "size"))) {
681 int s
= obt_xml_node_int(fnode
);
684 if ((fnode
= obt_xml_find_node(n
->children
, "weight"))) {
685 gchar
*w
= obt_xml_node_string(fnode
);
686 if (!g_ascii_strcasecmp(w
, "Bold"))
687 weight
= RR_FONTWEIGHT_BOLD
;
690 if ((fnode
= obt_xml_find_node(n
->children
, "slant"))) {
691 gchar
*s
= obt_xml_node_string(fnode
);
692 if (!g_ascii_strcasecmp(s
, "Italic"))
693 slant
= RR_FONTSLANT_ITALIC
;
694 if (!g_ascii_strcasecmp(s
, "Oblique"))
695 slant
= RR_FONTSLANT_OBLIQUE
;
699 *font
= RrFontOpen(ob_rr_inst
, name
, size
, weight
, slant
);
702 n
= obt_xml_find_node(n
->next
, "font");
706 static void parse_desktops(xmlNodePtr node
, gpointer d
)
710 node
= node
->children
;
712 if ((n
= obt_xml_find_node(node
, "number"))) {
713 gint d
= obt_xml_node_int(n
);
715 config_desktops_num
= (unsigned) d
;
717 if ((n
= obt_xml_find_node(node
, "firstdesk"))) {
718 gint d
= obt_xml_node_int(n
);
720 config_screen_firstdesk
= (unsigned) d
;
722 if ((n
= obt_xml_find_node(node
, "names"))) {
726 for (it
= config_desktops_names
; it
; it
= it
->next
)
728 g_slist_free(config_desktops_names
);
729 config_desktops_names
= NULL
;
731 nname
= obt_xml_find_node(n
->children
, "name");
733 config_desktops_names
=
734 g_slist_append(config_desktops_names
,
735 obt_xml_node_string(nname
));
736 nname
= obt_xml_find_node(nname
->next
, "name");
739 if ((n
= obt_xml_find_node(node
, "popupTime")))
740 config_desktop_popup_time
= obt_xml_node_int(n
);
743 static void parse_resize(xmlNodePtr node
, gpointer d
)
747 node
= node
->children
;
749 if ((n
= obt_xml_find_node(node
, "drawContents")))
750 config_resize_redraw
= obt_xml_node_bool(n
);
751 if ((n
= obt_xml_find_node(node
, "popupShow"))) {
752 config_resize_popup_show
= obt_xml_node_int(n
);
753 if (obt_xml_node_contains(n
, "Always"))
754 config_resize_popup_show
= 2;
755 else if (obt_xml_node_contains(n
, "Never"))
756 config_resize_popup_show
= 0;
757 else if (obt_xml_node_contains(n
, "Nonpixel"))
758 config_resize_popup_show
= 1;
760 if ((n
= obt_xml_find_node(node
, "popupPosition"))) {
761 if (obt_xml_node_contains(n
, "Top"))
762 config_resize_popup_pos
= OB_RESIZE_POS_TOP
;
763 else if (obt_xml_node_contains(n
, "Center"))
764 config_resize_popup_pos
= OB_RESIZE_POS_CENTER
;
765 else if (obt_xml_node_contains(n
, "Fixed")) {
766 config_resize_popup_pos
= OB_RESIZE_POS_FIXED
;
768 if ((n
= obt_xml_find_node(node
, "popupFixedPosition"))) {
771 if ((n2
= obt_xml_find_node(n
->children
, "x")))
772 config_parse_gravity_coord(n2
,
773 &config_resize_popup_fixed
.x
);
774 if ((n2
= obt_xml_find_node(n
->children
, "y")))
775 config_parse_gravity_coord(n2
,
776 &config_resize_popup_fixed
.y
);
778 config_resize_popup_fixed
.x
.pos
=
779 MAX(config_resize_popup_fixed
.x
.pos
, 0);
780 config_resize_popup_fixed
.y
.pos
=
781 MAX(config_resize_popup_fixed
.y
.pos
, 0);
787 static void parse_dock(xmlNodePtr node
, gpointer d
)
791 node
= node
->children
;
793 if ((n
= obt_xml_find_node(node
, "position"))) {
794 if (obt_xml_node_contains(n
, "TopLeft"))
795 config_dock_floating
= FALSE
,
796 config_dock_pos
= OB_DIRECTION_NORTHWEST
;
797 else if (obt_xml_node_contains(n
, "Top"))
798 config_dock_floating
= FALSE
,
799 config_dock_pos
= OB_DIRECTION_NORTH
;
800 else if (obt_xml_node_contains(n
, "TopRight"))
801 config_dock_floating
= FALSE
,
802 config_dock_pos
= OB_DIRECTION_NORTHEAST
;
803 else if (obt_xml_node_contains(n
, "Right"))
804 config_dock_floating
= FALSE
,
805 config_dock_pos
= OB_DIRECTION_EAST
;
806 else if (obt_xml_node_contains(n
, "BottomRight"))
807 config_dock_floating
= FALSE
,
808 config_dock_pos
= OB_DIRECTION_SOUTHEAST
;
809 else if (obt_xml_node_contains(n
, "Bottom"))
810 config_dock_floating
= FALSE
,
811 config_dock_pos
= OB_DIRECTION_SOUTH
;
812 else if (obt_xml_node_contains(n
, "BottomLeft"))
813 config_dock_floating
= FALSE
,
814 config_dock_pos
= OB_DIRECTION_SOUTHWEST
;
815 else if (obt_xml_node_contains(n
, "Left"))
816 config_dock_floating
= FALSE
,
817 config_dock_pos
= OB_DIRECTION_WEST
;
818 else if (obt_xml_node_contains(n
, "Floating"))
819 config_dock_floating
= TRUE
;
821 if (config_dock_floating
) {
822 if ((n
= obt_xml_find_node(node
, "floatingX")))
823 config_dock_x
= obt_xml_node_int(n
);
824 if ((n
= obt_xml_find_node(node
, "floatingY")))
825 config_dock_y
= obt_xml_node_int(n
);
827 if ((n
= obt_xml_find_node(node
, "noStrut")))
828 config_dock_nostrut
= obt_xml_node_bool(n
);
830 if ((n
= obt_xml_find_node(node
, "stacking"))) {
831 if (obt_xml_node_contains(n
, "normal"))
832 config_dock_layer
= OB_STACKING_LAYER_NORMAL
;
833 else if (obt_xml_node_contains(n
, "below"))
834 config_dock_layer
= OB_STACKING_LAYER_BELOW
;
835 else if (obt_xml_node_contains(n
, "above"))
836 config_dock_layer
= OB_STACKING_LAYER_ABOVE
;
838 if ((n
= obt_xml_find_node(node
, "direction"))) {
839 if (obt_xml_node_contains(n
, "horizontal"))
840 config_dock_orient
= OB_ORIENTATION_HORZ
;
841 else if (obt_xml_node_contains(n
, "vertical"))
842 config_dock_orient
= OB_ORIENTATION_VERT
;
844 if ((n
= obt_xml_find_node(node
, "autoHide")))
845 config_dock_hide
= obt_xml_node_bool(n
);
846 if ((n
= obt_xml_find_node(node
, "hideDelay")))
847 config_dock_hide_delay
= obt_xml_node_int(n
);
848 if ((n
= obt_xml_find_node(node
, "showDelay")))
849 config_dock_show_delay
= obt_xml_node_int(n
);
850 if ((n
= obt_xml_find_node(node
, "moveButton"))) {
851 gchar
*str
= obt_xml_node_string(n
);
853 if (translate_button(str
, &s
, &b
)) {
854 config_dock_app_move_button
= b
;
855 config_dock_app_move_modifiers
= s
;
857 g_message(_("Invalid button \"%s\" specified in config file"), str
);
863 static void parse_menu(xmlNodePtr node
, gpointer d
)
866 node
= node
->children
;
868 if ((n
= obt_xml_find_node(node
, "hideDelay")))
869 config_menu_hide_delay
= obt_xml_node_int(n
);
870 if ((n
= obt_xml_find_node(node
, "middle")))
871 config_menu_middle
= obt_xml_node_bool(n
);
872 if ((n
= obt_xml_find_node(node
, "submenuShowDelay")))
873 config_submenu_show_delay
= obt_xml_node_int(n
);
874 if ((n
= obt_xml_find_node(node
, "submenuHideDelay")))
875 config_submenu_hide_delay
= obt_xml_node_int(n
);
876 if ((n
= obt_xml_find_node(node
, "manageDesktops")))
877 config_menu_manage_desktops
= obt_xml_node_bool(n
);
878 if ((n
= obt_xml_find_node(node
, "showIcons"))) {
879 config_menu_show_icons
= obt_xml_node_bool(n
);
881 if (config_menu_show_icons
)
882 g_message(_("Openbox was compiled without Imlib2 image loading support. Icons in menus will not be loaded."));
886 while ((node
= obt_xml_find_node(node
, "file"))) {
887 gchar
*c
= obt_xml_node_string(node
);
888 config_menu_files
= g_slist_append(config_menu_files
,
889 obt_paths_expand_tilde(c
));
895 static void parse_resistance(xmlNodePtr node
, gpointer d
)
899 node
= node
->children
;
900 if ((n
= obt_xml_find_node(node
, "strength")))
901 config_resist_win
= obt_xml_node_int(n
);
902 if ((n
= obt_xml_find_node(node
, "screen_edge_strength")))
903 config_resist_edge
= obt_xml_node_int(n
);
909 const gchar
*actname
;
912 static void bind_default_keyboard(void)
915 ObDefKeyBind binds
[] = {
916 { "A-Tab", "NextWindow" },
917 { "S-A-Tab", "PreviousWindow" },
921 for (it
= binds
; it
->key
; ++it
) {
922 GList
*l
= g_list_append(NULL
, g_strdup(it
->key
));
923 keyboard_bind(l
, actions_parse_string(it
->actname
));
930 const gchar
*context
;
931 const ObMouseAction mact
;
932 const gchar
*actname
;
935 static void bind_default_mouse(void)
938 ObDefMouseBind binds
[] = {
939 { "Left", "Client", OB_MOUSE_ACTION_PRESS
, "Focus" },
940 { "Middle", "Client", OB_MOUSE_ACTION_PRESS
, "Focus" },
941 { "Right", "Client", OB_MOUSE_ACTION_PRESS
, "Focus" },
942 { "Left", "Desktop", OB_MOUSE_ACTION_PRESS
, "Focus" },
943 { "Middle", "Desktop", OB_MOUSE_ACTION_PRESS
, "Focus" },
944 { "Right", "Desktop", OB_MOUSE_ACTION_PRESS
, "Focus" },
945 { "Left", "Titlebar", OB_MOUSE_ACTION_PRESS
, "Focus" },
946 { "Left", "Bottom", OB_MOUSE_ACTION_PRESS
, "Focus" },
947 { "Left", "BLCorner", OB_MOUSE_ACTION_PRESS
, "Focus" },
948 { "Left", "BRCorner", OB_MOUSE_ACTION_PRESS
, "Focus" },
949 { "Left", "TLCorner", OB_MOUSE_ACTION_PRESS
, "Focus" },
950 { "Left", "TRCorner", OB_MOUSE_ACTION_PRESS
, "Focus" },
951 { "Left", "Close", OB_MOUSE_ACTION_PRESS
, "Focus" },
952 { "Left", "Maximize", OB_MOUSE_ACTION_PRESS
, "Focus" },
953 { "Left", "Iconify", OB_MOUSE_ACTION_PRESS
, "Focus" },
954 { "Left", "Icon", OB_MOUSE_ACTION_PRESS
, "Focus" },
955 { "Left", "AllDesktops", OB_MOUSE_ACTION_PRESS
, "Focus" },
956 { "Left", "Shade", OB_MOUSE_ACTION_PRESS
, "Focus" },
957 { "Left", "Client", OB_MOUSE_ACTION_CLICK
, "Raise" },
958 { "Left", "Titlebar", OB_MOUSE_ACTION_CLICK
, "Raise" },
959 { "Middle", "Titlebar", OB_MOUSE_ACTION_CLICK
, "Lower" },
960 { "Left", "BLCorner", OB_MOUSE_ACTION_CLICK
, "Raise" },
961 { "Left", "BRCorner", OB_MOUSE_ACTION_CLICK
, "Raise" },
962 { "Left", "TLCorner", OB_MOUSE_ACTION_CLICK
, "Raise" },
963 { "Left", "TRCorner", OB_MOUSE_ACTION_CLICK
, "Raise" },
964 { "Left", "Close", OB_MOUSE_ACTION_CLICK
, "Raise" },
965 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK
, "Raise" },
966 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK
, "Raise" },
967 { "Left", "Icon", OB_MOUSE_ACTION_CLICK
, "Raise" },
968 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK
, "Raise" },
969 { "Left", "Shade", OB_MOUSE_ACTION_CLICK
, "Raise" },
970 { "Left", "Close", OB_MOUSE_ACTION_CLICK
, "Close" },
971 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK
, "ToggleMaximize" },
972 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK
, "Iconify" },
973 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK
, "ToggleOmnipresent" },
974 { "Left", "Shade", OB_MOUSE_ACTION_CLICK
, "ToggleShade" },
975 { "Left", "TLCorner", OB_MOUSE_ACTION_MOTION
, "Resize" },
976 { "Left", "TRCorner", OB_MOUSE_ACTION_MOTION
, "Resize" },
977 { "Left", "BLCorner", OB_MOUSE_ACTION_MOTION
, "Resize" },
978 { "Left", "BRCorner", OB_MOUSE_ACTION_MOTION
, "Resize" },
979 { "Left", "Top", OB_MOUSE_ACTION_MOTION
, "Resize" },
980 { "Left", "Bottom", OB_MOUSE_ACTION_MOTION
, "Resize" },
981 { "Left", "Left", OB_MOUSE_ACTION_MOTION
, "Resize" },
982 { "Left", "Right", OB_MOUSE_ACTION_MOTION
, "Resize" },
983 { "Left", "Titlebar", OB_MOUSE_ACTION_MOTION
, "Move" },
984 { "A-Left", "Frame", OB_MOUSE_ACTION_MOTION
, "Move" },
985 { "A-Middle", "Frame", OB_MOUSE_ACTION_MOTION
, "Resize" },
986 { NULL
, NULL
, 0, NULL
}
989 for (it
= binds
; it
->button
; ++it
)
990 mouse_bind(it
->button
, frame_context_from_string(it
->context
),
991 it
->mact
, actions_parse_string(it
->actname
));
994 void config_startup(ObtXmlInst
*i
)
996 config_focus_new
= TRUE
;
997 config_focus_follow
= FALSE
;
998 config_focus_delay
= 0;
999 config_focus_raise
= FALSE
;
1000 config_focus_last
= TRUE
;
1001 config_focus_under_mouse
= FALSE
;
1002 config_unfocus_leave
= FALSE
;
1004 obt_xml_register(i
, "focus", parse_focus
, NULL
);
1006 config_place_policy
= OB_PLACE_POLICY_SMART
;
1007 config_place_center
= TRUE
;
1008 config_place_monitor
= OB_PLACE_MONITOR_PRIMARY
;
1010 config_primary_monitor_index
= 1;
1011 config_primary_monitor
= OB_PLACE_MONITOR_ACTIVE
;
1013 obt_xml_register(i
, "placement", parse_placement
, NULL
);
1015 STRUT_PARTIAL_SET(config_margins
, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1017 obt_xml_register(i
, "margins", parse_margins
, NULL
);
1019 config_theme
= NULL
;
1021 config_animate_iconify
= TRUE
;
1022 config_title_layout
= g_strdup("NLIMC");
1023 config_theme_keepborder
= TRUE
;
1024 config_theme_window_list_icon_size
= 36;
1026 config_font_activewindow
= NULL
;
1027 config_font_inactivewindow
= NULL
;
1028 config_font_menuitem
= NULL
;
1029 config_font_menutitle
= NULL
;
1030 config_font_activeosd
= NULL
;
1031 config_font_inactiveosd
= NULL
;
1033 obt_xml_register(i
, "theme", parse_theme
, NULL
);
1035 config_desktops_num
= 4;
1036 config_screen_firstdesk
= 1;
1037 config_desktops_names
= NULL
;
1038 config_desktop_popup_time
= 875;
1040 obt_xml_register(i
, "desktops", parse_desktops
, NULL
);
1042 config_resize_redraw
= TRUE
;
1043 config_resize_popup_show
= 1; /* nonpixel increments */
1044 config_resize_popup_pos
= OB_RESIZE_POS_CENTER
;
1045 GRAVITY_COORD_SET(config_resize_popup_fixed
.x
, 0, FALSE
, FALSE
);
1046 GRAVITY_COORD_SET(config_resize_popup_fixed
.y
, 0, FALSE
, FALSE
);
1048 obt_xml_register(i
, "resize", parse_resize
, NULL
);
1050 config_dock_layer
= OB_STACKING_LAYER_ABOVE
;
1051 config_dock_pos
= OB_DIRECTION_NORTHEAST
;
1052 config_dock_floating
= FALSE
;
1053 config_dock_nostrut
= FALSE
;
1056 config_dock_orient
= OB_ORIENTATION_VERT
;
1057 config_dock_hide
= FALSE
;
1058 config_dock_hide_delay
= 300;
1059 config_dock_show_delay
= 300;
1060 config_dock_app_move_button
= 2; /* middle */
1061 config_dock_app_move_modifiers
= 0;
1063 obt_xml_register(i
, "dock", parse_dock
, NULL
);
1065 translate_key("C-g", &config_keyboard_reset_state
,
1066 &config_keyboard_reset_keycode
);
1068 bind_default_keyboard();
1070 obt_xml_register(i
, "keyboard", parse_keyboard
, NULL
);
1072 config_mouse_threshold
= 8;
1073 config_mouse_dclicktime
= 200;
1074 config_mouse_screenedgetime
= 400;
1075 config_mouse_screenedgewarp
= FALSE
;
1077 bind_default_mouse();
1079 obt_xml_register(i
, "mouse", parse_mouse
, NULL
);
1081 config_resist_win
= 10;
1082 config_resist_edge
= 20;
1084 obt_xml_register(i
, "resistance", parse_resistance
, NULL
);
1086 config_menu_hide_delay
= 250;
1087 config_menu_middle
= FALSE
;
1088 config_submenu_show_delay
= 100;
1089 config_submenu_hide_delay
= 400;
1090 config_menu_manage_desktops
= TRUE
;
1091 config_menu_files
= NULL
;
1092 config_menu_show_icons
= TRUE
;
1094 obt_xml_register(i
, "menu", parse_menu
, NULL
);
1096 config_per_app_settings
= NULL
;
1098 obt_xml_register(i
, "applications", parse_per_app_settings
, NULL
);
1101 void config_shutdown(void)
1105 g_free(config_theme
);
1107 g_free(config_title_layout
);
1109 RrFontClose(config_font_activewindow
);
1110 RrFontClose(config_font_inactivewindow
);
1111 RrFontClose(config_font_menuitem
);
1112 RrFontClose(config_font_menutitle
);
1113 RrFontClose(config_font_activeosd
);
1114 RrFontClose(config_font_inactiveosd
);
1116 for (it
= config_desktops_names
; it
; it
= g_slist_next(it
))
1118 g_slist_free(config_desktops_names
);
1120 for (it
= config_menu_files
; it
; it
= g_slist_next(it
))
1122 g_slist_free(config_menu_files
);
1124 for (it
= config_per_app_settings
; it
; it
= g_slist_next(it
)) {
1125 ObAppSettings
*itd
= (ObAppSettings
*)it
->data
;
1126 if (itd
->name
) g_pattern_spec_free(itd
->name
);
1127 if (itd
->role
) g_pattern_spec_free(itd
->role
);
1128 if (itd
->title
) g_pattern_spec_free(itd
->title
);
1129 if (itd
->class) g_pattern_spec_free(itd
->class);
1130 g_slice_free(ObAppSettings
, it
->data
);
1132 g_slist_free(config_per_app_settings
);