diff options
Diffstat (limited to 'deimos/core/os_win32.cpp')
-rw-r--r-- | deimos/core/os_win32.cpp | 84 |
1 files changed, 75 insertions, 9 deletions
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);
}
|