From 9fbaf51eccf668a938f4c9a466cc4595195920f3 Mon Sep 17 00:00:00 2001 From: Mikko Levonmaa Date: Mon, 31 Mar 2014 11:25:33 -0700 Subject: Support configurable capabilities for input devices Change-Id: I070f7daec8fb13a7db838b3d0c67e8aebc790a6c Reviewed-by: Giulio Camuffo --- src/compositor/compositor_api/qwaylandinput.cpp | 9 +- src/compositor/compositor_api/qwaylandinput.h | 16 +++- src/compositor/wayland_wrapper/qwlinputdevice.cpp | 100 ++++++++++++++++------ src/compositor/wayland_wrapper/qwlinputdevice_p.h | 7 +- tests/auto/compositor/compositor.pro | 12 ++- tests/auto/compositor/tst_compositor.cpp | 23 +++++ 6 files changed, 135 insertions(+), 32 deletions(-) diff --git a/src/compositor/compositor_api/qwaylandinput.cpp b/src/compositor/compositor_api/qwaylandinput.cpp index de1df4965..97bbb23b3 100644 --- a/src/compositor/compositor_api/qwaylandinput.cpp +++ b/src/compositor/compositor_api/qwaylandinput.cpp @@ -60,8 +60,8 @@ QWaylandKeymap::QWaylandKeymap(const QString &layout, const QString &variant, co -QWaylandInputDevice::QWaylandInputDevice(QWaylandCompositor *compositor) - : d(new QtWayland::InputDevice(this,compositor->handle())) +QWaylandInputDevice::QWaylandInputDevice(QWaylandCompositor *compositor, CapabilityFlags caps) + : d(new QtWayland::InputDevice(this,compositor->handle(), caps)) { } @@ -178,4 +178,9 @@ QtWayland::InputDevice *QWaylandInputDevice::handle() const return d; } +QWaylandInputDevice::CapabilityFlags QWaylandInputDevice::capabilities() +{ + return d->capabilities(); +} + QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandinput.h b/src/compositor/compositor_api/qwaylandinput.h index 2b42690a5..c97d7c175 100644 --- a/src/compositor/compositor_api/qwaylandinput.h +++ b/src/compositor/compositor_api/qwaylandinput.h @@ -82,7 +82,17 @@ private: class Q_COMPOSITOR_EXPORT QWaylandInputDevice { public: - QWaylandInputDevice(QWaylandCompositor *compositor); + enum CapabilityFlag { + // The order should match the enum WL_SEAT_CAPABILITY_* + Pointer = 0x01, + Keyboard = 0x02, + Touch = 0x04, + + DefaultCapabilities = Pointer | Keyboard | Touch + }; + Q_DECLARE_FLAGS(CapabilityFlags, CapabilityFlag) + + QWaylandInputDevice(QWaylandCompositor *compositor, CapabilityFlags caps = DefaultCapabilities); ~QWaylandInputDevice(); void sendMousePressEvent(Qt::MouseButton button, const QPointF &localPos, const QPointF &globalPos = QPointF()); @@ -113,11 +123,15 @@ public: QWaylandCompositor *compositor() const; QtWayland::InputDevice *handle() const; + QWaylandInputDevice::CapabilityFlags capabilities(); + private: QtWayland::InputDevice *d; Q_DISABLE_COPY(QWaylandInputDevice) }; +Q_DECLARE_OPERATORS_FOR_FLAGS(QWaylandInputDevice::CapabilityFlags) + QT_END_NAMESPACE #endif // QWAYLANDINPUT_H diff --git a/src/compositor/wayland_wrapper/qwlinputdevice.cpp b/src/compositor/wayland_wrapper/qwlinputdevice.cpp index bcfadbdcd..dff84c6ee 100644 --- a/src/compositor/wayland_wrapper/qwlinputdevice.cpp +++ b/src/compositor/wayland_wrapper/qwlinputdevice.cpp @@ -59,14 +59,15 @@ QT_BEGIN_NAMESPACE namespace QtWayland { -InputDevice::InputDevice(QWaylandInputDevice *handle, Compositor *compositor) +InputDevice::InputDevice(QWaylandInputDevice *handle, Compositor *compositor, QWaylandInputDevice::CapabilityFlags caps) : QtWaylandServer::wl_seat(compositor->wl_display()) , m_handle(handle) , m_dragHandle(new QWaylandDrag(this)) , m_compositor(compositor) - , m_pointer(new Pointer(m_compositor, this)) - , m_keyboard(new Keyboard(m_compositor, this)) - , m_touch(new Touch(m_compositor)) + , m_capabilities(caps) + , m_pointer(m_capabilities & QWaylandInputDevice::Pointer ? new Pointer(m_compositor, this) : 0) + , m_keyboard(m_capabilities & QWaylandInputDevice::Keyboard ? new Keyboard(m_compositor, this) : 0) + , m_touch(m_capabilities & QWaylandInputDevice::Touch ? new Touch(m_compositor) : 0) , m_inputMethod(m_compositor->extensions() & QWaylandCompositor::TextInputExtension ? new InputMethod(m_compositor, this) : 0) , m_data_device() { @@ -118,26 +119,54 @@ void InputDevice::seat_destroy_resource(wl_seat::Resource *) void InputDevice::seat_bind_resource(wl_seat::Resource *resource) { - uint32_t caps = WL_SEAT_CAPABILITY_POINTER | WL_SEAT_CAPABILITY_KEYBOARD; - if (!QTouchDevice::devices().isEmpty()) - caps |= WL_SEAT_CAPABILITY_TOUCH; + // The order of m_capabilities matches the order defined in the wayland protocol + wl_seat::send_capabilities(resource->handle, (uint32_t)m_capabilities); +} + +void InputDevice::setCapabilities(QWaylandInputDevice::CapabilityFlags caps) +{ + if (m_capabilities != caps) { + QWaylandInputDevice::CapabilityFlags changed = caps ^ m_capabilities; + + if (changed & QWaylandInputDevice::Pointer) { + m_pointer.reset(m_pointer.isNull() ? new Pointer(m_compositor, this) : 0); + } + + if (changed & QWaylandInputDevice::Keyboard) { + m_keyboard.reset(m_keyboard.isNull() ? new Keyboard(m_compositor, this) : 0); + } - wl_seat::send_capabilities(resource->handle, caps); + if (changed & QWaylandInputDevice::Touch) { + m_touch.reset(m_touch.isNull() ? new Touch(m_compositor) : 0); + } + + m_capabilities = caps; + QList resources = resourceMap().values(); + for (int i = 0; i < resources.size(); i++) { + wl_seat::send_capabilities(resources.at(i)->handle, (uint32_t)m_capabilities); + } + } } void InputDevice::seat_get_pointer(wl_seat::Resource *resource, uint32_t id) { - m_pointer->add(resource->client(), id); + if (!m_pointer.isNull()) { + m_pointer->add(resource->client(), id); + } } void InputDevice::seat_get_keyboard(wl_seat::Resource *resource, uint32_t id) { - m_keyboard->add(resource->client(), id); + if (!m_keyboard.isNull()) { + m_keyboard->add(resource->client(), id); + } } void InputDevice::seat_get_touch(wl_seat::Resource *resource, uint32_t id) { - m_touch->add(resource->client(), id); + if (!m_touch.isNull()) { + m_touch->add(resource->client(), id); + } } void InputDevice::sendMousePressEvent(Qt::MouseButton button, const QPointF &localPos, const QPointF &globalPos) @@ -168,6 +197,10 @@ void InputDevice::sendMouseWheelEvent(Qt::Orientation orientation, int delta) void InputDevice::sendTouchPointEvent(int id, double x, double y, Qt::TouchPointState state) { + if (m_touch.isNull()) { + return; + } + switch (state) { case Qt::TouchPointPressed: m_touch->sendDown(id, QPointF(x, y)); @@ -188,12 +221,16 @@ void InputDevice::sendTouchPointEvent(int id, double x, double y, Qt::TouchPoint void InputDevice::sendTouchFrameEvent() { - m_touch->sendFrame(); + if (!m_touch.isNull()) { + m_touch->sendFrame(); + } } void InputDevice::sendTouchCancelEvent() { - m_touch->sendCancel(); + if (!m_touch.isNull()) { + m_touch->sendCancel(); + } } void InputDevice::sendFullKeyEvent(QKeyEvent *event) @@ -207,10 +244,12 @@ void InputDevice::sendFullKeyEvent(QKeyEvent *event) if (ext && ext->postQtKeyEvent(event, keyboardFocus())) return; - if (event->type() == QEvent::KeyPress) - m_keyboard->sendKeyPressEvent(event->nativeScanCode()); - else if (event->type() == QEvent::KeyRelease) - m_keyboard->sendKeyReleaseEvent(event->nativeScanCode()); + if (!m_keyboard.isNull()) { + if (event->type() == QEvent::KeyPress) + m_keyboard->sendKeyPressEvent(event->nativeScanCode()); + else if (event->type() == QEvent::KeyRelease) + m_keyboard->sendKeyReleaseEvent(event->nativeScanCode()); + } } void InputDevice::sendFullKeyEvent(Surface *surface, QKeyEvent *event) @@ -253,7 +292,7 @@ void InputDevice::sendFullTouchEvent(QTouchEvent *event) Surface *InputDevice::keyboardFocus() const { - return m_keyboard->focus(); + return m_keyboard.isNull() ? 0 : m_keyboard->focus(); } /*! @@ -264,15 +303,18 @@ bool InputDevice::setKeyboardFocus(Surface *surface) if (surface && (surface->transientInactive() || surface->isDestroyed())) return false; - m_keyboard->setFocus(surface); - if (m_data_device) - m_data_device->setFocus(m_keyboard->focusResource()); - return true; + if (!m_keyboard.isNull()) { + m_keyboard->setFocus(surface); + if (m_data_device) + m_data_device->setFocus(m_keyboard->focusResource()); + return true; + } + return false; } QWaylandSurfaceView *InputDevice::mouseFocus() const { - return m_pointer->focusSurface(); + return m_pointer.isNull() ? 0 : m_pointer->focusSurface(); } void InputDevice::setMouseFocus(QWaylandSurfaceView *view, const QPointF &localPos, const QPointF &globalPos) @@ -280,11 +322,15 @@ void InputDevice::setMouseFocus(QWaylandSurfaceView *view, const QPointF &localP if (view && view->surface()->handle()->isDestroyed()) return; - m_pointer->setMouseFocus(view, localPos, globalPos); + if (!m_pointer.isNull()) { + m_pointer->setMouseFocus(view, localPos, globalPos); + } - // We have no separate touch focus management so make it match the pointer focus always. - // No wl_touch_set_focus() is available so set it manually. - m_touch->setFocus(view); + if (!m_touch.isNull()) { + // We have no separate touch focus management so make it match the pointer focus always. + // No wl_touch_set_focus() is available so set it manually. + m_touch->setFocus(view); + } } void InputDevice::clientRequestedDataDevice(DataDeviceManager *, struct wl_client *client, uint32_t id) diff --git a/src/compositor/wayland_wrapper/qwlinputdevice_p.h b/src/compositor/wayland_wrapper/qwlinputdevice_p.h index aff6e2bdb..f98a43927 100644 --- a/src/compositor/wayland_wrapper/qwlinputdevice_p.h +++ b/src/compositor/wayland_wrapper/qwlinputdevice_p.h @@ -44,6 +44,7 @@ #include #include +#include #include #include @@ -77,7 +78,7 @@ class InputMethod; class Q_COMPOSITOR_EXPORT InputDevice : public QtWaylandServer::wl_seat { public: - InputDevice(QWaylandInputDevice *handle, Compositor *compositor); + InputDevice(QWaylandInputDevice *handle, Compositor *compositor, QWaylandInputDevice::CapabilityFlags caps); ~InputDevice(); void sendMousePressEvent(Qt::MouseButton button, const QPointF &localPos, const QPointF &globalPos = QPointF()); @@ -122,10 +123,14 @@ public: return static_cast(wl_seat::Resource::fromResource(resource)->seat); } + QWaylandInputDevice::CapabilityFlags capabilities() { return m_capabilities; } + void setCapabilities(QWaylandInputDevice::CapabilityFlags caps); + private: QWaylandInputDevice *m_handle; QWaylandDrag *m_dragHandle; Compositor *m_compositor; + QWaylandInputDevice::CapabilityFlags m_capabilities; QScopedPointer m_pointer; QScopedPointer m_keyboard; diff --git a/tests/auto/compositor/compositor.pro b/tests/auto/compositor/compositor.pro index 1da1ba25c..d049b17a0 100644 --- a/tests/auto/compositor/compositor.pro +++ b/tests/auto/compositor/compositor.pro @@ -2,7 +2,7 @@ CONFIG += testcase link_pkgconfig TARGET = tst_compositor QT += testlib -QT += core-private gui-private compositor +QT += core-private gui-private compositor compositor-private !contains(QT_CONFIG, no-pkg-config) { PKGCONFIG += wayland-client wayland-server @@ -10,5 +10,15 @@ QT += core-private gui-private compositor LIBS += -lwayland-client -lwayland-server } +config_xkbcommon { + !contains(QT_CONFIG, no-pkg-config) { + PKGCONFIG_PRIVATE += xkbcommon + } else { + LIBS_PRIVATE += -lxkbcommon + } +} else { + DEFINES += QT_NO_WAYLAND_XKB +} + SOURCES += tst_compositor.cpp testcompositor.cpp mockclient.cpp HEADERS += testcompositor.h mockclient.h diff --git a/tests/auto/compositor/tst_compositor.cpp b/tests/auto/compositor/tst_compositor.cpp index 99f08a4e5..803f280bc 100644 --- a/tests/auto/compositor/tst_compositor.cpp +++ b/tests/auto/compositor/tst_compositor.cpp @@ -46,6 +46,8 @@ #include +#include + class tst_WaylandCompositor : public QObject { Q_OBJECT @@ -56,6 +58,7 @@ public: } private slots: + void inputDeviceCapabilities(); void singleClient(); void multipleClients(); void geometry(); @@ -240,5 +243,25 @@ void tst_WaylandCompositor::frameCallback() wl_surface_destroy(surface); } +void tst_WaylandCompositor::inputDeviceCapabilities() +{ + TestCompositor compositor; + QtWayland::InputDevice dev(NULL, compositor.handle(), QWaylandInputDevice::Pointer); + + QTRY_VERIFY(dev.pointerDevice()); + QTRY_VERIFY(!dev.keyboardDevice()); + QTRY_VERIFY(!dev.touchDevice()); + + dev.setCapabilities(QWaylandInputDevice::Keyboard | QWaylandInputDevice::Touch); + QTRY_VERIFY(!dev.pointerDevice()); + QTRY_VERIFY(dev.keyboardDevice()); + QTRY_VERIFY(dev.touchDevice()); + + // Test that existing devices do not change when another is removed + QtWayland::Keyboard *k = dev.keyboardDevice(); + dev.setCapabilities(QWaylandInputDevice::Keyboard); + QTRY_COMPARE(k, dev.keyboardDevice()); +} + #include QTEST_MAIN(tst_WaylandCompositor); -- cgit v1.2.3