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