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