[PATCH 0/4] MR11289: win32u: Move client surface rect computation out of the drivers.
In preparation for rational DPI, to fix various rounding issues with display mode emulation. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11289
From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/win32u/window.c | 17 +++++++++++++---- dlls/winewayland.drv/wayland_surface.c | 6 ++++-- dlls/winewayland.drv/window.c | 2 +- dlls/winex11.drv/init.c | 4 ++-- include/wine/gdi_driver.h | 1 + 5 files changed, 21 insertions(+), 9 deletions(-) diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index b5136b69379..7925092385d 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -308,6 +308,7 @@ void detach_client_surfaces( HWND hwnd ) client_surface_add_ref( surface ); surface->funcs->detach( surface ); + surface->toplevel = NULL; surface->hwnd = NULL; } @@ -320,6 +321,13 @@ void detach_client_surfaces( HWND hwnd ) } } +static void client_surface_update_locked( struct client_surface *surface ) +{ + surface->toplevel = NtUserGetAncestor( surface->hwnd, GA_ROOT ); + surface->funcs->update( surface ); + InterlockedExchange( &surface->updated, 1 ); +} + void update_client_surfaces( HWND hwnd ) { struct client_surface *surface, *next; @@ -329,8 +337,7 @@ void update_client_surfaces( HWND hwnd ) LIST_FOR_EACH_ENTRY_SAFE( surface, next, &client_surfaces, struct client_surface, entry ) { if (NtUserGetAncestor( surface->hwnd, GA_ROOT ) != hwnd) continue; - surface->funcs->update( surface ); - InterlockedExchange( &surface->updated, 1 ); + client_surface_update_locked( surface ); } pthread_mutex_unlock( &surfaces_lock ); @@ -338,12 +345,14 @@ void update_client_surfaces( HWND hwnd ) void *client_surface_create( UINT size, const struct client_surface_funcs *funcs, HWND hwnd ) { + HWND toplevel = NtUserGetAncestor( hwnd, GA_ROOT ); struct client_surface *surface; if (!(surface = calloc( 1, size ))) return NULL; surface->funcs = funcs; surface->ref = 1; surface->hwnd = hwnd; + surface->toplevel = toplevel; list_init( &surface->entry ); TRACE( "created %s\n", debugstr_client_surface( surface ) ); @@ -394,7 +403,7 @@ void client_surface_present( struct client_surface *surface ) void client_surface_update( struct client_surface *surface ) { pthread_mutex_lock( &surfaces_lock ); - if (surface->hwnd) surface->funcs->update( surface ); + if (surface->hwnd) client_surface_update_locked( surface ); pthread_mutex_unlock( &surfaces_lock ); } @@ -404,7 +413,7 @@ void add_window_client_surface( HWND hwnd, struct client_surface *surface ) surface->hwnd = hwnd; list_add_tail( &client_surfaces, &surface->entry ); - surface->funcs->update( surface ); + client_surface_update_locked( surface ); pthread_mutex_unlock( &surfaces_lock ); } diff --git a/dlls/winewayland.drv/wayland_surface.c b/dlls/winewayland.drv/wayland_surface.c index 0f811ec904c..eb74b78061b 100644 --- a/dlls/winewayland.drv/wayland_surface.c +++ b/dlls/winewayland.drv/wayland_surface.c @@ -1181,9 +1181,11 @@ static void wayland_client_surface_detach(struct client_surface *client) static void wayland_client_surface_update(struct client_surface *client) { struct wayland_client_surface *surface = impl_from_client_surface(client); - HWND hwnd = client->hwnd, toplevel = NtUserGetAncestor(hwnd, GA_ROOT); + HWND hwnd = client->hwnd, toplevel = client->toplevel; struct wayland_win_data *data; + TRACE("%s\n", debugstr_client_surface(client)); + if (!(data = wayland_win_data_get(hwnd))) return; if (toplevel && NtUserIsWindowVisible(hwnd)) @@ -1197,7 +1199,7 @@ static void wayland_client_surface_update(struct client_surface *client) static void wayland_client_surface_present(struct client_surface *client, HDC hdc) { struct wayland_client_surface *surface = impl_from_client_surface(client); - HWND hwnd = client->hwnd, toplevel = NtUserGetAncestor(hwnd, GA_ROOT); + HWND hwnd = client->hwnd, toplevel = client->toplevel; struct wayland_surface *wayland_surface; struct wayland_win_data *data; diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index a3f0f35ff79..59baaf258db 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -807,7 +807,7 @@ void WAYLAND_UpdateLayeredWindow(HWND hwnd, BYTE alpha, UINT flags) void set_client_surface(HWND hwnd, struct wayland_client_surface *new_client) { - HWND toplevel = NtUserGetAncestor(hwnd, GA_ROOT); + HWND toplevel = new_client->client.toplevel; struct wayland_client_surface *old_client; struct wayland_win_data *data; diff --git a/dlls/winex11.drv/init.c b/dlls/winex11.drv/init.c index d5b4fdbf0aa..92b2683ae87 100644 --- a/dlls/winex11.drv/init.c +++ b/dlls/winex11.drv/init.c @@ -297,7 +297,7 @@ static void x11drv_client_surface_detach( struct client_surface *client ) static void client_surface_update_geometry( HWND hwnd, struct x11drv_client_surface *surface ) { UINT dpi = NtUserGetDpiForWindow( hwnd ); /* use window DPI here, DPI scaling is handled through offscreen presentation */ - HWND origin = hwnd, toplevel = NtUserGetAncestor( hwnd, GA_ROOT ); + HWND origin = hwnd, toplevel = surface->client.toplevel; XWindowChanges changes = surface->changes; struct x11drv_win_data *data; int mask = 0; @@ -400,7 +400,7 @@ static void x11drv_client_surface_update( struct client_surface *client ) static void X11DRV_client_surface_present( struct client_surface *client, HDC hdc ) { struct x11drv_client_surface *surface = impl_from_client_surface( client ); - HWND hwnd = client->hwnd, toplevel = NtUserGetAncestor( hwnd, GA_ROOT ); + HWND hwnd = client->hwnd, toplevel = client->toplevel; struct x11drv_win_data *data; RECT rect_dst, rect; Drawable window; diff --git a/include/wine/gdi_driver.h b/include/wine/gdi_driver.h index a5ec6807cf3..0ed84a51ba7 100644 --- a/include/wine/gdi_driver.h +++ b/include/wine/gdi_driver.h @@ -265,6 +265,7 @@ struct client_surface LONG ref; /* reference count */ HWND hwnd; /* window the surface was created for */ LONG updated; /* has been moved / resized / reparented */ + HWND toplevel; /* toplevel window of the surface */ LONG offscreen; /* client window is offscreen */ }; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11289
From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/win32u/window.c | 1 + dlls/winex11.drv/init.c | 3 --- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 7925092385d..b122453c0d8 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -393,6 +393,7 @@ void client_surface_present( struct client_surface *surface ) pthread_mutex_lock( &surfaces_lock ); if ((hwnd = surface->hwnd)) { + client_surface_update_locked( surface ); if (surface->offscreen) hdc = NtUserGetDCEx( hwnd, 0, DCX_CACHE | DCX_USESTYLE ); surface->funcs->present( surface, hdc ); if (hdc) NtUserReleaseDC( hwnd, hdc ); diff --git a/dlls/winex11.drv/init.c b/dlls/winex11.drv/init.c index 92b2683ae87..60c361147c3 100644 --- a/dlls/winex11.drv/init.c +++ b/dlls/winex11.drv/init.c @@ -408,9 +408,6 @@ static void X11DRV_client_surface_present( struct client_surface *client, HDC hd TRACE( "%s\n", debugstr_client_surface( client ) ); - client_surface_update_geometry( hwnd, surface ); - client_surface_update_offscreen( hwnd, surface ); - if (!hdc) return; window = X11DRV_get_whole_window( toplevel ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11289
From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/win32u/window.c | 29 ++++++++++++++- dlls/winemac.drv/window.c | 14 +------ dlls/winewayland.drv/wayland_surface.c | 24 ++++++------ dlls/winewayland.drv/waylanddrv.h | 3 +- dlls/winewayland.drv/window.c | 7 ++-- dlls/winex11.drv/init.c | 51 +++++--------------------- dlls/winex11.drv/x11drv.h | 1 - include/wine/gdi_driver.h | 2 + 8 files changed, 59 insertions(+), 72 deletions(-) diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index b122453c0d8..b9d36e076fe 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -321,9 +321,34 @@ void detach_client_surfaces( HWND hwnd ) } } +static RECT get_client_surface_rects( HWND toplevel, HWND hwnd, RECT *monitor_rect ) +{ + UINT dpi = get_dpi_for_window( hwnd ), raw_dpi; + struct window_rects rects, monitor_rects; + RECT rect = {0}; + + if (!toplevel) toplevel = NtUserGetAncestor( hwnd, GA_ROOT ); + get_window_rects( toplevel, COORDS_PARENT, &rects, dpi ); + monitor_rects = map_window_rects_virt_to_raw( rects, dpi ); + + if (get_present_rect( hwnd, &rect, dpi )) OffsetRect( &rect, -rects.client.left, -rects.client.top ); + else if (get_client_rect( hwnd, &rect, dpi )) map_window_points( hwnd, toplevel, (POINT *)&rect, 2, dpi ); + + get_win_monitor_dpi( hwnd, &raw_dpi ); + *monitor_rect = map_dpi_rect( rect, dpi, raw_dpi ); + OffsetRect( monitor_rect, monitor_rects.client.left - monitor_rects.visible.left, + monitor_rects.client.top - monitor_rects.visible.top ); + + return rect; +} + static void client_surface_update_locked( struct client_surface *surface ) { surface->toplevel = NtUserGetAncestor( surface->hwnd, GA_ROOT ); + surface->virtual_rect = get_client_surface_rects( surface->toplevel, surface->hwnd, &surface->monitor_rect ); + + TRACE( "updating %s, toplevel %p, virtual_rect %s, monitor_rect %s\n", debugstr_client_surface( surface ), surface->toplevel, + wine_dbgstr_rect( &surface->virtual_rect ), wine_dbgstr_rect( &surface->monitor_rect ) ); surface->funcs->update( surface ); InterlockedExchange( &surface->updated, 1 ); } @@ -353,9 +378,11 @@ void *client_surface_create( UINT size, const struct client_surface_funcs *funcs surface->ref = 1; surface->hwnd = hwnd; surface->toplevel = toplevel; + surface->virtual_rect = get_client_surface_rects( toplevel, hwnd, &surface->monitor_rect ); list_init( &surface->entry ); - TRACE( "created %s\n", debugstr_client_surface( surface ) ); + TRACE( "created %s, toplevel %p, virtual_rect %s, monitor_rect %s\n", debugstr_client_surface( surface ), toplevel, + wine_dbgstr_rect( &surface->virtual_rect ), wine_dbgstr_rect( &surface->monitor_rect ) ); return surface; } diff --git a/dlls/winemac.drv/window.c b/dlls/winemac.drv/window.c index 61f14ad496b..c0384f3f0d5 100644 --- a/dlls/winemac.drv/window.c +++ b/dlls/winemac.drv/window.c @@ -1105,16 +1105,11 @@ static void macdrv_client_surface_update(struct client_surface *client) struct macdrv_client_surface *surface = impl_from_client_surface(client); HWND hwnd = client->hwnd, toplevel = NtUserGetAncestor(hwnd, GA_ROOT); struct macdrv_win_data *data; - RECT rect; TRACE("%s\n", debugstr_client_surface(client)); - NtUserGetClientRect(hwnd, &rect, NtUserGetWinMonitorDpi(hwnd, MDT_RAW_DPI)); - NtUserMapWindowPoints(hwnd, toplevel, (POINT *)&rect, 2, NtUserGetWinMonitorDpi(toplevel, MDT_RAW_DPI)); - if (!(data = get_win_data(toplevel))) return; - OffsetRect(&rect, data->rects.client.left - data->rects.visible.left, data->rects.client.top - data->rects.visible.top); - macdrv_set_view_frame(surface->cocoa_view, cgrect_from_rect(rect)); + macdrv_set_view_frame(surface->cocoa_view, cgrect_from_rect(client->monitor_rect)); macdrv_set_view_superview(surface->cocoa_view, toplevel == hwnd ? NULL : data->client_view, data->cocoa_window, NULL, NULL); release_win_data(data); } @@ -1152,15 +1147,10 @@ struct macdrv_client_surface *impl_from_client_surface(struct client_surface *cl struct client_surface *macdrv_CreateClientSurface(HWND hwnd, int pixel_format) { - HWND toplevel = NtUserGetAncestor(hwnd, GA_ROOT); struct macdrv_client_surface *surface; - RECT rect; - - NtUserGetClientRect(hwnd, &rect, NtUserGetWinMonitorDpi(hwnd, MDT_RAW_DPI)); - NtUserMapWindowPoints(hwnd, toplevel, (POINT *)&rect, 2, NtUserGetWinMonitorDpi(toplevel, MDT_RAW_DPI)); surface = client_surface_create(sizeof(*surface), &macdrv_client_surface_funcs, hwnd); - surface->cocoa_view = macdrv_create_view(cgrect_from_rect(rect)); + surface->cocoa_view = macdrv_create_view(cgrect_from_rect(surface->client.monitor_rect)); macdrv_set_view_hidden(surface->cocoa_view, TRUE); if (surface) diff --git a/dlls/winewayland.drv/wayland_surface.c b/dlls/winewayland.drv/wayland_surface.c index eb74b78061b..ea802e6ed01 100644 --- a/dlls/winewayland.drv/wayland_surface.c +++ b/dlls/winewayland.drv/wayland_surface.c @@ -690,9 +690,10 @@ static void wayland_surface_reconfigure_client(struct wayland_surface *surface, const RECT *client_rect) { struct wayland_window_config *window = &surface->window; - RECT rect = *client_rect; + RECT rect = client->rect; /* The offset of the client area origin relatively to the window origin. */ + if (client_rect) rect = *client_rect; OffsetRect(&rect, window->client_rect.left - window->rect.left, window->client_rect.top - window->rect.top); rect = map_rect_to_surface(surface, rect); @@ -709,6 +710,8 @@ static void wayland_surface_reconfigure_client(struct wayland_surface *surface, wp_viewport_set_destination(client->wp_viewport, rect.right - rect.left, rect.bottom - rect.top); else /* We can't have a 0x0 destination, use 1x1 instead. */ wp_viewport_set_destination(client->wp_viewport, 1, 1); + + client->rect = *client_rect; } /********************************************************************** @@ -1173,7 +1176,7 @@ static void wayland_client_surface_detach(struct client_surface *client) if ((data = wayland_win_data_get(client->hwnd))) { if (data->client_surface == surface) data->client_surface = NULL; - wayland_client_surface_attach(surface, NULL); + wayland_client_surface_attach(surface, NULL, NULL); wayland_win_data_release(data); } } @@ -1189,9 +1192,9 @@ static void wayland_client_surface_update(struct client_surface *client) if (!(data = wayland_win_data_get(hwnd))) return; if (toplevel && NtUserIsWindowVisible(hwnd)) - wayland_client_surface_attach(surface, toplevel); + wayland_client_surface_attach(surface, toplevel, &client->monitor_rect); else - wayland_client_surface_attach(surface, NULL); + wayland_client_surface_attach(surface, NULL, NULL); wayland_win_data_release(data); } @@ -1280,12 +1283,10 @@ err: return NULL; } -void wayland_client_surface_attach(struct wayland_client_surface *client, HWND toplevel) +void wayland_client_surface_attach(struct wayland_client_surface *client, HWND toplevel, const RECT *rect) { struct wayland_win_data *toplevel_data; struct wayland_surface *surface; - HWND hwnd = client->client.hwnd; - RECT client_rect; if (!toplevel) { @@ -1302,12 +1303,12 @@ void wayland_client_surface_attach(struct wayland_client_surface *client, HWND t if (!(toplevel_data = wayland_win_data_get(toplevel)) || !(surface = toplevel_data->wayland_surface)) { if (toplevel_data) wayland_win_data_release(toplevel_data); - return wayland_client_surface_attach(client, NULL); + return wayland_client_surface_attach(client, NULL, NULL); } if (client->toplevel != toplevel) { - wayland_client_surface_attach(client, NULL); + wayland_client_surface_attach(client, NULL, NULL); client->wl_subsurface = wl_subcompositor_get_subsurface(process_wayland.wl_subcompositor, @@ -1321,10 +1322,7 @@ void wayland_client_surface_attach(struct wayland_client_surface *client, HWND t client->toplevel = toplevel; } - NtUserGetClientRect(hwnd, &client_rect, NtUserGetWinMonitorDpi(hwnd, MDT_RAW_DPI)); - NtUserMapWindowPoints(hwnd, toplevel, (POINT *)&client_rect, 2, NtUserGetWinMonitorDpi(hwnd, MDT_RAW_DPI)); - - wayland_surface_reconfigure_client(surface, client, &client_rect); + wayland_surface_reconfigure_client(surface, client, rect); /* Commit to apply subsurface positioning. */ wl_surface_commit(surface->wl_surface); diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h index f88c562112c..da166c939d4 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -249,6 +249,7 @@ struct wayland_client_surface { struct client_surface client; HWND toplevel; + RECT rect; struct wl_surface *wl_surface; struct wl_subsurface *wl_subsurface; struct wp_viewport *wp_viewport; @@ -337,7 +338,7 @@ RECT map_rect_to_surface(struct wayland_surface *surface, RECT rect); POINT map_point_to_surface(struct wayland_surface *surface, POINT point); RECT map_rect_from_surface(struct wayland_surface *surface, RECT rect); POINT map_point_from_surface(struct wayland_surface *surface, POINT point); -void wayland_client_surface_attach(struct wayland_client_surface *client, HWND toplevel); +void wayland_client_surface_attach(struct wayland_client_surface *client, HWND toplevel, const RECT *rect); void wayland_surface_ensure_contents(struct wayland_surface *surface); void wayland_surface_set_title(struct wayland_surface *surface, LPCWSTR title); void wayland_surface_assign_icon(struct wayland_surface *surface); diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index 59baaf258db..adff02e6c38 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -808,6 +808,7 @@ void WAYLAND_UpdateLayeredWindow(HWND hwnd, BYTE alpha, UINT flags) void set_client_surface(HWND hwnd, struct wayland_client_surface *new_client) { HWND toplevel = new_client->client.toplevel; + RECT rect = new_client->client.monitor_rect; struct wayland_client_surface *old_client; struct wayland_win_data *data; @@ -819,14 +820,14 @@ void set_client_surface(HWND hwnd, struct wayland_client_surface *new_client) if (new_client != data->client_surface) { if ((old_client = data->client_surface)) - wayland_client_surface_attach(old_client, NULL); + wayland_client_surface_attach(old_client, NULL, NULL); if ((data->client_surface = new_client)) { if (toplevel && NtUserIsWindowVisible(hwnd)) - wayland_client_surface_attach(new_client, toplevel); + wayland_client_surface_attach(new_client, toplevel, &rect); else - wayland_client_surface_attach(new_client, NULL); + wayland_client_surface_attach(new_client, NULL, NULL); } } diff --git a/dlls/winex11.drv/init.c b/dlls/winex11.drv/init.c index 60c361147c3..754349f6892 100644 --- a/dlls/winex11.drv/init.c +++ b/dlls/winex11.drv/init.c @@ -196,13 +196,6 @@ static HFONT X11DRV_SelectFont( PHYSDEV dev, HFONT hfont, UINT *aa_flags ) return dev->funcs->pSelectFont( dev, hfont, aa_flags ); } -static BOOL get_surface_rect( HWND hwnd, RECT *rect, UINT dpi ) -{ - if (!NtUserGetPresentRect( hwnd, rect, dpi ) && !NtUserGetClientRect( hwnd, rect, dpi )) return FALSE; - OffsetRect( rect, -rect->left, -rect->top ); - return TRUE; -} - static BOOL needs_client_window_clipping( HWND hwnd ) { RECT rect, client; @@ -296,30 +289,14 @@ static void x11drv_client_surface_detach( struct client_surface *client ) static void client_surface_update_geometry( HWND hwnd, struct x11drv_client_surface *surface ) { - UINT dpi = NtUserGetDpiForWindow( hwnd ); /* use window DPI here, DPI scaling is handled through offscreen presentation */ - HWND origin = hwnd, toplevel = surface->client.toplevel; XWindowChanges changes = surface->changes; - struct x11drv_win_data *data; + RECT rect = surface->client.virtual_rect; int mask = 0; - RECT rect; - - if (NtUserGetPresentRect( hwnd, &rect, dpi )) OffsetRect( &rect, -rect.left, -rect.top ); - else if (!NtUserGetClientRect( hwnd, &rect, dpi )) return; - else NtUserMapWindowPoints( origin, toplevel, (POINT *)&rect, 2, dpi ); - - if ((data = get_win_data( toplevel ))) - { - OffsetRect( &rect, data->rects.client.left - data->rects.visible.left, - data->rects.client.top - data->rects.visible.top ); - release_win_data( data ); - } changes.x = rect.left; changes.y = rect.top; changes.width = min( max( 1, rect.right - rect.left ), 65535 ); changes.height = min( max( 1, rect.bottom - rect.top ), 65535 ); - OffsetRect( &rect, -rect.left, -rect.top ); - surface->rect = rect; if (changes.x != surface->changes.x) mask |= CWX; if (changes.y != surface->changes.y) mask |= CWY; @@ -370,9 +347,13 @@ static void client_surface_update_offscreen( HWND hwnd, struct x11drv_client_sur { static const WCHAR displayW[] = {'D','I','S','P','L','A','Y', 0}; UNICODE_STRING device_str = RTL_CONSTANT_STRING(displayW); + RECT rect = surface->client.virtual_rect; + + OffsetRect( &rect, -rect.left, -rect.top ); surface->hdc_dst = NtGdiOpenDCW( &device_str, NULL, NULL, 0, TRUE, NULL, NULL, NULL ); surface->hdc_src = NtGdiOpenDCW( &device_str, NULL, NULL, 0, TRUE, NULL, NULL, NULL ); - set_dc_drawable( surface->hdc_src, surface->window, &surface->rect, IncludeInferiors ); + set_dc_drawable( surface->hdc_src, surface->window, &rect, IncludeInferiors ); + #ifdef SONAME_LIBXCOMPOSITE if (usexcomposite) pXCompositeRedirectWindow( gdi_display, surface->window, CompositeRedirectManual ); #endif @@ -401,8 +382,7 @@ static void X11DRV_client_surface_present( struct client_surface *client, HDC hd { struct x11drv_client_surface *surface = impl_from_client_surface( client ); HWND hwnd = client->hwnd, toplevel = client->toplevel; - struct x11drv_win_data *data; - RECT rect_dst, rect; + RECT rect_dst, rect_src = client->virtual_rect, rect; Drawable window; HRGN region; @@ -420,15 +400,7 @@ static void X11DRV_client_surface_present( struct client_surface *client, HDC hd else { region = get_dc_monitor_region( hwnd, hdc ); /* otherwise use the window region for clipping rules */ - if (!NtUserGetClientRect( hwnd, &rect_dst, NtUserGetWinMonitorDpi( hwnd, MDT_RAW_DPI ) )) goto done; - NtUserMapWindowPoints( hwnd, toplevel, (POINT *)&rect_dst, 2, NtUserGetWinMonitorDpi( hwnd, MDT_RAW_DPI ) ); - } - - if ((data = get_win_data( toplevel ))) - { - OffsetRect( &rect_dst, data->rects.client.left - data->rects.visible.left, - data->rects.client.top - data->rects.visible.top ); - release_win_data( data ); + rect_dst = client->monitor_rect; } if (get_dc_drawable( surface->hdc_dst, &rect ) != window || !EqualRect( &rect, &rect_dst )) @@ -436,10 +408,9 @@ static void X11DRV_client_surface_present( struct client_surface *client, HDC hd if (region) NtGdiExtSelectClipRgn( surface->hdc_dst, region, RGN_COPY ); NtGdiStretchBlt( surface->hdc_dst, 0, 0, rect_dst.right - rect_dst.left, rect_dst.bottom - rect_dst.top, - surface->hdc_src, 0, 0, surface->rect.right, surface->rect.bottom, SRCCOPY, 0 ); + surface->hdc_src, 0, 0, rect_src.right - rect_src.left, rect_src.bottom - rect_src.top, SRCCOPY, 0 ); XFlush( gdi_display ); -done: if (region) NtGdiDeleteObjectApp( region ); } @@ -476,9 +447,7 @@ struct client_surface *X11DRV_CreateClientSurface( HWND hwnd, int format ) if (!(surface = client_surface_create( sizeof(*surface), &x11drv_client_surface_funcs, hwnd ))) goto failed; surface->colormap = colormap; - - if (!get_surface_rect( hwnd, &surface->rect, NtUserGetDpiForWindow( hwnd ) )) goto failed; - if (!(surface->window = create_client_window( hwnd, surface->rect, &visual, colormap ))) goto failed; + if (!(surface->window = create_client_window( hwnd, surface->client.virtual_rect, &visual, colormap ))) goto failed; TRACE( "Created %s for client window %lx\n", debugstr_client_surface( &surface->client ), surface->window ); return &surface->client; diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 73d778259e5..fc59ac9f3b9 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -371,7 +371,6 @@ struct x11drv_client_surface XWindowChanges changes; Colormap colormap; Window window; - RECT rect; HDC hdc_src; HDC hdc_dst; diff --git a/include/wine/gdi_driver.h b/include/wine/gdi_driver.h index 0ed84a51ba7..384fdcac18e 100644 --- a/include/wine/gdi_driver.h +++ b/include/wine/gdi_driver.h @@ -267,6 +267,8 @@ struct client_surface LONG updated; /* has been moved / resized / reparented */ HWND toplevel; /* toplevel window of the surface */ LONG offscreen; /* client window is offscreen */ + RECT virtual_rect; /* virtual size and position in the toplevel ancestor */ + RECT monitor_rect; /* raw physical size and position in the toplevel ancestor */ }; W32KAPI void *client_surface_create( UINT size, const struct client_surface_funcs *funcs, HWND hwnd ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11289
From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/win32u/window.c | 11 ++++++++--- dlls/wineandroid.drv/window.c | 2 +- dlls/winewayland.drv/wayland_surface.c | 4 ++-- dlls/winex11.drv/event.c | 2 +- include/ntuser.h | 5 ++--- 5 files changed, 14 insertions(+), 10 deletions(-) diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index b9d36e076fe..1ecdca6c7d8 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -2390,7 +2390,7 @@ static BOOL apply_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags, stru return ret; } -static BOOL expose_window_surface( HWND hwnd, UINT flags, const RECT *rect, UINT dpi ) +static BOOL expose_window_surface( HWND hwnd, UINT flags, const RECT *rect ) { struct window_surface *surface; struct window_rects rects; @@ -2402,7 +2402,12 @@ static BOOL expose_window_surface( HWND hwnd, UINT flags, const RECT *rect, UINT rects = win->rects; release_win_ptr( win ); - if (rect) exposed_rect = map_dpi_rect( *rect, dpi, get_dpi_for_window( hwnd ) ); + if (rect) + { + UINT raw_dpi; + get_win_monitor_dpi( hwnd, &raw_dpi ); + exposed_rect = map_dpi_rect( *rect, raw_dpi, get_dpi_for_window( hwnd ) ); + } if (!surface || surface == &dummy_surface) { @@ -6228,7 +6233,7 @@ ULONG_PTR WINAPI NtUserCallHwndParam( HWND hwnd, DWORD_PTR param, DWORD code ) case NtUserCallHwndParam_ExposeWindowSurface: { struct expose_window_surface_params *params = (void *)param; - return expose_window_surface( hwnd, params->flags, params->whole ? NULL : ¶ms->rect, params->dpi ); + return expose_window_surface( hwnd, params->flags, params->whole ? NULL : ¶ms->rect ); } case NtUserCallHwndParam_GetWinMonitorDpi: diff --git a/dlls/wineandroid.drv/window.c b/dlls/wineandroid.drv/window.c index 3cc971558ff..136a458da32 100644 --- a/dlls/wineandroid.drv/window.c +++ b/dlls/wineandroid.drv/window.c @@ -1196,7 +1196,7 @@ LRESULT ANDROID_WindowMessage( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp ) } else { - NtUserExposeWindowSurface( hwnd, 0, NULL, 0 ); + NtUserExposeWindowSurface( hwnd, 0, NULL ); } return 0; default: diff --git a/dlls/winewayland.drv/wayland_surface.c b/dlls/winewayland.drv/wayland_surface.c index ea802e6ed01..c2b4c4be891 100644 --- a/dlls/winewayland.drv/wayland_surface.c +++ b/dlls/winewayland.drv/wayland_surface.c @@ -69,7 +69,7 @@ static void xdg_surface_handle_configure(void *private, struct xdg_surface *xdg_ * able to flush before due to the lack of the initial configure. */ if (initial_configure) { - NtUserExposeWindowSurface(hwnd, 0, NULL, 0); + NtUserExposeWindowSurface(hwnd, 0, NULL); } } @@ -169,7 +169,7 @@ void wp_fractional_scale_handle_scale(void* user_data, wayland_win_data_release(data); - NtUserExposeWindowSurface(hwnd, 0, NULL, 0); + NtUserExposeWindowSurface(hwnd, 0, NULL); } static const struct wp_fractional_scale_v1_listener wp_fractional_scale_listener = diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index e96b573083d..d4f490624ea 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -1005,7 +1005,7 @@ static BOOL X11DRV_Expose( HWND hwnd, XEvent *xev ) release_win_data( data ); - NtUserExposeWindowSurface( hwnd, flags, &rect, NtUserGetWinMonitorDpi( hwnd, MDT_RAW_DPI ) ); + NtUserExposeWindowSurface( hwnd, flags, &rect ); return TRUE; } diff --git a/include/ntuser.h b/include/ntuser.h index c3c4c8cdcf2..d5b59e67809 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -1618,12 +1618,11 @@ struct expose_window_surface_params UINT flags; BOOL whole; RECT rect; - UINT dpi; }; -static inline BOOL NtUserExposeWindowSurface( HWND hwnd, UINT flags, const RECT *rect, UINT dpi ) +static inline BOOL NtUserExposeWindowSurface( HWND hwnd, UINT flags, const RECT *rect ) { - struct expose_window_surface_params params = {.flags = flags, .whole = !rect, .dpi = dpi}; + struct expose_window_surface_params params = {.flags = flags, .whole = !rect}; if (rect) params.rect = *rect; return NtUserCallHwndParam( hwnd, (UINT_PTR)¶ms, NtUserCallHwndParam_ExposeWindowSurface ); } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11289
participants (2)
-
Rémi Bernon -
Rémi Bernon (@rbernon)