]> icculus.org git repositories - dana/openbox.git/blob - openbox/config.c
setting variables helps
[dana/openbox.git] / 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) 2004        Mikael Magnusson
5    Copyright (c) 2003        Ben 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 "prop.h"
24 #include "translate.h"
25 #include "client.h"
26 #include "parser/parse.h"
27 #include "openbox.h"
28
29 gboolean config_focus_new;
30 gboolean config_focus_follow;
31 guint    config_focus_delay;
32 gboolean config_focus_raise;
33 gboolean config_focus_last;
34
35 ObPlacePolicy config_place_policy;
36
37 gchar   *config_theme;
38 gboolean config_theme_keepborder;
39 gboolean config_theme_hidedisabled;
40
41 gchar *config_title_layout;
42
43 gint    config_desktops_num;
44 GSList *config_desktops_names;
45 gint    config_screen_firstdesk;
46
47 gboolean config_resize_redraw;
48 gboolean config_resize_four_corners;
49 gint     config_resize_popup_show;
50 gint     config_resize_popup_pos;
51
52 ObStackingLayer config_dock_layer;
53 gboolean        config_dock_floating;
54 gboolean        config_dock_nostrut;
55 ObDirection     config_dock_pos;
56 gint            config_dock_x;
57 gint            config_dock_y;
58 ObOrientation   config_dock_orient;
59 gboolean        config_dock_hide;
60 guint           config_dock_hide_delay;
61 guint           config_dock_show_delay;
62 guint           config_dock_app_move_button;
63 guint           config_dock_app_move_modifiers;
64
65 guint config_keyboard_reset_keycode;
66 guint config_keyboard_reset_state;
67
68 gint config_mouse_threshold;
69 gint config_mouse_dclicktime;
70
71 gboolean config_menu_warppointer;
72 gboolean config_menu_xorstyle;
73 guint    config_menu_hide_delay;
74 guint    config_submenu_show_delay;
75 gboolean config_menu_client_list_icons;
76
77 GSList *config_menu_files;
78
79 gint config_resist_win;
80 gint config_resist_edge;
81
82 gboolean config_resist_layers_below;
83
84 GSList *config_per_app_settings;
85
86 /*
87   <applications>
88     <application name="aterm">
89       <decor>false</decor>
90     </application>
91     <application name="Rhythmbox">
92       <layer>above</layer>
93       <position>
94         <x>700</x>
95         <y>0</y>
96       </position>
97       <head>1</head>
98     </application>
99   </applications>
100 */
101
102 /* Manages settings for individual applications.
103    Some notes: head is the screen number in a multi monitor
104    (Xinerama) setup (starting from 0) or mouse, meaning the
105    head the pointer is on. Default: mouse.
106    If decor is false and shade is true, the decor will be
107    set to true (otherwise we will have an invisible window).
108    Layer can be three values, above (Always on top), below
109    (Always on bottom) and everything else (normal behaviour).
110    Positions can be an integer value or center, which will
111    center the window in the specified axis. Position is relative
112    from head, so <position><x>center</x></position><head>1</head>
113    will center the window on the second head.
114 */
115 static void parse_per_app_settings(ObParseInst *i, xmlDocPtr doc,
116                                    xmlNodePtr node, gpointer d)
117 {
118     xmlNodePtr app = parse_find_node("application", node->children);
119     gchar *name;
120
121     while (app) {
122         gboolean x_pos_given = FALSE;
123         if (parse_attr_string("name", app, &name)) {
124             xmlNodePtr n, c;
125             ObAppSettings *settings = g_new0(ObAppSettings, 1);
126             settings->name = name;
127
128             settings->decor = TRUE;
129             if ((n = parse_find_node("decor", app->children)))
130                 settings->decor = parse_bool(doc, n);
131
132             if ((n = parse_find_node("shade", app->children)))
133                 settings->shade = parse_bool(doc, n);
134
135             settings->position.x = settings->position.y = 0;
136             settings->pos_given = FALSE;
137             if ((n = parse_find_node("position", app->children))) {
138                 if ((c = parse_find_node("x", n->children))) {
139                     if (!strcmp(parse_string(doc, c), "center")) {
140                         settings->center_x = TRUE;
141                         x_pos_given = TRUE;
142                     } else {
143                         settings->position.x = parse_int(doc, c);
144                         x_pos_given = TRUE;
145                     }
146                 }
147
148                 if (x_pos_given && (c = parse_find_node("y", n->children))) {
149                     if (!strcmp(parse_string(doc, c), "center")) {
150                         settings->center_y = TRUE;
151                         settings->pos_given = TRUE;
152                     } else {
153                         settings->position.y = parse_int(doc, c);
154                         settings->pos_given = TRUE;
155                     }
156                 }
157             }
158
159             if ((n = parse_find_node("focus", app->children)))
160                 settings->focus = parse_bool(doc, n);
161
162             if ((n = parse_find_node("desktop", app->children)))
163                 settings->desktop = parse_int(doc, n);
164             else
165                 settings->desktop = -1;
166
167             if ((n = parse_find_node("head", app->children))) {
168                 if (!strcmp(parse_string(doc, n), "mouse"))
169                     settings->head = -1;
170                 else
171                     settings->head = parse_int(doc, n);
172             }
173
174             if ((n = parse_find_node("layer", app->children))) {
175                 if (!strcmp(parse_string(doc, n), "above"))
176                     settings->layer = 1;
177                 else if (!strcmp(parse_string(doc, n), "below"))
178                     settings->layer = -1;
179                 else
180                     settings->layer = 0;
181             }
182
183             config_per_app_settings = g_slist_append(config_per_app_settings,
184                                               (gpointer) settings);
185         }
186         
187         app = parse_find_node("application", app->next);
188     }
189 }
190
191 /*
192
193 <keybind key="C-x">
194   <action name="ChangeDesktop">
195     <desktop>3</desktop>
196   </action>
197 </keybind>
198
199 */
200
201 static void parse_key(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
202                       GList *keylist)
203 {
204     gchar *key;
205     ObAction *action;
206     xmlNodePtr n, nact;
207     GList *it;
208
209     if ((n = parse_find_node("chainQuitKey", node))) {
210         key = parse_string(doc, n);
211         translate_key(key, &config_keyboard_reset_state,
212                       &config_keyboard_reset_keycode);
213         g_free(key);
214     }
215
216     n = parse_find_node("keybind", node);
217     while (n) {
218         if (parse_attr_string("key", n, &key)) {
219             keylist = g_list_append(keylist, key);
220
221             parse_key(i, doc, n->children, keylist);
222
223             it = g_list_last(keylist);
224             g_free(it->data);
225             keylist = g_list_delete_link(keylist, it);
226         }
227         n = parse_find_node("keybind", n->next);
228     }
229     if (keylist) {
230         nact = parse_find_node("action", node);
231         while (nact) {
232             if ((action = action_parse(i, doc, nact,
233                                        OB_USER_ACTION_KEYBOARD_KEY)))
234                 keyboard_bind(keylist, action);
235             nact = parse_find_node("action", nact->next);
236         }
237     }
238 }
239
240 static void parse_keyboard(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
241                            gpointer d)
242 {
243     keyboard_unbind_all();
244
245     parse_key(i, doc, node->children, NULL);
246 }
247
248 /*
249
250 <context name="Titlebar"> 
251   <mousebind button="Left" action="Press">
252     <action name="Raise"></action>
253   </mousebind>
254 </context>
255
256 */
257
258 static void parse_mouse(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
259                         gpointer d)
260 {
261     xmlNodePtr n, nbut, nact;
262     gchar *buttonstr;
263     gchar *contextstr;
264     ObUserAction uact;
265     ObMouseAction mact;
266     ObAction *action;
267
268     mouse_unbind_all();
269
270     node = node->children;
271     
272     if ((n = parse_find_node("dragThreshold", node)))
273         config_mouse_threshold = parse_int(doc, n);
274     if ((n = parse_find_node("doubleClickTime", node)))
275         config_mouse_dclicktime = parse_int(doc, n);
276
277     n = parse_find_node("context", node);
278     while (n) {
279         if (!parse_attr_string("name", n, &contextstr))
280             goto next_n;
281         nbut = parse_find_node("mousebind", n->children);
282         while (nbut) {
283             if (!parse_attr_string("button", nbut, &buttonstr))
284                 goto next_nbut;
285             if (parse_attr_contains("press", nbut, "action")) {
286                 uact = OB_USER_ACTION_MOUSE_PRESS;
287                 mact = OB_MOUSE_ACTION_PRESS;
288             } else if (parse_attr_contains("release", nbut, "action")) {
289                 uact = OB_USER_ACTION_MOUSE_RELEASE;
290                 mact = OB_MOUSE_ACTION_RELEASE;
291             } else if (parse_attr_contains("click", nbut, "action")) {
292                 uact = OB_USER_ACTION_MOUSE_CLICK;
293                 mact = OB_MOUSE_ACTION_CLICK;
294             } else if (parse_attr_contains("doubleclick", nbut,"action")) {
295                 uact = OB_USER_ACTION_MOUSE_DOUBLE_CLICK;
296                 mact = OB_MOUSE_ACTION_DOUBLE_CLICK;
297             } else if (parse_attr_contains("drag", nbut, "action")) {
298                 uact = OB_USER_ACTION_MOUSE_MOTION;
299                 mact = OB_MOUSE_ACTION_MOTION;
300             } else
301                 goto next_nbut;
302             nact = parse_find_node("action", nbut->children);
303             while (nact) {
304                 if ((action = action_parse(i, doc, nact, uact)))
305                     mouse_bind(buttonstr, contextstr, mact, action);
306                 nact = parse_find_node("action", nact->next);
307             }
308             g_free(buttonstr);
309         next_nbut:
310             nbut = parse_find_node("mousebind", nbut->next);
311         }
312         g_free(contextstr);
313     next_n:
314         n = parse_find_node("context", n->next);
315     }
316 }
317
318 static void parse_focus(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
319                         gpointer d)
320 {
321     xmlNodePtr n;
322
323     node = node->children;
324     
325     if ((n = parse_find_node("focusNew", node)))
326         config_focus_new = parse_bool(doc, n);
327     if ((n = parse_find_node("followMouse", node)))
328         config_focus_follow = parse_bool(doc, n);
329     if ((n = parse_find_node("focusDelay", node)))
330         config_focus_delay = parse_int(doc, n) * 1000;
331     if ((n = parse_find_node("raiseOnFocus", node)))
332         config_focus_raise = parse_bool(doc, n);
333     if ((n = parse_find_node("focusLast", node)))
334         config_focus_last = parse_bool(doc, n);
335 }
336
337 static void parse_placement(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
338                             gpointer d)
339 {
340     xmlNodePtr n;
341
342     node = node->children;
343     
344     if ((n = parse_find_node("policy", node)))
345         if (parse_contains("UnderMouse", doc, n))
346             config_place_policy = OB_PLACE_POLICY_MOUSE;
347 }
348
349 static void parse_theme(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
350                         gpointer d)
351 {
352     xmlNodePtr n;
353
354     node = node->children;
355
356     if ((n = parse_find_node("name", node))) {
357         gchar *c;
358
359         g_free(config_theme);
360         c = parse_string(doc, n);
361         config_theme = parse_expand_tilde(c);
362         g_free(c);
363     }
364     if ((n = parse_find_node("titleLayout", node))) {
365         g_free(config_title_layout);
366         config_title_layout = parse_string(doc, n);
367     }
368     if ((n = parse_find_node("keepBorder", node)))
369         config_theme_keepborder = parse_bool(doc, n);
370     if ((n = parse_find_node("hideDisabled", node)))
371         config_theme_hidedisabled = parse_bool(doc, n);
372 }
373
374 static void parse_desktops(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
375                            gpointer d)
376 {
377     xmlNodePtr n;
378
379     node = node->children;
380     
381     if ((n = parse_find_node("number", node))) {
382         gint d = parse_int(doc, n);
383         if (d > 0)
384             config_desktops_num = d;
385     }
386     if ((n = parse_find_node("firstdesk", node))) {
387         gint d = parse_int(doc, n);
388         if (d > 0)
389             config_screen_firstdesk = d;
390     }
391     if ((n = parse_find_node("names", node))) {
392         GSList *it;
393         xmlNodePtr nname;
394
395         for (it = config_desktops_names; it; it = it->next)
396             g_free(it->data);
397         g_slist_free(config_desktops_names);
398         config_desktops_names = NULL;
399
400         nname = parse_find_node("name", n->children);
401         while (nname) {
402             config_desktops_names = g_slist_append(config_desktops_names,
403                                                    parse_string(doc, nname));
404             nname = parse_find_node("name", nname->next);
405         }
406     }
407 }
408
409 static void parse_resize(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
410                          gpointer d)
411 {
412     xmlNodePtr n;
413
414     node = node->children;
415     
416     if ((n = parse_find_node("drawContents", node)))
417         config_resize_redraw = parse_bool(doc, n);
418     if ((n = parse_find_node("fourCorner", node)))
419         config_resize_four_corners = parse_bool(doc, n);
420     if ((n = parse_find_node("popupShow", node))) {
421         config_resize_popup_show = parse_int(doc, n);
422         if (parse_contains("Always", doc, n))
423             config_resize_popup_show = 2;
424         else if (parse_contains("Never", doc, n))
425             config_resize_popup_show = 0;
426         else if (parse_contains("Nonpixel", doc, n))
427             config_resize_popup_show = 1;
428     }
429     if ((n = parse_find_node("popupPosition", node))) {
430         config_resize_popup_pos = parse_int(doc, n);
431         if (parse_contains("Top", doc, n))
432             config_resize_popup_pos = 1;
433         else if (parse_contains("Center", doc, n))
434             config_resize_popup_pos = 0;
435     }
436 }
437
438 static void parse_dock(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
439                        gpointer d)
440 {
441     xmlNodePtr n;
442
443     node = node->children;
444
445     if ((n = parse_find_node("position", node))) {
446         if (parse_contains("TopLeft", doc, n))
447             config_dock_floating = FALSE,
448             config_dock_pos = OB_DIRECTION_NORTHWEST;
449         else if (parse_contains("Top", doc, n))
450             config_dock_floating = FALSE,
451             config_dock_pos = OB_DIRECTION_NORTH;
452         else if (parse_contains("TopRight", doc, n))
453             config_dock_floating = FALSE,
454             config_dock_pos = OB_DIRECTION_NORTHEAST;
455         else if (parse_contains("Right", doc, n))
456             config_dock_floating = FALSE,
457             config_dock_pos = OB_DIRECTION_EAST;
458         else if (parse_contains("BottomRight", doc, n))
459             config_dock_floating = FALSE,
460             config_dock_pos = OB_DIRECTION_SOUTHEAST;
461         else if (parse_contains("Bottom", doc, n))
462             config_dock_floating = FALSE,
463             config_dock_pos = OB_DIRECTION_SOUTH;
464         else if (parse_contains("BottomLeft", doc, n))
465             config_dock_floating = FALSE,
466             config_dock_pos = OB_DIRECTION_SOUTHWEST;
467         else if (parse_contains("Left", doc, n))
468             config_dock_floating = FALSE,
469             config_dock_pos = OB_DIRECTION_WEST;
470         else if (parse_contains("Floating", doc, n))
471             config_dock_floating = TRUE;
472     }
473     if (config_dock_floating) {
474         if ((n = parse_find_node("floatingX", node)))
475             config_dock_x = parse_int(doc, n);
476         if ((n = parse_find_node("floatingY", node)))
477             config_dock_y = parse_int(doc, n);
478     } else {
479         if ((n = parse_find_node("noStrut", node)))
480             config_dock_nostrut = parse_bool(doc, n);
481     }
482     if ((n = parse_find_node("stacking", node))) {
483         if (parse_contains("top", doc, n))
484             config_dock_layer = OB_STACKING_LAYER_ABOVE;
485         else if (parse_contains("normal", doc, n))
486             config_dock_layer = OB_STACKING_LAYER_NORMAL;
487         else if (parse_contains("bottom", doc, n))
488             config_dock_layer = OB_STACKING_LAYER_BELOW;
489     }
490     if ((n = parse_find_node("direction", node))) {
491         if (parse_contains("horizontal", doc, n))
492             config_dock_orient = OB_ORIENTATION_HORZ;
493         else if (parse_contains("vertical", doc, n))
494             config_dock_orient = OB_ORIENTATION_VERT;
495     }
496     if ((n = parse_find_node("autoHide", node)))
497         config_dock_hide = parse_bool(doc, n);
498     if ((n = parse_find_node("hideDelay", node)))
499         config_dock_hide_delay = parse_int(doc, n) * 1000;
500     if ((n = parse_find_node("showDelay", node)))
501         config_dock_show_delay = parse_int(doc, n) * 1000;
502     if ((n = parse_find_node("moveButton", node))) {
503         gchar *str = parse_string(doc, n);
504         guint b, s;
505         if (translate_button(str, &s, &b)) {
506             config_dock_app_move_button = b;
507             config_dock_app_move_modifiers = s;
508         } else {
509             g_warning("invalid button '%s'", str);
510         }
511         g_free(str);
512     }
513 }
514
515 static void parse_menu(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
516                        gpointer d)
517 {
518     xmlNodePtr n;
519     for (node = node->children; node; node = node->next) {
520         if (!xmlStrcasecmp(node->name, (const xmlChar*) "file")) {
521             gchar *c;
522
523             c = parse_string(doc, node);
524             config_menu_files = g_slist_append(config_menu_files,
525                                                parse_expand_tilde(c));
526             g_free(c);
527         }
528         if ((n = parse_find_node("warpPointer", node)))
529             config_menu_warppointer = parse_bool(doc, n);
530         if ((n = parse_find_node("xorStyle", node)))
531             config_menu_xorstyle = parse_bool(doc, n);
532         if ((n = parse_find_node("hideDelay", node)))
533             config_menu_hide_delay = parse_int(doc, n);
534         if ((n = parse_find_node("submenuShowDelay", node)))
535             config_submenu_show_delay = parse_int(doc, n);
536         if ((n = parse_find_node("desktopMenuIcons", node)))
537             config_menu_client_list_icons = parse_bool(doc, n);
538     }
539 }
540    
541 static void parse_resistance(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node, 
542                              gpointer d)
543 {
544     xmlNodePtr n;
545
546     node = node->children;
547     if ((n = parse_find_node("strength", node)))
548         config_resist_win = parse_int(doc, n);
549     if ((n = parse_find_node("screen_edge_strength", node)))
550         config_resist_edge = parse_int(doc, n);
551     if ((n = parse_find_node("edges_hit_layers_below", node)))
552         config_resist_layers_below = parse_bool(doc, n);
553 }
554
555 typedef struct
556 {
557     const gchar *key;
558     const gchar *actname;
559 } ObDefKeyBind;
560
561 static void bind_default_keyboard()
562 {
563     ObDefKeyBind *it;
564     ObDefKeyBind binds[] = {
565         { "A-Tab", "NextWindow" },
566         { "S-A-Tab", "PreviousWindow" },
567         { "A-F4", "Close" },
568         { NULL, NULL }
569     };
570
571     for (it = binds; it->key; ++it) {
572         GList *l = g_list_append(NULL, g_strdup(it->key));
573         keyboard_bind(l, action_from_string(it->actname,
574                                             OB_USER_ACTION_KEYBOARD_KEY));
575     }
576 }
577
578 typedef struct
579 {
580     const gchar *button;
581     const gchar *context;
582     const ObMouseAction mact;
583     const gchar *actname;
584 } ObDefMouseBind;
585
586 static void bind_default_mouse()
587 {
588     ObDefMouseBind *it;
589     ObDefMouseBind binds[] = {
590         { "Left", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
591         { "Middle", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
592         { "Right", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
593         { "Left", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
594         { "Middle", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
595         { "Right", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
596         { "Left", "Titlebar", OB_MOUSE_ACTION_PRESS, "Focus" },
597         { "Left", "Handle", OB_MOUSE_ACTION_PRESS, "Focus" },
598         { "Left", "BLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
599         { "Left", "BRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
600         { "Left", "TLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
601         { "Left", "TRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
602         { "Left", "Close", OB_MOUSE_ACTION_PRESS, "Focus" },
603         { "Left", "Maximize", OB_MOUSE_ACTION_PRESS, "Focus" },
604         { "Left", "Iconify", OB_MOUSE_ACTION_PRESS, "Focus" },
605         { "Left", "Icon", OB_MOUSE_ACTION_PRESS, "Focus" },
606         { "Left", "AllDesktops", OB_MOUSE_ACTION_PRESS, "Focus" },
607         { "Left", "Shade", OB_MOUSE_ACTION_PRESS, "Focus" },
608         { "Left", "Client", OB_MOUSE_ACTION_CLICK, "Raise" },
609         { "Left", "Titlebar", OB_MOUSE_ACTION_CLICK, "Raise" },
610         { "Middle", "Titlebar", OB_MOUSE_ACTION_CLICK, "Lower" },
611         { "Left", "Handle", OB_MOUSE_ACTION_CLICK, "Raise" },
612         { "Left", "BLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
613         { "Left", "BRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
614         { "Left", "TLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
615         { "Left", "TRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
616         { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Raise" },
617         { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "Raise" },
618         { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Raise" },
619         { "Left", "Icon", OB_MOUSE_ACTION_CLICK, "Raise" },
620         { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "Raise" },
621         { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "Raise" },
622         { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Close" },
623         { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "ToggleMaximizeFull" },
624         { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Iconify" },
625         { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "ToggleOmnipresent" },
626         { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "ToggleShade" },
627         { "Left", "TLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
628         { "Left", "TRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
629         { "Left", "BLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
630         { "Left", "BRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
631         { "Left", "Titlebar", OB_MOUSE_ACTION_MOTION, "Move" },
632         { "A-Left", "Frame", OB_MOUSE_ACTION_MOTION, "Move" },
633         { "A-Middle", "Frame", OB_MOUSE_ACTION_MOTION, "Resize" },
634         { NULL, NULL, 0, NULL }
635     };
636
637     for (it = binds; it->button; ++it) {
638         ObUserAction uact;
639         switch (it->mact) {
640         case OB_MOUSE_ACTION_PRESS:
641             uact = OB_USER_ACTION_MOUSE_PRESS; break;
642         case OB_MOUSE_ACTION_RELEASE:
643             uact = OB_USER_ACTION_MOUSE_RELEASE; break;
644         case OB_MOUSE_ACTION_CLICK:
645             uact = OB_USER_ACTION_MOUSE_CLICK; break;
646         case OB_MOUSE_ACTION_DOUBLE_CLICK:
647             uact = OB_USER_ACTION_MOUSE_DOUBLE_CLICK; break;
648         case OB_MOUSE_ACTION_MOTION:
649             uact = OB_USER_ACTION_MOUSE_MOTION; break;
650         case OB_NUM_MOUSE_ACTIONS:
651             g_assert_not_reached();
652         }
653         mouse_bind(it->button, it->context, it->mact,
654                    action_from_string(it->actname, uact));
655     }
656 }
657
658 void config_startup(ObParseInst *i)
659 {
660     config_focus_new = TRUE;
661     config_focus_follow = FALSE;
662     config_focus_delay = 0;
663     config_focus_raise = FALSE;
664     config_focus_last = FALSE;
665
666     parse_register(i, "focus", parse_focus, NULL);
667
668     config_place_policy = OB_PLACE_POLICY_SMART;
669
670     parse_register(i, "placement", parse_placement, NULL);
671
672     config_theme = NULL;
673
674     config_title_layout = g_strdup("NLIMC");
675     config_theme_keepborder = TRUE;
676     config_theme_hidedisabled = FALSE;
677
678     parse_register(i, "theme", parse_theme, NULL);
679
680     config_desktops_num = 4;
681     config_screen_firstdesk = 1;
682     config_desktops_names = NULL;
683
684     parse_register(i, "desktops", parse_desktops, NULL);
685
686     config_resize_redraw = TRUE;
687     config_resize_four_corners = FALSE;
688     config_resize_popup_show = 1; /* nonpixel increments */
689     config_resize_popup_pos = 0;  /* center of client */
690
691     parse_register(i, "resize", parse_resize, NULL);
692
693     config_dock_layer = OB_STACKING_LAYER_ABOVE;
694     config_dock_pos = OB_DIRECTION_NORTHEAST;
695     config_dock_floating = FALSE;
696     config_dock_nostrut = FALSE;
697     config_dock_x = 0;
698     config_dock_y = 0;
699     config_dock_orient = OB_ORIENTATION_VERT;
700     config_dock_hide = FALSE;
701     config_dock_hide_delay = 300;
702     config_dock_show_delay = 300;
703     config_dock_app_move_button = 2; /* middle */
704     config_dock_app_move_modifiers = 0;
705
706     parse_register(i, "dock", parse_dock, NULL);
707
708     translate_key("C-g", &config_keyboard_reset_state,
709                   &config_keyboard_reset_keycode);
710
711     bind_default_keyboard();
712
713     parse_register(i, "keyboard", parse_keyboard, NULL);
714
715     config_mouse_threshold = 3;
716     config_mouse_dclicktime = 200;
717
718     bind_default_mouse();
719
720     parse_register(i, "mouse", parse_mouse, NULL);
721
722     config_resist_win = 10;
723     config_resist_edge = 20;
724     config_resist_layers_below = FALSE;
725
726     parse_register(i, "resistance", parse_resistance, NULL);
727
728     config_menu_warppointer = TRUE;
729     config_menu_xorstyle = TRUE;
730     config_menu_hide_delay = 250;
731     config_submenu_show_delay = 0;
732     config_menu_client_list_icons = TRUE;
733     config_menu_files = NULL;
734
735     parse_register(i, "menu", parse_menu, NULL);
736
737     config_per_app_settings = NULL;
738
739     parse_register(i, "applications", parse_per_app_settings, NULL);
740 }
741
742 void config_shutdown()
743 {
744     GSList *it;
745
746     g_free(config_theme);
747
748     g_free(config_title_layout);
749
750     for (it = config_desktops_names; it; it = g_slist_next(it))
751         g_free(it->data);
752     g_slist_free(config_desktops_names);
753
754     for (it = config_menu_files; it; it = g_slist_next(it))
755         g_free(it->data);
756     g_slist_free(config_menu_files);
757
758     for (it = config_per_app_settings; it; it = g_slist_next(it))
759         g_free(it->data);
760     g_slist_free(config_per_app_settings);
761 }