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