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