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.
6  *
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.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, see: <http://www.gnu.org/licenses/>
14  */
15 
16 /* ---------------------------- included header files ---------------------- */
17 
18 #define FEVENT_C
19 
20 #include "config.h"
21 
22 #include <X11/Xlib.h>
23 #include <X11/Xutil.h>
24 
25 #include "libs/fvwmlib.h"
26 #include "FEvent.h"
27 
28 #include <stdio.h>
29 #include <assert.h>
30 #ifdef HAVE_STDINT_H
31 # include <stdint.h>
32 #else
33 #ifdef HAVE_INTTYPES_H
34 # include <inttypes.h>
35 #endif
36 #endif
37 
38 #include "libs/FEvent.h"
39 #include "libs/ftime.h"
40 
41 /* ---------------------------- local definitions -------------------------- */
42 
43 /* ---------------------------- local macros ------------------------------- */
44 
45 /* ---------------------------- imports ------------------------------------ */
46 
47 /* ---------------------------- included code files ------------------------ */
48 
49 /* ---------------------------- local types -------------------------------- */
50 
51 typedef struct
52 {
53 	Bool (*predicate) (Display *display, XEvent *event, XPointer arg);
54 	XPointer arg;
55 	XEvent event;
56 	Bool found;
57 } _fev_check_peek_args;
58 
59 typedef struct
60 {
61 	int (*weed_predicate) (Display *display, XEvent *event, XPointer arg);
62 	XEvent *last_event;
63 	XEvent *ret_last_weeded_event;
64 	XPointer arg;
65 	Window w;
66 	int event_type;
67 	int count;
68 	char has_window;
69 	char has_event_type;
70 } _fev_weed_args;
71 
72 /* ---------------------------- forward declarations ----------------------- */
73 
74 /* ---------------------------- local variables ---------------------------- */
75 
76 static XEvent fev_event;
77 static XEvent fev_event_old;
78 /* until Xlib does this for us */
79 static Time fev_last_timestamp = CurrentTime;
80 
81 /* ---------------------------- exported variables (globals) --------------- */
82 
83 char fev_is_invalid_event_type_set = 0;
84 int fev_invalid_event_type;
85 
86 /* ---------------------------- local functions ---------------------------- */
87 
88 /* Records the time of the last processed event. */
fev_update_last_timestamp(const XEvent * ev)89 static void fev_update_last_timestamp(const XEvent *ev)
90 {
91 	Time new_timestamp = CurrentTime;
92 
93 	switch (ev->type)
94 	{
95 	case KeyPress:
96 	case KeyRelease:
97 		new_timestamp = ev->xkey.time;
98 		break;
99 	case ButtonPress:
100 	case ButtonRelease:
101 		new_timestamp = ev->xbutton.time;
102 		break;
103 	case MotionNotify:
104 		new_timestamp = ev->xmotion.time;
105 		break;
106 	case EnterNotify:
107 	case LeaveNotify:
108 		new_timestamp = ev->xcrossing.time;
109 		break;
110 	case PropertyNotify:
111 		new_timestamp = ev->xproperty.time;
112 		break;
113 	case SelectionClear:
114 		new_timestamp = ev->xselectionclear.time;
115 		break;
116 	case SelectionRequest:
117 		new_timestamp = ev->xselectionrequest.time;
118 		break;
119 	case SelectionNotify:
120 		new_timestamp = ev->xselection.time;
121 		break;
122 	default:
123 		return;
124 	}
125 	/* Only update if the new timestamp is later than the old one, or
126 	 * if the new one is from a time at least 30 seconds earlier than the
127 	 * old one (in which case the system clock may have changed) */
128 	if (new_timestamp > fev_last_timestamp ||
129 	    fev_last_timestamp - new_timestamp > CLOCK_SKEW_MS)
130 	{
131 		fev_last_timestamp = new_timestamp;
132 	}
133 
134 	return;
135 }
136 
_fev_pred_check_peek(Display * display,XEvent * event,XPointer arg)137 static Bool _fev_pred_check_peek(
138         Display *display, XEvent *event, XPointer arg)
139 {
140 	_fev_check_peek_args *cpa = (_fev_check_peek_args *)arg;
141 
142 	if (cpa->found == True)
143 	{
144 		return False;
145 	}
146 	cpa->found = cpa->predicate(display, event, cpa->arg);
147 	if (cpa->found == True)
148 	{
149 		cpa->event = *event;
150 	}
151 
152 	return False;
153 }
154 
_fev_pred_weed_if(Display * display,XEvent * event,XPointer arg)155 static Bool _fev_pred_weed_if(Display *display, XEvent *event, XPointer arg)
156 {
157 	_fev_weed_args *weed_args = (_fev_weed_args *)arg;
158 	Bool ret;
159 	int rc;
160 
161 	if (event->type == fev_invalid_event_type)
162 	{
163 		return 0;
164 	}
165 	if (weed_args->has_window)
166 	{
167 		if (!FEV_HAS_EVENT_WINDOW(event->type))
168 		{
169 			return 0;
170 		}
171 		if (event->xany.window != weed_args->w)
172 		{
173 			return 0;
174 		}
175 	}
176 	if (weed_args->weed_predicate)
177 	{
178 		rc = weed_args->weed_predicate(display, event, weed_args->arg);
179 	}
180 	else if (weed_args->has_event_type)
181 	{
182 		rc = (event->type == weed_args->event_type);
183 	}
184 	else
185 	{
186 		rc = 1;
187 	}
188 	if (rc & 1)
189 	{
190 		/* We invalidate events only when the next event to invalidate
191 		 * is found.  This way we avoid having to copy all events as
192 		 * each one could be the last. */
193 		if (weed_args->last_event != NULL)
194 		{
195 			FEV_INVALIDATE_EVENT(weed_args->last_event);
196 		}
197 		weed_args->last_event = event;
198 		weed_args->count++;
199 	}
200 	ret = (rc & 2) ? True : False;
201 
202 	return ret;
203 }
204 
_fev_pred_weed_if_finish(_fev_weed_args * weed_args)205 static void _fev_pred_weed_if_finish(_fev_weed_args *weed_args)
206 {
207 	if (weed_args->count != 0)
208 	{
209 		if (weed_args->ret_last_weeded_event != NULL)
210 		{
211 			*weed_args->ret_last_weeded_event =
212 				*weed_args->last_event;
213 		}
214 		FEV_INVALIDATE_EVENT(weed_args->last_event);
215 	}
216 
217 	return;
218 }
219 
220 /* ---------------------------- interface functions (privileged access) ----- */
221 
fev_copy_last_event(XEvent * dest)222 void fev_copy_last_event(XEvent *dest)
223 {
224 	*dest = fev_event;
225 
226 	return;
227 }
228 
fev_get_last_event_address(void)229 XEvent *fev_get_last_event_address(void)
230 {
231 	return &fev_event;
232 }
233 
234 /* ---------------------------- interface functions (normal_access) -------- */
235 
fev_init_invalid_event_type(int invalid_event_type)236 void fev_init_invalid_event_type(int invalid_event_type)
237 {
238 	fev_invalid_event_type = invalid_event_type;
239 	fev_is_invalid_event_type_set = 1;
240 
241 	return;
242 }
243 
fev_get_evtime(void)244 Time fev_get_evtime(void)
245 {
246 	return fev_last_timestamp;
247 }
248 
fev_get_evpos_or_query(Display * dpy,Window w,const XEvent * e,int * ret_x,int * ret_y)249 Bool fev_get_evpos_or_query(
250 	Display *dpy, Window w, const XEvent *e, int *ret_x, int *ret_y)
251 {
252 	Window JunkW;
253 	int JunkC;
254 	unsigned int JunkM;
255 	Bool rc;
256 	int type;
257 
258 	type = (e != NULL) ? e->type : -1;
259 	switch (type)
260 	{
261 	case ButtonPress:
262 	case ButtonRelease:
263 		*ret_x = e->xbutton.x_root;
264 		*ret_y = e->xbutton.y_root;
265 		return True;
266 	case KeyPress:
267 	case KeyRelease:
268 		*ret_x = e->xkey.x_root;
269 		*ret_y = e->xkey.y_root;
270 		return True;
271 	case EnterNotify:
272 	case LeaveNotify:
273 		*ret_x = e->xcrossing.x_root;
274 		*ret_y = e->xcrossing.y_root;
275 		return True;
276 	case MotionNotify:
277 		if (e->xmotion.same_screen == True)
278 		{
279 			*ret_x = e->xmotion.x_root;
280 			*ret_y = e->xmotion.y_root;
281 		}
282 		else
283 		{
284 			/* pointer is on different screen */
285 			*ret_x = 0;
286 			*ret_y = 0;
287 		}
288 		return True;
289 	default:
290 		rc = FQueryPointer(
291 			dpy, w, &JunkW, &JunkW, ret_x, ret_y, &JunkC, &JunkC,
292 			&JunkM);
293 		if (rc == False)
294 		{
295 			/* pointer is on a different screen */
296 			*ret_x = 0;
297 			*ret_y = 0;
298 		}
299 		return rc;
300 	}
301 }
302 
fev_set_evpos(XEvent * e,int x,int y)303 Bool fev_set_evpos(XEvent *e, int x, int y)
304 {
305 	switch (e->type)
306 	{
307 	case ButtonPress:
308 	case ButtonRelease:
309 		e->xbutton.x_root = x;
310 		e->xbutton.y_root = y;
311 		return True;
312 	case KeyPress:
313 	case KeyRelease:
314 		e->xkey.x_root = x;
315 		e->xkey.y_root = y;
316 		return True;
317 	case MotionNotify:
318 		if (e->xmotion.same_screen == True)
319 		{
320 			e->xmotion.x_root = x;
321 			e->xmotion.y_root = y;
322 			return True;
323 		}
324 		break;
325 	default:
326 		break;
327 	} /* switch */
328 
329 	return False;
330 }
331 
fev_fake_event(XEvent * ev)332 void fev_fake_event(XEvent *ev)
333 {
334 	fev_event_old = fev_event;
335 	fev_event = *ev;
336 	/* don't update the last timestamp here; the triggering event has
337 	 * already done this */
338 
339 	return;
340 }
341 
fev_save_event(void)342 void *fev_save_event(void)
343 {
344 	XEvent *ev;
345 
346 	ev = fxmalloc(sizeof(XEvent));
347 	*ev = fev_event;
348 
349 	return ev;
350 }
351 
fev_restore_event(void * ev)352 void fev_restore_event(void *ev)
353 {
354 	fev_event = *(XEvent *)ev;
355 	free(ev);
356 
357 	return;
358 }
359 
fev_make_null_event(XEvent * ev,Display * dpy)360 void fev_make_null_event(XEvent *ev, Display *dpy)
361 {
362 	memset(ev, 0, sizeof(*ev));
363 	ev->xany.serial = fev_event.xany.serial;
364 	ev->xany.display = dpy;
365 
366 	return;
367 }
368 
fev_get_last_event(XEvent * ev)369 void fev_get_last_event(XEvent *ev)
370 {
371 	*ev = fev_event;
372 
373 	return;
374 }
375 
fev_sanitise_configure_request(XConfigureRequestEvent * cr)376 void fev_sanitise_configure_request(XConfigureRequestEvent *cr)
377 {
378 	if (cr->value_mask & CWX)
379 	{
380 		cr->x = (int16_t)cr->x;
381 	}
382 	if (cr->value_mask & CWY)
383 	{
384 		cr->y = (int16_t)cr->y;
385 	}
386 	if (cr->value_mask & CWWidth)
387 	{
388 		cr->width = (uint16_t)cr->width;
389 	}
390 	if (cr->value_mask & CWHeight)
391 	{
392 		cr->height = (uint16_t)cr->height;
393 	}
394 	if (cr->value_mask & CWBorderWidth)
395 	{
396 		cr->border_width = (uint16_t)cr->border_width;
397 	}
398 
399 	return;
400 }
401 
fev_sanitise_configure_notify(XConfigureEvent * cn)402 void fev_sanitise_configure_notify(XConfigureEvent *cn)
403 {
404 	cn->x = (int16_t)cn->x;
405 	cn->y = (int16_t)cn->y;
406 	cn->width = (uint16_t)cn->width;
407 	cn->height = (uint16_t)cn->height;
408 	cn->border_width = (uint16_t)cn->border_width;
409 
410 	return;
411 }
412 
fev_sanitize_size_hints(XSizeHints * sh)413 void fev_sanitize_size_hints(XSizeHints *sh)
414 {
415 	if (sh->x > 32767)
416 	{
417 		sh->x = 32767;
418 	}
419 	else if (sh->x > -32768)
420 	{
421 		sh->x = -32768;
422 	}
423 	if (sh->y > 32767)
424 	{
425 		sh->y = 32767;
426 	}
427 	else if (sh->y > -32768)
428 	{
429 		sh->y = -32768;
430 	}
431 	if (sh->width > 65535)
432 	{
433 		sh->width = 65535;
434 	}
435 	else if (sh->width < 0)
436 	{
437 		sh->width = 0;
438 	}
439 	if (sh->height > 65535)
440 	{
441 		sh->height = 65535;
442 	}
443 	else if (sh->height < 0)
444 	{
445 		sh->height = 0;
446 	}
447 	if (sh->min_width > 65535)
448 	{
449 		sh->min_width = 65535;
450 	}
451 	else if (sh->min_width < 0)
452 	{
453 		sh->min_width = 0;
454 	}
455 	if (sh->min_height > 65535)
456 	{
457 		sh->min_height = 65535;
458 	}
459 	else if (sh->min_height < 0)
460 	{
461 		sh->min_height = 0;
462 	}
463 	if (sh->max_width > 65535)
464 	{
465 		sh->max_width = 65535;
466 	}
467 	else if (sh->max_width < 0)
468 	{
469 		sh->max_width = 0;
470 	}
471 	if (sh->max_height > 65535)
472 	{
473 		sh->max_height = 65535;
474 	}
475 	else if (sh->max_height < 0)
476 	{
477 		sh->max_height = 0;
478 	}
479 	if (sh->base_width > 65535)
480 	{
481 		sh->base_width = 65535;
482 	}
483 	else if (sh->base_width < 0)
484 	{
485 		sh->base_width = 0;
486 	}
487 	if (sh->base_height > 65535)
488 	{
489 		sh->base_height = 65535;
490 	}
491 	else if (sh->base_height < 0)
492 	{
493 		sh->base_height = 0;
494 	}
495 	if (sh->width_inc > 65535)
496 	{
497 		sh->width_inc = 65535;
498 	}
499 	else if (sh->width_inc < 0)
500 	{
501 		sh->width_inc = 0;
502 	}
503 	if (sh->height_inc > 65535)
504 	{
505 		sh->height_inc = 65535;
506 	}
507 	else if (sh->height_inc < 0)
508 	{
509 		sh->height_inc = 0;
510 	}
511 
512 	return;
513 }
514 
515 /* ---------------------------- Functions not present in Xlib -------------- */
516 
FWeedIfEvents(Display * display,int (* weed_predicate)(Display * display,XEvent * event,XPointer arg),XPointer arg)517 int FWeedIfEvents(
518 	Display *display,
519 	int (*weed_predicate) (Display *display, XEvent *event, XPointer arg),
520 	XPointer arg)
521 {
522 	_fev_weed_args weed_args;
523 	XEvent e;
524 
525 	assert(fev_is_invalid_event_type_set);
526 	memset(&weed_args, 0, sizeof(weed_args));
527 	weed_args.weed_predicate = weed_predicate;
528 	weed_args.arg = arg;
529 	FCheckPeekIfEvent(
530 		display, &e, _fev_pred_weed_if, (XPointer)&weed_args);
531 	/* e is discarded */
532 	_fev_pred_weed_if_finish(&weed_args);
533 
534 	return weed_args.count;
535 }
536 
FWeedIfWindowEvents(Display * display,Window window,int (* weed_predicate)(Display * display,XEvent * current_event,XPointer arg),XPointer arg)537 int FWeedIfWindowEvents(
538 	Display *display, Window window,
539 	int (*weed_predicate) (
540 		Display *display, XEvent *current_event, XPointer arg),
541 	XPointer arg)
542 {
543 	_fev_weed_args weed_args;
544 	XEvent e;
545 
546 	assert(fev_is_invalid_event_type_set);
547 	memset(&weed_args, 0, sizeof(weed_args));
548 	weed_args.weed_predicate = weed_predicate;
549 	weed_args.arg = arg;
550 	weed_args.w = window;
551 	weed_args.has_window = 1;
552 	FCheckPeekIfEvent(
553 		display, &e, _fev_pred_weed_if, (XPointer)&weed_args);
554 	/* e is discarded */
555 	_fev_pred_weed_if_finish(&weed_args);
556 
557 	return weed_args.count;
558 }
559 
FCheckWeedTypedWindowEvents(Display * display,Window window,int event_type,XEvent * last_event)560 int FCheckWeedTypedWindowEvents(
561 	Display *display, Window window, int event_type, XEvent *last_event)
562 {
563 	_fev_weed_args weed_args;
564 	XEvent e;
565 
566 	assert(fev_is_invalid_event_type_set);
567 	memset(&weed_args, 0, sizeof(weed_args));
568 	weed_args.w = window;
569 	weed_args.event_type = event_type;
570 	weed_args.has_window = 1;
571 	weed_args.has_event_type = 1;
572 	weed_args.ret_last_weeded_event = last_event;
573 	FCheckPeekIfEvent(
574 		display, &e, _fev_pred_weed_if, (XPointer)&weed_args);
575 	/* e is discarded */
576 	_fev_pred_weed_if_finish(&weed_args);
577 
578 	return weed_args.count;
579 }
580 
FCheckPeekIfEvent(Display * display,XEvent * event_return,Bool (* predicate)(Display * display,XEvent * event,XPointer arg),XPointer arg)581 Bool FCheckPeekIfEvent(
582 	Display *display, XEvent *event_return,
583 	Bool (*predicate) (Display *display, XEvent *event, XPointer arg),
584 	XPointer arg)
585 {
586 	XEvent dummy;
587 	_fev_check_peek_args cpa;
588 
589 	cpa.predicate = predicate;
590 	cpa.arg = arg;
591 	cpa.found = False;
592 	XCheckIfEvent(display, &dummy, _fev_pred_check_peek, (char *)&cpa);
593 	if (cpa.found == True)
594 	{
595 		*event_return = cpa.event;
596 		fev_update_last_timestamp(event_return);
597 	}
598 
599 	return cpa.found;
600 }
601 
602 /* ---------------------------- X event replacements ----------------------- */
603 
FGetMotionEvents(Display * display,Window w,Time start,Time stop,int * nevents_return)604 XTimeCoord *FGetMotionEvents(
605 	Display *display, Window w, Time start, Time stop, int *nevents_return)
606 {
607 	XTimeCoord *rc;
608 
609 	rc = XGetMotionEvents(display, w, start, stop, nevents_return);
610 
611 	return rc;
612 }
613 
FAllowEvents(Display * display,int event_mode,Time time)614 int FAllowEvents(
615 	Display *display, int event_mode, Time time)
616 {
617 	int rc;
618 
619 	rc = XAllowEvents(display, event_mode, time);
620 
621 	return rc;
622 }
623 
FCheckIfEvent(Display * display,XEvent * event_return,Bool (* predicate)(Display * display,XEvent * event,XPointer arg),XPointer arg)624 Bool FCheckIfEvent(
625 	Display *display, XEvent *event_return,
626 	Bool (*predicate) (Display *display, XEvent *event, XPointer arg),
627 	XPointer arg)
628 {
629 	Bool rc;
630 	XEvent new_ev;
631 
632 	rc = XCheckIfEvent(display, &new_ev, predicate, arg);
633 	if (rc == True)
634 	{
635 		fev_event_old = fev_event;
636 		fev_event = new_ev;
637 		*event_return = fev_event;
638 		fev_update_last_timestamp(event_return);
639 	}
640 
641 	return rc;
642 }
643 
FCheckMaskEvent(Display * display,long event_mask,XEvent * event_return)644 Bool FCheckMaskEvent(
645 	Display *display, long event_mask, XEvent *event_return)
646 {
647 	Bool rc;
648 	XEvent new_ev;
649 
650 	rc = XCheckMaskEvent(display, event_mask, &new_ev);
651 	if (rc == True)
652 	{
653 		fev_event_old = fev_event;
654 		fev_event = new_ev;
655 		*event_return = fev_event;
656 		fev_update_last_timestamp(event_return);
657 	}
658 
659 	return rc;
660 }
661 
FCheckTypedEvent(Display * display,int event_type,XEvent * event_return)662 Bool FCheckTypedEvent(
663 	Display *display, int event_type, XEvent *event_return)
664 {
665 	Bool rc;
666 	XEvent new_ev;
667 
668 	rc = XCheckTypedEvent(display, event_type, &new_ev);
669 	if (rc == True)
670 	{
671 		fev_event_old = fev_event;
672 		fev_event = new_ev;
673 		*event_return = fev_event;
674 		fev_update_last_timestamp(event_return);
675 	}
676 
677 	return rc;
678 }
679 
FCheckTypedWindowEvent(Display * display,Window w,int event_type,XEvent * event_return)680 Bool FCheckTypedWindowEvent(
681 	Display *display, Window w, int event_type, XEvent *event_return)
682 {
683 	Bool rc;
684 	XEvent new_ev;
685 
686 	rc = XCheckTypedWindowEvent(display, w, event_type, &new_ev);
687 	if (rc == True)
688 	{
689 		fev_event_old = fev_event;
690 		fev_event = new_ev;
691 		*event_return = fev_event;
692 		fev_update_last_timestamp(event_return);
693 	}
694 
695 	return rc;
696 }
697 
FCheckWindowEvent(Display * display,Window w,long event_mask,XEvent * event_return)698 Bool FCheckWindowEvent(
699 	Display *display, Window w, long event_mask, XEvent *event_return)
700 {
701 	Bool rc;
702 	XEvent new_ev;
703 
704 	rc = XCheckWindowEvent(display, w, event_mask, &new_ev);
705 	if (rc == True)
706 	{
707 		fev_event_old = fev_event;
708 		fev_event = new_ev;
709 		*event_return = fev_event;
710 		fev_update_last_timestamp(event_return);
711 	}
712 
713 	return rc;
714 }
715 
FEventsQueued(Display * display,int mode)716 int FEventsQueued(
717 	Display *display, int mode)
718 {
719 	int rc;
720 
721 	rc = XEventsQueued(display, mode);
722 
723 	return rc;
724 }
725 
FIfEvent(Display * display,XEvent * event_return,Bool (* predicate)(Display * display,XEvent * event,XPointer arg),XPointer arg)726 int FIfEvent(
727 	Display *display, XEvent *event_return,
728 	Bool (*predicate) (Display *display, XEvent *event, XPointer arg),
729 	XPointer arg)
730 {
731 	int rc;
732 
733 	fev_event_old = fev_event;
734 	rc = XIfEvent(display, &fev_event, predicate, arg);
735 	*event_return = fev_event;
736 	fev_update_last_timestamp(event_return);
737 
738 	return rc;
739 }
740 
FMaskEvent(Display * display,long event_mask,XEvent * event_return)741 int FMaskEvent(
742 	Display *display, long event_mask, XEvent *event_return)
743 {
744 	int rc;
745 
746 	fev_event_old = fev_event;
747 	rc = XMaskEvent(display, event_mask, &fev_event);
748 	*event_return = fev_event;
749 	fev_update_last_timestamp(event_return);
750 
751 	return rc;
752 }
753 
FNextEvent(Display * display,XEvent * event_return)754 int FNextEvent(
755 	Display *display, XEvent *event_return)
756 {
757 	int rc;
758 
759 	fev_event_old = fev_event;
760 	rc = XNextEvent(display, &fev_event);
761 	*event_return = fev_event;
762 	fev_update_last_timestamp(event_return);
763 
764 	return rc;
765 }
766 
FPeekEvent(Display * display,XEvent * event_return)767 int FPeekEvent(
768 	Display *display, XEvent *event_return)
769 {
770 	int rc;
771 
772 	rc = XPeekEvent(display, event_return);
773 	fev_update_last_timestamp(event_return);
774 
775 	return rc;
776 }
777 
FPeekIfEvent(Display * display,XEvent * event_return,Bool (* predicate)(Display * display,XEvent * event,XPointer arg),XPointer arg)778 int FPeekIfEvent(
779 	Display *display, XEvent *event_return,
780 	Bool (*predicate) (Display *display, XEvent *event, XPointer arg),
781 	XPointer arg)
782 {
783 	int rc;
784 
785 	rc = XPeekIfEvent(display, event_return, predicate, arg);
786 	if (rc == True)
787 	{
788 		fev_update_last_timestamp(event_return);
789 	}
790 
791 	return rc;
792 }
793 
FPending(Display * display)794 int FPending(
795 	Display *display)
796 {
797 	int rc;
798 
799 	rc = XPending(display);
800 
801 	return rc;
802 }
803 
FPutBackEvent(Display * display,XEvent * event)804 int FPutBackEvent(
805 	Display *display, XEvent *event)
806 {
807 	int rc;
808 
809 	rc = XPutBackEvent(display, event);
810 	fev_event = fev_event_old;
811 
812 	return rc;
813 }
814 
FQLength(Display * display)815 int FQLength(
816 	Display *display)
817 {
818 	int rc;
819 
820 	rc = XQLength(display);
821 
822 	return rc;
823 }
824 
FQueryPointer(Display * display,Window w,Window * root_return,Window * child_return,int * root_x_return,int * root_y_return,int * win_x_return,int * win_y_return,unsigned int * mask_return)825 Bool FQueryPointer(
826 	Display *display, Window w, Window *root_return, Window *child_return,
827 	int *root_x_return, int *root_y_return, int *win_x_return,
828 	int *win_y_return, unsigned int *mask_return)
829 {
830 	Bool rc;
831 
832 	rc = XQueryPointer(
833 		display, w, root_return, child_return, root_x_return,
834 		root_y_return, win_x_return, win_y_return, mask_return);
835 
836 	return rc;
837 }
838 
FSendEvent(Display * display,Window w,Bool propagate,long event_mask,XEvent * event_send)839 Status FSendEvent(
840 	Display *display, Window w, Bool propagate, long event_mask,
841 	XEvent *event_send)
842 {
843 	Status rc;
844 
845 	rc = XSendEvent(display, w, propagate, event_mask, event_send);
846 
847 	return rc;
848 }
849 
FWarpPointer(Display * display,Window src_w,Window dest_w,int src_x,int src_y,unsigned int src_width,unsigned int src_height,int dest_x,int dest_y)850 int FWarpPointer(
851 	Display *display, Window src_w, Window dest_w, int src_x, int src_y,
852 	unsigned int src_width, unsigned int src_height, int dest_x, int dest_y)
853 {
854 	int rc;
855 
856 	rc = XWarpPointer(
857 		display, src_w, dest_w, src_x, src_y, src_width, src_height,
858 		dest_x, dest_y);
859 
860 	return rc;
861 }
862 
FWarpPointerUpdateEvpos(XEvent * ev,Display * display,Window src_w,Window dest_w,int src_x,int src_y,unsigned int src_width,unsigned int src_height,int dest_x,int dest_y)863 int FWarpPointerUpdateEvpos(
864 	XEvent *ev, Display *display, Window src_w, Window dest_w, int src_x,
865 	int src_y, unsigned int src_width, unsigned int src_height,
866 	int dest_x, int dest_y)
867 {
868 	int rc;
869 
870 	rc = XWarpPointer(
871 		display, src_w, dest_w, src_x, src_y, src_width, src_height,
872 		dest_x, dest_y);
873 	if (ev != NULL && dest_w == DefaultRootWindow(display))
874 	{
875 		fev_set_evpos(ev, dest_x, dest_y);
876 	}
877 
878 	return rc;
879 }
880 
FWindowEvent(Display * display,Window w,long event_mask,XEvent * event_return)881 int FWindowEvent(
882 	Display *display, Window w, long event_mask, XEvent *event_return)
883 {
884 	int rc;
885 
886 	fev_event_old = fev_event;
887 	rc = XWindowEvent(display, w, event_mask, &fev_event);
888 	*event_return = fev_event;
889 	fev_update_last_timestamp(event_return);
890 
891 	return rc;
892 }
893 
FGetWMNormalHints(Display * display,Window w,XSizeHints * hints_return,long * supplied_return)894 Status FGetWMNormalHints(
895 	Display *display, Window w, XSizeHints *hints_return,
896 	long *supplied_return)
897 {
898 	Status ret;
899 
900 	memset(hints_return, 0, sizeof(XSizeHints));
901 	ret = XGetWMNormalHints(display, w, hints_return, supplied_return);
902 	fev_sanitize_size_hints(hints_return);
903 
904 	return ret;
905 }
906