From: Zhiyi Zhang zzhang@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,