summaryrefslogtreecommitdiff
path: root/deimos/core
diff options
context:
space:
mode:
Diffstat (limited to 'deimos/core')
-rw-r--r--deimos/core/allocator.h6
-rw-r--r--deimos/core/os.h8
-rw-r--r--deimos/core/os_win32.cpp84
3 files changed, 84 insertions, 14 deletions
diff --git a/deimos/core/allocator.h b/deimos/core/allocator.h
index 5afb824..07a214e 100644
--- a/deimos/core/allocator.h
+++ b/deimos/core/allocator.h
@@ -25,15 +25,15 @@ struct IAllocator
class Allocator
{
- gsl::owner<IAllocator*> m_allocator;
- const MemoryScope m_scope;
+ IAllocator* m_allocator;
+ MemoryScope m_scope;
public:
constexpr Allocator(IAllocator* allocator, MemoryScope scope) :
m_allocator{allocator}, m_scope{scope}
{}
- deimos_NO_COPY_MOVE(Allocator);
+ deimos_DEFAULT_COPY_MOVE(Allocator);
~Allocator() = default;
diff --git a/deimos/core/os.h b/deimos/core/os.h
index ecbe3cd..c440555 100644
--- a/deimos/core/os.h
+++ b/deimos/core/os.h
@@ -50,7 +50,7 @@ public:
virtual void Commit(void* ptr, int64_t size) = 0;
};
-struct OsWindowHandle;
+struct OsWindow;
class OsWindowApi
{
@@ -59,7 +59,11 @@ public:
deimos_NO_COPY_MOVE(OsWindowApi);
virtual ~OsWindowApi() = default;
- virtual StatusOr<gsl::owner<OsWindowHandle*>> Create(gsl::czstring title, int32_t width, int32_t height) = 0;
+ virtual StatusOr<gsl::owner<OsWindow*>> Create(gsl::czstring title, int32_t width, int32_t height) = 0;
+
+ virtual void Update(OsWindow*) = 0;
+
+ virtual bool QuitRequested(const OsWindow*) = 0;
};
class OsApi
diff --git a/deimos/core/os_win32.cpp b/deimos/core/os_win32.cpp
index fe904cd..e80a1d5 100644
--- a/deimos/core/os_win32.cpp
+++ b/deimos/core/os_win32.cpp
@@ -10,9 +10,9 @@ namespace deimos
gsl::cwzstring Utf8ToUtf16Z(StringView src, Span<wchar_t> buffer)
{
- Expects(buffer.size() > 0 && buffer.size() > src.size());
+ Expects(!buffer.empty() && buffer.size() > src.size());
- int res = ::MultiByteToWideChar(CP_UTF8, 0, src.data(), (int)src.size_bytes(), buffer.data(), (int)buffer.size() - 1);
+ const int res = ::MultiByteToWideChar(CP_UTF8, 0, src.data(), (int)src.size_bytes(), buffer.data(), (int)buffer.size() - 1);
if (res < 0) { return L"< MBTWC ERROR >"; }
buffer[res] = L'\0';
@@ -84,18 +84,56 @@ public:
}
};
+struct OsWindow
+{
+ HWND hwnd{};
+ bool destroyed{};
+ bool quit_requested{};
+};
+
class Win32WindowApiImpl : public OsWindowApi
{
static constexpr wchar_t kClassName[] = L"Deimos window class";
- bool m_class_registered = false;
+ Allocator* m_allocator;
+ bool m_class_registered = false;
+
+ static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ if (uMsg == WM_CREATE)
+ {
+ const auto* create = (const CREATESTRUCT*)lParam; // NOLINT
+ ::SetWindowLongPtrW(hwnd, GWLP_USERDATA, std::bit_cast<LONG_PTR>(create->lpCreateParams));
+ return 0;
+ }
+
+ auto* window = std::bit_cast<OsWindow*>(::GetWindowLongPtrW(hwnd, GWLP_USERDATA));
+
+ switch (uMsg)
+ {
+ case WM_CLOSE:
+ {
+ window->quit_requested = true;
+ ::DestroyWindow(hwnd);
+ return 0;
+ }
+ case WM_DESTROY:
+ {
+ window->destroyed = true;
+ ::PostQuitMessage(0);
+ return 0;
+ }
+ default:
+ return ::DefWindowProcW(hwnd, uMsg, wParam, lParam);
+ }
+ }
void RegisterClass()
{
Expects(!m_class_registered);
WNDCLASSW wnd_class{};
- wnd_class.lpfnWndProc = ::DefWindowProcW;
+ wnd_class.lpfnWndProc = WindowProc;
wnd_class.hInstance = ::GetModuleHandleW(nullptr);
wnd_class.lpszClassName = kClassName;
@@ -105,7 +143,11 @@ class Win32WindowApiImpl : public OsWindowApi
}
public:
- StatusOr<gsl::owner<OsWindowHandle*>> Create(gsl::czstring title, int32_t width, int32_t height) override
+ explicit Win32WindowApiImpl(Allocator* allocator) :
+ m_allocator{allocator}
+ {}
+
+ StatusOr<gsl::owner<OsWindow*>> Create(gsl::czstring title, int32_t width, int32_t height) override
{
if (!m_class_registered)
{
@@ -115,11 +157,13 @@ public:
wchar_t title_w_buffer[128]{};
gsl::cwzstring title_w = Utf8ToUtf16Z(title, title_w_buffer);
+
+ auto* window = m_allocator->New<OsWindow>();
HWND hwnd = ::CreateWindowExW(
0, kClassName, title_w, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, width, height,
- nullptr, nullptr, ::GetModuleHandle(nullptr), nullptr);
+ nullptr, nullptr, ::GetModuleHandle(nullptr), window);
if (hwnd == nullptr)
{
@@ -128,7 +172,25 @@ public:
::ShowWindow(hwnd, SW_SHOW);
- return nullptr;
+ window->hwnd = hwnd;
+ return window;
+ }
+
+ void Update(OsWindow* window) override
+ {
+ if (window->destroyed) { return; }
+
+ MSG msg;
+ while (::PeekMessageW(&msg, window->hwnd, 0, 0, PM_REMOVE) != 0)
+ {
+ TranslateMessage(&msg);
+ DispatchMessageW(&msg);
+ }
+ }
+
+ bool QuitRequested(const OsWindow* window) override
+ {
+ return window->quit_requested;
}
};
@@ -140,7 +202,8 @@ class Win32OsApiImpl : public OsApi
Win32WindowApiImpl m_window_api;
public:
- Win32OsApiImpl()
+ explicit Win32OsApiImpl(Allocator* allocator) :
+ m_window_api(allocator)
{
console = &m_console_api;
dll = &m_dll_api;
@@ -152,7 +215,10 @@ public:
void RegisterOsApi(ApiRegistry* api_registry)
{
auto* allocator_api = api_registry->Get<AllocatorApi>();
- auto* os_api = allocator_api->system->New<Win32OsApiImpl>();
+
+ Allocator* allocator = allocator_api->CreateChild(allocator_api->system, "OS");
+ auto* os_api = allocator_api->system->New<Win32OsApiImpl>(allocator);
+
api_registry->Set(os_api);
}