Apply window-jump fix (D. Fries).
[fvwm.git] / libs / FEvent.c
blobb0eda1dfcb1bfa98b53d657c38c06293743a0f65
1 /* -*-c-*- */
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 ---------------------- */
19 #define FEVENT_C
20 #define FEVENT_PRIVILEGED_ACCESS
21 #include "config.h"
22 #include "libs/fvwmlib.h"
23 #include <X11/Xlib.h>
24 #include "FEvent.h"
25 #undef FEVENT_C
26 #undef FEVENT_PRIVILEGED_ACCESS
28 #include <stdio.h>
30 #include "libs/ftime.h"
32 /* ---------------------------- local definitions -------------------------- */
34 /* ---------------------------- local macros ------------------------------- */
36 /* ---------------------------- imports ------------------------------------ */
38 /* ---------------------------- included code files ------------------------ */
40 /* ---------------------------- local types -------------------------------- */
42 typedef struct
44 Bool (*predicate) (Display *display, XEvent *event, XPointer arg);
45 XPointer arg;
46 XEvent event;
47 Bool found;
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;
68 switch (ev->type)
70 case KeyPress:
71 case KeyRelease:
72 new_timestamp = ev->xkey.time;
73 break;
74 case ButtonPress:
75 case ButtonRelease:
76 new_timestamp = ev->xbutton.time;
77 break;
78 case MotionNotify:
79 new_timestamp = ev->xmotion.time;
80 break;
81 case EnterNotify:
82 case LeaveNotify:
83 new_timestamp = ev->xcrossing.time;
84 break;
85 case PropertyNotify:
86 new_timestamp = ev->xproperty.time;
87 break;
88 case SelectionClear:
89 new_timestamp = ev->xselectionclear.time;
90 break;
91 case SelectionRequest:
92 new_timestamp = ev->xselectionrequest.time;
93 break;
94 case SelectionNotify:
95 new_timestamp = ev->xselection.time;
96 break;
97 default:
98 return;
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;
109 return;
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)
119 return False;
121 cpa->found = cpa->predicate(display, event, cpa->arg);
122 if (cpa->found == True)
124 cpa->event = *event;
127 return False;
130 /* ---------------------------- interface functions (privileged access) ----- */
132 void fev_copy_last_event(XEvent *dest)
134 *dest = fev_event;
136 return;
139 XEvent *fev_get_last_event_address(void)
141 return &fev_event;
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)
154 Window JunkW;
155 int JunkC;
156 unsigned int JunkM;
157 Bool rc;
158 int type;
160 type = (e != NULL) ? e->type : -1;
161 switch (type)
163 case ButtonPress:
164 case ButtonRelease:
165 *ret_x = e->xbutton.x_root;
166 *ret_y = e->xbutton.y_root;
167 return True;
168 case KeyPress:
169 case KeyRelease:
170 *ret_x = e->xkey.x_root;
171 *ret_y = e->xkey.y_root;
172 return True;
173 case EnterNotify:
174 case LeaveNotify:
175 *ret_x = e->xcrossing.x_root;
176 *ret_y = e->xcrossing.y_root;
177 return True;
178 case MotionNotify:
179 if (e->xmotion.same_screen == True)
181 *ret_x = e->xmotion.x_root;
182 *ret_y = e->xmotion.y_root;
184 else
186 /* pointer is on different screen */
187 *ret_x = 0;
188 *ret_y = 0;
190 return True;
191 default:
192 rc = FQueryPointer(
193 dpy, w, &JunkW, &JunkW, ret_x, ret_y, &JunkC, &JunkC,
194 &JunkM);
195 if (rc == False)
197 /* pointer is on a different screen */
198 *ret_x = 0;
199 *ret_y = 0;
201 return rc;
205 Bool fev_set_evpos(XEvent *e, int x, int y)
207 switch (e->type)
209 case ButtonPress:
210 case ButtonRelease:
211 e->xbutton.x_root = x;
212 e->xbutton.y_root = y;
213 return True;
214 case KeyPress:
215 case KeyRelease:
216 e->xkey.x_root = x;
217 e->xkey.y_root = y;
218 return True;
219 case MotionNotify:
220 if (e->xmotion.same_screen == True)
222 e->xmotion.x_root = x;
223 e->xmotion.y_root = y;
224 return True;
226 break;
227 default:
228 break;
229 } /* switch */
231 return False;
234 void fev_fake_event(XEvent *ev)
236 fev_event_old = fev_event;
237 fev_event = *ev;
238 /* don't update the last timestamp here; the triggering event has
239 * already done this */
241 return;
244 void *fev_save_event(void)
246 XEvent *ev;
248 ev = (XEvent *)safemalloc(sizeof(XEvent));
249 *ev = fev_event;
251 return ev;
254 void fev_restore_event(void *ev)
256 fev_event = *(XEvent *)ev;
257 free(ev);
259 return;
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;
268 return;
271 void fev_get_last_event(XEvent *ev)
273 *ev = fev_event;
275 return;
278 /* ---------------------------- X event replacements ----------------------- */
280 XTimeCoord *FGetMotionEvents(
281 Display *display, Window w, Time start, Time stop, int *nevents_return)
283 XTimeCoord *rc;
285 rc = XGetMotionEvents(display, w, start, stop, nevents_return);
287 return rc;
290 int FAllowEvents(
291 Display *display, int event_mode, Time time)
293 int rc;
295 rc = XAllowEvents(display, event_mode, time);
297 return rc;
300 Bool FCheckIfEvent(
301 Display *display, XEvent *event_return,
302 Bool (*predicate) (Display *display, XEvent *event, XPointer arg),
303 XPointer arg)
305 Bool rc;
306 XEvent new_ev;
308 rc = XCheckIfEvent(display, &new_ev, predicate, arg);
309 if (rc == True)
311 fev_event_old = fev_event;
312 fev_event = new_ev;
313 *event_return = fev_event;
314 fev_update_last_timestamp(event_return);
317 return rc;
320 Bool FCheckMaskEvent(
321 Display *display, long event_mask, XEvent *event_return)
323 Bool rc;
324 XEvent new_ev;
326 rc = XCheckMaskEvent(display, event_mask, &new_ev);
327 if (rc == True)
329 fev_event_old = fev_event;
330 fev_event = new_ev;
331 *event_return = fev_event;
332 fev_update_last_timestamp(event_return);
335 return rc;
338 Bool FCheckPeekIfEvent(
339 Display *display, XEvent *event_return,
340 Bool (*predicate) (Display *display, XEvent *event, XPointer arg),
341 XPointer arg)
343 XEvent dummy;
344 fev_check_peek_args cpa;
346 cpa.predicate = predicate;
347 cpa.arg = arg;
348 cpa.found = False;
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);
356 return cpa.found;
359 Bool FCheckTypedEvent(
360 Display *display, int event_type, XEvent *event_return)
362 Bool rc;
363 XEvent new_ev;
365 rc = XCheckTypedEvent(display, event_type, &new_ev);
366 if (rc == True)
368 fev_event_old = fev_event;
369 fev_event = new_ev;
370 *event_return = fev_event;
371 fev_update_last_timestamp(event_return);
374 return rc;
377 Bool FCheckTypedWindowEvent(
378 Display *display, Window w, int event_type, XEvent *event_return)
380 Bool rc;
381 XEvent new_ev;
383 rc = XCheckTypedWindowEvent(display, w, event_type, &new_ev);
384 if (rc == True)
386 fev_event_old = fev_event;
387 fev_event = new_ev;
388 *event_return = fev_event;
389 fev_update_last_timestamp(event_return);
392 return rc;
395 Bool FCheckWindowEvent(
396 Display *display, Window w, long event_mask, XEvent *event_return)
398 Bool rc;
399 XEvent new_ev;
401 rc = XCheckWindowEvent(display, w, event_mask, &new_ev);
402 if (rc == True)
404 fev_event_old = fev_event;
405 fev_event = new_ev;
406 *event_return = fev_event;
407 fev_update_last_timestamp(event_return);
410 return rc;
413 int FEventsQueued(
414 Display *display, int mode)
416 int rc;
418 rc = XEventsQueued(display, mode);
420 return rc;
423 int FIfEvent(
424 Display *display, XEvent *event_return,
425 Bool (*predicate) (Display *display, XEvent *event, XPointer arg),
426 XPointer arg)
428 int rc;
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);
435 return rc;
438 int FMaskEvent(
439 Display *display, long event_mask, XEvent *event_return)
441 int rc;
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);
448 return rc;
451 int FNextEvent(
452 Display *display, XEvent *event_return)
454 int rc;
456 fev_event_old = fev_event;
457 rc = XNextEvent(display, &fev_event);
458 *event_return = fev_event;
459 fev_update_last_timestamp(event_return);
461 return rc;
464 int FPeekEvent(
465 Display *display, XEvent *event_return)
467 int rc;
469 rc = XPeekEvent(display, event_return);
470 if (rc == True)
472 fev_update_last_timestamp(event_return);
475 return rc;
478 int FPeekIfEvent(
479 Display *display, XEvent *event_return,
480 Bool (*predicate) (Display *display, XEvent *event, XPointer arg),
481 XPointer arg)
483 int rc;
485 rc = XPeekIfEvent(display, event_return, predicate, arg);
486 if (rc == True)
488 fev_update_last_timestamp(event_return);
491 return rc;
494 int FPending(
495 Display *display)
497 int rc;
499 rc = XPending(display);
501 return rc;
504 int FPutBackEvent(
505 Display *display, XEvent *event)
507 int rc;
509 rc = XPutBackEvent(display, event);
510 fev_event = fev_event_old;
512 return rc;
515 int FQLength(
516 Display *display)
518 int rc;
520 rc = XQLength(display);
522 return rc;
525 Bool FQueryPointer(
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)
530 Bool rc;
532 rc = XQueryPointer(
533 display, w, root_return, child_return, root_x_return,
534 root_y_return, win_x_return, win_y_return, mask_return);
536 return rc;
539 Status FSendEvent(
540 Display *display, Window w, Bool propagate, long event_mask,
541 XEvent *event_send)
543 Status rc;
545 rc = XSendEvent(display, w, propagate, event_mask, event_send);
547 return rc;
550 int FWarpPointer(
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)
554 int rc;
556 rc = XWarpPointer(
557 display, src_w, dest_w, src_x, src_y, src_width, src_height,
558 dest_x, dest_y);
560 return rc;
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)
568 int rc;
570 rc = XWarpPointer(
571 display, src_w, dest_w, src_x, src_y, src_width, src_height,
572 dest_x, dest_y);
573 if (ev != NULL && dest_w == DefaultRootWindow(display))
575 fev_set_evpos(ev, dest_x, dest_y);
578 return rc;
581 int FWindowEvent(
582 Display *display, Window w, long event_mask, XEvent *event_return)
584 int rc;
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);
591 return rc;