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