4 * Copyright (c) Tuomo Valkonen 1999-2001.
5 * See the included file LICENSE for details.
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;
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
;
48 /*void get_pointer_rootpos(Window rootwin, int *xret, int *yret)
54 XQueryPointer(wglobal.dpy, rootwin, &root, &win,
55 xret, yret, &wx, &wy, &mask);
59 static bool time_in_treshold(Time 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
)
83 if(!XTranslateCoordinates(wglobal
.dpy
, rootwin
, rootwin
,
84 x
, y
, &dstx
, &dsty
, childret
))
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
);
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
)
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
;
131 call_binding(binding
, wglobal
.grab_holder
);
135 thing
=find_parent(wglobal
.grab_holder
, binding
->func
->objdescr
);
141 static void call_motion(WBinding
*binding
, XMotionEvent
*ev
, int dx
, int dy
)
149 if(binding
->func
->callhnd
!=callhnd_drag_void
){
150 call_binding(binding
, wglobal
.grab_holder
);
154 fn
=((WDragHandler
*)binding
->func
->fn
)->motion
;
155 thing
=find_parent(wglobal
.grab_holder
, binding
->func
->objdescr
);
157 fn(thing
, ev
, dx
, dy
);
167 static int get_quadrant(int x
, int y
, int w
, int h
)
171 a
=2*(y
>(h
-x
*h
/w
)); /* 00/
175 b
=(y
>(x
*h
/w
)); /* \00
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;
193 qd
=get_quadrant(ev
->x
, ev
->y
, FRAME_W(frame
), FRAME_H(frame
));
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);
211 tw
=frame
->tab_w
+scr
->grdata
.spacing
;
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
);
220 client
=NEXT_THING(client
, WClient
);
224 *thing
=(WThing
*)client
;
226 return &(wglobal
.tab_bindmap
);
228 return &(wglobal
.main_bindmap
);
235 /*{{{ handle_button_press/release/motion */
238 bool handle_button_press(XButtonEvent
*ev
)
240 WBinding
*pressbind
=NULL
;
243 WBindmap
*bindmap
=NULL
;
252 thing
=FIND_WINDOW_T(ev
->window
, WThing
);
256 }else if(WTHING_IS(thing
, WClientWin
)){
258 bindmap
=&(wglobal
.main_bindmap
);
259 }else if(WTHING_IS(thing
, WFrame
)){
261 bindmap
=frame_press((WFrame
*)thing
, ev
, &thing
);
262 }else if(WTHING_IS(thing
, WInput
)){
264 bindmap
=&(wglobal
.input_bindmap
);
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
);
278 pressbind
=lookup_binding(bindmap
, ACT_BUTTONPRESS
, state
, button
);
286 p_orig_x
=p_x
=ev
->x_root
;
287 p_orig_y
=p_y
=ev
->y_root
;
291 p_motiontmp_dirty
=TRUE
;
292 p_screen
=SCREEN_OF(thing
);
294 call_button(pressbind
, ev
);
300 bool handle_button_release(XButtonEvent
*ev
)
302 WBinding
*binding
=NULL
;
304 if(p_button
!=ev
->button
)
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
);
316 call_button(binding
, ev
);
322 void handle_pointer_motion(XMotionEvent
*ev
)
327 if(p_motion
==FALSE
&& motion_in_treshold(ev
->x_root
, ev
->y_root
))
330 if(p_motiontmp_dirty
){
331 p_motiontmp
=lookup_binding(p_bindmap
, ACT_BUTTONMOTION
, p_state
, p_button
);
332 p_motiontmp_dirty
=FALSE
;
341 call_motion(p_motiontmp
, ev
, dx
, dy
);
353 static void p_tabdrag(WClient
*client
, XMotionEvent
*ev
, int dx
, int dy
)
355 WGRData
*grdata
=&(p_screen
->grdata
);
360 frame
=FIND_PARENT(client
, WFrame
);
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
);
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
;
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
);
400 draw_frame_bar(frame
, TRUE
);
402 /* Must be same screen */
403 if(ev
->root
!=p_screen
->root
.win
)
406 if(find_window_at(ev
->root
, ev
->x_root
, ev
->y_root
, &win
))
407 newframe
=find_frame_of(win
);
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
429 void p_resize(WFrame
*frame
, XMotionEvent
*ev
, int dx
, int dy
)
432 begin_resize((WWindow
*)frame
, p_dir
, p_primn
);
433 change_grab_cursor(CURSOR_RESIZE
);
439 if(p_primn
==TOP_OR_LEFT
)
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