user32: SetWindowPos should limit update region to nearest clipping parent. Take 2

Dmitry Timoshkov dmitry at codeweavers.com
Mon Mar 19 07:24:46 CDT 2007


Hello,

Alexandre asked me to add more tests to better understand what is going on.

This patch makes GetUpdateRect test pass under Wine and fixes the bug 7360.

Changelog:
    user32: SetWindowPos should limit update region to nearest clipping parent.

---
 dlls/user32/tests/win.c |   69 ++++++++++++++++++++++++++++++++++------------
 server/window.c         |   10 ++++++-
 2 files changed, 60 insertions(+), 19 deletions(-)

diff --git a/dlls/user32/tests/win.c b/dlls/user32/tests/win.c
index 5502bf9..13dabbd 100644
--- a/dlls/user32/tests/win.c
+++ b/dlls/user32/tests/win.c
@@ -4175,10 +4175,12 @@ static void test_gettext(void)
 
 static void test_GetUpdateRect(void)
 {
+    MSG msg;
+    BOOL ret, parent_wm_paint, grandparent_wm_paint;
     RECT rc1, rc2;
     HWND hgrandparent, hparent, hchild;
     WNDCLASSA cls;
-    const char* classNameA = "GetUpdateRectClass";
+    static const char classNameA[] = "GetUpdateRectClass";
 
     hgrandparent = CreateWindowA("static", "grandparent", WS_OVERLAPPEDWINDOW,
                                  0, 0, 100, 100, NULL, NULL, 0, NULL);
@@ -4193,21 +4195,35 @@ static void test_GetUpdateRect(void)
     UpdateWindow(hgrandparent);
 
     ShowWindow(hchild, SW_HIDE);
+
     SetRect(&rc2, 0, 0, 0, 0);
-    GetUpdateRect(hgrandparent, &rc1, FALSE);
-    todo_wine
-    {
-        ok(EqualRect(&rc1, &rc2), "rects do not match (%d,%d,%d,%d) / (%d,%d,%d,%d)\n",
-                rc1.left, rc1.top, rc1.right, rc1.bottom,
-                rc2.left, rc2.top, rc2.right, rc2.bottom);
-    }
+    ret = GetUpdateRect(hgrandparent, &rc1, FALSE);
+    ok(!ret, "GetUpdateRect returned not empty region\n");
+    ok(EqualRect(&rc1, &rc2), "rects do not match (%d,%d,%d,%d) / (%d,%d,%d,%d)\n",
+            rc1.left, rc1.top, rc1.right, rc1.bottom,
+            rc2.left, rc2.top, rc2.right, rc2.bottom);
 
     SetRect(&rc2, 10, 10, 40, 40);
-    GetUpdateRect(hparent, &rc1, FALSE);
+    ret = GetUpdateRect(hparent, &rc1, FALSE);
+    ok(ret, "GetUpdateRect returned empty region\n");
     ok(EqualRect(&rc1, &rc2), "rects do not match (%d,%d,%d,%d) / (%d,%d,%d,%d)\n",
             rc1.left, rc1.top, rc1.right, rc1.bottom,
             rc2.left, rc2.top, rc2.right, rc2.bottom);
 
+    parent_wm_paint = FALSE;
+    grandparent_wm_paint = FALSE;
+    while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
+    {
+        if (msg.message == WM_PAINT)
+        {
+            if (msg.hwnd == hgrandparent) grandparent_wm_paint = TRUE;
+            if (msg.hwnd == hparent) parent_wm_paint = TRUE;
+        }
+        DispatchMessage(&msg);
+    }
+    ok(parent_wm_paint, "WM_PAINT should have been recieved in parent\n");
+    ok(!grandparent_wm_paint, "WM_PAINT should NOT have been recieved in grandparent\n");
+
     DestroyWindow(hgrandparent);
 
     cls.style = 0;
@@ -4226,7 +4242,7 @@ static void test_GetUpdateRect(void)
        return;
     }
 
