Index: trunk/src/gui/kernel/qapplication_pm.cpp
===================================================================
--- trunk/src/gui/kernel/qapplication_pm.cpp	(revision 108)
+++ trunk/src/gui/kernel/qapplication_pm.cpp	(revision 109)
@@ -104,4 +104,6 @@
 extern QCursor *qt_grab_cursor();
 
+extern void qt_WinQueryClipRegionOrRect(HWND hwnd, HRGN hrgn); // qwidget_pm.cpp
+
 MRESULT EXPENTRY QtWndProc(HWND, ULONG, MPARAM, MPARAM);
 
@@ -125,6 +127,6 @@
 #endif
     bool        translatePaintEvent(const QMSG &qmsg);
-//  bool        translateConfigEvent(const MSG &msg);
-//  bool        translateCloseEvent(const MSG &msg);
+//  bool        translateConfigEvent(const QMSG &msg);
+    bool        translateCloseEvent(const QMSG &qmsg);
 //  void        repolishStyle(QStyle &style);
 //  inline void showChildren(bool spontaneous) { d_func()->showChildren(spontaneous); }
@@ -333,11 +335,15 @@
 void  QApplication::setCursorFlashTime(int msecs)
 {
-    // @todo implement
-}
-
+    WinSetSysValue(HWND_DESKTOP, SV_CURSORRATE, msecs / 2);
+    QApplicationPrivate::cursor_flash_time = msecs;
+}
 
 int QApplication::cursorFlashTime()
 {
-    // @todo implement
+    int blink = (int)WinQuerySysValue(HWND_DESKTOP, SV_CURSORRATE);
+    if (!blink)
+        return QApplicationPrivate::cursor_flash_time;
+    if (blink > 0)
+        return 2 * blink;
     return 0;
 }
@@ -345,23 +351,25 @@
 void QApplication::setDoubleClickInterval(int ms)
 {
-    // @todo implement
+    WinSetSysValue(HWND_DESKTOP, SV_DBLCLKTIME, ms);
+    QApplicationPrivate::mouse_double_click_time = ms;
 }
 
 int QApplication::doubleClickInterval()
 {
-    // @todo implement
-    return 0;
-}
-
+    int ms = (int) WinQuerySysValue(HWND_DESKTOP, SV_DBLCLKTIME);
+    if (ms != 0)
+        return ms;
+    return QApplicationPrivate::mouse_double_click_time;
+}
 
 void QApplication::setKeyboardInputInterval(int ms)
 {
-    // @todo implement
+    QApplicationPrivate::keyboard_input_time = ms;
 }
 
 int QApplication::keyboardInputInterval()
 {
-    // @todo implement
-    return 0;
+    // FIXME: get from the system
+    return QApplicationPrivate::keyboard_input_time;
 }
 
@@ -369,11 +377,10 @@
 void QApplication::setWheelScrollLines(int n)
 {
-    // @todo implement
+    QApplicationPrivate::wheel_scroll_lines = n;
 }
 
 int QApplication::wheelScrollLines()
 {
-    // @todo implement
-    return 0;
+    return QApplicationPrivate::wheel_scroll_lines;
 }
 #endif //QT_NO_WHEELEVENT
@@ -392,5 +399,5 @@
 void QApplication::beep()
 {
-    // @todo implement
+    WinAlarm(HWND_DESKTOP, WA_WARNING);
 }
 
@@ -431,4 +438,19 @@
   Main event loop
  *****************************************************************************/
+
+// sent to hwnd that has been entered to by a mouse pointer.
+// FID_CLIENT also receives enter messages of its WC_FRAME.
+// mp1 = hwnd that is entered, mp2 = hwnd that is left
+#define WM_U_MOUSEENTER 0x41E
+// sent to hwnd that has been left by a mouse pointer.
+// FID_CLIENT also receives leave messages of its WC_FRAME.
+// mp1 = hwnd that is left, mp2 = hwnd that is entered
+#define WM_U_MOUSELEAVE 0x41F
+
+// some undocumented system values
+#define SV_WORKAREA_YTOP    51
+#define SV_WORKAREA_YBOTTOM 52
+#define SV_WORKAREA_XRIGHT  53
+#define SV_WORKAREA_XLEFT   54
 
 // QtWndProc() receives all messages from the main event loop
