From: Zhiyi Zhang <zzhang(a)codeweavers.com> Checking flags of the thread desktop to determine whether virtual desktop is on is unreliable. For example, CEF applications create their own desktop and so is_virtual_desktop() could incorrectly report that virtual desktop is off. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=55810 --- dlls/win32u/winstation.c | 20 +++++++++++++++----- programs/explorer/desktop.c | 24 +++++++++++++++++++++++- 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/dlls/win32u/winstation.c b/dlls/win32u/winstation.c index b187b246941..249ea922f28 100644 --- a/dlls/win32u/winstation.c +++ b/dlls/win32u/winstation.c @@ -42,12 +42,22 @@ WINE_DECLARE_DEBUG_CHANNEL(win); BOOL is_virtual_desktop(void) { - HANDLE desktop = NtUserGetThreadDesktop( GetCurrentThreadId() ); - USEROBJECTFLAGS flags = {0}; - DWORD len; + static const WCHAR enabledW[] = {'E','n','a','b','l','e','d',0}; + static int enabled = -1; + char value_buffer[FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[40 * sizeof(WCHAR)])]; + KEY_VALUE_PARTIAL_INFORMATION *info = (void *)value_buffer; + DWORD size; + HKEY key; + + if (enabled == -1 && (key = reg_open_hkcu_key( "Software\\Wine\\Explorer\\VirtualDesktop" ))) + { + size = query_reg_value( key, enabledW, info, sizeof(value_buffer) ); + if (size == sizeof(DWORD) && info->Type == REG_DWORD) + enabled = *(DWORD *)info->Data > 0; + NtClose( key ); + } - if (!NtUserGetObjectInformation( desktop, UOI_FLAGS, &flags, sizeof(flags), &len )) return FALSE; - return !!(flags.dwFlags & DF_WINE_CREATE_DESKTOP); + return enabled > 0; } /*********************************************************************** diff --git a/programs/explorer/desktop.c b/programs/explorer/desktop.c index 9a58f13d887..923e5c27bb0 100644 --- a/programs/explorer/desktop.c +++ b/programs/explorer/desktop.c @@ -973,6 +973,21 @@ static void initialize_display_settings( unsigned int width, unsigned int height } } +static void save_virtual_desktop_settings( DWORD enabled ) +{ + LSTATUS ls; + HKEY hkey; + + /* Store virtual desktop status at HKCU\Software\Wine\Explorer\VirtualDesktop */ + ls = RegCreateKeyExW( HKEY_CURRENT_USER, L"Software\\Wine\\Explorer\\VirtualDesktop", 0, NULL, + REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, NULL ); + if (!ls) + { + RegSetValueExW( hkey, L"Enabled", 0, REG_DWORD, (BYTE *)&enabled, sizeof(enabled) ); + RegCloseKey( hkey ); + } +} + static void set_desktop_window_title( HWND hwnd, const WCHAR *name ) { static const WCHAR desktop_nameW[] = L"Wine desktop"; @@ -1065,7 +1080,10 @@ void manage_desktop( WCHAR *arg ) { DEVMODEW devmode = {.dmPelsWidth = width, .dmPelsHeight = height}; /* magic: desktop "root" means use the root window */ - if ((using_root = !wcsicmp( name, L"root" ))) desktop = CreateDesktopW( name, NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL ); + using_root = !wcsicmp( name, L"root" ); + /* save virtual desktop status to the registry before creating desktops */ + save_virtual_desktop_settings( !using_root ); + if (using_root) desktop = CreateDesktopW( name, NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL ); else desktop = CreateDesktopW( name, NULL, &devmode, DF_WINE_CREATE_DESKTOP, DESKTOP_ALL_ACCESS, NULL ); if (!desktop) { @@ -1074,6 +1092,10 @@ void manage_desktop( WCHAR *arg ) } SetThreadDesktop( desktop ); } + else + { + save_virtual_desktop_settings( FALSE ); + } /* create the desktop window */ hwnd = CreateWindowExW( 0, DESKTOP_CLASS_ATOM, NULL, -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/4786