summaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
authorVolker Hilsheimer <volker.hilsheimer@qt.io>2021-09-17 15:22:28 +0200
committerVolker Hilsheimer <volker.hilsheimer@qt.io>2021-09-24 19:19:42 +0200
commita5e5943d8a7d2a1345dc94dad0a97cf2966f6e7b (patch)
tree759bf3a2fa1a4f002163c170f26517920bed62d9 /src/plugins
parent8da42e1af631ffefc29fb2ef0e289dd11da376c5 (diff)
macOS: send enter/leave when a window opens/closes
Since macOS doesn't give us any event when a modal window opens, we need to do so ourselves explicitly so that the current mouse window gets a leave event when e.g. a popup opens, and an enter event when the popup closes again. The case for modal dialogs is partially handled by QGuiApplication already. Note: We cannot rely on the transientParent of the opening/closing window, as it's nullptr for QMenu windows even if the QMenu has a widget parent. Add a test for enter/leave events when a secondary window opens, covering both the dialog and the popup case. For the dialog case, we sometimes get two Enter events when the dailog closes, which we have to tolerate for now. To make the test pass on b2qt platforms, fix the offscreen plugin to explicitly send enter/leave events in the same way as Cocoa now does. Fixes: QTBUG-78970 Pick-to: 6.2 Change-Id: If45e43e625e8362c3502c740154f6a6a8962b9e9 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm20
-rw-r--r--src/plugins/platforms/offscreen/qoffscreenwindow.cpp16
2 files changed, 36 insertions, 0 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index 16e33ee014..5b23bb3174 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -1225,12 +1225,32 @@ void QCocoaWindow::windowDidResignKey()
void QCocoaWindow::windowDidOrderOnScreen()
{
+ // The current mouse window needs to get a leave event when a popup window opens.
+ // For modal dialogs, QGuiApplicationPrivate::showModalWindow takes care of this.
+ if (QWindowPrivate::get(window())->isPopup()) {
+ QWindowSystemInterface::handleLeaveEvent<QWindowSystemInterface::SynchronousDelivery>
+ (QGuiApplicationPrivate::currentMouseWindow);
+ }
+
[m_view setNeedsDisplay:YES];
}
void QCocoaWindow::windowDidOrderOffScreen()
{
handleExposeEvent(QRegion());
+ // We are closing a window, so the window that is now under the mouse
+ // might need to get an Enter event if it isn't already the mouse window.
+ if (window()->type() & Qt::Window) {
+ const QPointF screenPoint = QCocoaScreen::mapFromNative([NSEvent mouseLocation]);
+ if (QWindow *windowUnderMouse = QGuiApplication::topLevelAt(screenPoint.toPoint())) {
+ if (windowUnderMouse != QGuiApplicationPrivate::instance()->currentMouseWindow) {
+ const auto windowPoint = windowUnderMouse->mapFromGlobal(screenPoint);
+ // asynchronous delivery on purpose
+ QWindowSystemInterface::handleEnterEvent<QWindowSystemInterface::AsynchronousDelivery>
+ (windowUnderMouse, windowPoint, screenPoint);
+ }
+ }
+ }
}
void QCocoaWindow::windowDidChangeOcclusionState()
diff --git a/src/plugins/platforms/offscreen/qoffscreenwindow.cpp b/src/plugins/platforms/offscreen/qoffscreenwindow.cpp
index a46258a401..20aae06650 100644
--- a/src/plugins/platforms/offscreen/qoffscreenwindow.cpp
+++ b/src/plugins/platforms/offscreen/qoffscreenwindow.cpp
@@ -44,6 +44,7 @@
#include <qpa/qwindowsysteminterface.h>
#include <private/qwindow_p.h>
+#include <private/qguiapplication_p.h>
QT_BEGIN_NAMESPACE
@@ -129,11 +130,26 @@ void QOffscreenWindow::setVisible(bool visible)
}
}
+ const QPoint cursorPos = QCursor::pos();
if (visible) {
QRect rect(QPoint(), geometry().size());
QWindowSystemInterface::handleExposeEvent(window(), rect);
+ if (QWindowPrivate::get(window())->isPopup() && QGuiApplicationPrivate::currentMouseWindow) {
+ QWindowSystemInterface::handleLeaveEvent<QWindowSystemInterface::SynchronousDelivery>
+ (QGuiApplicationPrivate::currentMouseWindow);
+ }
+ if (geometry().contains(cursorPos))
+ QWindowSystemInterface::handleEnterEvent(window(),
+ window()->mapFromGlobal(cursorPos), cursorPos);
} else {
QWindowSystemInterface::handleExposeEvent(window(), QRegion());
+ if (window()->type() & Qt::Window) {
+ if (QWindow *windowUnderMouse = QGuiApplication::topLevelAt(cursorPos)) {
+ QWindowSystemInterface::handleEnterEvent(windowUnderMouse,
+ windowUnderMouse->mapFromGlobal(cursorPos),
+ cursorPos);
+ }
+ }
}
m_visible = visible;