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