_borderless maximize workarounds WIP

This commit is contained in:
2024-12-26 22:10:25 +02:00
parent bd81e3e89e
commit 89d1cc4270
2 changed files with 74 additions and 8 deletions

View File

@@ -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 <oleidl.h>
#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