Обработка событий X11 с помощью Qt5

Я переношу свое приложение с Qt4 на Qt5.

Насколько мне известно, Qt5 больше не поддерживает обработку событий Xlib и использует события XCB (обработчик событий получает объект xcb_generic_event_t). Однако библиотека spnav, которую я использую, поддерживает только события X11 (она анализирует объект XEvent для получения необходимой информации). Можно ли обрабатывать события X11 в Qt5 или конвертировать xcb_generic_event_t в XEvent?

В Qt4 код выглядел так:

bool MyApplication::x11EventFilter(XEvent *event) 
{
    spnav_event sev;
    spnav_x11_event(event,&sev);

    if(sev.type == SPNAV_EVENT_MOTION) 
    {
           emit joystickPositionEvent(sev.motion.x,sev.motion.y,sev.motion.z,sev.motion.rx,sev.motion.ry,sev.motion.rz);
    } 
    else if(sev.type == SPNAV_EVENT_BUTTON)
    {   
        emit joystickButtonEvent(sev.button.bnum,sev.button.press!=0);
    }

    return false;   
}

person Lecko    schedule 30.03.2016    source источник
comment
Взгляните на это   -  person IAmInPLS    schedule 30.03.2016
comment
@АлексисП. Я пробовал это, но метод фильтра имеет следующий прототип. bool QAbstractNativeEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, long *result). void* message на самом деле является указателем на xcb_generic_event_t, и я не могу получить полезную информацию из этого типа объекта.   -  person Lecko    schedule 30.03.2016
comment
Вам придется включить X11/Xlib.h и вручную синтезировать XEvent из xcb_generic_event_t.   -  person Kuba hasn't forgotten Monica    schedule 30.03.2016
comment
@KubaOber Я понимаю это. Вопрос был в том, есть ли общий способ сделать это   -  person Lecko    schedule 31.03.2016
comment
Боюсь, это обычный способ сделать это :(   -  person Kuba hasn't forgotten Monica    schedule 31.03.2016


Ответы (1)


На случай, если другие столкнутся с той же проблемой: spnav_x11_event() требует копирования только пары полей - вот код, который я получил для FreeCAD:

spnav_event navEvent;

// Qt4 used XEvents in native event filters, but Qt5 changed to XCB.  The
// SpaceNavigator API only works with XEvent, so we need to construct a
// temporary XEvent with just enough information for spnav_x11_event()
auto xcb_ev(static_cast<const xcb_client_message_event_t *>(message));
if ((xcb_ev->response_type & 0x7F) == XCB_CLIENT_MESSAGE) {
    XClientMessageEvent xev;

    xev.type = ClientMessage;
    xev.message_type = xcb_ev->type;
    memcpy(xev.data.b, xcb_ev->data.data8, sizeof(xev.data.b));
    xev.serial = 0; // These are just to squash warnings...
    xev.send_event = 0;
    xev.display = 0;
    xev.window = 0;
    xev.format = 0;

    if (!spnav_x11_event(reinterpret_cast<XEvent *>(&xev), &navEvent)) {
        return false;
    }
} else {
    return false;
}
// navEvent is now initialised
person Ian Rees    schedule 15.09.2018