From: Zhiyi Zhang zzhang@codeweavers.com
Based on RĂ©mi's idea.
CEF applications create their own desktops and so is_virtual_desktop() could incorrectly report that virtual desktop is off if DF_WINE_VIRTUAL_DESKTOP is not inherited.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=55810 --- dlls/user32/winstation.c | 3 ++- include/ntuser.h | 1 + programs/explorer/desktop.c | 2 +- server/winstation.c | 23 +++++++++++++++++++++-- 4 files changed, 25 insertions(+), 4 deletions(-)
diff --git a/dlls/user32/winstation.c b/dlls/user32/winstation.c index c433ea6ec88..ec8be243b32 100644 --- a/dlls/user32/winstation.c +++ b/dlls/user32/winstation.c @@ -256,7 +256,8 @@ HDESK WINAPI CreateDesktopW( LPCWSTR name, LPCWSTR device, LPDEVMODEW devmode, OBJECT_ATTRIBUTES attr; UNICODE_STRING str;
- if (device || (devmode && !(flags & DF_WINE_VIRTUAL_DESKTOP))) + if (device || (devmode && !(flags & DF_WINE_VIRTUAL_DESKTOP)) + || (flags & DF_WINE_ROOT_DESKTOP && flags & DF_WINE_VIRTUAL_DESKTOP)) { SetLastError( ERROR_INVALID_PARAMETER ); return 0; diff --git a/include/ntuser.h b/include/ntuser.h index a694fddf9d3..9043772dcd3 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -294,6 +294,7 @@ struct unpack_dde_message_params #define SPY_RESULT_DEFWND 0x0002
/* CreateDesktop wine specific flag */ +#define DF_WINE_ROOT_DESKTOP 0x40000000 #define DF_WINE_VIRTUAL_DESKTOP 0x80000000
/* NtUserMessageCall codes */ diff --git a/programs/explorer/desktop.c b/programs/explorer/desktop.c index e89addf5727..ae017533fc9 100644 --- a/programs/explorer/desktop.c +++ b/programs/explorer/desktop.c @@ -1065,7 +1065,7 @@ 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 ); + if ((using_root = !wcsicmp( name, L"root" ))) desktop = CreateDesktopW( name, NULL, NULL, DF_WINE_ROOT_DESKTOP, DESKTOP_ALL_ACCESS, NULL ); else desktop = CreateDesktopW( name, NULL, &devmode, DF_WINE_VIRTUAL_DESKTOP, DESKTOP_ALL_ACCESS, NULL ); if (!desktop) { diff --git a/server/winstation.c b/server/winstation.c index 5c59fbffae1..d7ae0c1db72 100644 --- a/server/winstation.c +++ b/server/winstation.c @@ -221,14 +221,30 @@ struct desktop *get_desktop_obj( struct process *process, obj_handle_t handle, u static struct desktop *create_desktop( const struct unicode_str *name, unsigned int attr, unsigned int flags, struct winstation *winstation ) { - struct desktop *desktop; + struct desktop *desktop, *current_desktop; + + if (flags & DF_WINE_ROOT_DESKTOP && flags & DF_WINE_VIRTUAL_DESKTOP) + { + set_error( STATUS_INVALID_PARAMETER ); + return NULL; + }
if ((desktop = create_named_object( &winstation->obj, &desktop_ops, name, attr, NULL ))) { if (get_error() != STATUS_OBJECT_NAME_EXISTS) { /* initialize it if it didn't already exist */ + desktop->flags = flags; + + /* inherit DF_WINE_*_DESKTOP flags if none of them are specified */ + if (!(flags & (DF_WINE_ROOT_DESKTOP | DF_WINE_VIRTUAL_DESKTOP)) + && (current_desktop = get_thread_desktop( current, 0 ))) + { + desktop->flags |= current_desktop->flags & (DF_WINE_VIRTUAL_DESKTOP | DF_WINE_ROOT_DESKTOP); + release_object( current_desktop ); + } + desktop->winstation = (struct winstation *)grab_object( winstation ); desktop->top_window = NULL; desktop->msg_window = NULL; @@ -243,7 +259,10 @@ static struct desktop *create_desktop( const struct unicode_str *name, unsigned } else { - desktop->flags |= (flags & DF_WINE_VIRTUAL_DESKTOP); + if (!(desktop->flags & DF_WINE_VIRTUAL_DESKTOP)) + desktop->flags |= flags & DF_WINE_ROOT_DESKTOP; + if (!(desktop->flags & DF_WINE_ROOT_DESKTOP)) + desktop->flags |= flags & DF_WINE_VIRTUAL_DESKTOP; clear_error(); } }