summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrediano Ziglio <fziglio@redhat.com>2015-08-03 10:45:42 +0100
committerFrediano Ziglio <fziglio@redhat.com>2015-08-03 10:45:42 +0100
commitc8c9be4a8ef46ae54c31cbb44ffa58734c0c90fa (patch)
tree3e941808002239e851da033da277bbecb964d70c
parent37b92905cb4f2110ce564810f019b609d815e8fc (diff)
Add XInput events
Allows to get any keypress/mouse events.
-rw-r--r--Makefile.am3
-rw-r--r--global.h13
-rw-r--r--spice-replay.c26
-rw-r--r--test_xi2.c355
-rw-r--r--xev.c4
5 files changed, 240 insertions, 161 deletions
diff --git a/Makefile.am b/Makefile.am
index d66a082..0cf181c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -26,4 +26,5 @@ spice_replay_LDADD = $(REPLAY_LIBS)
spice_replay_SOURCES = \
spice-replay.c \
- xev.c
+ xev.c \
+ test_xi2.c
diff --git a/global.h b/global.h
index 0ea6f7b..92fbb00 100644
--- a/global.h
+++ b/global.h
@@ -1,5 +1,18 @@
extern Display *dpy;
+/* standard events */
void xev_init(Window w);
void xev_dump(XEvent *event);
+
+/* XInput */
+extern int xi_opcode;
+
+void xinput_init(Display *display, Window win);
+void xinput_dump(Display *display, XGenericEventCookie *cookie);
+
+static inline int
+is_xinput_event(XEvent *event)
+{
+ return event->type == GenericEvent && event->xgeneric.extension == xi_opcode;
+}
diff --git a/spice-replay.c b/spice-replay.c
index 59ca8f5..151adfa 100644
--- a/spice-replay.c
+++ b/spice-replay.c
@@ -60,7 +60,7 @@ version(void)
int main(int argc, char **argv)
{
- Window w;
+ Window w = 0;
const char *fn_out = NULL;
const char *display = NULL;
@@ -105,6 +105,16 @@ int main(int argc, char **argv)
if (optind >= argc || mode == MODE_UNKNOWN)
usage(stderr);
+ if (mode == MODE_PLAY) {
+ fprintf (stderr, "playback mode still not supported\n");
+ return EXIT_FAILURE;
+ }
+
+ if (mode == MODE_RECORD && w == 0) {
+ fprintf (stderr, "record mode require a window to be specified\n");
+ return EXIT_FAILURE;
+ }
+
fn_out = argv[optind];
dpy = XOpenDisplay (display);
@@ -114,14 +124,24 @@ int main(int argc, char **argv)
}
xev_init(w);
+ xinput_init(dpy, w);
while(1) {
XEvent event;
XNextEvent (dpy, &event);
- if (verbose)
- xev_dump(&event);
+ if (is_xinput_event(&event)) {
+ XGenericEventCookie *cookie = &event.xcookie;
+ if (XGetEventData(dpy, cookie)) {
+ if (verbose)
+ xinput_dump(dpy, cookie);
+ XFreeEventData(dpy, cookie);
+ }
+ } else {
+ if (verbose)
+ xev_dump(&event);
+ }
}
XCloseDisplay (dpy);
diff --git a/test_xi2.c b/test_xi2.c
index 7abe25a..ba80326 100644
--- a/test_xi2.c
+++ b/test_xi2.c
@@ -22,24 +22,24 @@
*
*/
+#include <config.h>
-#include "xinput.h"
+#include <X11/Xlib.h>
+#include <X11/extensions/XInput.h>
+#ifdef HAVE_XI2
+#include <X11/extensions/XInput2.h>
+#endif
+#include <X11/Xutil.h>
+#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
-extern void print_classes_xi2(Display*, XIAnyClassInfo **classes,
- int num_classes);
+#include "global.h"
-static Window create_win(Display *dpy)
-{
- Window win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0, 200,
- 200, 0, 0, WhitePixel(dpy, 0));
- Window subwindow = XCreateSimpleWindow(dpy, win, 50, 50, 50, 50, 0, 0,
- BlackPixel(dpy, 0));
-
- XMapWindow(dpy, subwindow);
- XSelectInput(dpy, win, ExposureMask);
- return win;
-}
+int xi_opcode;
+
+static void print_classes_xi2(Display*, XIAnyClassInfo **classes,
+ int num_classes);
static void print_deviceevent(XIDeviceEvent* event)
{
@@ -88,12 +88,12 @@ static void print_deviceevent(XIDeviceEvent* event)
event->root, event->event, event->child);
}
-static void print_devicechangedevent(Display *dpy, XIDeviceChangedEvent *event)
+static void print_devicechangedevent(Display *display, XIDeviceChangedEvent *event)
{
printf(" device: %d (%d)\n", event->deviceid, event->sourceid);
printf(" reason: %s\n", (event->reason == XISlaveSwitch) ? "SlaveSwitch" :
"DeviceChanged");
- print_classes_xi2(dpy, event->classes, event->num_classes);
+ print_classes_xi2(display, event->classes, event->num_classes);
}
static void print_hierarchychangedevent(XIHierarchyEvent *event)
@@ -235,49 +235,6 @@ static void print_propertyevent(Display *display, XIPropertyEvent* event)
XFree(name);
}
-void
-test_sync_grab(Display *display, Window win)
-{
- int loop = 3;
- int rc;
- XIEventMask mask;
-
- /* Select for motion events */
- mask.deviceid = XIAllDevices;
- mask.mask_len = 2;
- mask.mask = calloc(2, sizeof(char));
- XISetMask(mask.mask, XI_ButtonPress);
-
- if ((rc = XIGrabDevice(display, 2, win, CurrentTime, None, GrabModeSync,
- GrabModeAsync, False, &mask)) != GrabSuccess)
- {
- fprintf(stderr, "Grab failed with %d\n", rc);
- return;
- }
- free(mask.mask);
-
- XSync(display, True);
- XIAllowEvents(display, 2, SyncPointer, CurrentTime);
- XFlush(display);
-
- printf("Holding sync grab for %d button presses.\n", loop);
-
- while(loop--)
- {
- XIEvent ev;
-
- XNextEvent(display, (XEvent*)&ev);
- if (ev.type == GenericEvent && ev.extension == xi_opcode )
- {
- XIDeviceEvent *event = (XIDeviceEvent*)&ev;
- print_deviceevent(event);
- XIAllowEvents(display, 2, SyncPointer, CurrentTime);
- }
- }
-
- XIUngrabDevice(display, 2, CurrentTime);
- printf("Done\n");
-}
static const char* type_to_name(int evtype)
{
@@ -313,48 +270,167 @@ static const char* type_to_name(int evtype)
return name;
}
+static void
+print_classes_xi2(Display* display, XIAnyClassInfo **classes,
+ int num_classes)
+{
+ int i, j;
+
+ printf("\tReporting %d classes:\n", num_classes);
+ for (i = 0; i < num_classes; i++)
+ {
+ printf("\t\tClass originated from: %d. Type: ", classes[i]->sourceid);
+ switch(classes[i]->type)
+ {
+ case XIButtonClass:
+ {
+ XIButtonClassInfo *b = (XIButtonClassInfo*)classes[i];
+ char *name;
+ printf("XIButtonClass\n");
+ printf("\t\tButtons supported: %d\n", b->num_buttons);
+ printf("\t\tButton labels:");
+ for (j = 0; j < b->num_buttons; j++)
+ {
+ name = (b->labels[j]) ? XGetAtomName(display, b->labels[j]) : NULL;
+ if (name)
+ printf(" \"%s\"", name);
+ else
+ printf(" None");
+ XFree(name);
+ }
+ printf("\n");
+ printf("\t\tButton state:");
+ for (j = 0; j < b->state.mask_len * 8; j++)
+ if (XIMaskIsSet(b->state.mask, j))
+ printf(" %d", j);
+ printf("\n");
+
+ }
+ break;
+ case XIKeyClass:
+ {
+ XIKeyClassInfo *k = (XIKeyClassInfo*)classes[i];
+ printf("XIKeyClass\n");
+ printf("\t\tKeycodes supported: %d\n", k->num_keycodes);
+ }
+ break;
+ case XIValuatorClass:
+ {
+ XIValuatorClassInfo *v = (XIValuatorClassInfo*)classes[i];
+ char *name = v->label ? XGetAtomName(display, v->label) : NULL;
+
+ /* Bug in X servers 1.7..1.8.1, mode was | OutOfProximity */
+ v->mode &= DeviceMode;
+
+ printf("XIValuatorClass\n");
+ printf("\t\tDetail for Valuator %d:\n", v->number);
+ printf("\t\t Label: %s\n", (name) ? name : "None");
+ printf("\t\t Range: %f - %f\n", v->min, v->max);
+ printf("\t\t Resolution: %d units/m\n", v->resolution);
+ printf("\t\t Mode: %s\n", v->mode == Absolute ? "absolute" :
+ "relative");
+ if (v->mode == Absolute)
+ printf("\t\t Current value: %f\n", v->value);
+ XFree(name);
+ }
+ break;
+#if HAVE_XI21
+ case XIScrollClass:
+ {
+ XIScrollClassInfo *s = (XIScrollClassInfo*)classes[i];
+
+ printf("XIScrollClass\n");
+ printf("\t\tScroll info for Valuator %d\n", s->number);
+ printf("\t\t type: %d (%s)\n", s->scroll_type,
+ (s->scroll_type == XIScrollTypeHorizontal) ? "horizontal" :
+ (s->scroll_type == XIScrollTypeVertical) ? "vertical" : "unknown");
+ printf("\t\t increment: %f\n", s->increment);
+ printf("\t\t flags: 0x%x", s->flags);
+ if (s->flags) {
+ printf(" (");
+ if (s->flags & XIScrollFlagNoEmulation)
+ printf(" no-emulation ");
+ if (s->flags & XIScrollFlagPreferred)
+ printf(" preferred ");
+ printf(")");
+ }
+ printf("\n");
+ }
+ break;
+#endif
+#if HAVE_XI22
+ case XITouchClass:
+ {
+ XITouchClassInfo *t = (XITouchClassInfo*)classes[i];
+
+ printf("XITouchClass\n");
+ printf("\t\tTouch mode: %s\n",
+ (t->mode == XIDirectTouch) ? "direct" : "dependent");
+ printf("\t\tMax number of touches: %d\n", t->num_touches);
+ }
+#endif
+ }
+ }
+
+ printf("\n");
+}
-int
-test_xi2(Display *display,
- int argc,
- char *argv[],
- char *name,
- char *desc)
+static int
+xinput_version(Display *display)
{
- XIEventMask mask[2];
- XIEventMask *m;
- Window win;
- int deviceid = -1;
- int use_root = 0;
- int rc;
+ XExtensionVersion *version;
+ int vers = 0;
+
+ version = XGetExtensionVersion(display, INAME);
+
+ if (version && (version != (XExtensionVersion*) NoSuchExtension)) {
+ vers = version->major_version;
+ XFree(version);
+ }
- setvbuf(stdout, NULL, _IOLBF, 0);
+#if HAVE_XI2
+ /* Announce our supported version so the server treats us correctly. */
+ if (vers >= XI_2_Major)
+ {
+ int maj = 2,
+ min = 0;
- if (argc >= 1 && strcmp(argv[0], "--root") == 0) {
- use_root = 1;
+#if HAVE_XI22
+ min = 2;
+#elif HAVE_XI21
+ min = 1;
+#endif
- argc--;
- argv++;
+ XIQueryVersion(display, &maj, &min);
}
+#endif
- rc = list(display, argc, argv, name, desc);
- if (rc != EXIT_SUCCESS)
- return rc;
+ return vers;
+}
- if (use_root)
- win = DefaultRootWindow(display);
- else
- win = create_win(display);
- if (argc >= 1) {
- XIDeviceInfo *info;
- info = xi2_find_device_info(display, argv[0]);
- deviceid = info->deviceid;
+void
+xinput_init(Display *display, Window win)
+{
+ XIEventMask mask[2];
+ XIEventMask *m;
+ int event, error;
+
+ if (!XQueryExtension(display, "XInputExtension", &xi_opcode, &event, &error)) {
+ fprintf(stderr, "X Input extension not available.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (!xinput_version(display)) {
+ fprintf(stderr, "%s extension not available\n", INAME);
+ exit(EXIT_FAILURE);
}
+ win = DefaultRootWindow(display);
+
/* Select for motion events */
m = &mask[0];
- m->deviceid = (deviceid == -1) ? XIAllDevices : deviceid;
+ m->deviceid = XIAllDevices;
m->mask_len = XIMaskLen(XI_LASTEVENT);
m->mask = calloc(m->mask_len, sizeof(char));
XISetMask(m->mask, XI_ButtonPress);
@@ -372,12 +448,11 @@ test_xi2(Display *display,
XISetMask(m->mask, XI_TouchUpdate);
XISetMask(m->mask, XI_TouchEnd);
#endif
- if (m->deviceid == XIAllDevices)
- XISetMask(m->mask, XI_HierarchyChanged);
+ XISetMask(m->mask, XI_HierarchyChanged);
XISetMask(m->mask, XI_PropertyEvent);
m = &mask[1];
- m->deviceid = (deviceid == -1) ? XIAllMasterDevices : deviceid;
+ m->deviceid = XIAllMasterDevices;
m->mask_len = XIMaskLen(XI_LASTEVENT);
m->mask = calloc(m->mask_len, sizeof(char));
XISetMask(m->mask, XI_RawKeyPress);
@@ -391,74 +466,46 @@ test_xi2(Display *display,
XISetMask(m->mask, XI_RawTouchEnd);
#endif
- XISelectEvents(display, win, &mask[0], use_root ? 2 : 1);
- if (!use_root) {
- XISelectEvents(display, DefaultRootWindow(display), &mask[1], 1);
- XMapWindow(display, win);
- }
+ XISelectEvents(display, win, &mask[0], 2);
XSync(display, False);
free(mask[0].mask);
free(mask[1].mask);
+}
- if (!use_root) {
- XEvent event;
- XMaskEvent(display, ExposureMask, &event);
- XSelectInput(display, win, 0);
- }
-
- /*
- test_sync_grab(display, win);
- */
-
- while(1)
+void
+xinput_dump(Display *display, XGenericEventCookie *cookie)
+{
+ printf("EVENT type %d (%s)\n", cookie->evtype, type_to_name(cookie->evtype));
+ switch (cookie->evtype)
{
- XEvent ev;
- XGenericEventCookie *cookie = (XGenericEventCookie*)&ev.xcookie;
- XNextEvent(display, (XEvent*)&ev);
-
- if (XGetEventData(display, cookie) &&
- cookie->type == GenericEvent &&
- cookie->extension == xi_opcode)
- {
- printf("EVENT type %d (%s)\n", cookie->evtype, type_to_name(cookie->evtype));
- switch (cookie->evtype)
- {
- case XI_DeviceChanged:
- print_devicechangedevent(display, cookie->data);
- break;
- case XI_HierarchyChanged:
- print_hierarchychangedevent(cookie->data);
- break;
- case XI_RawKeyPress:
- case XI_RawKeyRelease:
- case XI_RawButtonPress:
- case XI_RawButtonRelease:
- case XI_RawMotion:
- case XI_RawTouchBegin:
- case XI_RawTouchUpdate:
- case XI_RawTouchEnd:
- print_rawevent(cookie->data);
- break;
- case XI_Enter:
- case XI_Leave:
- case XI_FocusIn:
- case XI_FocusOut:
- print_enterleave(cookie->data);
- break;
- case XI_PropertyEvent:
- print_propertyevent(display, cookie->data);
- break;
- default:
- print_deviceevent(cookie->data);
- break;
- }
- }
-
- XFreeEventData(display, cookie);
+ case XI_DeviceChanged:
+ print_devicechangedevent(display, cookie->data);
+ break;
+ case XI_HierarchyChanged:
+ print_hierarchychangedevent(cookie->data);
+ break;
+ case XI_RawKeyPress:
+ case XI_RawKeyRelease:
+ case XI_RawButtonPress:
+ case XI_RawButtonRelease:
+ case XI_RawMotion:
+ case XI_RawTouchBegin:
+ case XI_RawTouchUpdate:
+ case XI_RawTouchEnd:
+ print_rawevent(cookie->data);
+ break;
+ case XI_Enter:
+ case XI_Leave:
+ case XI_FocusIn:
+ case XI_FocusOut:
+ print_enterleave(cookie->data);
+ break;
+ case XI_PropertyEvent:
+ print_propertyevent(display, cookie->data);
+ break;
+ default:
+ print_deviceevent(cookie->data);
+ break;
}
-
- XDestroyWindow(display, win);
-
- return EXIT_SUCCESS;
}
diff --git a/xev.c b/xev.c
index ab3a874..3146d81 100644
--- a/xev.c
+++ b/xev.c
@@ -866,10 +866,8 @@ xev_dump(XEvent *event)
prologue (event, "MappingNotify");
do_MappingNotify (event);
break;
-#if 0
default:
- printf ("Unknown event type %d\n", event.type);
+ printf ("Unknown event type %d\n", event->type);
break;
-#endif
}
}