Alexandre Julliard : user32: Copy the bits of child windows when the parent has a surface.

Alexandre Julliard julliard at winehq.org
Thu Jul 13 14:41:33 CDT 2017


Module: wine
Branch: master
Commit: 5b9c69b93ffa9dc9e4d71660cf076c43d4e05c60
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=5b9c69b93ffa9dc9e4d71660cf076c43d4e05c60

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Thu Jul 13 11:04:52 2017 +0200

user32: Copy the bits of child windows when the parent has a surface.

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

---

 dlls/user32/painting.c     | 35 +++++++++++++++++++++++++++++++++++
 dlls/user32/user_private.h |  2 ++
 dlls/user32/winpos.c       | 35 +++++++++++++++++++++++++++++++----
 3 files changed, 68 insertions(+), 4 deletions(-)

diff --git a/dlls/user32/painting.c b/dlls/user32/painting.c
index 1bfb86d..3c7f220 100644
--- a/dlls/user32/painting.c
+++ b/dlls/user32/painting.c
@@ -811,6 +811,41 @@ void move_window_bits( HWND hwnd, struct window_surface *old_surface,
 
 
 /***********************************************************************
+ *		move_window_bits_parent
+ *
+ * Move the window bits in the parent surface when a child is moved.
+ */
+void move_window_bits_parent( HWND hwnd, HWND parent, const RECT *window_rect, const RECT *valid_rects )
+{
+    struct window_surface *surface;
+    RECT dst = valid_rects[0];
+    RECT src = valid_rects[1];
+    WND *win;
+
+    if (src.left == dst.left && src.top == dst.top) return;
+
+    if (!(win = WIN_GetPtr( parent ))) return;
+    if (win == WND_DESKTOP || win == WND_OTHER_PROCESS) return;
+    if (!(surface = win->surface))
+    {
+        WIN_ReleasePtr( win );
+        return;
+    }
+
+    TRACE( "copying %s -> %s\n", wine_dbgstr_rect( &src ), wine_dbgstr_rect( &dst ));
+    MapWindowPoints( GetAncestor( hwnd, GA_PARENT ), parent, (POINT *)&src, 2 );
+    OffsetRect( &src, win->rectClient.left - win->visible_rect.left,
+                win->rectClient.top - win->visible_rect.top );
+    OffsetRect( &dst, -window_rect->left, -window_rect->top );
+    window_surface_add_ref( surface );
+    WIN_ReleasePtr( win );
+
+    copy_bits_from_surface( hwnd, surface, &dst, &src );
+    window_surface_release( surface );
+}
+
+
+/***********************************************************************
  *           update_now
  *
  * Implementation of RDW_UPDATENOW behavior.
diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h
index a697fd9..052fdd8 100644
--- a/dlls/user32/user_private.h
+++ b/dlls/user32/user_private.h
@@ -232,6 +232,8 @@ extern void move_window_bits( HWND hwnd, struct window_surface *old_surface,
                               struct window_surface *new_surface,
                               const RECT *visible_rect, const RECT *old_visible_rect,
                               const RECT *window_rect, const RECT *valid_rects ) DECLSPEC_HIDDEN;
+extern void move_window_bits_parent( HWND hwnd, HWND parent, const RECT *window_rect,
+                                     const RECT *valid_rects ) DECLSPEC_HIDDEN;
 extern void *get_hook_proc( void *proc, const WCHAR *module, HMODULE *free_module ) DECLSPEC_HIDDEN;
 extern RECT get_virtual_screen_rect(void) DECLSPEC_HIDDEN;
 extern LRESULT call_current_hook( HHOOK hhook, INT code, WPARAM wparam, LPARAM lparam ) DECLSPEC_HIDDEN;
diff --git a/dlls/user32/winpos.c b/dlls/user32/winpos.c
index a37ab7c..a89c60d 100644
--- a/dlls/user32/winpos.c
+++ b/dlls/user32/winpos.c
@@ -2060,8 +2060,7 @@ BOOL set_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags,
     WND *win;
     HWND surface_win = 0, parent = GetAncestor( hwnd, GA_PARENT );
     BOOL ret, needs_update = FALSE;
-    int old_width;
-    RECT visible_rect, old_visible_rect, old_window_rect;
+    RECT visible_rect, old_visible_rect, old_window_rect, old_client_rect;
     struct window_surface *old_surface, *new_surface = NULL;
 
     if (!parent || parent == GetDesktopWindow())
@@ -2080,8 +2079,8 @@ BOOL set_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags,
         if (new_surface) window_surface_release( new_surface );
         return FALSE;
     }
-    old_width = win->rectClient.right - win->rectClient.left;
     old_visible_rect = win->visible_rect;
+    old_client_rect = win->rectClient;
     old_surface = win->surface;
     if (old_surface != new_surface) swp_flags |= SWP_FRAMECHANGED;  /* force refreshing non-client area */
 
@@ -2126,7 +2125,8 @@ BOOL set_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags,
                 mirror_rect( &client, &win->visible_rect );
             }
             /* if an RTL window is resized the children have moved */
-            if (win->dwExStyle & WS_EX_LAYOUTRTL && client_rect->right - client_rect->left != old_width)
+            if (win->dwExStyle & WS_EX_LAYOUTRTL &&
+                client_rect->right - client_rect->left != old_client_rect.right - old_client_rect.left)
                 win->flags |= WIN_CHILDREN_MOVED;
         }
     }
@@ -2156,6 +2156,33 @@ BOOL set_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags,
             }
             window_surface_release( old_surface );
         }
+        else if (surface_win && surface_win != hwnd)
+        {
+            if (!IsRectEmpty( valid_rects ))
+            {
+                RECT rects[2];
+                int x_offset = old_visible_rect.left - visible_rect.left;
+                int y_offset = old_visible_rect.top - visible_rect.top;
+
+                /* if all that happened is that the whole window moved, copy everything */
+                if (!(swp_flags & SWP_FRAMECHANGED) &&
+                    old_visible_rect.right  - visible_rect.right  == x_offset &&
+                    old_visible_rect.bottom - visible_rect.bottom == y_offset &&
+                    old_client_rect.left    - client_rect->left   == x_offset &&
+                    old_client_rect.right   - client_rect->right  == x_offset &&
+                    old_client_rect.top     - client_rect->top    == y_offset &&
+                    old_client_rect.bottom  - client_rect->bottom == y_offset &&
+                    EqualRect( &valid_rects[0], client_rect ))
+                {
+                    rects[0] = visible_rect;
+                    rects[1] = old_visible_rect;
+                    valid_rects = rects;
+                }
+                move_window_bits_parent( hwnd, surface_win, window_rect, valid_rects );
+                valid_rects = NULL;  /* prevent the driver from trying to also move the bits */
+            }
+        }
+
         USER_Driver->pWindowPosChanged( hwnd, insert_after, swp_flags, window_rect,
                                         client_rect, &visible_rect, valid_rects, new_surface );
     }




More information about the wine-cvs mailing list