http://bugs.winehq.org/show_bug.cgi?id=58210
Bug ID: 58210 Summary: Alpha Protocol (Steam) launcher has grey overlay over buttons Product: Wine Version: unspecified Hardware: x86-64 URL: https://store.steampowered.com/app/34010/Alpha_Protoco l/ OS: Linux Status: NEW Keywords: regression Severity: minor Priority: P2 Component: win32u Assignee: wine-bugs@winehq.org Reporter: gyebro69@gmail.com CC: pgofman@codeweavers.com Regression SHA1: 3437ba2dea115381217e64fdad6c8496cb8052f8 Distribution: ArchLinux
This commit reintroduces bug #38975 for me: the buttons in the launcher are covered with a grey rectangle until you hover the mouse pointer over them (when the buttons are "uncovered").
commit 3437ba2dea115381217e64fdad6c8496cb8052f8 win32u: Don't redraw window in expose_window_surface() if window has surface.
Happens either in fullscreen or virtual desktop mode.
X.Org X Server 1.21.1.16 XFCE/XFWM 4.20 Nvidia binary drivers 575.51.02
http://bugs.winehq.org/show_bug.cgi?id=58210
Paul Gofman gofmanp@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |gofmanp@gmail.com
--- Comment #1 from Paul Gofman gofmanp@gmail.com --- Created attachment 78521 --> http://bugs.winehq.org/attachment.cgi?id=78521 PoC patch
The controls in question are comctl32 buttons (painted by the launcher itself though through WM_DRAWITEM). The main window is not a dialog but just normal "WS_POPUP WS_VISIBLE WS_CLIPSIBLINGS WS_CLIPCHILDREN" window, the buttons are created by the launcher itself. It initially creates those with "WS_CHILD WS_VISIBLE WS_CLIPSIBLINGS WS_TABSTOP 0000000b" and size of 100x100. Then, right after creation, without processing messages / getting WM_PAINT, it does:
InvalidateRect( button, NULL, FALSE); SetWindowPos(button, NULL, -1,-1, (329x46), SWP_NOMOVE | SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE);
Then it processes messages and gets WM_PAINT for control (sent as WM_DRAWITEM to parent window by comctl32), and does all the drawing. However, update region in Wine is 100x46 (100 because it is what is left in invalidated rect on the server after InvalidateRect, 46 because that was intersected with window rect during SetWindowPos). SetWindowPos did not extend invalidated region because of SWP_NOREDRAW. So that paints only the leff 100 pixel part of the button (while the text and the rest of its background is left behind). Upon hovering mouse it will do the same InvalidateRect() again and now correctly sized button will be invalidated as full and properly painted upon WM_PAINT processing.
I did some ad-hoc testing on Windows recreating essential parts of this process and dumping BeginPaint box in WM_PAINT, and without InvalidateRect() before resize Wine behaviour matches Windows: the window is not invalidated to the bigger resized part and stays unpainted. However, with the InvalidateRect() before SetWindowPos, there are two WM_PAINT messages and the second one covers the full window.
I've attached the patch mostly for future reference, it needs more testing and maybe a proper fix is more complicated than that (e. g., I don't know so far what is supposed to happen if InvalidateRect has explicit rect specified, what if the full window invalidation with NULL rect has a special meaning here). I am going to get back to properly testing and fixing that later.
The blamed commit is not wrong, the prior changes in 10 cycle without the blamed commit only fixed Bug 38975 only by chance (and maybe that even vary across different window managers / desktop emulation mode, I didn't check). Without the commit x11 Expose event (which is received after the mentioned sequence once the launcher processes messages) does RedrawWindow() invalidating everything and so that button paint has the full button area invalidated. But that RedrawWindow on X11 expose event should not be there (and was already breaking other launchers).
http://bugs.winehq.org/show_bug.cgi?id=58210
--- Comment #2 from Paul Gofman gofmanp@gmail.com --- A bit more testing on Windows shows that the essential behaviour (extending invalidated rect on Windows) only happens when InvalidateRect() or InvalidateRgn() set NULL rect / region. If rect is specified, even covering the whole window, SetWindowPos() changing size with SWP_NOREDRAW won't extend the invalidated rect. In any case, SWP_NOREDRAW flag is present in WM_WINDOWPOSCHANGING / WM_WINDOWPOSCHANGED (unlike what happens in Wine with the PoC patch).
All this suggests that probably it is not SetWindowPos() special cased for existing invalidated region but rather NULL region (invalidating the whole window) has a bit different semantics between Windows and Wine. Wine currently translates it to full client rect at the moment of invalidating (and thus it is indistinguishable from the app specified full window rect). Instead, it should probably be explicitly flagged as a "full window invalidated" and resolve to actual coordinates only when requested. This way if resize happens in between invalidating NULL rect and obtaining DC / otherwise querying invalidated region the returned region will match the current window size.
I am yet to finalize the tests and implement that.
http://bugs.winehq.org/show_bug.cgi?id=58210
--- Comment #3 from Paul Gofman gofmanp@gmail.com --- Sent a patch upstream: https://gitlab.winehq.org/wine/wine/-/merge_requests/8013
http://bugs.winehq.org/show_bug.cgi?id=58210
--- Comment #4 from Béla Gyebrószki gyebro69@gmail.com --- (In reply to Paul Gofman from comment #3)
Sent a patch upstream: https://gitlab.winehq.org/wine/wine/-/merge_requests/8013
The patch fixes the issue in the launcher, thanks for taking your time to look into this.