summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSamuel Rødal <samuel.rodal@nokia.com>2012-06-13 17:05:52 +0200
committerQt by Nokia <qt-info@nokia.com>2012-06-18 21:58:30 +0200
commit7967cb4f4860df436dc2e7e21c4eaca6a9b05f70 (patch)
tree7ea97e7dd0f56900d8b1304e22d2c6b659d08c36 /src
parent3c8eb404877df9c967d81fa9df7d718c538fb407 (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.cpp30
-rw-r--r--src/gui/kernel/qguiapplication_p.h1
-rw-r--r--src/gui/kernel/qwindow.cpp4
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);
}
/*!