ddraw: Restore WS_EX_TOPMOST in exclusive fullscreen mode if it got removed.
Tests show that there is a ~1.5s timer that checks for the presence of WS_EX_TOPMOST and restore it if it got removed when the timer times out. Manual tests that skip WM_TIMER handling show there is a 1.5s timer of ID 0x4242 keeps firing. The timer stops when its WM_TIMER message gets handled. Fix Deus Ex: Game of the Year Edition missing WS_EX_TOPMOST after changing resolutions in fullscreen mode. The application removes WS_EX_TOPMOST from its game window after entering fullscreen.
This commit is contained in:
parent
a87c1d251e
commit
9092a4ccca
8 changed files with 37 additions and 5 deletions
|
@ -587,7 +587,7 @@ static HRESULT ddraw_attach_d3d_device(struct ddraw *ddraw, HWND window,
|
|||
swapchain_desc.swap_effect = WINED3D_SWAP_EFFECT_DISCARD;
|
||||
swapchain_desc.device_window = window;
|
||||
swapchain_desc.windowed = !(cooplevel & DDSCL_FULLSCREEN);
|
||||
swapchain_desc.flags = WINED3D_SWAPCHAIN_ALLOW_MODE_SWITCH | WINED3D_SWAPCHAIN_IMPLICIT;
|
||||
swapchain_desc.flags = DDRAW_WINED3D_SWAPCHAIN_FLAGS;
|
||||
|
||||
if ((cooplevel & DDSCL_NOWINDOWCHANGES) || window != GetForegroundWindow())
|
||||
swapchain_desc.flags |= WINED3D_SWAPCHAIN_NO_WINDOW_CHANGES;
|
||||
|
|
|
@ -64,6 +64,9 @@ struct FvfToDecl
|
|||
| WINED3D_FOCUS_MESSAGES | WINED3D_PIXEL_CENTER_INTEGER | WINED3D_LEGACY_UNBOUND_RESOURCE_COLOR \
|
||||
| WINED3D_NO_PRIMITIVE_RESTART | WINED3D_LEGACY_CUBEMAP_FILTERING | WINED3D_NO_DRAW_INDIRECT)
|
||||
|
||||
#define DDRAW_WINED3D_SWAPCHAIN_FLAGS (WINED3D_SWAPCHAIN_ALLOW_MODE_SWITCH \
|
||||
| WINED3D_SWAPCHAIN_IMPLICIT | WINED3D_SWAPCHAIN_REGISTER_TOPMOST_TIMER)
|
||||
|
||||
#define DDRAW_MAX_ACTIVE_LIGHTS 32
|
||||
#define DDRAW_MAX_TEXTURES 8
|
||||
|
||||
|
|
|
@ -2807,7 +2807,7 @@ static void test_window_style(void)
|
|||
tmp = GetWindowLongA(window, GWL_STYLE);
|
||||
ok(!(tmp & WS_VISIBLE), "Got unexpected WS_VISIBLE.\n");
|
||||
tmp = GetWindowLongA(window, GWL_EXSTYLE);
|
||||
todo_wine ok(tmp & WS_EX_TOPMOST, "Expected WS_EX_TOPMOST.\n");
|
||||
ok(tmp & WS_EX_TOPMOST, "Expected WS_EX_TOPMOST.\n");
|
||||
|
||||
ref = IDirectDraw_Release(ddraw);
|
||||
ok(!ref, "Unexpected refcount %lu.\n", ref);
|
||||
|
|
|
@ -2893,7 +2893,7 @@ static void test_window_style(void)
|
|||
tmp = GetWindowLongA(window, GWL_STYLE);
|
||||
ok(!(tmp & WS_VISIBLE), "Got unexpected WS_VISIBLE.\n");
|
||||
tmp = GetWindowLongA(window, GWL_EXSTYLE);
|
||||
todo_wine ok(tmp & WS_EX_TOPMOST, "Expected WS_EX_TOPMOST.\n");
|
||||
ok(tmp & WS_EX_TOPMOST, "Expected WS_EX_TOPMOST.\n");
|
||||
|
||||
ref = IDirectDraw2_Release(ddraw);
|
||||
ok(!ref, "Unexpected refcount %lu.\n", ref);
|
||||
|
|
|
@ -3131,7 +3131,7 @@ static void test_window_style(void)
|
|||
tmp = GetWindowLongA(window, GWL_STYLE);
|
||||
ok(!(tmp & WS_VISIBLE), "Got unexpected WS_VISIBLE.\n");
|
||||
tmp = GetWindowLongA(window, GWL_EXSTYLE);
|
||||
todo_wine ok(tmp & WS_EX_TOPMOST, "Expected WS_EX_TOPMOST.\n");
|
||||
ok(tmp & WS_EX_TOPMOST, "Expected WS_EX_TOPMOST.\n");
|
||||
|
||||
ref = IDirectDraw4_Release(ddraw);
|
||||
ok(!ref, "Unexpected refcount %lu.\n", ref);
|
||||
|
|
|
@ -2850,7 +2850,7 @@ static void test_window_style(void)
|
|||
tmp = GetWindowLongA(window, GWL_STYLE);
|
||||
ok(!(tmp & WS_VISIBLE), "Got unexpected WS_VISIBLE.\n");
|
||||
tmp = GetWindowLongA(window, GWL_EXSTYLE);
|
||||
todo_wine ok(tmp & WS_EX_TOPMOST, "Expected WS_EX_TOPMOST.\n");
|
||||
ok(tmp & WS_EX_TOPMOST, "Expected WS_EX_TOPMOST.\n");
|
||||
|
||||
ref = IDirectDraw7_Release(ddraw);
|
||||
ok(!ref, "Unexpected refcount %lu.\n", ref);
|
||||
|
|
|
@ -2151,8 +2151,20 @@ struct wined3d_window_state
|
|||
int x, y, width, height;
|
||||
uint32_t flags;
|
||||
bool set_style;
|
||||
bool register_topmost_timer;
|
||||
bool set_topmost_timer;
|
||||
};
|
||||
|
||||
#define WINED3D_WINDOW_TOPMOST_TIMER_ID 0x4242
|
||||
|
||||
static void CALLBACK topmost_timer_proc(HWND hwnd, UINT msg, UINT_PTR id, DWORD time)
|
||||
{
|
||||
if (!(GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST))
|
||||
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
|
||||
|
||||
KillTimer(hwnd, WINED3D_WINDOW_TOPMOST_TIMER_ID);
|
||||
}
|
||||
|
||||
static DWORD WINAPI set_window_state_thread(void *ctx)
|
||||
{
|
||||
struct wined3d_window_state *s = ctx;
|
||||
|
@ -2176,6 +2188,7 @@ static DWORD WINAPI set_window_state_thread(void *ctx)
|
|||
|
||||
static void set_window_state(struct wined3d_window_state *s)
|
||||
{
|
||||
static const UINT timeout = 1500;
|
||||
DWORD window_tid = GetWindowThreadProcessId(s->window, NULL);
|
||||
DWORD tid = GetCurrentThreadId();
|
||||
HANDLE thread;
|
||||
|
@ -2187,6 +2200,17 @@ static void set_window_state(struct wined3d_window_state *s)
|
|||
if (window_tid == tid)
|
||||
{
|
||||
set_window_state_thread(s);
|
||||
|
||||
/* Deus Ex: Game of the Year Edition removes WS_EX_TOPMOST after changing resolutions in
|
||||
* exclusive fullscreen mode. Tests show that WS_EX_TOPMOST will be restored when a ~1.5s
|
||||
* timer times out */
|
||||
if (s->register_topmost_timer)
|
||||
{
|
||||
if (s->set_topmost_timer)
|
||||
SetTimer(s->window, WINED3D_WINDOW_TOPMOST_TIMER_ID, timeout, topmost_timer_proc);
|
||||
else
|
||||
KillTimer(s->window, WINED3D_WINDOW_TOPMOST_TIMER_ID);
|
||||
}
|
||||
}
|
||||
else if ((thread = CreateThread(NULL, 0, set_window_state_thread, s, 0, NULL)))
|
||||
{
|
||||
|
@ -2239,6 +2263,8 @@ HRESULT wined3d_swapchain_state_setup_fullscreen(struct wined3d_swapchain_state
|
|||
s->style = fullscreen_style(state->style);
|
||||
s->exstyle = fullscreen_exstyle(state->exstyle);
|
||||
s->set_style = true;
|
||||
s->register_topmost_timer = !!(state->desc.flags & WINED3D_SWAPCHAIN_REGISTER_TOPMOST_TIMER);
|
||||
s->set_topmost_timer = true;
|
||||
|
||||
TRACE("Old style was %08lx, %08lx, setting to %08lx, %08lx.\n",
|
||||
state->style, state->exstyle, s->style, s->exstyle);
|
||||
|
@ -2293,6 +2319,8 @@ void wined3d_swapchain_state_restore_from_fullscreen(struct wined3d_swapchain_st
|
|||
* when switching between windowed and fullscreen modes (HL2), some
|
||||
* depend on the original style (Eve Online). */
|
||||
s->set_style = style == fullscreen_style(state->style) && exstyle == fullscreen_exstyle(state->exstyle);
|
||||
s->register_topmost_timer = !!(state->desc.flags & WINED3D_SWAPCHAIN_REGISTER_TOPMOST_TIMER);
|
||||
s->set_topmost_timer = false;
|
||||
|
||||
if (window_rect)
|
||||
{
|
||||
|
|
|
@ -902,6 +902,7 @@ enum wined3d_memory_segment_group
|
|||
#define WINED3D_SWAPCHAIN_REGISTER_STATE 0x00020000u
|
||||
#define WINED3D_SWAPCHAIN_NO_WINDOW_CHANGES 0x00040000u
|
||||
#define WINED3D_SWAPCHAIN_RESTORE_WINDOW_STATE 0x00080000u
|
||||
#define WINED3D_SWAPCHAIN_REGISTER_TOPMOST_TIMER 0x00100000u
|
||||
|
||||
#define WINED3DDP_MAXTEXCOORD 8
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue