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