From: Namo Nath <nn.git@tuta.io> Implement the X11 driver callback for NtUserSetWindowDwmConfig to support DWM_CONFIG_OPAQUE_REGION. This translates DWM margins into XShape calls, effectively punching out the non-client area to support custom frame decorations. Glass effect (-1) is handled as a shape reset to prevent visibility issues on standard visuals. --- dlls/winex11.drv/init.c | 1 + dlls/winex11.drv/window.c | 76 +++++++++++++++++++++++++++++++++++++++ dlls/winex11.drv/x11drv.h | 4 +-- 3 files changed, 79 insertions(+), 2 deletions(-) diff --git a/dlls/winex11.drv/init.c b/dlls/winex11.drv/init.c index 09ef2bf8664..b55c4b83840 100644 --- a/dlls/winex11.drv/init.c +++ b/dlls/winex11.drv/init.c @@ -697,6 +697,7 @@ static const struct user_driver_funcs x11drv_funcs = .pSetDesktopWindow = X11DRV_SetDesktopWindow, .pActivateWindow = X11DRV_ActivateWindow, .pSetLayeredWindowAttributes = X11DRV_SetLayeredWindowAttributes, + .pSetWindowDwmConfig = X11DRV_SetWindowDwmConfig, .pSetParent = X11DRV_SetParent, .pSetWindowIcons = X11DRV_SetWindowIcons, .pSetWindowRgn = X11DRV_SetWindowRgn, diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 26cb17a2c77..1d5f38e5a3a 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -50,6 +50,7 @@ #include "x11drv.h" #include "wingdi.h" #include "winuser.h" +#include <uxtheme.h> #include "wine/debug.h" #include "wine/server.h" @@ -3468,6 +3469,81 @@ void X11DRV_SetLayeredWindowAttributes( HWND hwnd, COLORREF key, BYTE alpha, DWO } +/*********************************************************************** + * X11DRV_SetWindowDwmConfig (X11DRV.@) + * + * Handle DWM configuration requests. + */ +BOOL X11DRV_SetWindowDwmConfig( HWND hwnd, INT command, const void *data ) +{ + struct x11drv_win_data *data_ptr; + Window window; + const MARGINS *margins; + XRectangle opaque_rect; + int width, height; + + if (command != DWM_CONFIG_OPAQUE_REGION) return FALSE; + if (!(margins = data)) return FALSE; + + TRACE( "hwnd %p, margins %d,%d,%d,%d\n", hwnd, + margins->cxLeftWidth, margins->cxRightWidth, + margins->cyTopHeight, margins->cyBottomHeight ); + + if (!(data_ptr = get_win_data( hwnd ))) return FALSE; + + window = data_ptr->whole_window; + if (!window) + { + release_win_data( data_ptr ); + return FALSE; + } + + width = data_ptr->rects.visible.right - data_ptr->rects.visible.left; + height = data_ptr->rects.visible.bottom - data_ptr->rects.visible.top; + + X11DRV_expect_error( data_ptr->display, NULL, NULL ); + +#ifdef HAVE_LIBXSHAPE + /* -1 (Sheet of Glass) or 0 (Standard) resets the shape to the full window */ + if (margins->cxLeftWidth == -1 || + (margins->cxLeftWidth == 0 && margins->cxRightWidth == 0 && + margins->cyTopHeight == 0 && margins->cyBottomHeight == 0)) + { + XRectangle full_rect = { 0, 0, width, height }; + XShapeCombineRectangles( data_ptr->display, window, ShapeBounding, 0, 0, &full_rect, 1, ShapeSet, Unsorted ); + XShapeCombineRectangles( data_ptr->display, window, ShapeInput, 0, 0, &full_rect, 1, ShapeSet, Unsorted ); + } + /* Hole Punching (Custom Margins), calculates the region that should remain opaque */ + else + { + opaque_rect.x = margins->cxLeftWidth; + opaque_rect.y = margins->cyTopHeight; + opaque_rect.width = width - (margins->cxLeftWidth + margins->cxRightWidth); + opaque_rect.height = height - (margins->cyTopHeight + margins->cyBottomHeight); + + if (opaque_rect.width <= 0 || opaque_rect.height <= 0) + { + XShapeCombineMask( data_ptr->display, window, ShapeBounding, 0, 0, None, ShapeSet ); + XShapeCombineMask( data_ptr->display, window, ShapeInput, 0, 0, None, ShapeSet ); + } + else + { + XShapeCombineRectangles( data_ptr->display, window, ShapeBounding, 0, 0, &opaque_rect, 1, ShapeSet, Unsorted ); + XShapeCombineRectangles( data_ptr->display, window, ShapeInput, 0, 0, &opaque_rect, 1, ShapeSet, Unsorted ); + } + } +#else + WARN("XShape support not compiled in; DWM margins ignored.\n"); +#endif + + if (X11DRV_check_error()) + ERR("XShape error while applying DWM margins.\n"); + + release_win_data( data_ptr ); + return TRUE; +} + + /*********************************************************************** * UpdateLayeredWindow (X11DRV.@) */ diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 9f38ceba0df..3266ec305f8 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -235,8 +235,8 @@ extern void X11DRV_ReleaseDC( HWND hwnd, HDC hdc ); extern BOOL X11DRV_ScrollDC( HDC hdc, INT dx, INT dy, HRGN update ); extern void X11DRV_SetCapture( HWND hwnd, UINT flags ); extern void X11DRV_SetDesktopWindow( HWND hwnd ); -extern void X11DRV_SetLayeredWindowAttributes( HWND hwnd, COLORREF key, BYTE alpha, - DWORD flags ); +extern void X11DRV_SetLayeredWindowAttributes( HWND hwnd, COLORREF key, BYTE alpha, DWORD flags ); +extern BOOL X11DRV_SetWindowDwmConfig( HWND hwnd, INT command, const void *data ); extern void X11DRV_SetParent( HWND hwnd, HWND parent, HWND old_parent ); extern void X11DRV_SetWindowIcons( HWND hwnd, HICON icon, const ICONINFO *ii, HICON icon_small, const ICONINFO *ii_small ); extern void X11DRV_SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL redraw ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10180