Made the X11 eglfs hooks provide mouse input.

Makes the X11 hooks slightly more useful for testing eglfs.

Change-Id: I53652cef7b9fc6830ee72e44c153fe281bc1bd7d
Reviewed-by: Jørgen Lind <jorgen.lind@digia.com>
This commit is contained in:
Samuel Rødal 2013-05-23 09:47:35 +02:00 committed by The Qt Project
parent 7a85fccb8f
commit f610814b05
2 changed files with 159 additions and 3 deletions

View File

@ -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 \

View File

@ -41,13 +41,36 @@
#include "qeglfshooks.h"
#include <qpa/qwindowsysteminterface.h>
#include <QThread>
#include <X11/Xlib.h>
#include <X11/Xlib-xcb.h>
#include <xcb/xcb.h>
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;
}