]> diplodocus.org Git - xorg-xinput/blobdiff - src/test_xi2.c
gitlab CI: stop requiring Signed-off-by in commits
[xorg-xinput] / src / test_xi2.c
index b03b762559d0132012f4693d868cf2b6a3fc5903..5f97258c581350162dc9f62df65ea4db0ae540ed 100644 (file)
@@ -29,9 +29,6 @@
 extern void print_classes_xi2(Display*, XIAnyClassInfo **classes,
                               int num_classes);
 
-#define BitIsOn(ptr, bit) (((unsigned char *) (ptr))[(bit)>>3] & (1 << ((bit) & 7)))
-#define SetBit(ptr, bit)  (((unsigned char *) (ptr))[(bit)>>3] |= (1 << ((bit) & 7)))
-
 static Window create_win(Display *dpy)
 {
     Window win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0, 200,
@@ -39,10 +36,8 @@ static Window create_win(Display *dpy)
     Window subwindow = XCreateSimpleWindow(dpy, win, 50, 50, 50, 50, 0, 0,
             BlackPixel(dpy, 0));
 
-    XSelectInput(dpy, win, ExposureMask);
     XMapWindow(dpy, subwindow);
-    XMapWindow(dpy, win);
-    XFlush(dpy);
+    XSelectInput(dpy, win, ExposureMask);
     return win;
 }
 
@@ -52,38 +47,61 @@ static void print_deviceevent(XIDeviceEvent* event)
     int i;
 
     printf("    device: %d (%d)\n", event->deviceid, event->sourceid);
+    printf("    time: %ld\n", event->time);
     printf("    detail: %d\n", event->detail);
+    switch(event->evtype) {
+        case XI_KeyPress:
+        case XI_KeyRelease:
+            printf("    flags: %s\n", (event->flags & XIKeyRepeat) ?  "repeat" : "");
+            break;
+#if HAVE_XI21
+        case XI_ButtonPress:
+        case XI_ButtonRelease:
+        case XI_Motion:
+            printf("    flags: %s\n", (event->flags & XIPointerEmulated) ?  "emulated" : "");
+            break;
+#endif
+#if HAVE_XI22
+        case XI_TouchBegin:
+        case XI_TouchUpdate:
+        case XI_TouchEnd:
+            printf("    flags:%s%s\n",
+                   (event->flags & XITouchPendingEnd) ?  " pending_end" : "",
+                   (event->flags & XITouchEmulatingPointer) ?  " emulating" : "");
+            break;
+#endif
+    }
 
     printf("    root: %.2f/%.2f\n", event->root_x, event->root_y);
-    printf("    event: %.2f/%.2f\n", event->event_x, event->event_x);
+    printf("    event: %.2f/%.2f\n", event->event_x, event->event_y);
 
     printf("    buttons:");
-    for (i = 0; i < event->buttons->mask_len * 8; i++)
-        if (BitIsOn(event->buttons->mask, i))
+    for (i = 0; i < event->buttons.mask_len * 8; i++)
+        if (XIMaskIsSet(event->buttons.mask, i))
             printf(" %d", i);
     printf("\n");
 
-    printf("    modifiers: locked 0x%x latched 0x%x base 0x%x\n",
-            event->mods->locked, event->mods->latched,
-            event->mods->base);
-    printf("    group: locked 0x%x latched 0x%x base 0x%x\n",
-            event->group->locked, event->group->latched,
-            event->group->base);
-    printf("    valuators:");
-
-    val = event->valuators->values;
-    for (i = 0; i < event->valuators->mask_len * 8; i++)
-        if (BitIsOn(event->valuators->mask, i))
-            printf(" %.2f", *val++);
-    printf("\n");
+    printf("    modifiers: locked %#x latched %#x base %#x effective: %#x\n",
+            event->mods.locked, event->mods.latched,
+            event->mods.base, event->mods.effective);
+    printf("    group: locked %#x latched %#x base %#x effective: %#x\n",
+            event->group.locked, event->group.latched,
+            event->group.base, event->group.effective);
+    printf("    valuators:\n");
 
