Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=57665
---
The issue is that The Medium launcher uses a dialog window procedure, and implements its background by doing a StretchBlt call on WM_PAINT in the dialog procedure call, which happens before the window message loop.
It then itself calls InvalidateRect(hwnd, NULL, 0), which queues a WM_PAINT as well but with only the RDW_INVALIDATE flag.
Next, when the window message loop is executed, the WM_PAINT message is being processed as it should, but as we've invalidate the window with RDW_ERASE ourselves from the expose event, the WM_NCPAINT handler erases the entire window, clearing the pixels that the launcher has just painted.
This regressed since the window surface clipping region logic changed, as the expose event handling was previously not calling `NtUserRedrawWindow` on windows with a surface and without a clipping region. The clipping region was also previously not always set, or set later, and we're setting it more consistently since 51b16963f6e0e8df43118deac63f640aee4698b7, even when it matches the window rect, for compatibility with some old wineandroid logic (where I believe it was used to clip window surfaces to their proper sizes).
-- v2: winex11: Only erase the desktop window pixels on expose events.
From: Rémi Bernon rbernon@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=57665 --- dlls/winex11.drv/event.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 428dcb7b8b7..e5617d3ac11 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -968,7 +968,7 @@ static BOOL X11DRV_Expose( HWND hwnd, XEvent *xev ) RECT rect, abs_rect; POINT pos; struct x11drv_win_data *data; - UINT flags = RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN; + UINT flags = RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN;
TRACE( "win %p (%lx) %d,%d %dx%d\n", hwnd, event->window, event->x, event->y, event->width, event->height ); @@ -1008,6 +1008,7 @@ static BOOL X11DRV_Expose( HWND hwnd, XEvent *xev )
release_win_data( data );
+ if (hwnd == NtUserGetDesktopWindow()) flags |= RDW_ERASE; NtUserExposeWindowSurface( hwnd, flags, &rect, NtUserGetWinMonitorDpi( hwnd, MDT_RAW_DPI ) ); return TRUE; }
v2: Only use RDW_ERASE for the desktop window. I'm not completely sure that the flag isn't necessary, but I think invalidating the window contents should be enough for other windows?