From cd14ca800e91a072123fc9eadec5751d912f0dc8 Mon Sep 17 00:00:00 2001 From: bicarus <202771338+bicarus-dev@users.noreply.github.com> Date: Thu, 22 Jan 2026 19:06:31 -0800 Subject: [PATCH] graphics: fix window resize not working properly in some games (#530) ## Link to GitHub Issue, if one exists n/a ## Description of change Need to filter out system-created windows (such as `CicMarshalWnd`) when looking up which window to mess with when user interacts with F11 menu. While I'm here, clean up the hack for gfdm arena model that remembers the main window. ## Testing Tested: DDR gfdm arena 4 / 1 window modes iidx (windowed mode, with/without nosub option) sdvx with sub windows Need to check: full screen games --- src/spice2x/hooks/graphics/graphics.cpp | 29 ++++++++++--------- src/spice2x/hooks/graphics/graphics.h | 2 +- .../hooks/graphics/graphics_windowed.cpp | 19 ++++++++---- src/spice2x/overlay/windows/screen_resize.cpp | 9 +++--- 4 files changed, 35 insertions(+), 24 deletions(-) diff --git a/src/spice2x/hooks/graphics/graphics.cpp b/src/spice2x/hooks/graphics/graphics.cpp index 8dc2b89..8b92ba3 100644 --- a/src/spice2x/hooks/graphics/graphics.cpp +++ b/src/spice2x/hooks/graphics/graphics.cpp @@ -61,7 +61,6 @@ bool GRAPHICS_SHOW_CURSOR = false; graphics_orientation GRAPHICS_ADJUST_ORIENTATION = ORIENTATION_NORMAL; bool GRAPHICS_WINDOWED = false; std::vector GRAPHICS_WINDOWS; -std::optional GRAPHICS_WINDOW_MAIN; UINT GRAPHICS_FORCE_REFRESH = 0; std::optional GRAPHICS_FORCE_REFRESH_SUB; std::optional GRAPHICS_FORCE_VSYNC_BUFFER; @@ -403,12 +402,10 @@ static HWND WINAPI CreateWindowExA_hook(DWORD dwExStyle, LPCSTR lpClassName, LPC } // gfdm - bool is_gitadora_main_window = false; if (avs::game::is_model({"J32", "J33", "K32", "K33", "L32", "L33", "M32"})) { // set window name if (!lpWindowName) { lpWindowName = "GITADORA"; - is_gitadora_main_window = true; } } @@ -451,11 +448,6 @@ static HWND WINAPI CreateWindowExA_hook(DWORD dwExStyle, LPCSTR lpClassName, LPC hWndParent, hMenu, hInstance, lpParam); GRAPHICS_WINDOWS.push_back(result); - // this is only really needed for arena model, but pre-arena model was single window anyway - if (is_gitadora_main_window) { - GRAPHICS_WINDOW_MAIN = result; - } - if (is_tdj_sub_window) { // TDJ windowed mode: remember the subscreen window handle for later TDJ_SUBSCREEN_WINDOW = result; @@ -479,7 +471,12 @@ static HWND WINAPI CreateWindowExA_hook(DWORD dwExStyle, LPCSTR lpClassName, LPC } disable_touch_indicators(result); - log_misc("graphics", "CreateWindowExA returned {}", fmt::ptr(result)); + log_misc( + "graphics", + "CreateWindowExA returned {}, {}", + fmt::ptr(result), + lpWindowName ? lpWindowName : "(null)"); + return result; } @@ -511,7 +508,8 @@ static HWND WINAPI CreateWindowExW_hook(DWORD dwExStyle, LPCWSTR lpClassName, LP } // windowed mode adjustments - if (GRAPHICS_WINDOWED) { + // check the width to filter out invisible system-created windows + if (GRAPHICS_WINDOWED && nWidth > 0) { // change window style dwExStyle = 0; @@ -546,7 +544,12 @@ static HWND WINAPI CreateWindowExW_hook(DWORD dwExStyle, LPCWSTR lpClassName, LP hWndParent, hMenu, hInstance, lpParam); GRAPHICS_WINDOWS.push_back(result); - log_misc("graphics", "CreateWindowExW returned {}", fmt::ptr(result)); + log_misc( + "graphics", + "CreateWindowExW returned {}, {}", + fmt::ptr(result), + lpWindowName ? ws2s(lpWindowName) : "(null)"); + disable_touch_indicators(result); return result; } @@ -713,7 +716,7 @@ static BOOL WINAPI SetWindowPos_hook(HWND hWnd, HWND hWndInsertAfter, // prevent gitadora arena model from shifting windows around if the user has preferences if (GRAPHICS_WINDOWED && games::gitadora::is_arena_model() && - GRAPHICS_WINDOW_MAIN.has_value() && hWnd == GRAPHICS_WINDOW_MAIN.value() && + GRAPHICS_HOOKED_WINDOW.has_value() && hWnd == GRAPHICS_HOOKED_WINDOW.value() && cfg::SCREENRESIZE->enable_window_resize) { return TRUE; } @@ -725,7 +728,7 @@ static BOOL WINAPI SetWindowPos_hook(HWND hWnd, HWND hWndInsertAfter, static BOOL WINAPI ShowWindow_hook(HWND hWnd, int nCmdShow) { if (games::gitadora::is_arena_model() && games::gitadora::ARENA_SINGLE_WINDOW && - hWnd != GRAPHICS_WINDOW_MAIN) { + hWnd != GRAPHICS_HOOKED_WINDOW) { log_info("graphics", "ShowWindow_hook - hiding sub window {}", fmt::ptr(hWnd)); return true; } diff --git a/src/spice2x/hooks/graphics/graphics.h b/src/spice2x/hooks/graphics/graphics.h index 9916c4f..1724015 100644 --- a/src/spice2x/hooks/graphics/graphics.h +++ b/src/spice2x/hooks/graphics/graphics.h @@ -31,7 +31,6 @@ extern bool GRAPHICS_SHOW_CURSOR; extern bool GRAPHICS_WINDOWED; extern graphics_orientation GRAPHICS_ADJUST_ORIENTATION; extern std::vector GRAPHICS_WINDOWS; -extern std::optional GRAPHICS_WINDOW_MAIN; extern UINT GRAPHICS_FORCE_REFRESH; extern std::optional GRAPHICS_FORCE_REFRESH_SUB; extern std::optional GRAPHICS_FORCE_VSYNC_BUFFER; @@ -50,6 +49,7 @@ extern std::optional> GRAPHICS_WINDOW_SIZE; extern std::optional GRAPHICS_WINDOW_POS; extern bool GRAPHICS_WINDOW_ALWAYS_ON_TOP; extern bool GRAPHICS_WINDOW_BACKBUFFER_SCALE; +extern std::optional GRAPHICS_HOOKED_WINDOW; extern bool GRAPHICS_IIDX_WSUB; extern std::optional GRAPHICS_WSUB_SIZE; diff --git a/src/spice2x/hooks/graphics/graphics_windowed.cpp b/src/spice2x/hooks/graphics/graphics_windowed.cpp index 0d99475..841f5c2 100644 --- a/src/spice2x/hooks/graphics/graphics_windowed.cpp +++ b/src/spice2x/hooks/graphics/graphics_windowed.cpp @@ -24,6 +24,7 @@ std::optional> GRAPHICS_WINDOW_SIZE; std::optional GRAPHICS_WINDOW_POS; bool GRAPHICS_WINDOW_ALWAYS_ON_TOP = false; bool GRAPHICS_WINDOW_BACKBUFFER_SCALE = false; +std::optional GRAPHICS_HOOKED_WINDOW; // IIDX Windowed Subscreen - starts out as false, enabled by IIDX module on pre-attach as needed bool GRAPHICS_IIDX_WSUB = false; @@ -56,6 +57,8 @@ void graphics_capture_initial_window(HWND hWnd) { graphics_load_windowed_parameters(); + GRAPHICS_HOOKED_WINDOW = hWnd; + cfg::SCREENRESIZE->init_window_style = GetWindowLong(hWnd, GWL_STYLE); cfg::SCREENRESIZE->init_window_style_ex = GetWindowLong(hWnd, GWL_EXSTYLE); @@ -67,8 +70,9 @@ void graphics_capture_initial_window(HWND hWnd) { RECT rect; if (!GetClientRect(hWnd, &rect)) { log_warning( - "graphics", - "graphics_capture_initial_window - GetClientRect failed, GLE: {}", + "graphics-windowed", + "[{}] graphics_capture_initial_window - GetClientRect failed, GLE: {}", + fmt::ptr(hWnd), GetLastError()); return; } @@ -80,7 +84,8 @@ void graphics_capture_initial_window(HWND hWnd) { cfg::SCREENRESIZE->init_client_aspect_ratio = (float)client_w / (float)client_h; log_debug( "graphics-windowed", - "graphics_capture_initial_window initial window size {}x{}, ratio {}", + "[{}] graphics_capture_initial_window initial window size {}x{}, ratio {}", + fmt::ptr(hWnd), client_w, client_h, cfg::SCREENRESIZE->init_client_aspect_ratio); // ensure frame size is captured @@ -105,7 +110,8 @@ void graphics_capture_initial_window(HWND hWnd) { // resize must be done before applying the border if (cfg::SCREENRESIZE->enable_window_resize) { log_info( - "graphics-windowed", "change window rect - window offset: {}x{}, client size: {}x{}", + "graphics-windowed", "[{}] change window rect - window offset: {}x{}, client size: {}x{}", + fmt::ptr(hWnd), cfg::SCREENRESIZE->window_offset_x, cfg::SCREENRESIZE->window_offset_y, cfg::SCREENRESIZE->client_width, @@ -115,12 +121,13 @@ void graphics_capture_initial_window(HWND hWnd) { // ddr hangs when window frame doesn't have overlapped if (cfg::SCREENRESIZE->window_decoration != cfg::WindowDecorationMode::Default) { log_info( - "graphics-windowed", "change window style - decoration: {}", + "graphics-windowed", "[{}] change window style - decoration: {}", + fmt::ptr(hWnd), cfg::SCREENRESIZE->window_decoration); graphics_update_window_style(hWnd); } if (cfg::SCREENRESIZE->window_always_on_top) { - log_info("graphics-windowed", "change window z-order - always on top"); + log_info("graphics-windowed", "[{}] change window z-order - always on top", fmt::ptr(hWnd)); graphics_update_z_order(hWnd, true); } diff --git a/src/spice2x/overlay/windows/screen_resize.cpp b/src/spice2x/overlay/windows/screen_resize.cpp index e08bad8..ed637e5 100644 --- a/src/spice2x/overlay/windows/screen_resize.cpp +++ b/src/spice2x/overlay/windows/screen_resize.cpp @@ -27,11 +27,12 @@ namespace overlay::windows { } HWND ScreenResize::get_first_window() { - // hack for gitadora arena model which races to create many windows - // so [0] is not always the main one - if (GRAPHICS_WINDOW_MAIN.has_value()) { - return GRAPHICS_WINDOW_MAIN.value(); + // this is ideal + if (GRAPHICS_HOOKED_WINDOW.has_value()) { + return GRAPHICS_HOOKED_WINDOW.value(); } + // we typically do not want to check GRAPHICS_WINDOWS because it may include + // system windows (e.g., CicMarshalWnd) if (GRAPHICS_WINDOWS.size() == 0) { return NULL; }