From f610814b058b4639ef0d4d2592a8bcc3f81c974d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Thu, 23 May 2013 09:47:35 +0200 Subject: Made the X11 eglfs hooks provide mouse input. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Makes the X11 hooks slightly more useful for testing eglfs. Change-Id: I53652cef7b9fc6830ee72e44c153fe281bc1bd7d Reviewed-by: Jørgen Lind --- src/plugins/platforms/eglfs/eglfs.pri | 2 +- src/plugins/platforms/eglfs/qeglfshooks_x11.cpp | 160 +++++++++++++++++++++++- 2 files changed, 159 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/eglfs/eglfs.pri b/src/plugins/platforms/eglfs/eglfs.pri index eb66e17479..44455ed3d8 100644 --- a/src/plugins/platforms/eglfs/eglfs.pri +++ b/src/plugins/platforms/eglfs/eglfs.pri @@ -7,7 +7,7 @@ DEFINES += MESA_EGL_NO_X11_HEADERS #To test the hooks on x11 (xlib), comment the above define too #EGLFS_PLATFORM_HOOKS_SOURCES += qeglfshooks_x11.cpp -#LIBS += -lX11 +#LIBS += -lX11 -lX11-xcb -lxcb SOURCES += $$PWD/qeglfsintegration.cpp \ $$PWD/qeglfswindow.cpp \ diff --git a/src/plugins/platforms/eglfs/qeglfshooks_x11.cpp b/src/plugins/platforms/eglfs/qeglfshooks_x11.cpp index f44107e830..0d8be66438 100644 --- a/src/plugins/platforms/eglfs/qeglfshooks_x11.cpp +++ b/src/plugins/platforms/eglfs/qeglfshooks_x11.cpp @@ -41,13 +41,36 @@ #include "qeglfshooks.h" +#include +#include + #include +#include +#include QT_BEGIN_NAMESPACE +class EventReader : public QThread +{ +public: + EventReader(xcb_connection_t *connection) + : m_connection(connection) + { + } + + void run(); + + xcb_connection_t *connection() { return m_connection; } + +private: + xcb_connection_t *m_connection; +}; + class QEglFSX11Hooks : public QEglFSHooks { public: + QEglFSX11Hooks() : m_eventReader(0) {} + virtual void platformInit(); virtual void platformDestroy(); virtual EGLNativeDisplayType platformDisplay() const; @@ -55,20 +78,151 @@ public: virtual EGLNativeWindowType createNativeWindow(const QSize &size, const QSurfaceFormat &format); virtual void destroyNativeWindow(EGLNativeWindowType window); virtual bool hasCapability(QPlatformIntegration::Capability cap) const; + +private: + void sendConnectionEvent(xcb_atom_t a); + + EventReader *m_eventReader; + xcb_connection_t *m_connection; + xcb_window_t m_connectionEventListener; }; static Display *display = 0; +QAtomicInt running; + +static Qt::MouseButtons translateMouseButtons(int s) +{ + Qt::MouseButtons ret = 0; + if (s & XCB_BUTTON_MASK_1) + ret |= Qt::LeftButton; + if (s & XCB_BUTTON_MASK_2) + ret |= Qt::MidButton; + if (s & XCB_BUTTON_MASK_3) + ret |= Qt::RightButton; + return ret; +} + +static Qt::MouseButton translateMouseButton(xcb_button_t s) +{ + switch (s) { + case 1: return Qt::LeftButton; + case 2: return Qt::MidButton; + case 3: return Qt::RightButton; + // Button values 4-7 were already handled as Wheel events, and won't occur here. + case 8: return Qt::BackButton; // Also known as Qt::ExtraButton1 + case 9: return Qt::ForwardButton; // Also known as Qt::ExtraButton2 + case 10: return Qt::ExtraButton3; + case 11: return Qt::ExtraButton4; + case 12: return Qt::ExtraButton5; + case 13: return Qt::ExtraButton6; + case 14: return Qt::ExtraButton7; + case 15: return Qt::ExtraButton8; + case 16: return Qt::ExtraButton9; + case 17: return Qt::ExtraButton10; + case 18: return Qt::ExtraButton11; + case 19: return Qt::ExtraButton12; + case 20: return Qt::ExtraButton13; + case 21: return Qt::ExtraButton14; + case 22: return Qt::ExtraButton15; + case 23: return Qt::ExtraButton16; + case 24: return Qt::ExtraButton17; + case 25: return Qt::ExtraButton18; + case 26: return Qt::ExtraButton19; + case 27: return Qt::ExtraButton20; + case 28: return Qt::ExtraButton21; + case 29: return Qt::ExtraButton22; + case 30: return Qt::ExtraButton23; + case 31: return Qt::ExtraButton24; + default: return Qt::NoButton; + } +} + +void EventReader::run() +{ + Qt::MouseButtons buttons; + + xcb_generic_event_t *event; + while (running.load() && (event = xcb_wait_for_event(m_connection))) { + uint response_type = event->response_type & ~0x80; + switch (response_type) { + case XCB_BUTTON_PRESS: { + xcb_button_press_event_t *press = (xcb_button_press_event_t *)event; + QPoint p(press->event_x, press->event_y); + buttons = (buttons & ~0x7) | translateMouseButtons(press->state); + buttons |= translateMouseButton(press->detail); + QWindowSystemInterface::handleMouseEvent(0, press->time, p, p, buttons); + break; + } + case XCB_BUTTON_RELEASE: { + xcb_button_release_event_t *release = (xcb_button_release_event_t *)event; + QPoint p(release->event_x, release->event_y); + buttons = (buttons & ~0x7) | translateMouseButtons(release->state); + buttons &= ~translateMouseButton(release->detail); + QWindowSystemInterface::handleMouseEvent(0, release->time, p, p, buttons); + break; + } + case XCB_MOTION_NOTIFY: { + xcb_motion_notify_event_t *motion = (xcb_motion_notify_event_t *)event; + QPoint p(motion->event_x, motion->event_y); + QWindowSystemInterface::handleMouseEvent(0, motion->time, p, p, buttons); + break; + } + default: + break; + } + } +} + +void QEglFSX11Hooks::sendConnectionEvent(xcb_atom_t a) +{ + xcb_client_message_event_t event; + memset(&event, 0, sizeof(event)); + + event.response_type = XCB_CLIENT_MESSAGE; + event.format = 32; + event.sequence = 0; + event.window = m_connectionEventListener; + event.type = a; + + xcb_send_event(m_connection, false, m_connectionEventListener, XCB_EVENT_MASK_NO_EVENT, (const char *)&event); + xcb_flush(m_connection); +} + void QEglFSX11Hooks::platformInit() { display = XOpenDisplay(NULL); if (!display) qFatal("Could not open display"); + XSetEventQueueOwner(display, XCBOwnsEventQueue); + + running.ref(); + + m_connection = XGetXCBConnection(display); + + xcb_screen_iterator_t it = xcb_setup_roots_iterator(xcb_get_setup(m_connection)); + + m_connectionEventListener = xcb_generate_id(m_connection); + xcb_create_window(m_connection, XCB_COPY_FROM_PARENT, + m_connectionEventListener, it.data->root, + 0, 0, 1, 1, 0, XCB_WINDOW_CLASS_INPUT_ONLY, + it.data->root_visual, 0, 0); + + m_eventReader = new EventReader(m_connection); + m_eventReader->start(); } void QEglFSX11Hooks::platformDestroy() { + running.deref(); + + sendConnectionEvent(XCB_ATOM_NONE); + XCloseDisplay(display); + + m_eventReader->wait(); + delete m_eventReader; + m_eventReader = 0; } EGLNativeDisplayType QEglFSX11Hooks::platformDisplay() const @@ -91,10 +245,12 @@ EGLNativeWindowType QEglFSX11Hooks::createNativeWindow(const QSize &size, const Window root = DefaultRootWindow(display); XSetWindowAttributes swa; memset(&swa, 0, sizeof(swa)); - Window win = XCreateWindow(display, root, 0, 0, size.width(), size.height(), 0, CopyFromParent, - InputOutput, CopyFromParent, CWEventMask, &swa); + swa.event_mask = ButtonPressMask | ButtonReleaseMask | PointerMotionMask | ButtonMotionMask; + Window win = XCreateWindow(display, root, 0, 0, size.width(), size.height(), 0, CopyFromParent, + InputOutput, CopyFromParent, CWEventMask, &swa); XMapWindow(display, win); XStoreName(display, win, "EGLFS"); + return win; } -- cgit v1.2.3