[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