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