diff --git a/Source/Engine/Platform/SDL/SDLPlatform.cpp b/Source/Engine/Platform/SDL/SDLPlatform.cpp index 5a214acf8..427427af6 100644 --- a/Source/Engine/Platform/SDL/SDLPlatform.cpp +++ b/Source/Engine/Platform/SDL/SDLPlatform.cpp @@ -60,7 +60,7 @@ bool SDLPlatform::Init() SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1"); // Fixes context menu focus issues when clicking unfocused menus SDL_SetHint(SDL_HINT_WINDOWS_ERASE_BACKGROUND_MODE, "0"); SDL_SetHint(SDL_HINT_TIMER_RESOLUTION, "0"); // Already handled during platform initialization - SDL_SetHint("SDL_BORDERLESS_RESIZABLE_STYLE", "1"); // Allow borderless windows to be resizable on Windows, currently breaks maximize window functionality + SDL_SetHint("SDL_BORDERLESS_RESIZABLE_STYLE", "1"); // Allow borderless windows to be resizable on Windows SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_WARP_MOTION, "0"); SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_CURSOR_VISIBLE, "1"); // Needed for tracking mode SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_MODE_CENTER, "1"); // Is this needed? diff --git a/Source/Engine/Platform/SDL/SDLWindow.cpp b/Source/Engine/Platform/SDL/SDLWindow.cpp index 60abf4234..1e0846c5f 100644 --- a/Source/Engine/Platform/SDL/SDLWindow.cpp +++ b/Source/Engine/Platform/SDL/SDLWindow.cpp @@ -26,6 +26,8 @@ #if PLATFORM_WINDOWS #include "Engine/Platform/Win32/IncludeWindowsHeaders.h" +#define STYLE_RESIZABLE (WS_THICKFRAME | WS_MAXIMIZEBOX) +#define BORDERLESS_MAXIMIZE_WORKAROUND 2 #if USE_EDITOR #include #endif @@ -39,6 +41,9 @@ namespace { SDLWindow* LastEventWindow = nullptr; static SDL_Cursor* Cursors[SDL_SYSTEM_CURSOR_COUNT] = { nullptr }; +#if BORDERLESS_MAXIMIZE_WORKAROUND == 2 + int SkipMaximizeEventsCount = 0; +#endif } void* GetNativeWindowPointer(SDL_Window* window); @@ -548,11 +553,38 @@ void SDLWindow::HandleEvent(SDL_Event& event) _maximized = true; #if PLATFORM_WINDOWS - // This shouldn't be needed anymore, but maximize blocks any resize operations +#if BORDERLESS_MAXIMIZE_WORKAROUND == 2 + if (SkipMaximizeEventsCount > 0) + { + SkipMaximizeEventsCount--; + return; + } + if (!_settings.HasBorder && _settings.HasSizingFrame) + { + // Restore the window back to previous state + SDL_RestoreWindow(_window); + + // Remove the resizable flags from borderless windows and maximize the window again + auto style = ::GetWindowLong((HWND)_handle, GWL_STYLE); + style &= ~STYLE_RESIZABLE; + ::SetWindowLong((HWND)_handle, GWL_STYLE, style); + + SDL_MaximizeWindow(_window); + + // Re-enable the resizable borderless flags + style = ::GetWindowLong((HWND)_handle, GWL_STYLE) | STYLE_RESIZABLE; + ::SetWindowLong((HWND)_handle, GWL_STYLE, style); + + // The next SDL_EVENT_WINDOW_RESTORED and SDL_EVENT_WINDOW_MAXIMIZED events should be ignored + SkipMaximizeEventsCount = 2; + } + +#endif + if (false && !_settings.HasBorder && _settings.HasSizingFrame) { // Borderless editor window doesn't maximize properly, - // manually force the window into correct location and size. + // force the fullscreen window into correct location and size. SDL_Rect rect; SDL_DisplayID display = SDL_GetDisplayForWindow(_window); SDL_GetDisplayUsableBounds(display, &rect); // Excludes taskbar etc. @@ -562,11 +594,9 @@ void SDLWindow::HandleEvent(SDL_Event& event) auto size = GetClientSize(); if (pos.X < rect.x || pos.Y < rect.y || size.X > rect.w || size.Y > rect.h) { - SDL_RestoreWindow(_window); - // Set the internal floating window rectangle to expected position + // NOTE: Currently the resize operations are blocked while window is in maximized state SetClientBounds(Rectangle((float)rect.x, (float)rect.y, (float)rect.w, (float)rect.h)); - _cachedClientRectangle.Size = Float2((float)rect.w, (float)rect.h); } } #endif @@ -575,6 +605,14 @@ void SDLWindow::HandleEvent(SDL_Event& event) } case SDL_EVENT_WINDOW_RESTORED: { +#if BORDERLESS_MAXIMIZE_WORKAROUND == 2 + if (SkipMaximizeEventsCount > 0) + { + SkipMaximizeEventsCount--; + return; + } +#endif + if (_maximized) { _maximized = false; @@ -786,7 +824,19 @@ void SDLWindow::Maximize() if (!_settings.AllowMaximize) return; +#if PLATFORM_WINDOWS && BORDERLESS_MAXIMIZE_WORKAROUND == 1 + // Workaround for "SDL_BORDERLESS_RESIZABLE_STYLE" hint not working as expected when maximizing windows + auto style = ::GetWindowLong((HWND)_handle, GWL_STYLE); + style &= ~STYLE_RESIZABLE; + ::SetWindowLong((HWND)_handle, GWL_STYLE, style); + SDL_MaximizeWindow(_window); + + style = ::GetWindowLong((HWND)_handle, GWL_STYLE) | STYLE_RESIZABLE; + ::SetWindowLong((HWND)_handle, GWL_STYLE, style); +#else + SDL_MaximizeWindow(_window); +#endif } void SDLWindow::SetBorderless(bool isBorderless, bool maximized) @@ -806,7 +856,9 @@ void SDLWindow::SetBorderless(bool isBorderless, bool maximized) { SDL_SetWindowBordered(_window, !isBorderless ? true : false); if (maximized) - SDL_MaximizeWindow(_window); + { + Maximize(); + } else Focus(); } @@ -814,7 +866,9 @@ void SDLWindow::SetBorderless(bool isBorderless, bool maximized) { SDL_SetWindowBordered(_window, !isBorderless ? true : false); if (maximized) - SDL_MaximizeWindow(_window); + { + Maximize(); + } else Focus(); } @@ -824,7 +878,19 @@ void SDLWindow::SetBorderless(bool isBorderless, bool maximized) void SDLWindow::Restore() { +#if PLATFORM_WINDOWS && BORDERLESS_MAXIMIZE_WORKAROUND == 1 + // Workaround for "SDL_BORDERLESS_RESIZABLE_STYLE" hint not working as expected when maximizing windows + auto style = ::GetWindowLong((HWND)_handle, GWL_STYLE); + style &= ~STYLE_RESIZABLE; + ::SetWindowLong((HWND)_handle, GWL_STYLE, style); + SDL_RestoreWindow(_window); + + style = ::GetWindowLong((HWND)_handle, GWL_STYLE) | STYLE_RESIZABLE; + ::SetWindowLong((HWND)_handle, GWL_STYLE, style); +#else + SDL_RestoreWindow(_window); +#endif } bool SDLWindow::IsClosed() const