diff --git a/src/spice2x/hooks/graphics/graphics.cpp b/src/spice2x/hooks/graphics/graphics.cpp index 8b21216..08c430c 100644 --- a/src/spice2x/hooks/graphics/graphics.cpp +++ b/src/spice2x/hooks/graphics/graphics.cpp @@ -368,6 +368,10 @@ static HWND WINAPI CreateWindowExA_hook(DWORD dwExStyle, LPCSTR lpClassName, LPC } } + if (GRAPHICS_WINDOWED) { + graphics_window_check_bounds_before_creation(x, y, nWidth, nHeight); + } + // call original HWND result = CreateWindowExA_orig(dwExStyle, lpClassName, lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); @@ -468,6 +472,10 @@ static HWND WINAPI CreateWindowExW_hook(DWORD dwExStyle, LPCWSTR lpClassName, LP } } + if (GRAPHICS_WINDOWED) { + graphics_window_check_bounds_before_creation(x, y, nWidth, nHeight); + } + // call original HWND result = CreateWindowExW_orig( dwExStyle, lpClassName, lpWindowName, dwStyle, x, y, nWidth, nHeight, diff --git a/src/spice2x/hooks/graphics/graphics.h b/src/spice2x/hooks/graphics/graphics.h index 99077b9..179584e 100644 --- a/src/spice2x/hooks/graphics/graphics.h +++ b/src/spice2x/hooks/graphics/graphics.h @@ -108,6 +108,7 @@ bool graphics_window_decoration_change_crashes_game(); bool graphics_window_resize_breaks_game(); bool graphics_window_move_and_resize_breaks_game(); void graphics_load_windowed_subscreen_parameters(); +void graphics_window_check_bounds_before_creation(int &x, int &y, const int width, const int height); void change_primary_monitor(const std::string &monitor_name); void update_monitor_on_boot(std::optional target_orientation, UINT target_refresh_rate); \ No newline at end of file diff --git a/src/spice2x/hooks/graphics/graphics_windowed.cpp b/src/spice2x/hooks/graphics/graphics_windowed.cpp index 7be0f20..2fdad4d 100644 --- a/src/spice2x/hooks/graphics/graphics_windowed.cpp +++ b/src/spice2x/hooks/graphics/graphics_windowed.cpp @@ -560,3 +560,56 @@ bool graphics_window_resize_breaks_game() { return result; } + +void graphics_window_check_bounds_before_creation(int &x, int &y, const int width, const int height) { + RECT rect = { + .left = x, + .top = y, + .right = x + width, + .bottom = y + height + }; + + HMONITOR mon = MonitorFromRect(&rect, MONITOR_DEFAULTTONULL); + if (mon != nullptr) { + return; + } + + log_warning( + "graphics-windowed", + "window is completely out of bounds, resetting position: ({}, {}) => (0, 0)", + x, y); + x = 0; + y = 0; + rect = { + .left = x, + .top = y, + .right = x + width, + .bottom = y + height + }; + + mon = MonitorFromRect(&rect, MONITOR_DEFAULTTONEAREST); + MONITORINFO mi = {}; + mi.cbSize = sizeof(mi); + if (!GetMonitorInfo(mon, &mi)) { + log_warning( + "graphics-windowed", + "failed to get monitor info for out of bounds window"); + return; + } + + log_misc( + "graphics-windowed", + "nearest monitor for this window has work area ({}, {}),({}, {})", + mi.rcWork.left, mi.rcWork.top, mi.rcWork.right, mi.rcWork.bottom); + + RECT bounds = mi.rcWork; + const bool fully_visible = + (rect.left >= bounds.left && + rect.top >= bounds.top && + rect.right <= bounds.right && + rect.bottom <= bounds.bottom); + + if (!fully_visible) { + log_warning("graphics-windowed", "window will not be fully visible on monitor"); + } +}