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