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