window: refactored code

This commit is contained in:
Hyper
2024-10-30 11:41:48 +00:00
parent 7d04ed057c
commit 1c7b66237d
6 changed files with 238 additions and 120 deletions
+64 -34
View File
@@ -7,7 +7,6 @@ bool m_isFullscreenKeyReleased = true;
int Window_OnSDLEvent(void*, SDL_Event* event)
{
// TODO (Hyper): prevent window changes during boot to avoid buffer resize crashes.
switch (event->type)
{
case SDL_QUIT:
@@ -25,7 +24,10 @@ int Window_OnSDLEvent(void*, SDL_Event* event)
if (!(event->key.keysym.mod & KMOD_ALT) || !m_isFullscreenKeyReleased)
break;
Window::SetFullscreen(!Window::IsFullscreen());
Config::Fullscreen = Window::SetFullscreen(!Window::IsFullscreen());
if (!Config::Fullscreen)
Config::WindowState = Window::SetMaximised(Config::WindowState == EWindowState::Maximised);
// Block holding ALT+ENTER spamming window changes.
m_isFullscreenKeyReleased = false;
@@ -35,11 +37,8 @@ int Window_OnSDLEvent(void*, SDL_Event* event)
// Restore original window dimensions on F2.
case SDLK_F2:
{
Window::SetFullscreen(Config::Fullscreen);
Window::SetWindowDimensions(-1, -1, true);
Window::SetDimensions(SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, DEFAULT_WIDTH, DEFAULT_HEIGHT);
break;
}
}
break;
@@ -70,16 +69,43 @@ int Window_OnSDLEvent(void*, SDL_Event* event)
SDL_ShowCursor(Window::IsFullscreen() ? SDL_DISABLE : SDL_ENABLE);
break;
case SDL_WINDOWEVENT_RESTORED:
case SDL_WINDOWEVENT_MAXIMIZED:
{
Config::WindowState = Window::IsMaximised()
? EWindowState::Maximised
: EWindowState::Normal;
break;
}
case SDL_WINDOWEVENT_RESIZED:
{
Window::s_width = event->window.data1;
Window::s_height = event->window.data2;
Window::RaiseResizeEvents();
if (!Window::IsFullscreen())
{
Config::WindowWidth = Window::s_width;
Config::WindowHeight = Window::s_height;
}
break;
}
case SDL_WINDOWEVENT_MOVED:
Config::WindowX = event->window.data1;
Config::WindowY = event->window.data2;
{
Window::s_x = event->window.data1;
Window::s_y = event->window.data2;
if (!Window::IsFullscreen())
{
Config::WindowX = Window::s_x;
Config::WindowY = Window::s_y;
}
break;
}
}
break;
@@ -91,43 +117,47 @@ int Window_OnSDLEvent(void*, SDL_Event* event)
void Window::Init()
{
/* TODO: move this since it'll have to change
on soft reboot from the options menu. */
auto title = Config::Language == ELanguage::Japanese
? "Sonic World Adventure"
: "SONIC UNLEASHED";
SDL_InitSubSystem(SDL_INIT_VIDEO);
SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
SDL_AddEventWatch(Window_OnSDLEvent, s_window);
SDL_AddEventWatch(Window_OnSDLEvent, s_pWindow);
SetProcessDPIAware();
int32_t x = Config::WindowX < 0 ? SDL_WINDOWPOS_CENTERED : Config::WindowX;
int32_t y = Config::WindowY < 0 ? SDL_WINDOWPOS_CENTERED : Config::WindowY;
int32_t width = Config::WindowWidth;
int32_t height = Config::WindowHeight;
s_x = Config::WindowX;
s_y = Config::WindowY;
s_width = Config::WindowWidth;
s_height = Config::WindowHeight;
s_window = SDL_CreateWindow(title, x, y, width, height, SDL_WINDOW_RESIZABLE);
auto isPositionValid = IsPositionValid();
SDL_GetWindowPosition(s_window, &x, &y);
Config::WindowX = x;
Config::WindowY = y;
if (auto icon = GetIconSurface())
if (!isPositionValid)
{
SDL_SetWindowIcon(s_window, icon);
SDL_FreeSurface(icon);
s_x = SDL_WINDOWPOS_CENTERED;
s_y = SDL_WINDOWPOS_CENTERED;
s_width = DEFAULT_WIDTH;
s_height = DEFAULT_HEIGHT;
}
SetWindowDimensions();
SetFullscreen(Config::Fullscreen);
s_pWindow = SDL_CreateWindow("SWA", s_x, s_y, s_width, s_height, GetWindowFlags());
if (!isPositionValid)
{
auto rect = Window::GetDimensions();
Config::WindowX = rect.x;
Config::WindowY = rect.y;
Config::WindowWidth = rect.w;
Config::WindowHeight = rect.h;
}
SetIcon();
SetTitle();
SDL_SetWindowMinimumSize(s_pWindow, 640, 480);
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
SDL_GetWindowWMInfo(s_window, &info);
s_windowHandle = info.info.win.window;
SDL_GetWindowWMInfo(s_pWindow, &info);
s_handle = info.info.win.window;
}
// CApplication::Update
+109 -72
View File
@@ -2,21 +2,25 @@
#include <SDL.h>
#include "res/icon.h"
#include "ui/window_events.h"
#include "config.h"
#define DEFAULT_WIDTH 1280
#define DEFAULT_HEIGHT 720
struct Window
{
inline static std::vector<std::function<void(int, int)>> ms_resizeEvents;
public:
inline static SDL_Window* s_window;
inline static HWND s_windowHandle;
inline static SDL_Window* s_pWindow;
inline static HWND s_handle;
inline static int s_x;
inline static int s_y;
inline static int s_width = DEFAULT_WIDTH;
inline static int s_height = DEFAULT_HEIGHT;
inline static bool s_isFocused;
inline static int s_width = 1280;
inline static int s_height = 720;
static SDL_Surface* GetIconSurface(void* pIconBmp = nullptr, size_t iconSize = 0)
{
auto rw = SDL_RWFromMem(pIconBmp ? pIconBmp : (void*)g_icon, pIconBmp ? iconSize : g_icon_size);
@@ -28,98 +32,131 @@ public:
return surface;
}
static bool IsDisplayResolution(int w, int h, bool isExact = true)
static void SetIcon(void* pIconBmp = nullptr, size_t iconSize = 0)
{
auto width = w <= 0 ? Config::WindowWidth : w;
auto height = h <= 0 ? Config::WindowHeight : h;
SDL_Rect displayRect;
if (SDL_GetDisplayBounds(SDL_GetWindowDisplayIndex(s_window), &displayRect) == ERROR_SUCCESS)
if (auto icon = GetIconSurface(pIconBmp, iconSize))
{
if (isExact)
{
if (displayRect.w == width && displayRect.h == height)
return true;
}
else
{
if (displayRect.w <= width && displayRect.h <= height)
return true;
}
SDL_SetWindowIcon(s_pWindow, icon);
SDL_FreeSurface(icon);
}
}
static void SetTitle(const char* title = nullptr)
{
if (!title)
{
title = Config::Language == ELanguage::Japanese
? "Sonic World Adventure"
: "SONIC UNLEASHED";
}
return false;
SDL_SetWindowTitle(s_pWindow, title);
}
static bool IsFullscreen()
{
return SDL_GetWindowFlags(s_window) & SDL_WINDOW_FULLSCREEN_DESKTOP;
return SDL_GetWindowFlags(s_pWindow) & SDL_WINDOW_FULLSCREEN_DESKTOP;
}
static bool SetFullscreen(bool isEnabled)
{
if (isEnabled)
{
SDL_SetWindowFullscreen(s_window, SDL_WINDOW_FULLSCREEN_DESKTOP);
SDL_SetWindowFullscreen(s_pWindow, SDL_WINDOW_FULLSCREEN_DESKTOP);
SDL_ShowCursor(SDL_DISABLE);
return true;
}
else
{
SDL_SetWindowFullscreen(s_window, 0);
SDL_SetWindowFullscreen(s_pWindow, 0);
SDL_ShowCursor(SDL_ENABLE);
SetIcon();
}
SDL_Rect displayRect;
if (SDL_GetDisplayBounds(SDL_GetWindowDisplayIndex(s_window), &displayRect) == ERROR_SUCCESS)
{
// Maximise window if the config resolution is greater than the display.
if (IsDisplayResolution(s_width, s_height, false))
SDL_MaximizeWindow(s_window);
}
return isEnabled;
}
static bool IsMaximised()
{
return SDL_GetWindowFlags(s_pWindow) & SDL_WINDOW_MAXIMIZED;
}
static EWindowState SetMaximised(bool isEnabled)
{
if (isEnabled)
{
SDL_MaximizeWindow(s_pWindow);
}
else
{
SDL_RestoreWindow(s_pWindow);
}
return isEnabled
? EWindowState::Maximised
: EWindowState::Normal;
}
static SDL_Rect GetDimensions()
{
SDL_Rect rect{};
SDL_GetWindowPosition(s_pWindow, &rect.x, &rect.y);
SDL_GetWindowSize(s_pWindow, &rect.w, &rect.h);
return rect;
}
static void SetDimensions(int x, int y, int w, int h)
{
s_x = x;
s_y = y;
s_width = w;
s_height = h;
SDL_SetWindowSize(s_pWindow, w, h);
SDL_ResizeEvent(s_pWindow, w, h);
SDL_SetWindowPosition(s_pWindow, x, y);
SDL_MoveEvent(s_pWindow, x, y);
}
static uint32_t GetWindowFlags()
{
uint32_t flags = SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE;
if (Config::WindowState == EWindowState::Maximised)
flags |= SDL_WINDOW_MAXIMIZED;
if (Config::Fullscreen)
flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
return flags;
}
static bool IsPositionValid()
{
auto displayCount = SDL_GetNumVideoDisplays();
if (displayCount <= 0)
{
printf("Failed to validate window position: %s\n", SDL_GetError());
return false;
}
}
static void SetWindowDimensions(int w = -1, int h = -1, bool recenter = false)
{
auto width = w <= 0 ? Config::WindowWidth : w;
auto height = h <= 0 ? Config::WindowHeight : h;
auto isPendingMaximise = false;
if (IsDisplayResolution(width, height))
for (int i = 0; i < displayCount; i++)
{
height -= GetSystemMetrics(31);
isPendingMaximise = true;
SDL_Rect bounds;
if (SDL_GetDisplayBounds(i, &bounds) == 0)
{
if (s_x >= bounds.x && s_x < bounds.x + bounds.w &&
s_y >= bounds.y && s_y < bounds.y + bounds.h)
{
return true;
}
}
}
int32_t x = recenter ? SDL_WINDOWPOS_CENTERED : Config::WindowX;
int32_t y = recenter ? SDL_WINDOWPOS_CENTERED : Config::WindowY;
SDL_SetWindowSize(s_window, width, height);
SDL_SetWindowMinimumSize(s_window, 640, 480);
SDL_SetWindowPosition(s_window, x, y);
s_width = width;
s_height = height;
if (!isPendingMaximise)
return;
// Maximise window if the config resolution matches the display.
SDL_MaximizeWindow(s_window);
}
static void AddResizeEvent(std::function<void(int, int)> resizeEvent)
{
ms_resizeEvents.push_back(resizeEvent);
}
static void RaiseResizeEvents()
{
for (const auto& resizeEvent : ms_resizeEvents)
resizeEvent(s_width, s_height);
return false;
}
static void Init();
+28
View File
@@ -0,0 +1,28 @@
#pragma once
#include <SDL.h>
#include "ui/window.h"
inline static void SDL_ResizeEvent(SDL_Window* pWindow, int width, int height)
{
SDL_Event event{};
event.type = SDL_WINDOWEVENT;
event.window.event = SDL_WINDOWEVENT_RESIZED;
event.window.windowID = SDL_GetWindowID(pWindow);
event.window.data1 = width;
event.window.data2 = height;
SDL_PushEvent(&event);
}
inline static void SDL_MoveEvent(SDL_Window* pWindow, int x, int y)
{
SDL_Event event{};
event.type = SDL_WINDOWEVENT;
event.window.event = SDL_WINDOWEVENT_MOVED;
event.window.windowID = SDL_GetWindowID(pWindow);
event.window.data1 = x;
event.window.data2 = y;
SDL_PushEvent(&event);
}