4 * Copyright (c) Tuomo Valkonen 1999-2007.
6 * See the included file LICENSE for details.
10 #include <libtu/objp.h>
11 #include <libmainloop/defer.h>
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);
28 for(r=reg->bindings; r!=NULL; r=r->next){
29 if(r->bindmap==bindmap)
31 if(bindmap_lookup_binding(r->bindmap, binding->act, binding->state,
35 if(r==NULL && binding->area==0){
37 binding_grab_on(binding, win);
39 binding_ungrab_on(binding, win);
44 static void do_binding_grab_on_ungrab_ons(const WRegion *reg,
45 const WBindmap *bindmap,
49 WBinding *binding=NULL;
51 if(!(reg->flags®ION_BINDINGS_ARE_GRABBED) ||
52 bindmap->bindings==NULL){
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 *bindmap)
78 if(binding->area==0 && rbind->reg->flags®ION_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 *bindmap)
87 if(binding->area==0 && rbind->reg->flags®ION_BINDINGS_ARE_GRABBED)
88 do_binding_grab_on_ungrab_on(rbind->reg, binding, rbind->bindmap, FALSE);
98 static WRegBindingInfo *find_rbind(WRegion *reg, WBindmap *bindmap,
101 WRegBindingInfo *rbind;
103 for(rbind=(WRegBindingInfo*)reg->bindings; rbind!=NULL; rbind=rbind->next){
104 if(rbind->bindmap==bindmap && rbind->owner==owner)
118 static WRegBindingInfo *region_do_add_bindmap_owned(WRegion *reg,
123 WRegBindingInfo *rbind;
128 rbind=ALLOC(WRegBindingInfo);
133 rbind->bindmap=bindmap;
138 LINK_ITEM(bindmap->rbind_list, rbind, bm_next, bm_prev);
140 if(region_xwindow(reg)!=None && !(reg->flags®ION_GRAB_ON_PARENT))
141 grab_ungrabbed_bindings(reg, bindmap);
143 /* Link to reg's rbind list*/ {
144 WRegBindingInfo *b=reg->bindings;
146 LINK_ITEM_FIRST(b, rbind, next, prev);
148 LINK_ITEM_LAST(b, rbind, next, prev);
157 bool region_add_bindmap(WRegion *reg, WBindmap *bindmap)
159 if(find_rbind(reg, bindmap, NULL)!=NULL)
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);
175 if(region_xwindow(reg)!=None && !(reg->flags®ION_GRAB_ON_PARENT))
176 ungrab_freed_bindings(reg, rbind->bindmap);
182 void region_remove_bindmap(WRegion *reg, WBindmap *bindmap)
184 WRegBindingInfo *rbind=find_rbind(reg, bindmap, 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;
210 *binding_owner_ret=reg;
212 for(rbind=(WRegBindingInfo*)reg->bindings; rbind!=NULL; rbind=rbind->next){
213 bindmap=rbind->bindmap;
215 for(s=sc; s!=NULL && bindmap!=NULL; s=s->next){
216 binding=bindmap_lookup_binding(bindmap, BINDING_KEYPRESS, s->state, s->key);
223 bindmap=binding->submap;
227 /* There may be no next iteration so we must reset binding here
228 * because we have not found a proper binding.
234 binding=bindmap_lookup_binding(bindmap, act, state, kcb);
240 if(binding!=NULL && rbind->owner!=NULL)
241 *binding_owner_ret=rbind->owner;
247 WBinding *region_lookup_binding(WRegion *reg, int act, uint state,
250 WRegBindingInfo *rbind;
251 WBinding *binding=NULL;
253 for(rbind=(WRegBindingInfo*)reg->bindings; rbind!=NULL; rbind=rbind->next){
254 if(rbind->owner!=NULL)
256 binding=bindmap_lookup_binding_area(rbind->bindmap, act, state, kcb, area);
271 static void add_bindings(WRegion *reg, WRegion *r2)
273 WRegion *rx=REGION_MANAGER(r2);
274 WRegBindingInfo *rbind, *rb2;
275 WBinding *binding=NULL;
277 if(rx!=NULL && REGION_PARENT_REG(rx)==reg){
278 /* The recursion is here to get the bindmaps correctly ordered. */
279 add_bindings(reg, rx);
282 if(r2->flags®ION_GRAB_ON_PARENT){
283 for(rb2=(WRegBindingInfo*)r2->bindings; rb2!=NULL; rb2=rb2->next){
284 rbind=find_rbind(reg, rb2->bindmap, r2);
286 rbind=region_do_add_bindmap_owned(reg, rb2->bindmap,
296 void region_do_update_owned_grabs(WRegion *reg)
298 WRegBindingInfo *rbind, *rb2;
300 reg->flags&=~REGION_BINDING_UPDATE_SCHEDULED;
303 for(rbind=(WRegBindingInfo*)reg->bindings; rbind!=NULL; rbind=rbind->next)
307 if(reg->active_sub!=NULL)
308 add_bindings(reg, reg->active_sub);
310 /* remove old grabs */
311 for(rbind=(WRegBindingInfo*)reg->bindings; rbind!=NULL; rbind=rb2){
313 if(rbind->tmp!=1 && rbind->owner!=NULL)
314 remove_rbind(reg, rbind);
318 void region_update_owned_grabs(WRegion *reg)
320 if(reg->flags®ION_BINDING_UPDATE_SCHEDULED
321 || OBJ_IS_BEING_DESTROYED(reg)
322 || ioncore_g.opmode==IONCORE_OPMODE_DEINIT){
326 if(mainloop_defer_action((Obj*)reg,
327 (WDeferredAction*)region_do_update_owned_grabs)){
328 reg->flags|=REGION_BINDING_UPDATE_SCHEDULED;
330 region_do_update_owned_grabs(reg);