Add focus and modal dialog support.
authorLaszlo Agocs <laszlo.p.agocs@nokia.com>
Mon, 30 May 2011 12:16:43 +0000 (14:16 +0200)
committerLaszlo Agocs <laszlo.p.agocs@nokia.com>
Mon, 30 May 2011 12:41:14 +0000 (14:41 +0200)
Reviewed-by: Samuel Rødal
src/gui/kernel/qguiapplication.cpp
src/gui/kernel/qguiapplication_p.h
src/widgets/kernel/qapplication.cpp
src/widgets/kernel/qapplication_p.h
src/widgets/kernel/qapplication_qpa.cpp
src/widgets/kernel/qwidget_qpa.cpp
src/widgets/kernel/qwidgetwindow_qpa.cpp

index d837fb0..cbf4a94 100644 (file)
@@ -583,7 +583,10 @@ void QGuiApplicationPrivate::processLeaveEvent(QWindowSystemInterfacePrivate::Le
 
 void QGuiApplicationPrivate::processActivatedEvent(QWindowSystemInterfacePrivate::ActivatedWindowEvent *e)
 {
+    QWindow *previous = QGuiApplicationPrivate::active_window;
     QGuiApplicationPrivate::active_window = e->activated.data();
+    if (self)
+        self->notifyActiveWindowChange(previous);
 }
 
 void QGuiApplicationPrivate::processGeometryChangeEvent(QWindowSystemInterfacePrivate::GeometryChangeEvent *e)
@@ -721,6 +724,10 @@ void QGuiApplicationPrivate::notifyLayoutDirectionChange()
 {
 }
 
+void QGuiApplicationPrivate::notifyActiveWindowChange(QWindow *)
+{
+}
+
 /*!
     \property QGuiApplication::layoutDirection
     \brief the default layout direction for this application
index 80aa5a5..2d0f16c 100644 (file)
@@ -70,6 +70,7 @@ public:
     void createEventDispatcher();
 
     virtual void notifyLayoutDirectionChange();
+    virtual void notifyActiveWindowChange(QWindow *previous);
 
     static int keyboard_input_time;
     static int mouse_double_click_time;
index 15cad61..13a4eca 100644 (file)
@@ -536,7 +536,8 @@ QDesktopWidget *qt_desktopWidget = 0;                // root window widgets
 #if !defined(Q_WS_QPA) && !defined(QT_NO_CLIPBOARD)
 QClipboard              *qt_clipboard = 0;        // global clipboard object
 #endif
-QWidgetList * qt_modal_stack=0;                // stack of modal widgets
+QWidgetList * qt_modal_stack = 0;                // stack of modal widgets
+bool app_do_modal = false;
 
 /*!
     \internal
@@ -2422,7 +2423,6 @@ void QApplicationPrivate::notifyLayoutDirectionChange()
     }
 }
 
-
 /*!
     \fn Qt::WindowsVersion QApplication::winVersion()
 
@@ -2790,7 +2790,6 @@ bool QApplicationPrivate::isBlockedByModal(QWidget *widget)
     if (QApplication::activePopupWidget() == widget)
         return false;
 
-#if 0
     for (int i = 0; i < qt_modal_stack->size(); ++i) {
         QWidget *modalWidget = qt_modal_stack->at(i);
 
@@ -2869,7 +2868,6 @@ bool QApplicationPrivate::isBlockedByModal(QWidget *widget)
             break;
         }
     }
-#endif
     return false;
 }
 
index ad649f6..40308db 100644 (file)
@@ -304,6 +304,7 @@ public:
     ~QApplicationPrivate();
 
     virtual void notifyLayoutDirectionChange();
+    virtual void notifyActiveWindowChange(QWindow *);
 
 #if defined(Q_WS_X11)
 #ifndef QT_NO_SETTINGS
index 4ed8eda..0210c14 100644 (file)
@@ -71,6 +71,8 @@ QT_BEGIN_NAMESPACE
 
 static QString appName;
 static QString appFont;
+extern bool app_do_modal;
+extern QWidgetList *qt_modal_stack;
 
 QString QApplicationPrivate::appName() const
 {
@@ -82,7 +84,7 @@ void QApplicationPrivate::createEventDispatcher()
     QGuiApplicationPrivate::createEventDispatcher();
 }
 
-static bool qt_try_modal(QWidget *widget, QEvent::Type type)
+bool qt_try_modal(QWidget *widget, QEvent::Type type)
 {
     QWidget * top = 0;
 
@@ -116,21 +118,16 @@ static bool qt_try_modal(QWidget *widget, QEvent::Type type)
     return !block_event;
 }
 
-
-
-void QApplicationPrivate::enterModal_sys(QWidget *)
+void QApplicationPrivate::enterModal_sys(QWidget *widget)
 {
-#if 0
     if (!qt_modal_stack)
         qt_modal_stack = new QWidgetList;
     qt_modal_stack->insert(0, widget);
     app_do_modal = true;
-#endif
 }
 
-void QApplicationPrivate::leaveModal_sys(QWidget *)
+void QApplicationPrivate::leaveModal_sys(QWidget *widget)
 {
-#if 0
     if (qt_modal_stack && qt_modal_stack->removeAll(widget)) {
         if (qt_modal_stack->isEmpty()) {
             delete qt_modal_stack;
@@ -138,15 +135,36 @@ void QApplicationPrivate::leaveModal_sys(QWidget *)
         }
     }
     app_do_modal = qt_modal_stack != 0;
-#endif
 }
 
 bool QApplicationPrivate::modalState()
 {
-    return false;
-#if 0
     return app_do_modal;
-#endif
+}
+
+QWidget *qt_tlw_for_window(QWindow *wnd)
+{
+    if (wnd)
+        foreach (QWidget *tlw, qApp->topLevelWidgets())
+            if (tlw->windowHandle() == wnd)
+                return tlw;
+    return 0;
+}
+
+void QApplicationPrivate::notifyActiveWindowChange(QWindow *previous)
+{
+    Q_UNUSED(previous);
+    Q_Q(QApplication);
+    QWindow *wnd = QGuiApplicationPrivate::active_window;
+    QWidget *tlw = qt_tlw_for_window(wnd);
+    if (!tlw)
+        return;
+    if (modalState()
+        && !qt_try_modal(tlw, QEvent::MouseButtonRelease)
+        && q->activeWindow())
+        q->activeWindow()->activateWindow();
+    else
+        q->setActiveWindow(tlw);
 }
 
 void QApplicationPrivate::closePopup(QWidget *popup)
index 2120e40..99db2f5 100644 (file)
@@ -740,8 +740,11 @@ QWindow *QWidget::windowHandle() const
 {
     Q_D(const QWidget);
     QTLWExtra *extra = d->maybeTopData();
-    if (extra && extra->window)
+    if (extra) {
+        if (!extra->window)
+            const_cast<QWidgetPrivate *>(d)->createTLSysExtra();
         return extra->window;
+    }
 
     return 0;
 }
index 4bee0f2..38156d3 100644 (file)
@@ -52,6 +52,7 @@ QWidget *qt_button_down = 0; // widget got last button-down
 static QWidget *qt_popup_down = 0; // popup that contains the pressed widget
 extern int openPopupCount;
 static bool replayPopupMouseEvent = false;
+extern bool qt_try_modal(QWidget *widget, QEvent::Type type);
 
 QWidgetWindow::QWidgetWindow(QWidget *widget)
     : m_widget(widget)
@@ -203,6 +204,10 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event)
         return;
     }
 
+    // modal event handling
+    if (QApplicationPrivate::instance()->modalState() && !qt_try_modal(m_widget, event->type()))
+        return;
+
     // which child should have it?
     QWidget *widget = m_widget->childAt(event->pos());
     QPoint mapped = event->pos();
@@ -237,6 +242,9 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event)
 
 void QWidgetWindow::handleKeyEvent(QKeyEvent *event)
 {
+    if (QApplicationPrivate::instance()->modalState() && !qt_try_modal(m_widget, event->type()))
+        return;
+
     QWidget *widget = m_widget->focusWidget();
 
     if (!widget)
@@ -264,6 +272,9 @@ void QWidgetWindow::handleCloseEvent(QCloseEvent *)
 
 void QWidgetWindow::handleWheelEvent(QWheelEvent *event)
 {
+    if (QApplicationPrivate::instance()->modalState() && !qt_try_modal(m_widget, event->type()))
+        return;
+
     // which child should have it?
     QWidget *widget = m_widget->childAt(event->pos());