diff options
author | Samuel Rødal <samuel.rodal@nokia.com> | 2012-06-13 17:05:52 +0200 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-06-18 21:58:30 +0200 |
commit | 7967cb4f4860df436dc2e7e21c4eaca6a9b05f70 (patch) | |
tree | 7ea97e7dd0f56900d8b1304e22d2c6b659d08c36 /src | |
parent | 3c8eb404877df9c967d81fa9df7d718c538fb407 (diff) |
Prevent ending up in a state where focus is perpetually grabbed.
Mouse / enter / leave / key events etc are all blocked when a window has
the blockedByModalWindow flag set. The problem appears if a QWindow is
created and only later directly or indirectly parented to a modal window
that's currently showing. Since the decision on whether a window should
be blocked or not is based on its parent / transient parent chain, we
need to reevaluate the blocked status each time the parent or transient
parent of a window changes.
Task-number: QTBUG-26112
Change-Id: Ida6b118b556fe26d17fa86335a0fe7baddc7eaf8
Reviewed-by: Lars Knoll <lars.knoll@nokia.com>
Reviewed-by: Bradley T. Hughes <bradley.hughes@nokia.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/gui/kernel/qguiapplication.cpp | 30 | ||||
-rw-r--r-- | src/gui/kernel/qguiapplication_p.h | 1 | ||||
-rw-r--r-- | src/gui/kernel/qwindow.cpp | 4 |
3 files changed, 25 insertions, 10 deletions
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 3cd8d5f800..e22ccc762d 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -402,18 +402,30 @@ QWindow *QGuiApplication::modalWindow() return QGuiApplicationPrivate::self->modalWindowList.first(); } -void QGuiApplicationPrivate::showModalWindow(QWindow *window) +void QGuiApplicationPrivate::updateBlockedStatus(QWindow *window) { - self->modalWindowList.prepend(window); + bool shouldBeBlocked = false; + if (window->windowType() != Qt::Tool && !self->modalWindowList.isEmpty()) + shouldBeBlocked = self->isWindowBlocked(window); + + if (shouldBeBlocked != window->d_func()->blockedByModalWindow) { + QEvent e(shouldBeBlocked ? QEvent::WindowBlocked : QEvent::WindowUnblocked); + + window->d_func()->blockedByModalWindow = shouldBeBlocked; + QGuiApplication::sendEvent(window, &e); + } +} + +void QGuiApplicationPrivate::showModalWindow(QWindow *modal) +{ + self->modalWindowList.prepend(modal); QEvent e(QEvent::WindowBlocked); QWindowList windows = QGuiApplication::topLevelWindows(); for (int i = 0; i < windows.count(); ++i) { QWindow *window = windows.at(i); - if (!window->d_func()->blockedByModalWindow && window->windowType() != Qt::Tool && self->isWindowBlocked(window)) { - window->d_func()->blockedByModalWindow = true; - QGuiApplication::sendEvent(window, &e); - } + if (!window->d_func()->blockedByModalWindow) + updateBlockedStatus(window); } } @@ -425,10 +437,8 @@ void QGuiApplicationPrivate::hideModalWindow(QWindow *window) QWindowList windows = QGuiApplication::topLevelWindows(); for (int i = 0; i < windows.count(); ++i) { QWindow *window = windows.at(i); - if (window->d_func()->blockedByModalWindow && window->windowType() != Qt::Tool && !self->isWindowBlocked(window)) { - window->d_func()->blockedByModalWindow = false; - QGuiApplication::sendEvent(window, &e); - } + if (window->d_func()->blockedByModalWindow) + updateBlockedStatus(window); } } diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h index 76f0a71270..a564120a3b 100644 --- a/src/gui/kernel/qguiapplication_p.h +++ b/src/gui/kernel/qguiapplication_p.h @@ -168,6 +168,7 @@ public: QWindowList modalWindowList; static void showModalWindow(QWindow *window); static void hideModalWindow(QWindow *window); + static void updateBlockedStatus(QWindow *window); virtual bool isWindowBlocked(QWindow *window, QWindow **blockingWindow = 0) const; static Qt::MouseButtons buttons; diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp index f30a794b55..d6f0aab50d 100644 --- a/src/gui/kernel/qwindow.cpp +++ b/src/gui/kernel/qwindow.cpp @@ -360,6 +360,8 @@ void QWindow::setParent(QWindow *parent) } d->parentWindow = parent; + + QGuiApplicationPrivate::updateBlockedStatus(this); } /*! @@ -784,6 +786,8 @@ void QWindow::setTransientParent(QWindow *parent) { Q_D(QWindow); d->transientParent = parent; + + QGuiApplicationPrivate::updateBlockedStatus(this); } /*! |