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