1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
3 config.c for the Openbox window manager
4 Copyright (c) 2006 Mikael Magnusson
5 Copyright (c) 2003-2007 Dana Jansens
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 See the COPYING file for a copy of the GNU General Public License.
24 #include "translate.h"
29 #include "obt/paths.h"
31 gboolean config_focus_new
;
32 gboolean config_focus_follow
;
33 guint config_focus_delay
;
34 gboolean config_focus_raise
;
35 gboolean config_focus_last
;
36 gboolean config_focus_under_mouse
;
37 gboolean config_unfocus_leave
;
39 ObPlacePolicy config_place_policy
;
40 gboolean config_place_center
;
41 ObPlaceMonitor config_place_monitor
;
43 guint config_primary_monitor_index
;
44 ObPlaceMonitor config_primary_monitor
;
46 StrutPartial config_margins
;
49 gboolean config_theme_keepborder
;
50 guint config_theme_window_list_icon_size
;
52 gchar
*config_title_layout
;
54 gboolean config_animate_iconify
;
56 RrFont
*config_font_activewindow
;
57 RrFont
*config_font_inactivewindow
;
58 RrFont
*config_font_menuitem
;
59 RrFont
*config_font_menutitle
;
60 RrFont
*config_font_activeosd
;
61 RrFont
*config_font_inactiveosd
;
63 guint config_desktops_num
;
64 GSList
*config_desktops_names
;
65 guint config_screen_firstdesk
;
66 guint config_desktop_popup_time
;
68 gboolean config_resize_redraw
;
69 gint config_resize_popup_show
;
70 ObResizePopupPos config_resize_popup_pos
;
71 GravityPoint config_resize_popup_fixed
;
73 ObStackingLayer config_dock_layer
;
74 gboolean config_dock_floating
;
75 gboolean config_dock_nostrut
;
76 ObDirection config_dock_pos
;
79 ObOrientation config_dock_orient
;
80 gboolean config_dock_hide
;
81 guint config_dock_hide_delay
;
82 guint config_dock_show_delay
;
83 guint config_dock_app_move_button
;
84 guint config_dock_app_move_modifiers
;
86 guint config_keyboard_reset_keycode
;
87 guint config_keyboard_reset_state
;
89 gint config_mouse_threshold
;
90 gint config_mouse_dclicktime
;
91 gint config_mouse_screenedgetime
;
92 gboolean config_mouse_screenedgewarp
;
94 guint config_menu_hide_delay
;
95 gboolean config_menu_middle
;
96 guint config_submenu_show_delay
;
97 guint config_submenu_hide_delay
;
98 gboolean config_menu_manage_desktops
;
99 gboolean config_menu_show_icons
;
101 GSList
*config_menu_files
;
103 gint config_resist_win
;
104 gint config_resist_edge
;
106 GSList
*config_per_app_settings
;
108 ObAppSettings
* config_create_app_settings(void)
110 ObAppSettings
*settings
= g_slice_new0(ObAppSettings
);
112 settings
->decor
= -1;
113 settings
->shade
= -1;
114 settings
->monitor_type
= OB_PLACE_MONITOR_ANY
;
115 settings
->monitor
= -1;
116 settings
->focus
= -1;
117 settings
->desktop
= 0;
118 settings
->layer
= -2;
119 settings
->iconic
= -1;
120 settings
->skip_pager
= -1;
121 settings
->skip_taskbar
= -1;
122 settings
->fullscreen
= -1;
123 settings
->max_horz
= -1;
124 settings
->max_vert
= -1;
128 #define copy_if(setting, default) \
129 if (src->setting != default) dst->setting = src->setting
130 void config_app_settings_copy_non_defaults(const ObAppSettings
*src
,
133 g_assert(src
!= NULL
);
134 g_assert(dst
!= NULL
);
136 copy_if(type
, (ObClientType
)-1);
139 copy_if(monitor_type
, OB_PLACE_MONITOR_ANY
);
140 copy_if(monitor
, -1);
145 copy_if(skip_pager
, -1);
146 copy_if(skip_taskbar
, -1);
147 copy_if(fullscreen
, -1);
148 copy_if(max_horz
, -1);
149 copy_if(max_vert
, -1);
151 if (src
->pos_given
) {
152 dst
->pos_given
= TRUE
;
153 dst
->pos_force
= src
->pos_force
;
154 dst
->position
= src
->position
;
155 /* monitor is copied above */
158 dst
->width_num
= src
->width_num
;
159 dst
->width_denom
= src
->width_denom
;
160 dst
->height_num
= src
->height_num
;
161 dst
->height_denom
= src
->height_denom
;
164 void config_parse_relative_number(gchar
*s
, gint
*num
, gint
*denom
)
166 *num
= strtol(s
, &s
, 10);
170 } else if (*s
== '/') {
175 void config_parse_gravity_coord(xmlNodePtr node
, GravityCoord
*c
)
177 gchar
*s
= obt_xml_node_string(node
);
178 if (!g_ascii_strcasecmp(s
, "center"))
184 if (s
[0] == '-' || s
[0] == '+')
186 config_parse_relative_number(ps
, &c
->pos
, &c
->denom
);
193 <application name="aterm">
196 <application name="Rhythmbox">
203 .. there is a lot more settings available
208 static void parse_single_per_app_settings(xmlNodePtr app
,
209 ObAppSettings
*settings
)
212 gboolean x_pos_given
= FALSE
;
214 if ((n
= obt_xml_find_node(app
->children
, "decor")))
215 if (!obt_xml_node_contains(n
, "default"))
216 settings
->decor
= obt_xml_node_bool(n
);
218 if ((n
= obt_xml_find_node(app
->children
, "shade")))
219 if (!obt_xml_node_contains(n
, "default"))
220 settings
->shade
= obt_xml_node_bool(n
);
222 if ((n
= obt_xml_find_node(app
->children
, "position"))) {
223 if ((c
= obt_xml_find_node(n
->children
, "x"))) {
224 if (!obt_xml_node_contains(c
, "default")) {
225 config_parse_gravity_coord(c
, &settings
->position
.x
);
230 if (x_pos_given
&& (c
= obt_xml_find_node(n
->children
, "y"))) {
231 if (!obt_xml_node_contains(c
, "default")) {
232 config_parse_gravity_coord(c
, &settings
->position
.y
);
233 settings
->pos_given
= TRUE
;
237 /* monitor can be set without setting x or y */
238 if ((c
= obt_xml_find_node(n
->children
, "monitor"))) {
239 if (!obt_xml_node_contains(c
, "default")) {
240 gchar
*s
= obt_xml_node_string(c
);
241 if (!g_ascii_strcasecmp(s
, "mouse"))
242 settings
->monitor_type
= OB_PLACE_MONITOR_MOUSE
;
243 else if (!g_ascii_strcasecmp(s
, "active"))
244 settings
->monitor_type
= OB_PLACE_MONITOR_ACTIVE
;
245 else if (!g_ascii_strcasecmp(s
, "primary"))
246 settings
->monitor_type
= OB_PLACE_MONITOR_PRIMARY
;
248 settings
->monitor
= obt_xml_node_int(c
);
253 obt_xml_attr_bool(n
, "force", &settings
->pos_force
);
256 if ((n
= obt_xml_find_node(app
->children
, "size"))) {
257 if ((c
= obt_xml_find_node(n
->children
, "width"))) {
258 if (!obt_xml_node_contains(c
, "default")) {
259 gchar
*s
= obt_xml_node_string(c
);
260 config_parse_relative_number(s
,
261 &settings
->width_num
,
262 &settings
->width_denom
);
263 if (settings
->width_num
<= 0 || settings
->width_denom
< 0)
264 settings
->width_num
= settings
->width_denom
= 0;
269 if ((c
= obt_xml_find_node(n
->children
, "height"))) {
270 if (!obt_xml_node_contains(c
, "default")) {
271 gchar
*s
= obt_xml_node_string(c
);
272 config_parse_relative_number(s
,
273 &settings
->height_num
,
274 &settings
->height_denom
);
275 if (settings
->height_num
<= 0 || settings
->height_denom
< 0)
276 settings
->height_num
= settings
->height_denom
= 0;
282 if ((n
= obt_xml_find_node(app
->children
, "focus"))) {
283 if (!obt_xml_node_contains(n
, "default"))
284 settings
->focus
= obt_xml_node_bool(n
);
287 if ((n
= obt_xml_find_node(app
->children
, "desktop"))) {
288 if (!obt_xml_node_contains(n
, "default")) {
289 gchar
*s
= obt_xml_node_string(n
);
290 if (!g_ascii_strcasecmp(s
, "all"))
291 settings
->desktop
= DESKTOP_ALL
;
293 gint i
= obt_xml_node_int(n
);
295 settings
->desktop
= i
;
301 if ((n
= obt_xml_find_node(app
->children
, "layer"))) {
302 if (!obt_xml_node_contains(n
, "default")) {
303 gchar
*s
= obt_xml_node_string(n
);
304 if (!g_ascii_strcasecmp(s
, "above"))
306 else if (!g_ascii_strcasecmp(s
, "below"))
307 settings
->layer
= -1;
314 if ((n
= obt_xml_find_node(app
->children
, "iconic")))
315 if (!obt_xml_node_contains(n
, "default"))
316 settings
->iconic
= obt_xml_node_bool(n
);
318 if ((n
= obt_xml_find_node(app
->children
, "skip_pager")))
319 if (!obt_xml_node_contains(n
, "default"))
320 settings
->skip_pager
= obt_xml_node_bool(n
);
322 if ((n
= obt_xml_find_node(app
->children
, "skip_taskbar")))
323 if (!obt_xml_node_contains(n
, "default"))
324 settings
->skip_taskbar
= obt_xml_node_bool(n
);
326 if ((n
= obt_xml_find_node(app
->children
, "fullscreen")))
327 if (!obt_xml_node_contains(n
, "default"))
328 settings
->fullscreen
= obt_xml_node_bool(n
);
330 if ((n
= obt_xml_find_node(app
->children
, "maximized"))) {
331 if (!obt_xml_node_contains(n
, "default")) {
332 gchar
*s
= obt_xml_node_string(n
);
333 if (!g_ascii_strcasecmp(s
, "horizontal")) {
334 settings
->max_horz
= TRUE
;
335 settings
->max_vert
= FALSE
;
336 } else if (!g_ascii_strcasecmp(s
, "vertical")) {
337 settings
->max_horz
= FALSE
;
338 settings
->max_vert
= TRUE
;
340 settings
->max_horz
= settings
->max_vert
=
341 obt_xml_node_bool(n
);
347 /* Manages settings for individual applications.
348 Some notes: monitor is the screen number in a multi monitor
349 (Xinerama) setup (starting from 0), or mouse: the monitor the pointer
350 is on, active: the active monitor, primary: the primary monitor.
351 Layer can be three values, above (Always on top), below
352 (Always on bottom) and everything else (normal behaviour).
353 Positions can be an integer value or center, which will
354 center the window in the specified axis. Position is within
355 the monitor, so <position><x>center</x></position><monitor>2</monitor>
356 will center the window on the second monitor.
358 static void parse_per_app_settings(xmlNodePtr node
, gpointer d
)
360 xmlNodePtr app
= obt_xml_find_node(node
->children
, "application");
361 for (; app
; app
= obt_xml_find_node(app
->next
, "application")) {
362 ObAppSettings
*settings
;
364 gboolean name_set
, class_set
, role_set
, title_set
,
365 type_set
, group_name_set
, group_class_set
;
366 gchar
*name
= NULL
, *class = NULL
, *role
= NULL
, *title
= NULL
,
367 *type_str
= NULL
, *group_name
= NULL
, *group_class
= NULL
;
370 class_set
= obt_xml_attr_string(app
, "class", &class);
371 name_set
= obt_xml_attr_string(app
, "name", &name
);
372 group_class_set
= obt_xml_attr_string(app
, "groupclass", &group_class
);
373 group_name_set
= obt_xml_attr_string(app
, "groupname", &group_name
);
374 type_set
= obt_xml_attr_string(app
, "type", &type_str
);
375 role_set
= obt_xml_attr_string(app
, "role", &role
);
376 title_set
= obt_xml_attr_string(app
, "title", &title
);
378 /* validate the type tho */
380 if (!g_ascii_strcasecmp(type_str
, "normal"))
381 type
= OB_CLIENT_TYPE_NORMAL
;
382 else if (!g_ascii_strcasecmp(type_str
, "dialog"))
383 type
= OB_CLIENT_TYPE_DIALOG
;
384 else if (!g_ascii_strcasecmp(type_str
, "splash"))
385 type
= OB_CLIENT_TYPE_SPLASH
;
386 else if (!g_ascii_strcasecmp(type_str
, "utility"))
387 type
= OB_CLIENT_TYPE_UTILITY
;
388 else if (!g_ascii_strcasecmp(type_str
, "menu"))
389 type
= OB_CLIENT_TYPE_MENU
;
390 else if (!g_ascii_strcasecmp(type_str
, "toolbar"))
391 type
= OB_CLIENT_TYPE_TOOLBAR
;
392 else if (!g_ascii_strcasecmp(type_str
, "dock"))
393 type
= OB_CLIENT_TYPE_DOCK
;
394 else if (!g_ascii_strcasecmp(type_str
, "desktop"))
395 type
= OB_CLIENT_TYPE_DESKTOP
;
397 type_set
= FALSE
; /* not valid! */
400 if (!(class_set
|| name_set
|| role_set
|| title_set
||
401 type_set
|| group_class_set
|| group_name_set
))
404 settings
= config_create_app_settings();
407 settings
->name
= g_pattern_spec_new(name
);
409 settings
->class = g_pattern_spec_new(class);
411 settings
->group_name
= g_pattern_spec_new(group_name
);
413 settings
->group_class
= g_pattern_spec_new(group_class
);
415 settings
->role
= g_pattern_spec_new(role
);
417 settings
->title
= g_pattern_spec_new(title
);
419 settings
->type
= type
;
429 parse_single_per_app_settings(app
, settings
);
430 config_per_app_settings
= g_slist_append(config_per_app_settings
,
438 <action name="ChangeDesktop">
445 static void parse_key(xmlNodePtr node
, GList
*keylist
)
447 gchar
*keystring
, **keys
, **key
;
449 gboolean is_chroot
= FALSE
;
451 if (!obt_xml_attr_string(node
, "key", &keystring
))
454 obt_xml_attr_bool(node
, "chroot", &is_chroot
);
456 keys
= g_strsplit(keystring
, " ", 0);
457 for (key
= keys
; *key
; ++key
) {
458 keylist
= g_list_append(keylist
, *key
);
460 if ((n
= obt_xml_find_node(node
->children
, "keybind"))) {
462 parse_key(n
, keylist
);
463 n
= obt_xml_find_node(n
->next
, "keybind");
466 else if ((n
= obt_xml_find_node(node
->children
, "action"))) {
468 ObActionsAct
*action
;
470 action
= actions_parse(n
);
472 keyboard_bind(keylist
, action
);
473 n
= obt_xml_find_node(n
->next
, "action");
479 keyboard_chroot(keylist
);
480 keylist
= g_list_delete_link(keylist
, g_list_last(keylist
));
487 static void parse_keyboard(xmlNodePtr node
, gpointer d
)
492 keyboard_unbind_all();
494 if ((n
= obt_xml_find_node(node
->children
, "chainQuitKey"))) {
495 key
= obt_xml_node_string(n
);
496 translate_key(key
, &config_keyboard_reset_state
,
497 &config_keyboard_reset_keycode
);
501 if ((n
= obt_xml_find_node(node
->children
, "keybind")))
504 n
= obt_xml_find_node(n
->next
, "keybind");
510 <context name="Titlebar">
511 <mousebind button="Left" action="Press">
512 <action name="Raise"></action>
518 static void parse_mouse(xmlNodePtr node
, gpointer d
)
520 xmlNodePtr n
, nbut
, nact
;
527 node
= node
->children
;
529 if ((n
= obt_xml_find_node(node
, "dragThreshold")))
530 config_mouse_threshold
= obt_xml_node_int(n
);
531 if ((n
= obt_xml_find_node(node
, "doubleClickTime")))
532 config_mouse_dclicktime
= obt_xml_node_int(n
);
533 if ((n
= obt_xml_find_node(node
, "screenEdgeWarpTime"))) {
534 config_mouse_screenedgetime
= obt_xml_node_int(n
);
535 /* minimum value of 25 for this property, when it is 1 and you hit the
536 edge it basically never stops */
537 if (config_mouse_screenedgetime
&& config_mouse_screenedgetime
< 25)
538 config_mouse_screenedgetime
= 25;
540 if ((n
= obt_xml_find_node(node
, "screenEdgeWarpMouse")))
541 config_mouse_screenedgewarp
= obt_xml_node_bool(n
);
543 n
= obt_xml_find_node(node
, "context");
548 if (!obt_xml_attr_string(n
, "name", &cxstr
))
551 modcxstr
= g_strdup(cxstr
); /* make a copy to mutilate */
552 while (frame_next_context_from_string(modcxstr
, &cx
)) {
554 gchar
*s
= strchr(modcxstr
, ' ');
557 g_message(_("Invalid context \"%s\" in mouse binding"),
564 nbut
= obt_xml_find_node(n
->children
, "mousebind");
566 if (!obt_xml_attr_string(nbut
, "button", &buttonstr
))
568 if (obt_xml_attr_contains(nbut
, "action", "press"))
569 mact
= OB_MOUSE_ACTION_PRESS
;
570 else if (obt_xml_attr_contains(nbut
, "action", "release"))
571 mact
= OB_MOUSE_ACTION_RELEASE
;
572 else if (obt_xml_attr_contains(nbut
, "action", "click"))
573 mact
= OB_MOUSE_ACTION_CLICK
;
574 else if (obt_xml_attr_contains(nbut
, "action","doubleclick"))
575 mact
= OB_MOUSE_ACTION_DOUBLE_CLICK
;
576 else if (obt_xml_attr_contains(nbut
, "action", "drag"))
577 mact
= OB_MOUSE_ACTION_MOTION
;
581 nact
= obt_xml_find_node(nbut
->children
, "action");
583 ObActionsAct
*action
;
585 if ((action
= actions_parse(nact
)))
586 mouse_bind(buttonstr
, cx
, mact
, action
);
587 nact
= obt_xml_find_node(nact
->next
, "action");
591 nbut
= obt_xml_find_node(nbut
->next
, "mousebind");
597 n
= obt_xml_find_node(n
->next
, "context");
601 static void parse_focus(xmlNodePtr node
, gpointer d
)
605 node
= node
->children
;
607 if ((n
= obt_xml_find_node(node
, "focusNew")))
608 config_focus_new
= obt_xml_node_bool(n
);
609 if ((n
= obt_xml_find_node(node
, "followMouse")))
610 config_focus_follow
= obt_xml_node_bool(n
);
611 if ((n
= obt_xml_find_node(node
, "focusDelay")))
612 config_focus_delay
= obt_xml_node_int(n
);
613 if ((n
= obt_xml_find_node(node
, "raiseOnFocus")))
614 config_focus_raise
= obt_xml_node_bool(n
);
615 if ((n
= obt_xml_find_node(node
, "focusLast")))
616 config_focus_last
= obt_xml_node_bool(n
);
617 if ((n
= obt_xml_find_node(node
, "underMouse")))
618 config_focus_under_mouse
= obt_xml_node_bool(n
);
619 if ((n
= obt_xml_find_node(node
, "unfocusOnLeave")))
620 config_unfocus_leave
= obt_xml_node_bool(n
);
623 static void parse_placement(xmlNodePtr node
, gpointer d
)
627 node
= node
->children
;
629 if ((n
= obt_xml_find_node(node
, "policy"))) {
630 if (obt_xml_node_contains(n
, "UnderMouse"))
631 config_place_policy
= OB_PLACE_POLICY_MOUSE
;
633 if ((n
= obt_xml_find_node(node
, "center"))) {
634 config_place_center
= obt_xml_node_bool(n
);
636 if ((n
= obt_xml_find_node(node
, "monitor"))) {
637 if (obt_xml_node_contains(n
, "active"))
638 config_place_monitor
= OB_PLACE_MONITOR_ACTIVE
;
639 else if (obt_xml_node_contains(n
, "mouse"))
640 config_place_monitor
= OB_PLACE_MONITOR_MOUSE
;
641 else if (obt_xml_node_contains(n
, "any"))
642 config_place_monitor
= OB_PLACE_MONITOR_ANY
;
644 if ((n
= obt_xml_find_node(node
, "primaryMonitor"))) {
645 config_primary_monitor_index
= obt_xml_node_int(n
);
646 if (!config_primary_monitor_index
) {
647 if (obt_xml_node_contains(n
, "mouse"))
648 config_primary_monitor
= OB_PLACE_MONITOR_MOUSE
;
653 static void parse_margins(xmlNodePtr node
, gpointer d
)
657 node
= node
->children
;
659 if ((n
= obt_xml_find_node(node
, "top")))
660 config_margins
.top
= MAX(0, obt_xml_node_int(n
));
661 if ((n
= obt_xml_find_node(node
, "left")))
662 config_margins
.left
= MAX(0, obt_xml_node_int(n
));
663 if ((n
= obt_xml_find_node(node
, "right")))
664 config_margins
.right
= MAX(0, obt_xml_node_int(n
));
665 if ((n
= obt_xml_find_node(node
, "bottom")))
666 config_margins
.bottom
= MAX(0, obt_xml_node_int(n
));
669 static void parse_theme(xmlNodePtr node
, gpointer d
)
673 node
= node
->children
;
675 if ((n
= obt_xml_find_node(node
, "name"))) {
678 g_free(config_theme
);
679 c
= obt_xml_node_string(n
);
680 config_theme
= obt_paths_expand_tilde(c
);
683 if ((n
= obt_xml_find_node(node
, "titleLayout"))) {
686 g_free(config_title_layout
);
687 config_title_layout
= obt_xml_node_string(n
);
689 /* replace duplicates with spaces */
690 for (c
= config_title_layout
; *c
!= '\0'; ++c
)
691 for (d
= c
+1; *d
!= '\0'; ++d
)
692 if (*c
== *d
) *d
= ' ';
694 if ((n
= obt_xml_find_node(node
, "keepBorder")))
695 config_theme_keepborder
= obt_xml_node_bool(n
);
696 if ((n
= obt_xml_find_node(node
, "animateIconify")))
697 config_animate_iconify
= obt_xml_node_bool(n
);
698 if ((n
= obt_xml_find_node(node
, "windowListIconSize"))) {
699 config_theme_window_list_icon_size
= obt_xml_node_int(n
);
700 if (config_theme_window_list_icon_size
< 16)
701 config_theme_window_list_icon_size
= 16;
702 else if (config_theme_window_list_icon_size
> 96)
703 config_theme_window_list_icon_size
= 96;
706 n
= obt_xml_find_node(node
, "font");
710 gchar
*name
= g_strdup(RrDefaultFontFamily
);
711 gint size
= RrDefaultFontSize
;
712 RrFontWeight weight
= RrDefaultFontWeight
;
713 RrFontSlant slant
= RrDefaultFontSlant
;
715 if (obt_xml_attr_contains(n
, "place", "ActiveWindow"))
716 font
= &config_font_activewindow
;
717 else if (obt_xml_attr_contains(n
, "place", "InactiveWindow"))
718 font
= &config_font_inactivewindow
;
719 else if (obt_xml_attr_contains(n
, "place", "MenuHeader"))
720 font
= &config_font_menutitle
;
721 else if (obt_xml_attr_contains(n
, "place", "MenuItem"))
722 font
= &config_font_menuitem
;
723 else if (obt_xml_attr_contains(n
, "place", "ActiveOnScreenDisplay"))
724 font
= &config_font_activeosd
;
725 else if (obt_xml_attr_contains(n
, "place", "OnScreenDisplay"))
726 font
= &config_font_activeosd
;
727 else if (obt_xml_attr_contains(n
, "place","InactiveOnScreenDisplay"))
728 font
= &config_font_inactiveosd
;
732 if ((fnode
= obt_xml_find_node(n
->children
, "name"))) {
734 name
= obt_xml_node_string(fnode
);
736 if ((fnode
= obt_xml_find_node(n
->children
, "size"))) {
737 int s
= obt_xml_node_int(fnode
);
740 if ((fnode
= obt_xml_find_node(n
->children
, "weight"))) {
741 gchar
*w
= obt_xml_node_string(fnode
);
742 if (!g_ascii_strcasecmp(w
, "Bold"))
743 weight
= RR_FONTWEIGHT_BOLD
;
746 if ((fnode
= obt_xml_find_node(n
->children
, "slant"))) {
747 gchar
*s
= obt_xml_node_string(fnode
);
748 if (!g_ascii_strcasecmp(s
, "Italic"))
749 slant
= RR_FONTSLANT_ITALIC
;
750 if (!g_ascii_strcasecmp(s
, "Oblique"))
751 slant
= RR_FONTSLANT_OBLIQUE
;
755 *font
= RrFontOpen(ob_rr_inst
, name
, size
, weight
, slant
);
758 n
= obt_xml_find_node(n
->next
, "font");
762 static void parse_desktops(xmlNodePtr node
, gpointer d
)
766 node
= node
->children
;
768 if ((n
= obt_xml_find_node(node
, "number"))) {
769 gint d
= obt_xml_node_int(n
);
771 config_desktops_num
= (unsigned) d
;
773 if ((n
= obt_xml_find_node(node
, "firstdesk"))) {
774 gint d
= obt_xml_node_int(n
);
776 config_screen_firstdesk
= (unsigned) d
;
778 if ((n
= obt_xml_find_node(node
, "names"))) {
782 for (it
= config_desktops_names
; it
; it
= it
->next
)
784 g_slist_free(config_desktops_names
);
785 config_desktops_names
= NULL
;
787 nname
= obt_xml_find_node(n
->children
, "name");
789 config_desktops_names
=
790 g_slist_append(config_desktops_names
,
791 obt_xml_node_string(nname
));
792 nname
= obt_xml_find_node(nname
->next
, "name");
795 if ((n
= obt_xml_find_node(node
, "popupTime")))
796 config_desktop_popup_time
= obt_xml_node_int(n
);
799 static void parse_resize(xmlNodePtr node
, gpointer d
)
803 node
= node
->children
;
805 if ((n
= obt_xml_find_node(node
, "drawContents")))
806 config_resize_redraw
= obt_xml_node_bool(n
);
807 if ((n
= obt_xml_find_node(node
, "popupShow"))) {
808 config_resize_popup_show
= obt_xml_node_int(n
);
809 if (obt_xml_node_contains(n
, "Always"))
810 config_resize_popup_show
= 2;
811 else if (obt_xml_node_contains(n
, "Never"))
812 config_resize_popup_show
= 0;
813 else if (obt_xml_node_contains(n
, "Nonpixel"))
814 config_resize_popup_show
= 1;
816 if ((n
= obt_xml_find_node(node
, "popupPosition"))) {
817 if (obt_xml_node_contains(n
, "Top"))
818 config_resize_popup_pos
= OB_RESIZE_POS_TOP
;
819 else if (obt_xml_node_contains(n
, "Center"))
820 config_resize_popup_pos
= OB_RESIZE_POS_CENTER
;
821 else if (obt_xml_node_contains(n
, "Fixed")) {
822 config_resize_popup_pos
= OB_RESIZE_POS_FIXED
;
824 if ((n
= obt_xml_find_node(node
, "popupFixedPosition"))) {
827 if ((n2
= obt_xml_find_node(n
->children
, "x")))
828 config_parse_gravity_coord(n2
,
829 &config_resize_popup_fixed
.x
);
830 if ((n2
= obt_xml_find_node(n
->children
, "y")))
831 config_parse_gravity_coord(n2
,
832 &config_resize_popup_fixed
.y
);
834 config_resize_popup_fixed
.x
.pos
=
835 MAX(config_resize_popup_fixed
.x
.pos
, 0);
836 config_resize_popup_fixed
.y
.pos
=
837 MAX(config_resize_popup_fixed
.y
.pos
, 0);
843 static void parse_dock(xmlNodePtr node
, gpointer d
)
847 node
= node
->children
;
849 if ((n
= obt_xml_find_node(node
, "position"))) {
850 if (obt_xml_node_contains(n
, "TopLeft"))
851 config_dock_floating
= FALSE
,
852 config_dock_pos
= OB_DIRECTION_NORTHWEST
;
853 else if (obt_xml_node_contains(n
, "Top"))
854 config_dock_floating
= FALSE
,
855 config_dock_pos
= OB_DIRECTION_NORTH
;
856 else if (obt_xml_node_contains(n
, "TopRight"))
857 config_dock_floating
= FALSE
,
858 config_dock_pos
= OB_DIRECTION_NORTHEAST
;
859 else if (obt_xml_node_contains(n
, "Right"))
860 config_dock_floating
= FALSE
,
861 config_dock_pos
= OB_DIRECTION_EAST
;
862 else if (obt_xml_node_contains(n
, "BottomRight"))
863 config_dock_floating
= FALSE
,
864 config_dock_pos
= OB_DIRECTION_SOUTHEAST
;
865 else if (obt_xml_node_contains(n
, "Bottom"))
866 config_dock_floating
= FALSE
,
867 config_dock_pos
= OB_DIRECTION_SOUTH
;
868 else if (obt_xml_node_contains(n
, "BottomLeft"))
869 config_dock_floating
= FALSE
,
870 config_dock_pos
= OB_DIRECTION_SOUTHWEST
;
871 else if (obt_xml_node_contains(n
, "Left"))
872 config_dock_floating
= FALSE
,
873 config_dock_pos
= OB_DIRECTION_WEST
;
874 else if (obt_xml_node_contains(n
, "Floating"))
875 config_dock_floating
= TRUE
;
877 if (config_dock_floating
) {
878 if ((n
= obt_xml_find_node(node
, "floatingX")))
879 config_dock_x
= obt_xml_node_int(n
);
880 if ((n
= obt_xml_find_node(node
, "floatingY")))
881 config_dock_y
= obt_xml_node_int(n
);
883 if ((n
= obt_xml_find_node(node
, "noStrut")))
884 config_dock_nostrut
= obt_xml_node_bool(n
);
886 if ((n
= obt_xml_find_node(node
, "stacking"))) {
887 if (obt_xml_node_contains(n
, "normal"))
888 config_dock_layer
= OB_STACKING_LAYER_NORMAL
;
889 else if (obt_xml_node_contains(n
, "below"))
890 config_dock_layer
= OB_STACKING_LAYER_BELOW
;
891 else if (obt_xml_node_contains(n
, "above"))
892 config_dock_layer
= OB_STACKING_LAYER_ABOVE
;
894 if ((n
= obt_xml_find_node(node
, "direction"))) {
895 if (obt_xml_node_contains(n
, "horizontal"))
896 config_dock_orient
= OB_ORIENTATION_HORZ
;
897 else if (obt_xml_node_contains(n
, "vertical"))
898 config_dock_orient
= OB_ORIENTATION_VERT
;
900 if ((n
= obt_xml_find_node(node
, "autoHide")))
901 config_dock_hide
= obt_xml_node_bool(n
);
902 if ((n
= obt_xml_find_node(node
, "hideDelay")))
903 config_dock_hide_delay
= obt_xml_node_int(n
);
904 if ((n
= obt_xml_find_node(node
, "showDelay")))
905 config_dock_show_delay
= obt_xml_node_int(n
);
906 if ((n
= obt_xml_find_node(node
, "moveButton"))) {
907 gchar
*str
= obt_xml_node_string(n
);
909 if (translate_button(str
, &s
, &b
)) {
910 config_dock_app_move_button
= b
;
911 config_dock_app_move_modifiers
= s
;
913 g_message(_("Invalid button \"%s\" specified in config file"), str
);
919 static void parse_menu(xmlNodePtr node
, gpointer d
)
922 node
= node
->children
;
924 if ((n
= obt_xml_find_node(node
, "hideDelay")))
925 config_menu_hide_delay
= obt_xml_node_int(n
);
926 if ((n
= obt_xml_find_node(node
, "middle")))
927 config_menu_middle
= obt_xml_node_bool(n
);
928 if ((n
= obt_xml_find_node(node
, "submenuShowDelay")))
929 config_submenu_show_delay
= obt_xml_node_int(n
);
930 if ((n
= obt_xml_find_node(node
, "submenuHideDelay")))
931 config_submenu_hide_delay
= obt_xml_node_int(n
);
932 if ((n
= obt_xml_find_node(node
, "manageDesktops")))
933 config_menu_manage_desktops
= obt_xml_node_bool(n
);
934 if ((n
= obt_xml_find_node(node
, "showIcons"))) {
935 config_menu_show_icons
= obt_xml_node_bool(n
);
936 #if !defined(USE_IMLIB2) && !defined(USE_LIBRSVG)
937 if (config_menu_show_icons
)
938 g_message(_("Openbox was compiled without image loading support. Icons in menus will not be loaded."));
942 while ((node
= obt_xml_find_node(node
, "file"))) {
943 gchar
*c
= obt_xml_node_string(node
);
944 config_menu_files
= g_slist_append(config_menu_files
,
945 obt_paths_expand_tilde(c
));
951 static void parse_resistance(xmlNodePtr node
, gpointer d
)
955 node
= node
->children
;
956 if ((n
= obt_xml_find_node(node
, "strength")))
957 config_resist_win
= obt_xml_node_int(n
);
958 if ((n
= obt_xml_find_node(node
, "screen_edge_strength")))
959 config_resist_edge
= obt_xml_node_int(n
);
965 const gchar
*actname
;
968 static void bind_default_keyboard(void)
971 ObDefKeyBind binds
[] = {
972 { "A-Tab", "NextWindow" },
973 { "S-A-Tab", "PreviousWindow" },
977 for (it
= binds
; it
->key
; ++it
) {
978 GList
*l
= g_list_append(NULL
, g_strdup(it
->key
));
979 keyboard_bind(l
, actions_parse_string(it
->actname
));
986 const gchar
*context
;
987 const ObMouseAction mact
;
988 const gchar
*actname
;
991 static void bind_default_mouse(void)
994 ObDefMouseBind binds
[] = {
995 { "Left", "Client", OB_MOUSE_ACTION_PRESS
, "Focus" },
996 { "Middle", "Client", OB_MOUSE_ACTION_PRESS
, "Focus" },
997 { "Right", "Client", OB_MOUSE_ACTION_PRESS
, "Focus" },
998 { "Left", "Desktop", OB_MOUSE_ACTION_PRESS
, "Focus" },
999 { "Middle", "Desktop", OB_MOUSE_ACTION_PRESS
, "Focus" },
1000 { "Right", "Desktop", OB_MOUSE_ACTION_PRESS
, "Focus" },
1001 { "Left", "Titlebar", OB_MOUSE_ACTION_PRESS
, "Focus" },
1002 { "Left", "Bottom", OB_MOUSE_ACTION_PRESS
, "Focus" },
1003 { "Left", "BLCorner", OB_MOUSE_ACTION_PRESS
, "Focus" },
1004 { "Left", "BRCorner", OB_MOUSE_ACTION_PRESS
, "Focus" },
1005 { "Left", "TLCorner", OB_MOUSE_ACTION_PRESS
, "Focus" },
1006 { "Left", "TRCorner", OB_MOUSE_ACTION_PRESS
, "Focus" },
1007 { "Left", "Close", OB_MOUSE_ACTION_PRESS
, "Focus" },
1008 { "Left", "Maximize", OB_MOUSE_ACTION_PRESS
, "Focus" },
1009 { "Left", "Iconify", OB_MOUSE_ACTION_PRESS
, "Focus" },
1010 { "Left", "Icon", OB_MOUSE_ACTION_PRESS
, "Focus" },
1011 { "Left", "AllDesktops", OB_MOUSE_ACTION_PRESS
, "Focus" },
1012 { "Left", "Shade", OB_MOUSE_ACTION_PRESS
, "Focus" },
1013 { "Left", "Client", OB_MOUSE_ACTION_CLICK
, "Raise" },
1014 { "Left", "Titlebar", OB_MOUSE_ACTION_CLICK
, "Raise" },
1015 { "Middle", "Titlebar", OB_MOUSE_ACTION_CLICK
, "Lower" },
1016 { "Left", "BLCorner", OB_MOUSE_ACTION_CLICK
, "Raise" },
1017 { "Left", "BRCorner", OB_MOUSE_ACTION_CLICK
, "Raise" },
1018 { "Left", "TLCorner", OB_MOUSE_ACTION_CLICK
, "Raise" },
1019 { "Left", "TRCorner", OB_MOUSE_ACTION_CLICK
, "Raise" },
1020 { "Left", "Close", OB_MOUSE_ACTION_CLICK
, "Raise" },
1021 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK
, "Raise" },
1022 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK
, "Raise" },
1023 { "Left", "Icon", OB_MOUSE_ACTION_CLICK
, "Raise" },
1024 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK
, "Raise" },
1025 { "Left", "Shade", OB_MOUSE_ACTION_CLICK
, "Raise" },
1026 { "Left", "Close", OB_MOUSE_ACTION_CLICK
, "Close" },
1027 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK
, "ToggleMaximize" },
1028 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK
, "Iconify" },
1029 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK
, "ToggleOmnipresent" },
1030 { "Left", "Shade", OB_MOUSE_ACTION_CLICK
, "ToggleShade" },
1031 { "Left", "TLCorner", OB_MOUSE_ACTION_MOTION
, "Resize" },
1032 { "Left", "TRCorner", OB_MOUSE_ACTION_MOTION
, "Resize" },
1033 { "Left", "BLCorner", OB_MOUSE_ACTION_MOTION
, "Resize" },
1034 { "Left", "BRCorner", OB_MOUSE_ACTION_MOTION
, "Resize" },
1035 { "Left", "Top", OB_MOUSE_ACTION_MOTION
, "Resize" },
1036 { "Left", "Bottom", OB_MOUSE_ACTION_MOTION
, "Resize" },
1037 { "Left", "Left", OB_MOUSE_ACTION_MOTION
, "Resize" },
1038 { "Left", "Right", OB_MOUSE_ACTION_MOTION
, "Resize" },
1039 { "Left", "Titlebar", OB_MOUSE_ACTION_MOTION
, "Move" },
1040 { "A-Left", "Frame", OB_MOUSE_ACTION_MOTION
, "Move" },
1041 { "A-Middle", "Frame", OB_MOUSE_ACTION_MOTION
, "Resize" },
1042 { NULL
, NULL
, 0, NULL
}
1045 for (it
= binds
; it
->button
; ++it
)
1046 mouse_bind(it
->button
, frame_context_from_string(it
->context
),
1047 it
->mact
, actions_parse_string(it
->actname
));
1050 void config_startup(ObtXmlInst
*i
)
1052 config_focus_new
= TRUE
;
1053 config_focus_follow
= FALSE
;
1054 config_focus_delay
= 0;
1055 config_focus_raise
= FALSE
;
1056 config_focus_last
= TRUE
;
1057 config_focus_under_mouse
= FALSE
;
1058 config_unfocus_leave
= FALSE
;
1060 obt_xml_register(i
, "focus", parse_focus
, NULL
);
1062 config_place_policy
= OB_PLACE_POLICY_SMART
;
1063 config_place_center
= TRUE
;
1064 config_place_monitor
= OB_PLACE_MONITOR_PRIMARY
;
1066 config_primary_monitor_index
= 1;
1067 config_primary_monitor
= OB_PLACE_MONITOR_ACTIVE
;
1069 obt_xml_register(i
, "placement", parse_placement
, NULL
);
1071 STRUT_PARTIAL_SET(config_margins
, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1073 obt_xml_register(i
, "margins", parse_margins
, NULL
);
1075 config_theme
= NULL
;
1077 config_animate_iconify
= TRUE
;
1078 config_title_layout
= g_strdup("NLIMC");
1079 config_theme_keepborder
= TRUE
;
1080 config_theme_window_list_icon_size
= 36;
1082 config_font_activewindow
= NULL
;
1083 config_font_inactivewindow
= NULL
;
1084 config_font_menuitem
= NULL
;
1085 config_font_menutitle
= NULL
;
1086 config_font_activeosd
= NULL
;
1087 config_font_inactiveosd
= NULL
;
1089 obt_xml_register(i
, "theme", parse_theme
, NULL
);
1091 config_desktops_num
= 4;
1092 config_screen_firstdesk
= 1;
1093 config_desktops_names
= NULL
;
1094 config_desktop_popup_time
= 875;
1096 obt_xml_register(i
, "desktops", parse_desktops
, NULL
);
1098 config_resize_redraw
= TRUE
;
1099 config_resize_popup_show
= 1; /* nonpixel increments */
1100 config_resize_popup_pos
= OB_RESIZE_POS_CENTER
;
1101 GRAVITY_COORD_SET(config_resize_popup_fixed
.x
, 0, FALSE
, FALSE
);
1102 GRAVITY_COORD_SET(config_resize_popup_fixed
.y
, 0, FALSE
, FALSE
);
1104 obt_xml_register(i
, "resize", parse_resize
, NULL
);
1106 config_dock_layer
= OB_STACKING_LAYER_ABOVE
;
1107 config_dock_pos
= OB_DIRECTION_NORTHEAST
;
1108 config_dock_floating
= FALSE
;
1109 config_dock_nostrut
= FALSE
;
1112 config_dock_orient
= OB_ORIENTATION_VERT
;
1113 config_dock_hide
= FALSE
;
1114 config_dock_hide_delay
= 300;
1115 config_dock_show_delay
= 300;
1116 config_dock_app_move_button
= 2; /* middle */
1117 config_dock_app_move_modifiers
= 0;
1119 obt_xml_register(i
, "dock", parse_dock
, NULL
);
1121 translate_key("C-g", &config_keyboard_reset_state
,
1122 &config_keyboard_reset_keycode
);
1124 bind_default_keyboard();
1126 obt_xml_register(i
, "keyboard", parse_keyboard
, NULL
);
1128 config_mouse_threshold
= 8;
1129 config_mouse_dclicktime
= 500;
1130 config_mouse_screenedgetime
= 400;
1131 config_mouse_screenedgewarp
= FALSE
;
1133 bind_default_mouse();
1135 obt_xml_register(i
, "mouse", parse_mouse
, NULL
);
1137 config_resist_win
= 10;
1138 config_resist_edge
= 20;
1140 obt_xml_register(i
, "resistance", parse_resistance
, NULL
);
1142 config_menu_hide_delay
= 250;
1143 config_menu_middle
= FALSE
;
1144 config_submenu_show_delay
= 100;
1145 config_submenu_hide_delay
= 400;
1146 config_menu_manage_desktops
= TRUE
;
1147 config_menu_files
= NULL
;
1148 config_menu_show_icons
= TRUE
;
1150 obt_xml_register(i
, "menu", parse_menu
, NULL
);
1152 config_per_app_settings
= NULL
;
1154 obt_xml_register(i
, "applications", parse_per_app_settings
, NULL
);
1157 void config_shutdown(void)
1161 g_free(config_theme
);
1163 g_free(config_title_layout
);
1165 RrFontClose(config_font_activewindow
);
1166 RrFontClose(config_font_inactivewindow
);
1167 RrFontClose(config_font_menuitem
);
1168 RrFontClose(config_font_menutitle
);
1169 RrFontClose(config_font_activeosd
);
1170 RrFontClose(config_font_inactiveosd
);
1172 for (it
= config_desktops_names
; it
; it
= g_slist_next(it
))
1174 g_slist_free(config_desktops_names
);
1176 for (it
= config_menu_files
; it
; it
= g_slist_next(it
))
1178 g_slist_free(config_menu_files
);
1180 for (it
= config_per_app_settings
; it
; it
= g_slist_next(it
)) {
1181 ObAppSettings
*itd
= (ObAppSettings
*)it
->data
;
1182 if (itd
->name
) g_pattern_spec_free(itd
->name
);
1183 if (itd
->role
) g_pattern_spec_free(itd
->role
);
1184 if (itd
->title
) g_pattern_spec_free(itd
->title
);
1185 if (itd
->class) g_pattern_spec_free(itd
->class);
1186 if (itd
->group_name
) g_pattern_spec_free(itd
->group_name
);
1187 if (itd
->group_class
) g_pattern_spec_free(itd
->group_class
);
1188 g_slice_free(ObAppSettings
, it
->data
);
1190 g_slist_free(config_per_app_settings
);