-    hgrandparent = CreateWindowA("static", "grandparent", WS_OVERLAPPEDWINDOW,
+    hgrandparent = CreateWindowA(classNameA, "grandparent", WS_OVERLAPPEDWINDOW,
                                  0, 0, 100, 100, NULL, NULL, 0, NULL);
 
     hparent = CreateWindowA(classNameA, "parent", WS_CHILD|WS_VISIBLE,
@@ -4238,22 +4254,39 @@ static void test_GetUpdateRect(void)
     ShowWindow(hgrandparent, SW_SHOW);
     UpdateWindow(hgrandparent);
 
+    ret = GetUpdateRect(hgrandparent, &rc1, FALSE);
+    ok(!ret, "GetUpdateRect returned not empty region\n");
+
     ShowWindow(hchild, SW_HIDE);
+
     SetRect(&rc2, 0, 0, 0, 0);
-    GetUpdateRect(hgrandparent, &rc1, FALSE);
-    todo_wine
-    {
-        ok(EqualRect(&rc1, &rc2), "rects do not match (%d,%d,%d,%d) / (%d,%d,%d,%d)\n",
-                rc1.left, rc1.top, rc1.right, rc1.bottom,
-                rc2.left, rc2.top, rc2.right, rc2.bottom);
-    }
+    ret = GetUpdateRect(hgrandparent, &rc1, FALSE);
+    ok(!ret, "GetUpdateRect returned not empty region\n");
+    ok(EqualRect(&rc1, &rc2), "rects do not match (%d,%d,%d,%d) / (%d,%d,%d,%d)\n",
+            rc1.left, rc1.top, rc1.right, rc1.bottom,
+            rc2.left, rc2.top, rc2.right, rc2.bottom);
 
     SetRect(&rc2, 10, 10, 40, 40);
-    GetUpdateRect(hparent, &rc1, FALSE);
+    ret = GetUpdateRect(hparent, &rc1, FALSE);
+    ok(ret, "GetUpdateRect returned empty region\n");
     ok(EqualRect(&rc1, &rc2), "rects do not match (%d,%d,%d,%d) / (%d,%d,%d,%d)\n",
             rc1.left, rc1.top, rc1.right, rc1.bottom,
             rc2.left, rc2.top, rc2.right, rc2.bottom);
 
+    parent_wm_paint = FALSE;
+    grandparent_wm_paint = FALSE;
+    while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
+    {
+        if (msg.message == WM_PAINT)
+        {
+            if (msg.hwnd == hgrandparent) grandparent_wm_paint = TRUE;
+            if (msg.hwnd == hparent) parent_wm_paint = TRUE;
+        }
+        DispatchMessage(&msg);
+    }
+    ok(parent_wm_paint, "WM_PAINT should have been recieved in parent\n");
+    ok(!grandparent_wm_paint, "WM_PAINT should NOT have been recieved in grandparent\n");
+
     DestroyWindow(hgrandparent);
 }
 
diff --git a/server/window.c b/server/window.c
index cbb4296..cb07a91 100644
--- a/server/window.c
+++ b/server/window.c
@@ -838,6 +838,14 @@ static inline struct window *get_top_clipping_window( struct window *win )
 }
 
 
+/* get the parent window to clip against for a given window */
+static inline struct window *get_clipping_window( struct window *win )
+{
+    if (win->parent && !is_desktop_window(win->parent)) win = win->parent;
+    return win;
+}
+
+
 /* compute the visible region of a window, in window coordinates */
 static struct region *get_visible_region( struct window *win, struct window *top, unsigned int flags )
 {
@@ -1338,7 +1346,7 @@ static void set_window_pos( struct window *win, struct window *previous,
     const rectangle_t old_window_rect = win->window_rect;
     const rectangle_t old_visible_rect = win->visible_rect;
     const rectangle_t old_client_rect = win->client_rect;
-    struct window *top = get_top_clipping_window( win );
+    struct window *top = get_clipping_window( win );
     int visible = (win->style & WS_VISIBLE) || (swp_flags & SWP_SHOWWINDOW);
 
     if (win->parent && !is_visible( win->parent )) visible = 0;
-- 
1.5.0.2






More information about the wine-patches mailing list