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