Consistency fixes
[notion.git] / ioncore / regbind.c
blobb18e5c8e06f96764c869d2f753daf477fb27d50b
1 /*
2 * ion/regbind.c
4 * Copyright (c) Tuomo Valkonen 1999-2009.
6 * See the included file LICENSE for details.
7 */
9 #include <string.h>
10 #include <libtu/objp.h>
11 #include <libmainloop/defer.h>
12 #include "common.h"
13 #include "region.h"
14 #include "binding.h"
15 #include "regbind.h"
18 /*{{{ Grab/ungrab */
21 static void do_binding_grab_on_ungrab_on(const WRegion *reg,
22 const WBinding *binding,
23 const WBindmap *bindmap, bool grab)
25 Window win=region_xwindow(reg);
26 WRegBindingInfo *r;
28 for(r=reg->bindings; r!=NULL; r=r->next){
29 if(r->bindmap==bindmap)
30 continue;
31 if(bindmap_lookup_binding(r->bindmap, binding->act, binding->state,
32 binding->kcb)!=NULL)
33 break;
35 if(r==NULL && binding->area==0){
36 if(grab)
37 binding_grab_on(binding, win);
38 else
39 binding_ungrab_on(binding, win);
44 static void do_binding_grab_on_ungrab_ons(const WRegion *reg,
45 const WBindmap *bindmap,
46 bool grab)
48 Rb_node node=NULL;
49 WBinding *binding=NULL;
51 if(!(reg->flags&REGION_BINDINGS_ARE_GRABBED) ||
52 bindmap->bindings==NULL){
53 return;
56 FOR_ALL_BINDINGS(binding, node, bindmap->bindings){
57 do_binding_grab_on_ungrab_on(reg, binding, bindmap, grab);
62 static void grab_ungrabbed_bindings(const WRegion *reg, const WBindmap *bindmap)
64 do_binding_grab_on_ungrab_ons(reg, bindmap, TRUE);
68 static void ungrab_freed_bindings(const WRegion *reg, const WBindmap *bindmap)
70 do_binding_grab_on_ungrab_ons(reg, bindmap, FALSE);
74 void rbind_binding_added(const WRegBindingInfo *rbind,
75 const WBinding *binding,
76 const WBindmap *UNUSED(bindmap))
78 if(binding->area==0 && rbind->reg->flags&REGION_BINDINGS_ARE_GRABBED)
79 do_binding_grab_on_ungrab_on(rbind->reg, binding, rbind->bindmap, TRUE);
83 void rbind_binding_removed(const WRegBindingInfo *rbind,
84 const WBinding *binding,
85 const WBindmap *UNUSED(bindmap))
87 if(binding->area==0 && rbind->reg->flags&REGION_BINDINGS_ARE_GRABBED)
88 do_binding_grab_on_ungrab_on(rbind->reg, binding, rbind->bindmap, FALSE);
92 /*}}}*/
95 /*{{{ Find */
98 static WRegBindingInfo *find_rbind(WRegion *reg, WBindmap *bindmap,
99 WRegion *owner)
101 WRegBindingInfo *rbind;
103 for(rbind=(WRegBindingInfo*)reg->bindings; rbind!=NULL; rbind=rbind->next){
104 if(rbind->bindmap==bindmap && rbind->owner==owner)
105 return rbind;
108 return NULL;
112 /*}}}*/
115 /*{{{ Interface */
118 static WRegBindingInfo *region_do_add_bindmap_owned(WRegion *reg,
119 WBindmap *bindmap,
120 WRegion *owner,
121 bool first)
123 WRegBindingInfo *rbind;
125 if(bindmap==NULL)
126 return NULL;
128 rbind=ALLOC(WRegBindingInfo);
130 if(rbind==NULL)
131 return NULL;
133 rbind->bindmap=bindmap;
134 rbind->owner=owner;
135 rbind->reg=reg;
136 rbind->tmp=0;
138 LINK_ITEM(bindmap->rbind_list, rbind, bm_next, bm_prev);
140 if(region_xwindow(reg)!=None && !(reg->flags&REGION_GRAB_ON_PARENT))
141 grab_ungrabbed_bindings(reg, bindmap);
143 /* Link to reg's rbind list*/ {
144 WRegBindingInfo *b=reg->bindings;
145 if(first){
146 LINK_ITEM_FIRST(b, rbind, next, prev);
147 }else{
148 LINK_ITEM_LAST(b, rbind, next, prev);
150 reg->bindings=b;
153 return rbind;
157 bool region_add_bindmap(WRegion *reg, WBindmap *bindmap)
159 if(find_rbind(reg, bindmap, NULL)!=NULL)
160 return FALSE;
161 return (region_do_add_bindmap_owned(reg, bindmap, NULL, TRUE)!=NULL);
165 static void remove_rbind(WRegion *reg, WRegBindingInfo *rbind)
167 UNLINK_ITEM(rbind->bindmap->rbind_list, rbind, bm_next, bm_prev);
169 /* Unlink from reg's rbind list*/ {
170 WRegBindingInfo *b=reg->bindings;
171 UNLINK_ITEM(b, rbind, next, prev);
172 reg->bindings=b;
175 if(region_xwindow(reg)!=None && !(reg->flags&REGION_GRAB_ON_PARENT))
176 ungrab_freed_bindings(reg, rbind->bindmap);
178 free(rbind);
182 void region_remove_bindmap(WRegion *reg, WBindmap *bindmap)
184 WRegBindingInfo *rbind=find_rbind(reg, bindmap, NULL);
185 if(rbind!=NULL)
186 remove_rbind(reg, rbind);
190 void region_remove_bindings(WRegion *reg)
192 WRegBindingInfo *rbind;
194 while((rbind=(WRegBindingInfo*)reg->bindings)!=NULL)
195 remove_rbind(reg, rbind);
199 WBinding *region_lookup_keybinding(WRegion *reg,
200 int act, uint state, uint kcb,
201 const WSubmapState *sc,
202 WRegion **binding_owner_ret)
204 WRegBindingInfo *rbind=NULL;
205 WBinding *binding=NULL;
206 const WSubmapState *s=NULL;
207 WBindmap *bindmap=NULL;
209 *binding_owner_ret=reg;
211 for(rbind=(WRegBindingInfo*)reg->bindings; rbind!=NULL; rbind=rbind->next){
212 bindmap=rbind->bindmap;
214 for(s=sc; s!=NULL && bindmap!=NULL; s=s->next){
215 binding=bindmap_lookup_binding(bindmap, BINDING_KEYPRESS, s->state, s->key);
217 if(binding==NULL){
218 bindmap=NULL;
219 break;
222 bindmap=binding->submap;
225 if(bindmap==NULL){
226 /* There may be no next iteration so we must reset binding here
227 * because we have not found a proper binding.
229 binding=NULL;
230 continue;
233 binding=bindmap_lookup_binding(bindmap, act, state, kcb);
235 if(binding!=NULL)
236 break;
239 if(binding!=NULL && rbind->owner!=NULL)
240 *binding_owner_ret=rbind->owner;
242 return binding;
246 WBinding *region_lookup_binding(WRegion *reg, int act, uint state,
247 uint kcb, int area)
249 WRegBindingInfo *rbind;
250 WBinding *binding=NULL;
252 for(rbind=(WRegBindingInfo*)reg->bindings; rbind!=NULL; rbind=rbind->next){
253 if(rbind->owner!=NULL)
254 continue;
255 binding=bindmap_lookup_binding_area(rbind->bindmap, act, state, kcb, area);
256 if(binding!=NULL)
257 break;
260 return binding;
264 /*}}}*/
267 /*{{{ Update */
270 static void add_bindings(WRegion *reg, WRegion *r2)
272 WRegion *rx=REGION_MANAGER(r2);
273 WRegBindingInfo *rbind, *rb2;
275 if(rx!=NULL && REGION_PARENT_REG(rx)==reg){
276 /* The recursion is here to get the bindmaps correctly ordered. */
277 add_bindings(reg, rx);
280 if(r2->flags&REGION_GRAB_ON_PARENT){
281 for(rb2=(WRegBindingInfo*)r2->bindings; rb2!=NULL; rb2=rb2->next){
282 rbind=find_rbind(reg, rb2->bindmap, r2);
283 if(rbind==NULL){
284 rbind=region_do_add_bindmap_owned(reg, rb2->bindmap,
285 r2, TRUE);
287 if(rbind!=NULL)
288 rbind->tmp=1;
294 void region_do_update_owned_grabs(WRegion *reg)
296 WRegBindingInfo *rbind, *rb2;
298 reg->flags&=~REGION_BINDING_UPDATE_SCHEDULED;
300 /* clear flags */
301 for(rbind=(WRegBindingInfo*)reg->bindings; rbind!=NULL; rbind=rbind->next)
302 rbind->tmp=0;
304 /* make new grabs */
305 if(reg->active_sub!=NULL)
306 add_bindings(reg, reg->active_sub);
308 /* remove old grabs */
309 for(rbind=(WRegBindingInfo*)reg->bindings; rbind!=NULL; rbind=rb2){
310 rb2=rbind->next;
311 if(rbind->tmp!=1 && rbind->owner!=NULL)
312 remove_rbind(reg, rbind);
316 void region_update_owned_grabs(WRegion *reg)
318 if(reg->flags&REGION_BINDING_UPDATE_SCHEDULED
319 || OBJ_IS_BEING_DESTROYED(reg)
320 || ioncore_g.opmode==IONCORE_OPMODE_DEINIT){
321 return;
324 if(mainloop_defer_action((Obj*)reg,
325 (WDeferredAction*)region_do_update_owned_grabs)){
326 reg->flags|=REGION_BINDING_UPDATE_SCHEDULED;
327 }else{
328 region_do_update_owned_grabs(reg);
333 /*}}}*/