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