XI_ButtonPress/XI_ButtonRelease events lost from master devices

Naman Dixit namandixit at cse.iitb.ac.in
Wed Dec 18 11:47:17 UTC 2019


On Fedora 31, when using XInput2 to get mouse events, all the non-raw events 
seem to get lost if the `deviceid` in mask is  XIAllMasterDevices. The 
following code is a sample which reproduces the problem; in this example, the 
RawMotion events are received properly while the ButtonPressed/ButtonReleased 
events seem to get lost. However, if the `deviceid` is changed to 
XIAllDevices, then all the events are delivered. This experiment was done on 
Dell Inspiron 7572 with the default touchpad.

Can someone please point out the bug in the following code sample? Also, is 
there a better source of documentation for the library other than Peter 
Hutterer's blog?

Thank you.


// Compile: gcc xinput2.c -lX11 -lXi -o xinput2
#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/extensions/XInput2.h>

int main(int argc, char** args)
{
     int width = 800;
     int height = 600;

     Display* display = XOpenDisplay(0);

     int root = DefaultRootWindow(display);
     int defaultScreen = DefaultScreen(display);
     int screenBitDepth = 24;
     XVisualInfo visinfo = {};
     XMatchVisualInfo(display, defaultScreen, screenBitDepth, TrueColor, 
&visinfo);

     XSetWindowAttributes windowAttr;
     windowAttr.background_pixel = 0;
     windowAttr.colormap = XCreateColormap(display, root,
                                           visinfo.visual, AllocNone);

     windowAttr.event_mask = (StructureNotifyMask |
                              KeyPressMask | KeyReleaseMask |
                              ButtonPressMask | ButtonReleaseMask);
     unsigned long attributeMask = CWBackPixel | CWColormap | CWEventMask;
     Window window = XCreateWindow(display, root,
                                   0, 0,
                                   width, height, 0,
                                   visinfo.depth, InputOutput,
                                   visinfo.visual, attributeMask, 
&windowAttr);

     XMapWindow(display, window);
     XFlush(display);

     Atom WM_DELETE_WINDOW = XInternAtom(display, "WM_DELETE_WINDOW", False);
     XSetWMProtocols(display, window, &WM_DELETE_WINDOW, 1);


     int xi2_event, xi2_error, xi2_opcode;
     Bool exists_success = XQueryExtension(display, "XInputExtension",
                                           &xi2_opcode, &xi2_event, 
&xi2_error);
     if (exists_success == False) {
         return -1;
     }

     int xi2_major = 2, xi2_minor = 3;
     Status version_status = XIQueryVersion(display, &xi2_major, &xi2_minor);
     if (version_status == BadRequest) {
         return -1;
     }

     XIEventMask xi2_eventmask = {0};
     unsigned char xi2_mask[(XI_LASTEVENT + 7) / 8] = {0};

     XISetMask(xi2_mask, XI_RawMotion);
     XISetMask(xi2_mask, XI_ButtonPress);
     XISetMask(xi2_mask, XI_ButtonRelease);

     xi2_eventmask.deviceid = XIAllMasterDevices;
//    xi2_eventmask.deviceid = XIAllDevices;
     xi2_eventmask.mask_len = sizeof(xi2_mask);
     xi2_eventmask.mask = xi2_mask;

     Status select_status = XISelectEvents(display, root, &xi2_eventmask, 1);
     if (select_status != Success) {
         return -1;
     }

     int windowOpen = 1;
     while(windowOpen) {
         XEvent event = {0};
         while(XPending(display) > 0) {
             XNextEvent(display, &event);

             if (event.xcookie.type == GenericEvent &&
                 event.xcookie.extension == xi2_opcode &&
                 XGetEventData(display, &event.xcookie)) {

                 switch(event.xcookie.evtype) {
                     case XI_ButtonPress:
                     case XI_ButtonRelease: {
                         printf("Button\n");
                     } break;

                     case XI_RawMotion: {
                         printf("Motion\n");
                     } break;
                 }
             } else {
                 switch(event.type) {
                     case DestroyNotify: {
                         XDestroyWindowEvent* e = (XDestroyWindowEvent*) 
&event;
                         if(e->window == window) {
                             windowOpen = 0;
                         }
                     } break;

                     case ClientMessage: {
                         XClientMessageEvent* e = 
(XClientMessageEvent*)&event;
                         if((Atom)e->data.l[0] == WM_DELETE_WINDOW) {
                             XDestroyWindow(display, window);
                             windowOpen = 0;
                         }
                     } break;
                 }
             }
         }
     };

     return 0;
}


More information about the xorg mailing list