summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMaurice Kalinowski <maurice.kalinowski@qt.io>2016-11-24 15:09:25 +0100
committerJani Heikkinen <jani.heikkinen@qt.io>2016-12-08 10:08:53 +0000
commit181860e1afa2f071a9cfcbf4d39b8526e9330ae2 (patch)
tree1e1be081f8b27b26c83a1530f831153cd3230412 /src
parent10143ea8030e6754b2021c84c30859ade79dc570 (diff)
winrt: Fix input grabbing
Beside its usage in widgets, mouse grabs are required for QML menus to work. Task-number: QTBUG-57079 Change-Id: I306cb68624186da69725470e147bc7b979dac8e4 Reviewed-by: Oliver Wolff <oliver.wolff@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/plugins/platforms/winrt/qwinrtscreen.cpp76
-rw-r--r--src/plugins/platforms/winrt/qwinrtscreen.h7
-rw-r--r--src/plugins/platforms/winrt/qwinrtwindow.cpp23
-rw-r--r--src/plugins/platforms/winrt/qwinrtwindow.h3
4 files changed, 106 insertions, 3 deletions
diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp
index 6d4edcc8dc..f87ae9fd24 100644
--- a/src/plugins/platforms/winrt/qwinrtscreen.cpp
+++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp
@@ -486,6 +486,9 @@ public:
QHash<ApplicationView2CallbackRemover, EventRegistrationToken> view2Tokens;
ComPtr<IApplicationView2> view2;
#endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
+ QAtomicPointer<QWinRTWindow> mouseGrabWindow;
+ QAtomicPointer<QWinRTWindow> keyboardGrabWindow;
+ QWindow *currentPressWindow = 0;
};
// To be called from the XAML thread
@@ -877,6 +880,44 @@ void QWinRTScreen::lower(QWindow *window)
handleExpose();
}
+bool QWinRTScreen::setMouseGrabWindow(QWinRTWindow *window, bool grab)
+{
+ Q_D(QWinRTScreen);
+ qCDebug(lcQpaWindows) << __FUNCTION__ << window
+ << "(" << window->window()->objectName() << "):" << grab;
+
+ if (!grab || window == nullptr)
+ d->mouseGrabWindow = nullptr;
+ else if (d->mouseGrabWindow != window)
+ d->mouseGrabWindow = window;
+ return grab;
+}
+
+QWinRTWindow *QWinRTScreen::mouseGrabWindow() const
+{
+ Q_D(const QWinRTScreen);
+ return d->mouseGrabWindow;
+}
+
+bool QWinRTScreen::setKeyboardGrabWindow(QWinRTWindow *window, bool grab)
+{
+ Q_D(QWinRTScreen);
+ qCDebug(lcQpaWindows) << __FUNCTION__ << window
+ << "(" << window->window()->objectName() << "):" << grab;
+
+ if (!grab || window == nullptr)
+ d->keyboardGrabWindow = nullptr;
+ else if (d->keyboardGrabWindow != window)
+ d->keyboardGrabWindow = window;
+ return grab;
+}
+
+QWinRTWindow *QWinRTScreen::keyboardGrabWindow() const
+{
+ Q_D(const QWinRTScreen);
+ return d->keyboardGrabWindow;
+}
+
void QWinRTScreen::updateWindowTitle(const QString &title)
{
Q_D(QWinRTScreen);
@@ -1022,7 +1063,11 @@ HRESULT QWinRTScreen::onPointerEntered(ICoreWindow *, IPointerEventArgs *args)
pointerPoint->get_Position(&point);
QPoint pos(point.X * d->scaleFactor, point.Y * d->scaleFactor);
- QWindowSystemInterface::handleEnterEvent(topWindow(), pos, pos);
+ QWindow *targetWindow = topWindow();
+ if (d->mouseGrabWindow)
+ targetWindow = d->mouseGrabWindow.load()->window();
+
+ QWindowSystemInterface::handleEnterEvent(targetWindow, pos, pos);
}
return S_OK;
}
@@ -1041,7 +1086,11 @@ HRESULT QWinRTScreen::onPointerExited(ICoreWindow *, IPointerEventArgs *args)
d->touchPoints.remove(id);
- QWindowSystemInterface::handleLeaveEvent(0);
+ QWindow *targetWindow = nullptr;
+ if (d->mouseGrabWindow)
+ targetWindow = d->mouseGrabWindow.load()->window();
+
+ QWindowSystemInterface::handleLeaveEvent(targetWindow);
return S_OK;
}
@@ -1063,7 +1112,12 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *, IPointerEventArgs *args)
QPointF localPos = pos;
const QPoint posPoint = pos.toPoint();
- QWindow *targetWindow = windowAt(posPoint);
+ QWindow *windowUnderPointer = windowAt(posPoint);
+ QWindow *targetWindow = windowUnderPointer;
+
+ if (d->mouseGrabWindow)
+ targetWindow = d->mouseGrabWindow.load()->window();
+
if (targetWindow) {
const QPointF globalPosDelta = pos - posPoint;
localPos = targetWindow->mapFromGlobal(posPoint) + globalPosDelta;
@@ -1127,6 +1181,22 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *, IPointerEventArgs *args)
if (isPressed)
buttons |= Qt::XButton2;
+ // In case of a mouse grab we have to store the target of a press event
+ // to be able to send one additional release event to this target when the mouse
+ // button is released. This is a similar approach to AutoMouseCapture in the
+ // windows qpa backend. Otherwise the release might not be propagated and the original
+ // press event receiver considers a button to still be pressed, as in Qt Quick Controls 1
+ // menus.
+ if (buttons != Qt::NoButton && d->currentPressWindow == nullptr && !d->mouseGrabWindow)
+ d->currentPressWindow = windowUnderPointer;
+ if (!isPressed && d->currentPressWindow && d->mouseGrabWindow) {
+ const QPointF globalPosDelta = pos - posPoint;
+ const QPointF localPressPos = d->currentPressWindow->mapFromGlobal(posPoint) + globalPosDelta;
+
+ QWindowSystemInterface::handleMouseEvent(d->currentPressWindow, localPressPos, pos, buttons, mods);
+ d->currentPressWindow = nullptr;
+ }
+
QWindowSystemInterface::handleMouseEvent(targetWindow, localPos, pos, buttons, mods);
break;
diff --git a/src/plugins/platforms/winrt/qwinrtscreen.h b/src/plugins/platforms/winrt/qwinrtscreen.h
index e489e208d5..04ab985699 100644
--- a/src/plugins/platforms/winrt/qwinrtscreen.h
+++ b/src/plugins/platforms/winrt/qwinrtscreen.h
@@ -83,6 +83,7 @@ class QTouchDevice;
class QWinRTCursor;
class QWinRTInputContext;
class QWinRTScreenPrivate;
+class QWinRTWindow;
class QWinRTScreen : public QPlatformScreen
{
public:
@@ -110,6 +111,12 @@ public:
void raise(QWindow *window);
void lower(QWindow *window);
+ bool setMouseGrabWindow(QWinRTWindow *window, bool grab);
+ QWinRTWindow* mouseGrabWindow() const;
+
+ bool setKeyboardGrabWindow(QWinRTWindow *window, bool grab);
+ QWinRTWindow* keyboardGrabWindow() const;
+
void updateWindowTitle(const QString &title);
ABI::Windows::UI::Core::ICoreWindow *coreWindow() const;
diff --git a/src/plugins/platforms/winrt/qwinrtwindow.cpp b/src/plugins/platforms/winrt/qwinrtwindow.cpp
index 297e6618d1..8f3b86ff3b 100644
--- a/src/plugins/platforms/winrt/qwinrtwindow.cpp
+++ b/src/plugins/platforms/winrt/qwinrtwindow.cpp
@@ -191,6 +191,11 @@ QWinRTWindow::~QWinRTWindow()
});
RETURN_VOID_IF_FAILED("Failed to completely destroy window resources, likely because the application is shutting down");
+ if (d->screen->mouseGrabWindow() == this)
+ d->screen->setMouseGrabWindow(this, false);
+ if (d->screen->keyboardGrabWindow() == this)
+ d->screen->setKeyboardGrabWindow(this, false);
+
d->screen->removeWindow(window());
if (!d->surface)
@@ -384,6 +389,24 @@ void QWinRTWindow::setWindowState(Qt::WindowState state)
d->state = state;
}
+bool QWinRTWindow::setMouseGrabEnabled(bool grab)
+{
+ Q_D(QWinRTWindow);
+ if (!isActive() && grab) {
+ qWarning("%s: Not setting mouse grab for invisible window %s/'%s'",
+ __FUNCTION__, window()->metaObject()->className(),
+ qPrintable(window()->objectName()));
+ return false;
+ }
+ return d->screen->setMouseGrabWindow(this, grab);
+}
+
+bool QWinRTWindow::setKeyboardGrabEnabled(bool grab)
+{
+ Q_D(QWinRTWindow);
+ return d->screen->setKeyboardGrabWindow(this, grab);
+}
+
EGLSurface QWinRTWindow::eglSurface() const
{
Q_D(const QWinRTWindow);
diff --git a/src/plugins/platforms/winrt/qwinrtwindow.h b/src/plugins/platforms/winrt/qwinrtwindow.h
index 48e092d455..35a4c493b6 100644
--- a/src/plugins/platforms/winrt/qwinrtwindow.h
+++ b/src/plugins/platforms/winrt/qwinrtwindow.h
@@ -70,6 +70,9 @@ public:
qreal devicePixelRatio() const Q_DECL_OVERRIDE;
void setWindowState(Qt::WindowState state) Q_DECL_OVERRIDE;
+ bool setMouseGrabEnabled(bool grab) Q_DECL_OVERRIDE;
+ bool setKeyboardGrabEnabled(bool grab) Q_DECL_OVERRIDE;
+
EGLSurface eglSurface() const;
void createEglSurface(EGLDisplay display, EGLConfig config);