From fd6f50c0d3e96947846ca82ed0c9bd79fd8e5b80 Mon Sep 17 00:00:00 2001 From: Zhiyi Zhang Date: Mon, 11 May 2020 16:55:27 +0800 Subject: [PATCH] winex11.drv: Resize desktop upon display change events. Otherwise, Wine still has the old desktop size after a user changed display resolution using host system utilities. X11DRV_DisplayDevices_Update() is introduced so that display devices reinitialization is separated from desktop resizing. Otherwise, X11DRV_DisplayDevices_Init() would have to be called twice to resize the desktop with up-to-date primary monitor dimensions, wasting resources. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=48441 Signed-off-by: Zhiyi Zhang Signed-off-by: Alexandre Julliard --- dlls/winex11.drv/desktop.c | 37 ++++++++++++++++++++----------------- dlls/winex11.drv/display.c | 18 ++++++++++++++++++ dlls/winex11.drv/window.c | 2 +- dlls/winex11.drv/x11drv.h | 3 ++- dlls/winex11.drv/xrandr.c | 11 ++++++++--- dlls/winex11.drv/xvidmode.c | 2 +- 6 files changed, 50 insertions(+), 23 deletions(-) diff --git a/dlls/winex11.drv/desktop.c b/dlls/winex11.drv/desktop.c index bde4841ed42..9011f50c20c 100644 --- a/dlls/winex11.drv/desktop.c +++ b/dlls/winex11.drv/desktop.c @@ -145,7 +145,10 @@ static LONG X11DRV_desktop_SetCurrentMode(int mode) */ } TRACE("Resizing Wine desktop window to %dx%d\n", dd_modes[mode].width, dd_modes[mode].height); - X11DRV_resize_desktop(dd_modes[mode].width, dd_modes[mode].height); + + desktop_width = dd_modes[mode].width; + desktop_height = dd_modes[mode].height; + X11DRV_DisplayDevices_Update( TRUE ); return DISP_CHANGE_SUCCESSFUL; } @@ -387,35 +390,35 @@ static void update_desktop_fullscreen( unsigned int width, unsigned int height) /*********************************************************************** * X11DRV_resize_desktop */ -void X11DRV_resize_desktop( unsigned int width, unsigned int height ) +void X11DRV_resize_desktop( UINT mask, BOOL send_display_change ) { - RECT old_virtual_rect, new_virtual_rect; + RECT primary_rect, virtual_rect; HWND hwnd = GetDesktopWindow(); - UINT mask = 0; + INT width, height; - old_virtual_rect = get_virtual_screen_rect(); - desktop_width = width; - desktop_height = height; - X11DRV_DisplayDevices_Init( TRUE ); - new_virtual_rect = get_virtual_screen_rect(); - - if (old_virtual_rect.left != new_virtual_rect.left) mask |= CWX; - if (old_virtual_rect.top != new_virtual_rect.top) mask |= CWY; + virtual_rect = get_virtual_screen_rect(); + primary_rect = get_primary_monitor_rect(); + width = primary_rect.right; + height = primary_rect.bottom; if (GetWindowThreadProcessId( hwnd, NULL ) != GetCurrentThreadId()) { - SendMessageW( hwnd, WM_X11DRV_RESIZE_DESKTOP, 0, MAKELPARAM( width, height ) ); + SendMessageW( hwnd, WM_X11DRV_RESIZE_DESKTOP, (WPARAM)mask, (LPARAM)send_display_change ); } else { TRACE( "desktop %p change to (%dx%d)\n", hwnd, width, height ); update_desktop_fullscreen( width, height ); - SetWindowPos( hwnd, 0, new_virtual_rect.left, new_virtual_rect.top, - new_virtual_rect.right - new_virtual_rect.left, new_virtual_rect.bottom - new_virtual_rect.top, + SetWindowPos( 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(); - SendMessageTimeoutW( HWND_BROADCAST, WM_DISPLAYCHANGE, screen_bpp, - MAKELPARAM( width, height ), SMTO_ABORTIFHUNG, 2000, NULL ); + + if (send_display_change) + { + SendMessageTimeoutW( HWND_BROADCAST, WM_DISPLAYCHANGE, screen_bpp, MAKELPARAM( width, height ), + SMTO_ABORTIFHUNG, 2000, NULL ); + } } EnumWindows( update_windows_on_desktop_resize, (LPARAM)mask ); diff --git a/dlls/winex11.drv/display.c b/dlls/winex11.drv/display.c index 4429cb89224..503f8c96877 100644 --- a/dlls/winex11.drv/display.c +++ b/dlls/winex11.drv/display.c @@ -273,6 +273,24 @@ void X11DRV_DisplayDevices_RegisterEventHandlers(void) handler->register_event_handlers(); } +void X11DRV_DisplayDevices_Update(BOOL send_display_change) +{ + RECT old_virtual_rect, new_virtual_rect; + UINT mask = 0; + + old_virtual_rect = get_virtual_screen_rect(); + X11DRV_DisplayDevices_Init(TRUE); + new_virtual_rect = get_virtual_screen_rect(); + + /* 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(mask, send_display_change); +} + /* Initialize a GPU instance and return its GUID string in guid_string and driver value in driver parameter */ static BOOL X11DRV_InitGpu(HDEVINFO devinfo, const struct x11drv_gpu *gpu, INT gpu_index, WCHAR *guid_string, WCHAR *driver) diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index c773c278b72..ca40005d729 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -2729,7 +2729,7 @@ LRESULT CDECL X11DRV_WindowMessage( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp ) } return 0; case WM_X11DRV_RESIZE_DESKTOP: - X11DRV_resize_desktop( LOWORD(lp), HIWORD(lp) ); + X11DRV_resize_desktop( (UINT)wp, (BOOL)lp ); return 0; case WM_X11DRV_SET_CURSOR: if ((data = get_win_data( hwnd ))) diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 98cab8947be..1f8af184808 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -657,7 +657,7 @@ struct x11drv_mode_info }; extern void X11DRV_init_desktop( Window win, unsigned int width, unsigned int height ) DECLSPEC_HIDDEN; -extern void X11DRV_resize_desktop(unsigned int width, unsigned int height) DECLSPEC_HIDDEN; +extern void X11DRV_resize_desktop(UINT, BOOL) DECLSPEC_HIDDEN; extern BOOL is_virtual_desktop(void) DECLSPEC_HIDDEN; extern BOOL is_desktop_fullscreen(void) DECLSPEC_HIDDEN; extern BOOL create_desktop_win_data( Window win ) DECLSPEC_HIDDEN; @@ -755,6 +755,7 @@ struct x11drv_display_device_handler 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(BOOL) 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 95e4a5d6dba..76e76806c55 100644 --- a/dlls/winex11.drv/xrandr.c +++ b/dlls/winex11.drv/xrandr.c @@ -209,7 +209,7 @@ static LONG xrandr10_set_current_mode( int mode ) if (stat == RRSetConfigSuccess) { xrandr_current_mode = mode; - X11DRV_resize_desktop( dd_modes[mode].width, dd_modes[mode].height ); + X11DRV_DisplayDevices_Update( TRUE ); return DISP_CHANGE_SUCCESSFUL; } @@ -457,7 +457,7 @@ static LONG xrandr12_set_current_mode( int mode ) } xrandr_current_mode = mode; - X11DRV_resize_desktop( dd_modes[mode].width, dd_modes[mode].height ); + X11DRV_DisplayDevices_Update( TRUE ); return DISP_CHANGE_SUCCESSFUL; } @@ -1094,7 +1094,12 @@ static void xrandr14_free_monitors( struct x11drv_monitor *monitors ) static BOOL xrandr14_device_change_handler( HWND hwnd, XEvent *event ) { if (hwnd == GetDesktopWindow() && GetWindowThreadProcessId( hwnd, NULL ) == GetCurrentThreadId()) - X11DRV_DisplayDevices_Init( TRUE ); + { + /* Don't send a WM_DISPLAYCHANGE message here because this event may be a result from + * ChangeDisplaySettings(). Otherwise, ChangeDisplaySettings() would send multiple + * WM_DISPLAYCHANGE messages instead of just one */ + X11DRV_DisplayDevices_Update( FALSE ); + } return FALSE; } diff --git a/dlls/winex11.drv/xvidmode.c b/dlls/winex11.drv/xvidmode.c index 890dbc46c71..a5884543163 100644 --- a/dlls/winex11.drv/xvidmode.c +++ b/dlls/winex11.drv/xvidmode.c @@ -145,7 +145,7 @@ static LONG X11DRV_XF86VM_SetCurrentMode(int mode) XWarpPointer(gdi_display, None, DefaultRootWindow(gdi_display), 0, 0, 0, 0, 0, 0); #endif XSync(gdi_display, False); - X11DRV_resize_desktop( real_xf86vm_modes[mode]->hdisplay, real_xf86vm_modes[mode]->vdisplay ); + X11DRV_DisplayDevices_Update( TRUE ); return DISP_CHANGE_SUCCESSFUL; }