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