summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/widgets/kernel/qapplication.cpp8
-rw-r--r--src/widgets/kernel/qapplication_p.h2
-rw-r--r--src/widgets/kernel/qwidgetwindow.cpp34
3 files changed, 44 insertions, 0 deletions
diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp
index 89d451589a8..e8c7598a826 100644
--- a/src/widgets/kernel/qapplication.cpp
+++ b/src/widgets/kernel/qapplication.cpp
@@ -124,6 +124,8 @@ QApplicationPrivate *QApplicationPrivate::self = nullptr;
bool QApplicationPrivate::autoSipEnabled = true;
+bool QApplicationPrivate::replayMousePress = false;
+
QApplicationPrivate::QApplicationPrivate(int &argc, char **argv)
: QGuiApplicationPrivate(argc, argv)
{
@@ -3350,6 +3352,12 @@ void QApplicationPrivate::closePopup(QWidget *popup)
if (popupGrabOk) {
popupGrabOk = false;
+ if (active_window && active_window->windowHandle()
+ && !popup->geometry().contains(QGuiApplicationPrivate::lastCursorPosition.toPoint())
+ && !popup->testAttribute(Qt::WA_NoMouseReplay)) {
+ QApplicationPrivate::replayMousePress = true;
+ }
+
// transfer grab back to mouse grabber if any, otherwise release the grab
ungrabMouseForPopup(popup);
diff --git a/src/widgets/kernel/qapplication_p.h b/src/widgets/kernel/qapplication_p.h
index 5f1d4ef13c3..622d36135cd 100644
--- a/src/widgets/kernel/qapplication_p.h
+++ b/src/widgets/kernel/qapplication_p.h
@@ -109,6 +109,8 @@ public:
static bool inPopupMode();
void closePopup(QWidget *popup);
void openPopup(QWidget *popup);
+ static bool replayMousePress;
+
static void setFocusWidget(QWidget *focus, Qt::FocusReason reason);
static QWidget *focusNextPrevChild_helper(QWidget *toplevel, bool next,
bool *wrappingOccurred = nullptr);
diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp
index e3f92564cce..1d2b7dfadbf 100644
--- a/src/widgets/kernel/qwidgetwindow.cpp
+++ b/src/widgets/kernel/qwidgetwindow.cpp
@@ -588,6 +588,40 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event)
}
}
+ if (QApplication::activePopupWidget() != activePopupWidget
+ && QApplicationPrivate::replayMousePress
+ && QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::ReplayMousePressOutsidePopup).toBool()) {
+ if (m_widget->windowType() != Qt::Popup)
+ qt_button_down = nullptr;
+ if (event->type() == QEvent::MouseButtonPress) {
+ // the popup disappeared: replay the mouse press event to whatever is behind it
+ QWidget *w = QApplication::widgetAt(event->globalPosition().toPoint());
+ if (w && !QApplicationPrivate::isBlockedByModal(w)) {
+ // activate window of the widget under mouse pointer
+ if (!w->isActiveWindow()) {
+ w->activateWindow();
+ w->window()->raise();
+ }
+
+ if (auto win = qt_widget_private(w)->windowHandle(QWidgetPrivate::WindowHandleMode::Closest)) {
+ const QRect globalGeometry = win->isTopLevel()
+ ? win->geometry()
+ : QRect(win->mapToGlobal(QPoint(0, 0)), win->size());
+ if (globalGeometry.contains(event->globalPosition().toPoint())) {
+ // Use postEvent() to ensure the local QEventLoop terminates when called from QMenu::exec()
+ const QPoint localPos = win->mapFromGlobal(event->globalPosition().toPoint());
+ QMouseEvent *e = new QMouseEvent(QEvent::MouseButtonPress, localPos, localPos, event->globalPosition().toPoint(),
+ event->button(), event->buttons(), event->modifiers(), event->source());
+ QCoreApplicationPrivate::setEventSpontaneous(e, true);
+ e->setTimestamp(event->timestamp());
+ QCoreApplication::postEvent(win, e);
+ }
+ }
+ }
+ }
+ QApplicationPrivate::replayMousePress = false;
+ }
+
if (releaseAfter) {
qt_button_down = nullptr;
qt_popup_down_closed = false;