2 /* This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 /* ---------------------------- included header files ---------------------- */
20 #define FEVENT_PRIVILEGED_ACCESS
22 #include "libs/fvwmlib.h"
26 #undef FEVENT_PRIVILEGED_ACCESS
30 #include "libs/ftime.h"
32 /* ---------------------------- local definitions -------------------------- */
34 /* ---------------------------- local macros ------------------------------- */
36 /* ---------------------------- imports ------------------------------------ */
38 /* ---------------------------- included code files ------------------------ */
40 /* ---------------------------- local types -------------------------------- */
44 Bool (*predicate
) (Display
*display
, XEvent
*event
, XPointer arg
);
48 } fev_check_peek_args
;
50 /* ---------------------------- forward declarations ----------------------- */
52 /* ---------------------------- local variables ---------------------------- */
54 static XEvent fev_event
;
55 static XEvent fev_event_old
;
56 /* until Xlib does this for us */
57 Time fev_last_timestamp
= CurrentTime
;
59 /* ---------------------------- exported variables (globals) --------------- */
61 /* ---------------------------- local functions ---------------------------- */
63 /* Records the time of the last processed event. */
64 static void fev_update_last_timestamp(const XEvent
*ev
)
66 Time new_timestamp
= CurrentTime
;
72 new_timestamp
= ev
->xkey
.time
;
76 new_timestamp
= ev
->xbutton
.time
;
79 new_timestamp
= ev
->xmotion
.time
;
83 new_timestamp
= ev
->xcrossing
.time
;
86 new_timestamp
= ev
->xproperty
.time
;
89 new_timestamp
= ev
->xselectionclear
.time
;
91 case SelectionRequest
:
92 new_timestamp
= ev
->xselectionrequest
.time
;
95 new_timestamp
= ev
->xselection
.time
;
100 /* Only update if the new timestamp is later than the old one, or
101 * if the new one is from a time at least 30 seconds earlier than the
102 * old one (in which case the system clock may have changed) */
103 if (new_timestamp
> fev_last_timestamp
||
104 fev_last_timestamp
- new_timestamp
> CLOCK_SKEW_MS
)
106 fev_last_timestamp
= new_timestamp
;
112 static Bool
fev_check_peek_pred(
113 Display
*display
, XEvent
*event
, XPointer arg
)
115 fev_check_peek_args
*cpa
= (fev_check_peek_args
*)arg
;
117 if (cpa
->found
== True
)
121 cpa
->found
= cpa
->predicate(display
, event
, cpa
->arg
);
122 if (cpa
->found
== True
)
130 /* ---------------------------- interface functions (privileged access) ----- */
132 void fev_copy_last_event(XEvent
*dest
)
139 XEvent
*fev_get_last_event_address(void)
144 /* ---------------------------- interface functions (normal_access) -------- */
146 Time
fev_get_evtime(void)
148 return fev_last_timestamp
;
151 Bool
fev_get_evpos_or_query(
152 Display
*dpy
, Window w
, const XEvent
*e
, int *ret_x
, int *ret_y
)
160 type
= (e
!= NULL
) ? e
->type
: -1;
165 *ret_x
= e
->xbutton
.x_root
;
166 *ret_y
= e
->xbutton
.y_root
;
170 *ret_x
= e
->xkey
.x_root
;
171 *ret_y
= e
->xkey
.y_root
;
175 *ret_x
= e
->xcrossing
.x_root
;
176 *ret_y
= e
->xcrossing
.y_root
;
179 if (e
->xmotion
.same_screen
== True
)
181 *ret_x
= e
->xmotion
.x_root
;
182 *ret_y
= e
->xmotion
.y_root
;
186 /* pointer is on different screen */
193 dpy
, w
, &JunkW
, &JunkW
, ret_x
, ret_y
, &JunkC
, &JunkC
,
197 /* pointer is on a different screen */
205 Bool
fev_set_evpos(XEvent
*e
, int x
, int y
)
211 e
->xbutton
.x_root
= x
;
212 e
->xbutton
.y_root
= y
;
220 if (e
->xmotion
.same_screen
== True
)
222 e
->xmotion
.x_root
= x
;
223 e
->xmotion
.y_root
= y
;
234 void fev_fake_event(XEvent
*ev
)
236 fev_event_old
= fev_event
;
238 /* don't update the last timestamp here; the triggering event has
239 * already done this */
244 void *fev_save_event(void)
248 ev
= (XEvent
*)safemalloc(sizeof(XEvent
));
254 void fev_restore_event(void *ev
)
256 fev_event
= *(XEvent
*)ev
;
262 void fev_make_null_event(XEvent
*ev
, Display
*dpy
)
264 memset(ev
, 0, sizeof(*ev
));
265 ev
->xany
.serial
= fev_event
.xany
.serial
;
266 ev
->xany
.display
= dpy
;
271 void fev_get_last_event(XEvent
*ev
)
278 /* ---------------------------- X event replacements ----------------------- */
280 XTimeCoord
*FGetMotionEvents(
281 Display
*display
, Window w
, Time start
, Time stop
, int *nevents_return
)
285 rc
= XGetMotionEvents(display
, w
, start
, stop
, nevents_return
);
291 Display
*display
, int event_mode
, Time time
)
295 rc
= XAllowEvents(display
, event_mode
, time
);
301 Display
*display
, XEvent
*event_return
,
302 Bool (*predicate
) (Display
*display
, XEvent
*event
, XPointer arg
),
308 rc
= XCheckIfEvent(display
, &new_ev
, predicate
, arg
);
311 fev_event_old
= fev_event
;
313 *event_return
= fev_event
;
314 fev_update_last_timestamp(event_return
);
320 Bool
FCheckMaskEvent(
321 Display
*display
, long event_mask
, XEvent
*event_return
)
326 rc
= XCheckMaskEvent(display
, event_mask
, &new_ev
);
329 fev_event_old
= fev_event
;
331 *event_return
= fev_event
;
332 fev_update_last_timestamp(event_return
);
338 Bool
FCheckPeekIfEvent(
339 Display
*display
, XEvent
*event_return
,
340 Bool (*predicate
) (Display
*display
, XEvent
*event
, XPointer arg
),
344 fev_check_peek_args cpa
;
346 cpa
.predicate
= predicate
;
349 XCheckIfEvent(display
, &dummy
, fev_check_peek_pred
, (char *)&cpa
);
350 if (cpa
.found
== True
)
352 *event_return
= cpa
.event
;
353 fev_update_last_timestamp(event_return
);
359 Bool
FCheckTypedEvent(
360 Display
*display
, int event_type
, XEvent
*event_return
)
365 rc
= XCheckTypedEvent(display
, event_type
, &new_ev
);
368 fev_event_old
= fev_event
;
370 *event_return
= fev_event
;
371 fev_update_last_timestamp(event_return
);
377 Bool
FCheckTypedWindowEvent(
378 Display
*display
, Window w
, int event_type
, XEvent
*event_return
)
383 rc
= XCheckTypedWindowEvent(display
, w
, event_type
, &new_ev
);
386 fev_event_old
= fev_event
;
388 *event_return
= fev_event
;
389 fev_update_last_timestamp(event_return
);
395 Bool
FCheckWindowEvent(
396 Display
*display
, Window w
, long event_mask
, XEvent
*event_return
)
401 rc
= XCheckWindowEvent(display
, w
, event_mask
, &new_ev
);
404 fev_event_old
= fev_event
;
406 *event_return
= fev_event
;
407 fev_update_last_timestamp(event_return
);
414 Display
*display
, int mode
)
418 rc
= XEventsQueued(display
, mode
);
424 Display
*display
, XEvent
*event_return
,
425 Bool (*predicate
) (Display
*display
, XEvent
*event
, XPointer arg
),
430 fev_event_old
= fev_event
;
431 rc
= XIfEvent(display
, &fev_event
, predicate
, arg
);
432 *event_return
= fev_event
;
433 fev_update_last_timestamp(event_return
);
439 Display
*display
, long event_mask
, XEvent
*event_return
)
443 fev_event_old
= fev_event
;
444 rc
= XMaskEvent(display
, event_mask
, &fev_event
);
445 *event_return
= fev_event
;
446 fev_update_last_timestamp(event_return
);
452 Display
*display
, XEvent
*event_return
)
456 fev_event_old
= fev_event
;
457 rc
= XNextEvent(display
, &fev_event
);
458 *event_return
= fev_event
;
459 fev_update_last_timestamp(event_return
);
465 Display
*display
, XEvent
*event_return
)
469 rc
= XPeekEvent(display
, event_return
);
472 fev_update_last_timestamp(event_return
);
479 Display
*display
, XEvent
*event_return
,
480 Bool (*predicate
) (Display
*display
, XEvent
*event
, XPointer arg
),
485 rc
= XPeekIfEvent(display
, event_return
, predicate
, arg
);
488 fev_update_last_timestamp(event_return
);
499 rc
= XPending(display
);
505 Display
*display
, XEvent
*event
)
509 rc
= XPutBackEvent(display
, event
);
510 fev_event
= fev_event_old
;
520 rc
= XQLength(display
);
526 Display
*display
, Window w
, Window
*root_return
, Window
*child_return
,
527 int *root_x_return
, int *root_y_return
, int *win_x_return
,
528 int *win_y_return
, unsigned int *mask_return
)
533 display
, w
, root_return
, child_return
, root_x_return
,
534 root_y_return
, win_x_return
, win_y_return
, mask_return
);
540 Display
*display
, Window w
, Bool propagate
, long event_mask
,
545 rc
= XSendEvent(display
, w
, propagate
, event_mask
, event_send
);
551 Display
*display
, Window src_w
, Window dest_w
, int src_x
, int src_y
,
552 unsigned int src_width
, unsigned int src_height
, int dest_x
, int dest_y
)
557 display
, src_w
, dest_w
, src_x
, src_y
, src_width
, src_height
,
563 int FWarpPointerUpdateEvpos(
564 XEvent
*ev
, Display
*display
, Window src_w
, Window dest_w
, int src_x
,
565 int src_y
, unsigned int src_width
, unsigned int src_height
,
566 int dest_x
, int dest_y
)
571 display
, src_w
, dest_w
, src_x
, src_y
, src_width
, src_height
,
573 if (ev
!= NULL
&& dest_w
== DefaultRootWindow(display
))
575 fev_set_evpos(ev
, dest_x
, dest_y
);
582 Display
*display
, Window w
, long event_mask
, XEvent
*event_return
)
586 fev_event_old
= fev_event
;
587 rc
= XWindowEvent(display
, w
, event_mask
, &fev_event
);
588 *event_return
= fev_event
;
589 fev_update_last_timestamp(event_return
);