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 if(ev->subwindow!=None){
237 XButtonEvent ev2=*ev;
238 ev2.window=ev->subwindow;
239 if(XTranslateCoordinates(ioncore_g.dpy, ev->window, ev2.window,
240 ev->x, ev->y, &(ev2.x), &(ev2.y),
242 if(ioncore_do_handle_buttonpress(&ev2))
247 dblclick=(p_clickcnt==1 && time_in_threshold(ev->time) &&
248 p_button==button && p_state==state && reg==p_reg);
251 p_motion_begin_handler=NULL;
252 p_motion_handler=NULL;
253 p_motion_end_handler=NULL;
255 p_killed_handler=NULL;
259 p_orig_x=p_x=ev->x_root;
260 p_orig_y=p_y=ev->y_root;
264 watch_setup(&p_regwatch, (Obj*)reg, NULL);
266 subreg=region_current(reg);
267 p_area=window_press((WWindow*)reg, ev, &subreg);
269 watch_setup(&p_subregwatch, (Obj*)subreg, NULL);
272 pressbind=region_lookup_binding(reg, BINDING_BUTTONDBLCLICK, state,
277 pressbind=region_lookup_binding(reg, BINDING_BUTTONPRESS, state,
281 ioncore_grab_establish(reg, handle_key, pointer_grab_killed, 0);
284 call_button(pressbind, ev);
290 bool ioncore_do_handle_buttonrelease(XButtonEvent *ev)
292 WBinding *binding=NULL;
294 if(p_button!=ev->button)
300 binding=region_lookup_binding(p_reg, BINDING_BUTTONCLICK,
301 p_state, p_button, p_area);
302 call_button(binding, ev);
309 ioncore_grab_remove(handle_key);
316 void ioncore_do_handle_motionnotify(XMotionEvent *ev)
319 WBinding *binding=NULL;
325 if(motion_in_threshold(ev->x_root, ev->y_root))
327 binding=region_lookup_binding(p_reg, BINDING_BUTTONMOTION,
328 p_state, p_button, p_area);
338 call_motion_begin(binding, ev, dx, dy);
341 call_motion(ev, dx, dy);