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