Window: add game icon and window events

This commit is contained in:
Hyper
2024-10-17 17:51:17 +01:00
parent 0f237c693d
commit 7b4caece2f
8 changed files with 981 additions and 2 deletions
+83
View File
@@ -2,6 +2,80 @@
#include <config.h>
#include <kernel/function.h>
#include <SDL_syswm.h>
#include "game.h"
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)
{
// TODO: use Game::Exit().
case SDL_QUIT:
ExitProcess(0);
break;
case SDL_KEYDOWN:
{
switch (event->key.keysym.sym)
{
// Toggle fullscreen on ALT+ENTER.
case SDLK_RETURN:
{
if (!(event->key.keysym.mod & KMOD_ALT) || !m_isFullscreenKeyReleased)
break;
Window::SetFullscreen(!Window::IsFullscreen());
// Block holding ALT+ENTER spamming window changes.
m_isFullscreenKeyReleased = false;
break;
}
}
break;
}
case SDL_KEYUP:
{
switch (event->key.keysym.sym)
{
// Allow user to input ALT+ENTER again.
case SDLK_RETURN:
m_isFullscreenKeyReleased = true;
break;
}
}
case SDL_WINDOWEVENT:
{
switch (event->window.event)
{
case SDL_WINDOWEVENT_FOCUS_LOST:
Window::s_isFocused = false;
SDL_ShowCursor(SDL_ENABLE);
break;
case SDL_WINDOWEVENT_FOCUS_GAINED:
Window::s_isFocused = true;
SDL_ShowCursor(Window::IsFullscreen() ? SDL_DISABLE : SDL_ENABLE);
break;
case SDL_WINDOWEVENT_RESIZED:
Window::s_width = event->window.data1;
Window::s_height = event->window.data2;
Window::RaiseResizeEvents();
break;
}
break;
}
}
return 0;
}
void Window::Init()
{
@@ -11,9 +85,18 @@ void Window::Init()
SDL_InitSubSystem(SDL_INIT_VIDEO);
SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
SDL_AddEventWatch(Window_OnSDLEvent, s_window);
s_window = SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_RESIZABLE);
if (auto icon = GetIconSurface())
{
SDL_SetWindowIcon(s_window, icon);
SDL_FreeSurface(icon);
}
SetFullscreen(Config::Fullscreen);
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
SDL_GetWindowWMInfo(s_window, &info);
+111 -2
View File
@@ -1,10 +1,119 @@
#pragma once
#include <SDL.h>
#include "res/icon.h"
struct Window
{
static inline SDL_Window* s_window;
static inline HWND s_windowHandle;
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 bool s_isFocused;
inline static int s_width;
inline static int s_height;
static SDL_Surface* GetIconSurface(void* pIconBmp = nullptr)
{
auto rw = SDL_RWFromMem(pIconBmp ? pIconBmp : (void*)g_icon, g_icon_size);
auto surface = SDL_LoadBMP_RW(rw, 1);
if (!surface)
printf("Failed to load icon: %s\n", SDL_GetError());
return surface;
}
static bool IsDisplayResolution(int w, int h, bool isExact = true)
{
auto width = w <= 0 ? Config::Width : w;
auto height = h <= 0 ? Config::Height : h;
SDL_Rect displayRect;
if (SDL_GetDisplayBounds(SDL_GetWindowDisplayIndex(s_window), &displayRect) == ERROR_SUCCESS)
{
if (isExact)
{
if (displayRect.w == width && displayRect.h == height)
return true;
}
else
{
if (displayRect.w <= width && displayRect.h <= height)
return true;
}
}
return false;
}
static bool IsFullscreen()
{
return SDL_GetWindowFlags(s_window) & SDL_WINDOW_FULLSCREEN_DESKTOP;
}
static bool SetFullscreen(bool isEnabled)
{
if (isEnabled)
{
SDL_SetWindowFullscreen(s_window, SDL_WINDOW_FULLSCREEN_DESKTOP);
SDL_ShowCursor(SDL_DISABLE);
return true;
}
else
{
SDL_SetWindowFullscreen(s_window, 0);
SDL_ShowCursor(SDL_ENABLE);
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(Config::Width, Config::Height, false))
SDL_MaximizeWindow(s_window);
}
return false;
}
}
static void SetWindowDimensions(int w, int h)
{
auto width = w <= 0 ? Config::Width : w;
auto height = h <= 0 ? Config::Height : h;
auto isPendingMaximise = false;
if (IsDisplayResolution(width, height))
{
height -= GetSystemMetrics(31);
isPendingMaximise = true;
}
SDL_SetWindowSize(s_window, width, height);
SDL_SetWindowMinimumSize(s_window, 640, 480);
SDL_SetWindowPosition(s_window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
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);
}
static void Init();
};