[PATCH v2 2/3] wined3d: Update the swapchain windows' sizes after it has been unminimized.
Gabriel Ivăncescu
gabrielopcode at gmail.com
Fri Oct 2 09:58:27 CDT 2020
Hi Stefan,
I did more tests (and hacks) to see what Windows does. I'm not entirely
sure how to fix it honestly—so I need some tips after I detail it. I'll
first try to answer your random thoughts and then give more
details/message sequences I observed on Windows.
On 01/10/2020 23:35, Stefan Dösinger wrote:
> Hi,
>
> Henri asked me to add my thoughts here because I once wrote most of the
> focus handling code but so far I am lost. This entire thing is fragile
> on both Windows and Wine.
>
> I'm just dumping some random thoughts here. Maybe it gives you some
> idea, or some of your answers help me remember some bits:
>
> *) I am wondering why the SetWindowPos in wined3d_swapchain_activate in
> the activate=true case doesn't use SWP_SHOWWINDOW or why there's no
> ShowWindow(SW_RESTORE) call.
According to a hack test I did, Windows' d3d9 definitely doesn't restore
the window here, so I guess it's correct as far as this is concerned.
> *) When testing messages on Windows, be aware that messages that d3d9
> generates in response to WM_ACTIVATEAPP appear to be send *before*
> WM_ACTIVATEAPP because the calls that generate them happen before d3d9
> forwards the WM_ACTIVATEAPP message to the original wndproc.
>
Right, I noticed it now and that does seem to be the case. It doesn't
help the game though, because all of this happens while it's minimized.
> *) The test shows that a WM_WINDOWPOSCHANGED message arrives after the
> window has been put out of iconic state, but the exact sequence isn't
> clear. Is this message produced by d3d9 or is it e.g. triggered by the
> taskbar.
>
I think it's both. It's only one message, but it is the size of the
fullscreen (swapchain's backbuffer), *not* the size of the restored
window, and unfortunately this seems to be important…
> *) Something that may be tricky to answer: What happens if a non-taskbar
> event brings the window of HOMM 5 back into the foreground, e.g. a
> separate process calling SetForegroundWindow? I think alt-tab behaves
> very similarly to the taskbar.
>
Ok so I tested both of these. Alt-tab has the same sequence as clicking
on the taskbar (which I'll show below), while if I used a hack and
SetForegroundWindow, it doesn't ever restore the window at all. It does
receive the WM_ACTIVATEAPP of course, and the window pos messages before it.
This happens even if I "unminimize" the window by clearing the
WS_MINIMIZE style; it doesn't change anything.
> *) Is it possible that there is some WM_SYSCOMMAND specific behavior?
> d3d9 does hook this particular message.
>
Yeah, and we already hook/handle it (and my patch does, but now I know
it's wrong).
> *) On which Linux environment does the regression happen? There may be
> window manager specific behavior...
>
I don't think that matters here, and I doubt it's a problem, but I
tested it on Compiz with XFCE. Anyway, clearly our current behavior is
wrong wrt to Windows, even if the patch that caused this regression is
actually correct in that sense. It used to work by luck before.
So let me provide some details. First, the requirements: HOMM V expects
the window pos messages to arrive after it's been unminimized, and they
need to set it to the fullscreen size. In sequences below, it's
1920x1080 (window non-fullscreen size is 640x480).
WM_ACTIVATEAPP *does* send window pos messages; it worked before,
because we unminimized the window first before activating it. But that's
wrong (for other games, like Project CARS, which depend on it). For some
reason it sends with SWP_NOMOVE and SWP_NOSIZE.
Regardless, I want to touch the current code as little as possible
outside of this scenario, since there's also wined3d flags so I assume
the behavior is not the same across all versions, and I don't want to
mess those up.
So here's the sequences. First, I click on the taskbar:
WM_WINDOWPOSCHANGING, hwndInsertAfter 00000000, x 0, y 0, cx 0, cy 0,
flags SWP_NOSIZE | SWP_NOMOVE
WM_WINDOWPOSCHANGED, hwndInsertAfter 00000000, x -32000, y -32000, cx
160, cy 24, flags 00001803
WM_ACTIVATEAPP, wParam 00000001, lParam 00000718
WM_NCACTIVATE, wParam 00200001, lParam 00000000
WM_GETTEXT, wParam 000001FE, lParam 0022F130
WM_ACTIVATE, wParam 00200001, lParam 00000000
WM_SYSCOMMAND, wParam SC_RESTORE, lParam 00000000
WM_QUERYOPEN, wParam 00000000, lParam 00000000
WM_WINDOWPOSCHANGING, hwndInsertAfter 00000000, x 0, y 0, cx 1920, cy
1080, flags SWP_STATECHANGED | SWP_NOCOPYBITS | SWP_FRAMECHANGED
WM_GETMINMAXINFO, wParam 00000000, lParam 0022F624
WM_NCCALCSIZE, wParam 00000001, lParam 0022F97C
WM_NCPAINT, wParam 00000001, lParam 00000000
WM_GETTEXT, wParam 000001FE, lParam 0022EE20
WM_ERASEBKGND, wParam 01010052, lParam 00000000
WM_WINDOWPOSCHANGED, hwndInsertAfter 00000000, x 0, y 0, cx 1920, cy
1080, flags 00008124
WM_MOVE, wParam 00000000, lParam 00170004
WM_SIZE, wParam 00000000, lParam 041D0778
WM_SETFOCUS, wParam 00000000, lParam 00000000
WM_ACTIVATE, wParam 00000001, lParam 00000000
Now I sent a WM_SYSCOMMAND SC_RESTORE directly and I got:
WM_SYSCOMMAND, wParam SC_RESTORE, lParam 00000000
WM_QUERYOPEN, wParam 00000000, lParam 00000000
WM_WINDOWPOSCHANGING, hwndInsertAfter 00000000, x 0, y 0, cx 1920, cy
1080, flags SWP_STATECHANGED | SWP_NOCOPYBITS | SWP_FRAMECHANGED
WM_GETMINMAXINFO, wParam 00000000, lParam 0022F5D4
WM_NCCALCSIZE, wParam 00000001, lParam 0022F92C
WM_ACTIVATEAPP, wParam 00000001, lParam 00000000
WM_NCACTIVATE, wParam 00000001, lParam 00000000
WM_GETTEXT, wParam 000001FE, lParam 0022EDD0
WM_ACTIVATE, wParam 00000001, lParam 00000000
WM_SETFOCUS, wParam 00000000, lParam 00000000
WM_NCPAINT, wParam 00000001, lParam 00000000
WM_GETTEXT, wParam 000001FE, lParam 0022EDD0
WM_ERASEBKGND, wParam 01010054, lParam 00000000
WM_WINDOWPOSCHANGED, hwndInsertAfter 00000000, x 0, y 0, cx 1920, cy
1080, flags 00008120
WM_MOVE, wParam 00000000, lParam 00170004
WM_SIZE, wParam 00000000, lParam 041D0778
WM_ACTIVATE, wParam 00000001, lParam 00000000
Then I cleared the WS_MINIMIZE style and SetForegroundWindow:
WM_WINDOWPOSCHANGING, hwndInsertAfter 00000000, x 0, y 0, cx 0, cy 0,
flags SWP_NOSIZE | SWP_NOMOVE
WM_WINDOWPOSCHANGED, hwndInsertAfter 00000000, x -32000, y -32000, cx
160, cy 24, flags 00001803
WM_ACTIVATEAPP, wParam 00000001, lParam 000005F4
WM_NCACTIVATE, wParam 00000001, lParam 00000000
WM_GETTEXT, wParam 000001FE, lParam 0022F130
WM_ACTIVATE, wParam 00000001, lParam 00000000
WM_SETFOCUS, wParam 00000000, lParam 00000000
It's interesting to note that not clearing the WS_MINIMIZE style changed
nothing at all, except the wParam in WM_ACTIVATE which kept the
"minimized" flag (note how this flag also happens in first test, when
WM_ACTIVATE is received while it's still minimized).
Also note that WM_ACTIVATEAPP in the second case (WM_SYSCOMMAND sent
manually) doesn't generate any window pos messages at all. In fact, the
behavior prior to the patch that caused this regression works by luck as
you can see: we only sent WM_SYSCOMMAND without activating the window
first, so WM_ACTIVATEAPP's window pos message worked correctly.
———————————————
My problem now is, I don't know how to fix this. Obviously I'll have to
somehow handle this in our SC_RESTORE hook (which we already do, we just
call DefWindowProc). However, that would restore the window to its
normal restored size (640x480) and not fullscreen. My current patch
changes its position again, but that's wrong, as on Windows it's only
sent once.
Should I hook WM_WINDOWPOSCHANGING and change the position and size to
match under this scenario? (i.e. change them to 1920x1080 from 640x480
in that example above)
And my other question is: how should I detect in WM_ACTIVATEAPP that we
send it with SWP_NOMOVE | SWP_NOSIZE (so it doesn't ruin other
versions). Furthermore: WM_ACTIVATEAPP doesn't SetWindowPos again if
SYSCOMMAND is sent directly—how to best detect this? Do I use a wined3d
flag? A new field, boolean? Or is that too ugly/too much of a hack?
Checking for WS_MINIMIZE or IsIconic doesn't work properly, since
Windows completely ignores that, so that's a no-go.
Thanks,
Gabriel
More information about the wine-devel
mailing list