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