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