]> Dogcows Code - chaz/openbox/blob - openbox/config.c
lower the default submenu show delay
[chaz/openbox] / openbox / config.c
1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
2
3 config.c for the Openbox window manager
4 Copyright (c) 2006 Mikael Magnusson
5 Copyright (c) 2003-2007 Dana Jansens
6
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.
11
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.
16
17 See the COPYING file for a copy of the GNU General Public License.
18 */
19
20 #include "config.h"
21 #include "keyboard.h"
22 #include "mouse.h"
23 #include "actions.h"
24 #include "translate.h"
25 #include "client.h"
26 #include "screen.h"
27 #include "openbox.h"
28 #include "gettext.h"
29 #include "obt/paths.h"
30
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;
38
39 ObPlacePolicy config_place_policy;
40 gboolean config_place_center;
41 ObPlaceMonitor config_place_monitor;
42
43 guint config_primary_monitor_index;
44 ObPlaceMonitor config_primary_monitor;
45
46 StrutPartial config_margins;
47
48 gchar *config_theme;
49 gboolean config_theme_keepborder;
50 guint config_theme_window_list_icon_size;
51
52 gchar *config_title_layout;
53
54 gboolean config_animate_iconify;
55
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;
62
63 guint config_desktops_num;
64 GSList *config_desktops_names;
65 guint config_screen_firstdesk;
66 guint config_desktop_popup_time;
67
68 gboolean config_resize_redraw;
69 gint config_resize_popup_show;
70 ObResizePopupPos config_resize_popup_pos;
71 GravityPoint config_resize_popup_fixed;
72
73 ObStackingLayer config_dock_layer;
74 gboolean config_dock_floating;
75 gboolean config_dock_nostrut;
76 ObDirection config_dock_pos;
77 gint config_dock_x;
78 gint config_dock_y;
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;
85
86 guint config_keyboard_reset_keycode;
87 guint config_keyboard_reset_state;
88
89 gint config_mouse_threshold;
90 gint config_mouse_dclicktime;
91 gint config_mouse_screenedgetime;
92
93 guint config_menu_hide_delay;
94 gboolean config_menu_middle;
95 guint config_submenu_show_delay;
96 guint config_submenu_hide_delay;
97 gboolean config_menu_manage_desktops;
98 gboolean config_menu_show_icons;
99
100 GSList *config_menu_files;
101
102 gint config_resist_win;
103 gint config_resist_edge;
104
105 GSList *config_per_app_settings;
106
107 ObAppSettings* config_create_app_settings(void)
108 {
109 ObAppSettings *settings = g_slice_new0(ObAppSettings);
110 settings->type = -1;
111 settings->decor = -1;
112 settings->shade = -1;
113 settings->monitor = -1;
114 settings->focus = -1;
115 settings->desktop = 0;
116 settings->layer = -2;
117 settings->iconic = -1;
118 settings->skip_pager = -1;
119 settings->skip_taskbar = -1;
120 settings->fullscreen = -1;
121 settings->max_horz = -1;
122 settings->max_vert = -1;
123 return settings;
124 }
125
126 #define copy_if(setting, default) \
127 if (src->setting != default) dst->setting = src->setting
128 void config_app_settings_copy_non_defaults(const ObAppSettings *src,
129 ObAppSettings *dst)
130 {
131 g_assert(src != NULL);
132 g_assert(dst != NULL);
133
134 copy_if(type, (ObClientType)-1);
135 copy_if(decor, -1);
136 copy_if(shade, -1);
137 copy_if(monitor, -1);
138 copy_if(focus, -1);
139 copy_if(desktop, 0);
140 copy_if(layer, -2);
141 copy_if(iconic, -1);
142 copy_if(skip_pager, -1);
143 copy_if(skip_taskbar, -1);
144 copy_if(fullscreen, -1);
145 copy_if(max_horz, -1);
146 copy_if(max_vert, -1);
147
148 if (src->pos_given) {
149 dst->pos_given = TRUE;
150 dst->pos_force = src->pos_force;
151 dst->position = src->position;
152 /* monitor is copied above */
153 }
154 }
155
156 static void config_parse_gravity_coord(xmlNodePtr node, GravityCoord *c)
157 {
158 gchar *s = obt_xml_node_string(node);
159 if (!g_ascii_strcasecmp(s, "center"))
160 c->center = TRUE;
161 else {
162 if (s[0] == '-')
163 c->opposite = TRUE;
164 if (s[0] == '-' || s[0] == '+')
165 c->pos = atoi(s+1);
166 else
167 c->pos = atoi(s);
168 }
169 g_free(s);
170 }
171
172 /*
173 <applications>
174 <application name="aterm">
175 <decor>false</decor>
176 </application>
177 <application name="Rhythmbox">
178 <layer>above</layer>
179 <position>
180 <x>700</x>
181 <y>0</y>
182 <monitor>1</monitor>
183 </position>
184 .. there is a lot more settings available
185 </application>
186 </applications>
187 */
188
189 /* Manages settings for individual applications.
190 Some notes: monitor is the screen number in a multi monitor
191 (Xinerama) setup (starting from 0) or mouse, meaning the
192 monitor the pointer is on. Default: mouse.
193 Layer can be three values, above (Always on top), below
194 (Always on bottom) and everything else (normal behaviour).
195 Positions can be an integer value or center, which will
196 center the window in the specified axis. Position is within
197 the monitor, so <position><x>center</x></position><monitor>2</monitor>
198 will center the window on the second monitor.
199 */
200 static void parse_per_app_settings(xmlNodePtr node, gpointer d)
201 {
202 xmlNodePtr app = obt_xml_find_node(node->children, "application");
203 gchar *name = NULL, *class = NULL, *role = NULL, *title = NULL,
204 *type_str = NULL;
205 gboolean name_set, class_set, type_set, role_set, title_set;
206 ObClientType type;
207 gboolean x_pos_given;
208
209 while (app) {
210 x_pos_given = FALSE;
211
212 class_set = obt_xml_attr_string(app, "class", &class);
213 name_set = obt_xml_attr_string(app, "name", &name);
214 type_set = obt_xml_attr_string(app, "type", &type_str);
215 role_set = obt_xml_attr_string(app, "role", &role);
216 title_set = obt_xml_attr_string(app, "title", &title);
217
218 /* validate the type tho */
219 if (type_set) {
220 if (!g_ascii_strcasecmp(type_str, "normal"))
221 type = OB_CLIENT_TYPE_NORMAL;
222 else if (!g_ascii_strcasecmp(type_str, "dialog"))
223 type = OB_CLIENT_TYPE_DIALOG;
224 else if (!g_ascii_strcasecmp(type_str, "splash"))
225 type = OB_CLIENT_TYPE_SPLASH;
226 else if (!g_ascii_strcasecmp(type_str, "utility"))
227 type = OB_CLIENT_TYPE_UTILITY;
228 else if (!g_ascii_strcasecmp(type_str, "menu"))
229 type = OB_CLIENT_TYPE_MENU;
230 else if (!g_ascii_strcasecmp(type_str, "toolbar"))
231 type = OB_CLIENT_TYPE_TOOLBAR;
232 else if (!g_ascii_strcasecmp(type_str, "dock"))
233 type = OB_CLIENT_TYPE_DOCK;
234 else if (!g_ascii_strcasecmp(type_str, "desktop"))
235 type = OB_CLIENT_TYPE_DESKTOP;
236 else
237 type_set = FALSE; /* not valid! */
238 }
239
240 if (class_set || name_set || role_set || title_set || type_set) {
241 xmlNodePtr n, c;
242 ObAppSettings *settings = config_create_app_settings();
243
244 if (name_set)
245 settings->name = g_pattern_spec_new(name);
246
247 if (class_set)
248 settings->class = g_pattern_spec_new(class);
249
250 if (role_set)
251 settings->role = g_pattern_spec_new(role);
252
253 if (title_set)
254 settings->title = g_pattern_spec_new(title);
255
256 if (type_set)
257 settings->type = type;
258
259 if ((n = obt_xml_find_node(app->children, "decor")))
260 if (!obt_xml_node_contains(n, "default"))
261 settings->decor = obt_xml_node_bool(n);
262
263 if ((n = obt_xml_find_node(app->children, "shade")))
264 if (!obt_xml_node_contains(n, "default"))
265 settings->shade = obt_xml_node_bool(n);
266
267 if ((n = obt_xml_find_node(app->children, "position"))) {
268 if ((c = obt_xml_find_node(n->children, "x")))
269 if (!obt_xml_node_contains(c, "default")) {
270 config_parse_gravity_coord(c, &settings->position.x);
271 x_pos_given = TRUE;
272 }
273
274 if (x_pos_given && (c = obt_xml_find_node(n->children, "y")))
275 if (!obt_xml_node_contains(c, "default")) {
276 config_parse_gravity_coord(c, &settings->position.y);
277 settings->pos_given = TRUE;
278 }
279
280 if (settings->pos_given &&
281 (c = obt_xml_find_node(n->children, "monitor")))
282 if (!obt_xml_node_contains(c, "default")) {
283 gchar *s = obt_xml_node_string(c);
284 if (!g_ascii_strcasecmp(s, "mouse"))
285 settings->monitor = 0;
286 else
287 settings->monitor = obt_xml_node_int(c);
288 g_free(s);
289 }
290
291 obt_xml_attr_bool(n, "force", &settings->pos_force);
292 }
293
294 if ((n = obt_xml_find_node(app->children, "focus")))
295 if (!obt_xml_node_contains(n, "default"))
296 settings->focus = obt_xml_node_bool(n);
297
298 if ((n = obt_xml_find_node(app->children, "desktop"))) {
299 if (!obt_xml_node_contains(n, "default")) {
300 gchar *s = obt_xml_node_string(n);
301 if (!g_ascii_strcasecmp(s, "all"))
302 settings->desktop = DESKTOP_ALL;
303 else {
304 gint i = obt_xml_node_int(n);
305 if (i > 0)
306 settings->desktop = i;
307 }
308 g_free(s);
309 }
310 }
311
312 if ((n = obt_xml_find_node(app->children, "layer")))
313 if (!obt_xml_node_contains(n, "default")) {
314 gchar *s = obt_xml_node_string(n);
315 if (!g_ascii_strcasecmp(s, "above"))
316 settings->layer = 1;
317 else if (!g_ascii_strcasecmp(s, "below"))
318 settings->layer = -1;
319 else
320 settings->layer = 0;
321 g_free(s);
322 }
323
324 if ((n = obt_xml_find_node(app->children, "iconic")))
325 if (!obt_xml_node_contains(n, "default"))
326 settings->iconic = obt_xml_node_bool(n);
327
328 if ((n = obt_xml_find_node(app->children, "skip_pager")))
329 if (!obt_xml_node_contains(n, "default"))
330 settings->skip_pager = obt_xml_node_bool(n);
331
332 if ((n = obt_xml_find_node(app->children, "skip_taskbar")))
333 if (!obt_xml_node_contains(n, "default"))
334 settings->skip_taskbar = obt_xml_node_bool(n);
335
336 if ((n = obt_xml_find_node(app->children, "fullscreen")))
337 if (!obt_xml_node_contains(n, "default"))
338 settings->fullscreen = obt_xml_node_bool(n);
339
340 if ((n = obt_xml_find_node(app->children, "maximized")))
341 if (!obt_xml_node_contains(n, "default")) {
342 gchar *s = obt_xml_node_string(n);
343 if (!g_ascii_strcasecmp(s, "horizontal")) {
344 settings->max_horz = TRUE;
345 settings->max_vert = FALSE;
346 } else if (!g_ascii_strcasecmp(s, "vertical")) {
347 settings->max_horz = FALSE;
348 settings->max_vert = TRUE;
349 } else
350 settings->max_horz = settings->max_vert =
351 obt_xml_node_bool(n);
352 g_free(s);
353 }
354
355 config_per_app_settings = g_slist_append(config_per_app_settings,
356 (gpointer) settings);
357 g_free(name);
358 g_free(class);
359 g_free(role);
360 g_free(title);
361 name = class = role = title = NULL;
362 }
363
364 app = obt_xml_find_node(app->next, "application");
365 }
366 }
367
368 /*
369
370 <keybind key="C-x">
371 <action name="ChangeDesktop">
372 <desktop>3</desktop>
373 </action>
374 </keybind>
375
376 */
377
378 static void parse_key(xmlNodePtr node, GList *keylist)
379 {
380 gchar *key;
381 xmlNodePtr n;
382 gboolean is_chroot = FALSE;
383
384 if (!obt_xml_attr_string(node, "key", &key))
385 return;
386
387 obt_xml_attr_bool(node, "chroot", &is_chroot);
388
389 keylist = g_list_append(keylist, key);
390
391 if ((n = obt_xml_find_node(node->children, "keybind"))) {
392 while (n) {
393 parse_key(n, keylist);
394 n = obt_xml_find_node(n->next, "keybind");
395 }
396 }
397 else if ((n = obt_xml_find_node(node->children, "action"))) {
398 while (n) {
399 ObActionsAct *action;
400
401 action = actions_parse(n);
402 if (action)
403 keyboard_bind(keylist, action);
404 n = obt_xml_find_node(n->next, "action");
405 }
406 }
407
408 if (is_chroot)
409 keyboard_chroot(keylist);
410
411 g_free(key);
412 keylist = g_list_delete_link(keylist, g_list_last(keylist));
413 }
414
415 static void parse_keyboard(xmlNodePtr node, gpointer d)
416 {
417 xmlNodePtr n;
418 gchar *key;
419
420 keyboard_unbind_all();
421
422 if ((n = obt_xml_find_node(node->children, "chainQuitKey"))) {
423 key = obt_xml_node_string(n);
424 translate_key(key, &config_keyboard_reset_state,
425 &config_keyboard_reset_keycode);
426 g_free(key);
427 }
428
429 if ((n = obt_xml_find_node(node->children, "keybind")))
430 while (n) {
431 parse_key(n, NULL);
432 n = obt_xml_find_node(n->next, "keybind");
433 }
434 }
435
436 /*
437
438 <context name="Titlebar">
439 <mousebind button="Left" action="Press">
440 <action name="Raise"></action>
441 </mousebind>
442 </context>
443
444 */
445
446 static void parse_mouse(xmlNodePtr node, gpointer d)
447 {
448 xmlNodePtr n, nbut, nact;
449 gchar *buttonstr;
450 gchar *contextstr;
451 ObMouseAction mact;
452
453 mouse_unbind_all();
454
455 node = node->children;
456
457 if ((n = obt_xml_find_node(node, "dragThreshold")))
458 config_mouse_threshold = obt_xml_node_int(n);
459 if ((n = obt_xml_find_node(node, "doubleClickTime")))
460 config_mouse_dclicktime = obt_xml_node_int(n);
461 if ((n = obt_xml_find_node(node, "screenEdgeWarpTime"))) {
462 config_mouse_screenedgetime = obt_xml_node_int(n);
463 /* minimum value of 25 for this property, when it is 1 and you hit the
464 edge it basically never stops */
465 if (config_mouse_screenedgetime && config_mouse_screenedgetime < 25)
466 config_mouse_screenedgetime = 25;
467 }
468
469 n = obt_xml_find_node(node, "context");
470 while (n) {
471 if (!obt_xml_attr_string(n, "name", &contextstr))
472 goto next_n;
473 nbut = obt_xml_find_node(n->children, "mousebind");
474 while (nbut) {
475 if (!obt_xml_attr_string(nbut, "button", &buttonstr))
476 goto next_nbut;
477 if (obt_xml_attr_contains(nbut, "action", "press")) {
478 mact = OB_MOUSE_ACTION_PRESS;
479 } else if (obt_xml_attr_contains(nbut, "action", "release")) {
480 mact = OB_MOUSE_ACTION_RELEASE;
481 } else if (obt_xml_attr_contains(nbut, "action", "click")) {
482 mact = OB_MOUSE_ACTION_CLICK;
483 } else if (obt_xml_attr_contains(nbut, "action","doubleclick")) {
484 mact = OB_MOUSE_ACTION_DOUBLE_CLICK;
485 } else if (obt_xml_attr_contains(nbut, "action", "drag")) {
486 mact = OB_MOUSE_ACTION_MOTION;
487 } else
488 goto next_nbut;
489 nact = obt_xml_find_node(nbut->children, "action");
490 while (nact) {
491 ObActionsAct *action;
492
493 if ((action = actions_parse(nact)))
494 mouse_bind(buttonstr, contextstr, mact, action);
495 nact = obt_xml_find_node(nact->next, "action");
496 }
497 g_free(buttonstr);
498 next_nbut:
499 nbut = obt_xml_find_node(nbut->next, "mousebind");
500 }
501 g_free(contextstr);
502 next_n:
503 n = obt_xml_find_node(n->next, "context");
504 }
505 }
506
507 static void parse_focus(xmlNodePtr node, gpointer d)
508 {
509 xmlNodePtr n;
510
511 node = node->children;
512
513 if ((n = obt_xml_find_node(node, "focusNew")))
514 config_focus_new = obt_xml_node_bool(n);
515 if ((n = obt_xml_find_node(node, "followMouse")))
516 config_focus_follow = obt_xml_node_bool(n);
517 if ((n = obt_xml_find_node(node, "focusDelay")))
518 config_focus_delay = obt_xml_node_int(n);
519 if ((n = obt_xml_find_node(node, "raiseOnFocus")))
520 config_focus_raise = obt_xml_node_bool(n);
521 if ((n = obt_xml_find_node(node, "focusLast")))
522 config_focus_last = obt_xml_node_bool(n);
523 if ((n = obt_xml_find_node(node, "underMouse")))
524 config_focus_under_mouse = obt_xml_node_bool(n);
525 if ((n = obt_xml_find_node(node, "unfocusOnLeave")))
526 config_unfocus_leave = obt_xml_node_bool(n);
527 }
528
529 static void parse_placement(xmlNodePtr node, gpointer d)
530 {
531 xmlNodePtr n;
532
533 node = node->children;
534
535 if ((n = obt_xml_find_node(node, "policy")))
536 if (obt_xml_node_contains(n, "UnderMouse"))
537 config_place_policy = OB_PLACE_POLICY_MOUSE;
538 if ((n = obt_xml_find_node(node, "center")))
539 config_place_center = obt_xml_node_bool(n);
540 if ((n = obt_xml_find_node(node, "monitor"))) {
541 if (obt_xml_node_contains(n, "active"))
542 config_place_monitor = OB_PLACE_MONITOR_ACTIVE;
543 else if (obt_xml_node_contains(n, "mouse"))
544 config_place_monitor = OB_PLACE_MONITOR_MOUSE;
545 }
546 if ((n = obt_xml_find_node(node, "primaryMonitor"))) {
547 config_primary_monitor_index = obt_xml_node_int(n);
548 if (!config_primary_monitor_index) {
549 if (obt_xml_node_contains(n, "mouse"))
550 config_primary_monitor = OB_PLACE_MONITOR_MOUSE;
551 }
552 }
553 }
554
555 static void parse_margins(xmlNodePtr node, gpointer d)
556 {
557 xmlNodePtr n;
558
559 node = node->children;
560
561 if ((n = obt_xml_find_node(node, "top")))
562 config_margins.top = MAX(0, obt_xml_node_int(n));
563 if ((n = obt_xml_find_node(node, "left")))
564 config_margins.left = MAX(0, obt_xml_node_int(n));
565 if ((n = obt_xml_find_node(node, "right")))
566 config_margins.right = MAX(0, obt_xml_node_int(n));
567 if ((n = obt_xml_find_node(node, "bottom")))
568 config_margins.bottom = MAX(0, obt_xml_node_int(n));
569 }
570
571 static void parse_theme(xmlNodePtr node, gpointer d)
572 {
573 xmlNodePtr n;
574
575 node = node->children;
576
577 if ((n = obt_xml_find_node(node, "name"))) {
578 gchar *c;
579
580 g_free(config_theme);
581 c = obt_xml_node_string(n);
582 config_theme = obt_paths_expand_tilde(c);
583 g_free(c);
584 }
585 if ((n = obt_xml_find_node(node, "titleLayout"))) {
586 gchar *c, *d;
587
588 g_free(config_title_layout);
589 config_title_layout = obt_xml_node_string(n);
590
591 /* replace duplicates with spaces */
592 for (c = config_title_layout; *c != '\0'; ++c)
593 for (d = c+1; *d != '\0'; ++d)
594 if (*c == *d) *d = ' ';
595 }
596 if ((n = obt_xml_find_node(node, "keepBorder")))
597 config_theme_keepborder = obt_xml_node_bool(n);
598 if ((n = obt_xml_find_node(node, "animateIconify")))
599 config_animate_iconify = obt_xml_node_bool(n);
600 if ((n = obt_xml_find_node(node, "windowListIconSize"))) {
601 config_theme_window_list_icon_size = obt_xml_node_int(n);
602 if (config_theme_window_list_icon_size < 16)
603 config_theme_window_list_icon_size = 16;
604 else if (config_theme_window_list_icon_size > 96)
605 config_theme_window_list_icon_size = 96;
606 }
607
608 n = obt_xml_find_node(node, "font");
609 while (n) {
610 xmlNodePtr fnode;
611 RrFont **font;
612 gchar *name = g_strdup(RrDefaultFontFamily);
613 gint size = RrDefaultFontSize;
614 RrFontWeight weight = RrDefaultFontWeight;
615 RrFontSlant slant = RrDefaultFontSlant;
616
617 if (obt_xml_attr_contains(n, "place", "ActiveWindow"))
618 font = &config_font_activewindow;
619 else if (obt_xml_attr_contains(n, "place", "InactiveWindow"))
620 font = &config_font_inactivewindow;
621 else if (obt_xml_attr_contains(n, "place", "MenuHeader"))
622 font = &config_font_menutitle;
623 else if (obt_xml_attr_contains(n, "place", "MenuItem"))
624 font = &config_font_menuitem;
625 else if (obt_xml_attr_contains(n, "place", "ActiveOnScreenDisplay"))
626 font = &config_font_activeosd;
627 else if (obt_xml_attr_contains(n, "place", "OnScreenDisplay"))
628 font = &config_font_activeosd;
629 else if (obt_xml_attr_contains(n, "place","InactiveOnScreenDisplay"))
630 font = &config_font_inactiveosd;
631 else
632 goto next_font;
633
634 if ((fnode = obt_xml_find_node(n->children, "name"))) {
635 g_free(name);
636 name = obt_xml_node_string(fnode);
637 }
638 if ((fnode = obt_xml_find_node(n->children, "size"))) {
639 int s = obt_xml_node_int(fnode);
640 if (s > 0) size = s;
641 }
642 if ((fnode = obt_xml_find_node(n->children, "weight"))) {
643 gchar *w = obt_xml_node_string(fnode);
644 if (!g_ascii_strcasecmp(w, "Bold"))
645 weight = RR_FONTWEIGHT_BOLD;
646 g_free(w);
647 }
648 if ((fnode = obt_xml_find_node(n->children, "slant"))) {
649 gchar *s = obt_xml_node_string(fnode);
650 if (!g_ascii_strcasecmp(s, "Italic"))
651 slant = RR_FONTSLANT_ITALIC;
652 if (!g_ascii_strcasecmp(s, "Oblique"))
653 slant = RR_FONTSLANT_OBLIQUE;
654 g_free(s);
655 }
656
657 *font = RrFontOpen(ob_rr_inst, name, size, weight, slant);
658 g_free(name);
659 next_font:
660 n = obt_xml_find_node(n->next, "font");
661 }
662 }
663
664 static void parse_desktops(xmlNodePtr node, gpointer d)
665 {
666 xmlNodePtr n;
667
668 node = node->children;
669
670 if ((n = obt_xml_find_node(node, "number"))) {
671 gint d = obt_xml_node_int(n);
672 if (d > 0)
673 config_desktops_num = (unsigned) d;
674 }
675 if ((n = obt_xml_find_node(node, "firstdesk"))) {
676 gint d = obt_xml_node_int(n);
677 if (d > 0)
678 config_screen_firstdesk = (unsigned) d;
679 }
680 if ((n = obt_xml_find_node(node, "names"))) {
681 GSList *it;
682 xmlNodePtr nname;
683
684 for (it = config_desktops_names; it; it = it->next)
685 g_free(it->data);
686 g_slist_free(config_desktops_names);
687 config_desktops_names = NULL;
688
689 nname = obt_xml_find_node(n->children, "name");
690 while (nname) {
691 config_desktops_names =
692 g_slist_append(config_desktops_names,
693 obt_xml_node_string(nname));
694 nname = obt_xml_find_node(nname->next, "name");
695 }
696 }
697 if ((n = obt_xml_find_node(node, "popupTime")))
698 config_desktop_popup_time = obt_xml_node_int(n);
699 }
700
701 static void parse_resize(xmlNodePtr node, gpointer d)
702 {
703 xmlNodePtr n;
704
705 node = node->children;
706
707 if ((n = obt_xml_find_node(node, "drawContents")))
708 config_resize_redraw = obt_xml_node_bool(n);
709 if ((n = obt_xml_find_node(node, "popupShow"))) {
710 config_resize_popup_show = obt_xml_node_int(n);
711 if (obt_xml_node_contains(n, "Always"))
712 config_resize_popup_show = 2;
713 else if (obt_xml_node_contains(n, "Never"))
714 config_resize_popup_show = 0;
715 else if (obt_xml_node_contains(n, "Nonpixel"))
716 config_resize_popup_show = 1;
717 }
718 if ((n = obt_xml_find_node(node, "popupPosition"))) {
719 if (obt_xml_node_contains(n, "Top"))
720 config_resize_popup_pos = OB_RESIZE_POS_TOP;
721 else if (obt_xml_node_contains(n, "Center"))
722 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
723 else if (obt_xml_node_contains(n, "Fixed")) {
724 config_resize_popup_pos = OB_RESIZE_POS_FIXED;
725
726 if ((n = obt_xml_find_node(node, "popupFixedPosition"))) {
727 xmlNodePtr n2;
728
729 if ((n2 = obt_xml_find_node(n->children, "x")))
730 config_parse_gravity_coord(n2,
731 &config_resize_popup_fixed.x);
732 if ((n2 = obt_xml_find_node(n->children, "y")))
733 config_parse_gravity_coord(n2,
734 &config_resize_popup_fixed.y);
735
736 config_resize_popup_fixed.x.pos =
737 MAX(config_resize_popup_fixed.x.pos, 0);
738 config_resize_popup_fixed.y.pos =
739 MAX(config_resize_popup_fixed.y.pos, 0);
740 }
741 }
742 }
743 }
744
745 static void parse_dock(xmlNodePtr node, gpointer d)
746 {
747 xmlNodePtr n;
748
749 node = node->children;
750
751 if ((n = obt_xml_find_node(node, "position"))) {
752 if (obt_xml_node_contains(n, "TopLeft"))
753 config_dock_floating = FALSE,
754 config_dock_pos = OB_DIRECTION_NORTHWEST;
755 else if (obt_xml_node_contains(n, "Top"))
756 config_dock_floating = FALSE,
757 config_dock_pos = OB_DIRECTION_NORTH;
758 else if (obt_xml_node_contains(n, "TopRight"))
759 config_dock_floating = FALSE,
760 config_dock_pos = OB_DIRECTION_NORTHEAST;
761 else if (obt_xml_node_contains(n, "Right"))
762 config_dock_floating = FALSE,
763 config_dock_pos = OB_DIRECTION_EAST;
764 else if (obt_xml_node_contains(n, "BottomRight"))
765 config_dock_floating = FALSE,
766 config_dock_pos = OB_DIRECTION_SOUTHEAST;
767 else if (obt_xml_node_contains(n, "Bottom"))
768 config_dock_floating = FALSE,
769 config_dock_pos = OB_DIRECTION_SOUTH;
770 else if (obt_xml_node_contains(n, "BottomLeft"))
771 config_dock_floating = FALSE,
772 config_dock_pos = OB_DIRECTION_SOUTHWEST;
773 else if (obt_xml_node_contains(n, "Left"))
774 config_dock_floating = FALSE,
775 config_dock_pos = OB_DIRECTION_WEST;
776 else if (obt_xml_node_contains(n, "Floating"))
777 config_dock_floating = TRUE;
778 }
779 if (config_dock_floating) {
780 if ((n = obt_xml_find_node(node, "floatingX")))
781 config_dock_x = obt_xml_node_int(n);
782 if ((n = obt_xml_find_node(node, "floatingY")))
783 config_dock_y = obt_xml_node_int(n);
784 } else {
785 if ((n = obt_xml_find_node(node, "noStrut")))
786 config_dock_nostrut = obt_xml_node_bool(n);
787 }
788 if ((n = obt_xml_find_node(node, "stacking"))) {
789 if (obt_xml_node_contains(n, "normal"))
790 config_dock_layer = OB_STACKING_LAYER_NORMAL;
791 else if (obt_xml_node_contains(n, "below"))
792 config_dock_layer = OB_STACKING_LAYER_BELOW;
793 else if (obt_xml_node_contains(n, "above"))
794 config_dock_layer = OB_STACKING_LAYER_ABOVE;
795 }
796 if ((n = obt_xml_find_node(node, "direction"))) {
797 if (obt_xml_node_contains(n, "horizontal"))
798 config_dock_orient = OB_ORIENTATION_HORZ;
799 else if (obt_xml_node_contains(n, "vertical"))
800 config_dock_orient = OB_ORIENTATION_VERT;
801 }
802 if ((n = obt_xml_find_node(node, "autoHide")))
803 config_dock_hide = obt_xml_node_bool(n);
804 if ((n = obt_xml_find_node(node, "hideDelay")))
805 config_dock_hide_delay = obt_xml_node_int(n);
806 if ((n = obt_xml_find_node(node, "showDelay")))
807 config_dock_show_delay = obt_xml_node_int(n);
808 if ((n = obt_xml_find_node(node, "moveButton"))) {
809 gchar *str = obt_xml_node_string(n);
810 guint b, s;
811 if (translate_button(str, &s, &b)) {
812 config_dock_app_move_button = b;
813 config_dock_app_move_modifiers = s;
814 } else {
815 g_message(_("Invalid button \"%s\" specified in config file"), str);
816 }
817 g_free(str);
818 }
819 }
820
821 static void parse_menu(xmlNodePtr node, gpointer d)
822 {
823 xmlNodePtr n;
824 node = node->children;
825
826 if ((n = obt_xml_find_node(node, "hideDelay")))
827 config_menu_hide_delay = obt_xml_node_int(n);
828 if ((n = obt_xml_find_node(node, "middle")))
829 config_menu_middle = obt_xml_node_bool(n);
830 if ((n = obt_xml_find_node(node, "submenuShowDelay")))
831 config_submenu_show_delay = obt_xml_node_int(n);
832 if ((n = obt_xml_find_node(node, "submenuHideDelay")))
833 config_submenu_hide_delay = obt_xml_node_int(n);
834 if ((n = obt_xml_find_node(node, "manageDesktops")))
835 config_menu_manage_desktops = obt_xml_node_bool(n);
836 if ((n = obt_xml_find_node(node, "showIcons"))) {
837 config_menu_show_icons = obt_xml_node_bool(n);
838 #ifndef USE_IMLIB2
839 if (config_menu_show_icons)
840 g_message(_("Openbox was compiled without Imlib2 image loading support. Icons in menus will not be loaded."));
841 #endif
842 }
843
844 while ((node = obt_xml_find_node(node, "file"))) {
845 gchar *c = obt_xml_node_string(node);
846 config_menu_files = g_slist_append(config_menu_files,
847 obt_paths_expand_tilde(c));
848 g_free(c);
849 node = node->next;
850 }
851 }
852
853 static void parse_resistance(xmlNodePtr node, gpointer d)
854 {
855 xmlNodePtr n;
856
857 node = node->children;
858 if ((n = obt_xml_find_node(node, "strength")))
859 config_resist_win = obt_xml_node_int(n);
860 if ((n = obt_xml_find_node(node, "screen_edge_strength")))
861 config_resist_edge = obt_xml_node_int(n);
862 }
863
864 typedef struct
865 {
866 const gchar *key;
867 const gchar *actname;
868 } ObDefKeyBind;
869
870 static void bind_default_keyboard(void)
871 {
872 ObDefKeyBind *it;
873 ObDefKeyBind binds[] = {
874 { "A-Tab", "NextWindow" },
875 { "S-A-Tab", "PreviousWindow" },
876 { "A-F4", "Close" },
877 { NULL, NULL }
878 };
879 for (it = binds; it->key; ++it) {
880 GList *l = g_list_append(NULL, g_strdup(it->key));
881 keyboard_bind(l, actions_parse_string(it->actname));
882 }
883 }
884
885 typedef struct
886 {
887 const gchar *button;
888 const gchar *context;
889 const ObMouseAction mact;
890 const gchar *actname;
891 } ObDefMouseBind;
892
893 static void bind_default_mouse(void)
894 {
895 ObDefMouseBind *it;
896 ObDefMouseBind binds[] = {
897 { "Left", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
898 { "Middle", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
899 { "Right", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
900 { "Left", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
901 { "Middle", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
902 { "Right", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
903 { "Left", "Titlebar", OB_MOUSE_ACTION_PRESS, "Focus" },
904 { "Left", "Bottom", OB_MOUSE_ACTION_PRESS, "Focus" },
905 { "Left", "BLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
906 { "Left", "BRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
907 { "Left", "TLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
908 { "Left", "TRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
909 { "Left", "Close", OB_MOUSE_ACTION_PRESS, "Focus" },
910 { "Left", "Maximize", OB_MOUSE_ACTION_PRESS, "Focus" },
911 { "Left", "Iconify", OB_MOUSE_ACTION_PRESS, "Focus" },
912 { "Left", "Icon", OB_MOUSE_ACTION_PRESS, "Focus" },
913 { "Left", "AllDesktops", OB_MOUSE_ACTION_PRESS, "Focus" },
914 { "Left", "Shade", OB_MOUSE_ACTION_PRESS, "Focus" },
915 { "Left", "Client", OB_MOUSE_ACTION_CLICK, "Raise" },
916 { "Left", "Titlebar", OB_MOUSE_ACTION_CLICK, "Raise" },
917 { "Middle", "Titlebar", OB_MOUSE_ACTION_CLICK, "Lower" },
918 { "Left", "BLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
919 { "Left", "BRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
920 { "Left", "TLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
921 { "Left", "TRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
922 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Raise" },
923 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "Raise" },
924 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Raise" },
925 { "Left", "Icon", OB_MOUSE_ACTION_CLICK, "Raise" },
926 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "Raise" },
927 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "Raise" },
928 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Close" },
929 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "ToggleMaximize" },
930 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Iconify" },
931 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "ToggleOmnipresent" },
932 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "ToggleShade" },
933 { "Left", "TLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
934 { "Left", "TRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
935 { "Left", "BLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
936 { "Left", "BRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
937 { "Left", "Top", OB_MOUSE_ACTION_MOTION, "Resize" },
938 { "Left", "Bottom", OB_MOUSE_ACTION_MOTION, "Resize" },
939 { "Left", "Left", OB_MOUSE_ACTION_MOTION, "Resize" },
940 { "Left", "Right", OB_MOUSE_ACTION_MOTION, "Resize" },
941 { "Left", "Titlebar", OB_MOUSE_ACTION_MOTION, "Move" },
942 { "A-Left", "Frame", OB_MOUSE_ACTION_MOTION, "Move" },
943 { "A-Middle", "Frame", OB_MOUSE_ACTION_MOTION, "Resize" },
944 { NULL, NULL, 0, NULL }
945 };
946
947 for (it = binds; it->button; ++it)
948 mouse_bind(it->button, it->context, it->mact,
949 actions_parse_string(it->actname));
950 }
951
952 void config_startup(ObtXmlInst *i)
953 {
954 config_focus_new = TRUE;
955 config_focus_follow = FALSE;
956 config_focus_delay = 0;
957 config_focus_raise = FALSE;
958 config_focus_last = TRUE;
959 config_focus_under_mouse = FALSE;
960 config_unfocus_leave = FALSE;
961
962 obt_xml_register(i, "focus", parse_focus, NULL);
963
964 config_place_policy = OB_PLACE_POLICY_SMART;
965 config_place_center = TRUE;
966 config_place_monitor = OB_PLACE_MONITOR_ANY;
967
968 config_primary_monitor_index = 1;
969 config_primary_monitor = OB_PLACE_MONITOR_ACTIVE;
970
971 obt_xml_register(i, "placement", parse_placement, NULL);
972
973 STRUT_PARTIAL_SET(config_margins, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
974
975 obt_xml_register(i, "margins", parse_margins, NULL);
976
977 config_theme = NULL;
978
979 config_animate_iconify = TRUE;
980 config_title_layout = g_strdup("NLIMC");
981 config_theme_keepborder = TRUE;
982 config_theme_window_list_icon_size = 36;
983
984 config_font_activewindow = NULL;
985 config_font_inactivewindow = NULL;
986 config_font_menuitem = NULL;
987 config_font_menutitle = NULL;
988 config_font_activeosd = NULL;
989 config_font_inactiveosd = NULL;
990
991 obt_xml_register(i, "theme", parse_theme, NULL);
992
993 config_desktops_num = 4;
994 config_screen_firstdesk = 1;
995 config_desktops_names = NULL;
996 config_desktop_popup_time = 875;
997
998 obt_xml_register(i, "desktops", parse_desktops, NULL);
999
1000 config_resize_redraw = TRUE;
1001 config_resize_popup_show = 1; /* nonpixel increments */
1002 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
1003 GRAVITY_COORD_SET(config_resize_popup_fixed.x, 0, FALSE, FALSE);
1004 GRAVITY_COORD_SET(config_resize_popup_fixed.y, 0, FALSE, FALSE);
1005
1006 obt_xml_register(i, "resize", parse_resize, NULL);
1007
1008 config_dock_layer = OB_STACKING_LAYER_ABOVE;
1009 config_dock_pos = OB_DIRECTION_NORTHEAST;
1010 config_dock_floating = FALSE;
1011 config_dock_nostrut = FALSE;
1012 config_dock_x = 0;
1013 config_dock_y = 0;
1014 config_dock_orient = OB_ORIENTATION_VERT;
1015 config_dock_hide = FALSE;
1016 config_dock_hide_delay = 300;
1017 config_dock_show_delay = 300;
1018 config_dock_app_move_button = 2; /* middle */
1019 config_dock_app_move_modifiers = 0;
1020
1021 obt_xml_register(i, "dock", parse_dock, NULL);
1022
1023 translate_key("C-g", &config_keyboard_reset_state,
1024 &config_keyboard_reset_keycode);
1025
1026 bind_default_keyboard();
1027
1028 obt_xml_register(i, "keyboard", parse_keyboard, NULL);
1029
1030 config_mouse_threshold = 8;
1031 config_mouse_dclicktime = 200;
1032 config_mouse_screenedgetime = 400;
1033
1034 bind_default_mouse();
1035
1036 obt_xml_register(i, "mouse", parse_mouse, NULL);
1037
1038 config_resist_win = 10;
1039 config_resist_edge = 20;
1040
1041 obt_xml_register(i, "resistance", parse_resistance, NULL);
1042
1043 config_menu_hide_delay = 250;
1044 config_menu_middle = FALSE;
1045 config_submenu_show_delay = 100;
1046 config_submenu_hide_delay = 400;
1047 config_menu_manage_desktops = TRUE;
1048 config_menu_files = NULL;
1049 config_menu_show_icons = TRUE;
1050
1051 obt_xml_register(i, "menu", parse_menu, NULL);
1052
1053 config_per_app_settings = NULL;
1054
1055 obt_xml_register(i, "applications", parse_per_app_settings, NULL);
1056 }
1057
1058 void config_shutdown(void)
1059 {
1060 GSList *it;
1061
1062 g_free(config_theme);
1063
1064 g_free(config_title_layout);
1065
1066 RrFontClose(config_font_activewindow);
1067 RrFontClose(config_font_inactivewindow);
1068 RrFontClose(config_font_menuitem);
1069 RrFontClose(config_font_menutitle);
1070 RrFontClose(config_font_activeosd);
1071 RrFontClose(config_font_inactiveosd);
1072
1073 for (it = config_desktops_names; it; it = g_slist_next(it))
1074 g_free(it->data);
1075 g_slist_free(config_desktops_names);
1076
1077 for (it = config_menu_files; it; it = g_slist_next(it))
1078 g_free(it->data);
1079 g_slist_free(config_menu_files);
1080
1081 for (it = config_per_app_settings; it; it = g_slist_next(it)) {
1082 ObAppSettings *itd = (ObAppSettings *)it->data;
1083 if (itd->name) g_pattern_spec_free(itd->name);
1084 if (itd->role) g_pattern_spec_free(itd->role);
1085 if (itd->title) g_pattern_spec_free(itd->title);
1086 if (itd->class) g_pattern_spec_free(itd->class);
1087 g_slice_free(ObAppSettings, it->data);
1088 }
1089 g_slist_free(config_per_app_settings);
1090 }
This page took 0.0876479999999999 seconds and 5 git commands to generate.