To avoid direct callbacks from display drivers to win32u while changing display settings.
-- v4: winemac.drv: Resize desktop window on WM_DISPLAYCHANGE message. winex11.drv: Resize desktop window on WM_DISPLAYCHANGE message. win32u: Send WM_DISPLAYCHANGE message to the desktop window. winex11.drv: Send WM_X11DRV_CLIP_CURSOR_REQUEST message from the deskop. winex11.drv: Sync window positions in a WM_X11DRV_DESKTOP_RESIZED message.
From: Rémi Bernon rbernon@codeweavers.com
After desktop is resized, instead of doing it only for the current process windows. --- dlls/winex11.drv/desktop.c | 23 ++++++++++++++--------- dlls/winex11.drv/display.c | 34 ---------------------------------- dlls/winex11.drv/window.c | 23 +++++++++++++++++++++++ dlls/winex11.drv/x11drv.h | 1 + 4 files changed, 38 insertions(+), 43 deletions(-)
diff --git a/dlls/winex11.drv/desktop.c b/dlls/winex11.drv/desktop.c index 3da8f92978d..b912c519947 100644 --- a/dlls/winex11.drv/desktop.c +++ b/dlls/winex11.drv/desktop.c @@ -456,6 +456,8 @@ static void update_desktop_fullscreen( unsigned int width, unsigned int height) */ void X11DRV_resize_desktop(void) { + static RECT old_virtual_rect; + RECT primary_rect, virtual_rect; HWND hwnd = NtUserGetDesktopWindow(); INT width, height; @@ -468,14 +470,17 @@ void X11DRV_resize_desktop(void) if (NtUserGetWindowThread( hwnd, NULL ) != GetCurrentThreadId()) { send_message( hwnd, WM_X11DRV_RESIZE_DESKTOP, 0, 0 ); + return; } - else - { - TRACE( "desktop %p change to (%dx%d)\n", hwnd, width, height ); - update_desktop_fullscreen( width, height ); - NtUserSetWindowPos( hwnd, 0, virtual_rect.left, virtual_rect.top, - virtual_rect.right - virtual_rect.left, virtual_rect.bottom - virtual_rect.top, - SWP_NOZORDER | SWP_NOACTIVATE | SWP_DEFERERASE ); - ungrab_clipping_window(); - } + + TRACE( "desktop %p change to (%dx%d)\n", hwnd, width, height ); + update_desktop_fullscreen( width, height ); + NtUserSetWindowPos( hwnd, 0, virtual_rect.left, virtual_rect.top, + virtual_rect.right - virtual_rect.left, virtual_rect.bottom - virtual_rect.top, + SWP_NOZORDER | SWP_NOACTIVATE | SWP_DEFERERASE ); + ungrab_clipping_window(); + send_message_timeout( HWND_BROADCAST, WM_X11DRV_DESKTOP_RESIZED, old_virtual_rect.left, + old_virtual_rect.top, SMTO_ABORTIFHUNG, 2000, FALSE ); + + old_virtual_rect = virtual_rect; } diff --git a/dlls/winex11.drv/display.c b/dlls/winex11.drv/display.c index 76defa7f0e8..b552c52cb56 100644 --- a/dlls/winex11.drv/display.c +++ b/dlls/winex11.drv/display.c @@ -560,47 +560,13 @@ void X11DRV_DisplayDevices_RegisterEventHandlers(void)
void X11DRV_DisplayDevices_Update(void) { - RECT old_virtual_rect, new_virtual_rect; DWORD tid, pid; HWND foreground; - UINT mask = 0, i; - HWND *list;
- old_virtual_rect = NtUserGetVirtualScreenRect(); X11DRV_DisplayDevices_Init(TRUE); - new_virtual_rect = NtUserGetVirtualScreenRect(); - - /* Calculate XReconfigureWMWindow() mask */ - if (old_virtual_rect.left != new_virtual_rect.left) - mask |= CWX; - if (old_virtual_rect.top != new_virtual_rect.top) - mask |= CWY;
X11DRV_resize_desktop();
- list = build_hwnd_list(); - for (i = 0; list && list[i] != HWND_BOTTOM; i++) - { - struct x11drv_win_data *data; - - if (!(data = get_win_data( list[i] ))) continue; - - /* update the full screen state */ - update_net_wm_states(data); - - if (mask && data->whole_window) - { - POINT pos = virtual_screen_to_root(data->whole_rect.left, data->whole_rect.top); - XWindowChanges changes; - changes.x = pos.x; - changes.y = pos.y; - XReconfigureWMWindow(data->display, data->whole_window, data->vis.screen, mask, &changes); - } - release_win_data(data); - } - - free( list ); - /* forward clip_fullscreen_window request to the foreground window */ if ((foreground = NtUserGetForegroundWindow()) && (tid = NtUserGetWindowThread( foreground, &pid )) && pid == GetCurrentProcessId()) diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index c0c6e779772..7f4a92abe5f 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -2996,6 +2996,29 @@ LRESULT X11DRV_WindowMessage( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp ) case WM_X11DRV_RESIZE_DESKTOP: X11DRV_resize_desktop(); return 0; + case WM_X11DRV_DESKTOP_RESIZED: + if ((data = get_win_data( hwnd ))) + { + /* update the full screen state */ + update_net_wm_states( data ); + + if (data->whole_window) + { + /* sync window position with the new virtual screen rect */ + POINT old_pos = {.x = data->whole_rect.left - wp, .y = data->whole_rect.top - lp}; + POINT pos = virtual_screen_to_root( data->whole_rect.left, data->whole_rect.top ); + XWindowChanges changes = {.x = pos.x, .y = pos.y}; + UINT mask = 0; + + if (old_pos.x != pos.x) mask |= CWX; + if (old_pos.y != pos.y) mask |= CWY; + + if (mask) XReconfigureWMWindow( data->display, data->whole_window, data->vis.screen, mask, &changes ); + } + + release_win_data( data ); + } + return 0; case WM_X11DRV_SET_CURSOR: { Window win = 0; diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index d1a70da9998..fc646771acd 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -573,6 +573,7 @@ enum x11drv_window_messages WM_X11DRV_UPDATE_CLIPBOARD = 0x80001000, WM_X11DRV_SET_WIN_REGION, WM_X11DRV_RESIZE_DESKTOP, + WM_X11DRV_DESKTOP_RESIZED, WM_X11DRV_SET_CURSOR, WM_X11DRV_CLIP_CURSOR_NOTIFY, WM_X11DRV_CLIP_CURSOR_REQUEST,
From: Rémi Bernon rbernon@codeweavers.com
Using send_notify_message directly, which calls clip_fullscreen_window synchronously if the target thread is the same. --- dlls/winex11.drv/desktop.c | 3 +++ dlls/winex11.drv/display.c | 11 ----------- 2 files changed, 3 insertions(+), 11 deletions(-)
diff --git a/dlls/winex11.drv/desktop.c b/dlls/winex11.drv/desktop.c index b912c519947..721e805f820 100644 --- a/dlls/winex11.drv/desktop.c +++ b/dlls/winex11.drv/desktop.c @@ -482,5 +482,8 @@ void X11DRV_resize_desktop(void) send_message_timeout( HWND_BROADCAST, WM_X11DRV_DESKTOP_RESIZED, old_virtual_rect.left, old_virtual_rect.top, SMTO_ABORTIFHUNG, 2000, FALSE );
+ /* forward clip_fullscreen_window request to the foreground window */ + send_notify_message( NtUserGetForegroundWindow(), WM_X11DRV_CLIP_CURSOR_REQUEST, TRUE, TRUE ); + old_virtual_rect = virtual_rect; } diff --git a/dlls/winex11.drv/display.c b/dlls/winex11.drv/display.c index b552c52cb56..87f7adb76d2 100644 --- a/dlls/winex11.drv/display.c +++ b/dlls/winex11.drv/display.c @@ -560,20 +560,9 @@ void X11DRV_DisplayDevices_RegisterEventHandlers(void)
void X11DRV_DisplayDevices_Update(void) { - DWORD tid, pid; - HWND foreground; - X11DRV_DisplayDevices_Init(TRUE);
X11DRV_resize_desktop(); - - /* forward clip_fullscreen_window request to the foreground window */ - if ((foreground = NtUserGetForegroundWindow()) && - (tid = NtUserGetWindowThread( foreground, &pid )) && pid == GetCurrentProcessId()) - { - if (tid == GetCurrentThreadId()) clip_fullscreen_window( foreground, TRUE ); - else send_notify_message( foreground, WM_X11DRV_CLIP_CURSOR_REQUEST, TRUE, TRUE ); - } }
static BOOL force_display_devices_refresh;
From: Rémi Bernon rbernon@codeweavers.com
And pass it down to the drivers DesktopWindowProc entry. --- dlls/user32/desktop.c | 1 + dlls/win32u/defwnd.c | 3 ++- dlls/win32u/sysparams.c | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/dlls/user32/desktop.c b/dlls/user32/desktop.c index 377c21d4f48..b0384b6d8c2 100644 --- a/dlls/user32/desktop.c +++ b/dlls/user32/desktop.c @@ -83,6 +83,7 @@ LRESULT WINAPI DesktopWndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lP case WM_NCCREATE: case WM_NCCALCSIZE: case WM_PARENTNOTIFY: + case WM_DISPLAYCHANGE: return NtUserMessageCall( hwnd, message, wParam, lParam, 0, NtUserDesktopWindowProc, FALSE );
default: diff --git a/dlls/win32u/defwnd.c b/dlls/win32u/defwnd.c index a5644f594ad..e26e68442ab 100644 --- a/dlls/win32u/defwnd.c +++ b/dlls/win32u/defwnd.c @@ -2953,7 +2953,8 @@ LRESULT desktop_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) } case WM_NCCALCSIZE: return 0; - + case WM_DISPLAYCHANGE: + return user_driver->pDesktopWindowProc( hwnd, msg, wparam, lparam ); default: if (msg >= WM_USER && hwnd == get_desktop_window()) return user_driver->pDesktopWindowProc( hwnd, msg, wparam, lparam ); diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 494bb94c7f1..1c81dda9dd3 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -2487,6 +2487,8 @@ static LONG apply_display_settings( const WCHAR *devname, const DEVMODEW *devmod user_driver->pGetCurrentDisplaySettings( adapter->dev.device_name, ¤t_mode ); adapter_release( adapter );
+ send_message( NtUserGetDesktopWindow(), WM_DISPLAYCHANGE, current_mode.dmBitsPerPel, + MAKELPARAM( current_mode.dmPelsWidth, current_mode.dmPelsHeight ) ); send_message_timeout( HWND_BROADCAST, WM_DISPLAYCHANGE, current_mode.dmBitsPerPel, MAKELPARAM( current_mode.dmPelsWidth, current_mode.dmPelsHeight ), SMTO_ABORTIFHUNG, 2000, FALSE );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/desktop.c | 6 ------ dlls/winex11.drv/display.c | 9 +-------- dlls/winex11.drv/window.c | 6 +++--- dlls/winex11.drv/x11drv.h | 2 -- dlls/winex11.drv/xrandr.c | 3 ++- 5 files changed, 6 insertions(+), 20 deletions(-)
diff --git a/dlls/winex11.drv/desktop.c b/dlls/winex11.drv/desktop.c index 721e805f820..c6a08291f6a 100644 --- a/dlls/winex11.drv/desktop.c +++ b/dlls/winex11.drv/desktop.c @@ -467,12 +467,6 @@ void X11DRV_resize_desktop(void) width = primary_rect.right; height = primary_rect.bottom;
- if (NtUserGetWindowThread( hwnd, NULL ) != GetCurrentThreadId()) - { - send_message( hwnd, WM_X11DRV_RESIZE_DESKTOP, 0, 0 ); - return; - } - TRACE( "desktop %p change to (%dx%d)\n", hwnd, width, height ); update_desktop_fullscreen( width, height ); NtUserSetWindowPos( hwnd, 0, virtual_rect.left, virtual_rect.top, diff --git a/dlls/winex11.drv/display.c b/dlls/winex11.drv/display.c index 87f7adb76d2..572b81aa491 100644 --- a/dlls/winex11.drv/display.c +++ b/dlls/winex11.drv/display.c @@ -419,7 +419,7 @@ LONG X11DRV_ChangeDisplaySettings( LPDEVMODEW displays, HWND hwnd, DWORD flags, if (ret == DISP_CHANGE_SUCCESSFUL) ret = apply_display_settings( displays, ids, TRUE ); if (ret == DISP_CHANGE_SUCCESSFUL) - X11DRV_DisplayDevices_Update(); + X11DRV_DisplayDevices_Init(TRUE);
done: free( ids ); @@ -558,13 +558,6 @@ void X11DRV_DisplayDevices_RegisterEventHandlers(void) handler->register_event_handlers(); }
-void X11DRV_DisplayDevices_Update(void) -{ - X11DRV_DisplayDevices_Init(TRUE); - - X11DRV_resize_desktop(); -} - static BOOL force_display_devices_refresh;
BOOL X11DRV_UpdateDisplayDevices( const struct gdi_device_manager *device_manager, BOOL force, void *param ) diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 7f4a92abe5f..70a29d24fb1 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -1893,6 +1893,9 @@ LRESULT X11DRV_DesktopWindowProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp ) case WM_WINE_ADD_TAB: send_notify_message( (HWND)wp, WM_X11DRV_ADD_TAB, 0, 0 ); break; + case WM_DISPLAYCHANGE: + X11DRV_resize_desktop(); + break; } return NtUserMessageCall( hwnd, msg, wp, lp, 0, NtUserDefWindowProc, FALSE ); } @@ -2993,9 +2996,6 @@ LRESULT X11DRV_WindowMessage( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp ) release_win_data( data ); } return 0; - case WM_X11DRV_RESIZE_DESKTOP: - X11DRV_resize_desktop(); - return 0; case WM_X11DRV_DESKTOP_RESIZED: if ((data = get_win_data( hwnd ))) { diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index fc646771acd..f8f8fe3d4d1 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -572,7 +572,6 @@ enum x11drv_window_messages { WM_X11DRV_UPDATE_CLIPBOARD = 0x80001000, WM_X11DRV_SET_WIN_REGION, - WM_X11DRV_RESIZE_DESKTOP, WM_X11DRV_DESKTOP_RESIZED, WM_X11DRV_SET_CURSOR, WM_X11DRV_CLIP_CURSOR_NOTIFY, @@ -805,7 +804,6 @@ extern BOOL get_host_primary_gpu(struct gdi_gpu *gpu) DECLSPEC_HIDDEN; extern void X11DRV_DisplayDevices_SetHandler(const struct x11drv_display_device_handler *handler) DECLSPEC_HIDDEN; extern void X11DRV_DisplayDevices_Init(BOOL force) DECLSPEC_HIDDEN; extern void X11DRV_DisplayDevices_RegisterEventHandlers(void) DECLSPEC_HIDDEN; -extern void X11DRV_DisplayDevices_Update(void) DECLSPEC_HIDDEN; /* Display device handler used in virtual desktop mode */ extern struct x11drv_display_device_handler desktop_handler DECLSPEC_HIDDEN;
diff --git a/dlls/winex11.drv/xrandr.c b/dlls/winex11.drv/xrandr.c index a0ac2cb5ec1..c7f922b1aae 100644 --- a/dlls/winex11.drv/xrandr.c +++ b/dlls/winex11.drv/xrandr.c @@ -1198,8 +1198,9 @@ static BOOL xrandr14_device_change_handler( HWND hwnd, XEvent *event ) xrandr14_invalidate_current_mode_cache(); if (hwnd == NtUserGetDesktopWindow() && NtUserGetWindowThread( hwnd, NULL ) == GetCurrentThreadId()) { - X11DRV_DisplayDevices_Update(); + X11DRV_DisplayDevices_Init( TRUE ); init_registry_display_settings(); + X11DRV_resize_desktop(); } return FALSE; }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winemac.drv/display.c | 5 +---- dlls/winemac.drv/macdrv.h | 2 +- dlls/winemac.drv/window.c | 44 ++++++++++++++++++++------------------ 3 files changed, 25 insertions(+), 26 deletions(-)
diff --git a/dlls/winemac.drv/display.c b/dlls/winemac.drv/display.c index 977949fc47f..e8d26dfd241 100644 --- a/dlls/winemac.drv/display.c +++ b/dlls/winemac.drv/display.c @@ -831,10 +831,7 @@ LONG macdrv_ChangeDisplaySettings(LPDEVMODEW displays, HWND hwnd, DWORD flags, L ret = DISP_CHANGE_BADMODE; } else if (macdrv_set_display_mode(&macdrv_displays[0], best_display_mode)) - { macdrv_init_display_devices(TRUE); - send_message(NtUserGetDesktopWindow(), WM_MACDRV_UPDATE_DESKTOP_RECT, 0, 0); - } else { WARN("Failed to set display mode\n"); @@ -1172,7 +1169,7 @@ void macdrv_displays_changed(const macdrv_event *event) { macdrv_init_display_devices(TRUE); init_registry_display_settings(); - send_message(hwnd, WM_MACDRV_UPDATE_DESKTOP_RECT, 0, 0); + macdrv_resize_desktop(); } }
diff --git a/dlls/winemac.drv/macdrv.h b/dlls/winemac.drv/macdrv.h index 683fd1851a3..ea51cf0f702 100644 --- a/dlls/winemac.drv/macdrv.h +++ b/dlls/winemac.drv/macdrv.h @@ -92,7 +92,6 @@ extern BOOL CDECL macdrv_SetDeviceGammaRamp(PHYSDEV dev, LPVOID ramp) DECLSPEC_H enum macdrv_window_messages { WM_MACDRV_SET_WIN_REGION = 0x80001000, - WM_MACDRV_UPDATE_DESKTOP_RECT, WM_MACDRV_RESET_DEVICE_METRICS, WM_MACDRV_DISPLAYCHANGE, WM_MACDRV_ACTIVATE_ON_FOLLOWING_FOCUS, @@ -268,6 +267,7 @@ extern void macdrv_status_item_mouse_move(const macdrv_event *event) DECLSPEC_HI
extern void check_retina_status(void) DECLSPEC_HIDDEN; extern void macdrv_init_display_devices(BOOL force) DECLSPEC_HIDDEN; +extern void macdrv_resize_desktop(void) DECLSPEC_HIDDEN; extern void init_user_driver(void) DECLSPEC_HIDDEN;
/* unixlib interface */ diff --git a/dlls/winemac.drv/window.c b/dlls/winemac.drv/window.c index 7a0f6df6449..37696f02d25 100644 --- a/dlls/winemac.drv/window.c +++ b/dlls/winemac.drv/window.c @@ -1570,6 +1570,26 @@ BOOL macdrv_CreateDesktopWindow(HWND hwnd) return TRUE; }
+void macdrv_resize_desktop(void) +{ + HWND hwnd = NtUserGetDesktopWindow(); + CGRect new_desktop_rect; + RECT current_desktop_rect; + + macdrv_reset_device_metrics(); + new_desktop_rect = macdrv_get_desktop_rect(); + if (!NtUserGetWindowRect(hwnd, ¤t_desktop_rect) || + !CGRectEqualToRect(cgrect_from_rect(current_desktop_rect), new_desktop_rect)) + { + send_message_timeout(HWND_BROADCAST, WM_MACDRV_RESET_DEVICE_METRICS, 0, 0, + SMTO_ABORTIFHUNG, 2000, NULL); + NtUserSetWindowPos(hwnd, 0, CGRectGetMinX(new_desktop_rect), CGRectGetMinY(new_desktop_rect), + CGRectGetWidth(new_desktop_rect), CGRectGetHeight(new_desktop_rect), + SWP_NOZORDER | SWP_NOACTIVATE | SWP_DEFERERASE); + send_message_timeout(HWND_BROADCAST, WM_MACDRV_DISPLAYCHANGE, 0, 0, + SMTO_ABORTIFHUNG, 2000, NULL); + } +}
#define WM_WINE_NOTIFY_ACTIVITY WM_USER
@@ -1591,6 +1611,9 @@ LRESULT macdrv_DesktopWindowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) #pragma clang diagnostic pop break; } + case WM_DISPLAYCHANGE: + macdrv_resize_desktop(); + break; } return NtUserMessageCall(hwnd, msg, wp, lp, 0, NtUserDefWindowProc, FALSE); } @@ -1987,27 +2010,6 @@ LRESULT macdrv_WindowMessage(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) release_win_data(data); } return 0; - case WM_MACDRV_UPDATE_DESKTOP_RECT: - if (hwnd == NtUserGetDesktopWindow()) - { - CGRect new_desktop_rect; - RECT current_desktop_rect; - - macdrv_reset_device_metrics(); - new_desktop_rect = macdrv_get_desktop_rect(); - if (!NtUserGetWindowRect(hwnd, ¤t_desktop_rect) || - !CGRectEqualToRect(cgrect_from_rect(current_desktop_rect), new_desktop_rect)) - { - send_message_timeout(HWND_BROADCAST, WM_MACDRV_RESET_DEVICE_METRICS, 0, 0, - SMTO_ABORTIFHUNG, 2000, NULL); - NtUserSetWindowPos(hwnd, 0, CGRectGetMinX(new_desktop_rect), CGRectGetMinY(new_desktop_rect), - CGRectGetWidth(new_desktop_rect), CGRectGetHeight(new_desktop_rect), - SWP_NOZORDER | SWP_NOACTIVATE | SWP_DEFERERASE); - send_message_timeout(HWND_BROADCAST, WM_MACDRV_DISPLAYCHANGE, 0, 0, - SMTO_ABORTIFHUNG, 2000, NULL); - } - } - return 0; case WM_MACDRV_RESET_DEVICE_METRICS: macdrv_reset_device_metrics(); return 0;
v4: Fix fullscreen clipping restoration, rebase on upstream for the tests to run.
This merge request was approved by Zhiyi Zhang.
The ddraw failure looks possibly genuine, I'll have a look.
I ran the pipeline a few more times, and it seems to pass mostly consistently, I'll assume it was a fluke.