2 * ion/ioncore/pointer.c
4 * Copyright (c) Tuomo Valkonen 1999-2007.
6 * See the included file LICENSE for details.
23 static uint p_button=0, p_state=0;
24 static int p_x=-1, p_y=-1;
25 static int p_orig_x=-1, p_orig_y=-1;
26 static bool p_motion=FALSE;
27 static int p_clickcnt=0;
30 static enum{ST_NO, ST_INIT, ST_HELD} p_grabstate=ST_NO;
32 static WButtonHandler *p_motion_end_handler=NULL;
33 static WMotionHandler *p_motion_handler=NULL;
34 static WMotionHandler *p_motion_begin_handler=NULL;
35 static GrabHandler *p_key_handler=NULL;
36 static GrabKilledHandler *p_killed_handler=NULL;
38 static Watch p_regwatch=WATCH_INIT, p_subregwatch=WATCH_INIT;
40 #define p_reg ((WRegion*)p_regwatch.obj)
41 #define p_subreg ((WRegion*)p_subregwatch.obj)
47 /*{{{ Handler setup */
50 bool ioncore_set_drag_handlers(WRegion *reg,
51 WMotionHandler *begin,
52 WMotionHandler *motion,
54 GrabHandler *keypress,
55 GrabKilledHandler *killed)
57 if(ioncore_pointer_grab_region()==NULL || p_motion)
60 /* A motion handler set at this point may not set a begin handler */
61 if(p_grabstate!=ST_HELD && begin!=NULL)
65 watch_setup(&p_regwatch, (Obj*)reg, NULL);
66 watch_reset(&p_subregwatch);
69 p_motion_begin_handler=begin;
70 p_motion_handler=motion;
71 p_motion_end_handler=end;
72 p_key_handler=keypress;
73 p_killed_handler=killed;
86 static bool time_in_threshold(Time time)
95 return t<ioncore_g.dblclick_delay;
99 static bool motion_in_threshold(int x, int y)
101 return (x>p_x-CF_DRAG_TRESHOLD && x<p_x+CF_DRAG_TRESHOLD &&
102 y>p_y-CF_DRAG_TRESHOLD && y<p_y+CF_DRAG_TRESHOLD);
106 WRegion *ioncore_pointer_grab_region()
108 if(p_grabstate==ST_NO)
117 /*{{{ Call handlers */
120 static XEvent *p_curr_event=NULL;
123 XEvent *ioncore_current_pointer_event()
129 static void call_button(WBinding *binding, XButtonEvent *ev)
136 p_curr_event=(XEvent*)ev;
137 extl_call(binding->func, "ooo", NULL, p_reg, p_subreg,
138 (p_reg!=NULL ? p_reg->active_sub : NULL));
143 static void call_motion(XMotionEvent *ev, int dx, int dy)
145 if(p_motion_handler!=NULL && p_reg!=NULL){
146 p_curr_event=(XEvent*)ev;
147 p_motion_handler(p_reg, ev, dx, dy);
153 static void call_motion_end(XButtonEvent *ev)
155 if(p_motion_end_handler!=NULL && p_reg!=NULL){
156 p_curr_event=(XEvent*)ev;
157 p_motion_end_handler(p_reg, ev);
163 static void call_motion_begin(WBinding *binding, XMotionEvent *ev,
171 p_curr_event=(XEvent*)ev;
173 extl_call(binding->func, "oo", NULL, p_reg, p_subreg);
175 if(p_motion_begin_handler!=NULL && p_reg!=NULL)
176 p_motion_begin_handler(p_reg, ev, dx, dy);
178 p_motion_begin_handler=NULL;
187 /*{{{ ioncore_handle_button_press/release/motion */
190 static void finish_pointer()
193 window_release((WWindow*)p_reg);
195 watch_reset(&p_subregwatch);
199 static bool handle_key(WRegion *reg, XEvent *ev)
201 if(p_key_handler!=NULL){
202 if(p_key_handler(reg, ev)){
211 static void pointer_grab_killed(WRegion *unused)
213 if(p_reg!=NULL && p_killed_handler!=NULL)
214 p_killed_handler(p_reg);
215 watch_reset(&p_regwatch);
220 bool ioncore_do_handle_buttonpress(XButtonEvent *ev)
222 WBinding *pressbind=NULL;
224 WRegion *subreg=NULL;
231 reg=(WRegion*)XWINDOW_REGION_OF_T(ev->window, WWindow);
236 dblclick=(p_clickcnt==1 && time_in_threshold(ev->time) &&
237 p_button==button && p_state==state && reg==p_reg);
240 p_motion_begin_handler=NULL;
241 p_motion_handler=NULL;
242 p_motion_end_handler=NULL;
244 p_killed_handler=NULL;
248 p_orig_x=p_x=ev->x_root;
249 p_orig_y=p_y=ev->y_root;
253 watch_setup(&p_regwatch, (Obj*)reg, NULL);
255 subreg=region_current(reg);
256 p_area=window_press((WWindow*)reg, ev, &subreg);
258 watch_setup(&p_subregwatch, (Obj*)subreg, NULL);
261 pressbind=region_lookup_binding(reg, BINDING_BUTTONDBLCLICK, state,
266 pressbind=region_lookup_binding(reg, BINDING_BUTTONPRESS, state,
270 ioncore_grab_establish(reg, handle_key, pointer_grab_killed, 0);
273 call_button(pressbind, ev);
279 bool ioncore_do_handle_buttonrelease(XButtonEvent *ev)
281 WBinding *binding=NULL;
283 if(p_button!=ev->button)
289 binding=region_lookup_binding(p_reg, BINDING_BUTTONCLICK,
290 p_state, p_button, p_area);
291 call_button(binding, ev);
298 ioncore_grab_remove(handle_key);
305 void ioncore_do_handle_motionnotify(XMotionEvent *ev)
308 WBinding *binding=NULL;
314 if(motion_in_threshold(ev->x_root, ev->y_root))
316 binding=region_lookup_binding(p_reg, BINDING_BUTTONMOTION,
317 p_state, p_button, p_area);
327 call_motion_begin(binding, ev, dx, dy);
330 call_motion(ev, dx, dy);