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