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 ObPlaceMonitor config_place_monitor
;
42 guint config_primary_monitor_index
;
43 ObPlaceMonitor config_primary_monitor
;
45 StrutPartial config_margins
;
48 gboolean config_theme_keepborder
;
49 guint config_theme_window_list_icon_size
;
50 guint config_frame_flash_delay
;
51 guint config_frame_flash_duration
;
53 gchar
*config_title_layout
;
55 gboolean config_animate_iconify
;
57 RrFont
*config_font_activewindow
;
58 RrFont
*config_font_inactivewindow
;
59 RrFont
*config_font_menuitem
;
60 RrFont
*config_font_menutitle
;
61 RrFont
*config_font_activeosd
;
62 RrFont
*config_font_inactiveosd
;
64 guint config_desktops_num
;
65 GSList
*config_desktops_names
;
66 guint config_screen_firstdesk
;
67 guint config_desktop_popup_time
;
69 gboolean config_resize_redraw
;
70 gint config_resize_popup_show
;
71 ObResizePopupPos config_resize_popup_pos
;
72 GravityPoint config_resize_popup_fixed
;
74 ObStackingLayer config_dock_layer
;
75 gboolean config_dock_floating
;
76 gboolean config_dock_nostrut
;
77 ObDirection config_dock_pos
;
80 ObOrientation config_dock_orient
;
81 gboolean config_dock_hide
;
82 guint config_dock_hide_delay
;
83 guint config_dock_show_delay
;
84 guint config_dock_app_move_button
;
85 guint config_dock_app_move_modifiers
;
87 guint config_keyboard_reset_keycode
;
88 guint config_keyboard_reset_state
;
90 gint config_mouse_threshold
;
91 gint config_mouse_dclicktime
;
92 gint config_mouse_screenedgetime
;
93 gboolean config_mouse_screenedgewarp
;
95 guint config_menu_hide_delay
;
96 gboolean config_menu_middle
;
97 guint config_submenu_show_delay
;
98 guint config_submenu_hide_delay
;
99 gboolean config_menu_manage_desktops
;
100 gboolean config_menu_show_icons
;
102 GSList
*config_menu_files
;
104 gint config_resist_win
;
105 gint config_resist_edge
;
107 GSList
*config_per_app_settings
;
109 ObAppSettings
* config_create_app_settings(void)
111 ObAppSettings
*settings
= g_slice_new0(ObAppSettings
);
113 settings
->decor
= -1;
114 settings
->shade
= -1;
115 settings
->monitor_type
= OB_PLACE_MONITOR_ANY
;
116 settings
->monitor
= -1;
117 settings
->focus
= -1;
118 settings
->desktop
= 0;
119 settings
->layer
= -2;
120 settings
->iconic
= -1;
121 settings
->skip_pager
= -1;
122 settings
->skip_taskbar
= -1;
123 settings
->fullscreen
= -1;
124 settings
->max_horz
= -1;
125 settings
->max_vert
= -1;
126 settings
->opacity
= -1;
130 #define copy_if(setting, default) \
131 if (src->setting != default) dst->setting = src->setting
132 void config_app_settings_copy_non_defaults(const ObAppSettings
*src
,
135 g_assert(src
!= NULL
);
136 g_assert(dst
!= NULL
);
138 copy_if(type
, (ObClientType
)-1);
141 copy_if(monitor_type
, OB_PLACE_MONITOR_ANY
);
142 copy_if(monitor
, -1);
147 copy_if(skip_pager
, -1);
148 copy_if(skip_taskbar
, -1);
149 copy_if(fullscreen
, -1);
150 copy_if(max_horz
, -1);
151 copy_if(max_vert
, -1);
152 copy_if(opacity
, -1);
154 if (src
->pos_given
) {
155 dst
->pos_given
= TRUE
;
156 dst
->pos_force
= src
->pos_force
;
157 dst
->position
= src
->position
;
158 /* monitor is copied above */
161 if (src
->size_given
) {
162 dst
->size_given
= TRUE
;
163 dst
->width_num
= src
->width_num
;
164 dst
->width_denom
= src
->width_denom
;
165 dst
->height_num
= src
->height_num
;
166 dst
->height_denom
= src
->height_denom
;
170 void config_parse_relative_number(gchar
*s
, gint
*num
, gint
*denom
)
172 *num
= strtol(s
, &s
, 10);
176 } else if (*s
== '/') {
181 void config_parse_gravity_coord(xmlNodePtr node
, GravityCoord
*c
)
183 gchar
*s
= obt_xml_node_string(node
);
184 if (!g_ascii_strcasecmp(s
, "center"))
190 if (s
[0] == '-' || s
[0] == '+')
192 config_parse_relative_number(ps
, &c
->pos
, &c
->denom
);
199 <application name="aterm">
202 <application name="Rhythmbox">
209 .. there is a lot more settings available
214 static void parse_single_per_app_settings(xmlNodePtr app
,
215 ObAppSettings
*settings
)
218 gboolean x_pos_given
= FALSE
;
219 gboolean width_given
= FALSE
;
221 if ((n
= obt_xml_find_node(app
->children
, "decor")))
222 if (!obt_xml_node_contains(n
, "default"))
223 settings
->decor
= obt_xml_node_bool(n
);
225 if ((n
= obt_xml_find_node(app
->children
, "shade")))
226 if (!obt_xml_node_contains(n
, "default"))
227 settings
->shade
= obt_xml_node_bool(n
);
229 if ((n
= obt_xml_find_node(app
->children
, "position"))) {
230 if ((c
= obt_xml_find_node(n
->children
, "x"))) {
231 if (!obt_xml_node_contains(c
, "default")) {
232 config_parse_gravity_coord(c
, &settings
->position
.x
);
237 if (x_pos_given
&& (c
= obt_xml_find_node(n
->children
, "y"))) {
238 if (!obt_xml_node_contains(c
, "default")) {
239 config_parse_gravity_coord(c
, &settings
->position
.y
);
240 settings
->pos_given
= TRUE
;
244 /* monitor can be set without setting x or y */
245 if ((c
= obt_xml_find_node(n
->children
, "monitor"))) {
246 if (!obt_xml_node_contains(c
, "default")) {
247 gchar
*s
= obt_xml_node_string(c
);
248 if (!g_ascii_strcasecmp(s
, "mouse"))
249 settings
->monitor_type
= OB_PLACE_MONITOR_MOUSE
;
250 else if (!g_ascii_strcasecmp(s
, "active"))
251 settings
->monitor_type
= OB_PLACE_MONITOR_ACTIVE
;
252 else if (!g_ascii_strcasecmp(s
, "primary"))
253 settings
->monitor_type
= OB_PLACE_MONITOR_PRIMARY
;
255 settings
->monitor
= obt_xml_node_int(c
);
260 obt_xml_attr_bool(n
, "force", &settings
->pos_force
);
263 if ((n
= obt_xml_find_node(app
->children
, "size"))) {
264 if ((c
= obt_xml_find_node(n
->children
, "width"))) {
265 if (!obt_xml_node_contains(c
, "default")) {
266 gchar
*s
= obt_xml_node_string(c
);
267 config_parse_relative_number(s
,
268 &settings
->width_num
,
269 &settings
->width_denom
);
270 if (settings
->width_num
> 0 && settings
->width_denom
>= 0)
276 if (width_given
&& (c
= obt_xml_find_node(n
->children
, "height"))) {
277 gchar
*s
= obt_xml_node_string(c
);
278 config_parse_relative_number(s
,
279 &settings
->height_num
,
280 &settings
->height_denom
);
281 if (settings
->height_num
> 0 && settings
->height_denom
>= 0)
282 settings
->size_given
= TRUE
;
287 if ((n
= obt_xml_find_node(app
->children
, "focus"))) {
288 if (!obt_xml_node_contains(n
, "default"))
289 settings
->focus
= obt_xml_node_bool(n
);
292 if ((n
= obt_xml_find_node(app
->children
, "desktop"))) {
293 if (!obt_xml_node_contains(n
, "default")) {
294 gchar
*s
= obt_xml_node_string(n
);
295 if (!g_ascii_strcasecmp(s
, "all"))
296 settings
->desktop
= DESKTOP_ALL
;
298 gint i
= obt_xml_node_int(n
);
300 settings
->desktop
= i
;
306 if ((n
= obt_xml_find_node(app
->children
, "layer"))) {
307 if (!obt_xml_node_contains(n
, "default")) {
308 gchar
*s
= obt_xml_node_string(n
);
309 if (!g_ascii_strcasecmp(s
, "above"))
311 else if (!g_ascii_strcasecmp(s
, "below"))
312 settings
->layer
= -1;
319 if ((n
= obt_xml_find_node(app
->children
, "iconic")))
320 if (!obt_xml_node_contains(n
, "default"))
321 settings
->iconic
= obt_xml_node_bool(n
);
323 if ((n
= obt_xml_find_node(app
->children
, "skip_pager")))
324 if (!obt_xml_node_contains(n
, "default"))
325 settings
->skip_pager
= obt_xml_node_bool(n
);
327 if ((n
= obt_xml_find_node(app
->children
, "skip_taskbar")))
328 if (!obt_xml_node_contains(n
, "default"))
329 settings
->skip_taskbar
= obt_xml_node_bool(n
);
331 if ((n
= obt_xml_find_node(app
->children
, "fullscreen")))
332 if (!obt_xml_node_contains(n
, "default"))
333 settings
->fullscreen
= obt_xml_node_bool(n
);
335 if ((n
= obt_xml_find_node(app
->children
, "maximized"))) {
336 if (!obt_xml_node_contains(n
, "default")) {
337 gchar
*s
= obt_xml_node_string(n
);
338 if (!g_ascii_strcasecmp(s
, "horizontal")) {
339 settings
->max_horz
= TRUE
;
340 settings
->max_vert
= FALSE
;
341 } else if (!g_ascii_strcasecmp(s
, "vertical")) {
342 settings
->max_horz
= FALSE
;
343 settings
->max_vert
= TRUE
;
345 settings
->max_horz
= settings
->max_vert
=
346 obt_xml_node_bool(n
);
351 if ((n
= obt_xml_find_node(app
->children
, "opacity")))
352 if (!obt_xml_node_contains(n
, "default"))
353 settings
->opacity
= obt_xml_node_int(n
);
356 /* Manages settings for individual applications.
357 Some notes: monitor is the screen number in a multi monitor
358 (Xinerama) setup (starting from 0), or mouse: the monitor the pointer
359 is on, active: the active monitor, primary: the primary monitor.
360 Layer can be three values, above (Always on top), below
361 (Always on bottom) and everything else (normal behaviour).
362 Positions can be an integer value or center, which will
363 center the window in the specified axis. Position is within
364 the monitor, so <position><x>center</x></position><monitor>2</monitor>
365 will center the window on the second monitor.
367 static void parse_per_app_settings(xmlNodePtr node
, gpointer d
)
369 xmlNodePtr app
= obt_xml_find_node(node
->children
, "application");
370 for (; app
; app
= obt_xml_find_node(app
->next
, "application")) {
371 ObAppSettings
*settings
;
373 gboolean name_set
, class_set
, role_set
, title_set
,
374 type_set
, group_name_set
, group_class_set
;
375 gchar
*name
= NULL
, *class = NULL
, *role
= NULL
, *title
= NULL
,
376 *type_str
= NULL
, *group_name
= NULL
, *group_class
= NULL
;
379 class_set
= obt_xml_attr_string(app
, "class", &class);
380 name_set
= obt_xml_attr_string(app
, "name", &name
);
381 group_class_set
= obt_xml_attr_string(app
, "groupclass", &group_class
);
382 group_name_set
= obt_xml_attr_string(app
, "groupname", &group_name
);
383 type_set
= obt_xml_attr_string(app
, "type", &type_str
);
384 role_set
= obt_xml_attr_string(app
, "role", &role
);
385 title_set
= obt_xml_attr_string(app
, "title", &title
);
387 /* validate the type tho */
389 if (!g_ascii_strcasecmp(type_str
, "normal"))
390 type
= OB_CLIENT_TYPE_NORMAL
;
391 else if (!g_ascii_strcasecmp(type_str
, "dialog"))
392 type
= OB_CLIENT_TYPE_DIALOG
;
393 else if (!g_ascii_strcasecmp(type_str
, "splash"))
394 type
= OB_CLIENT_TYPE_SPLASH
;
395 else if (!g_ascii_strcasecmp(type_str
, "utility"))
396 type
= OB_CLIENT_TYPE_UTILITY
;
397 else if (!g_ascii_strcasecmp(type_str
, "menu"))
398 type
= OB_CLIENT_TYPE_MENU
;
399 else if (!g_ascii_strcasecmp(type_str
, "toolbar"))
400 type
= OB_CLIENT_TYPE_TOOLBAR
;
401 else if (!g_ascii_strcasecmp(type_str
, "dock"))
402 type
= OB_CLIENT_TYPE_DOCK
;
403 else if (!g_ascii_strcasecmp(type_str
, "desktop"))
404 type
= OB_CLIENT_TYPE_DESKTOP
;
406 type_set
= FALSE
; /* not valid! */
409 if (!(class_set
|| name_set
|| role_set
|| title_set
||
410 type_set
|| group_class_set
|| group_name_set
))
413 settings
= config_create_app_settings();
416 settings
->name
= g_pattern_spec_new(name
);
418 settings
->class = g_pattern_spec_new(class);
420 settings
->group_name
= g_pattern_spec_new(group_name
);
422 settings
->group_class
= g_pattern_spec_new(group_class
);
424 settings
->role
= g_pattern_spec_new(role
);
426 settings
->title
= g_pattern_spec_new(title
);
428 settings
->type
= type
;
438 parse_single_per_app_settings(app
, settings
);
439 config_per_app_settings
= g_slist_append(config_per_app_settings
,
447 <action name="ChangeDesktop">
454 static void parse_key(xmlNodePtr node
, GList
*keylist
)
456 gchar
*keystring
, **keys
, **key
;
458 gboolean is_chroot
= FALSE
;
460 if (!obt_xml_attr_string(node
, "key", &keystring
))
463 obt_xml_attr_bool(node
, "chroot", &is_chroot
);
465 keys
= g_strsplit(keystring
, " ", 0);
466 for (key
= keys
; *key
; ++key
) {
467 keylist
= g_list_append(keylist
, *key
);
469 if ((n
= obt_xml_find_node(node
->children
, "keybind"))) {
471 parse_key(n
, keylist
);
472 n
= obt_xml_find_node(n
->next
, "keybind");
475 else if ((n
= obt_xml_find_node(node
->children
, "action"))) {
477 ObActionsAct
*action
;
479 action
= actions_parse(n
);
481 keyboard_bind(keylist
, action
);
482 n
= obt_xml_find_node(n
->next
, "action");
488 keyboard_chroot(keylist
);
489 keylist
= g_list_delete_link(keylist
, g_list_last(keylist
));
496 static void parse_keyboard(xmlNodePtr node
, gpointer d
)
501 keyboard_unbind_all();
503 if ((n
= obt_xml_find_node(node
->children
, "chainQuitKey"))) {
504 key
= obt_xml_node_string(n
);
505 translate_key(key
, &config_keyboard_reset_state
,
506 &config_keyboard_reset_keycode
);
510 if ((n
= obt_xml_find_node(node
->children
, "keybind")))
513 n
= obt_xml_find_node(n
->next
, "keybind");
519 <context name="Titlebar">
520 <mousebind button="Left" action="Press">
521 <action name="Raise"></action>
527 static void parse_mouse(xmlNodePtr node
, gpointer d
)
529 xmlNodePtr n
, nbut
, nact
;
536 node
= node
->children
;
538 if ((n
= obt_xml_find_node(node
, "dragThreshold")))
539 config_mouse_threshold
= obt_xml_node_int(n
);
540 if ((n
= obt_xml_find_node(node
, "doubleClickTime")))
541 config_mouse_dclicktime
= obt_xml_node_int(n
);
542 if ((n
= obt_xml_find_node(node
, "screenEdgeWarpTime"))) {
543 config_mouse_screenedgetime
= obt_xml_node_int(n
);
544 /* minimum value of 25 for this property, when it is 1 and you hit the
545 edge it basically never stops */
546 if (config_mouse_screenedgetime
&& config_mouse_screenedgetime
< 25)
547 config_mouse_screenedgetime
= 25;
549 if ((n
= obt_xml_find_node(node
, "screenEdgeWarpMouse")))
550 config_mouse_screenedgewarp
= obt_xml_node_bool(n
);
552 n
= obt_xml_find_node(node
, "context");
557 if (!obt_xml_attr_string(n
, "name", &cxstr
))
560 modcxstr
= g_strdup(cxstr
); /* make a copy to mutilate */
561 while (frame_next_context_from_string(modcxstr
, &cx
)) {
563 gchar
*s
= strchr(modcxstr
, ' ');
566 g_message(_("Invalid context \"%s\" in mouse binding"),
573 nbut
= obt_xml_find_node(n
->children
, "mousebind");
575 if (!obt_xml_attr_string(nbut
, "button", &buttonstr
))
577 if (obt_xml_attr_contains(nbut
, "action", "press"))
578 mact
= OB_MOUSE_ACTION_PRESS
;
579 else if (obt_xml_attr_contains(nbut
, "action", "release"))
580 mact
= OB_MOUSE_ACTION_RELEASE
;
581 else if (obt_xml_attr_contains(nbut
, "action", "click"))
582 mact
= OB_MOUSE_ACTION_CLICK
;
583 else if (obt_xml_attr_contains(nbut
, "action","doubleclick"))
584 mact
= OB_MOUSE_ACTION_DOUBLE_CLICK
;
585 else if (obt_xml_attr_contains(nbut
, "action", "drag"))
586 mact
= OB_MOUSE_ACTION_MOTION
;
590 nact
= obt_xml_find_node(nbut
->children
, "action");
592 ObActionsAct
*action
;
594 if ((action
= actions_parse(nact
)))
595 mouse_bind(buttonstr
, cx
, mact
, action
);
596 nact
= obt_xml_find_node(nact
->next
, "action");
600 nbut
= obt_xml_find_node(nbut
->next
, "mousebind");
606 n
= obt_xml_find_node(n
->next
, "context");
610 static void parse_focus(xmlNodePtr node
, gpointer d
)
614 node
= node
->children
;
616 if ((n
= obt_xml_find_node(node
, "focusNew")))
617 config_focus_new
= obt_xml_node_bool(n
);
618 if ((n
= obt_xml_find_node(node
, "followMouse")))
619 config_focus_follow
= obt_xml_node_bool(n
);
620 if ((n
= obt_xml_find_node(node
, "focusDelay")))
621 config_focus_delay
= obt_xml_node_int(n
);
622 if ((n
= obt_xml_find_node(node
, "raiseOnFocus")))
623 config_focus_raise
= obt_xml_node_bool(n
);
624 if ((n
= obt_xml_find_node(node
, "focusLast")))
625 config_focus_last
= obt_xml_node_bool(n
);
626 if ((n
= obt_xml_find_node(node
, "underMouse")))
627 config_focus_under_mouse
= obt_xml_node_bool(n
);
628 if ((n
= obt_xml_find_node(node
, "unfocusOnLeave")))
629 config_unfocus_leave
= obt_xml_node_bool(n
);
632 static void parse_placement(xmlNodePtr node
, gpointer d
)
636 node
= node
->children
;
638 if ((n
= obt_xml_find_node(node
, "policy")))
639 if (obt_xml_node_contains(n
, "UnderMouse"))
640 config_place_policy
= OB_PLACE_POLICY_MOUSE
;
641 if ((n
= obt_xml_find_node(node
, "monitor"))) {
642 if (obt_xml_node_contains(n
, "active"))
643 config_place_monitor
= OB_PLACE_MONITOR_ACTIVE
;
644 else if (obt_xml_node_contains(n
, "mouse"))
645 config_place_monitor
= OB_PLACE_MONITOR_MOUSE
;
646 else if (obt_xml_node_contains(n
, "any"))
647 config_place_monitor
= OB_PLACE_MONITOR_ANY
;
649 if ((n
= obt_xml_find_node(node
, "primaryMonitor"))) {
650 config_primary_monitor_index
= obt_xml_node_int(n
);
651 if (!config_primary_monitor_index
) {
652 if (obt_xml_node_contains(n
, "mouse"))
653 config_primary_monitor
= OB_PLACE_MONITOR_MOUSE
;
658 static void parse_margins(xmlNodePtr node
, gpointer d
)
662 node
= node
->children
;
664 if ((n
= obt_xml_find_node(node
, "top")))
665 config_margins
.top
= MAX(0, obt_xml_node_int(n
));
666 if ((n
= obt_xml_find_node(node
, "left")))
667 config_margins
.left
= MAX(0, obt_xml_node_int(n
));
668 if ((n
= obt_xml_find_node(node
, "right")))
669 config_margins
.right
= MAX(0, obt_xml_node_int(n
));
670 if ((n
= obt_xml_find_node(node
, "bottom")))
671 config_margins
.bottom
= MAX(0, obt_xml_node_int(n
));
674 static void parse_theme(xmlNodePtr node
, gpointer d
)
678 node
= node
->children
;
680 if ((n
= obt_xml_find_node(node
, "name"))) {
683 g_free(config_theme
);
684 c
= obt_xml_node_string(n
);
685 config_theme
= obt_paths_expand_tilde(c
);
688 if ((n
= obt_xml_find_node(node
, "titleLayout"))) {
691 g_free(config_title_layout
);
692 config_title_layout
= obt_xml_node_string(n
);
694 /* replace duplicates with spaces */
695 for (c
= config_title_layout
; *c
!= '\0'; ++c
)
696 for (d
= c
+1; *d
!= '\0'; ++d
)
697 if (*c
== *d
) *d
= ' ';
699 if ((n
= obt_xml_find_node(node
, "keepBorder")))
700 config_theme_keepborder
= obt_xml_node_bool(n
);
701 if ((n
= obt_xml_find_node(node
, "animateIconify")))
702 config_animate_iconify
= obt_xml_node_bool(n
);
703 if ((n
= obt_xml_find_node(node
, "windowListIconSize"))) {
704 config_theme_window_list_icon_size
= obt_xml_node_int(n
);
705 if (config_theme_window_list_icon_size
< 16)
706 config_theme_window_list_icon_size
= 16;
707 else if (config_theme_window_list_icon_size
> 96)
708 config_theme_window_list_icon_size
= 96;
710 if ((n
= obt_xml_find_node(node
, "flashFrameDelay")))
711 config_frame_flash_delay
= obt_xml_node_int(n
);
712 if ((n
= obt_xml_find_node(node
, "flashFrameDuration")))
713 config_frame_flash_duration
= obt_xml_node_int(n
);
715 n
= obt_xml_find_node(node
, "font");
719 gchar
*name
= g_strdup(RrDefaultFontFamily
);
720 gint size
= RrDefaultFontSize
;
721 RrFontWeight weight
= RrDefaultFontWeight
;
722 RrFontSlant slant
= RrDefaultFontSlant
;
724 if (obt_xml_attr_contains(n
, "place", "ActiveWindow"))
725 font
= &config_font_activewindow
;
726 else if (obt_xml_attr_contains(n
, "place", "InactiveWindow"))
727 font
= &config_font_inactivewindow
;
728 else if (obt_xml_attr_contains(n
, "place", "MenuHeader"))
729 font
= &config_font_menutitle
;
730 else if (obt_xml_attr_contains(n
, "place", "MenuItem"))
731 font
= &config_font_menuitem
;
732 else if (obt_xml_attr_contains(n
, "place", "ActiveOnScreenDisplay"))
733 font
= &config_font_activeosd
;
734 else if (obt_xml_attr_contains(n
, "place", "OnScreenDisplay"))
735 font
= &config_font_activeosd
;
736 else if (obt_xml_attr_contains(n
, "place","InactiveOnScreenDisplay"))
737 font
= &config_font_inactiveosd
;
741 if ((fnode
= obt_xml_find_node(n
->children
, "name"))) {
743 name
= obt_xml_node_string(fnode
);
745 if ((fnode
= obt_xml_find_node(n
->children
, "size"))) {
746 int s
= obt_xml_node_int(fnode
);
749 if ((fnode
= obt_xml_find_node(n
->children
, "weight"))) {
750 gchar
*w
= obt_xml_node_string(fnode
);
751 if (!g_ascii_strcasecmp(w
, "Bold"))
752 weight
= RR_FONTWEIGHT_BOLD
;
755 if ((fnode
= obt_xml_find_node(n
->children
, "slant"))) {
756 gchar
*s
= obt_xml_node_string(fnode
);
757 if (!g_ascii_strcasecmp(s
, "Italic"))
758 slant
= RR_FONTSLANT_ITALIC
;
759 if (!g_ascii_strcasecmp(s
, "Oblique"))
760 slant
= RR_FONTSLANT_OBLIQUE
;
764 *font
= RrFontOpen(ob_rr_inst
, name
, size
, weight
, slant
);
767 n
= obt_xml_find_node(n
->next
, "font");
771 static void parse_desktops(xmlNodePtr node
, gpointer d
)
775 node
= node
->children
;
777 if ((n
= obt_xml_find_node(node
, "number"))) {
778 gint d
= obt_xml_node_int(n
);
780 config_desktops_num
= (unsigned) d
;
782 if ((n
= obt_xml_find_node(node
, "firstdesk"))) {
783 gint d
= obt_xml_node_int(n
);
785 config_screen_firstdesk
= (unsigned) d
;
787 if ((n
= obt_xml_find_node(node
, "names"))) {
791 for (it
= config_desktops_names
; it
; it
= it
->next
)
793 g_slist_free(config_desktops_names
);
794 config_desktops_names
= NULL
;
796 nname
= obt_xml_find_node(n
->children
, "name");
798 config_desktops_names
=
799 g_slist_append(config_desktops_names
,
800 obt_xml_node_string(nname
));
801 nname
= obt_xml_find_node(nname
->next
, "name");
804 if ((n
= obt_xml_find_node(node
, "popupTime")))
805 config_desktop_popup_time
= obt_xml_node_int(n
);
808 static void parse_resize(xmlNodePtr node
, gpointer d
)
812 node
= node
->children
;
814 if ((n
= obt_xml_find_node(node
, "drawContents")))
815 config_resize_redraw
= obt_xml_node_bool(n
);
816 if ((n
= obt_xml_find_node(node
, "popupShow"))) {
817 config_resize_popup_show
= obt_xml_node_int(n
);
818 if (obt_xml_node_contains(n
, "Always"))
819 config_resize_popup_show
= 2;
820 else if (obt_xml_node_contains(n
, "Never"))
821 config_resize_popup_show
= 0;
822 else if (obt_xml_node_contains(n
, "Nonpixel"))
823 config_resize_popup_show
= 1;
825 if ((n
= obt_xml_find_node(node
, "popupPosition"))) {
826 if (obt_xml_node_contains(n
, "Top"))
827 config_resize_popup_pos
= OB_RESIZE_POS_TOP
;
828 else if (obt_xml_node_contains(n
, "Center"))
829 config_resize_popup_pos
= OB_RESIZE_POS_CENTER
;
830 else if (obt_xml_node_contains(n
, "Fixed")) {
831 config_resize_popup_pos
= OB_RESIZE_POS_FIXED
;
833 if ((n
= obt_xml_find_node(node
, "popupFixedPosition"))) {
836 if ((n2
= obt_xml_find_node(n
->children
, "x")))
837 config_parse_gravity_coord(n2
,
838 &config_resize_popup_fixed
.x
);
839 if ((n2
= obt_xml_find_node(n
->children
, "y")))
840 config_parse_gravity_coord(n2
,
841 &config_resize_popup_fixed
.y
);
843 config_resize_popup_fixed
.x
.pos
=
844 MAX(config_resize_popup_fixed
.x
.pos
, 0);
845 config_resize_popup_fixed
.y
.pos
=
846 MAX(config_resize_popup_fixed
.y
.pos
, 0);
852 static void parse_dock(xmlNodePtr node
, gpointer d
)
856 node
= node
->children
;
858 if ((n
= obt_xml_find_node(node
, "position"))) {
859 if (obt_xml_node_contains(n
, "TopLeft"))
860 config_dock_floating
= FALSE
,
861 config_dock_pos
= OB_DIRECTION_NORTHWEST
;
862 else if (obt_xml_node_contains(n
, "Top"))
863 config_dock_floating
= FALSE
,
864 config_dock_pos
= OB_DIRECTION_NORTH
;
865 else if (obt_xml_node_contains(n
, "TopRight"))
866 config_dock_floating
= FALSE
,
867 config_dock_pos
= OB_DIRECTION_NORTHEAST
;
868 else if (obt_xml_node_contains(n
, "Right"))
869 config_dock_floating
= FALSE
,
870 config_dock_pos
= OB_DIRECTION_EAST
;
871 else if (obt_xml_node_contains(n
, "BottomRight"))
872 config_dock_floating
= FALSE
,
873 config_dock_pos
= OB_DIRECTION_SOUTHEAST
;
874 else if (obt_xml_node_contains(n
, "Bottom"))
875 config_dock_floating
= FALSE
,
876 config_dock_pos
= OB_DIRECTION_SOUTH
;
877 else if (obt_xml_node_contains(n
, "BottomLeft"))
878 config_dock_floating
= FALSE
,
879 config_dock_pos
= OB_DIRECTION_SOUTHWEST
;
880 else if (obt_xml_node_contains(n
, "Left"))
881 config_dock_floating
= FALSE
,
882 config_dock_pos
= OB_DIRECTION_WEST
;
883 else if (obt_xml_node_contains(n
, "Floating"))
884 config_dock_floating
= TRUE
;
886 if (config_dock_floating
) {
887 if ((n
= obt_xml_find_node(node
, "floatingX")))
888 config_dock_x
= obt_xml_node_int(n
);
889 if ((n
= obt_xml_find_node(node
, "floatingY")))
890 config_dock_y
= obt_xml_node_int(n
);
892 if ((n
= obt_xml_find_node(node
, "noStrut")))
893 config_dock_nostrut
= obt_xml_node_bool(n
);
895 if ((n
= obt_xml_find_node(node
, "stacking"))) {
896 if (obt_xml_node_contains(n
, "normal"))
897 config_dock_layer
= OB_STACKING_LAYER_NORMAL
;
898 else if (obt_xml_node_contains(n
, "below"))
899 config_dock_layer
= OB_STACKING_LAYER_BELOW
;
900 else if (obt_xml_node_contains(n
, "above"))
901 config_dock_layer
= OB_STACKING_LAYER_ABOVE
;
903 if ((n
= obt_xml_find_node(node
, "direction"))) {
904 if (obt_xml_node_contains(n
, "horizontal"))
905 config_dock_orient
= OB_ORIENTATION_HORZ
;
906 else if (obt_xml_node_contains(n
, "vertical"))
907 config_dock_orient
= OB_ORIENTATION_VERT
;
909 if ((n
= obt_xml_find_node(node
, "autoHide")))
910 config_dock_hide
= obt_xml_node_bool(n
);
911 if ((n
= obt_xml_find_node(node
, "hideDelay")))
912 config_dock_hide_delay
= obt_xml_node_int(n
);
913 if ((n
= obt_xml_find_node(node
, "showDelay")))
914 config_dock_show_delay
= obt_xml_node_int(n
);
915 if ((n
= obt_xml_find_node(node
, "moveButton"))) {
916 gchar
*str
= obt_xml_node_string(n
);
918 if (translate_button(str
, &s
, &b
)) {
919 config_dock_app_move_button
= b
;
920 config_dock_app_move_modifiers
= s
;
922 g_message(_("Invalid button \"%s\" specified in config file"), str
);
928 static void parse_menu(xmlNodePtr node
, gpointer d
)
931 node
= node
->children
;
933 if ((n
= obt_xml_find_node(node
, "hideDelay")))
934 config_menu_hide_delay
= obt_xml_node_int(n
);
935 if ((n
= obt_xml_find_node(node
, "middle")))
936 config_menu_middle
= obt_xml_node_bool(n
);
937 if ((n
= obt_xml_find_node(node
, "submenuShowDelay")))
938 config_submenu_show_delay
= obt_xml_node_int(n
);
939 if ((n
= obt_xml_find_node(node
, "submenuHideDelay")))
940 config_submenu_hide_delay
= obt_xml_node_int(n
);
941 if ((n
= obt_xml_find_node(node
, "manageDesktops")))
942 config_menu_manage_desktops
= obt_xml_node_bool(n
);
943 if ((n
= obt_xml_find_node(node
, "showIcons"))) {
944 config_menu_show_icons
= obt_xml_node_bool(n
);
946 if (config_menu_show_icons
)
947 g_message(_("Openbox was compiled without Imlib2 image loading support. Icons in menus will not be loaded."));
951 while ((node
= obt_xml_find_node(node
, "file"))) {
952 gchar
*c
= obt_xml_node_string(node
);
953 config_menu_files
= g_slist_append(config_menu_files
,
954 obt_paths_expand_tilde(c
));
960 static void parse_resistance(xmlNodePtr node
, gpointer d
)
964 node
= node
->children
;
965 if ((n
= obt_xml_find_node(node
, "strength")))
966 config_resist_win
= obt_xml_node_int(n
);
967 if ((n
= obt_xml_find_node(node
, "screen_edge_strength")))
968 config_resist_edge
= obt_xml_node_int(n
);
974 const gchar
*actname
;
977 static void bind_default_keyboard(void)
980 ObDefKeyBind binds
[] = {
981 { "A-Tab", "NextWindow" },
982 { "S-A-Tab", "PreviousWindow" },
986 for (it
= binds
; it
->key
; ++it
) {
987 GList
*l
= g_list_append(NULL
, g_strdup(it
->key
));
988 keyboard_bind(l
, actions_parse_string(it
->actname
));
995 const gchar
*context
;
996 const ObMouseAction mact
;
997 const gchar
*actname
;
1000 static void bind_default_mouse(void)
1003 ObDefMouseBind binds
[] = {
1004 { "Left", "Client", OB_MOUSE_ACTION_PRESS
, "Focus" },
1005 { "Middle", "Client", OB_MOUSE_ACTION_PRESS
, "Focus" },
1006 { "Right", "Client", OB_MOUSE_ACTION_PRESS
, "Focus" },
1007 { "Left", "Desktop", OB_MOUSE_ACTION_PRESS
, "Focus" },
1008 { "Middle", "Desktop", OB_MOUSE_ACTION_PRESS
, "Focus" },
1009 { "Right", "Desktop", OB_MOUSE_ACTION_PRESS
, "Focus" },
1010 { "Left", "Titlebar", OB_MOUSE_ACTION_PRESS
, "Focus" },
1011 { "Left", "Bottom", OB_MOUSE_ACTION_PRESS
, "Focus" },
1012 { "Left", "BLCorner", OB_MOUSE_ACTION_PRESS
, "Focus" },
1013 { "Left", "BRCorner", OB_MOUSE_ACTION_PRESS
, "Focus" },
1014 { "Left", "TLCorner", OB_MOUSE_ACTION_PRESS
, "Focus" },
1015 { "Left", "TRCorner", OB_MOUSE_ACTION_PRESS
, "Focus" },
1016 { "Left", "Close", OB_MOUSE_ACTION_PRESS
, "Focus" },
1017 { "Left", "Maximize", OB_MOUSE_ACTION_PRESS
, "Focus" },
1018 { "Left", "Iconify", OB_MOUSE_ACTION_PRESS
, "Focus" },
1019 { "Left", "Icon", OB_MOUSE_ACTION_PRESS
, "Focus" },
1020 { "Left", "AllDesktops", OB_MOUSE_ACTION_PRESS
, "Focus" },
1021 { "Left", "Shade", OB_MOUSE_ACTION_PRESS
, "Focus" },
1022 { "Left", "Client", OB_MOUSE_ACTION_CLICK
, "Raise" },
1023 { "Left", "Titlebar", OB_MOUSE_ACTION_CLICK
, "Raise" },
1024 { "Middle", "Titlebar", OB_MOUSE_ACTION_CLICK
, "Lower" },
1025 { "Left", "BLCorner", OB_MOUSE_ACTION_CLICK
, "Raise" },
1026 { "Left", "BRCorner", OB_MOUSE_ACTION_CLICK
, "Raise" },
1027 { "Left", "TLCorner", OB_MOUSE_ACTION_CLICK
, "Raise" },
1028 { "Left", "TRCorner", OB_MOUSE_ACTION_CLICK
, "Raise" },
1029 { "Left", "Close", OB_MOUSE_ACTION_CLICK
, "Raise" },
1030 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK
, "Raise" },
1031 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK
, "Raise" },
1032 { "Left", "Icon", OB_MOUSE_ACTION_CLICK
, "Raise" },
1033 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK
, "Raise" },
1034 { "Left", "Shade", OB_MOUSE_ACTION_CLICK
, "Raise" },
1035 { "Left", "Close", OB_MOUSE_ACTION_CLICK
, "Close" },
1036 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK
, "ToggleMaximize" },
1037 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK
, "Iconify" },
1038 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK
, "ToggleOmnipresent" },
1039 { "Left", "Shade", OB_MOUSE_ACTION_CLICK
, "ToggleShade" },
1040 { "Left", "TLCorner", OB_MOUSE_ACTION_MOTION
, "Resize" },
1041 { "Left", "TRCorner", OB_MOUSE_ACTION_MOTION
, "Resize" },
1042 { "Left", "BLCorner", OB_MOUSE_ACTION_MOTION
, "Resize" },
1043 { "Left", "BRCorner", OB_MOUSE_ACTION_MOTION
, "Resize" },
1044 { "Left", "Top", OB_MOUSE_ACTION_MOTION
, "Resize" },
1045 { "Left", "Bottom", OB_MOUSE_ACTION_MOTION
, "Resize" },
1046 { "Left", "Left", OB_MOUSE_ACTION_MOTION
, "Resize" },
1047 { "Left", "Right", OB_MOUSE_ACTION_MOTION
, "Resize" },
1048 { "Left", "Titlebar", OB_MOUSE_ACTION_MOTION
, "Move" },
1049 { "A-Left", "Frame", OB_MOUSE_ACTION_MOTION
, "Move" },
1050 { "A-Middle", "Frame", OB_MOUSE_ACTION_MOTION
, "Resize" },
1051 { NULL
, NULL
, 0, NULL
}
1054 for (it
= binds
; it
->button
; ++it
)
1055 mouse_bind(it
->button
, frame_context_from_string(it
->context
),
1056 it
->mact
, actions_parse_string(it
->actname
));
1059 void config_startup(ObtXmlInst
*i
)
1061 config_focus_new
= TRUE
;
1062 config_focus_follow
= FALSE
;
1063 config_focus_delay
= 0;
1064 config_focus_raise
= FALSE
;
1065 config_focus_last
= TRUE
;
1066 config_focus_under_mouse
= FALSE
;
1067 config_unfocus_leave
= FALSE
;
1069 obt_xml_register(i
, "focus", parse_focus
, NULL
);
1071 config_place_policy
= OB_PLACE_POLICY_SMART
;
1072 config_place_monitor
= OB_PLACE_MONITOR_PRIMARY
;
1074 config_primary_monitor_index
= 1;
1075 config_primary_monitor
= OB_PLACE_MONITOR_ACTIVE
;
1077 obt_xml_register(i
, "placement", parse_placement
, NULL
);
1079 STRUT_PARTIAL_SET(config_margins
, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1081 obt_xml_register(i
, "margins", parse_margins
, NULL
);
1083 config_theme
= NULL
;
1085 config_animate_iconify
= TRUE
;
1086 config_title_layout
= g_strdup("NLIMC");
1087 config_theme_keepborder
= TRUE
;
1088 config_theme_window_list_icon_size
= 36;
1089 config_frame_flash_delay
= 600;
1090 config_frame_flash_duration
= 5000;
1092 config_font_activewindow
= NULL
;
1093 config_font_inactivewindow
= NULL
;
1094 config_font_menuitem
= NULL
;
1095 config_font_menutitle
= NULL
;
1096 config_font_activeosd
= NULL
;
1097 config_font_inactiveosd
= NULL
;
1099 obt_xml_register(i
, "theme", parse_theme
, NULL
);
1101 config_desktops_num
= 4;
1102 config_screen_firstdesk
= 1;
1103 config_desktops_names
= NULL
;
1104 config_desktop_popup_time
= 875;
1106 obt_xml_register(i
, "desktops", parse_desktops
, NULL
);
1108 config_resize_redraw
= TRUE
;
1109 config_resize_popup_show
= 1; /* nonpixel increments */
1110 config_resize_popup_pos
= OB_RESIZE_POS_CENTER
;
1111 GRAVITY_COORD_SET(config_resize_popup_fixed
.x
, 0, FALSE
, FALSE
);
1112 GRAVITY_COORD_SET(config_resize_popup_fixed
.y
, 0, FALSE
, FALSE
);
1114 obt_xml_register(i
, "resize", parse_resize
, NULL
);
1116 config_dock_layer
= OB_STACKING_LAYER_ABOVE
;
1117 config_dock_pos
= OB_DIRECTION_NORTHEAST
;
1118 config_dock_floating
= FALSE
;
1119 config_dock_nostrut
= FALSE
;
1122 config_dock_orient
= OB_ORIENTATION_VERT
;
1123 config_dock_hide
= FALSE
;
1124 config_dock_hide_delay
= 300;
1125 config_dock_show_delay
= 300;
1126 config_dock_app_move_button
= 2; /* middle */
1127 config_dock_app_move_modifiers
= 0;
1129 obt_xml_register(i
, "dock", parse_dock
, NULL
);
1131 translate_key("C-g", &config_keyboard_reset_state
,
1132 &config_keyboard_reset_keycode
);
1134 bind_default_keyboard();
1136 obt_xml_register(i
, "keyboard", parse_keyboard
, NULL
);
1138 config_mouse_threshold
= 8;
1139 config_mouse_dclicktime
= 500;
1140 config_mouse_screenedgetime
= 400;
1141 config_mouse_screenedgewarp
= FALSE
;
1143 bind_default_mouse();
1145 obt_xml_register(i
, "mouse", parse_mouse
, NULL
);
1147 config_resist_win
= 10;
1148 config_resist_edge
= 20;
1150 obt_xml_register(i
, "resistance", parse_resistance
, NULL
);
1152 config_menu_hide_delay
= 250;
1153 config_menu_middle
= FALSE
;
1154 config_submenu_show_delay
= 100;
1155 config_submenu_hide_delay
= 400;
1156 config_menu_manage_desktops
= TRUE
;
1157 config_menu_files
= NULL
;
1158 config_menu_show_icons
= TRUE
;
1160 obt_xml_register(i
, "menu", parse_menu
, NULL
);
1162 config_per_app_settings
= NULL
;
1164 obt_xml_register(i
, "applications", parse_per_app_settings
, NULL
);
1167 void config_shutdown(void)
1171 g_free(config_theme
);
1173 g_free(config_title_layout
);
1175 RrFontClose(config_font_activewindow
);
1176 RrFontClose(config_font_inactivewindow
);
1177 RrFontClose(config_font_menuitem
);
1178 RrFontClose(config_font_menutitle
);
1179 RrFontClose(config_font_activeosd
);
1180 RrFontClose(config_font_inactiveosd
);
1182 for (it
= config_desktops_names
; it
; it
= g_slist_next(it
))
1184 g_slist_free(config_desktops_names
);
1186 for (it
= config_menu_files
; it
; it
= g_slist_next(it
))
1188 g_slist_free(config_menu_files
);
1190 for (it
= config_per_app_settings
; it
; it
= g_slist_next(it
)) {
1191 ObAppSettings
*itd
= (ObAppSettings
*)it
->data
;
1192 if (itd
->name
) g_pattern_spec_free(itd
->name
);
1193 if (itd
->role
) g_pattern_spec_free(itd
->role
);
1194 if (itd
->title
) g_pattern_spec_free(itd
->title
);
1195 if (itd
->class) g_pattern_spec_free(itd
->class);
1196 if (itd
->group_name
) g_pattern_spec_free(itd
->group_name
);
1197 if (itd
->group_class
) g_pattern_spec_free(itd
->group_class
);
1198 g_slice_free(ObAppSettings
, it
->data
);
1200 g_slist_free(config_per_app_settings
);