-    printf("    windows: root 0x%lx event 0x%lx child 0x%ld\n",
+    val = event->valuators.values;
+    for (i = 0; i < event->valuators.mask_len * 8; i++)
+        if (XIMaskIsSet(event->valuators.mask, i))
+            printf("        %i: %.2f\n", i, *val++);
+
+    printf("    windows: root 0x%lx event 0x%lx child 0x%lx\n",
             event->root, event->event, event->child);
 }
 
 static void print_devicechangedevent(Display *dpy, XIDeviceChangedEvent *event)
 {
     printf("    device: %d (%d)\n", event->deviceid, event->sourceid);
+    printf("    time: %ld\n", event->time);
     printf("    reason: %s\n", (event->reason == XISlaveSwitch) ? "SlaveSwitch" :
                                 "DeviceChanged");
     print_classes_xi2(dpy, event->classes, event->num_classes);
@@ -92,6 +110,7 @@ static void print_devicechangedevent(Display *dpy, XIDeviceChangedEvent *event)
 static void print_hierarchychangedevent(XIHierarchyEvent *event)
 {
     int i;
+    printf("    time: %ld\n", event->time);
     printf("    Changes happened: %s %s %s %s %s %s %s %s\n",
             (event->flags & XIMasterAdded) ? "[new master]" : "",
             (event->flags & XIMasterRemoved) ? "[master removed]" : "",
@@ -102,14 +121,14 @@ static void print_hierarchychangedevent(XIHierarchyEvent *event)
             (event->flags & XIDeviceEnabled) ? "[device enabled]" : "",
             (event->flags & XIDeviceDisabled) ? "[device disabled]" : "");
 
-    for (i = 0; i < event->num_devices; i++)
+    for (i = 0; i < event->num_info; i++)
     {
-        char *use;
+        char *use = "<undefined>";
         switch(event->info[i].use)
         {
-            case XIMasterPointer: use = "master pointer";
+            case XIMasterPointer: use = "master pointer"; break;
             case XIMasterKeyboard: use = "master keyboard"; break;
-            case XISlavePointer: use = "slave pointer";
+            case XISlavePointer: use = "slave pointer"; break;
             case XISlaveKeyboard: use = "slave keyboard"; break;
             case XIFloatingSlave: use = "floating slave"; break;
                 break;
@@ -140,58 +159,73 @@ static void print_rawevent(XIRawEvent *event)
     int i;
     double *val, *raw_val;
 
-    printf("    device: %d\n", event->deviceid);
+    printf("    device: %d (%d)\n", event->deviceid, event->sourceid);
+    printf("    time:   %ld\n", event->time);
     printf("    detail: %d\n", event->detail);
-    printf("    valuators:\n");
+#if HAVE_XI21
+    switch(event->evtype) {
+        case XI_RawButtonPress:
+        case XI_RawButtonRelease:
+        case XI_RawMotion:
+            printf("    flags: %s\n", (event->flags & XIPointerEmulated) ?  "emulated" : "");
+            break;
+    }
+#endif
 
-    val = event->valuators->values;
+    printf("    valuators:\n");
+    val = event->valuators.values;
     raw_val = event->raw_values;
-    for (i = 0; i < event->valuators->mask_len * 8; i++)
-        if (BitIsOn(event->valuators->mask, i))
+    for (i = 0; i < event->valuators.mask_len * 8; i++)
+        if (XIMaskIsSet(event->valuators.mask, i))
             printf("         %2d: %.2f (%.2f)\n", i, *val++, *raw_val++);
     printf("\n");
 }
 
 static void print_enterleave(XILeaveEvent* event)
 {
-    char *mode, *detail;
+    char *mode = "<undefined>",
+         *detail = "<undefined>";
     int i;
 
+    printf("    device: %d (%d)\n", event->deviceid, event->sourceid);
+    printf("    time:   %ld\n", event->time);
     printf("    windows: root 0x%lx event 0x%lx child 0x%ld\n",
             event->root, event->event, event->child);
     switch(event->mode)
     {
-        case NotifyNormal:       mode = "NotifyNormal"; break;
-        case NotifyGrab:         mode = "NotifyGrab"; break;
-        case NotifyUngrab:       mode = "NotifyUngrab"; break;
-        case NotifyWhileGrabbed: mode = "NotifyWhileGrabbed"; break;
+        case XINotifyNormal:       mode = "NotifyNormal"; break;
+        case XINotifyGrab:         mode = "NotifyGrab"; break;
+        case XINotifyUngrab:       mode = "NotifyUngrab"; break;
+        case XINotifyWhileGrabbed: mode = "NotifyWhileGrabbed"; break;
+        case XINotifyPassiveGrab:  mode = "NotifyPassiveGrab"; break;
+        case XINotifyPassiveUngrab:mode = "NotifyPassiveUngrab"; break;
     }
     switch (event->detail)
     {
-        case NotifyAncestor: detail = "NotifyAncestor"; break;
-        case NotifyVirtual: detail = "NotifyVirtual"; break;
-        case NotifyInferior: detail = "NotifyInferior"; break;
-        case NotifyNonlinear: detail = "NotifyNonlinear"; break;
-        case NotifyNonlinearVirtual: detail = "NotifyNonlinearVirtual"; break;
-        case NotifyPointer: detail = "NotifyPointer"; break;
-        case NotifyPointerRoot: detail = "NotifyPointerRoot"; break;
-        case NotifyDetailNone: detail = "NotifyDetailNone"; break;
+        case XINotifyAncestor: detail = "NotifyAncestor"; break;
+        case XINotifyVirtual: detail = "NotifyVirtual"; break;
+        case XINotifyInferior: detail = "NotifyInferior"; break;
+        case XINotifyNonlinear: detail = "NotifyNonlinear"; break;
+        case XINotifyNonlinearVirtual: detail = "NotifyNonlinearVirtual"; break;
+        case XINotifyPointer: detail = "NotifyPointer"; break;
+        case XINotifyPointerRoot: detail = "NotifyPointerRoot"; break;
+        case XINotifyDetailNone: detail = "NotifyDetailNone"; break;
     }
     printf("    mode: %s (detail %s)\n", mode, detail);
     printf("    flags: %s %s\n", event->focus ? "[focus]" : "",
                                  event->same_screen ? "[same screen]" : "");
     printf("    buttons:");
-    for (i = 0; i < event->buttons->mask_len * 8; i++)
-        if (BitIsOn(event->buttons->mask, i))
+    for (i = 0; i < event->buttons.mask_len * 8; i++)
+        if (XIMaskIsSet(event->buttons.mask, i))
             printf(" %d", i);
     printf("\n");
 
-    printf("    modifiers: locked 0x%x latched 0x%x base 0x%x\n",
-            event->mods->locked, event->mods->latched,
-            event->mods->base);
-    printf("    group: locked 0x%x latched 0x%x base 0x%x\n",
-            event->group->locked, event->group->latched,
-            event->group->base);
+    printf("    modifiers: locked %#x latched %#x base %#x effective: %#x\n",
+            event->mods.locked, event->mods.latched,
+            event->mods.base, event->mods.effective);
+    printf("    group: locked %#x latched %#x base %#x effective: %#x\n",
+            event->group.locked, event->group.latched,
+            event->group.base, event->group.effective);
 
     printf("    root x/y:  %.2f / %.2f\n", event->root_x, event->root_y);
     printf("    event x/y: %.2f / %.2f\n", event->event_x, event->event_y);
@@ -201,6 +235,7 @@ static void print_enterleave(XILeaveEvent* event)
 static void print_propertyevent(Display *display, XIPropertyEvent* event)
 {
     char *changed;
+    char *name;
 
     if (event->what == XIPropertyDeleted)
         changed = "deleted";
@@ -208,10 +243,12 @@ static void print_propertyevent(Display *display, XIPropertyEvent* event)
         changed = "created";
     else
         changed = "modified";
-
-    printf("     property: %ld '%s'\n", event->property, XGetAtomName(display, event->property));
+    name = XGetAtomName(display, event->property);
+    printf("     time:   %ld\n", event->time);
+    printf("     property: %ld '%s'\n", event->property, name);
     printf("     changed: %s\n", changed);
 
+    XFree(name);
 }
 void
 test_sync_grab(Display *display, Window win)
@@ -224,7 +261,7 @@ test_sync_grab(Display *display, Window win)
     mask.deviceid = XIAllDevices;
     mask.mask_len = 2;
     mask.mask = calloc(2, sizeof(char));
-    SetBit(mask.mask, XI_ButtonPress);
+    XISetMask(mask.mask, XI_ButtonPress);
 
     if ((rc = XIGrabDevice(display, 2,  win, CurrentTime, None, GrabModeSync,
                            GrabModeAsync, False, &mask)) != GrabSuccess)
@@ -245,12 +282,11 @@ test_sync_grab(Display *display, Window win)
         XIEvent ev;
 
         XNextEvent(display, (XEvent*)&ev);
-        if (ev.type == GenericEvent)
+        if (ev.type == GenericEvent && ev.extension == xi_opcode )
         {
             XIDeviceEvent *event = (XIDeviceEvent*)&ev;
             print_deviceevent(event);
             XIAllowEvents(display, 2, SyncPointer, CurrentTime);
-            XIFreeEventData(&ev);
         }
     }
 
@@ -258,6 +294,41 @@ test_sync_grab(Display *display, Window win)
     printf("Done\n");
 }
 
+static const char* type_to_name(int evtype)
+{
+    const char *name;
+
+    switch(evtype) {
+        case XI_DeviceChanged:    name = "DeviceChanged";       break;
+        case XI_KeyPress:         name = "KeyPress";            break;
+        case XI_KeyRelease:       name = "KeyRelease";          break;
+        case XI_ButtonPress:      name = "ButtonPress";         break;
+        case XI_ButtonRelease:    name = "ButtonRelease";       break;
+        case XI_Motion:           name = "Motion";              break;
+        case XI_Enter:            name = "Enter";               break;
+        case XI_Leave:            name = "Leave";               break;
+        case XI_FocusIn:          name = "FocusIn";             break;
+        case XI_FocusOut:         name = "FocusOut";            break;
+        case XI_HierarchyChanged: name = "HierarchyChanged";    break;
+        case XI_PropertyEvent:    name = "PropertyEvent";       break;
+        case XI_RawKeyPress:      name = "RawKeyPress";         break;
+        case XI_RawKeyRelease:    name = "RawKeyRelease";       break;
+        case XI_RawButtonPress:   name = "RawButtonPress";      break;
+        case XI_RawButtonRelease: name = "RawButtonRelease";    break;
+        case XI_RawMotion:        name = "RawMotion";           break;
+        case XI_TouchBegin:       name = "TouchBegin";          break;
+        case XI_TouchUpdate:      name = "TouchUpdate";         break;
+        case XI_TouchEnd:         name = "TouchEnd";            break;
+        case XI_RawTouchBegin:    name = "RawTouchBegin";       break;
+        case XI_RawTouchUpdate:   name = "RawTouchUpdate";      break;
+        case XI_RawTouchEnd:      name = "RawTouchEnd";         break;
+        default:
+                                  name = "unknown event type"; break;
+    }
+    return name;
+}
+
+
 int
 test_xi2(Display       *display,
          int   argc,
@@ -265,59 +336,91 @@ test_xi2(Display  *display,
          char  *name,
          char  *desc)
 {
-    XIEventMask mask;
+    XIEventMask mask[2];
+    XIEventMask *m;
     Window win;
+    int deviceid = -1;
+    int use_root = 0;
+    int rc;
 
-    list(display, argc, argv, name, desc);
-    win = create_win(display);
+    setvbuf(stdout, NULL, _IOLBF, 0);
 
-    XSync(display, False);
+    if (argc >= 1 && strcmp(argv[0], "--root") == 0) {
+        use_root = 1;
 
-    /* Select for motion events */
-    mask.deviceid = XIAllDevices;
-    mask.mask_len = 2;
-    mask.mask = calloc(mask.mask_len, sizeof(char));
-    SetBit(mask.mask, XI_ButtonPress);
-    SetBit(mask.mask, XI_ButtonRelease);
-    SetBit(mask.mask, XI_KeyPress);
-    SetBit(mask.mask, XI_KeyRelease);
-    SetBit(mask.mask, XI_Motion);
-    SetBit(mask.mask, XI_DeviceChanged);
-    SetBit(mask.mask, XI_Enter);
-    SetBit(mask.mask, XI_Leave);
-    SetBit(mask.mask, XI_FocusIn);
-    SetBit(mask.mask, XI_FocusOut);
-    SetBit(mask.mask, XI_HierarchyChanged);
-    SetBit(mask.mask, XI_PropertyEvent);
-    XISelectEvents(display, win, &mask, 1);
-    XSync(display, False);
+        argc--;
+        argv++;
+    }
 
-    {
-        int modifiers[] = {0, 0x10, 0x1, 0x11};
-        int nmods = sizeof(modifiers)/sizeof(modifiers[0]);
-
-        mask.deviceid = 2;
-        memset(mask.mask, 0, 2);
-        SetBit(mask.mask, XI_KeyPress);
-        SetBit(mask.mask, XI_KeyRelease);
-        SetBit(mask.mask, XI_ButtonPress);
-        SetBit(mask.mask, XI_Motion);
-        XIGrabButton(display, 2, 1, win, None, GrabModeAsync, GrabModeAsync,
-                False, &mask, nmods, modifiers);
-        XIGrabKeysym(display, 3, 0x71, win, GrabModeAsync, GrabModeAsync,
-                False, &mask, nmods, modifiers);
-        XIUngrabButton(display, 3, 1, win, nmods - 2, &modifiers[2]);
-        XIUngrabKeysym(display, 3, 0x71, win, nmods - 2, &modifiers[2]);
+    rc = list(display, argc, argv, name, desc);
+    if (rc != EXIT_SUCCESS)
+        return rc;
+
+    if (use_root)
+        win = DefaultRootWindow(display);
+    else
+        win = create_win(display);
+
+    if (argc >= 1) {
+        XIDeviceInfo *info;
+        info = xi2_find_device_info(display, argv[0]);
+        /* info is alway valid, the list() call exits if the device
+           cannot be found, but let's shut up coverity */
+        if (!info)
+            return EXIT_FAILURE;
+        deviceid = info->deviceid;
     }
 
-    mask.deviceid = XIAllMasterDevices;
-    memset(mask.mask, 0, 2);
-    SetBit(mask.mask, XI_RawEvent);
-    XISelectEvents(display, DefaultRootWindow(display), &mask, 1);
+    /* Select for motion events */
+    m = &mask[0];
+    m->deviceid = (deviceid == -1) ? XIAllDevices : deviceid;
+    m->mask_len = XIMaskLen(XI_LASTEVENT);
+    m->mask = calloc(m->mask_len, sizeof(char));
+    XISetMask(m->mask, XI_ButtonPress);
+    XISetMask(m->mask, XI_ButtonRelease);
+    XISetMask(m->mask, XI_KeyPress);
+    XISetMask(m->mask, XI_KeyRelease);
+    XISetMask(m->mask, XI_Motion);
+    XISetMask(m->mask, XI_DeviceChanged);
+    XISetMask(m->mask, XI_Enter);
+    XISetMask(m->mask, XI_Leave);
+    XISetMask(m->mask, XI_FocusIn);
+    XISetMask(m->mask, XI_FocusOut);
+#if HAVE_XI22
+    XISetMask(m->mask, XI_TouchBegin);
+    XISetMask(m->mask, XI_TouchUpdate);
+    XISetMask(m->mask, XI_TouchEnd);
+#endif
+    if (m->deviceid == XIAllDevices)
+        XISetMask(m->mask, XI_HierarchyChanged);
+    XISetMask(m->mask, XI_PropertyEvent);
+
+    m = &mask[1];
+    m->deviceid = (deviceid == -1) ? XIAllMasterDevices : deviceid;
+    m->mask_len = XIMaskLen(XI_LASTEVENT);
+    m->mask = calloc(m->mask_len, sizeof(char));
+    XISetMask(m->mask, XI_RawKeyPress);
+    XISetMask(m->mask, XI_RawKeyRelease);
+    XISetMask(m->mask, XI_RawButtonPress);
+    XISetMask(m->mask, XI_RawButtonRelease);
+    XISetMask(m->mask, XI_RawMotion);
+#if HAVE_XI22
+    XISetMask(m->mask, XI_RawTouchBegin);
+    XISetMask(m->mask, XI_RawTouchUpdate);
+    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);
+    }
+    XSync(display, False);
 
-    free(mask.mask);
+    free(mask[0].mask);
+    free(mask[1].mask);
 
-    {
+    if (!use_root) {
         XEvent event;
         XMaskEvent(display, ExposureMask, &event);
         XSelectInput(display, win, 0);
@@ -329,41 +432,49 @@ test_xi2(Display  *display,
 
     while(1)
     {
-        XIEvent ev;
+        XEvent ev;
+        XGenericEventCookie *cookie = (XGenericEventCookie*)&ev.xcookie;
         XNextEvent(display, (XEvent*)&ev);
-        if (ev.type == GenericEvent)
-        {
-            XIDeviceEvent *event = (XIDeviceEvent*)&ev;
 
-            printf("EVENT type %d\n", event->evtype);
-            switch (event->evtype)
+        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,
-                                             (XIDeviceChangedEvent*)event);
+                    print_devicechangedevent(display, cookie->data);
                     break;
                 case XI_HierarchyChanged:
-                    print_hierarchychangedevent((XIHierarchyEvent*)event);
+                    print_hierarchychangedevent(cookie->data);
                     break;
-                case XI_RawEvent:
-                    print_rawevent((XIRawEvent*)event);
+                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((XILeaveEvent*)event);
+                    print_enterleave(cookie->data);
                     break;
                 case XI_PropertyEvent:
-                    print_propertyevent(display, (XIPropertyEvent*)event);
+                    print_propertyevent(display, cookie->data);
                     break;
                 default:
-                    print_deviceevent(event);
+                    print_deviceevent(cookie->data);
                     break;
             }
         }
 
-        XIFreeEventData(&ev);
+        XFreeEventData(display, cookie);
     }
 
     XDestroyWindow(display, win);