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