]> git.decadent.org.uk Git - ion3.git/blob - ioncore/bindmaps.c
e7318a865a235306dc512a7222a80efd603aa3ca
[ion3.git] / ioncore / bindmaps.c
1 /*
2  * ion/ioncore/bindmaps.c
3  *
4  * Copyright (c) Tuomo Valkonen 1999-2008. 
5  *
6  * See the included file LICENSE for details.
7  */
8
9 #include <libtu/rb.h>
10 #include <libextl/extl.h>
11 #include "common.h"
12 #include "conf-bindings.h"
13 #include "binding.h"
14 #include "framep.h"
15 #include "bindmaps.h"
16 #include "global.h"
17 #include "regbind.h"
18
19
20 /* 
21  * This file contains higher-level bindmap management code
22  */
23
24
25 WBindmap *ioncore_screen_bindmap=NULL;
26 WBindmap *ioncore_mplex_bindmap=NULL;
27 WBindmap *ioncore_mplex_toplevel_bindmap=NULL;
28 WBindmap *ioncore_frame_bindmap=NULL;
29 WBindmap *ioncore_frame_toplevel_bindmap=NULL;
30 WBindmap *ioncore_frame_floating_bindmap=NULL;
31 WBindmap *ioncore_frame_tiled_bindmap=NULL;
32 WBindmap *ioncore_frame_transient_bindmap=NULL;
33 WBindmap *ioncore_moveres_bindmap=NULL;
34 WBindmap *ioncore_group_bindmap=NULL;
35 WBindmap *ioncore_groupcw_bindmap=NULL;
36 WBindmap *ioncore_groupws_bindmap=NULL;
37 WBindmap *ioncore_clientwin_bindmap=NULL;
38
39 static Rb_node known_bindmaps=NULL;
40
41 static StringIntMap frame_areas[]={
42     {"border",      FRAME_AREA_BORDER},
43     {"tab",         FRAME_AREA_TAB},
44     {"empty_tab",   FRAME_AREA_TAB},
45     {"client",      FRAME_AREA_CLIENT},
46     END_STRINGINTMAP
47 };
48
49
50 #define DO_FREE(X, Y)                                       \
51     if(ioncore_ ## X ## _bindmap!=NULL){                    \
52         ioncore_free_bindmap(Y, ioncore_ ## X ## _bindmap); \
53         ioncore_ ## X ## _bindmap=NULL;                     \
54     }
55
56 void ioncore_deinit_bindmaps()
57 {
58     DO_FREE(screen, "WScreen");
59     DO_FREE(mplex, "WMPlex");
60     DO_FREE(mplex_toplevel, "WMPlex.toplevel");
61     DO_FREE(frame, "WFrame");
62     DO_FREE(frame_toplevel, "WFrame.toplevel");
63     DO_FREE(frame_floating, "WFrame.floating");
64     DO_FREE(frame_tiled, "WFrame.tiled");
65     DO_FREE(frame_transient, "WFrame.transient");
66     DO_FREE(moveres, "WMoveresMode");
67     DO_FREE(group, "WGroup");
68     DO_FREE(groupcw, "WGroupCW");
69     DO_FREE(groupws, "WGroupWS");
70     DO_FREE(clientwin, "WClientWin");
71     rb_free_tree(known_bindmaps);
72     known_bindmaps=NULL;
73 }
74
75
76 #define DO_ALLOC(X, Y, Z)                                  \
77     ioncore_ ## X ## _bindmap=ioncore_alloc_bindmap(Y, Z); \
78     if(ioncore_ ## X ## _bindmap==NULL)                    \
79         return FALSE;
80
81 bool ioncore_init_bindmaps()
82 {
83     known_bindmaps=make_rb();
84     
85     if(known_bindmaps==NULL)
86         return FALSE;
87     
88     DO_ALLOC(screen, "WScreen", NULL);
89     DO_ALLOC(mplex, "WMPlex", NULL);
90     DO_ALLOC(mplex_toplevel, "WMPlex.toplevel", NULL);
91     DO_ALLOC(frame, "WFrame", frame_areas);
92     DO_ALLOC(frame_toplevel, "WFrame.toplevel", frame_areas);
93     DO_ALLOC(frame_floating, "WFrame.floating", frame_areas);
94     DO_ALLOC(frame_tiled, "WFrame.tiled", frame_areas);
95     DO_ALLOC(frame_transient, "WFrame.transient", frame_areas);
96     DO_ALLOC(moveres, "WMoveresMode", NULL);
97     DO_ALLOC(group, "WGroup", NULL);
98     DO_ALLOC(groupcw, "WGroupCW", NULL);
99     DO_ALLOC(groupws, "WGroupWS", NULL);
100     DO_ALLOC(clientwin, "WClientWin", NULL);
101     
102     return TRUE;
103 }
104
105
106
107 void ioncore_refresh_bindmaps()
108 {
109     Rb_node node;
110     
111     ioncore_update_modmap();
112     
113     rb_traverse(node,known_bindmaps){
114         bindmap_refresh((WBindmap*)rb_val(node));
115     }
116 }
117
118
119 WBindmap *ioncore_alloc_bindmap(const char *name, const StringIntMap *areas)
120 {
121     WBindmap *bm=create_bindmap();
122
123     if(bm==NULL)
124         return NULL;
125     
126     bm->areamap=areas;
127     
128     if(!rb_insert(known_bindmaps, name, bm)){
129         bindmap_destroy(bm);
130         return NULL;
131     }
132     
133     return bm;
134 }
135
136
137 WBindmap *ioncore_alloc_bindmap_frame(const char *name)
138 {
139     return ioncore_alloc_bindmap(name, frame_areas);
140 }
141
142
143 void ioncore_free_bindmap(const char *name, WBindmap *bm)
144 {
145     int found=0;
146     Rb_node node;
147     
148     node=rb_find_key_n(known_bindmaps, name, &found);
149     assert(found!=0 && rb_val(node)==(void*)bm);
150     
151     rb_delete_node(node);
152     bindmap_destroy(bm);
153 }
154
155
156 WBindmap *ioncore_lookup_bindmap(const char *name)
157 {
158     int found=0;
159     Rb_node node;
160     
161     node=rb_find_key_n(known_bindmaps, name, &found);
162     
163     if(found==0)
164         return NULL;
165     
166     return (WBindmap*)rb_val(node);
167 }
168
169
170 EXTL_EXPORT
171 bool ioncore_do_defbindings(const char *name, ExtlTab tab)
172 {
173     WBindmap *bm=ioncore_lookup_bindmap(name);
174     if(bm==NULL){
175         warn("Unknown bindmap %s.", name);
176         return FALSE;
177     }
178     return bindmap_defbindings(bm, tab, FALSE);
179 }
180
181
182 EXTL_SAFE
183 EXTL_EXPORT
184 ExtlTab ioncore_do_getbindings()
185 {
186     Rb_node node;
187     ExtlTab tab;
188     
189     tab=extl_create_table();
190     
191     rb_traverse(node, known_bindmaps){
192         ExtlTab bmtab=bindmap_getbindings((WBindmap*)rb_val(node));
193         extl_table_sets_t(tab, (const char*)node->k.key, bmtab);
194         extl_unref_table(bmtab);
195     }
196     
197     return tab;
198 }
199
200
201 WBindmap *ioncore_create_cycle_bindmap(uint kcb, uint state, 
202                                        ExtlFn cycle, ExtlFn bcycle)
203 {
204     WBindmap *bindmap=create_bindmap();
205     WBinding b;
206     
207     if(bindmap==NULL)
208         return NULL;
209         
210     b.ksb=XKeycodeToKeysym(ioncore_g.dpy, kcb, 0);
211     b.kcb=kcb;
212     b.state=state;
213     b.act=BINDING_KEYPRESS;
214     b.area=0;
215     b.wait=FALSE;
216     b.submap=NULL;
217     b.func=extl_ref_fn(cycle);
218     
219     if(!bindmap_add_binding(bindmap, &b)){
220         extl_unref_fn(b.func);
221         bindmap_destroy(bindmap);
222         return NULL;
223     }
224     
225     if((b.state&ShiftMask)==0 && bcycle!=extl_fn_none()){
226         b.func=extl_ref_fn(bcycle);
227         b.state|=ShiftMask;
228         bindmap_add_binding(bindmap, &b);
229     }
230     
231     return bindmap;
232 }
233
234
235 WBindmap *region_add_cycle_bindmap(WRegion *reg, uint kcb, uint state, 
236                                    ExtlFn cycle, ExtlFn bcycle)
237 {
238     WBindmap *bindmap=ioncore_create_cycle_bindmap(kcb, state, cycle, bcycle);
239     
240     if(bindmap!=NULL){
241         if(!region_add_bindmap(reg, bindmap)){
242             bindmap_destroy(bindmap);
243             return NULL;
244         }
245     }
246     
247     return bindmap;
248 }
249