summaryrefslogtreecommitdiffstats
path: root/src/gui/kernel/qguiapplication.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/kernel/qguiapplication.cpp')
-rw-r--r--src/gui/kernel/qguiapplication.cpp158
1 files changed, 157 insertions, 1 deletions
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index 6a93ef4d09..36b2d261e4 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -114,7 +114,6 @@ enum ApplicationResourceFlags
static unsigned applicationResourceFlags = 0;
QString *QGuiApplicationPrivate::platform_name = 0;
-bool QGuiApplicationPrivate::app_do_modal = false;
QPalette *QGuiApplicationPrivate::app_pal = 0; // default application palette
@@ -381,6 +380,132 @@ QGuiApplicationPrivate::QGuiApplicationPrivate(int &argc, char **argv, int flags
}
/*!
+ Returns the most recently shown modal window. If no modal windows are
+ visible, this function returns zero.
+
+ A modal window is a window which has its
+ \l{QWindow::windowModality}{windowModality} property set to Qt::WindowModal
+ or Qt::ApplicationModal. A modal window must be closed before the user can
+ continue with other parts of the program.
+
+ Modal window are organized in a stack. This function returns the modal
+ window at the top of the stack.
+
+ \sa Qt::WindowModality, QWindow::setWindowModality()
+*/
+QWindow *QGuiApplication::modalWindow()
+{
+ if (QGuiApplicationPrivate::self->modalWindowList.isEmpty())
+ return 0;
+ return QGuiApplicationPrivate::self->modalWindowList.first();
+}
+
+void QGuiApplicationPrivate::showModalWindow(QWindow *window)
+{
+ self->modalWindowList.prepend(window);
+
+ 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);
+ }
+ }
+}
+
+void QGuiApplicationPrivate::hideModalWindow(QWindow *window)
+{
+ self->modalWindowList.removeAll(window);
+
+ QEvent e(QEvent::WindowUnblocked);
+ 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);
+ }
+ }
+}
+
+/*
+ Returns true if \a window is blocked by a modal window. If \a
+ blockingWindow is non-zero, *blockingWindow will be set to the blocking
+ window (or to zero if \a window is not blocked).
+*/
+bool QGuiApplicationPrivate::isWindowBlocked(QWindow *window, QWindow **blockingWindow) const
+{
+ QWindow *unused = 0;
+ if (!blockingWindow)
+ blockingWindow = &unused;
+
+ if (modalWindowList.isEmpty()) {
+ *blockingWindow = 0;
+ return false;
+ }
+
+ for (int i = 0; i < modalWindowList.count(); ++i) {
+ QWindow *modalWindow = modalWindowList.at(i);
+
+ {
+ // check if the modal window is our window or a (transient) parent of our window
+ QWindow *w = window;
+ while (w) {
+ if (w == modalWindow) {
+ *blockingWindow = 0;
+ return false;
+ }
+ QWindow *p = w->parent();
+ if (!p)
+ p = w->transientParent();
+ w = p;
+ }
+ }
+
+ Qt::WindowModality windowModality = modalWindow->windowModality();
+ switch (windowModality) {
+ case Qt::ApplicationModal:
+ {
+ if (modalWindow != window) {
+ *blockingWindow = modalWindow;
+ return true;
+ }
+ break;
+ }
+ case Qt::WindowModal:
+ {
+ QWindow *w = window;
+ do {
+ QWindow *m = modalWindow;
+ do {
+ if (m == w) {
+ *blockingWindow = m;
+ return true;
+ }
+ QWindow *p = m->parent();
+ if (!p)
+ p = m->transientParent();
+ m = p;
+ } while (m);
+ QWindow *p = w->parent();
+ if (!p)
+ p = w->transientParent();
+ w = p;
+ } while (w);
+ break;
+ }
+ default:
+ Q_ASSERT_X(false, "QGuiApplication", "internal error, a modal widget cannot be modeless");
+ break;
+ }
+ }
+ *blockingWindow = 0;
+ return false;
+}
+
+/*!
Returns the QWindow that receives events tied to focus,
such as key events.
*/
@@ -1049,6 +1174,11 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo
}
if (window) {
+ if (window->d_func()->blockedByModalWindow) {
+ // a modal window is blocking this window, don't allow mouse events through
+ return;
+ }
+
QMouseEvent ev(type, localPoint, localPoint, globalPoint, button, buttons, e->modifiers);
ev.setTimestamp(e->timestamp);
#ifndef QT_NO_CURSOR
@@ -1111,6 +1241,11 @@ void QGuiApplicationPrivate::processWheelEvent(QWindowSystemInterfacePrivate::Wh
QWindow *window = e->window.data();
if (window) {
+ if (window->d_func()->blockedByModalWindow) {
+ // a modal window is blocking this window, don't allow wheel events through
+ return;
+ }
+
QWheelEvent ev(e->localPos, e->globalPos, e->pixelDelta, e->angleDelta, e->qt4Delta, e->qt4Orientation, buttons, e->modifiers);
ev.setTimestamp(e->timestamp);
QGuiApplication::sendSpontaneousEvent(window, &ev);
@@ -1128,6 +1263,10 @@ void QGuiApplicationPrivate::processKeyEvent(QWindowSystemInterfacePrivate::KeyE
window = QGuiApplication::activeWindow();
if (!window)
return;
+ if (window->d_func()->blockedByModalWindow) {
+ // a modal window is blocking this window, don't allow key events through
+ return;
+ }
QKeyEvent ev(e->keyType, e->key, e->modifiers,
e->nativeScanCode, e->nativeVirtualKey, e->nativeModifiers,
@@ -1140,6 +1279,10 @@ void QGuiApplicationPrivate::processEnterEvent(QWindowSystemInterfacePrivate::En
{
if (!e->enter)
return;
+ if (e->enter.data()->d_func()->blockedByModalWindow) {
+ // a modal window is blocking this window, don't allow enter events through
+ return;
+ }
QEvent event(QEvent::Enter);
QCoreApplication::sendSpontaneousEvent(e->enter.data(), &event);
@@ -1149,6 +1292,10 @@ void QGuiApplicationPrivate::processLeaveEvent(QWindowSystemInterfacePrivate::Le
{
if (!e->leave)
return;
+ if (e->leave.data()->d_func()->blockedByModalWindow) {
+ // a modal window is blocking this window, don't allow leave events through
+ return;
+ }
QEvent event(QEvent::Leave);
QCoreApplication::sendSpontaneousEvent(e->leave.data(), &event);
@@ -1263,6 +1410,10 @@ void QGuiApplicationPrivate::processCloseEvent(QWindowSystemInterfacePrivate::Cl
{
if (e->window.isNull())
return;
+ if (e->window.data()->d_func()->blockedByModalWindow) {
+ // a modal window is blocking this window, don't allow close events through
+ return;
+ }
QCloseEvent event;
QGuiApplication::sendSpontaneousEvent(e->window.data(), &event);
@@ -1451,6 +1602,11 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To
break;
}
+ if (w->d_func()->blockedByModalWindow) {
+ // a modal window is blocking this window, don't allow touch events through
+ continue;
+ }
+
QTouchEvent touchEvent(eventType,
e->device,
e->modifiers,