summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGiulio Camuffo <giuliocamuffo@gmail.com>2013-09-06 15:30:15 +0200
committerAndy Nichols <andy.nichols@digia.com>2013-09-20 18:28:03 +0200
commit1a40ec4f8dd333386250fa1ba01826ce83c8e1a0 (patch)
tree6940c7f86f0d5895cb3017e21ca8e79eb75afe50
parent4a789f67dcc397125b4b13949a0f6c05a5ac840a (diff)
Support application internal mouse grabbing for popup windows
Mouse grabbing is used to close a popup window when the user clicks on another window. Wayland doesn't support mouse grabbing by design and sends an event when the user clicks on a window of another application. This patch fakes mouse grabbing for the windows of the application the popup belongs to, so that it closes when the user clicks on a window of the same application. Change-Id: Iac210bed0ca0fc6d3ffdbdb76d069886de51cf04 Reviewed-by: Jan Arne Petersen <jan.petersen@kdab.com> Reviewed-by: Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> Reviewed-by: Laszlo Agocs <laszlo.agocs@digia.com> Reviewed-by: Andrew Knight <andrew.knight@digia.com> Reviewed-by: Andy Nichols <andy.nichols@digia.com>
-rw-r--r--src/plugins/platforms/wayland_common/qwaylandinputdevice.cpp30
-rw-r--r--src/plugins/platforms/wayland_common/qwaylandwindow.cpp19
-rw-r--r--src/plugins/platforms/wayland_common/qwaylandwindow.h5
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 e081601d2..3fe6ca309 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 103865694..60b899cc0 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 8fd104d0a..6e548b20a 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