Alexandre Julliard : user32: Take into account the offset between old and new parent in SetParent().

Alexandre Julliard julliard at winehq.org
Mon May 7 16:34:41 CDT 2018


Module: wine
Branch: master
Commit: e95d0c684915c625aba0bfe4332a6c3e5259701c
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=e95d0c684915c625aba0bfe4332a6c3e5259701c

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Mon May  7 12:00:17 2018 +0200

user32: Take into account the offset between old and new parent in SetParent().

Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/user32/message.c      |  2 +-
 dlls/user32/tests/msg.c    |  2 +-
 dlls/user32/user_private.h |  2 +-
 dlls/user32/win.c          | 23 +++++++++++++++--------
 dlls/user32/winpos.c       | 25 +++++++++++++------------
 5 files changed, 31 insertions(+), 23 deletions(-)

diff --git a/dlls/user32/message.c b/dlls/user32/message.c
index d2e6a75..79ea577 100644
--- a/dlls/user32/message.c
+++ b/dlls/user32/message.c
@@ -1858,7 +1858,7 @@ static LRESULT handle_internal_message( HWND hwnd, UINT msg, WPARAM wparam, LPAR
         return WIN_DestroyWindow( hwnd );
     case WM_WINE_SETWINDOWPOS:
         if (is_desktop_window( hwnd )) return 0;
-        return USER_SetWindowPos( (WINDOWPOS *)lparam );
+        return USER_SetWindowPos( (WINDOWPOS *)lparam, 0, 0 );
     case WM_WINE_SHOWWINDOW:
         if (is_desktop_window( hwnd )) return 0;
         return ShowWindow( hwnd, wparam );
diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c
index 69841d3..a0f2cbe 100644
--- a/dlls/user32/tests/msg.c
+++ b/dlls/user32/tests/msg.c
@@ -15433,7 +15433,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/user_private.h b/dlls/user32/user_private.h
index 30ab511..9699297 100644
--- a/dlls/user32/user_private.h
+++ b/dlls/user32/user_private.h
@@ -254,7 +254,7 @@ extern void SYSPARAMS_Init(void) DECLSPEC_HIDDEN;
 extern void USER_CheckNotLock(void) DECLSPEC_HIDDEN;
 extern BOOL USER_IsExitingThread( DWORD tid ) DECLSPEC_HIDDEN;
 
-extern BOOL USER_SetWindowPos( WINDOWPOS * winpos ) DECLSPEC_HIDDEN;
+extern BOOL USER_SetWindowPos( WINDOWPOS * winpos, int parent_x, int parent_y ) DECLSPEC_HIDDEN;
 
 typedef LRESULT (*winproc_callback_t)( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp,
                                        LRESULT *result, void *arg );
diff --git a/dlls/user32/win.c b/dlls/user32/win.c
index 7bb0088..0d694a1 100644
--- a/dlls/user32/win.c
+++ b/dlls/user32/win.c
@@ -3014,12 +3014,13 @@ HWND WINAPI GetAncestor( HWND hwnd, UINT type )
  */
 HWND WINAPI SetParent( HWND hwnd, HWND parent )
 {
+    WINDOWPOS winpos;
     HWND full_handle;
     HWND old_parent = 0;
     BOOL was_visible;
     WND *wndPtr;
-    POINT pt;
     BOOL ret;
+    RECT window_rect, old_screen_rect, new_screen_rect;
 
     TRACE("(%p %p)\n", hwnd, parent);
 
@@ -3062,8 +3063,8 @@ HWND WINAPI SetParent( HWND hwnd, HWND parent )
     wndPtr = WIN_GetPtr( hwnd );
     if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return 0;
 
-    pt.x = wndPtr->rectWindow.left;
-    pt.y = wndPtr->rectWindow.top;
+    WIN_GetRectangles( hwnd, COORDS_PARENT, &window_rect, NULL );
+    WIN_GetRectangles( hwnd, COORDS_SCREEN, &old_screen_rect, NULL );
 
     SERVER_START_REQ( set_parent )
     {
@@ -3082,11 +3083,17 @@ HWND WINAPI SetParent( HWND hwnd, HWND parent )
 
     USER_Driver->pSetParent( full_handle, parent, old_parent );
 
-    /* SetParent additionally needs to make hwnd the topmost window
-       in the x-order and send the expected WM_WINDOWPOSCHANGING and
-       WM_WINDOWPOSCHANGED notification messages.
-    */
-    SetWindowPos( hwnd, HWND_TOP, pt.x, pt.y, 0, 0, SWP_NOSIZE );
+    winpos.hwnd = hwnd;
+    winpos.hwndInsertAfter = HWND_TOP;
+    winpos.x = window_rect.left;
+    winpos.y = window_rect.top;
+    winpos.cx = 0;
+    winpos.cy = 0;
+    winpos.flags = SWP_NOSIZE;
+
+    WIN_GetRectangles( hwnd, COORDS_SCREEN, &new_screen_rect, NULL );
+    USER_SetWindowPos( &winpos, new_screen_rect.left - old_screen_rect.left,
+                       new_screen_rect.top - old_screen_rect.top );
 
     if (was_visible) ShowWindow( hwnd, SW_SHOW );
 
diff --git a/dlls/user32/winpos.c b/dlls/user32/winpos.c
index 434fe6e..19ab297 100644
--- a/dlls/user32/winpos.c
+++ b/dlls/user32/winpos.c
@@ -1855,7 +1855,8 @@ done:
  *           SWP_DoNCCalcSize
  */
 static UINT SWP_DoNCCalcSize( WINDOWPOS *pWinpos, const RECT *old_window_rect, const RECT *old_client_rect,
-                              const RECT *new_window_rect, RECT *new_client_rect, RECT *validRects )
+                              const RECT *new_window_rect, RECT *new_client_rect, RECT *validRects,
+                              int parent_x, int parent_y )
 {
     UINT wvrFlags = 0;
 
@@ -1879,8 +1880,8 @@ static UINT SWP_DoNCCalcSize( WINDOWPOS *pWinpos, const RECT *old_window_rect, c
                wine_dbgstr_rect(old_window_rect), wine_dbgstr_rect(old_client_rect),
                wine_dbgstr_rect(new_window_rect), wine_dbgstr_rect(new_client_rect) );
 
-        if (new_client_rect->left != old_client_rect->left ||
-            new_client_rect->top != old_client_rect->top)
+        if (new_client_rect->left != old_client_rect->left - parent_x ||
+            new_client_rect->top != old_client_rect->top - parent_y)
             pWinpos->flags &= ~SWP_NOCLIENTMOVE;
 
         if( (new_client_rect->right - new_client_rect->left !=
@@ -1901,8 +1902,8 @@ static UINT SWP_DoNCCalcSize( WINDOWPOS *pWinpos, const RECT *old_window_rect, c
     else
     {
         if (!(pWinpos->flags & SWP_NOMOVE) &&
-            (new_client_rect->left != old_client_rect->left ||
-             new_client_rect->top != old_client_rect->top))
+            (new_client_rect->left != old_client_rect->left - parent_x ||
+             new_client_rect->top != old_client_rect->top - parent_y))
             pWinpos->flags &= ~SWP_NOCLIENTMOVE;
     }
 
@@ -1917,7 +1918,7 @@ static UINT SWP_DoNCCalcSize( WINDOWPOS *pWinpos, const RECT *old_window_rect, c
 }
 
 /* fix redundant flags and values in the WINDOWPOS structure */
-static BOOL fixup_flags( WINDOWPOS *winpos, const RECT *old_window_rect )
+static BOOL fixup_flags( WINDOWPOS *winpos, const RECT *old_window_rect, int parent_x, int parent_y )
 {
     HWND parent;
     WND *wndPtr = WIN_GetPtr( winpos->hwnd );
@@ -1955,7 +1956,7 @@ static BOOL fixup_flags( WINDOWPOS *winpos, const RECT *old_window_rect )
         (old_window_rect->bottom - old_window_rect->top == winpos->cy))
         winpos->flags |= SWP_NOSIZE;    /* Already the right size */
 
-    if ((old_window_rect->left == winpos->x) && (old_window_rect->top == winpos->y))
+    if ((old_window_rect->left - parent_x == winpos->x) && (old_window_rect->top - parent_y == winpos->y))
         winpos->flags |= SWP_NOMOVE;    /* Already the right position */
 
     if ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD)
@@ -2203,7 +2204,7 @@ BOOL set_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags,
  *
  *     User32 internal function
  */
-BOOL USER_SetWindowPos( WINDOWPOS * winpos )
+BOOL USER_SetWindowPos( WINDOWPOS * winpos, int parent_x, int parent_y )
 {
     RECT old_window_rect, old_client_rect, new_window_rect, new_client_rect, valid_rects[2];
     UINT orig_flags;
@@ -2251,7 +2252,7 @@ BOOL USER_SetWindowPos( WINDOWPOS * winpos )
                                &new_window_rect, &new_client_rect )) return FALSE;
 
     /* Fix redundant flags */
-    if (!fixup_flags( winpos, &old_window_rect )) return FALSE;
+    if (!fixup_flags( winpos, &old_window_rect, parent_x, parent_y )) return FALSE;
 
     if((winpos->flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER)
     {
@@ -2262,7 +2263,7 @@ BOOL USER_SetWindowPos( WINDOWPOS * winpos )
     /* Common operations */
 
     SWP_DoNCCalcSize( winpos, &old_window_rect, &old_client_rect,
-                      &new_window_rect, &new_client_rect, valid_rects );
+                      &new_window_rect, &new_client_rect, valid_rects, parent_x, parent_y );
 
     if (!set_window_pos( winpos->hwnd, winpos->hwndInsertAfter, winpos->flags,
                          &new_window_rect, &new_client_rect, valid_rects ))
@@ -2350,7 +2351,7 @@ BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
     winpos.flags = flags;
     
     if (WIN_IsCurrentThread( hwnd ))
-        return USER_SetWindowPos(&winpos);
+        return USER_SetWindowPos( &winpos, 0, 0 );
 
     return SendMessageW( winpos.hwnd, WM_WINE_SETWINDOWPOS, 0, (LPARAM)&winpos );
 }
@@ -2499,7 +2500,7 @@ BOOL WINAPI EndDeferWindowPos( HDWP hdwp )
                winpos->cx, winpos->cy, winpos->flags);
 
         if (WIN_IsCurrentThread( winpos->hwnd ))
-            USER_SetWindowPos( winpos );
+            USER_SetWindowPos( winpos, 0, 0 );
         else
             SendMessageW( winpos->hwnd, WM_WINE_SETWINDOWPOS, 0, (LPARAM)winpos );
     }




More information about the wine-cvs mailing list