From 3fc96a5d3586c756bda50fe6caa023cb44e0300c Mon Sep 17 00:00:00 2001 From: Conor McCarthy Date: Mon, 29 Jul 2019 16:00:54 +0430 Subject: [PATCH] wined3d: Track windows styles per-swapchain. Instead of per-device. Signed-off-by: Henri Verbeet Signed-off-by: Alexandre Julliard --- dlls/wined3d/device.c | 134 +++------------------------------ dlls/wined3d/swapchain.c | 122 ++++++++++++++++++++++++++++-- dlls/wined3d/wined3d_private.h | 21 ++++-- 3 files changed, 141 insertions(+), 136 deletions(-) diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 71242bba111..8502b967905 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -910,115 +910,6 @@ static void destroy_default_samplers(struct wined3d_device *device, struct wined device->null_sampler = NULL; } -static LONG fullscreen_style(LONG style) -{ - /* Make sure the window is managed, otherwise we won't get keyboard input. */ - style |= WS_POPUP | WS_SYSMENU; - style &= ~(WS_CAPTION | WS_THICKFRAME); - - return style; -} - -static LONG fullscreen_exstyle(LONG exstyle) -{ - /* Filter out window decorations. */ - exstyle &= ~(WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE); - - return exstyle; -} - -HRESULT wined3d_device_setup_fullscreen_window(struct wined3d_device *device, - HWND window, unsigned int w, unsigned int h) -{ - LONG style, exstyle; - BOOL filter; - - TRACE("Setting up window %p for fullscreen mode.\n", window); - - if (!IsWindow(window)) - { - WARN("%p is not a valid window.\n", window); - return WINED3DERR_NOTAVAILABLE; - } - - if (device->style || device->exStyle) - { - ERR("Changing the window style for window %p, but another style (%08x, %08x) is already stored.\n", - window, device->style, device->exStyle); - } - - device->style = GetWindowLongW(window, GWL_STYLE); - device->exStyle = GetWindowLongW(window, GWL_EXSTYLE); - - style = fullscreen_style(device->style); - exstyle = fullscreen_exstyle(device->exStyle); - - TRACE("Old style was %08x, %08x, setting to %08x, %08x.\n", - device->style, device->exStyle, style, exstyle); - - filter = wined3d_filter_messages(window, TRUE); - - SetWindowLongW(window, GWL_STYLE, style); - SetWindowLongW(window, GWL_EXSTYLE, exstyle); - SetWindowPos(window, HWND_TOPMOST, 0, 0, w, h, SWP_FRAMECHANGED | SWP_SHOWWINDOW | SWP_NOACTIVATE); - - wined3d_filter_messages(window, filter); - - return WINED3D_OK; -} - -void wined3d_device_restore_fullscreen_window(struct wined3d_device *device, - HWND window, const RECT *window_rect) -{ - unsigned int window_pos_flags = SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOACTIVATE; - LONG style, exstyle; - RECT rect = {0}; - BOOL filter; - - if (!device->style && !device->exStyle) - return; - - style = GetWindowLongW(window, GWL_STYLE); - exstyle = GetWindowLongW(window, GWL_EXSTYLE); - - /* These flags are set by wined3d_device_setup_fullscreen_window, not the - * application, and we want to ignore them in the test below, since it's - * not the application's fault that they changed. Additionally, we want to - * preserve the current status of these flags (i.e. don't restore them) to - * more closely emulate the behavior of Direct3D, which leaves these flags - * alone when returning to windowed mode. */ - device->style ^= (device->style ^ style) & WS_VISIBLE; - device->exStyle ^= (device->exStyle ^ exstyle) & WS_EX_TOPMOST; - - TRACE("Restoring window style of window %p to %08x, %08x.\n", - window, device->style, device->exStyle); - - filter = wined3d_filter_messages(window, TRUE); - - /* Only restore the style if the application didn't modify it during the - * fullscreen phase. Some applications change it before calling Reset() - * when switching between windowed and fullscreen modes (HL2), some - * depend on the original style (Eve Online). */ - if (style == fullscreen_style(device->style) && exstyle == fullscreen_exstyle(device->exStyle)) - { - SetWindowLongW(window, GWL_STYLE, device->style); - SetWindowLongW(window, GWL_EXSTYLE, device->exStyle); - } - - if (window_rect) - rect = *window_rect; - else - window_pos_flags |= (SWP_NOMOVE | SWP_NOSIZE); - SetWindowPos(window, 0, rect.left, rect.top, - rect.right - rect.left, rect.bottom - rect.top, window_pos_flags); - - wined3d_filter_messages(window, filter); - - /* Delete the old values. */ - device->style = 0; - device->exStyle = 0; -} - HRESULT CDECL wined3d_device_acquire_focus_window(struct wined3d_device *device, HWND window) { TRACE("device %p, window %p.\n", device, window); @@ -5543,19 +5434,18 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device, } else if (!swapchain_desc->windowed) { - DWORD style = device->style; - DWORD exStyle = device->exStyle; - /* If we're in fullscreen, and the mode wasn't changed, we have to get the window back into - * the right position. Some applications(Battlefield 2, Guild Wars) move it and then call - * Reset to clear up their mess. Guild Wars also loses the device during that. - */ - device->style = 0; - device->exStyle = 0; - wined3d_device_setup_fullscreen_window(device, swapchain->device_window, - swapchain_desc->backbuffer_width, - swapchain_desc->backbuffer_height); - device->style = style; - device->exStyle = exStyle; + DWORD style = swapchain->state.style; + DWORD exstyle = swapchain->state.exstyle; + /* If we're in fullscreen, and the mode wasn't changed, we have to get + * the window back into the right position. Some applications + * (Battlefield 2, Guild Wars) move it and then call Reset() to clean + * up their mess. Guild Wars also loses the device during that. */ + swapchain->state.style = 0; + swapchain->state.exstyle = 0; + wined3d_swapchain_state_setup_fullscreen(&swapchain->state, swapchain->device_window, + swapchain_desc->backbuffer_width, swapchain_desc->backbuffer_height); + swapchain->state.style = style; + swapchain->state.exstyle = exstyle; } if (FAILED(hr = wined3d_swapchain_resize_buffers(swapchain, swapchain_desc->backbuffer_count, diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c index d08ddf0d81a..665c49a2fd6 100644 --- a/dlls/wined3d/swapchain.c +++ b/dlls/wined3d/swapchain.c @@ -85,14 +85,14 @@ static void swapchain_cleanup(struct wined3d_swapchain *swapchain) if (swapchain->desc.flags & WINED3D_SWAPCHAIN_RESTORE_WINDOW_RECT) { - wined3d_device_restore_fullscreen_window(swapchain->device, swapchain->device_window, - &swapchain->original_window_rect); + wined3d_window_state_restore_from_fullscreen(&swapchain->state, + swapchain->device_window, &swapchain->original_window_rect); wined3d_device_release_focus_window(swapchain->device); } } else { - wined3d_device_restore_fullscreen_window(swapchain->device, swapchain->device_window, NULL); + wined3d_window_state_restore_from_fullscreen(&swapchain->state, swapchain->device_window, NULL); } } @@ -811,7 +811,8 @@ static HRESULT swapchain_init(struct wined3d_swapchain *swapchain, struct wined3 } else { - wined3d_device_setup_fullscreen_window(device, window, desc->backbuffer_width, desc->backbuffer_height); + wined3d_swapchain_state_setup_fullscreen(&swapchain->state, + window, desc->backbuffer_width, desc->backbuffer_height); } swapchain->desc = *desc; wined3d_swapchain_apply_sample_count_override(swapchain, swapchain->desc.backbuffer_format, @@ -1390,6 +1391,115 @@ HRESULT CDECL wined3d_swapchain_resize_target(struct wined3d_swapchain *swapchai return WINED3D_OK; } +static LONG fullscreen_style(LONG style) +{ + /* Make sure the window is managed, otherwise we won't get keyboard input. */ + style |= WS_POPUP | WS_SYSMENU; + style &= ~(WS_CAPTION | WS_THICKFRAME); + + return style; +} + +static LONG fullscreen_exstyle(LONG exstyle) +{ + /* Filter out window decorations. */ + exstyle &= ~(WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE); + + return exstyle; +} + +HRESULT wined3d_swapchain_state_setup_fullscreen(struct wined3d_swapchain_state *state, + HWND window, unsigned int w, unsigned int h) +{ + LONG style, exstyle; + BOOL filter; + + TRACE("Setting up window %p for fullscreen mode.\n", window); + + if (!IsWindow(window)) + { + WARN("%p is not a valid window.\n", window); + return WINED3DERR_NOTAVAILABLE; + } + + if (state->style || state->exstyle) + { + ERR("Changing the window style for window %p, but another style (%08x, %08x) is already stored.\n", + window, state->style, state->exstyle); + } + + state->style = GetWindowLongW(window, GWL_STYLE); + state->exstyle = GetWindowLongW(window, GWL_EXSTYLE); + + style = fullscreen_style(state->style); + exstyle = fullscreen_exstyle(state->exstyle); + + TRACE("Old style was %08x, %08x, setting to %08x, %08x.\n", + state->style, state->exstyle, style, exstyle); + + filter = wined3d_filter_messages(window, TRUE); + + SetWindowLongW(window, GWL_STYLE, style); + SetWindowLongW(window, GWL_EXSTYLE, exstyle); + SetWindowPos(window, HWND_TOPMOST, 0, 0, w, h, SWP_FRAMECHANGED | SWP_SHOWWINDOW | SWP_NOACTIVATE); + + wined3d_filter_messages(window, filter); + + return WINED3D_OK; +} + +void wined3d_window_state_restore_from_fullscreen(struct wined3d_swapchain_state *state, + HWND window, const RECT *window_rect) +{ + unsigned int window_pos_flags = SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOACTIVATE; + LONG style, exstyle; + RECT rect = {0}; + BOOL filter; + + if (!state->style && !state->exstyle) + return; + + style = GetWindowLongW(window, GWL_STYLE); + exstyle = GetWindowLongW(window, GWL_EXSTYLE); + + /* These flags are set by wined3d_device_setup_fullscreen_window, not the + * application, and we want to ignore them in the test below, since it's + * not the application's fault that they changed. Additionally, we want to + * preserve the current status of these flags (i.e. don't restore them) to + * more closely emulate the behavior of Direct3D, which leaves these flags + * alone when returning to windowed mode. */ + state->style ^= (state->style ^ style) & WS_VISIBLE; + state->exstyle ^= (state->exstyle ^ exstyle) & WS_EX_TOPMOST; + + TRACE("Restoring window style of window %p to %08x, %08x.\n", + window, state->style, state->exstyle); + + filter = wined3d_filter_messages(window, TRUE); + + /* Only restore the style if the application didn't modify it during the + * fullscreen phase. Some applications change it before calling Reset() + * when switching between windowed and fullscreen modes (HL2), some + * depend on the original style (Eve Online). */ + if (style == fullscreen_style(state->style) && exstyle == fullscreen_exstyle(state->exstyle)) + { + SetWindowLongW(window, GWL_STYLE, state->style); + SetWindowLongW(window, GWL_EXSTYLE, state->exstyle); + } + + if (window_rect) + rect = *window_rect; + else + window_pos_flags |= (SWP_NOMOVE | SWP_NOSIZE); + SetWindowPos(window, 0, rect.left, rect.top, + rect.right - rect.left, rect.bottom - rect.top, window_pos_flags); + + wined3d_filter_messages(window, filter); + + /* Delete the old values. */ + state->style = 0; + state->exstyle = 0; +} + HRESULT CDECL wined3d_swapchain_set_fullscreen(struct wined3d_swapchain *swapchain, const struct wined3d_swapchain_desc *swapchain_desc, const struct wined3d_display_mode *mode) { @@ -1446,7 +1556,7 @@ HRESULT CDECL wined3d_swapchain_set_fullscreen(struct wined3d_swapchain *swapcha if (swapchain->desc.windowed) { /* Switch from windowed to fullscreen */ - if (FAILED(hr = wined3d_device_setup_fullscreen_window(device, + if (FAILED(hr = wined3d_swapchain_state_setup_fullscreen(&swapchain->state, swapchain->device_window, width, height))) return hr; } @@ -1469,7 +1579,7 @@ HRESULT CDECL wined3d_swapchain_set_fullscreen(struct wined3d_swapchain *swapcha RECT *window_rect = NULL; if (swapchain->desc.flags & WINED3D_SWAPCHAIN_RESTORE_WINDOW_RECT) window_rect = &swapchain->original_window_rect; - wined3d_device_restore_fullscreen_window(device, swapchain->device_window, window_rect); + wined3d_window_state_restore_from_fullscreen(&swapchain->state, swapchain->device_window, window_rect); } swapchain->desc.windowed = swapchain_desc->windowed; diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index d62774cc659..daf25076d84 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -3167,10 +3167,6 @@ struct wined3d_device struct wined3d *wined3d; struct wined3d_adapter *adapter; - /* Window styles to restore when switching fullscreen mode */ - LONG style; - LONG exStyle; - const struct wined3d_shader_backend_ops *shader_backend; void *shader_priv; void *fragment_priv; @@ -3255,12 +3251,8 @@ LRESULT device_process_message(struct wined3d_device *device, HWND window, BOOL void device_resource_add(struct wined3d_device *device, struct wined3d_resource *resource) DECLSPEC_HIDDEN; void device_resource_released(struct wined3d_device *device, struct wined3d_resource *resource) DECLSPEC_HIDDEN; void device_invalidate_state(const struct wined3d_device *device, DWORD state) DECLSPEC_HIDDEN; -void wined3d_device_restore_fullscreen_window(struct wined3d_device *device, - HWND window, const RECT *window_rect) DECLSPEC_HIDDEN; HRESULT wined3d_device_set_implicit_swapchain(struct wined3d_device *device, struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN; -HRESULT wined3d_device_setup_fullscreen_window(struct wined3d_device *device, - HWND window, unsigned int w, unsigned int h) DECLSPEC_HIDDEN; void wined3d_device_uninit_3d(struct wined3d_device *device) DECLSPEC_HIDDEN; struct wined3d_device_no3d @@ -4182,6 +4174,18 @@ static inline struct wined3d_unordered_access_view_gl *wined3d_unordered_access_ return CONTAINING_RECORD(view, struct wined3d_unordered_access_view_gl, v); } +struct wined3d_swapchain_state +{ + /* Window styles to restore when switching fullscreen mode. */ + LONG style; + LONG exstyle; +}; + +void wined3d_window_state_restore_from_fullscreen(struct wined3d_swapchain_state *state, + HWND window, const RECT *window_rect) DECLSPEC_HIDDEN; +HRESULT wined3d_swapchain_state_setup_fullscreen(struct wined3d_swapchain_state *state, + HWND window, unsigned int w, unsigned int h) DECLSPEC_HIDDEN; + struct wined3d_swapchain_ops { void (*swapchain_present)(struct wined3d_swapchain *swapchain, @@ -4215,6 +4219,7 @@ struct wined3d_swapchain struct wined3d_context **context; unsigned int num_contexts; + struct wined3d_swapchain_state state; HWND win_handle; HWND device_window;