diff options
3 files changed, 47 insertions, 7 deletions
diff --git a/src/plugins/platforms/wayland_common/qwaylandinputdevice.cpp b/src/plugins/platforms/wayland_common/qwaylandinputdevice.cpp index e081601d..3fe6ca30 100644 --- a/src/plugins/platforms/wayland_common/qwaylandinputdevice.cpp +++ b/src/plugins/platforms/wayland_common/qwaylandinputdevice.cpp @@ -223,8 +223,11 @@ void QWaylandInputDevice::pointer_enter(uint32_t serial, struct wl_surface *surf mSerial = serial; mEnterSerial = serial; - window->handleMouseEnter(this); - window->handleMouse(this, mTime, mSurfacePos, mGlobalPos, mButtons, Qt::NoModifier); + QWaylandWindow *grab = QWaylandWindow::mouseGrab(); + if (!grab) { + window->handleMouseEnter(this); + window->handleMouse(this, mTime, mSurfacePos, mGlobalPos, mButtons, Qt::NoModifier); + } } void QWaylandInputDevice::pointer_leave(uint32_t time, struct wl_surface *surface) @@ -234,8 +237,10 @@ void QWaylandInputDevice::pointer_leave(uint32_t time, struct wl_surface *surfac if (!surface) return; - QWaylandWindow *window = QWaylandWindow::fromWlSurface(surface); - window->handleMouseLeave(this); + if (!QWaylandWindow::mouseGrab()) { + QWaylandWindow *window = QWaylandWindow::fromWlSurface(surface); + window->handleMouseLeave(this); + } mPointerFocus = 0; mButtons = Qt::NoButton; @@ -264,7 +269,15 @@ void QWaylandInputDevice::pointer_motion(uint32_t time, wl_fixed_t surface_x, wl mGlobalPos = global; mTime = time; - window->handleMouse(this, time, mSurfacePos, mGlobalPos, mButtons, Qt::NoModifier); + QWaylandWindow *grab = QWaylandWindow::mouseGrab(); + if (grab && grab != window) { + // We can't know the true position since we're getting events for another surface, + // so we just set it outside of the window boundaries. + pos = QPointF(-1, -1); + global = grab->window()->mapToGlobal(pos.toPoint()); + grab->handleMouse(this, time, pos, global, mButtons, Qt::NoModifier); + } else + window->handleMouse(this, time, mSurfacePos, mGlobalPos, mButtons, Qt::NoModifier); } void QWaylandInputDevice::pointer_button(uint32_t serial, uint32_t time, @@ -304,7 +317,12 @@ void QWaylandInputDevice::pointer_button(uint32_t serial, uint32_t time, mTime = time; mSerial = serial; - if (window) + QWaylandWindow *grab = QWaylandWindow::mouseGrab(); + if (grab && grab != mPointerFocus) { + QPointF pos = QPointF(-1, -1); + QPointF global = grab->window()->mapToGlobal(pos.toPoint()); + grab->handleMouse(this, time, pos, global, mButtons, Qt::NoModifier); + } else if (window) window->handleMouse(this, time, mSurfacePos, mGlobalPos, mButtons, Qt::NoModifier); } diff --git a/src/plugins/platforms/wayland_common/qwaylandwindow.cpp b/src/plugins/platforms/wayland_common/qwaylandwindow.cpp index 10386569..60b899cc 100644 --- a/src/plugins/platforms/wayland_common/qwaylandwindow.cpp +++ b/src/plugins/platforms/wayland_common/qwaylandwindow.cpp @@ -61,6 +61,8 @@ QT_BEGIN_NAMESPACE +QWaylandWindow *QWaylandWindow::mMouseGrab = 0; + QWaylandWindow::QWaylandWindow(QWindow *window) : QObject() , QPlatformWindow(window) @@ -139,6 +141,10 @@ QWaylandWindow::~QWaylandWindow() if (w->transientParent() == parent) QWindowSystemInterface::handleCloseEvent(w); } + + if (mMouseGrab == this) { + mMouseGrab = 0; + } } QWaylandWindow *QWaylandWindow::fromWlSurface(::wl_surface *surface) @@ -183,7 +189,7 @@ void QWaylandWindow::setGeometry(const QRect &rect) qBound(window()->minimumWidth(), rect.width(), window()->maximumWidth()), qBound(window()->minimumHeight(), rect.height(), window()->maximumHeight()))); - if (shellSurface() && window()->transientParent()) + if (shellSurface() && window()->transientParent() && window()->type() != Qt::Popup) shellSurface()->updateTransientParent(window()->transientParent()); if (mWindowDecoration && window()->isVisible()) @@ -582,4 +588,15 @@ void QWaylandWindow::restoreMouseCursor(QWaylandInputDevice *device) setMouseCursor(device, window()->cursor().shape()); } +bool QWaylandWindow::setMouseGrabEnabled(bool grab) +{ + if (window()->type() != Qt::Popup) { + qWarning("This plugin supports grabbing the mouse only for popup windows"); + return false; + } + + mMouseGrab = grab ? this : 0; + return true; +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/wayland_common/qwaylandwindow.h b/src/plugins/platforms/wayland_common/qwaylandwindow.h index 8fd104d0..6e548b20 100644 --- a/src/plugins/platforms/wayland_common/qwaylandwindow.h +++ b/src/plugins/platforms/wayland_common/qwaylandwindow.h @@ -162,6 +162,10 @@ public: QMutex *resizeMutex() { return &mResizeLock; } void doResize(); void setCanResize(bool canResize); + + bool setMouseGrabEnabled(bool grab); + static QWaylandWindow *mouseGrab() { return mMouseGrab; } + public slots: void requestResize(); @@ -209,6 +213,7 @@ private: static void frameCallback(void *data, struct wl_callback *wl_callback, uint32_t time); static QMutex mFrameSyncMutex; + static QWaylandWindow *mMouseGrab; }; inline QIcon QWaylandWindow::windowIcon() const |