[PATCH 0/4] MR9721: win32u, winex11: Use the D3D present rect for fullscreen exclusive windows.
From: Rémi Bernon <rbernon(a)codeweavers.com> Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=58844 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=58443 --- dlls/win32u/window.c | 28 +++++++++++++++++++++++++--- dlls/wow64win/user.c | 18 +++++++++++++++--- include/ntuser.h | 19 +++++++++++++------ 3 files changed, 53 insertions(+), 12 deletions(-) diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 66d270fd3a2..a5094e82de5 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -5992,6 +5992,19 @@ static BOOL set_raw_window_pos( HWND hwnd, RECT rect, UINT flags, BOOL internal return NtUserSetWindowPos( hwnd, 0, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, flags ); } +static BOOL get_present_rect( HWND hwnd, RECT *rect, UINT dpi ) +{ + UINT dpi_from = get_dpi_for_window( hwnd ); + WND *win; + + if (!(win = get_win_ptr( hwnd )) || win == WND_OTHER_PROCESS || win == WND_DESKTOP) return FALSE; + if (dpi != -1) *rect = map_dpi_rect( win->present_rect, dpi_from, dpi ); + else *rect = map_rect_virt_to_raw( win->present_rect, dpi_from ); + release_win_ptr( win ); + + return !IsRectEmpty( rect ); +} + /***************************************************************************** * NtUserCallHwnd (win32u.@) */ @@ -6111,11 +6124,20 @@ ULONG_PTR WINAPI NtUserCallHwndParam( HWND hwnd, DWORD_PTR param, DWORD code ) case NtUserCallHwndParam_GetWindowLongPtrW: return get_window_long_ptr( hwnd, param, FALSE ); - case NtUserCallHwndParam_GetWindowRects: + case NtUserCallHwndParam_GetWindowRect: + { + struct get_window_rects_params *params = (void *)param; + return get_window_rect( hwnd, params->rect, params->dpi ); + } + case NtUserCallHwndParam_GetClientRect: + { + struct get_window_rects_params *params = (void *)param; + return get_client_rect( hwnd, params->rect, params->dpi ); + } + case NtUserCallHwndParam_GetPresentRect: { struct get_window_rects_params *params = (void *)param; - return params->client ? get_client_rect( hwnd, params->rect, params->dpi ) - : get_window_rect( hwnd, params->rect, params->dpi ); + return get_present_rect( hwnd, params->rect, params->dpi ); } case NtUserCallHwndParam_GetWindowRelative: diff --git a/dlls/wow64win/user.c b/dlls/wow64win/user.c index b728e7c01d7..8304517fbf7 100644 --- a/dlls/wow64win/user.c +++ b/dlls/wow64win/user.c @@ -1681,18 +1681,30 @@ NTSTATUS WINAPI wow64_NtUserCallHwndParam( UINT *args ) return NtUserCallHwndParam( hwnd, (UINT_PTR)&info, code ); } - case NtUserCallHwndParam_GetWindowRects: + case NtUserCallHwndParam_GetWindowRect: + { + struct + { + ULONG rect; + UINT dpi; + } *params32 = UlongToPtr( param ); + struct get_window_rects_params params; + + params.rect = UlongToPtr( params32->rect ); + params.dpi = params32->dpi; + return NtUserCallHwndParam( hwnd, (UINT_PTR)¶ms, code ); + } + + case NtUserCallHwndParam_GetClientRect: { struct { ULONG rect; - BOOL client; UINT dpi; } *params32 = UlongToPtr( param ); struct get_window_rects_params params; params.rect = UlongToPtr( params32->rect ); - params.client = params32->client; params.dpi = params32->dpi; return NtUserCallHwndParam( hwnd, (UINT_PTR)¶ms, code ); } diff --git a/include/ntuser.h b/include/ntuser.h index 78eee8f17d5..068055a87cf 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -1404,7 +1404,9 @@ enum NtUserCallHwndParam_GetWindowLongW, NtUserCallHwndParam_GetWindowLongPtrA, NtUserCallHwndParam_GetWindowLongPtrW, - NtUserCallHwndParam_GetWindowRects, + NtUserCallHwndParam_GetWindowRect, + NtUserCallHwndParam_GetClientRect, + NtUserCallHwndParam_GetPresentRect, NtUserCallHwndParam_GetWindowRelative, NtUserCallHwndParam_GetWindowThread, NtUserCallHwndParam_GetWindowWord, @@ -1424,7 +1426,6 @@ enum struct get_window_rects_params { RECT *rect; - BOOL client; UINT dpi; }; @@ -1465,8 +1466,14 @@ static inline WORD NtUserGetClassWord( HWND hwnd, INT offset ) static inline BOOL NtUserGetClientRect( HWND hwnd, RECT *rect, UINT dpi ) { - struct get_window_rects_params params = {.rect = rect, .client = TRUE, .dpi = dpi}; - return NtUserCallHwndParam( hwnd, (UINT_PTR)¶ms, NtUserCallHwndParam_GetWindowRects ); + struct get_window_rects_params params = {.rect = rect, .dpi = dpi}; + return NtUserCallHwndParam( hwnd, (UINT_PTR)¶ms, NtUserCallHwndParam_GetClientRect ); +} + +static inline BOOL NtUserGetPresentRect( HWND hwnd, RECT *rect, UINT dpi ) +{ + struct get_window_rects_params params = {.rect = rect, .dpi = dpi}; + return NtUserCallHwndParam( hwnd, (UINT_PTR)¶ms, NtUserCallHwndParam_GetPresentRect ); } struct get_scroll_info_params @@ -1508,8 +1515,8 @@ static inline LONG NtUserGetWindowLongW( HWND hwnd, INT offset ) static inline BOOL NtUserGetWindowRect( HWND hwnd, RECT *rect, UINT dpi ) { - struct get_window_rects_params params = {.rect = rect, .client = FALSE, .dpi = dpi}; - return NtUserCallHwndParam( hwnd, (UINT_PTR)¶ms, NtUserCallHwndParam_GetWindowRects ); + struct get_window_rects_params params = {.rect = rect, .dpi = dpi}; + return NtUserCallHwndParam( hwnd, (UINT_PTR)¶ms, NtUserCallHwndParam_GetWindowRect ); } static inline HWND NtUserGetWindowRelative( HWND hwnd, UINT rel ) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9721
From: Rémi Bernon <rbernon(a)codeweavers.com> And force the window to be fullscreen. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=58844 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=58443 --- dlls/win32u/win32u_private.h | 1 + dlls/win32u/window.c | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index 0b69ccd481d..15bae4e5a20 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -257,6 +257,7 @@ extern BOOL client_to_screen( HWND hwnd, POINT *pt ); extern void destroy_thread_windows(void); extern LRESULT destroy_window( HWND hwnd ); extern BOOL get_client_rect( HWND hwnd, RECT *rect, UINT dpi ); +extern BOOL get_present_rect( HWND hwnd, RECT *rect, UINT dpi ); extern HWND get_desktop_window(void); extern UINT get_dpi_for_window( HWND hwnd ); extern HWND get_full_window_handle( HWND hwnd ); diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index a5094e82de5..6b4c0b06947 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -1992,6 +1992,7 @@ static RECT get_visible_rect( HWND hwnd, BOOL shaped, UINT style, UINT ex_style, UINT dpi = get_dpi_for_window( hwnd ), style_mask, ex_style_mask; RECT visible_rect, rect = {0}; + if (get_present_rect( hwnd, &rect, get_thread_dpi() )) return rect; if (IsRectEmpty( &rects->window ) || EqualRect( &rects->window, &rects->client ) || shaped || !decorated_mode) return rects->window; if (!user_driver->pGetWindowStyleMasks( hwnd, style, ex_style, &style_mask, &ex_style_mask )) return rects->window; if (!NtUserAdjustWindowRect( &rect, style & style_mask, FALSE, ex_style & ex_style_mask, dpi )) return rects->window; @@ -2081,7 +2082,7 @@ static struct window_surface *get_window_surface( HWND hwnd, UINT swp_flags, BOO if (get_window_region( hwnd, FALSE, &shape, &dummy )) shaped = FALSE; else if ((shaped = !!shape)) NtGdiDeleteObjectApp( shape ); - rects->visible = rects->window; + if (!get_present_rect( hwnd, &rects->visible, get_thread_dpi() )) rects->visible = rects->window; if (is_child) monitor_rects = map_dpi_window_rects( *rects, get_thread_dpi(), raw_dpi ); else monitor_rects = map_window_rects_virt_to_raw( *rects, get_thread_dpi() ); @@ -2271,6 +2272,15 @@ static BOOL apply_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags, stru if (win->dwStyle & WS_THICKFRAME) swp_flags |= WINE_SWP_RESIZABLE; if (is_child) monitor_rects = map_dpi_window_rects( *new_rects, dpi, raw_dpi ); + else if (!IsRectEmpty( &win->present_rect )) + { + MONITORINFO monitor_info = monitor_info_from_rect( new_rects->window, dpi ); + struct window_rects rects = { monitor_info.rcMonitor, monitor_info.rcMonitor, monitor_info.rcMonitor }; + OffsetRect( &rects.client, -rects.client.left, -rects.client.top ); + swp_flags |= WINE_SWP_FULLSCREEN; + swp_flags &= ~WINE_SWP_RESIZABLE; + monitor_rects = map_window_rects_virt_to_raw( rects, dpi ); + } else { MONITORINFO monitor_info = monitor_info_from_rect( new_rects->window, dpi ); @@ -5992,7 +6002,7 @@ static BOOL set_raw_window_pos( HWND hwnd, RECT rect, UINT flags, BOOL internal return NtUserSetWindowPos( hwnd, 0, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, flags ); } -static BOOL get_present_rect( HWND hwnd, RECT *rect, UINT dpi ) +BOOL get_present_rect( HWND hwnd, RECT *rect, UINT dpi ) { UINT dpi_from = get_dpi_for_window( hwnd ); WND *win; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9721
From: Rémi Bernon <rbernon(a)codeweavers.com> Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=58844 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=58443 --- dlls/win32u/input.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c index 57d054a9df6..7ba5b97fbc2 100644 --- a/dlls/win32u/input.c +++ b/dlls/win32u/input.c @@ -2671,7 +2671,8 @@ BOOL clip_fullscreen_window( HWND hwnd, BOOL reset ) if ((style & WS_MAXIMIZE) && (style & WS_CAPTION) == WS_CAPTION) return FALSE; ctx = set_thread_dpi_awareness_context( NTUSER_DPI_PER_MONITOR_AWARE ); - ret = get_window_rect( hwnd, &window_rect, get_thread_dpi() ); + if (!(ret = get_present_rect( hwnd, &window_rect, get_thread_dpi() ))) + ret = get_window_rect( hwnd, &window_rect, get_thread_dpi() ); monitor_info = monitor_info_from_window( hwnd, MONITOR_DEFAULTTONEAREST ); virtual_rect = get_virtual_screen_rect( get_thread_dpi(), MDT_DEFAULT ); monitor_rect = map_rect_virt_to_raw( monitor_info.rcMonitor, get_thread_dpi() ); @@ -2777,6 +2778,7 @@ BOOL WINAPI NtUserGetClipCursor( RECT *rect ) */ BOOL WINAPI NtUserClipCursor( const RECT *rect ) { + UINT dpi = get_thread_dpi(); RECT new_rect; BOOL ret; @@ -2784,8 +2786,14 @@ BOOL WINAPI NtUserClipCursor( const RECT *rect ) if (rect) { + HWND foreground = NtUserGetForegroundWindow(); + if (IsRectEmpty( rect ) && get_present_rect( foreground, &new_rect, dpi )) + { + WARN( "Fullscreen clipping fixup to %s\n", wine_dbgstr_rect(&new_rect) ); + rect = &new_rect; + } if (rect->left > rect->right || rect->top > rect->bottom) return FALSE; - new_rect = map_rect_virt_to_raw( *rect, get_thread_dpi() ); + new_rect = map_rect_virt_to_raw( *rect, dpi ); rect = &new_rect; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9721
From: Rémi Bernon <rbernon(a)codeweavers.com> Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=58844 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=58443 --- dlls/winex11.drv/event.c | 1 + dlls/winex11.drv/init.c | 32 +++++++++++++++++++++++++------- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 153ec78f889..d951eaa9ed9 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -610,6 +610,7 @@ static inline BOOL can_activate_window( HWND hwnd ) if (style & WS_MINIMIZE) return FALSE; if (NtUserGetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOACTIVATE) return FALSE; if (hwnd == NtUserGetDesktopWindow()) return FALSE; + if (NtUserGetPresentRect( hwnd, &rect, 0 )) return TRUE; if (NtUserGetWindowRect( hwnd, &rect, NtUserGetDpiForWindow( hwnd ) ) && IsRectEmpty( &rect )) return FALSE; return !(style & WS_DISABLED); } diff --git a/dlls/winex11.drv/init.c b/dlls/winex11.drv/init.c index 5da09b3f101..00454832ca3 100644 --- a/dlls/winex11.drv/init.c +++ b/dlls/winex11.drv/init.c @@ -195,6 +195,13 @@ 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; @@ -202,6 +209,7 @@ static BOOL needs_client_window_clipping( HWND hwnd ) HRGN region; HDC hdc; + if (NtUserGetPresentRect( hwnd, &client, 0 )) return FALSE; if (!NtUserGetClientRect( hwnd, &client, NtUserGetDpiForWindow( hwnd ) )) return FALSE; OffsetRect( &client, -client.left, -client.top ); @@ -306,14 +314,15 @@ static void x11drv_client_surface_detach( struct client_surface *client ) static void client_surface_update_geometry( HWND hwnd, struct x11drv_client_surface *surface ) { - HWND toplevel = NtUserGetAncestor( hwnd, GA_ROOT ); + HWND origin = hwnd, toplevel = NtUserGetAncestor( hwnd, GA_ROOT ); XWindowChanges changes = surface->changes; struct x11drv_win_data *data; int mask = 0; RECT rect; - if (!NtUserGetClientRect( hwnd, &rect, NtUserGetDpiForWindow( hwnd ) )) return; - NtUserMapWindowPoints( hwnd, toplevel, (POINT *)&rect, 2, NtUserGetDpiForWindow( hwnd ) ); + if (NtUserGetPresentRect( toplevel, &rect, -1 /* raw dpi */ )) origin = hwnd; + else if (!NtUserGetClientRect( hwnd, &rect, NtUserGetWinMonitorDpi( hwnd, MDT_RAW_DPI ) )) return; + NtUserMapWindowPoints( origin, toplevel, (POINT *)&rect, 2, NtUserGetWinMonitorDpi( hwnd, MDT_RAW_DPI ) ); if ((data = get_win_data( toplevel ))) { OffsetRect( &rect, data->rects.client.left - data->rects.visible.left, @@ -420,10 +429,19 @@ static void X11DRV_client_surface_present( struct client_surface *client, HDC hd if (!hdc) return; window = X11DRV_get_whole_window( toplevel ); - region = get_dc_monitor_region( hwnd, hdc ); - 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 (NtUserGetPresentRect( toplevel, &rect_dst, -1 /* raw dpi */ )) + { + region = 0; /* window is exclusive fullscreen, ignore everything else */ + if (toplevel != hwnd) return; /* toplevel is exclusive fullscreen, don't present */ + NtUserMapWindowPoints( 0, toplevel, (POINT *)&rect_dst, 2, NtUserGetWinMonitorDpi( hwnd, MDT_RAW_DPI ) ); + } + 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 ))) { @@ -472,7 +490,7 @@ Window x11drv_client_surface_create( HWND hwnd, int format, struct client_surfac if (!(surface = client_surface_create( sizeof(*surface), &x11drv_client_surface_funcs, hwnd ))) goto failed; surface->colormap = colormap; - if (!NtUserGetClientRect( hwnd, &surface->rect, NtUserGetDpiForWindow( hwnd ) )) goto failed; + if (!get_surface_rect( hwnd, &surface->rect, NtUserGetDpiForWindow( hwnd ) )) goto failed; if (!(surface->window = create_client_window( hwnd, surface->rect, &visual, colormap ))) goto failed; TRACE( "Created %s for client window %lx\n", debugstr_client_surface( &surface->client ), surface->window ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9721
participants (1)
-
Rémi Bernon