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