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