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