diff options
author | Simon Rettberg | 2021-04-06 14:23:46 +0200 |
---|---|---|
committer | Simon Rettberg | 2021-04-06 14:23:46 +0200 |
commit | 26b6e4255d4b9ff79a6dca10de5bec7bfc8691f9 (patch) | |
tree | a51e1637554bcd84e63cccb1cb220c898a2c4ee8 /driver/test-xinput.c | |
parent | 5.44 (diff) | |
download | xscreensaver-26b6e4255d4b9ff79a6dca10de5bec7bfc8691f9.tar.gz xscreensaver-26b6e4255d4b9ff79a6dca10de5bec7bfc8691f9.tar.xz xscreensaver-26b6e4255d4b9ff79a6dca10de5bec7bfc8691f9.zip |
xscreensaver 6.00
Diffstat (limited to 'driver/test-xinput.c')
-rw-r--r-- | driver/test-xinput.c | 306 |
1 files changed, 306 insertions, 0 deletions
diff --git a/driver/test-xinput.c b/driver/test-xinput.c new file mode 100644 index 0000000..e3a6487 --- /dev/null +++ b/driver/test-xinput.c @@ -0,0 +1,306 @@ +/* test-xinput.c --- playing with the XInput2 extension. + * xscreensaver, Copyright © 2021 Jamie Zawinski <jwz@jwz.org> + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation. No representations are made about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <stdlib.h> +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif + +#include <stdio.h> +#include <time.h> +#include <sys/time.h> + +#include <X11/Xlib.h> +#include <X11/Xatom.h> +#include <X11/Intrinsic.h> +#include <X11/Xproto.h> +#include <X11/extensions/XInput2.h> + +#include "blurb.h" +#include "xinput.h" + +char *progclass = "XScreenSaver"; +Bool debug_p = True; + +static void +ungrab_timer (XtPointer closure, XtIntervalId *id) +{ + Display *dpy = (Display *) closure; + fprintf (stderr, "\n%s: ungrabbing\n\n", blurb()); + XUngrabKeyboard (dpy, CurrentTime); + XUngrabPointer (dpy, CurrentTime); +} + + +static const char * +grab_string (int status) +{ + switch (status) { + case GrabSuccess: return "GrabSuccess"; + case AlreadyGrabbed: return "AlreadyGrabbed"; + case GrabInvalidTime: return "GrabInvalidTime"; + case GrabNotViewable: return "GrabNotViewable"; + case GrabFrozen: return "GrabFrozen"; + default: + { + static char buf[255]; + sprintf(buf, "unknown status: %d", status); + return buf; + } + } +} + + +int +main (int argc, char **argv) +{ + XtAppContext app; + Widget toplevel_shell; + Display *dpy; + int xi_opcode; + Bool grab_kbd_p = False; + Bool grab_mouse_p = False; + Bool mouse_sync_p = True; + Bool kbd_sync_p = True; + int i; + + progname = argv[0]; + + for (i = 1; i < argc; i++) + { + const char *oa = argv[i]; + if (argv[i][0] == '-' && argv[i][1] == '-') + argv[i]++; + if (!strcmp (argv[i], "-grab")) + grab_kbd_p = grab_mouse_p = True; + else if (!strcmp (argv[i], "-grab-kbd") || + !strcmp (argv[i], "-grab-keyboard")) + grab_kbd_p = True; + else if (!strcmp (argv[i], "-grab-mouse") || + !strcmp (argv[i], "-grab-pointer")) + grab_mouse_p = True; + else if (!strcmp (argv[i], "-kbd-sync") || + !strcmp (argv[i], "-keyboard-sync")) + kbd_sync_p = True; + else if (!strcmp (argv[i], "-kbd-async") || + !strcmp (argv[i], "-keyboard-async")) + kbd_sync_p = False; + else if (!strcmp (argv[i], "-mouse-sync") || + !strcmp (argv[i], "-pointer-sync")) + mouse_sync_p = True; + else if (!strcmp (argv[i], "-mouse-async") || + !strcmp (argv[i], "-pointer-async")) + mouse_sync_p = False; + else + { + fprintf (stderr, "%s: unknown option: %s\n", blurb(), oa); + exit (1); + } + } + + toplevel_shell = XtAppInitialize (&app, progclass, 0, 0, + &argc, argv, 0, 0, 0); + dpy = XtDisplay (toplevel_shell); + if (!dpy) exit(1); + + if (! init_xinput (dpy, &xi_opcode)) + exit (1); + + if (grab_kbd_p || grab_mouse_p) + { + int timeout = 15; + Window w = RootWindow (dpy, 0); + int status; + XColor black = { 0, }; + Pixmap bit = XCreateBitmapFromData (dpy, w, "\000", 1, 1); + Cursor cursor = XCreatePixmapCursor (dpy, bit, bit, &black, &black, 0, 0); + + if (grab_kbd_p) + { + status = XGrabKeyboard (dpy, w, True, + (mouse_sync_p ? GrabModeSync : GrabModeAsync), + (kbd_sync_p ? GrabModeSync : GrabModeAsync), + CurrentTime); + if (status == GrabSuccess) + fprintf (stderr, "%s: grabbed keyboard (%s, %s)\n", blurb(), + (mouse_sync_p ? "sync" : "async"), + (kbd_sync_p ? "sync" : "async")); + else + { + fprintf (stderr, "%s: failed to grab keyboard (%s, %s): %s\n", + blurb(), + (mouse_sync_p ? "sync" : "async"), + (kbd_sync_p ? "sync" : "async"), + grab_string (status)); + exit(1); + } + } + + if (grab_mouse_p) + { + status = XGrabPointer (dpy, w, True, + (ButtonPressMask | ButtonReleaseMask | + EnterWindowMask | LeaveWindowMask | + PointerMotionMask | PointerMotionHintMask | + Button1MotionMask | Button2MotionMask | + Button3MotionMask | Button4MotionMask | + Button5MotionMask | ButtonMotionMask), + (mouse_sync_p ? GrabModeSync : GrabModeAsync), + (kbd_sync_p ? GrabModeSync : GrabModeAsync), + w, cursor, CurrentTime); + if (status == GrabSuccess) + fprintf (stderr, "%s: grabbed mouse (%s, %s)\n", blurb(), + (mouse_sync_p ? "sync" : "async"), + (kbd_sync_p ? "sync" : "async")); + else + { + fprintf (stderr, "%s: failed to grab mouse (%s, %s): %s\n", + blurb(), + (mouse_sync_p ? "sync" : "async"), + (kbd_sync_p ? "sync" : "async"), + grab_string (status)); + exit(1); + } + } + + fprintf (stderr, "%s: ungrabbing in %d seconds\n", blurb(), timeout); + XtAppAddTimeOut (app, 1000 * timeout, ungrab_timer, (XtPointer) dpy); + } + + while (1) + { + XEvent xev; + XIRawEvent *re; + + XtAppNextEvent (app, &xev); + XtDispatchEvent (&xev); + + switch (xev.xany.type) { + case KeyPress: + case KeyRelease: + { + static XComposeStatus compose = { 0, }; + KeySym keysym = 0; + char c[100]; + int n; + n = XLookupString (&xev.xkey, c, sizeof(c)-1, &keysym, &compose); + c[n] = 0; + fprintf (stderr, "%s: X11 Key%s %02x %02x %s \"%s\"\n", blurb(), + (xev.xkey.type == KeyPress ? "Press " : "Release"), + xev.xkey.keycode, xev.xkey.state, + XKeysymToString (keysym), c); + } + break; + case ButtonPress: + case ButtonRelease: + fprintf (stderr, "%s: X11 Button%s %d %d\n", blurb(), + (xev.xany.type == ButtonPress ? "Press " : "Release"), + xev.xbutton.button, xev.xbutton.state); + break; + case MotionNotify: + fprintf (stderr, "%s: X11 MotionNotify %4d, %-4d\n", + blurb(), xev.xmotion.x_root, xev.xmotion.y_root); + break; + case GenericEvent: + break; + case EnterNotify: + case LeaveNotify: + break; + default: + fprintf (stderr, "%s: X11 event %d on 0x%lx\n", + blurb(), xev.xany.type, xev.xany.window); + break; + } + + if (xev.xcookie.type != GenericEvent || + xev.xcookie.extension != xi_opcode) + continue; /* not an XInput event */ + if (!xev.xcookie.data) + XGetEventData (dpy, &xev.xcookie); + if (!xev.xcookie.data) + continue; /* Bogus XInput event */ + + re = xev.xcookie.data; + switch (xev.xcookie.evtype) { + case XI_RawKeyPress: + case XI_RawKeyRelease: + { + /* Fake up an XKeyEvent in order to call XKeysymToString(). */ + XEvent ev2; + Bool ok = xinput_event_to_xlib (xev.xcookie.evtype, + (XIDeviceEvent *) re, + &ev2); + if (!ok) + fprintf (stderr, "%s: unable to translate XInput2 event\n", + blurb()); + else + { + static XComposeStatus compose = { 0, }; + KeySym keysym = 0; + char c[100]; + int n; + n = XLookupString (&ev2.xkey, c, sizeof(c)-1, &keysym, &compose); + c[n] = 0; + fprintf (stderr, "%s: XI_RawKey%s %02x %02x %s \"%s\"\n", + blurb(), + (ev2.xkey.type == KeyPress ? "Press " : "Release"), + ev2.xkey.keycode, ev2.xkey.state, + XKeysymToString (keysym), c); + } + } + break; + case XI_RawButtonPress: + case XI_RawButtonRelease: + fprintf (stderr, "%s: XI_RawButton%s %d\n", blurb(), + (re->evtype == XI_RawButtonPress ? "Press " : "Release"), + re->detail); + break; + case XI_RawMotion: + { + Window root_ret, child_ret; + int root_x, root_y; + int win_x, win_y; + unsigned int mask; + XQueryPointer (dpy, DefaultRootWindow (dpy), + &root_ret, &child_ret, &root_x, &root_y, + &win_x, &win_y, &mask); + fprintf (stderr, "%s: XI_RawMotion %4d, %-4d %7.02f, %-7.02f\n", + blurb(), + root_x, root_y, + re->raw_values[0], re->raw_values[1]); + } + break; + case XI_RawTouchBegin: + fprintf (stderr, "%s: XI_RawTouchBegin\n", blurb()); + break; + case XI_RawTouchEnd: + fprintf (stderr, "%s: XI_RawTouchEnd", blurb()); + break; + case XI_RawTouchUpdate: + fprintf (stderr, "%s: XI_RawTouchUpdate", blurb()); + break; + + default: + fprintf (stderr, "%s: XInput unknown event %d\n", blurb(), + xev.xcookie.evtype); + break; + } + + XFreeEventData (dpy, &xev.xcookie); + } + + exit (0); +} |