Renamed package to ion1, and made it conflict with package 'ion'.
[ion1.git] / src / pointer.c
blobed914933649e47ec971f7bcd78c5f12328ccb173
1 /*
2 * ion/pointer.c
4 * Copyright (c) Tuomo Valkonen 1999-2001.
5 * See the included file LICENSE for details.
6 */
8 #include "common.h"
9 #include "pointer.h"
10 #include "frame.h"
11 #include "cursor.h"
12 #include "event.h"
13 #include "binding.h"
14 #include "global.h"
15 #include "client.h"
16 #include "draw.h"
17 #include "wedln.h"
18 #include "split.h"
19 #include "resize.h"
20 #include "focus.h"
21 #include "grab.h"
24 /*{{{ Variables */
27 static uint p_button=0, p_state=0;
28 static WBindmap *p_bindmap=NULL;
29 static int p_x=-1, p_y=-1;
30 static int p_orig_x=-1, p_orig_y=-1;
31 static bool p_motion=FALSE;
32 static int p_clickcnt=0;
33 static Time p_time=0;
34 static int p_tab_x, p_tab_y;
35 static bool p_motiontmp_dirty;
36 static WBinding *p_motiontmp=NULL;
37 static WThing *p_dbltmp=NULL;
38 static int p_dir, p_primn;
39 static WScreen *p_screen=NULL;
42 /*}}}*/
45 /*{{{ Misc. */
48 /*void get_pointer_rootpos(Window rootwin, int *xret, int *yret)
50 Window root, win;
51 int x, y, wx, wy;
52 uint mask;
54 XQueryPointer(wglobal.dpy, rootwin, &root, &win,
55 xret, yret, &wx, &wy, &mask);
56 }*/
59 static bool time_in_treshold(Time time)
61 Time t;
63 if(time<p_time)
64 t=p_time-time;
65 else
66 t=time-p_time;
68 return t<wglobal.dblclick_delay;
72 static bool motion_in_treshold(int x, int y)
74 return (x>p_x-CF_DRAG_TRESHOLD && x<p_x+CF_DRAG_TRESHOLD &&
75 y>p_y-CF_DRAG_TRESHOLD && y<p_y+CF_DRAG_TRESHOLD);
79 bool find_window_at(Window rootwin, int x, int y, Window *childret)
81 int dstx, dsty;
83 if(!XTranslateCoordinates(wglobal.dpy, rootwin, rootwin,
84 x, y, &dstx, &dsty, childret))
85 return FALSE;
87 if(*childret==None)
88 return FALSE;
90 return TRUE;
94 static bool inrect(WRectangle g, int x, int y)
96 return (x>=g.x && x<g.x+g.w && y>=g.y && y<g.y+g.h);
100 /*}}}*/
103 /*{{{ Call handlers */
106 void callhnd_button_void(WThing *thing, WFunction *func,
107 int n, const Token *args)
112 void callhnd_drag_void(WThing *thing, WFunction *func,
113 int n, const Token *args)
118 static void call_button(WBinding *binding, XButtonEvent *ev)
120 WButtonHandler *fn;
121 WThing *thing;
123 if(binding==NULL)
124 return;
126 if(binding->func->callhnd==callhnd_button_void){
127 fn=(WButtonHandler*)binding->func->fn;
128 }else if(binding->func->callhnd==callhnd_drag_void){
129 fn=((WDragHandler*)binding->func->fn)->release;
130 }else{
131 call_binding(binding, wglobal.grab_holder);
132 return;
135 thing=find_parent(wglobal.grab_holder, binding->func->objdescr);
136 if(thing!=NULL)
137 fn(thing, ev);
141 static void call_motion(WBinding *binding, XMotionEvent *ev, int dx, int dy)
143 WMotionHandler *fn;
144 WThing *thing;
146 if(binding==NULL)
147 return;
149 if(binding->func->callhnd!=callhnd_drag_void){
150 call_binding(binding, wglobal.grab_holder);
151 return;
154 fn=((WDragHandler*)binding->func->fn)->motion;
155 thing=find_parent(wglobal.grab_holder, binding->func->objdescr);
156 if(thing!=NULL)
157 fn(thing, ev, dx, dy);
161 /*}}}*/
164 /*{{{ Frame press */
167 static int get_quadrant(int x, int y, int w, int h)
169 int a, b;
171 a=2*(y>(h-x*h/w)); /* 00/
172 * 0/2
173 * /22 */
175 b=(y>(x*h/w)); /* \00
176 * 1\0
177 * 11\ */
179 return a+b;
182 static WBindmap *frame_press(WFrame *frame, XButtonEvent *ev, WThing **thing)
184 WScreen *scr=SCREEN_OF(frame);
185 int cw=CF_CORNER_SIZE, ch=CF_CORNER_SIZE;
186 int actx=-1, tabnum=-1;
187 bool ret;
188 WRectangle g;
189 int tw, x;
190 int qd, off;
191 WClient *client;
193 qd=get_quadrant(ev->x, ev->y, FRAME_W(frame), FRAME_H(frame));
195 if(qd==0 || qd==3)
196 p_dir=VERTICAL;
197 else
198 p_dir=HORIZONTAL;
200 if(qd==0 || qd==1)
201 p_primn=TOP_OR_LEFT;
202 else
203 p_primn=BOTTOM_OR_RIGHT;
205 frame_bar_geom(frame, &g);
207 if(inrect(g, ev->x, ev->y)){
208 off=((!scr->grdata.shortcut_corner && frame->shortcut!=0)
209 ? FRAME_SHORTCUT_W : 0);
210 x=ev->x-g.x-off;
211 tw=frame->tab_w+scr->grdata.spacing;
212 x/=tw;
213 p_tab_x=off+x*tw+g.x+FRAME_X(frame);
214 p_tab_y=FRAME_Y(frame)+g.y;
216 client=FIRST_THING(frame, WClient);
217 while(x--){
218 if(client==NULL)
219 break;
220 client=NEXT_THING(client, WClient);
223 if(client!=NULL)
224 *thing=(WThing*)client;
226 return &(wglobal.tab_bindmap);
228 return &(wglobal.main_bindmap);
232 /*}}}*/
235 /*{{{ handle_button_press/release/motion */
238 bool handle_button_press(XButtonEvent *ev)
240 WBinding *pressbind=NULL;
241 WThing *thing=NULL;
242 uint button, state;
243 WBindmap *bindmap=NULL;
245 p_motiontmp=NULL;
246 p_dir=VERTICAL;
247 p_primn=TOP_OR_LEFT;
249 state=ev->state;
250 button=ev->button;
252 thing=FIND_WINDOW_T(ev->window, WThing);
254 if(thing==NULL){
255 return FALSE;
256 }else if(WTHING_IS(thing, WClientWin)){
257 /* client */
258 bindmap=&(wglobal.main_bindmap);
259 }else if(WTHING_IS(thing, WFrame)){
260 /* frame */
261 bindmap=frame_press((WFrame*)thing, ev, &thing);
262 }else if(WTHING_IS(thing, WInput)){
263 /* input */
264 bindmap=&(wglobal.input_bindmap);
265 }else{
266 /* unknown */
267 return FALSE;
270 do_grab_kb_ptr(ev->root, thing, FocusChangeMask);
272 if(p_clickcnt==1 && time_in_treshold(ev->time) && p_button==button &&
273 p_state==state && thing==p_dbltmp && p_bindmap==bindmap){
274 pressbind=lookup_binding(bindmap, ACT_BUTTONDBLCLICK, state, button);
277 if(pressbind==NULL){
278 pressbind=lookup_binding(bindmap, ACT_BUTTONPRESS, state, button);
281 end:
282 p_dbltmp=thing;
283 p_bindmap=bindmap;
284 p_button=button;
285 p_state=state;
286 p_orig_x=p_x=ev->x_root;
287 p_orig_y=p_y=ev->y_root;
288 p_time=ev->time;
289 p_motion=FALSE;
290 p_clickcnt=0;
291 p_motiontmp_dirty=TRUE;
292 p_screen=SCREEN_OF(thing);
294 call_button(pressbind, ev);
296 return TRUE;
300 bool handle_button_release(XButtonEvent *ev)
302 WBinding *binding=NULL;
304 if(p_button!=ev->button)
305 return FALSE;
307 if(p_motion==FALSE){
308 p_clickcnt=1;
309 binding=lookup_binding(p_bindmap, ACT_BUTTONCLICK, p_state, p_button);
310 }else if(p_motiontmp_dirty){
311 binding=lookup_binding(p_bindmap, ACT_BUTTONMOTION, p_state, p_button);
312 }else{
313 binding=p_motiontmp;
316 call_button(binding, ev);
318 return TRUE;
322 void handle_pointer_motion(XMotionEvent *ev)
324 WThing *tmp;
325 int dx, dy;
327 if(p_motion==FALSE && motion_in_treshold(ev->x_root, ev->y_root))
328 return;
330 if(p_motiontmp_dirty){
331 p_motiontmp=lookup_binding(p_bindmap, ACT_BUTTONMOTION, p_state, p_button);
332 p_motiontmp_dirty=FALSE;
335 p_time=ev->time;
336 dx=ev->x_root-p_x;
337 dy=ev->y_root-p_y;
338 p_x=ev->x_root;
339 p_y=ev->y_root;
341 call_motion(p_motiontmp, ev, dx, dy);
343 p_motion=TRUE;
347 /*}}}*/
350 /*{{{ Tab drag */
353 static void p_tabdrag(WClient *client, XMotionEvent *ev, int dx, int dy)
355 WGRData *grdata=&(p_screen->grdata);
356 WFrame *frame;
357 int x, y;
359 if(p_motion==FALSE){
360 frame=FIND_PARENT(client, WFrame);
362 if(frame==NULL)
363 return;
365 change_grab_cursor(CURSOR_DRAG);
367 grdata->tabdrag_geom.w=frame->tab_w;
368 grdata->tabdrag_geom.h=grdata->bar_h;
369 XResizeWindow(wglobal.dpy, grdata->tabdrag_win,
370 frame->tab_w, grdata->bar_h);
371 XSelectInput(wglobal.dpy, grdata->tabdrag_win, ExposureMask);
373 client->flags|=CLIENT_DRAG;
374 draw_frame_bar(frame, FALSE);
377 x=p_tab_x+(p_x-p_orig_x);
378 y=p_tab_y+(p_y-p_orig_y);
380 XMoveWindow(wglobal.dpy, grdata->tabdrag_win, x, y);
382 if(p_motion==FALSE)
383 XMapRaised(wglobal.dpy, grdata->tabdrag_win);
387 static void p_tabdrag_end(WClient *client, XButtonEvent *ev)
389 WGRData *grdata=&(p_screen->grdata);
390 WFrame *frame, *newframe=NULL;
391 Window win;
393 XUnmapWindow(wglobal.dpy, grdata->tabdrag_win);
394 XSelectInput(wglobal.dpy, grdata->tabdrag_win, 0);
396 client->flags&=~CLIENT_DRAG;
398 frame=FIND_PARENT(client, WFrame);
399 if(frame!=NULL)
400 draw_frame_bar(frame, TRUE);
402 /* Must be same screen */
403 if(ev->root!=p_screen->root.win)
404 return;
406 if(find_window_at(ev->root, ev->x_root, ev->y_root, &win))
407 newframe=find_frame_of(win);
409 if(newframe==NULL)
410 return;
412 frame_attach_client(newframe, client, TRUE);
413 set_focus((WThing*)newframe);
417 WDragHandler p_tabdrag_handler={
418 (WMotionHandler*)p_tabdrag,
419 (WButtonHandler*)p_tabdrag_end
423 /*}}}*/
426 /*{{{ Resize */
429 void p_resize(WFrame *frame, XMotionEvent *ev, int dx, int dy)
431 if(p_motion==FALSE){
432 begin_resize((WWindow*)frame, p_dir, p_primn);
433 change_grab_cursor(CURSOR_RESIZE);
436 if(p_dir==VERTICAL)
437 dx=dy;
439 if(p_primn==TOP_OR_LEFT)
440 dx=-dx;
442 /*resize((WWindow*)frame, dx, p_dir, p_primn);*/
443 resize((WWindow*)frame, dx, p_primn, FALSE);
447 void p_resize_end(WFrame *frame, XButtonEvent *ev)
449 end_resize((WWindow*)frame);
453 WDragHandler p_resize_handler={
454 (WMotionHandler*)p_resize,
455 (WButtonHandler*)p_resize_end
459 /*}}}*/