Cloaking is implemented by setting the opacity of a window to zero, and setting an empty shape using libXshape. This makes it transparent to mouse input and completely invisible, while otherwise still processing the exact same messages/events as a visible window would, to match what Windows does.
While a cloaked window still has a taskbar visible, it also has the same traits as a normal window. For example, a minimized cloaked window will show the "Restore" or "Unminimize" function when right-clicking on its taskbar icon. So that means unmapping the window would *not* be the same behavior as Windows, since it even removes the taskbar item in the first place.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com ---
The reason the GetWindow( hwnd, GW_OWNER ) check is done in this patch, rather than in user32, is because it must not be checked for shell-cloaked windows (last patch in the series). The shell has full control over what windows it hides and doesn't abide by that, at least on Wine, because of how virtual desktops work.
dlls/winex11.drv/window.c | 106 ++++++++++++++++++++++++++++-- dlls/winex11.drv/winex11.drv.spec | 1 + dlls/winex11.drv/x11drv.h | 41 ++++++++++++ 3 files changed, 141 insertions(+), 7 deletions(-)
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 4571739..3e4f9eb 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -44,6 +44,7 @@ #include "wine/unicode.h"
#include "x11drv.h" +#include "dwmapi.h" #include "wine/debug.h" #include "wine/server.h" #include "mwm.h" @@ -390,7 +391,7 @@ static void sync_window_region( struct x11drv_win_data *data, HRGN win_region ) if (!data->whole_window) return; data->shaped = FALSE;
- if (IsRectEmpty( &data->window_rect )) /* set an empty shape */ + if (IsRectEmpty( &data->window_rect ) || data->cloaked) /* set an empty shape */ { static XRectangle empty_rect; XShapeCombineRectangles( data->display, data->whole_window, ShapeBounding, 0, 0, @@ -1581,7 +1582,13 @@ static void create_whole_window( struct x11drv_win_data *data ) if (win_rgn || IsRectEmpty( &data->window_rect )) sync_window_region( data, win_rgn );
/* set the window opacity */ - if (!GetLayeredWindowAttributes( data->hwnd, &key, &alpha, &layered_flags )) layered_flags = 0; + if (data->cloaked) + { + key = 0; + alpha = 0; + layered_flags = LWA_ALPHA; + } + else if (!GetLayeredWindowAttributes( data->hwnd, &key, &alpha, &layered_flags )) layered_flags = 0; sync_window_opacity( data->display, data->whole_window, key, alpha, layered_flags );
XFlush( data->display ); /* make sure the window exists before we start painting to it */ @@ -1714,7 +1721,7 @@ void CDECL X11DRV_SetWindowStyle( HWND hwnd, INT offset, STYLESTRUCT *style ) { data->layered = FALSE; set_window_visual( data, &default_visual, FALSE ); - sync_window_opacity( data->display, data->whole_window, 0, 0, 0 ); + if (!data->cloaked) sync_window_opacity( data->display, data->whole_window, 0, 0, 0 ); if (data->surface) set_surface_color_key( data->surface, CLR_INVALID ); } done: @@ -2572,6 +2579,80 @@ done: }
+/********************************************************************** + * SetWindowCompositionAttribute (X11DRV.@) + */ +DWORD CDECL X11DRV_SetWindowCompositionAttribute( HWND hwnd, DWORD attribute, void *attr_data ) +{ + struct x11drv_win_data *data; + DWORD ret = 0; + HWND owner; + + switch (attribute) + { + case WCA_CLOAK: + if (!(data = get_win_data( hwnd ))) + { + SetLastError( ERROR_INVALID_HANDLE ); + return ~0; + } + ret = *(BOOL*)attr_data ? SET_WINDOW_CLOAKED_ON : 0; + + /* If the owner is cloaked, manual uncloaking is not allowed */ + if (!ret && (owner = GetWindow( hwnd, GW_OWNER ))) + { + struct x11drv_win_data *owner_data = get_win_data( owner ); + DWORD cloaked = 0; + if (owner_data) + { + cloaked = owner_data->cloaked ? DWM_CLOAKED_APP : 0; + release_win_data( owner_data ); + } + else + { + SERVER_START_REQ( get_window_cloaked ) + { + req->handle = wine_server_user_handle( owner ); + if (!wine_server_call( req )) cloaked = reply->cloaked; + } + SERVER_END_REQ; + } + if (cloaked) + { + release_win_data( data ); + SetLastError( ERROR_INVALID_PARAMETER ); + return ~0; + } + } + + if (!data->cloaked != !ret) + { +#ifdef HAVE_LIBXSHAPE + DWORD layered_flags = LWA_ALPHA; + COLORREF key = 0; + BYTE alpha = 0; + + data->cloaked = ret; + if (!ret && !GetLayeredWindowAttributes( hwnd, &key, &alpha, &layered_flags )) + layered_flags = 0; + + sync_window_opacity( data->display, data->whole_window, key, alpha, layered_flags ); + sync_window_region( data, (HRGN)1 ); +#else + FIXME("libXshape is not available, but cloaking requires it.\n"); + SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); + ret = ~0; +#endif + } + release_win_data( data ); + break; + default: + break; + } + return ret; +} + + /********************************************************************** * SetWindowIcon (X11DRV.@) * @@ -2631,7 +2712,7 @@ void CDECL X11DRV_SetLayeredWindowAttributes( HWND hwnd, COLORREF key, BYTE alph { set_window_visual( data, &default_visual, FALSE );
- if (data->whole_window) + if (data->whole_window && !data->cloaked) sync_window_opacity( data->display, data->whole_window, key, alpha, flags ); if (data->surface) set_surface_color_key( data->surface, (flags & LWA_COLORKEY) ? key : CLR_INVALID ); @@ -2656,9 +2737,20 @@ void CDECL X11DRV_SetLayeredWindowAttributes( HWND hwnd, COLORREF key, BYTE alph Window win = X11DRV_get_whole_window( hwnd ); if (win) { - sync_window_opacity( gdi_display, win, key, alpha, flags ); - if (flags & LWA_COLORKEY) - FIXME( "LWA_COLORKEY not supported on foreign process window %p\n", hwnd ); + DWORD cloaked = 0; + + SERVER_START_REQ( get_window_cloaked ) + { + req->handle = wine_server_user_handle( hwnd ); + if (!wine_server_call( req )) cloaked = reply->cloaked; + } + SERVER_END_REQ; + if (!cloaked) + { + sync_window_opacity( gdi_display, win, key, alpha, flags ); + if (flags & LWA_COLORKEY) + FIXME( "LWA_COLORKEY not supported on foreign process window %p\n", hwnd ); + } } } } diff --git a/dlls/winex11.drv/winex11.drv.spec b/dlls/winex11.drv/winex11.drv.spec index c0e24d8..3d8c267 100644 --- a/dlls/winex11.drv/winex11.drv.spec +++ b/dlls/winex11.drv/winex11.drv.spec @@ -33,6 +33,7 @@ @ cdecl SetFocus(long) X11DRV_SetFocus @ cdecl SetLayeredWindowAttributes(long long long long) X11DRV_SetLayeredWindowAttributes @ cdecl SetParent(long long long) X11DRV_SetParent +@ cdecl SetWindowCompositionAttribute(long long ptr) X11DRV_SetWindowCompositionAttribute @ cdecl SetWindowIcon(long long long) X11DRV_SetWindowIcon @ cdecl SetWindowRgn(long long long) X11DRV_SetWindowRgn @ cdecl SetWindowStyle(ptr long ptr) X11DRV_SetWindowStyle diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 173d94b..d62fcfd 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -570,6 +570,7 @@ struct x11drv_win_data BOOL managed : 1; /* is window managed? */ BOOL mapped : 1; /* is window mapped? (in either normal or iconic state) */ BOOL iconic : 1; /* is window in iconic state? */ + BOOL cloaked : 1; /* is window cloaked manually? */ BOOL embedded : 1; /* is window an XEMBED client? */ BOOL shaped : 1; /* is window using a custom region shape? */ BOOL layered : 1; /* is window layered and with valid attributes? */ @@ -824,4 +825,44 @@ static inline BOOL is_window_rect_mapped( const RECT *rect ) max( rect->bottom, rect->top + 1 ) > virtual_rect.top); }
+/* Undocumented structure for (Get|Set)WindowCompositionAttribute */ +struct WINCOMPATTRDATA +{ + DWORD attribute; + void *pData; + ULONG dataSize; +}; +enum +{ + WCA_UNDEFINED = 0, + WCA_NCRENDERING_ENABLED = 1, + WCA_NCRENDERING_POLICY = 2, + WCA_TRANSITIONS_FORCEDISABLED = 3, + WCA_ALLOW_NCPAINT = 4, + WCA_CAPTION_BUTTON_BOUNDS = 5, + WCA_NONCLIENT_RTL_LAYOUT = 6, + WCA_FORCE_ICONIC_REPRESENTATION = 7, + WCA_EXTENDED_FRAME_BOUNDS = 8, + WCA_HAS_ICONIC_BITMAP = 9, + WCA_THEME_ATTRIBUTES = 10, + WCA_NCRENDERING_EXILED = 11, + WCA_NCADORNMENTINFO = 12, + WCA_EXCLUDED_FROM_LIVEPREVIEW = 13, + WCA_VIDEO_OVERLAY_ACTIVE = 14, + WCA_FORCE_ACTIVEWINDOW_APPEARANCE = 15, + WCA_DISALLOW_PEEK = 16, + WCA_CLOAK = 17, + WCA_CLOAKED = 18, + WCA_ACCENT_POLICY = 19, + WCA_FREEZE_REPRESENTATION = 20, + WCA_EVER_UNCLOAKED = 21, + WCA_VISUAL_OWNER = 22, + WCA_HOLOGRAPHIC = 23, + WCA_EXCLUDED_FROM_DDA = 24, + WCA_PASSIVEUPDATEMODE = 25, + WCA_USEDARKMODECOLORS = 26, + WCA_LAST +}; +BOOL WINAPI SetWindowCompositionAttribute(HWND, const struct WINCOMPATTRDATA*); + #endif /* __WINE_X11DRV_H */