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
;
586 if ((n
= obt_xml_find_node(node
, "primaryMonitor"))) {
587 config_primary_monitor_index
= obt_xml_node_int(n
);
588 if (!config_primary_monitor_index
) {
589 if (obt_xml_node_contains(n
, "mouse"))
590 config_primary_monitor
= OB_PLACE_MONITOR_MOUSE
;
595 static void parse_margins(xmlNodePtr node
, gpointer d
)
599 node
= node
->children
;
601 if ((n
= obt_xml_find_node(node
, "top")))
602 config_margins
.top
= MAX(0, obt_xml_node_int(n
));
603 if ((n
= obt_xml_find_node(node
, "left")))
604 config_margins
.left
= MAX(0, obt_xml_node_int(n
));
605 if ((n
= obt_xml_find_node(node
, "right")))
606 config_margins
.right
= MAX(0, obt_xml_node_int(n
));
607 if ((n
= obt_xml_find_node(node
, "bottom")))
608 config_margins
.bottom
= MAX(0, obt_xml_node_int(n
));
611 static void parse_theme(xmlNodePtr node
, gpointer d
)
615 node
= node
->children
;
617 if ((n
= obt_xml_find_node(node
, "name"))) {
620 g_free(config_theme
);
621 c
= obt_xml_node_string(n
);
622 config_theme
= obt_paths_expand_tilde(c
);
625 if ((n
= obt_xml_find_node(node
, "titleLayout"))) {
628 g_free(config_title_layout
);
629 config_title_layout
= obt_xml_node_string(n
);
631 /* replace duplicates with spaces */
632 for (c
= config_title_layout
; *c
!= '\0'; ++c
)
633 for (d
= c
+1; *d
!= '\0'; ++d
)
634 if (*c
== *d
) *d
= ' ';
636 if ((n
= obt_xml_find_node(node
, "keepBorder")))
637 config_theme_keepborder
= obt_xml_node_bool(n
);
638 if ((n
= obt_xml_find_node(node
, "animateIconify")))
639 config_animate_iconify
= obt_xml_node_bool(n
);
640 if ((n
= obt_xml_find_node(node
, "windowListIconSize"))) {
641 config_theme_window_list_icon_size
= obt_xml_node_int(n
);
642 if (config_theme_window_list_icon_size
< 16)
643 config_theme_window_list_icon_size
= 16;
644 else if (config_theme_window_list_icon_size
> 96)
645 config_theme_window_list_icon_size
= 96;
648 n
= obt_xml_find_node(node
, "font");
652 gchar
*name
= g_strdup(RrDefaultFontFamily
);
653 gint size
= RrDefaultFontSize
;
654 RrFontWeight weight
= RrDefaultFontWeight
;
655 RrFontSlant slant
= RrDefaultFontSlant
;
657 if (obt_xml_attr_contains(n
, "place", "ActiveWindow"))
658 font
= &config_font_activewindow
;
659 else if (obt_xml_attr_contains(n
, "place", "InactiveWindow"))
660 font
= &config_font_inactivewindow
;
661 else if (obt_xml_attr_contains(n
, "place", "MenuHeader"))
662 font
= &config_font_menutitle
;
663 else if (obt_xml_attr_contains(n
, "place", "MenuItem"))
664 font
= &config_font_menuitem
;
665 else if (obt_xml_attr_contains(n
, "place", "ActiveOnScreenDisplay"))
666 font
= &config_font_activeosd
;
667 else if (obt_xml_attr_contains(n
, "place", "OnScreenDisplay"))
668 font
= &config_font_activeosd
;
669 else if (obt_xml_attr_contains(n
, "place","InactiveOnScreenDisplay"))
670 font
= &config_font_inactiveosd
;
674 if ((fnode
= obt_xml_find_node(n
->children
, "name"))) {
676 name
= obt_xml_node_string(fnode
);
678 if ((fnode
= obt_xml_find_node(n
->children
, "size"))) {
679 int s
= obt_xml_node_int(fnode
);
682 if ((fnode
= obt_xml_find_node(n
->children
, "weight"))) {
683 gchar
*w
= obt_xml_node_string(fnode
);
684 if (!g_ascii_strcasecmp(w
, "Bold"))
685 weight
= RR_FONTWEIGHT_BOLD
;
688 if ((fnode
= obt_xml_find_node(n
->children
, "slant"))) {
689 gchar
*s
= obt_xml_node_string(fnode
);
690 if (!g_ascii_strcasecmp(s
, "Italic"))
691 slant
= RR_FONTSLANT_ITALIC
;
692 if (!g_ascii_strcasecmp(s
, "Oblique"))
693 slant
= RR_FONTSLANT_OBLIQUE
;
697 *font
= RrFontOpen(ob_rr_inst
, name
, size
, weight
, slant
);
700 n
= obt_xml_find_node(n
->next
, "font");
704 static void parse_desktops(xmlNodePtr node
, gpointer d
)
708 node
= node
->children
;
710 if ((n
= obt_xml_find_node(node
, "number"))) {
711 gint d
= obt_xml_node_int(n
);
713 config_desktops_num
= (unsigned) d
;
715 if ((n
= obt_xml_find_node(node
, "firstdesk"))) {
716 gint d
= obt_xml_node_int(n
);
718 config_screen_firstdesk
= (unsigned) d
;
720 if ((n
= obt_xml_find_node(node
, "names"))) {
724 for (it
= config_desktops_names
; it
; it
= it
->next
)
726 g_slist_free(config_desktops_names
);
727 config_desktops_names
= NULL
;
729 nname
= obt_xml_find_node(n
->children
, "name");
731 config_desktops_names
=
732 g_slist_append(config_desktops_names
,
733 obt_xml_node_string(nname
));
734 nname
= obt_xml_find_node(nname
->next
, "name");
737 if ((n
= obt_xml_find_node(node
, "popupTime")))
738 config_desktop_popup_time
= obt_xml_node_int(n
);
741 static void parse_resize(xmlNodePtr node
, gpointer d
)
745 node
= node
->children
;
747 if ((n
= obt_xml_find_node(node
, "drawContents")))
748 config_resize_redraw
= obt_xml_node_bool(n
);
749 if ((n
= obt_xml_find_node(node
, "popupShow"))) {
750 config_resize_popup_show
= obt_xml_node_int(n
);
751 if (obt_xml_node_contains(n
, "Always"))
752 config_resize_popup_show
= 2;
753 else if (obt_xml_node_contains(n
, "Never"))
754 config_resize_popup_show
= 0;
755 else if (obt_xml_node_contains(n
, "Nonpixel"))
756 config_resize_popup_show
= 1;
758 if ((n
= obt_xml_find_node(node
, "popupPosition"))) {
759 if (obt_xml_node_contains(n
, "Top"))
760 config_resize_popup_pos
= OB_RESIZE_POS_TOP
;
761 else if (obt_xml_node_contains(n
, "Center"))
762 config_resize_popup_pos
= OB_RESIZE_POS_CENTER
;
763 else if (obt_xml_node_contains(n
, "Fixed")) {
764 config_resize_popup_pos
= OB_RESIZE_POS_FIXED
;
766 if ((n
= obt_xml_find_node(node
, "popupFixedPosition"))) {
769 if ((n2
= obt_xml_find_node(n
->children
, "x")))
770 config_parse_gravity_coord(n2
,
771 &config_resize_popup_fixed
.x
);
772 if ((n2
= obt_xml_find_node(n
->children
, "y")))
773 config_parse_gravity_coord(n2
,
774 &config_resize_popup_fixed
.y
);
776 config_resize_popup_fixed
.x
.pos
=
777 MAX(config_resize_popup_fixed
.x
.pos
, 0);
778 config_resize_popup_fixed
.y
.pos
=
779 MAX(config_resize_popup_fixed
.y
.pos
, 0);
785 static void parse_dock(xmlNodePtr node
, gpointer d
)
789 node
= node
->children
;
791 if ((n
= obt_xml_find_node(node
, "position"))) {
792 if (obt_xml_node_contains(n
, "TopLeft"))
793 config_dock_floating
= FALSE
,
794 config_dock_pos
= OB_DIRECTION_NORTHWEST
;
795 else if (obt_xml_node_contains(n
, "Top"))
796 config_dock_floating
= FALSE
,
797 config_dock_pos
= OB_DIRECTION_NORTH
;
798 else if (obt_xml_node_contains(n
, "TopRight"))
799 config_dock_floating
= FALSE
,
800 config_dock_pos
= OB_DIRECTION_NORTHEAST
;
801 else if (obt_xml_node_contains(n
, "Right"))
802 config_dock_floating
= FALSE
,
803 config_dock_pos
= OB_DIRECTION_EAST
;
804 else if (obt_xml_node_contains(n
, "BottomRight"))
805 config_dock_floating
= FALSE
,
806 config_dock_pos
= OB_DIRECTION_SOUTHEAST
;
807 else if (obt_xml_node_contains(n
, "Bottom"))
808 config_dock_floating
= FALSE
,
809 config_dock_pos
= OB_DIRECTION_SOUTH
;
810 else if (obt_xml_node_contains(n
, "BottomLeft"))
811 config_dock_floating
= FALSE
,
812 config_dock_pos
= OB_DIRECTION_SOUTHWEST
;
813 else if (obt_xml_node_contains(n
, "Left"))
814 config_dock_floating
= FALSE
,
815 config_dock_pos
= OB_DIRECTION_WEST
;
816 else if (obt_xml_node_contains(n
, "Floating"))
817 config_dock_floating
= TRUE
;
819 if (config_dock_floating
) {
820 if ((n
= obt_xml_find_node(node
, "floatingX")))
821 config_dock_x
= obt_xml_node_int(n
);
822 if ((n
= obt_xml_find_node(node
, "floatingY")))
823 config_dock_y
= obt_xml_node_int(n
);
825 if ((n
= obt_xml_find_node(node
, "noStrut")))
826 config_dock_nostrut
= obt_xml_node_bool(n
);
828 if ((n
= obt_xml_find_node(node
, "stacking"))) {
829 if (obt_xml_node_contains(n
, "normal"))
830 config_dock_layer
= OB_STACKING_LAYER_NORMAL
;
831 else if (obt_xml_node_contains(n
, "below"))
832 config_dock_layer
= OB_STACKING_LAYER_BELOW
;
833 else if (obt_xml_node_contains(n
, "above"))
834 config_dock_layer
= OB_STACKING_LAYER_ABOVE
;
836 if ((n
= obt_xml_find_node(node
, "direction"))) {
837 if (obt_xml_node_contains(n
, "horizontal"))
838 config_dock_orient
= OB_ORIENTATION_HORZ
;
839 else if (obt_xml_node_contains(n
, "vertical"))
840 config_dock_orient
= OB_ORIENTATION_VERT
;
842 if ((n
= obt_xml_find_node(node
, "autoHide")))
843 config_dock_hide
= obt_xml_node_bool(n
);
844 if ((n
= obt_xml_find_node(node
, "hideDelay")))
845 config_dock_hide_delay
= obt_xml_node_int(n
);
846 if ((n
= obt_xml_find_node(node
, "showDelay")))
847 config_dock_show_delay
= obt_xml_node_int(n
);
848 if ((n
= obt_xml_find_node(node
, "moveButton"))) {
849 gchar
*str
= obt_xml_node_string(n
);
851 if (translate_button(str
, &s
, &b
)) {
852 config_dock_app_move_button
= b
;
853 config_dock_app_move_modifiers
= s
;
855 g_message(_("Invalid button \"%s\" specified in config file"), str
);
861 static void parse_menu(xmlNodePtr node
, gpointer d
)
864 node
= node
->children
;
866 if ((n
= obt_xml_find_node(node
, "hideDelay")))
867 config_menu_hide_delay
= obt_xml_node_int(n
);
868 if ((n
= obt_xml_find_node(node
, "middle")))
869 config_menu_middle
= obt_xml_node_bool(n
);
870 if ((n
= obt_xml_find_node(node
, "submenuShowDelay")))
871 config_submenu_show_delay
= obt_xml_node_int(n
);
872 if ((n
= obt_xml_find_node(node
, "submenuHideDelay")))
873 config_submenu_hide_delay
= obt_xml_node_int(n
);
874 if ((n
= obt_xml_find_node(node
, "manageDesktops")))
875 config_menu_manage_desktops
= obt_xml_node_bool(n
);
876 if ((n
= obt_xml_find_node(node
, "showIcons"))) {
877 config_menu_show_icons
= obt_xml_node_bool(n
);
879 if (config_menu_show_icons
)
880 g_message(_("Openbox was compiled without Imlib2 image loading support. Icons in menus will not be loaded."));
884 while ((node
= obt_xml_find_node(node
, "file"))) {
885 gchar
*c
= obt_xml_node_string(node
);
886 config_menu_files
= g_slist_append(config_menu_files
,
887 obt_paths_expand_tilde(c
));
893 static void parse_resistance(xmlNodePtr node
, gpointer d
)
897 node
= node
->children
;
898 if ((n
= obt_xml_find_node(node
, "strength")))
899 config_resist_win
= obt_xml_node_int(n
);
900 if ((n
= obt_xml_find_node(node
, "screen_edge_strength")))
901 config_resist_edge
= obt_xml_node_int(n
);
907 const gchar
*actname
;
910 static void bind_default_keyboard(void)
913 ObDefKeyBind binds
[] = {
914 { "A-Tab", "NextWindow" },
915 { "S-A-Tab", "PreviousWindow" },
919 for (it
= binds
; it
->key
; ++it
) {
920 GList
*l
= g_list_append(NULL
, g_strdup(it
->key
));
921 keyboard_bind(l
, actions_parse_string(it
->actname
));
928 const gchar
*context
;
929 const ObMouseAction mact
;
930 const gchar
*actname
;
933 static void bind_default_mouse(void)
936 ObDefMouseBind binds
[] = {
937 { "Left", "Client", OB_MOUSE_ACTION_PRESS
, "Focus" },
938 { "Middle", "Client", OB_MOUSE_ACTION_PRESS
, "Focus" },
939 { "Right", "Client", OB_MOUSE_ACTION_PRESS
, "Focus" },
940 { "Left", "Desktop", OB_MOUSE_ACTION_PRESS
, "Focus" },
941 { "Middle", "Desktop", OB_MOUSE_ACTION_PRESS
, "Focus" },
942 { "Right", "Desktop", OB_MOUSE_ACTION_PRESS
, "Focus" },
943 { "Left", "Titlebar", OB_MOUSE_ACTION_PRESS
, "Focus" },
944 { "Left", "Bottom", OB_MOUSE_ACTION_PRESS
, "Focus" },
945 { "Left", "BLCorner", OB_MOUSE_ACTION_PRESS
, "Focus" },
946 { "Left", "BRCorner", OB_MOUSE_ACTION_PRESS
, "Focus" },
947 { "Left", "TLCorner", OB_MOUSE_ACTION_PRESS
, "Focus" },
948 { "Left", "TRCorner", OB_MOUSE_ACTION_PRESS
, "Focus" },
949 { "Left", "Close", OB_MOUSE_ACTION_PRESS
, "Focus" },
950 { "Left", "Maximize", OB_MOUSE_ACTION_PRESS
, "Focus" },
951 { "Left", "Iconify", OB_MOUSE_ACTION_PRESS
, "Focus" },
952 { "Left", "Icon", OB_MOUSE_ACTION_PRESS
, "Focus" },
953 { "Left", "AllDesktops", OB_MOUSE_ACTION_PRESS
, "Focus" },
954 { "Left", "Shade", OB_MOUSE_ACTION_PRESS
, "Focus" },
955 { "Left", "Client", OB_MOUSE_ACTION_CLICK
, "Raise" },
956 { "Left", "Titlebar", OB_MOUSE_ACTION_CLICK
, "Raise" },
957 { "Middle", "Titlebar", OB_MOUSE_ACTION_CLICK
, "Lower" },
958 { "Left", "BLCorner", OB_MOUSE_ACTION_CLICK
, "Raise" },
959 { "Left", "BRCorner", OB_MOUSE_ACTION_CLICK
, "Raise" },
960 { "Left", "TLCorner", OB_MOUSE_ACTION_CLICK
, "Raise" },
961 { "Left", "TRCorner", OB_MOUSE_ACTION_CLICK
, "Raise" },
962 { "Left", "Close", OB_MOUSE_ACTION_CLICK
, "Raise" },
963 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK
, "Raise" },
964 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK
, "Raise" },
965 { "Left", "Icon", OB_MOUSE_ACTION_CLICK
, "Raise" },
966 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK
, "Raise" },
967 { "Left", "Shade", OB_MOUSE_ACTION_CLICK
, "Raise" },
968 { "Left", "Close", OB_MOUSE_ACTION_CLICK
, "Close" },
969 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK
, "ToggleMaximize" },
970 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK
, "Iconify" },
971 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK
, "ToggleOmnipresent" },
972 { "Left", "Shade", OB_MOUSE_ACTION_CLICK
, "ToggleShade" },
973 { "Left", "TLCorner", OB_MOUSE_ACTION_MOTION
, "Resize" },
974 { "Left", "TRCorner", OB_MOUSE_ACTION_MOTION
, "Resize" },
975 { "Left", "BLCorner", OB_MOUSE_ACTION_MOTION
, "Resize" },
976 { "Left", "BRCorner", OB_MOUSE_ACTION_MOTION
, "Resize" },
977 { "Left", "Top", OB_MOUSE_ACTION_MOTION
, "Resize" },
978 { "Left", "Bottom", OB_MOUSE_ACTION_MOTION
, "Resize" },
979 { "Left", "Left", OB_MOUSE_ACTION_MOTION
, "Resize" },
980 { "Left", "Right", OB_MOUSE_ACTION_MOTION
, "Resize" },
981 { "Left", "Titlebar", OB_MOUSE_ACTION_MOTION
, "Move" },
982 { "A-Left", "Frame", OB_MOUSE_ACTION_MOTION
, "Move" },
983 { "A-Middle", "Frame", OB_MOUSE_ACTION_MOTION
, "Resize" },
984 { NULL
, NULL
, 0, NULL
}
987 for (it
= binds
; it
->button
; ++it
)
988 mouse_bind(it
->button
, frame_context_from_string(it
->context
),
989 it
->mact
, actions_parse_string(it
->actname
));
992 void config_startup(ObtXmlInst
*i
)
994 config_focus_new
= TRUE
;
995 config_focus_follow
= FALSE
;
996 config_focus_delay
= 0;
997 config_focus_raise
= FALSE
;
998 config_focus_last
= TRUE
;
999 config_focus_under_mouse
= FALSE
;
1000 config_unfocus_leave
= FALSE
;
1002 obt_xml_register(i
, "focus", parse_focus
, NULL
);
1004 config_place_policy
= OB_PLACE_POLICY_SMART
;
1005 config_place_center
= TRUE
;
1006 config_place_monitor
= OB_PLACE_MONITOR_ANY
;
1008 config_primary_monitor_index
= 1;
1009 config_primary_monitor
= OB_PLACE_MONITOR_ACTIVE
;
1011 obt_xml_register(i
, "placement", parse_placement
, NULL
);
1013 STRUT_PARTIAL_SET(config_margins
, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1015 obt_xml_register(i
, "margins", parse_margins
, NULL
);
1017 config_theme
= NULL
;
1019 config_animate_iconify
= TRUE
;
1020 config_title_layout
= g_strdup("NLIMC");
1021 config_theme_keepborder
= TRUE
;
1022 config_theme_window_list_icon_size
= 36;
1024 config_font_activewindow
= NULL
;
1025 config_font_inactivewindow
= NULL
;
1026 config_font_menuitem
= NULL
;
1027 config_font_menutitle
= NULL
;
1028 config_font_activeosd
= NULL
;
1029 config_font_inactiveosd
= NULL
;
1031 obt_xml_register(i
, "theme", parse_theme
, NULL
);
1033 config_desktops_num
= 4;
1034 config_screen_firstdesk
= 1;
1035 config_desktops_names
= NULL
;
1036 config_desktop_popup_time
= 875;
1038 obt_xml_register(i
, "desktops", parse_desktops
, NULL
);
1040 config_resize_redraw
= TRUE
;
1041 config_resize_popup_show
= 1; /* nonpixel increments */
1042 config_resize_popup_pos
= OB_RESIZE_POS_CENTER
;
1043 GRAVITY_COORD_SET(config_resize_popup_fixed
.x
, 0, FALSE
, FALSE
);
1044 GRAVITY_COORD_SET(config_resize_popup_fixed
.y
, 0, FALSE
, FALSE
);
1046 obt_xml_register(i
, "resize", parse_resize
, NULL
);
1048 config_dock_layer
= OB_STACKING_LAYER_ABOVE
;
1049 config_dock_pos
= OB_DIRECTION_NORTHEAST
;
1050 config_dock_floating
= FALSE
;
1051 config_dock_nostrut
= FALSE
;
1054 config_dock_orient
= OB_ORIENTATION_VERT
;
1055 config_dock_hide
= FALSE
;
1056 config_dock_hide_delay
= 300;
1057 config_dock_show_delay
= 300;
1058 config_dock_app_move_button
= 2; /* middle */
1059 config_dock_app_move_modifiers
= 0;
1061 obt_xml_register(i
, "dock", parse_dock
, NULL
);
1063 translate_key("C-g", &config_keyboard_reset_state
,
1064 &config_keyboard_reset_keycode
);
1066 bind_default_keyboard();
1068 obt_xml_register(i
, "keyboard", parse_keyboard
, NULL
);
1070 config_mouse_threshold
= 8;
1071 config_mouse_dclicktime
= 200;
1072 config_mouse_screenedgetime
= 400;
1073 config_mouse_screenedgewarp
= FALSE
;
1075 bind_default_mouse();
1077 obt_xml_register(i
, "mouse", parse_mouse
, NULL
);
1079 config_resist_win
= 10;
1080 config_resist_edge
= 20;
1082 obt_xml_register(i
, "resistance", parse_resistance
, NULL
);
1084 config_menu_hide_delay
= 250;
1085 config_menu_middle
= FALSE
;
1086 config_submenu_show_delay
= 100;
1087 config_submenu_hide_delay
= 400;
1088 config_menu_manage_desktops
= TRUE
;
1089 config_menu_files
= NULL
;
1090 config_menu_show_icons
= TRUE
;
1092 obt_xml_register(i
, "menu", parse_menu
, NULL
);
1094 config_per_app_settings
= NULL
;
1096 obt_xml_register(i
, "applications", parse_per_app_settings
, NULL
);
1099 void config_shutdown(void)
1103 g_free(config_theme
);
1105 g_free(config_title_layout
);
1107 RrFontClose(config_font_activewindow
);
1108 RrFontClose(config_font_inactivewindow
);
1109 RrFontClose(config_font_menuitem
);
1110 RrFontClose(config_font_menutitle
);
1111 RrFontClose(config_font_activeosd
);
1112 RrFontClose(config_font_inactiveosd
);
1114 for (it
= config_desktops_names
; it
; it
= g_slist_next(it
))
1116 g_slist_free(config_desktops_names
);
1118 for (it
= config_menu_files
; it
; it
= g_slist_next(it
))
1120 g_slist_free(config_menu_files
);
1122 for (it
= config_per_app_settings
; it
; it
= g_slist_next(it
)) {
1123 ObAppSettings
*itd
= (ObAppSettings
*)it
->data
;
1124 if (itd
->name
) g_pattern_spec_free(itd
->name
);
1125 if (itd
->role
) g_pattern_spec_free(itd
->role
);
1126 if (itd
->title
) g_pattern_spec_free(itd
->title
);
1127 if (itd
->class) g_pattern_spec_free(itd
->class);
1128 g_slice_free(ObAppSettings
, it
->data
);
1130 g_slist_free(config_per_app_settings
);