@@ -537,7 +559,26 @@
             case WM_SHOW: {
                 // @todo there is some more processing in Qt4, see
-                // WM_SHOWWINDOW in Win32 sources
+                // WM_SHOWWINDOW in qapplication_win.cpp
                 if (!SHORT1FROMMP(mp1) && autoCaptureWnd == widget->internalWinId())
                     releaseAutoCapture();
+                break;
+            }
+
+            case WM_CLOSE: { // close window
+                widget->translateCloseEvent(qmsg);
+                return (MRESULT)TRUE;
+            }
+
+            case WM_DESTROY: { // destroy window
+                if (hwnd == curWin) {
+                    QWidget *enter = QWidget::mouseGrabber();
+                    if (enter == widget)
+                        enter = 0;
+                    QApplicationPrivate::dispatchEnterLeave(enter, widget);
+                    curWin = enter ? enter->effectiveWinId() : 0;
+                    qt_last_mouse_receiver = enter;
+                }
+                if (widget == popupButtonFocus)
+                    popupButtonFocus = 0;
                 break;
             }
@@ -564,4 +605,47 @@
 #endif
 
+            case WM_U_MOUSELEAVE: {
+                // We receive a mouse leave for curWin, meaning
+                // the mouse was moved outside our widgets
+                if (widget->internalWinId() == curWin) {
+                    bool dispatch = !widget->underMouse();
+                    // hasMouse is updated when dispatching enter/leave,
+                    // so test if it is actually up-to-date
+                    if (!dispatch) {
+                        QRect geom = widget->geometry();
+                        if (widget->parentWidget() && !widget->isWindow()) {
+                            QPoint gp = widget->parentWidget()->mapToGlobal(widget->pos());
+                            geom.setX(gp.x());
+                            geom.setY(gp.y());
+                        }
+                        QPoint cpos = QCursor::pos();
+                        dispatch = !geom.contains(cpos);
+                        if ( !dispatch && !QWidget::mouseGrabber()) {
+                            QWidget *hittest = QApplication::widgetAt(cpos);
+                            dispatch = !hittest || hittest->internalWinId() != curWin;
+                        }
+                        if (!dispatch) {
+                            HPS hps = qt_display_ps();
+                            HRGN hrgn = GpiCreateRegion(hps, 0, NULL);
+                            qt_WinQueryClipRegionOrRect(hwnd, hrgn);
+                            QPoint lcpos = widget->mapFromGlobal(cpos);
+                            // flip y coordinate
+                            POINTL pt = { lcpos.x(), widget->height() - (lcpos.y() + 1) };
+                            dispatch = !GpiPtInRegion(hps, hrgn, &pt);
+                            GpiDestroyRegion(hps, hrgn);
+                        }
+                    }
+                    if (dispatch) {
+                        if (qt_last_mouse_receiver && !qt_last_mouse_receiver->internalWinId())
+                            QApplicationPrivate::dispatchEnterLeave(0, qt_last_mouse_receiver);
+                        else
+                            QApplicationPrivate::dispatchEnterLeave(0, QWidget::find((WId)curWin));
+                        curWin = 0;
+                        qt_last_mouse_receiver = 0;
+                    }
+                }
+                break;
+            }
+
             default:
                 break;
