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