title: Blocking a specific input device in Xorg apps, using xcb_wait_for_event only
body: <p>There is a bug in Qt in which multiple touch screens causes Qt to be in an inconsistent state. More about the issue <a href="https://bugreports.qt.io/browse/QTBUG-73708" rel="nofollow noreferrer">here</a>.</p>
  
  <p>As a short-term patch, I'd to use event filters (which Qt provides for xcb events) to prevent multiple devices from being processed by Qt at a time.</p>
  
  <p>The steps would be as followed.</p>
  
  <ol>
  <li>A sequence of events for input is beginning (mouse button down, touch press, etc).</li>
  <li>Block all other events for devices that don't belong to the current device being used.</li>
  <li>When the sequence of events is completed, Resume events for all devices, starting back at step 1.</li>
  </ol>
  
  <p>Effectively, I want to gate the events, so that only one device can be used at a time. I'm hoping this get's around Qt's bug.</p>
  
  <p>First, I am trying to just filter events for a hard-coded device to see if this even gets around Qt's bug, but it doesn't.</p>
  
  <pre class="lang-cpp prettyprint-override"><code>class DuplicateHardwareEventFilter : public QAbstractNativeEventFilter
  {
  public:
      DuplicateHardwareEventFilter() {}
      bool nativeEventFilter(const QByteArray &amp;eventType, void *message, long *) override
      {
          if (eventType == "xcb_generic_event_t") {
              xcb_generic_event_t* ev = static_cast&lt;xcb_generic_event_t *&gt;(message);
              uint responseType = ev-&gt;response_type &amp; ~0x80;
  
              if(responseType == XCB_GE_GENERIC) {
                  xcb_ge_event_t* gev = reinterpret_cast&lt;xcb_ge_event_t*&gt;(ev);
  
                  // assume input event
                  xcb_input_button_press_event_t* xiEvent = reinterpret_cast&lt;xcb_input_button_press_event_t*&gt;(ev);
  
                  if(xiEvent-&gt;event_type == XCB_INPUT_DEVICE_CHANGED) {
                      auto inputChangedEvent = reinterpret_cast&lt;xcb_input_device_changed_event_t *&gt;(gev);
                      if(inputChangedEvent-&gt;sourceid == 11) {
                          return true;
                      }
                      qDebug("xcb device changed: %d source: %d", xiEvent-&gt;deviceid, inputChangedEvent-&gt;sourceid);
                      return false;
                  }
  
                  if(xiEvent-&gt;event_type == XCB_INPUT_MOTION) {
                      auto inputMotionEvent = reinterpret_cast&lt;xcb_input_motion_event_t*&gt;(gev);
                      if(inputMotionEvent-&gt;sourceid == 11) {
                          return true;
                      }
                      qDebug("xcb motion: %d source: %d", inputMotionEvent-&gt;deviceid, inputMotionEvent-&gt;sourceid);
                      return false;
                  }
  
                  if(xiEvent-&gt;event_type == XCB_INPUT_ENTER) {
                      auto inputEnterEvent = reinterpret_cast&lt;xcb_input_enter_event_t*&gt;(gev);
                      if(inputEnterEvent-&gt;sourceid == 11) {
                          return true;
                      }
                      qDebug("xcb enter: %d source: %d", inputEnterEvent-&gt;deviceid, inputEnterEvent-&gt;sourceid);
                      return false;
                  }
  
                  if(xiEvent-&gt;event_type == XCB_INPUT_LEAVE) {
                      auto inputLeaveEvent = reinterpret_cast&lt;xcb_input_leave_event_t*&gt;(gev);
                      qDebug("xcb leave: %d source: %d", inputLeaveEvent-&gt;deviceid, inputLeaveEvent-&gt;sourceid);
                      return false;
                  }
  
                  if(xiEvent-&gt;event_type == XCB_INPUT_BUTTON_PRESS) {
                      auto buttonPressEvent = reinterpret_cast&lt;xcb_input_button_press_event_t*&gt;(gev);
                      qDebug("xcb buttonPress: %d source: %d", buttonPressEvent-&gt;deviceid, buttonPressEvent-&gt;sourceid);
                      return false;
                  }
  
                  if(xiEvent-&gt;event_type == XCB_INPUT_BUTTON_RELEASE) {
                      auto buttonReleaseEvent = reinterpret_cast&lt;xcb_input_button_release_event_t*&gt;(gev);
                      qDebug("xcb buttonRelease: %d source: %d", buttonReleaseEvent-&gt;deviceid, buttonReleaseEvent-&gt;sourceid);
                      return false;
                  }
  
                  if(xiEvent-&gt;event_type == XCB_INPUT_TOUCH_BEGIN) {
                      auto touchBeginEvent = reinterpret_cast&lt;xcb_input_touch_begin_event_t*&gt;(gev);
                      if(touchBeginEvent-&gt;sourceid == 11) {
                          return true;
                      }
                      qDebug("xcb touchBegin: %d source: %d", touchBeginEvent-&gt;deviceid, touchBeginEvent-&gt;sourceid);
                      return false;
                  }
  
                  if(xiEvent-&gt;event_type == XCB_INPUT_TOUCH_UPDATE) {
                      auto touchUpdateEvent = reinterpret_cast&lt;xcb_input_touch_update_event_t*&gt;(gev);
                      if(touchUpdateEvent-&gt;sourceid == 11) {
                          return true;
                      }
                      qDebug("xcb touchUpdate: %d source: %d", touchUpdateEvent-&gt;deviceid, touchUpdateEvent-&gt;sourceid);
                      return false;
                  }
  
                  if(xiEvent-&gt;event_type == XCB_INPUT_TOUCH_END) {
                      auto touchEndEvent = reinterpret_cast&lt;xcb_input_touch_end_event_t*&gt;(gev);
                      if(touchEndEvent-&gt;sourceid == 11) {
                          return true;
                      }
                      qDebug("touchEnd: %d source: %d", touchEndEvent-&gt;deviceid, touchEndEvent-&gt;sourceid);
                      return false;
                  }
  
                  if(xiEvent-&gt;event_type == XCB_INPUT_PROPERTY) {
                      auto propertyEvent = reinterpret_cast&lt;xcb_input_property_event_t*&gt;(gev);
                      qDebug("property: %d", propertyEvent-&gt;deviceid);
                      return false;
                  }
  
                  return false;
              }
          }
          return false;
      }
  };
  </code></pre>
  
  <p>Qt still get's into it's quirky state.</p>
  
  <p><strong>How do I block a device completely, with filtering of the events of <code>xcb_wait_for_event</code>?</strong></p>