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