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