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