http://bugs.winehq.org/show_bug.cgi?id=2082
Ken Thomases ken@codeweavers.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |ken@codeweavers.com
--- Comment #125 from Ken Thomases ken@codeweavers.com --- I've been looking into this bug as it affects Worms Armageddon. That game has built-in Wine-specific tweaks to work around the problem, but they don't work with the Mac driver because the Mac driver doesn't support a virtual desktop window. For testing purposes, I'm using the X11 driver with WA's tweaks disabled.
I'm going to summarize what I have found (which has also been demonstrated by some of the test cases):
* WA creates window A. * WA creates a dialog window D, which is owned by window A. This has sometimes been described as a child window but it's not. It's a top-level window. Being owned by window A means that it is kept in front of window A. * The dialog D has various controls, including buttons, etc. * WA calls IDirectDraw::SetCooperativeLevel(window A, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN). The presence of DDSCL_FULLSCREEN should mean that it draws directly to the screen, bypassing all normal (GDI) drawing of other windows. So, even though dialog D is in front of window A, the drawing to window A should appear on screen. * Wine's ddraw calls wined3d_device_setup_fullscreen_window() to set window A up as a full-screen window. This attempts to order window A to the front of all windows by calling SetWindowPos(window A, HWND_TOPMOST, ...). However, because dialog D is owned by window A, user32 keeps D in front.
The ultimate result is that dialog D obscures window A. I haven't investigated why dialog D is all black as opposed to looking like a typical user32 dialog window with controls.
I have confirmed this with a gross hack. In dlls/user32/dialog.c:DIALOG_CreateIndirect(), I have modified the two calls to CreateWindowEx[AW]() to pass NULL for the owner. This means that dialog D is not owned by window A and window A can be moved in front of it. The result is that you can see the rendering. However, clicks on the window are ignored. That's because window A isn't prepared to respond to the clicks. The dialog D is supposed to receive those clicks.
I think that Stefan was on the right path. I think that, when ddraw/wined3d goes to set up window A for full-screen, it should not attempt to change the Win32 window. I think it needs to work with the user driver to set up a full-screen OpenGL surface that's outside of the Win32 window hierarchy. This surface would have to avoid interfering with mouse events. Those should still be delivered to whatever Win32 window is under the cursor.
It may be that targeting the desktop window is the most appropriate way for ddraw/wined3d to communicate the need to draw to the full screen to the user driver, although Stefan mentioned that that has its own problems. Given that ddraw (and d3d?) has a need to bypass the normal windowing and graphics, I think it makes sense for it to communicate directly with the user driver.