Instead of reapplying the old shape, which not only includes the window shape but also the old clipping and visible areas that can change independently.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=57551
-- v2: server: Remove now unnecessary needs_update member. win32u: Always update the surface regions in apply_window_pos.
From: Rémi Bernon rbernon@codeweavers.com
We need to call update_surface_region whenever the window rect changes as it uses the visible rect to clip the regions to the visible area of the window.
We could delegate this to the host windowing system in most cases, but it was explicitly clipped to the visible rect in the Android driver.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=57551 --- dlls/win32u/window.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-)
diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 4855555d926..ba204957669 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -2046,7 +2046,7 @@ static BOOL apply_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags, stru struct window_rects monitor_rects; WND *win; HWND owner_hint, surface_win = 0, parent = NtUserGetAncestor( hwnd, GA_PARENT ); - BOOL ret, is_fullscreen, is_layered, is_child, needs_update = FALSE; + BOOL ret, is_fullscreen, is_layered, is_child; struct window_rects old_rects; RECT extra_rects[3]; struct window_surface *old_surface; @@ -2064,11 +2064,7 @@ static BOOL apply_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags, stru
if (!(win = get_win_ptr( hwnd )) || win == WND_DESKTOP || win == WND_OTHER_PROCESS) return FALSE; old_surface = win->surface; - if (old_surface != new_surface) - { - if (old_surface && new_surface) window_surface_set_shape( new_surface, old_surface->shape_region ); - swp_flags |= SWP_FRAMECHANGED; /* force refreshing non-client area */ - } + if (old_surface != new_surface) swp_flags |= SWP_FRAMECHANGED; /* force refreshing non-client area */
if (new_surface == &dummy_surface) swp_flags |= SWP_NOREDRAW; else if (old_surface == &dummy_surface) @@ -2112,7 +2108,6 @@ static BOOL apply_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags, stru win->rects = *new_rects; if ((win->surface = new_surface)) window_surface_add_ref( win->surface ); surface_win = wine_server_ptr_handle( reply->surface_win ); - needs_update = reply->needs_update; if (get_window_long( win->parent, GWL_EXSTYLE ) & WS_EX_LAYOUTRTL) { RECT client = {0}; @@ -2131,7 +2126,7 @@ static BOOL apply_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags, stru
if (ret) { - if (needs_update) update_surface_region( surface_win ); + update_surface_region( surface_win ); if (((swp_flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) || (swp_flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW | SWP_STATECHANGED | SWP_FRAMECHANGED))) invalidate_dce( win, &old_rects.window );
From: Rémi Bernon rbernon@codeweavers.com
--- server/protocol.def | 1 - server/window.c | 11 +---------- 2 files changed, 1 insertion(+), 11 deletions(-)
diff --git a/server/protocol.def b/server/protocol.def index 37e7cffa748..292303c385f 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -2692,7 +2692,6 @@ enum message_type unsigned int new_style; /* new window style */ unsigned int new_ex_style; /* new window extended style */ user_handle_t surface_win; /* parent window that holds the surface */ - int needs_update; /* whether the surface region needs an update */ @END #define SET_WINPOS_PAINT_SURFACE 0x01 /* window has a paintable surface */ #define SET_WINPOS_PIXEL_FORMAT 0x02 /* window has a custom pixel format */ diff --git a/server/window.c b/server/window.c index a510eafbf78..9d6ce4ba169 100644 --- a/server/window.c +++ b/server/window.c @@ -134,7 +134,6 @@ static const struct object_ops window_ops = #define PAINT_NONCLIENT 0x0040 /* needs WM_NCPAINT */ #define PAINT_DELAYED_ERASE 0x0080 /* still needs erase after WM_ERASEBKGND */ #define PAINT_PIXEL_FORMAT_CHILD 0x0100 /* at least one child has a custom pixel format */ -#define PAINT_REGION_CHANGED 0x0200 /* window region has changed */
/* growable array of user handles */ struct user_handle_array @@ -2076,9 +2075,6 @@ static void set_window_region( struct window *win, struct region *region, int re
if (redraw) old_vis_rgn = get_visible_region( win, DCX_WINDOW );
- if (!region != !win->win_region || (region && !is_region_equal( region, win->win_region ))) - win->paint_flags |= PAINT_REGION_CHANGED; - if (win->win_region) free_region( win->win_region ); win->win_region = region;
@@ -2651,12 +2647,7 @@ DECL_HANDLER(set_window_pos) reply->new_ex_style = win->ex_style;
top = get_top_clipping_window( win ); - if (is_visible( top ) && (top->paint_flags & PAINT_HAS_SURFACE)) - { - reply->surface_win = top->handle; - reply->needs_update = !!(top->paint_flags & (PAINT_HAS_PIXEL_FORMAT | PAINT_PIXEL_FORMAT_CHILD | PAINT_REGION_CHANGED)); - top->paint_flags &= ~PAINT_REGION_CHANGED; - } + if (is_visible( top ) && (top->paint_flags & PAINT_HAS_SURFACE)) reply->surface_win = top->handle; }
v2: Always update the surface regions when moving/resizing window.
We could alternatively check for visible rect changes in wineserver, setting needs_update when its size changes but I feel like this would be the case most of the time anyway and removing some conditions makes the code simpler instead.
On Thu Jan 2 10:02:12 2025 +0000, darkblaze69 wrote:
This has a side effect, in both GNOME and KDE at least without decorations (without vcrun2017) on resizing out the window it isn't refreshed and partially stays black. With decorations (vcrun2017) I don't see this effect. ![Screenshot_From_2024-12-16_20-11-30](/uploads/70061b5d0fdce3f9c3f40c0c367301a8/Screenshot_From_2024-12-16_20-11-30.png){width=80%} ![Screencast_From_2024-12-16_20-10-42-s](/uploads/ce6ddfa81049625e32ab7e72352e0e3d/Screencast_From_2024-12-16_20-10-42-s.mp4){width=80%}
Thanks, the new version should address this.
On Thu Jan 2 10:02:12 2025 +0000, Rémi Bernon wrote:
Thanks, the new version should address this.
Thanks, tested it, looks good now.