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