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>
This commit is contained in:
parent
10143ea803
commit
181860e1af
@ -486,6 +486,9 @@ public:
|
|||||||
QHash<ApplicationView2CallbackRemover, EventRegistrationToken> view2Tokens;
|
QHash<ApplicationView2CallbackRemover, EventRegistrationToken> view2Tokens;
|
||||||
ComPtr<IApplicationView2> view2;
|
ComPtr<IApplicationView2> view2;
|
||||||
#endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
|
#endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
|
||||||
|
QAtomicPointer<QWinRTWindow> mouseGrabWindow;
|
||||||
|
QAtomicPointer<QWinRTWindow> keyboardGrabWindow;
|
||||||
|
QWindow *currentPressWindow = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// To be called from the XAML thread
|
// To be called from the XAML thread
|
||||||
@ -877,6 +880,44 @@ void QWinRTScreen::lower(QWindow *window)
|
|||||||
handleExpose();
|
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)
|
void QWinRTScreen::updateWindowTitle(const QString &title)
|
||||||
{
|
{
|
||||||
Q_D(QWinRTScreen);
|
Q_D(QWinRTScreen);
|
||||||
@ -1022,7 +1063,11 @@ HRESULT QWinRTScreen::onPointerEntered(ICoreWindow *, IPointerEventArgs *args)
|
|||||||
pointerPoint->get_Position(&point);
|
pointerPoint->get_Position(&point);
|
||||||
QPoint pos(point.X * d->scaleFactor, point.Y * d->scaleFactor);
|
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;
|
return S_OK;
|
||||||
}
|
}
|
||||||
@ -1041,7 +1086,11 @@ HRESULT QWinRTScreen::onPointerExited(ICoreWindow *, IPointerEventArgs *args)
|
|||||||
|
|
||||||
d->touchPoints.remove(id);
|
d->touchPoints.remove(id);
|
||||||
|
|
||||||
QWindowSystemInterface::handleLeaveEvent(0);
|
QWindow *targetWindow = nullptr;
|
||||||
|
if (d->mouseGrabWindow)
|
||||||
|
targetWindow = d->mouseGrabWindow.load()->window();
|
||||||
|
|
||||||
|
QWindowSystemInterface::handleLeaveEvent(targetWindow);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1063,7 +1112,12 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *, IPointerEventArgs *args)
|
|||||||
QPointF localPos = pos;
|
QPointF localPos = pos;
|
||||||
|
|
||||||
const QPoint posPoint = pos.toPoint();
|
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) {
|
if (targetWindow) {
|
||||||
const QPointF globalPosDelta = pos - posPoint;
|
const QPointF globalPosDelta = pos - posPoint;
|
||||||
localPos = targetWindow->mapFromGlobal(posPoint) + globalPosDelta;
|
localPos = targetWindow->mapFromGlobal(posPoint) + globalPosDelta;
|
||||||
@ -1127,6 +1181,22 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *, IPointerEventArgs *args)
|
|||||||
if (isPressed)
|
if (isPressed)
|
||||||
buttons |= Qt::XButton2;
|
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);
|
QWindowSystemInterface::handleMouseEvent(targetWindow, localPos, pos, buttons, mods);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -83,6 +83,7 @@ class QTouchDevice;
|
|||||||
class QWinRTCursor;
|
class QWinRTCursor;
|
||||||
class QWinRTInputContext;
|
class QWinRTInputContext;
|
||||||
class QWinRTScreenPrivate;
|
class QWinRTScreenPrivate;
|
||||||
|
class QWinRTWindow;
|
||||||
class QWinRTScreen : public QPlatformScreen
|
class QWinRTScreen : public QPlatformScreen
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -110,6 +111,12 @@ public:
|
|||||||
void raise(QWindow *window);
|
void raise(QWindow *window);
|
||||||
void lower(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);
|
void updateWindowTitle(const QString &title);
|
||||||
|
|
||||||
ABI::Windows::UI::Core::ICoreWindow *coreWindow() const;
|
ABI::Windows::UI::Core::ICoreWindow *coreWindow() const;
|
||||||
|
@ -191,6 +191,11 @@ QWinRTWindow::~QWinRTWindow()
|
|||||||
});
|
});
|
||||||
RETURN_VOID_IF_FAILED("Failed to completely destroy window resources, likely because the application is shutting down");
|
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());
|
d->screen->removeWindow(window());
|
||||||
|
|
||||||
if (!d->surface)
|
if (!d->surface)
|
||||||
@ -384,6 +389,24 @@ void QWinRTWindow::setWindowState(Qt::WindowState state)
|
|||||||
d->state = 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
|
EGLSurface QWinRTWindow::eglSurface() const
|
||||||
{
|
{
|
||||||
Q_D(const QWinRTWindow);
|
Q_D(const QWinRTWindow);
|
||||||
|
@ -70,6 +70,9 @@ public:
|
|||||||
qreal devicePixelRatio() const Q_DECL_OVERRIDE;
|
qreal devicePixelRatio() const Q_DECL_OVERRIDE;
|
||||||
void setWindowState(Qt::WindowState state) 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;
|
EGLSurface eglSurface() const;
|
||||||
void createEglSurface(EGLDisplay display, EGLConfig config);
|
void createEglSurface(EGLDisplay display, EGLConfig config);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user