From: "Gabriel Ivăncescu" Subject: [PATCH] wined3d: Restore the Topmost state upon exiting fullscreen, when used from DXGI. Message-Id: <0b102a1e6d5ca149bb8fc6027e603012b50af411.1593693120.git.gabrielopcode@gmail.com> Date: Thu, 2 Jul 2020 15:41:55 +0300 DXGI, unlike D3D9 and below, restores the topmost state when exiting fullscreen. Unreal Engine 4 games (e.g. Deep Rock Galactic) depend on this because they don't unset it manually, so the window remains topmost on Wine. Signed-off-by: Gabriel Ivăncescu --- In fact, we already have tests for this in DXGI, but they've been marked todo_wine, which this patch fixes. dlls/dxgi/swapchain.c | 2 ++ dlls/dxgi/tests/dxgi.c | 2 -- dlls/wined3d/swapchain.c | 8 +++++++- include/wine/wined3d.h | 1 + 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/dlls/dxgi/swapchain.c b/dlls/dxgi/swapchain.c index f37aee9..2895e0e 100644 --- a/dlls/dxgi/swapchain.c +++ b/dlls/dxgi/swapchain.c @@ -416,6 +416,7 @@ static HRESULT STDMETHODCALLTYPE DECLSPEC_HOTPATCH d3d11_swapchain_SetFullscreen wined3d_swapchain_get_desc(swapchain->wined3d_swapchain, &swapchain_desc); swapchain_desc.output = dxgi_output->wined3d_output; swapchain_desc.windowed = !fullscreen; + swapchain_desc.flags |= WINED3D_SWAPCHAIN_TOPMOST_RESTORE; hr = wined3d_swapchain_state_set_fullscreen(state, &swapchain_desc, NULL); wined3d_mutex_unlock(); if (FAILED(hr)) @@ -2243,6 +2244,7 @@ static HRESULT STDMETHODCALLTYPE DECLSPEC_HOTPATCH d3d12_swapchain_SetFullscreen goto fail; wined3d_mutex_lock(); wined3d_desc.windowed = !fullscreen; + wined3d_desc.flags |= WINED3D_SWAPCHAIN_TOPMOST_RESTORE; hr = wined3d_swapchain_state_set_fullscreen(swapchain->state, &wined3d_desc, NULL); wined3d_mutex_unlock(); if (FAILED(hr)) diff --git a/dlls/dxgi/tests/dxgi.c b/dlls/dxgi/tests/dxgi.c index 8f52e1d..8d243e2 100644 --- a/dlls/dxgi/tests/dxgi.c +++ b/dlls/dxgi/tests/dxgi.c @@ -5859,7 +5859,6 @@ static void test_swapchain_window_styles(void) todo_wine_if(!(tests[i].expected_style & WS_VISIBLE)) ok(style == tests[i].expected_style, "Test %u: Got style %#x, expected %#x.\n", i, style, tests[i].expected_style); - todo_wine_if(!(tests[i].expected_exstyle & WS_EX_TOPMOST)) ok(exstyle == tests[i].expected_exstyle, "Test %u: Got exstyle %#x, expected %#x.\n", i, exstyle, tests[i].expected_exstyle); @@ -5871,7 +5870,6 @@ static void test_swapchain_window_styles(void) todo_wine_if(!(tests[i].expected_style & WS_VISIBLE)) ok(style == tests[i].expected_style, "Test %u: Got style %#x, expected %#x.\n", i, style, tests[i].expected_style); - todo_wine_if(!(tests[i].expected_exstyle & WS_EX_TOPMOST)) ok(exstyle == tests[i].expected_exstyle, "Test %u: Got exstyle %#x, expected %#x.\n", i, exstyle, tests[i].expected_exstyle); diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c index e9d6272..84aba06 100644 --- a/dlls/wined3d/swapchain.c +++ b/dlls/wined3d/swapchain.c @@ -2114,6 +2114,10 @@ void wined3d_swapchain_state_restore_from_fullscreen(struct wined3d_swapchain_st if (!state->style && !state->exstyle) return; + /* DXGI restores WS_EX_TOPMOST, unlike Direct3D 9 and below */ + if ((state->desc.flags & WINED3D_SWAPCHAIN_TOPMOST_RESTORE) && !(state->exstyle & WS_EX_TOPMOST)) + window_pos_flags &= ~SWP_NOZORDER; + style = GetWindowLongW(window, GWL_STYLE); exstyle = GetWindowLongW(window, GWL_EXSTYLE); @@ -2145,7 +2149,7 @@ void wined3d_swapchain_state_restore_from_fullscreen(struct wined3d_swapchain_st rect = *window_rect; else window_pos_flags |= (SWP_NOMOVE | SWP_NOSIZE); - SetWindowPos(window, 0, rect.left, rect.top, + SetWindowPos(window, HWND_NOTOPMOST, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, window_pos_flags); wined3d_filter_messages(window, filter); @@ -2243,6 +2247,8 @@ HRESULT CDECL wined3d_swapchain_state_set_fullscreen(struct wined3d_swapchain_st RECT *window_rect = NULL; if (state->desc.flags & WINED3D_SWAPCHAIN_RESTORE_WINDOW_RECT) window_rect = &state->original_window_rect; + if (swapchain_desc->flags & WINED3D_SWAPCHAIN_TOPMOST_RESTORE) + state->desc.flags |= WINED3D_SWAPCHAIN_TOPMOST_RESTORE; wined3d_swapchain_state_restore_from_fullscreen(state, state->device_window, window_rect); } diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index 346d1d0..cee46d3 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -905,6 +905,7 @@ enum wined3d_shader_type #define WINED3D_SWAPCHAIN_GDI_COMPATIBLE 0x00008000u #define WINED3D_SWAPCHAIN_IMPLICIT 0x00010000u #define WINED3D_SWAPCHAIN_HOOK 0x00020000u +#define WINED3D_SWAPCHAIN_TOPMOST_RESTORE 0x00040000u #define WINED3DDP_MAXTEXCOORD 8 -- 2.21.0