add the chainQuitKey option to teh <keyboard> section of the rc3
[mikachu/openbox.git] / openbox / config.c
1 #include "config.h"
2 #include "keyboard.h"
3 #include "mouse.h"
4 #include "prop.h"
5 #include "translate.h"
6 #include "parser/parse.h"
7
8 gboolean config_focus_new;
9 gboolean config_focus_follow;
10 gboolean config_focus_last;
11 gboolean config_focus_last_on_desktop;
12 gboolean config_focus_popup;
13 gboolean config_desktop_popup;
14
15 char *config_theme;
16
17 gchar *config_title_layout;
18
19 int     config_desktops_num;
20 GSList *config_desktops_names;
21
22 gboolean config_redraw_resize;
23
24 ObStackingLayer config_dock_layer;
25 gboolean        config_dock_floating;
26 ObDirection     config_dock_pos;
27 gint            config_dock_x;
28 gint            config_dock_y;
29 ObOrientation   config_dock_orient;
30 gboolean        config_dock_hide;
31 guint           config_dock_hide_timeout;
32
33 guint config_keyboard_reset_keycode;
34 guint config_keyboard_reset_state;
35
36 gint config_mouse_threshold;
37 gint config_mouse_dclicktime;
38
39 /*
40
41 <keybind key="C-x">
42   <action name="ChangeDesktop">
43     <desktop>3</desktop>
44   </action>
45 </keybind>
46
47 */
48
49 static void parse_key(xmlDocPtr doc, xmlNodePtr node, GList *keylist)
50 {
51     char *key;
52     ObAction *action;
53     xmlNodePtr n, nact;
54     GList *it;
55
56     if ((n = parse_find_node("chainQuitKey", node))) {
57         key = parse_string(doc, n);
58         translate_key(key, &config_keyboard_reset_state,
59                       &config_keyboard_reset_keycode);
60     }
61
62     n = parse_find_node("keybind", node);
63     while (n) {
64         if (parse_attr_string("key", n, &key)) {
65             keylist = g_list_append(keylist, key);
66
67             parse_key(doc, n->xmlChildrenNode, keylist);
68
69             it = g_list_last(keylist);
70             g_free(it->data);
71             keylist = g_list_delete_link(keylist, it);
72         }
73         n = parse_find_node("keybind", n->next);
74     }
75     if (keylist) {
76         nact = parse_find_node("action", node);
77         while (nact) {
78             if ((action = action_parse(doc, nact))) {
79                 /* validate that its okay for a key binding */
80                 if (action->func == action_moveresize &&
81                     action->data.moveresize.corner !=
82                     prop_atoms.net_wm_moveresize_move_keyboard &&
83                     action->data.moveresize.corner !=
84                     prop_atoms.net_wm_moveresize_size_keyboard) {
85                     action_free(action);
86                     action = NULL;
87                 }
88
89                 if (action)
90                     keyboard_bind(keylist, action);
91             }
92             nact = parse_find_node("action", nact->next);
93         }
94     }
95 }
96
97 static void parse_keyboard(xmlDocPtr doc, xmlNodePtr node, void *d)
98 {
99     parse_key(doc, node->xmlChildrenNode, NULL);
100 }
101
102 static int threshold;
103 static int dclicktime;
104 /*
105
106 <context name="Titlebar"> 
107   <mousebind button="Left" action="Press">
108     <action name="Raise"></action>
109   </mousebind>
110 </context>
111
112 */
113
114 static void parse_mouse(xmlDocPtr doc, xmlNodePtr node, void *d)
115 {
116     xmlNodePtr n, nbut, nact;
117     char *buttonstr;
118     char *contextstr;
119     ObMouseAction mact;
120     ObAction *action;
121
122     node = node->xmlChildrenNode;
123     
124     if ((n = parse_find_node("dragThreshold", node)))
125         threshold = parse_int(doc, n);
126     if ((n = parse_find_node("doubleClickTime", node)))
127         dclicktime = parse_int(doc, n);
128
129     n = parse_find_node("context", node);
130     while (n) {
131         if (!parse_attr_string("name", n, &contextstr))
132             goto next_n;
133         nbut = parse_find_node("mousebind", n->xmlChildrenNode);
134         while (nbut) {
135             if (!parse_attr_string("button", nbut, &buttonstr))
136                 goto next_nbut;
137             if (parse_attr_contains("press", nbut, "action"))
138                 mact = MouseAction_Press;
139             else if (parse_attr_contains("release", nbut, "action"))
140                 mact = MouseAction_Release;
141             else if (parse_attr_contains("click", nbut, "action"))
142                 mact = MouseAction_Click;
143             else if (parse_attr_contains("doubleclick", nbut,"action"))
144                 mact = MouseAction_DClick;
145             else if (parse_attr_contains("drag", nbut, "action"))
146                 mact = MouseAction_Motion;
147             else
148                 goto next_nbut;
149             nact = parse_find_node("action", nbut->xmlChildrenNode);
150             while (nact) {
151                 if ((action = action_parse(doc, nact))) {
152                     /* validate that its okay for a mouse binding*/
153                     if (mact == MouseAction_Motion) {
154                         if (action->func != action_moveresize ||
155                             action->data.moveresize.corner ==
156                             prop_atoms.net_wm_moveresize_move_keyboard ||
157                             action->data.moveresize.corner ==
158                             prop_atoms.net_wm_moveresize_size_keyboard) {
159                             action_free(action);
160                             action = NULL;
161                         }
162                     } else {
163                         if (action->func == action_moveresize &&
164                             action->data.moveresize.corner !=
165                             prop_atoms.net_wm_moveresize_move_keyboard &&
166                             action->data.moveresize.corner !=
167                             prop_atoms.net_wm_moveresize_size_keyboard) {
168                             action_free(action);
169                             action = NULL;
170                         }
171                     }
172                     if (action)
173                         mouse_bind(buttonstr, contextstr, mact, action);
174                 }
175                 nact = parse_find_node("action", nact->next);
176             }
177             g_free(buttonstr);
178         next_nbut:
179             nbut = parse_find_node("mousebind", nbut->next);
180         }
181         g_free(contextstr);
182     next_n:
183         n = parse_find_node("context", n->next);
184     }
185 }
186
187 static void parse_focus(xmlDocPtr doc, xmlNodePtr node, void *d)
188 {
189     xmlNodePtr n;
190
191     node = node->xmlChildrenNode;
192     
193     if ((n = parse_find_node("focusNew", node)))
194         config_focus_new = parse_bool(doc, n);
195     if ((n = parse_find_node("followMouse", node)))
196         config_focus_follow = parse_bool(doc, n);
197     if ((n = parse_find_node("focusLast", node)))
198         config_focus_last = parse_bool(doc, n);
199     if ((n = parse_find_node("focusLastOnDesktop", node)))
200         config_focus_last_on_desktop = parse_bool(doc, n);
201     if ((n = parse_find_node("cyclingDialog", node)))
202         config_focus_popup = parse_bool(doc, n);
203 }
204
205 static void parse_theme(xmlDocPtr doc, xmlNodePtr node, void *d)
206 {
207     xmlNodePtr n;
208
209     node = node->xmlChildrenNode;
210
211     if ((n = parse_find_node("theme", node))) {
212         g_free(config_theme);
213         config_theme = parse_string(doc, n);
214     }
215     if ((n = parse_find_node("titlelayout", node))) {
216         g_free(config_title_layout);
217         config_title_layout = parse_string(doc, n);
218     }
219 }
220
221 static void parse_desktops(xmlDocPtr doc, xmlNodePtr node, void *d)
222 {
223     xmlNodePtr n;
224
225     node = node->xmlChildrenNode;
226     
227     if ((n = parse_find_node("number", node)))
228         config_desktops_num = parse_int(doc, n);
229     if ((n = parse_find_node("names", node))) {
230         GSList *it;
231         xmlNodePtr nname;
232
233         for (it = config_desktops_names; it; it = it->next)
234             g_free(it->data);
235         g_slist_free(config_desktops_names);
236         config_desktops_names = NULL;
237
238         nname = parse_find_node("name", n->xmlChildrenNode);
239         while (nname) {
240             config_desktops_names = g_slist_append(config_desktops_names,
241                                                    parse_string(doc, nname));
242             nname = parse_find_node("name", nname->next);
243         }
244     }
245     if ((n = parse_find_node("cyclingDialog", node)))
246         config_desktop_popup = parse_bool(doc, n);
247 }
248
249 static void parse_resize(xmlDocPtr doc, xmlNodePtr node, void *d)
250 {
251     xmlNodePtr n;
252
253     node = node->xmlChildrenNode;
254     
255     if ((n = parse_find_node("drawContents", node)))
256         config_redraw_resize = parse_bool(doc, n);
257 }
258
259 static void parse_dock(xmlDocPtr doc, xmlNodePtr node, void *d)
260 {
261     xmlNodePtr n;
262
263     node = node->xmlChildrenNode;
264
265     if ((n = parse_find_node("position", node))) {
266         if (parse_contains("TopLeft", doc, n))
267             config_dock_floating = FALSE,
268             config_dock_pos = OB_DIRECTION_NORTHWEST;
269         else if (parse_contains("Top", doc, n))
270             config_dock_floating = FALSE,
271             config_dock_pos = OB_DIRECTION_NORTH;
272         else if (parse_contains("TopRight", doc, n))
273             config_dock_floating = FALSE,
274             config_dock_pos = OB_DIRECTION_NORTHEAST;
275         else if (parse_contains("Right", doc, n))
276             config_dock_floating = FALSE,
277             config_dock_pos = OB_DIRECTION_EAST;
278         else if (parse_contains("BottomRight", doc, n))
279             config_dock_floating = FALSE,
280             config_dock_pos = OB_DIRECTION_SOUTHEAST;
281         else if (parse_contains("Bottom", doc, n))
282             config_dock_floating = FALSE,
283             config_dock_pos = OB_DIRECTION_SOUTH;
284         else if (parse_contains("BottomLeft", doc, n))
285             config_dock_floating = FALSE,
286             config_dock_pos = OB_DIRECTION_SOUTHWEST;
287         else if (parse_contains("Left", doc, n))
288             config_dock_floating = FALSE,
289             config_dock_pos = OB_DIRECTION_WEST;
290         else if (parse_contains("Floating", doc, n))
291             config_dock_floating = TRUE;
292     }
293     if (config_dock_floating) {
294         if ((n = parse_find_node("floatingX", node)))
295             config_dock_x = parse_int(doc, n);
296         if ((n = parse_find_node("floatingY", node)))
297             config_dock_y = parse_int(doc, n);
298     }
299     if ((n = parse_find_node("stacking", node))) {
300         if (parse_contains("top", doc, n))
301             config_dock_layer = OB_STACKING_LAYER_TOP;
302         else if (parse_contains("normal", doc, n))
303             config_dock_layer = OB_STACKING_LAYER_NORMAL;
304         else if (parse_contains("bottom", doc, n))
305             config_dock_layer = OB_STACKING_LAYER_BELOW;
306     }
307     if ((n = parse_find_node("direction", node))) {
308         if (parse_contains("horizontal", doc, n))
309             config_dock_orient = OB_ORIENTATION_HORZ;
310         else if (parse_contains("vertical", doc, n))
311             config_dock_orient = OB_ORIENTATION_VERT;
312     }
313     if ((n = parse_find_node("autoHide", node)))
314         config_dock_hide = parse_bool(doc, n);
315     if ((n = parse_find_node("hideTimeout", node)))
316         config_dock_hide_timeout = parse_int(doc, n);
317 }
318
319 void config_startup()
320 {
321     config_focus_new = TRUE;
322     config_focus_follow = FALSE;
323     config_focus_last = TRUE;
324     config_focus_last_on_desktop = TRUE;
325     config_focus_popup = TRUE;
326
327     parse_register("focus", parse_focus, NULL);
328
329     config_theme = NULL;
330
331     config_title_layout = g_strdup("NLIMC");
332
333     parse_register("theme", parse_theme, NULL);
334
335     config_desktops_num = 4;
336     config_desktops_names = NULL;
337     config_desktop_popup = TRUE;
338
339     parse_register("desktops", parse_desktops, NULL);
340
341     config_redraw_resize = TRUE;
342
343     parse_register("resize", parse_resize, NULL);
344
345     config_dock_layer = OB_STACKING_LAYER_TOP;
346     config_dock_pos = OB_DIRECTION_NORTHEAST;
347     config_dock_floating = FALSE;
348     config_dock_x = 0;
349     config_dock_y = 0;
350     config_dock_orient = OB_ORIENTATION_VERT;
351     config_dock_hide = FALSE;
352     config_dock_hide_timeout = 3000;
353
354     parse_register("dock", parse_dock, NULL);
355
356     translate_key("C-g", &config_keyboard_reset_state,
357                   &config_keyboard_reset_keycode);
358
359     parse_register("keyboard", parse_keyboard, NULL);
360
361     config_mouse_threshold = 3;
362     config_mouse_dclicktime = 200;
363
364     parse_register("mouse", parse_mouse, NULL);
365 }
366
367 void config_shutdown()
368 {
369     GSList *it;
370
371     g_free(config_theme);
372
373     for (it = config_desktops_names; it; it = it->next)
374         g_free(it->data);
375     g_slist_free(config_desktops_names);
376 }