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