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