From 190bfbae64006216b4114a02153c60d604ac24f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= <jorgen.lind@digia.com> Date: Tue, 21 Oct 2014 13:47:01 +0200 Subject: [PATCH] Ensure that a leave event is sent to a popup that is being closed If a context menu contains a menu item which will open a dialog, the context menu will never get the leave event, which might leave the menu in an invalid state. Synthetic leave events are sent to windows, but not to popups that are blocked by modal dialogs. Hovever, a popup is removed from the popup stack in QApplication before it receives the leave event. Therefore always give popups events, even when they are not visible. Task-number: QTBUG-38021 Change-Id: I63f6febed44f1e7c8f29e7a09af07f32b4ddbc82 Reviewed-by: Shawn Rutledge <shawn.rutledge@digia.com> --- src/gui/kernel/qguiapplication.cpp | 9 ++------- src/gui/kernel/qwindow_p.h | 4 ++++ src/widgets/kernel/qapplication.cpp | 3 ++- src/widgets/kernel/qwidgetwindow.cpp | 1 + 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 2e050572c1a..c5e7fb523d1 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -216,11 +216,6 @@ static inline void clearFontUnlocked() QGuiApplicationPrivate::app_font = 0; } -static inline bool isPopupWindow(const QWindow *w) -{ - return (w->flags() & Qt::WindowType_Mask) == Qt::Popup; -} - // Geometry specification for top level windows following the convention of the // -geometry command line arguments in X11 (see XParseGeometry). struct QWindowGeometrySpecification @@ -672,7 +667,7 @@ static void updateBlockedStatusRecursion(QWindow *window, bool shouldBeBlocked) void QGuiApplicationPrivate::updateBlockedStatus(QWindow *window) { bool shouldBeBlocked = false; - if (!isPopupWindow(window) && !self->modalWindowList.isEmpty()) + if (!QWindowPrivate::get(window)->isPopup() && !self->modalWindowList.isEmpty()) shouldBeBlocked = self->isWindowBlocked(window); updateBlockedStatusRecursion(window, shouldBeBlocked); } @@ -682,7 +677,7 @@ void QGuiApplicationPrivate::showModalWindow(QWindow *modal) self->modalWindowList.prepend(modal); // Send leave for currently entered window if it should be blocked - if (currentMouseWindow && !isPopupWindow(currentMouseWindow)) { + if (currentMouseWindow && !QWindowPrivate::get(currentMouseWindow)->isPopup()) { bool shouldBeBlocked = self->isWindowBlocked(currentMouseWindow); if (shouldBeBlocked) { // Remove the new window from modalWindowList temporarily so leave can go through diff --git a/src/gui/kernel/qwindow_p.h b/src/gui/kernel/qwindow_p.h index ea0bb75d85f..40f23b1c36e 100644 --- a/src/gui/kernel/qwindow_p.h +++ b/src/gui/kernel/qwindow_p.h @@ -137,6 +137,10 @@ public: virtual void clearFocusObject(); + bool isPopup() const { return (windowFlags & Qt::WindowType_Mask) == Qt::Popup; } + + static QWindowPrivate *get(QWindow *window) { return window->d_func(); } + QWindow::SurfaceType surfaceType; Qt::WindowFlags windowFlags; QWindow *parentWindow; diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index 6df1d735a1f..9abec13b5be 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -64,6 +64,7 @@ #include <QtWidgets/qgraphicsproxywidget.h> #include <QtGui/qstylehints.h> #include <QtGui/qinputmethod.h> +#include <QtGui/private/qwindow_p.h> #include <qpa/qplatformtheme.h> #ifndef QT_NO_WHATSTHIS #include <QtWidgets/QWhatsThis> @@ -2489,7 +2490,7 @@ bool QApplicationPrivate::isWindowBlocked(QWindow *window, QWindow **blockingWin } QWidget *popupWidget = QApplication::activePopupWidget(); QWindow *popupWindow = popupWidget ? popupWidget->windowHandle() : 0; - if (popupWindow == window) { + if (popupWindow == window || (!popupWindow && QWindowPrivate::get(window)->isPopup())) { *blockingWindow = 0; return false; } diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index d40fc84d778..7b52638e28e 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -403,6 +403,7 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event) QGuiApplicationPrivate::setMouseEventSource(&e, QGuiApplicationPrivate::mouseEventSource(event)); e.setTimestamp(event->timestamp()); QApplicationPrivate::sendMouseEvent(receiver, &e, alien, m_widget, &qt_button_down, qt_last_mouse_receiver); + qt_last_mouse_receiver = receiver; } else { // close disabled popups when a mouse button is pressed or released switch (event->type()) { -- GitLab