Блокировка определенного устройства ввода в приложениях Xorg с использованием только xcb_wait_for_event - PullRequest
0 голосов
/ 10 февраля 2019

В Qt есть ошибка, из-за которой несколько сенсорных экранов приводят к тому, что Qt находится в несовместимом состоянии.Подробнее о проблеме здесь .

В качестве краткосрочного патча я бы использовал фильтры событий (которые Qt предоставляет для событий xcb), чтобы предотвратить обработку нескольких устройств Qt по адресувремя.

Шаги будут следующими:

  1. Начинается последовательность событий для ввода (нажатие кнопки мыши, касание и т. д.).
  2. Заблокируйте все другие события для устройств, которые не принадлежат текущему используемому устройству.
  3. Когда последовательность событий завершена, возобновите события для всех устройств, начиная с шага 1.

По сути, я хочу контролировать события, чтобы одновременно можно было использовать только одно устройство.Я надеюсь, что это связано с ошибкой Qt.

Во-первых, я пытаюсь просто отфильтровать события для жестко запрограммированного устройства, чтобы посмотреть, сможет ли это вообще исправить ошибку Qt, но это не так.

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 все еще входит в свое странное состояние.

Как полностью заблокировать устройство с фильтрацией событий xcb_wait_for_event?

1 Ответ

0 голосов
/ 11 февраля 2019

Я не понимаю точно в чем ваша проблема, так как я не понимаю, что делает несовместимое состояние, но здесь определенно возможный путь, если вы впадаете в отчаяние.

Для Wayland я хотел создать API, который бы взаимодействовал с моим сенсорным экраном, что-то вроде autohotkey или xdotools.Используя ядро ​​Linux uinput, я добился замечательных успехов, взаимодействуя с устройством и заставляя его выдавать команды, и действительно ручаюсь за то, как легко было работать.Просто посмотрите здесь:

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

Определенно стоит создать API и, возможно, даже драйвер виртуального устройства.

...