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