[PATCH] user32/tests: Added tests for infinite WM_PAINT loop (resent)

Austin Lund austin.lund at gmail.com
Wed Jul 22 19:27:12 CDT 2009


-------------- next part --------------
From 1ece9154b124bfbe3a7937f0629f6c73b2c9ac78 Mon Sep 17 00:00:00 2001
From: Austin Lund <austin.lund at gmail.com>
Date: Fri, 10 Jul 2009 09:10:07 +1000
Subject: [PATCH] user32/tests: Added tests for infinite WM_PAINT loop

In most situations processing a WM_PAINT message should leave the
entire window validated when it returns.  Bug 10522 displays a
situation where this is not true in Wine (when using Microsoft
software).  Programs which trigger this problem have a call to
RedrawWindow() with RDW_FRAME and RDW_INVALIDATE flags set when
processing a WM_NCPAINT message.  In Windows when the WM_PAINT
message calls BeginPaint(), WM_NCPAINT may be called and it would
invalidate the entire window due to the RedrawWindow() call.  But
when BeginPaint() returns, the entire window is validated.  In
Wine this is not the case.  So when processing the WM_PAINT
message is finished, Wine leaves the window invalid where as
Windows does not.  This patch adds a test for this behaviour.
---
 dlls/user32/tests/win.c |   99 +++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 99 insertions(+), 0 deletions(-)

diff --git a/dlls/user32/tests/win.c b/dlls/user32/tests/win.c
index d45eba3..8e1c1ca 100644
--- a/dlls/user32/tests/win.c
+++ b/dlls/user32/tests/win.c
@@ -4859,6 +4859,104 @@ static void test_Expose(void)
     DestroyWindow(mw);
 }
 
+static LRESULT CALLBACK TestNCRedraw_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+    static UINT ncredrawflags;
+    PAINTSTRUCT ps;
+    RECT rect;
+    BOOL updateRectValue;
+
+    switch(msg) {
+    case WM_CREATE:
+        ncredrawflags = *(UINT *) (((CREATESTRUCT *)lParam)->lpCreateParams);
+        return 0;
+    case WM_NCPAINT:
+        updateRectValue = GetUpdateRect(hwnd, &rect, FALSE);
+        RedrawWindow(hwnd, NULL, NULL, ncredrawflags);
+        if (ncredrawflags & RDW_INVALIDATE)
+            ok(GetUpdateRect(hwnd, &rect, FALSE) == 1,
+            "RedrawWindow did not invalidate window with RDW_INVALIDATE\n");
+        else
+            ok(GetUpdateRect(hwnd, &rect, FALSE) == updateRectValue,
+            "RedrawWindow changed validation state without RDW_INVALIDATE\n");
+        return DefWindowProc(hwnd, msg, wParam, lParam);
+    case WM_PAINT:
+        BeginPaint(hwnd, &ps);
+        if (ncredrawflags & RDW_INVALIDATE)
+            todo_wine ok(GetUpdateRect(hwnd, &rect, FALSE) == 0,
+                         "BeginPaint() did not validate window\n");
+        else
+            ok(GetUpdateRect(hwnd, &rect, FALSE) == 0,
+               "BeginPaint() did not validate window\n");
+        EndPaint(hwnd, &ps);
+        if (ncredrawflags & RDW_INVALIDATE)
+            todo_wine ok(GetUpdateRect(hwnd, &rect, FALSE) == 0,
+                         "Window not valid at end of WM_PAINT\n");
+        else
+            ok(GetUpdateRect(hwnd, &rect, FALSE) == 0,
+               "Window not valid at end of WM_PAINT\n");
+        return 0;
+    }
+    return DefWindowProc(hwnd, msg, wParam, lParam);
+}
+
+static void test_NCRedraw(void)
+{
+    WNDCLASSA wndclass;
+    HWND hwnd;
+    RECT rect;
+    UINT ncredrawflags;
+
+    wndclass.lpszClassName = "TestNCRedrawClass";
+    wndclass.style = CS_HREDRAW | CS_VREDRAW;
+    wndclass.lpfnWndProc = TestNCRedraw_WndProc;
+    wndclass.cbClsExtra = 0;
+    wndclass.cbWndExtra = 0;
+    wndclass.hInstance = 0;
+    wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
+    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
+    wndclass.hbrBackground = GetStockObject(WHITE_BRUSH);
+    wndclass.lpszMenuName = NULL;
+
+    RegisterClassA(&wndclass);
+
+    ncredrawflags = RDW_FRAME | RDW_INVALIDATE;
+    hwnd = CreateWindowA("TestNCRedrawClass", "MainWindow", 
+                         WS_OVERLAPPEDWINDOW, 0, 0, 200, 100,
+                         NULL, NULL, 0, &ncredrawflags);
+    ShowWindow(hwnd, SW_SHOW);
+    ok(GetUpdateRect(hwnd, &rect, FALSE) == 1,
+       "No update region for new window\n");
+    UpdateWindow(hwnd);
+    todo_wine ok(GetUpdateRect(hwnd, &rect, FALSE) == 0,
+                 "WM_PAINT failed to clear update region\n");
+    DestroyWindow(hwnd);
+
+    ncredrawflags = RDW_FRAME;
+    hwnd = CreateWindowA("TestNCRedrawClass", "MainWindow",
+                         WS_OVERLAPPEDWINDOW, 0, 0, 200, 100,
+                         NULL, NULL, 0, &ncredrawflags);
+    ShowWindow(hwnd, SW_SHOW);
+    ok(GetUpdateRect(hwnd, &rect, FALSE) == 1,
+       "No update region for new window\n");
+    UpdateWindow(hwnd);
+    ok(GetUpdateRect(hwnd, &rect, FALSE) == 0,
+       "WM_PAINT failed to clear update region\n");
+    DestroyWindow(hwnd);
+
+    ncredrawflags = RDW_INVALIDATE;
+    hwnd = CreateWindowA("TestNCRedrawClass", "MainWindow",
+                         WS_OVERLAPPEDWINDOW, 0, 0, 200, 100,
+                         NULL, NULL, 0, &ncredrawflags);
+    ShowWindow(hwnd, SW_SHOW);
+    ok(GetUpdateRect(hwnd, &rect, FALSE) == 1,
+       "No update region for new window\n");
+    UpdateWindow(hwnd);
+    todo_wine ok(GetUpdateRect(hwnd, &rect, FALSE) == 0,
+                 "WM_PAINT failed to clear update region\n");
+    DestroyWindow(hwnd);
+}
+
 static void test_GetWindowModuleFileName(void)
 {
     HWND hwnd;
@@ -5669,6 +5767,7 @@ START_TEST(win)
     if (0) test_gettext(); /* crashes on NT4 */
     test_GetUpdateRect();
     test_Expose();
+    test_NCRedraw();
     test_layered_window();
 
     test_SetForegroundWindow(hwndMain);
-- 
1.6.0.4


More information about the wine-patches mailing list