diff options
author | Mikko Levonmaa <mikko.levonmaa@lge.com> | 2014-03-31 11:31:18 -0700 |
---|---|---|
committer | Mikko Levonmaa <mikko.levonmaa@lge.com> | 2014-10-20 09:58:56 +0200 |
commit | 155aee0c513e88f83364ee932b344cfbee1f4986 (patch) | |
tree | 40da8e773c2f62d6dbbb676570392912677c6940 /src/compositor | |
parent | 0febf7c52f5cc4bc5c7767f7572ff87a5aa8a7af (diff) |
Support for multiple input devices
Allows the registration of multiple input devices for the compositor via
private APIs. Since the Qt stack does not support separate input devices
via the QPA, the identification of each device (wl_seat) is left up to
the implementor.
The compositor will identify input event via the QWaylandInputDevice::isOwner
method. Usually this will happen when an item on the UI has received an
event and would like to send it to the client surface. See
QWaylandSurfaceItem for more details.
Includes basic unit tests
Change-Id: I7ee1db49388713bf3076c23cf8f8a165aefc2fe0
Reviewed-by: Mikko Levonmaa <mikko.levonmaa@lge.com>
Reviewed-by: Giulio Camuffo <giulio.camuffo@jollamobile.com>
Diffstat (limited to 'src/compositor')
-rw-r--r-- | src/compositor/compositor_api/qwaylandcompositor.cpp | 5 | ||||
-rw-r--r-- | src/compositor/compositor_api/qwaylandcompositor.h | 4 | ||||
-rw-r--r-- | src/compositor/compositor_api/qwaylandinput.cpp | 6 | ||||
-rw-r--r-- | src/compositor/compositor_api/qwaylandinput.h | 3 | ||||
-rw-r--r-- | src/compositor/compositor_api/qwaylandsurfaceitem.cpp | 29 | ||||
-rw-r--r-- | src/compositor/compositor_api/qwaylandsurfaceitem.h | 3 | ||||
-rw-r--r-- | src/compositor/wayland_wrapper/qwlcompositor.cpp | 43 | ||||
-rw-r--r-- | src/compositor/wayland_wrapper/qwlcompositor_p.h | 14 | ||||
-rw-r--r-- | src/compositor/wayland_wrapper/qwlsurface.cpp | 6 |
9 files changed, 89 insertions, 24 deletions
diff --git a/src/compositor/compositor_api/qwaylandcompositor.cpp b/src/compositor/compositor_api/qwaylandcompositor.cpp index 0891e8a9f..25ceb6e85 100644 --- a/src/compositor/compositor_api/qwaylandcompositor.cpp +++ b/src/compositor/compositor_api/qwaylandcompositor.cpp @@ -297,4 +297,9 @@ QWaylandSurfaceView *QWaylandCompositor::createView(QWaylandSurface *surface) return new QWaylandSurfaceView(surface); } +QWaylandInputDevice *QWaylandCompositor::inputDeviceFor(QInputEvent *inputEvent) +{ + return m_compositor->inputDeviceFor(inputEvent); +} + QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandcompositor.h b/src/compositor/compositor_api/qwaylandcompositor.h index 751fc420b..2c73a1d3e 100644 --- a/src/compositor/compositor_api/qwaylandcompositor.h +++ b/src/compositor/compositor_api/qwaylandcompositor.h @@ -51,6 +51,8 @@ struct wl_display; QT_BEGIN_NAMESPACE +class QInputEvent; + class QMimeData; class QUrl; class QOpenGLContext; @@ -149,6 +151,8 @@ public: virtual QWaylandSurfaceView *createView(QWaylandSurface *surface); + QWaylandInputDevice *inputDeviceFor(QInputEvent *inputEvent); + protected: QWaylandCompositor(QWindow *window, const char *socketName, QtWayland::Compositor *dptr); virtual void retainedSelectionReceived(QMimeData *mimeData); diff --git a/src/compositor/compositor_api/qwaylandinput.cpp b/src/compositor/compositor_api/qwaylandinput.cpp index 97bbb23b3..76e365fb5 100644 --- a/src/compositor/compositor_api/qwaylandinput.cpp +++ b/src/compositor/compositor_api/qwaylandinput.cpp @@ -183,4 +183,10 @@ QWaylandInputDevice::CapabilityFlags QWaylandInputDevice::capabilities() return d->capabilities(); } +bool QWaylandInputDevice::isOwner(QInputEvent *inputEvent) +{ + Q_UNUSED(inputEvent); + return true; +} + QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandinput.h b/src/compositor/compositor_api/qwaylandinput.h index 2c0b9ee7c..209228b97 100644 --- a/src/compositor/compositor_api/qwaylandinput.h +++ b/src/compositor/compositor_api/qwaylandinput.h @@ -54,6 +54,7 @@ class QWaylandSurface; class QKeyEvent; class QTouchEvent; class QWaylandSurfaceView; +class QInputEvent; namespace QtWayland { class InputDevice; @@ -125,6 +126,8 @@ public: QWaylandInputDevice::CapabilityFlags capabilities(); + virtual bool isOwner(QInputEvent *inputEvent); + private: QtWayland::InputDevice *d; Q_DISABLE_COPY(QWaylandInputDevice) diff --git a/src/compositor/compositor_api/qwaylandsurfaceitem.cpp b/src/compositor/compositor_api/qwaylandsurfaceitem.cpp index 254d45bbd..79afa3786 100644 --- a/src/compositor/compositor_api/qwaylandsurfaceitem.cpp +++ b/src/compositor/compositor_api/qwaylandsurfaceitem.cpp @@ -149,7 +149,7 @@ void QWaylandSurfaceItem::mousePressEvent(QMouseEvent *event) return; } - QWaylandInputDevice *inputDevice = compositor()->defaultInputDevice(); + QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event); if (inputDevice->mouseFocus() != this) inputDevice->setMouseFocus(this, event->localPos(), event->windowPos()); inputDevice->sendMousePressEvent(event->button(), event->localPos(), event->windowPos()); @@ -158,7 +158,7 @@ void QWaylandSurfaceItem::mousePressEvent(QMouseEvent *event) void QWaylandSurfaceItem::mouseMoveEvent(QMouseEvent *event) { if (surface()) { - QWaylandInputDevice *inputDevice = compositor()->defaultInputDevice(); + QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event); inputDevice->sendMouseMoveEvent(this, event->localPos(), event->windowPos()); } } @@ -166,7 +166,7 @@ void QWaylandSurfaceItem::mouseMoveEvent(QMouseEvent *event) void QWaylandSurfaceItem::mouseReleaseEvent(QMouseEvent *event) { if (surface()) { - QWaylandInputDevice *inputDevice = compositor()->defaultInputDevice(); + QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event); inputDevice->sendMouseReleaseEvent(event->button(), event->localPos(), event->windowPos()); } } @@ -174,7 +174,7 @@ void QWaylandSurfaceItem::mouseReleaseEvent(QMouseEvent *event) void QWaylandSurfaceItem::hoverEnterEvent(QHoverEvent *event) { if (surface()) { - QWaylandInputDevice *inputDevice = compositor()->defaultInputDevice(); + QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event); inputDevice->sendMouseMoveEvent(this, event->pos()); } } @@ -182,7 +182,7 @@ void QWaylandSurfaceItem::hoverEnterEvent(QHoverEvent *event) void QWaylandSurfaceItem::hoverMoveEvent(QHoverEvent *event) { if (surface()) { - QWaylandInputDevice *inputDevice = compositor()->defaultInputDevice(); + QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event); inputDevice->sendMouseMoveEvent(this, event->pos()); } } @@ -190,7 +190,7 @@ void QWaylandSurfaceItem::hoverMoveEvent(QHoverEvent *event) void QWaylandSurfaceItem::hoverLeaveEvent(QHoverEvent *event) { if (surface()) { - QWaylandInputDevice *inputDevice = compositor()->defaultInputDevice(); + QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event); inputDevice->sendMouseMoveEvent(this, event->pos()); } } @@ -203,7 +203,7 @@ void QWaylandSurfaceItem::wheelEvent(QWheelEvent *event) return; } - QWaylandInputDevice *inputDevice = compositor()->defaultInputDevice(); + QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event); inputDevice->sendMouseWheelEvent(event->orientation(), event->delta()); } } @@ -211,7 +211,7 @@ void QWaylandSurfaceItem::wheelEvent(QWheelEvent *event) void QWaylandSurfaceItem::keyPressEvent(QKeyEvent *event) { if (surface()) { - QWaylandInputDevice *inputDevice = compositor()->defaultInputDevice(); + QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event); inputDevice->sendFullKeyEvent(event); } } @@ -219,7 +219,7 @@ void QWaylandSurfaceItem::keyPressEvent(QKeyEvent *event) void QWaylandSurfaceItem::keyReleaseEvent(QKeyEvent *event) { if (surface() && hasFocus()) { - QWaylandInputDevice *inputDevice = compositor()->defaultInputDevice(); + QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event); inputDevice->sendFullKeyEvent(event); } } @@ -227,7 +227,7 @@ void QWaylandSurfaceItem::keyReleaseEvent(QKeyEvent *event) void QWaylandSurfaceItem::touchEvent(QTouchEvent *event) { if (m_touchEventsEnabled) { - QWaylandInputDevice *inputDevice = compositor()->defaultInputDevice(); + QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event); QPoint pointPos; const QList<QTouchEvent::TouchPoint> &points = event->touchPoints(); @@ -249,15 +249,18 @@ void QWaylandSurfaceItem::touchEvent(QTouchEvent *event) } } -void QWaylandSurfaceItem::takeFocus() +void QWaylandSurfaceItem::takeFocus(QWaylandInputDevice *device) { setFocus(true); if (!surface()) return; - QWaylandInputDevice *inputDevice = compositor()->defaultInputDevice(); - inputDevice->setKeyboardFocus(surface()); + QWaylandInputDevice *target = device; + if (!target) { + target = compositor()->defaultInputDevice(); + } + target->setKeyboardFocus(surface()); } void QWaylandSurfaceItem::surfaceMapped() diff --git a/src/compositor/compositor_api/qwaylandsurfaceitem.h b/src/compositor/compositor_api/qwaylandsurfaceitem.h index 58dc4d871..fb70705b2 100644 --- a/src/compositor/compositor_api/qwaylandsurfaceitem.h +++ b/src/compositor/compositor_api/qwaylandsurfaceitem.h @@ -57,6 +57,7 @@ QT_BEGIN_NAMESPACE class QWaylandSurfaceTextureProvider; class QMutex; +class QWaylandInputDevice; class Q_COMPOSITOR_EXPORT QWaylandSurfaceItem : public QQuickItem, public QWaylandSurfaceView { @@ -101,7 +102,7 @@ protected: void touchEvent(QTouchEvent *event); public slots: - void takeFocus(); + virtual void takeFocus(QWaylandInputDevice *device = 0); void setPaintEnabled(bool paintEnabled); private slots: diff --git a/src/compositor/wayland_wrapper/qwlcompositor.cpp b/src/compositor/wayland_wrapper/qwlcompositor.cpp index ada82a2e1..a792d5531 100644 --- a/src/compositor/wayland_wrapper/qwlcompositor.cpp +++ b/src/compositor/wayland_wrapper/qwlcompositor.cpp @@ -109,7 +109,6 @@ Compositor *Compositor::instance() Compositor::Compositor(QWaylandCompositor *qt_compositor, QWaylandCompositor::ExtensionFlags extensions) : m_extensions(extensions) , m_display(new Display) - , m_default_input_device(0) , m_current_frame(0) , m_last_queued_buf(-1) , m_qt_compositor(qt_compositor) @@ -188,6 +187,7 @@ Compositor::~Compositor() delete m_touchExtension; delete m_qtkeyExtension; + removeInputDevice(m_default_wayland_input_device); delete m_default_wayland_input_device; delete m_data_device_manager; @@ -226,6 +226,16 @@ void Compositor::destroySurface(Surface *surface) m_destroyed_surfaces << surface->waylandSurface(); } +void Compositor::resetInputDevice(Surface *surface) +{ + foreach (QWaylandInputDevice *dev, m_inputDevices) { + if (dev->keyboardFocus() == surface->waylandSurface()) + dev->setKeyboardFocus(0); + if (dev->mouseFocus() && dev->mouseFocus()->surface() == surface->waylandSurface()) + dev->setMouseFocus(0, QPointF(), QPointF()); + } +} + void Compositor::cleanupGraphicsResources() { qDeleteAll(m_destroyed_surfaces); @@ -323,7 +333,7 @@ void Compositor::initializeExtensions() void Compositor::initializeDefaultInputDevice() { m_default_wayland_input_device = new QWaylandInputDevice(m_qt_compositor); - m_default_input_device = m_default_wayland_input_device->handle(); + registerInputDevice(m_default_wayland_input_device); } QList<QWaylandClient *> Compositor::clients() const @@ -381,7 +391,8 @@ QWaylandCompositor::ExtensionFlags Compositor::extensions() const InputDevice* Compositor::defaultInputDevice() { - return m_default_input_device; + // The list gets prepended so that default is the last element + return m_inputDevices.last()->handle(); } QList<QtWayland::Surface *> Compositor::surfacesForClient(wl_client *client) @@ -499,6 +510,32 @@ void Compositor::loadServerBufferIntegration() } } +void Compositor::registerInputDevice(QWaylandInputDevice *device) +{ + // The devices get prepended as the first input device that gets added + // is assumed to be the default and it will claim to accept all the input + // events if asked + m_inputDevices.prepend(device); +} + +void Compositor::removeInputDevice(QWaylandInputDevice *device) +{ + m_inputDevices.removeOne(device); +} + +QWaylandInputDevice *Compositor::inputDeviceFor(QInputEvent *inputEvent) +{ + QWaylandInputDevice *dev = NULL; + for (int i = 0; i < m_inputDevices.size(); i++) { + QWaylandInputDevice *candidate = m_inputDevices.at(i); + if (candidate->isOwner(inputEvent)) { + dev = candidate; + break; + } + } + return dev; +} + } // namespace Wayland QT_END_NAMESPACE diff --git a/src/compositor/wayland_wrapper/qwlcompositor_p.h b/src/compositor/wayland_wrapper/qwlcompositor_p.h index 9c6192fae..9c3a0f9de 100644 --- a/src/compositor/wayland_wrapper/qwlcompositor_p.h +++ b/src/compositor/wayland_wrapper/qwlcompositor_p.h @@ -59,6 +59,8 @@ QT_BEGIN_NAMESPACE class QWaylandClient; class QWaylandClientPrivate; +class QInputEvent; + class QWaylandCompositor; class QWaylandInputDevice; class WindowManagerServerIntegration; @@ -96,7 +98,12 @@ public: void sendFrameCallbacks(QList<QWaylandSurface *> visibleSurfaces); void frameFinished(Surface *surface = 0); - InputDevice *defaultInputDevice(); //we just have 1 default device for now (since QPA doesn't give us anything else) + InputDevice *defaultInputDevice(); + + void registerInputDevice(QWaylandInputDevice *device); + QList<QWaylandInputDevice *> inputDevices() const { return m_inputDevices; } + QWaylandInputDevice *inputDeviceFor(QInputEvent *inputEvent); + void removeInputDevice(QWaylandInputDevice *device); void destroySurface(Surface *surface); @@ -156,6 +163,8 @@ public: void feedRetainedSelectionData(QMimeData *data); static void bindGlobal(wl_client *client, void *data, uint32_t version, uint32_t id); + void resetInputDevice(Surface *surface); + public slots: void cleanupGraphicsResources(); @@ -176,7 +185,8 @@ protected: /* Input */ QWaylandInputDevice *m_default_wayland_input_device; - InputDevice *m_default_input_device; + + QList<QWaylandInputDevice *> m_inputDevices; /* Output */ //make this a list of the available screens diff --git a/src/compositor/wayland_wrapper/qwlsurface.cpp b/src/compositor/wayland_wrapper/qwlsurface.cpp index 143002845..b494b3e01 100644 --- a/src/compositor/wayland_wrapper/qwlsurface.cpp +++ b/src/compositor/wayland_wrapper/qwlsurface.cpp @@ -294,11 +294,7 @@ void Surface::setBackBuffer(SurfaceBuffer *buffer) m_damage = m_damage.intersected(QRect(QPoint(), m_size)); emit m_waylandSurface->damaged(m_damage); } else { - InputDevice *inputDevice = m_compositor->defaultInputDevice(); - if (inputDevice->keyboardFocus() == this) - inputDevice->setKeyboardFocus(0); - if (inputDevice->mouseFocus() && inputDevice->mouseFocus()->surface() == waylandSurface()) - inputDevice->setMouseFocus(0, QPointF(), QPointF()); + m_compositor->resetInputDevice(this); } m_damage = QRegion(); } |