4 * Copyright (c) Tuomo Valkonen 1999-2009.
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
);