]> Dogcows Code - chaz/openbox/blob - openbox/config.c
Change default doubleclick timeout to 500ms and keep track of where last click was
[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 g_free(type_str);
374 name = class = role = title = type_str = NULL;
375 }
376
377 app = obt_xml_find_node(app->next, "application");
378 }
379 }
380
381 /*
382
383 <keybind key="C-x">
384 <action name="ChangeDesktop">
385 <desktop>3</desktop>
386 </action>
387 </keybind>
388
389 */
390
391 static void parse_key(xmlNodePtr node, GList *keylist)
392 {
393 gchar *keystring, **keys, **key;
394 xmlNodePtr n;
395 gboolean is_chroot = FALSE;
396
397 if (!obt_xml_attr_string(node, "key", &keystring))
398 return;
399
400 obt_xml_attr_bool(node, "chroot", &is_chroot);
401
402 keys = g_strsplit(keystring, " ", 0);
403 for (key = keys; *key; ++key) {
404 keylist = g_list_append(keylist, *key);
405
406 if ((n = obt_xml_find_node(node->children, "keybind"))) {
407 while (n) {
408 parse_key(n, keylist);
409 n = obt_xml_find_node(n->next, "keybind");
410 }
411 }
412 else if ((n = obt_xml_find_node(node->children, "action"))) {
413 while (n) {
414 ObActionsAct *action;
415
416 action = actions_parse(n);
417 if (action)
418 keyboard_bind(keylist, action);
419 n = obt_xml_find_node(n->next, "action");
420 }
421 }
422
423
424 if (is_chroot)
425 keyboard_chroot(keylist);
426 keylist = g_list_delete_link(keylist, g_list_last(keylist));
427 }
428
429 g_strfreev(keys);
430 g_free(keystring);
431 }
432
433 static void parse_keyboard(xmlNodePtr node, gpointer d)
434 {
435 xmlNodePtr n;
436 gchar *key;
437
438 keyboard_unbind_all();
439
440 if ((n = obt_xml_find_node(node->children, "chainQuitKey"))) {
441 key = obt_xml_node_string(n);
442 translate_key(key, &config_keyboard_reset_state,
443 &config_keyboard_reset_keycode);
444 g_free(key);
445 }
446
447 if ((n = obt_xml_find_node(node->children, "keybind")))
448 while (n) {
449 parse_key(n, NULL);
450 n = obt_xml_find_node(n->next, "keybind");
451 }
452 }
453
454 /*
455
456 <context name="Titlebar">
457 <mousebind button="Left" action="Press">
458 <action name="Raise"></action>
459 </mousebind>
460 </context>
461
462 */
463
464 static void parse_mouse(xmlNodePtr node, gpointer d)
465 {
466 xmlNodePtr n, nbut, nact;
467 gchar *buttonstr;
468 gchar *cxstr;
469 ObMouseAction mact;
470
471 mouse_unbind_all();
472
473 node = node->children;
474
475 if ((n = obt_xml_find_node(node, "dragThreshold")))
476 config_mouse_threshold = obt_xml_node_int(n);
477 if ((n = obt_xml_find_node(node, "doubleClickTime")))
478 config_mouse_dclicktime = obt_xml_node_int(n);
479 if ((n = obt_xml_find_node(node, "screenEdgeWarpTime"))) {
480 config_mouse_screenedgetime = obt_xml_node_int(n);
481 /* minimum value of 25 for this property, when it is 1 and you hit the
482 edge it basically never stops */
483 if (config_mouse_screenedgetime && config_mouse_screenedgetime < 25)
484 config_mouse_screenedgetime = 25;
485 }
486 if ((n = obt_xml_find_node(node, "screenEdgeWarpMouse")))
487 config_mouse_screenedgewarp = obt_xml_node_bool(n);
488
489 n = obt_xml_find_node(node, "context");
490 while (n) {
491 gchar *modcxstr;
492 ObFrameContext cx;
493
494 if (!obt_xml_attr_string(n, "name", &cxstr))
495 goto next_n;
496
497 modcxstr = g_strdup(cxstr); /* make a copy to mutilate */
498 while (frame_next_context_from_string(modcxstr, &cx)) {
499 if (!cx) {
500 gchar *s = strchr(modcxstr, ' ');
501 if (s) {
502 *s = '\0';
503 g_message(_("Invalid context \"%s\" in mouse binding"),
504 modcxstr);
505 *s = ' ';
506 }
507 continue;
508 }
509
510 nbut = obt_xml_find_node(n->children, "mousebind");
511 while (nbut) {
512 if (!obt_xml_attr_string(nbut, "button", &buttonstr))
513 goto next_nbut;
514 if (obt_xml_attr_contains(nbut, "action", "press"))
515 mact = OB_MOUSE_ACTION_PRESS;
516 else if (obt_xml_attr_contains(nbut, "action", "release"))
517 mact = OB_MOUSE_ACTION_RELEASE;
518 else if (obt_xml_attr_contains(nbut, "action", "click"))
519 mact = OB_MOUSE_ACTION_CLICK;
520 else if (obt_xml_attr_contains(nbut, "action","doubleclick"))
521 mact = OB_MOUSE_ACTION_DOUBLE_CLICK;
522 else if (obt_xml_attr_contains(nbut, "action", "drag"))
523 mact = OB_MOUSE_ACTION_MOTION;
524 else
525 goto next_nbut;
526
527 nact = obt_xml_find_node(nbut->children, "action");
528 while (nact) {
529 ObActionsAct *action;
530
531 if ((action = actions_parse(nact)))
532 mouse_bind(buttonstr, cx, mact, action);
533 nact = obt_xml_find_node(nact->next, "action");
534 }
535 g_free(buttonstr);
536 next_nbut:
537 nbut = obt_xml_find_node(nbut->next, "mousebind");
538 }
539 }
540 g_free(modcxstr);
541 g_free(cxstr);
542 next_n:
543 n = obt_xml_find_node(n->next, "context");
544 }
545 }
546
547 static void parse_focus(xmlNodePtr node, gpointer d)
548 {
549 xmlNodePtr n;
550
551 node = node->children;
552
553 if ((n = obt_xml_find_node(node, "focusNew")))
554 config_focus_new = obt_xml_node_bool(n);
555 if ((n = obt_xml_find_node(node, "followMouse")))
556 config_focus_follow = obt_xml_node_bool(n);
557 if ((n = obt_xml_find_node(node, "focusDelay")))
558 config_focus_delay = obt_xml_node_int(n);
559 if ((n = obt_xml_find_node(node, "raiseOnFocus")))
560 config_focus_raise = obt_xml_node_bool(n);
561 if ((n = obt_xml_find_node(node, "focusLast")))
562 config_focus_last = obt_xml_node_bool(n);
563 if ((n = obt_xml_find_node(node, "underMouse")))
564 config_focus_under_mouse = obt_xml_node_bool(n);
565 if ((n = obt_xml_find_node(node, "unfocusOnLeave")))
566 config_unfocus_leave = obt_xml_node_bool(n);
567 }
568
569 static void parse_placement(xmlNodePtr node, gpointer d)
570 {
571 xmlNodePtr n;
572
573 node = node->children;
574
575 if ((n = obt_xml_find_node(node, "policy")))
576 if (obt_xml_node_contains(n, "UnderMouse"))
577 config_place_policy = OB_PLACE_POLICY_MOUSE;
578 if ((n = obt_xml_find_node(node, "center")))
579 config_place_center = obt_xml_node_bool(n);
580 if ((n = obt_xml_find_node(node, "monitor"))) {
581 if (obt_xml_node_contains(n, "active"))
582 config_place_monitor = OB_PLACE_MONITOR_ACTIVE;
583 else if (obt_xml_node_contains(n, "mouse"))
584 config_place_monitor = OB_PLACE_MONITOR_MOUSE;
585 else if (obt_xml_node_contains(n, "any"))
586 config_place_monitor = OB_PLACE_MONITOR_ANY;
587 }
588 if ((n = obt_xml_find_node(node, "primaryMonitor"))) {
589 config_primary_monitor_index = obt_xml_node_int(n);
590 if (!config_primary_monitor_index) {
591 if (obt_xml_node_contains(n, "mouse"))
592 config_primary_monitor = OB_PLACE_MONITOR_MOUSE;
593 }
594 }
595 }
596
597 static void parse_margins(xmlNodePtr node, gpointer d)
598 {
599 xmlNodePtr n;
600
601 node = node->children;
602
603 if ((n = obt_xml_find_node(node, "top")))
604 config_margins.top = MAX(0, obt_xml_node_int(n));
605 if ((n = obt_xml_find_node(node, "left")))
606 config_margins.left = MAX(0, obt_xml_node_int(n));
607 if ((n = obt_xml_find_node(node, "right")))
608 config_margins.right = MAX(0, obt_xml_node_int(n));
609 if ((n = obt_xml_find_node(node, "bottom")))
610 config_margins.bottom = MAX(0, obt_xml_node_int(n));
611 }
612
613 static void parse_theme(xmlNodePtr node, gpointer d)
614 {
615 xmlNodePtr n;
616
617 node = node->children;
618
619 if ((n = obt_xml_find_node(node, "name"))) {
620 gchar *c;
621
622 g_free(config_theme);
623 c = obt_xml_node_string(n);
624 config_theme = obt_paths_expand_tilde(c);
625 g_free(c);
626 }
627 if ((n = obt_xml_find_node(node, "titleLayout"))) {
628 gchar *c, *d;
629
630 g_free(config_title_layout);
631 config_title_layout = obt_xml_node_string(n);
632
633 /* replace duplicates with spaces */
634 for (c = config_title_layout; *c != '\0'; ++c)
635 for (d = c+1; *d != '\0'; ++d)
636 if (*c == *d) *d = ' ';
637 }
638 if ((n = obt_xml_find_node(node, "keepBorder")))
639 config_theme_keepborder = obt_xml_node_bool(n);
640 if ((n = obt_xml_find_node(node, "animateIconify")))
641 config_animate_iconify = obt_xml_node_bool(n);
642 if ((n = obt_xml_find_node(node, "windowListIconSize"))) {
643 config_theme_window_list_icon_size = obt_xml_node_int(n);
644 if (config_theme_window_list_icon_size < 16)
645 config_theme_window_list_icon_size = 16;
646 else if (config_theme_window_list_icon_size > 96)
647 config_theme_window_list_icon_size = 96;
648 }
649
650 n = obt_xml_find_node(node, "font");
651 while (n) {
652 xmlNodePtr fnode;
653 RrFont **font;
654 gchar *name = g_strdup(RrDefaultFontFamily);
655 gint size = RrDefaultFontSize;
656 RrFontWeight weight = RrDefaultFontWeight;
657 RrFontSlant slant = RrDefaultFontSlant;
658
659 if (obt_xml_attr_contains(n, "place", "ActiveWindow"))
660 font = &config_font_activewindow;
661 else if (obt_xml_attr_contains(n, "place", "InactiveWindow"))
662 font = &config_font_inactivewindow;
663 else if (obt_xml_attr_contains(n, "place", "MenuHeader"))
664 font = &config_font_menutitle;
665 else if (obt_xml_attr_contains(n, "place", "MenuItem"))
666 font = &config_font_menuitem;
667 else if (obt_xml_attr_contains(n, "place", "ActiveOnScreenDisplay"))
668 font = &config_font_activeosd;
669 else if (obt_xml_attr_contains(n, "place", "OnScreenDisplay"))
670 font = &config_font_activeosd;
671 else if (obt_xml_attr_contains(n, "place","InactiveOnScreenDisplay"))
672 font = &config_font_inactiveosd;
673 else
674 goto next_font;
675
676 if ((fnode = obt_xml_find_node(n->children, "name"))) {
677 g_free(name);
678 name = obt_xml_node_string(fnode);
679 }
680 if ((fnode = obt_xml_find_node(n->children, "size"))) {
681 int s = obt_xml_node_int(fnode);
682 if (s > 0) size = s;
683 }
684 if ((fnode = obt_xml_find_node(n->children, "weight"))) {
685 gchar *w = obt_xml_node_string(fnode);
686 if (!g_ascii_strcasecmp(w, "Bold"))
687 weight = RR_FONTWEIGHT_BOLD;
688 g_free(w);
689 }
690 if ((fnode = obt_xml_find_node(n->children, "slant"))) {
691 gchar *s = obt_xml_node_string(fnode);
692 if (!g_ascii_strcasecmp(s, "Italic"))
693 slant = RR_FONTSLANT_ITALIC;
694 if (!g_ascii_strcasecmp(s, "Oblique"))
695 slant = RR_FONTSLANT_OBLIQUE;
696 g_free(s);
697 }
698
699 *font = RrFontOpen(ob_rr_inst, name, size, weight, slant);
700 g_free(name);
701 next_font:
702 n = obt_xml_find_node(n->next, "font");
703 }
704 }
705
706 static void parse_desktops(xmlNodePtr node, gpointer d)
707 {
708 xmlNodePtr n;
709
710 node = node->children;
711
712 if ((n = obt_xml_find_node(node, "number"))) {
713 gint d = obt_xml_node_int(n);
714 if (d > 0)
715 config_desktops_num = (unsigned) d;
716 }
717 if ((n = obt_xml_find_node(node, "firstdesk"))) {
718 gint d = obt_xml_node_int(n);
719 if (d > 0)
720 config_screen_firstdesk = (unsigned) d;
721 }
722 if ((n = obt_xml_find_node(node, "names"))) {
723 GSList *it;
724 xmlNodePtr nname;
725
726 for (it = config_desktops_names; it; it = it->next)
727 g_free(it->data);
728 g_slist_free(config_desktops_names);
729 config_desktops_names = NULL;
730
731 nname = obt_xml_find_node(n->children, "name");
732 while (nname) {
733 config_desktops_names =
734 g_slist_append(config_desktops_names,
735 obt_xml_node_string(nname));
736 nname = obt_xml_find_node(nname->next, "name");
737 }
738 }
739 if ((n = obt_xml_find_node(node, "popupTime")))
740 config_desktop_popup_time = obt_xml_node_int(n);
741 }
742
743 static void parse_resize(xmlNodePtr node, gpointer d)
744 {
745 xmlNodePtr n;
746
747 node = node->children;
748
749 if ((n = obt_xml_find_node(node, "drawContents")))
750 config_resize_redraw = obt_xml_node_bool(n);
751 if ((n = obt_xml_find_node(node, "popupShow"))) {
752 config_resize_popup_show = obt_xml_node_int(n);
753 if (obt_xml_node_contains(n, "Always"))
754 config_resize_popup_show = 2;
755 else if (obt_xml_node_contains(n, "Never"))
756 config_resize_popup_show = 0;
757 else if (obt_xml_node_contains(n, "Nonpixel"))
758 config_resize_popup_show = 1;
759 }
760 if ((n = obt_xml_find_node(node, "popupPosition"))) {
761 if (obt_xml_node_contains(n, "Top"))
762 config_resize_popup_pos = OB_RESIZE_POS_TOP;
763 else if (obt_xml_node_contains(n, "Center"))
764 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
765 else if (obt_xml_node_contains(n, "Fixed")) {
766 config_resize_popup_pos = OB_RESIZE_POS_FIXED;
767
768 if ((n = obt_xml_find_node(node, "popupFixedPosition"))) {
769 xmlNodePtr n2;
770
771 if ((n2 = obt_xml_find_node(n->children, "x")))
772 config_parse_gravity_coord(n2,
773 &config_resize_popup_fixed.x);
774 if ((n2 = obt_xml_find_node(n->children, "y")))
775 config_parse_gravity_coord(n2,
776 &config_resize_popup_fixed.y);
777
778 config_resize_popup_fixed.x.pos =
779 MAX(config_resize_popup_fixed.x.pos, 0);
780 config_resize_popup_fixed.y.pos =
781 MAX(config_resize_popup_fixed.y.pos, 0);
782 }
783 }
784 }
785 }
786
787 static void parse_dock(xmlNodePtr node, gpointer d)
788 {
789 xmlNodePtr n;
790
791 node = node->children;
792
793 if ((n = obt_xml_find_node(node, "position"))) {
794 if (obt_xml_node_contains(n, "TopLeft"))
795 config_dock_floating = FALSE,
796 config_dock_pos = OB_DIRECTION_NORTHWEST;
797 else if (obt_xml_node_contains(n, "Top"))
798 config_dock_floating = FALSE,
799 config_dock_pos = OB_DIRECTION_NORTH;
800 else if (obt_xml_node_contains(n, "TopRight"))
801 config_dock_floating = FALSE,
802 config_dock_pos = OB_DIRECTION_NORTHEAST;
803 else if (obt_xml_node_contains(n, "Right"))
804 config_dock_floating = FALSE,
805 config_dock_pos = OB_DIRECTION_EAST;
806 else if (obt_xml_node_contains(n, "BottomRight"))
807 config_dock_floating = FALSE,
808 config_dock_pos = OB_DIRECTION_SOUTHEAST;
809 else if (obt_xml_node_contains(n, "Bottom"))
810 config_dock_floating = FALSE,
811 config_dock_pos = OB_DIRECTION_SOUTH;
812 else if (obt_xml_node_contains(n, "BottomLeft"))
813 config_dock_floating = FALSE,
814 config_dock_pos = OB_DIRECTION_SOUTHWEST;
815 else if (obt_xml_node_contains(n, "Left"))
816 config_dock_floating = FALSE,
817 config_dock_pos = OB_DIRECTION_WEST;
818 else if (obt_xml_node_contains(n, "Floating"))
819 config_dock_floating = TRUE;
820 }
821 if (config_dock_floating) {
822 if ((n = obt_xml_find_node(node, "floatingX")))
823 config_dock_x = obt_xml_node_int(n);
824 if ((n = obt_xml_find_node(node, "floatingY")))
825 config_dock_y = obt_xml_node_int(n);
826 } else {
827 if ((n = obt_xml_find_node(node, "noStrut")))
828 config_dock_nostrut = obt_xml_node_bool(n);
829 }
830 if ((n = obt_xml_find_node(node, "stacking"))) {
831 if (obt_xml_node_contains(n, "normal"))
832 config_dock_layer = OB_STACKING_LAYER_NORMAL;
833 else if (obt_xml_node_contains(n, "below"))
834 config_dock_layer = OB_STACKING_LAYER_BELOW;
835 else if (obt_xml_node_contains(n, "above"))
836 config_dock_layer = OB_STACKING_LAYER_ABOVE;
837 }
838 if ((n = obt_xml_find_node(node, "direction"))) {
839 if (obt_xml_node_contains(n, "horizontal"))
840 config_dock_orient = OB_ORIENTATION_HORZ;
841 else if (obt_xml_node_contains(n, "vertical"))
842 config_dock_orient = OB_ORIENTATION_VERT;
843 }
844 if ((n = obt_xml_find_node(node, "autoHide")))
845 config_dock_hide = obt_xml_node_bool(n);
846 if ((n = obt_xml_find_node(node, "hideDelay")))
847 config_dock_hide_delay = obt_xml_node_int(n);
848 if ((n = obt_xml_find_node(node, "showDelay")))
849 config_dock_show_delay = obt_xml_node_int(n);
850 if ((n = obt_xml_find_node(node, "moveButton"))) {
851 gchar *str = obt_xml_node_string(n);
852 guint b, s;
853 if (translate_button(str, &s, &b)) {
854 config_dock_app_move_button = b;
855 config_dock_app_move_modifiers = s;
856 } else {
857 g_message(_("Invalid button \"%s\" specified in config file"), str);
858 }
859 g_free(str);
860 }
861 }
862
863 static void parse_menu(xmlNodePtr node, gpointer d)
864 {
865 xmlNodePtr n;
866 node = node->children;
867
868 if ((n = obt_xml_find_node(node, "hideDelay")))
869 config_menu_hide_delay = obt_xml_node_int(n);
870 if ((n = obt_xml_find_node(node, "middle")))
871 config_menu_middle = obt_xml_node_bool(n);
872 if ((n = obt_xml_find_node(node, "submenuShowDelay")))
873 config_submenu_show_delay = obt_xml_node_int(n);
874 if ((n = obt_xml_find_node(node, "submenuHideDelay")))
875 config_submenu_hide_delay = obt_xml_node_int(n);
876 if ((n = obt_xml_find_node(node, "manageDesktops")))
877 config_menu_manage_desktops = obt_xml_node_bool(n);
878 if ((n = obt_xml_find_node(node, "showIcons"))) {
879 config_menu_show_icons = obt_xml_node_bool(n);
880 #ifndef USE_IMLIB2
881 if (config_menu_show_icons)
882 g_message(_("Openbox was compiled without Imlib2 image loading support. Icons in menus will not be loaded."));
883 #endif
884 }
885
886 while ((node = obt_xml_find_node(node, "file"))) {
887 gchar *c = obt_xml_node_string(node);
888 config_menu_files = g_slist_append(config_menu_files,
889 obt_paths_expand_tilde(c));
890 g_free(c);
891 node = node->next;
892 }
893 }
894
895 static void parse_resistance(xmlNodePtr node, gpointer d)
896 {
897 xmlNodePtr n;
898
899 node = node->children;
900 if ((n = obt_xml_find_node(node, "strength")))
901 config_resist_win = obt_xml_node_int(n);
902 if ((n = obt_xml_find_node(node, "screen_edge_strength")))
903 config_resist_edge = obt_xml_node_int(n);
904 }
905
906 typedef struct
907 {
908 const gchar *key;
909 const gchar *actname;
910 } ObDefKeyBind;
911
912 static void bind_default_keyboard(void)
913 {
914 ObDefKeyBind *it;
915 ObDefKeyBind binds[] = {
916 { "A-Tab", "NextWindow" },
917 { "S-A-Tab", "PreviousWindow" },
918 { "A-F4", "Close" },
919 { NULL, NULL }
920 };
921 for (it = binds; it->key; ++it) {
922 GList *l = g_list_append(NULL, g_strdup(it->key));
923 keyboard_bind(l, actions_parse_string(it->actname));
924 }
925 }
926
927 typedef struct
928 {
929 const gchar *button;
930 const gchar *context;
931 const ObMouseAction mact;
932 const gchar *actname;
933 } ObDefMouseBind;
934
935 static void bind_default_mouse(void)
936 {
937 ObDefMouseBind *it;
938 ObDefMouseBind binds[] = {
939 { "Left", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
940 { "Middle", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
941 { "Right", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
942 { "Left", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
943 { "Middle", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
944 { "Right", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
945 { "Left", "Titlebar", OB_MOUSE_ACTION_PRESS, "Focus" },
946 { "Left", "Bottom", OB_MOUSE_ACTION_PRESS, "Focus" },
947 { "Left", "BLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
948 { "Left", "BRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
949 { "Left", "TLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
950 { "Left", "TRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
951 { "Left", "Close", OB_MOUSE_ACTION_PRESS, "Focus" },
952 { "Left", "Maximize", OB_MOUSE_ACTION_PRESS, "Focus" },
953 { "Left", "Iconify", OB_MOUSE_ACTION_PRESS, "Focus" },
954 { "Left", "Icon", OB_MOUSE_ACTION_PRESS, "Focus" },
955 { "Left", "AllDesktops", OB_MOUSE_ACTION_PRESS, "Focus" },
956 { "Left", "Shade", OB_MOUSE_ACTION_PRESS, "Focus" },
957 { "Left", "Client", OB_MOUSE_ACTION_CLICK, "Raise" },
958 { "Left", "Titlebar", OB_MOUSE_ACTION_CLICK, "Raise" },
959 { "Middle", "Titlebar", OB_MOUSE_ACTION_CLICK, "Lower" },
960 { "Left", "BLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
961 { "Left", "BRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
962 { "Left", "TLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
963 { "Left", "TRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
964 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Raise" },
965 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "Raise" },
966 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Raise" },
967 { "Left", "Icon", OB_MOUSE_ACTION_CLICK, "Raise" },
968 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "Raise" },
969 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "Raise" },
970 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Close" },
971 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "ToggleMaximize" },
972 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Iconify" },
973 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "ToggleOmnipresent" },
974 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "ToggleShade" },
975 { "Left", "TLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
976 { "Left", "TRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
977 { "Left", "BLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
978 { "Left", "BRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
979 { "Left", "Top", OB_MOUSE_ACTION_MOTION, "Resize" },
980 { "Left", "Bottom", OB_MOUSE_ACTION_MOTION, "Resize" },
981 { "Left", "Left", OB_MOUSE_ACTION_MOTION, "Resize" },
982 { "Left", "Right", OB_MOUSE_ACTION_MOTION, "Resize" },
983 { "Left", "Titlebar", OB_MOUSE_ACTION_MOTION, "Move" },
984 { "A-Left", "Frame", OB_MOUSE_ACTION_MOTION, "Move" },
985 { "A-Middle", "Frame", OB_MOUSE_ACTION_MOTION, "Resize" },
986 { NULL, NULL, 0, NULL }
987 };
988
989 for (it = binds; it->button; ++it)
990 mouse_bind(it->button, frame_context_from_string(it->context),
991 it->mact, actions_parse_string(it->actname));
992 }
993
994 void config_startup(ObtXmlInst *i)
995 {
996 config_focus_new = TRUE;
997 config_focus_follow = FALSE;
998 config_focus_delay = 0;
999 config_focus_raise = FALSE;
1000 config_focus_last = TRUE;
1001 config_focus_under_mouse = FALSE;
1002 config_unfocus_leave = FALSE;
1003
1004 obt_xml_register(i, "focus", parse_focus, NULL);
1005
1006 config_place_policy = OB_PLACE_POLICY_SMART;
1007 config_place_center = TRUE;
1008 config_place_monitor = OB_PLACE_MONITOR_PRIMARY;
1009
1010 config_primary_monitor_index = 1;
1011 config_primary_monitor = OB_PLACE_MONITOR_ACTIVE;
1012
1013 obt_xml_register(i, "placement", parse_placement, NULL);
1014
1015 STRUT_PARTIAL_SET(config_margins, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1016
1017 obt_xml_register(i, "margins", parse_margins, NULL);
1018
1019 config_theme = NULL;
1020
1021 config_animate_iconify = TRUE;
1022 config_title_layout = g_strdup("NLIMC");
1023 config_theme_keepborder = TRUE;
1024 config_theme_window_list_icon_size = 36;
1025
1026 config_font_activewindow = NULL;
1027 config_font_inactivewindow = NULL;
1028 config_font_menuitem = NULL;
1029 config_font_menutitle = NULL;
1030 config_font_activeosd = NULL;
1031 config_font_inactiveosd = NULL;
1032
1033 obt_xml_register(i, "theme", parse_theme, NULL);
1034
1035 config_desktops_num = 4;
1036 config_screen_firstdesk = 1;
1037 config_desktops_names = NULL;
1038 config_desktop_popup_time = 875;
1039
1040 obt_xml_register(i, "desktops", parse_desktops, NULL);
1041
1042 config_resize_redraw = TRUE;
1043 config_resize_popup_show = 1; /* nonpixel increments */
1044 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
1045 GRAVITY_COORD_SET(config_resize_popup_fixed.x, 0, FALSE, FALSE);
1046 GRAVITY_COORD_SET(config_resize_popup_fixed.y, 0, FALSE, FALSE);
1047
1048 obt_xml_register(i, "resize", parse_resize, NULL);
1049
1050 config_dock_layer = OB_STACKING_LAYER_ABOVE;
1051 config_dock_pos = OB_DIRECTION_NORTHEAST;
1052 config_dock_floating = FALSE;
1053 config_dock_nostrut = FALSE;
1054 config_dock_x = 0;
1055 config_dock_y = 0;
1056 config_dock_orient = OB_ORIENTATION_VERT;
1057 config_dock_hide = FALSE;
1058 config_dock_hide_delay = 300;
1059 config_dock_show_delay = 300;
1060 config_dock_app_move_button = 2; /* middle */
1061 config_dock_app_move_modifiers = 0;
1062
1063 obt_xml_register(i, "dock", parse_dock, NULL);
1064
1065 translate_key("C-g", &config_keyboard_reset_state,
1066 &config_keyboard_reset_keycode);
1067
1068 bind_default_keyboard();
1069
1070 obt_xml_register(i, "keyboard", parse_keyboard, NULL);
1071
1072 config_mouse_threshold = 8;
1073 config_mouse_dclicktime = 500;
1074 config_mouse_screenedgetime = 400;
1075 config_mouse_screenedgewarp = FALSE;
1076
1077 bind_default_mouse();
1078
1079 obt_xml_register(i, "mouse", parse_mouse, NULL);
1080
1081 config_resist_win = 10;
1082 config_resist_edge = 20;
1083
1084 obt_xml_register(i, "resistance", parse_resistance, NULL);
1085
1086 config_menu_hide_delay = 250;
1087 config_menu_middle = FALSE;
1088 config_submenu_show_delay = 100;
1089 config_submenu_hide_delay = 400;
1090 config_menu_manage_desktops = TRUE;
1091 config_menu_files = NULL;
1092 config_menu_show_icons = TRUE;
1093
1094 obt_xml_register(i, "menu", parse_menu, NULL);
1095
1096 config_per_app_settings = NULL;
1097
1098 obt_xml_register(i, "applications", parse_per_app_settings, NULL);
1099 }
1100
1101 void config_shutdown(void)
1102 {
1103 GSList *it;
1104
1105 g_free(config_theme);
1106
1107 g_free(config_title_layout);
1108
1109 RrFontClose(config_font_activewindow);
1110 RrFontClose(config_font_inactivewindow);
1111 RrFontClose(config_font_menuitem);
1112 RrFontClose(config_font_menutitle);
1113 RrFontClose(config_font_activeosd);
1114 RrFontClose(config_font_inactiveosd);
1115
1116 for (it = config_desktops_names; it; it = g_slist_next(it))
1117 g_free(it->data);
1118 g_slist_free(config_desktops_names);
1119
1120 for (it = config_menu_files; it; it = g_slist_next(it))
1121 g_free(it->data);
1122 g_slist_free(config_menu_files);
1123
1124 for (it = config_per_app_settings; it; it = g_slist_next(it)) {
1125 ObAppSettings *itd = (ObAppSettings *)it->data;
1126 if (itd->name) g_pattern_spec_free(itd->name);
1127 if (itd->role) g_pattern_spec_free(itd->role);
1128 if (itd->title) g_pattern_spec_free(itd->title);
1129 if (itd->class) g_pattern_spec_free(itd->class);
1130 g_slice_free(ObAppSettings, it->data);
1131 }
1132 g_slist_free(config_per_app_settings);
1133 }
This page took 0.094203 seconds and 5 git commands to generate.