[3/3] user32: SetParent() needs to map window rectangle to the new parent.

Dmitry Timoshkov dmitry at codeweavers.com
Thu Feb 10 02:49:14 CST 2011


---
 dlls/user32/tests/msg.c |    2 +-
 dlls/user32/win.c       |    8 +++++
 server/window.c         |   69 ++++++++++++++++++++++++++++++++---------------
 3 files changed, 56 insertions(+), 23 deletions(-)

diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c
index b3ca5d0..20976ef 100644
--- a/dlls/user32/tests/msg.c
+++ b/dlls/user32/tests/msg.c
@@ -12734,7 +12734,7 @@ static void test_SetParent(void)
 
     SetParent(child, parent2);
     flush_events();
-    ok_sequence(WmSetParentSeq_1, "SetParent() visible WS_CHILD", TRUE);
+    ok_sequence(WmSetParentSeq_1, "SetParent() visible WS_CHILD", FALSE);
 
     ok(GetWindowLongA(child, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
     ok(!IsWindowVisible(child), "IsWindowVisible() should return FALSE\n");
diff --git a/dlls/user32/win.c b/dlls/user32/win.c
index ba0a4ad..3c6429e 100644
--- a/dlls/user32/win.c
+++ b/dlls/user32/win.c
@@ -2782,6 +2782,7 @@ HWND WINAPI SetParent( HWND hwnd, HWND parent )
     HWND old_parent = 0;
     BOOL was_visible;
     WND *wndPtr;
+    RECT rc;
     POINT pt;
     BOOL ret;
 
@@ -2827,6 +2828,13 @@ HWND WINAPI SetParent( HWND hwnd, HWND parent )
     pt.x = wndPtr->rectWindow.left;
     pt.y = wndPtr->rectWindow.top;
 
+    rc = wndPtr->rectWindow;
+    MapWindowPoints( old_parent, parent, (POINT *)&rc, 2 );
+    wndPtr->rectWindow = rc;
+    rc = wndPtr->rectClient;
+    MapWindowPoints( old_parent, parent, (POINT *)&rc, 2 );
+    wndPtr->rectClient = rc;
+
     SERVER_START_REQ( set_parent )
     {
         req->handle = wine_server_user_handle( hwnd );
diff --git a/server/window.c b/server/window.c
index 635dd9b..d9fd3dd 100644
--- a/server/window.c
+++ b/server/window.c
@@ -215,10 +215,45 @@ static void link_window( struct window *win, struct window *previous )
     win->is_linked = 1;
 }
 
+/* convert coordinates from client to screen coords */
+static inline void client_to_screen( struct window *win, int *x, int *y )
+{
+    for ( ; win && !is_desktop_window(win); win = win->parent)
+    {
+        *x += win->client_rect.left;
+        *y += win->client_rect.top;
+    }
+}
+
+/* convert coordinates from client to screen coords */
+static inline void client_to_screen_rect( struct window *win, rectangle_t *rect )
+{
+    for ( ; win && !is_desktop_window(win); win = win->parent)
+    {
+        rect->left   += win->client_rect.left;
+        rect->right  += win->client_rect.left;
+        rect->top    += win->client_rect.top;
+        rect->bottom += win->client_rect.top;
+    }
+}
+
+/* convert coordinates from screen to client coords */
+static inline void screen_to_client_rect( struct window *win, rectangle_t *rect )
+{
+    for ( ; win && !is_desktop_window(win); win = win->parent)
+    {
+        rect->left   -= win->client_rect.left;
+        rect->right  -= win->client_rect.left;
+        rect->top    -= win->client_rect.top;
+        rect->bottom -= win->client_rect.top;
+    }
+}
+
 /* change the parent of a window (or unlink the window if the new parent is NULL) */
 static int set_parent_window( struct window *win, struct window *parent )
 {
     struct window *ptr;
+    rectangle_t window_rect, client_rect;
 
     /* make sure parent is not a child of window */
     for (ptr = parent; ptr; ptr = ptr->parent)
@@ -230,11 +265,19 @@ static int set_parent_window( struct window *win, struct window *parent )
         }
     }
 
+    window_rect = win->window_rect;
+    client_to_screen_rect( win, &window_rect );
+    client_rect = win->client_rect;
+    client_to_screen_rect( win, &client_rect );
+
     if (parent)
     {
         win->parent = parent;
         link_window( win, WINPTR_TOP );
 
+        screen_to_client_rect( win, &window_rect );
+        screen_to_client_rect( win, &client_rect );
+
         /* if parent belongs to a different thread and the window isn't */
         /* top-level, attach the two threads */
         if (parent->thread && parent->thread != win->thread && !is_desktop_window(parent))
@@ -246,6 +289,10 @@ static int set_parent_window( struct window *win, struct window *parent )
         list_add_head( &win->parent->unlinked, &win->entry );
         win->is_linked = 0;
     }
+
+    win->window_rect = window_rect;
+    win->client_rect = client_rect;
+
     return 1;
 }
 
@@ -825,28 +872,6 @@ static struct region *intersect_window_region( struct region *region, struct win
 }
 
 
-/* convert coordinates from client to screen coords */
-static inline void client_to_screen( struct window *win, int *x, int *y )
-{
-    for ( ; win && !is_desktop_window(win); win = win->parent)
-    {
-        *x += win->client_rect.left;
-        *y += win->client_rect.top;
-    }
-}
-
-/* convert coordinates from client to screen coords */
-static inline void client_to_screen_rect( struct window *win, rectangle_t *rect )
-{
-    for ( ; win && !is_desktop_window(win); win = win->parent)
-    {
-        rect->left   += win->client_rect.left;
-        rect->right  += win->client_rect.left;
-        rect->top    += win->client_rect.top;
-        rect->bottom += win->client_rect.top;
-    }
-}
-
 /* map the region from window to screen coordinates */
 static inline void map_win_region_to_screen( struct window *win, struct region *region )
 {
-- 
1.7.3.5




More information about the wine-patches mailing list