0

There is a bug in Qt in which multiple touch screens causes Qt to be in an inconsistent state. More about the issue here.

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.

The steps would be as followed.

  1. A sequence of events for input is beginning (mouse button down, touch press, etc).
  2. Block all other events for devices that don't belong to the current device being used.
  3. When the sequence of events is completed, Resume events for all devices, starting back at step 1.

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.

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.

class DuplicateHardwareEventFilter : public QAbstractNativeEventFilter
{
public:
    DuplicateHardwareEventFilter() {}
    bool nativeEventFilter(const QByteArray &eventType, void *message, long *) override
    {
        if (eventType == "xcb_generic_event_t") {
            xcb_generic_event_t* ev = static_cast<xcb_generic_event_t *>(message);
            uint responseType = ev->response_type & ~0x80;

            if(responseType == XCB_GE_GENERIC) {
                xcb_ge_event_t* gev = reinterpret_cast<xcb_ge_event_t*>(ev);

                // assume input event
                xcb_input_button_press_event_t* xiEvent = reinterpret_cast<xcb_input_button_press_event_t*>(ev);

                if(xiEvent->event_type == XCB_INPUT_DEVICE_CHANGED) {
                    auto inputChangedEvent = reinterpret_cast<xcb_input_device_changed_event_t *>(gev);
                    if(inputChangedEvent->sourceid == 11) {
                        return true;
                    }
                    qDebug("xcb device changed: %d source: %d", xiEvent->deviceid, inputChangedEvent->sourceid);
                    return false;
                }

                if(xiEvent->event_type == XCB_INPUT_MOTION) {
                    auto inputMotionEvent = reinterpret_cast<xcb_input_motion_event_t*>(gev);
                    if(inputMotionEvent->sourceid == 11) {
                        return true;
                    }
                    qDebug("xcb motion: %d source: %d", inputMotionEvent->deviceid, inputMotionEvent->sourceid);
                    return false;
                }

                if(xiEvent->event_type == XCB_INPUT_ENTER) {
                    auto inputEnterEvent = reinterpret_cast<xcb_input_enter_event_t*>(gev);
                    if(inputEnterEvent->sourceid == 11) {
                        return true;
                    }
                    qDebug("xcb enter: %d source: %d", inputEnterEvent->deviceid, inputEnterEvent->sourceid);
                    return false;
                }

                if(xiEvent->event_type == XCB_INPUT_LEAVE) {
                    auto inputLeaveEvent = reinterpret_cast<xcb_input_leave_event_t*>(gev);
                    qDebug("xcb leave: %d source: %d", inputLeaveEvent->deviceid, inputLeaveEvent->sourceid);
                    return false;
                }

                if(xiEvent->event_type == XCB_INPUT_BUTTON_PRESS) {
                    auto buttonPressEvent = reinterpret_cast<xcb_input_button_press_event_t*>(gev);
                    qDebug("xcb buttonPress: %d source: %d", buttonPressEvent->deviceid, buttonPressEvent->sourceid);
                    return false;
                }

                if(xiEvent->event_type == XCB_INPUT_BUTTON_RELEASE) {
                    auto buttonReleaseEvent = reinterpret_cast<xcb_input_button_release_event_t*>(gev);
                    qDebug("xcb buttonRelease: %d source: %d", buttonReleaseEvent->deviceid, buttonReleaseEvent->sourceid);
                    return false;
                }

                if(xiEvent->event_type == XCB_INPUT_TOUCH_BEGIN) {
                    auto touchBeginEvent = reinterpret_cast<xcb_input_touch_begin_event_t*>(gev);
                    if(touchBeginEvent->sourceid == 11) {
                        return true;
                    }
                    qDebug("xcb touchBegin: %d source: %d", touchBeginEvent->deviceid, touchBeginEvent->sourceid);
                    return false;
                }

                if(xiEvent->event_type == XCB_INPUT_TOUCH_UPDATE) {
                    auto touchUpdateEvent = reinterpret_cast<xcb_input_touch_update_event_t*>(gev);
                    if(touchUpdateEvent->sourceid == 11) {
                        return true;
                    }
                    qDebug("xcb touchUpdate: %d source: %d", touchUpdateEvent->deviceid, touchUpdateEvent->sourceid);
                    return false;
                }

                if(xiEvent->event_type == XCB_INPUT_TOUCH_END) {
                    auto touchEndEvent = reinterpret_cast<xcb_input_touch_end_event_t*>(gev);
                    if(touchEndEvent->sourceid == 11) {
                        return true;
                    }
                    qDebug("touchEnd: %d source: %d", touchEndEvent->deviceid, touchEndEvent->sourceid);
                    return false;
                }

                if(xiEvent->event_type == XCB_INPUT_PROPERTY) {
                    auto propertyEvent = reinterpret_cast<xcb_input_property_event_t*>(gev);
                    qDebug("property: %d", propertyEvent->deviceid);
                    return false;
                }

                return false;
            }
        }
        return false;
    }
};

Qt still get's into it's quirky state.

How do I block a device completely, with filtering of the events of xcb_wait_for_event?

Paul Knopf
  • 9,568
  • 23
  • 77
  • 142

1 Answers1

1

I do not grasp exactly what your issue is here, as I do not grasp what the inconsistent state does, but here is definitely a possible avenue if you get desperate.

For wayland, I wanted to create an API that would interface with my touchscreen, something like autohotkey or xdotools. Using the linux Kernel's uinput, I achieved remarkable success, interfacing with the device, and having it issue commands, and really vouch for how easy it was to get working. Just take a look here:

https://www.kernel.org/doc/html/v4.12/input/uinput.html

Definitely worth building an API, and perhaps even a virtual device driver.

Anon
  • 2,267
  • 3
  • 34
  • 51