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