@@ -620,22 +704,92 @@
 bool QApplicationPrivate::modalState()
 {
-    // @todo implement
-    return false;
+    return app_do_modal;
 }
 
 void QApplicationPrivate::enterModal_sys(QWidget *widget)
 {
-    // @todo implement
+    if (!qt_modal_stack)
+        qt_modal_stack = new QWidgetList;
+
+    releaseAutoCapture();
+    QWidget *leave = qt_last_mouse_receiver;
+    if (!leave)
+        leave = QWidget::find(curWin);
+    QApplicationPrivate::dispatchEnterLeave(0, leave);
+    qt_modal_stack->insert(0, widget);
+    app_do_modal = true;
+    curWin = 0;
+    qt_last_mouse_receiver = 0;
+    ignoreNextMouseReleaseEvent = false;
 }
 
 void QApplicationPrivate::leaveModal_sys(QWidget *widget)
 {
-    // @todo implement
-}
-
-bool qt_try_modal(QWidget *widget, QMSG *qmsg, MRESULT& rc)
-{
-    // @todo implement
-    return false;
+    if (qt_modal_stack && qt_modal_stack->removeAll(widget)) {
+        if (qt_modal_stack->isEmpty()) {
+            delete qt_modal_stack;
+            qt_modal_stack = 0;
+            QPoint p(QCursor::pos());
+            app_do_modal = false; // necessary, we may get recursively into qt_try_modal below
+            QWidget* w = QApplication::widgetAt(p.x(), p.y());
+            QWidget *leave = qt_last_mouse_receiver;
+            if (!leave)
+                leave = QWidget::find(curWin);
+            if (QWidget *grabber = QWidget::mouseGrabber()) {
+                w = grabber;
+                if (leave == w)
+                    leave = 0;
+            }
+            QApplicationPrivate::dispatchEnterLeave(w, leave); // send synthetic enter event
+            curWin = w ? w->effectiveWinId() : 0;
+            qt_last_mouse_receiver = w;
+        }
+        ignoreNextMouseReleaseEvent = true;
+    }
+    app_do_modal = qt_modal_stack != 0;
+}
+
+bool qt_try_modal(QWidget *widget, QMSG *qmsg, MRESULT &rc)
+{
+    QWidget *top = 0;
+
+    if (QApplicationPrivate::tryModalHelper(widget, &top))
+        return true;
+
+    int type = qmsg->msg;
+
+    bool block_event = false;
+    if ((type >= WM_MOUSEFIRST && type <= WM_MOUSELAST) ||
+        (type >= WM_EXTMOUSEFIRST && type <= WM_EXTMOUSELAST) ||
+         type == WM_VSCROLL || type == WM_HSCROLL ||
+         type == WM_U_MOUSELEAVE ||
+         type == WM_CHAR) {
+        if (type == WM_MOUSEMOVE) {
+#ifndef QT_NO_CURSOR
+            QCursor *c = qt_grab_cursor();
+            if (!c)
+                c = QApplication::overrideCursor();
+            if (c) // application cursor defined
+                WinSetPointer(HWND_DESKTOP, c->handle());
+            else
+                WinSetPointer(HWND_DESKTOP, QCursor(Qt::ArrowCursor).handle());
+#endif // QT_NO_CURSOR
+        } else if (type == WM_BUTTON1DOWN || type == type == WM_BUTTON2DOWN ||
+                   type == WM_BUTTON3DOWN) {
+            if (!top->isActiveWindow()) {
+                top->activateWindow();
+            } else {
+                QApplication::beep();
+            }
+        }
+        block_event = true;
+    } else if (type == WM_CLOSE) {
+        block_event = true;
+    } else if (type == WM_SYSCOMMAND) {
+        if (!(SHORT1FROMMP(qmsg->mp1) == SC_RESTORE && widget->isMinimized()))
+            block_event = true;
+    }
+
+    return !block_event;
 }
 
@@ -1245,3 +1399,15 @@
 #endif
 
+//
+// Close window event translation.
+//
+// This class is a friend of QApplication because it needs to emit the
+// lastWindowClosed() signal when the last top level widget is closed.
+//
+
+bool QETWidget::translateCloseEvent(const QMSG &)
+{
+    return d_func()->close_helper(QWidgetPrivate::CloseWithSpontaneousEvent);
+}
+
 QT_END_NAMESPACE
