winex11.drv: Handle WM_DELETE_WINDOW by simulating clicking the caption Close button.

Dmitry Timoshkov dmitry at codeweavers.com
Wed Sep 9 03:21:52 CDT 2009


Currently Winword crashes when someone tries to close a modified document
by clicking the caption Close button and answer 'No' whether to save.

The problem is with processing internal WM_X11DRV_DELETE_WINDOW message in
response to WM_DELETE_WINDOW event. Word's message processing loop looks
similar to the following:

if (PeekMessage(&msg, 0, 0, 0, PM_NOYIELD))
{
    if (!PeekMessage(&msg, 0, msg.message, msg.message, PM_REMOVE))
        assert(0);
    TranslateMessage(&msg);
    DispatchMessage(&msg);
}

and it appears that Word doesn't like when main window disappears inside of
PeekMessage(&msg, 0, 0, 0, PM_NOYIELD) call.

This patch follows Alexandre's suggestion and makes Word not crash on exit.
---
 dlls/winex11.drv/event.c  |    8 ++++++--
 dlls/winex11.drv/window.c |    2 --
 dlls/winex11.drv/x11drv.h |    1 -
 3 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c
index 9a489cd..542fce8 100644
--- a/dlls/winex11.drv/event.c
+++ b/dlls/winex11.drv/event.c
@@ -511,6 +511,7 @@ static void handle_wm_protocols( HWND hwnd, XClientMessageEvent *event )
         if (IsWindowEnabled(hwnd))
         {
             HMENU hSysMenu;
+            POINT pt;
 
             if (GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE) return;
             hSysMenu = GetSystemMenu(hwnd, FALSE);
@@ -524,7 +525,7 @@ static void handle_wm_protocols( HWND hwnd, XClientMessageEvent *event )
             {
                 LRESULT ma = SendMessageW( hwnd, WM_MOUSEACTIVATE,
                                            (WPARAM)GetAncestor( hwnd, GA_ROOT ),
-                                           MAKELONG(HTCLOSE,WM_LBUTTONDOWN) );
+                                           MAKELPARAM( HTCLOSE, WM_NCLBUTTONDOWN ) );
                 switch(ma)
                 {
                     case MA_NOACTIVATEANDEAT:
@@ -541,7 +542,10 @@ static void handle_wm_protocols( HWND hwnd, XClientMessageEvent *event )
                         break;
                 }
             }
-            PostMessageW( hwnd, WM_X11DRV_DELETE_WINDOW, 0, 0 );
+            /* Simulate clicking the caption Close button */
+            GetCursorPos( &pt );
+            PostMessageW( hwnd, WM_NCLBUTTONDOWN, HTCLOSE, MAKELPARAM( pt.x, pt.y ) );
+            PostMessageW( hwnd, WM_LBUTTONUP, HTCLOSE, MAKELPARAM( pt.x, pt.y ) );
         }
     }
     else if (protocol == x11drv_atom(WM_TAKE_FOCUS))
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c
index 19551fa..4bbd5de 100644
--- a/dlls/winex11.drv/window.c
+++ b/dlls/winex11.drv/window.c
@@ -2308,8 +2308,6 @@ LRESULT CDECL X11DRV_WindowMessage( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
     {
     case WM_X11DRV_ACQUIRE_SELECTION:
         return X11DRV_AcquireClipboard( hwnd );
-    case WM_X11DRV_DELETE_WINDOW:
-        return SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, 0 );
     case WM_X11DRV_SET_WIN_FORMAT:
         return set_win_format( hwnd, (XID)wp );
     case WM_X11DRV_SET_WIN_REGION:
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index 404be34..eb84089 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -700,7 +700,6 @@ extern DWORD EVENT_x11_time_to_win32_time(Time time);
 enum x11drv_window_messages
 {
     WM_X11DRV_ACQUIRE_SELECTION = 0x80001000,
-    WM_X11DRV_DELETE_WINDOW,
     WM_X11DRV_SET_WIN_FORMAT,
     WM_X11DRV_SET_WIN_REGION,
     WM_X11DRV_RESIZE_DESKTOP
-- 
1.6.4.2




More information about the wine-patches mailing list