Merge branch 'contrib_goto_focus'
[notion.git] / ioncore / bindmaps.c
blob4212570e7bfa17d317b723a4d124f420b8c5be02
1 /*
2 * ion/ioncore/bindmaps.c
4 * Copyright (c) Tuomo Valkonen 1999-2009.
6 * See the included file LICENSE for details.
7 */
9 #include <X11/XKBlib.h>
10 #include <libtu/rb.h>
11 #include <libextl/extl.h>
12 #include "common.h"
13 #include "conf-bindings.h"
14 #include "binding.h"
15 #include "framep.h"
16 #include "bindmaps.h"
17 #include "global.h"
18 #include "regbind.h"
21 /*
22 * This file contains higher-level bindmap management code
26 WBindmap *ioncore_screen_bindmap=NULL;
27 WBindmap *ioncore_mplex_bindmap=NULL;
28 WBindmap *ioncore_mplex_toplevel_bindmap=NULL;
29 WBindmap *ioncore_frame_bindmap=NULL;
30 WBindmap *ioncore_frame_toplevel_bindmap=NULL;
31 WBindmap *ioncore_frame_floating_bindmap=NULL;
32 WBindmap *ioncore_frame_tiled_bindmap=NULL;
33 WBindmap *ioncore_frame_transient_bindmap=NULL;
34 WBindmap *ioncore_moveres_bindmap=NULL;
35 WBindmap *ioncore_group_bindmap=NULL;
36 WBindmap *ioncore_groupcw_bindmap=NULL;
37 WBindmap *ioncore_groupws_bindmap=NULL;
38 WBindmap *ioncore_clientwin_bindmap=NULL;
40 static Rb_node known_bindmaps=NULL;
42 static StringIntMap frame_areas[]={
43 {"border", FRAME_AREA_BORDER},
44 {"tab", FRAME_AREA_TAB},
45 {"empty_tab", FRAME_AREA_TAB},
46 {"client", FRAME_AREA_CLIENT},
47 END_STRINGINTMAP
51 #define DO_FREE(X, Y) \
52 if(ioncore_ ## X ## _bindmap!=NULL){ \
53 ioncore_free_bindmap(Y, ioncore_ ## X ## _bindmap); \
54 ioncore_ ## X ## _bindmap=NULL; \
57 void ioncore_deinit_bindmaps()
59 DO_FREE(screen, "WScreen");
60 DO_FREE(mplex, "WMPlex");
61 DO_FREE(mplex_toplevel, "WMPlex.toplevel");
62 DO_FREE(frame, "WFrame");
63 DO_FREE(frame_toplevel, "WFrame.toplevel");
64 DO_FREE(frame_floating, "WFrame.floating");
65 DO_FREE(frame_tiled, "WFrame.tiled");
66 DO_FREE(frame_transient, "WFrame.transient");
67 DO_FREE(moveres, "WMoveresMode");
68 DO_FREE(group, "WGroup");
69 DO_FREE(groupcw, "WGroupCW");
70 DO_FREE(groupws, "WGroupWS");
71 DO_FREE(clientwin, "WClientWin");
72 rb_free_tree(known_bindmaps);
73 known_bindmaps=NULL;
77 #define DO_ALLOC(X, Y, Z) \
78 ioncore_ ## X ## _bindmap=ioncore_alloc_bindmap(Y, Z); \
79 if(ioncore_ ## X ## _bindmap==NULL) \
80 return FALSE;
82 bool ioncore_init_bindmaps()
84 known_bindmaps=make_rb();
86 if(known_bindmaps==NULL)
87 return FALSE;
89 DO_ALLOC(screen, "WScreen", NULL);
90 DO_ALLOC(mplex, "WMPlex", NULL);
91 DO_ALLOC(mplex_toplevel, "WMPlex.toplevel", NULL);
92 DO_ALLOC(frame, "WFrame", frame_areas);
93 DO_ALLOC(frame_toplevel, "WFrame.toplevel", frame_areas);
94 DO_ALLOC(frame_floating, "WFrame.floating", frame_areas);
95 DO_ALLOC(frame_tiled, "WFrame.tiled", frame_areas);
96 DO_ALLOC(frame_transient, "WFrame.transient", frame_areas);
97 DO_ALLOC(moveres, "WMoveresMode", NULL);
98 DO_ALLOC(group, "WGroup", NULL);
99 DO_ALLOC(groupcw, "WGroupCW", NULL);
100 DO_ALLOC(groupws, "WGroupWS", NULL);
101 DO_ALLOC(clientwin, "WClientWin", NULL);
103 return TRUE;
108 void ioncore_refresh_bindmaps()
110 Rb_node node;
112 ioncore_update_modmap();
114 rb_traverse(node,known_bindmaps){
115 bindmap_refresh((WBindmap*)rb_val(node));
120 WBindmap *ioncore_alloc_bindmap(const char *name, const StringIntMap *areas)
122 WBindmap *bm=create_bindmap();
124 if(bm==NULL)
125 return NULL;
127 bm->areamap=areas;
129 if(!rb_insert(known_bindmaps, name, bm)){
130 bindmap_destroy(bm);
131 return NULL;
134 return bm;
138 WBindmap *ioncore_alloc_bindmap_frame(const char *name)
140 return ioncore_alloc_bindmap(name, frame_areas);
144 void ioncore_free_bindmap(const char *name, WBindmap *bm)
146 int found=0;
147 Rb_node node;
149 node=rb_find_key_n(known_bindmaps, name, &found);
150 assert(found!=0 && rb_val(node)==(void*)bm);
152 rb_delete_node(node);
153 bindmap_destroy(bm);
157 WBindmap *ioncore_lookup_bindmap(const char *name)
159 int found=0;
160 Rb_node node;
162 node=rb_find_key_n(known_bindmaps, name, &found);
164 if(found==0)
165 return NULL;
167 return (WBindmap*)rb_val(node);
171 EXTL_EXPORT
172 bool ioncore_do_defbindings(const char *name, ExtlTab tab)
174 WBindmap *bm=ioncore_lookup_bindmap(name);
175 if(bm==NULL){
176 warn("Unknown bindmap %s.", name);
177 return FALSE;
179 return bindmap_defbindings(bm, tab, FALSE);
183 EXTL_SAFE
184 EXTL_EXPORT
185 ExtlTab ioncore_do_getbindings()
187 Rb_node node;
188 ExtlTab tab;
190 tab=extl_create_table();
192 rb_traverse(node, known_bindmaps){
193 ExtlTab bmtab=bindmap_getbindings((WBindmap*)rb_val(node));
194 extl_table_sets_t(tab, (const char*)node->k.key, bmtab);
195 extl_unref_table(bmtab);
198 return tab;
202 WBindmap *ioncore_create_cycle_bindmap(uint kcb, uint state,
203 ExtlFn cycle, ExtlFn bcycle)
205 WBindmap *bindmap=create_bindmap();
206 WBinding b;
208 if(bindmap==NULL)
209 return NULL;
211 b.ksb=XkbKeycodeToKeysym(ioncore_g.dpy, kcb, 0, 0);
212 b.kcb=kcb;
213 b.state=state;
214 b.act=BINDING_KEYPRESS;
215 b.area=0;
216 b.wait=FALSE;
217 b.submap=NULL;
218 b.func=extl_ref_fn(cycle);
220 if(!bindmap_add_binding(bindmap, &b)){
221 extl_unref_fn(b.func);
222 bindmap_destroy(bindmap);
223 return NULL;
226 if((b.state&ShiftMask)==0 && bcycle!=extl_fn_none()){
227 b.func=extl_ref_fn(bcycle);
228 b.state|=ShiftMask;
229 bindmap_add_binding(bindmap, &b);
232 return bindmap;
236 WBindmap *region_add_cycle_bindmap(WRegion *reg, uint kcb, uint state,
237 ExtlFn cycle, ExtlFn bcycle)
239 WBindmap *bindmap=ioncore_create_cycle_bindmap(kcb, state, cycle, bcycle);
241 if(bindmap!=NULL){
242 if(!region_add_bindmap(reg, bindmap)){
243 bindmap_destroy(bindmap);
244 return NULL;
248 return bindmap;