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