16 OutputDebugStringW(message);
17 OutputDebugStringW(L
"\n");
20 int len = WideCharToMultiByte(CP_UTF8, 0, message, -1, NULL, 0, NULL, NULL);
22 char* utf8 = (
char*)malloc(len);
24 WideCharToMultiByte(CP_UTF8, 0, message, -1, utf8, len, NULL, NULL);
25 fprintf(stderr,
"[Win32] %s\n", utf8);
31static LRESULT CALLBACK
WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
44 int w = LOWORD(lparam);
45 int h = HIWORD(lparam);
46 if (w > 0 && h > 0 && (w != window->
width || h != window->
height)) {
65 UINT size =
sizeof(raw);
67 if (GetRawInputData((HRAWINPUT)lparam, RID_INPUT, &raw,
68 &size,
sizeof(RAWINPUTHEADER)) != (UINT)-1) {
69 if (raw.header.dwType == RIM_TYPEMOUSE) {
81 RECT*
const prcNewWindow = (RECT*)lparam;
82 SetWindowPos(window->
hwnd, NULL,
85 prcNewWindow->right - prcNewWindow->left,
86 prcNewWindow->bottom - prcNewWindow->top,
87 SWP_NOZORDER | SWP_NOACTIVATE);
98 return DefWindowProc(hwnd, msg, wparam, lparam);
109 SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
111 HINSTANCE hinstance = GetModuleHandle(NULL);
113 WNDCLASSW wc = { 0 };
115 wc.hInstance = hinstance;
116 wc.lpszClassName = L
"SBglWindowClass";
117 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
122 int title_len = MultiByteToWideChar(CP_UTF8, 0, title, -1, NULL, 0);
123 wchar_t* wtitle = malloc(title_len *
sizeof(
wchar_t));
124 MultiByteToWideChar(CP_UTF8, 0, title, -1, wtitle, title_len);
127 RECT rect = { 0, 0, width, height };
128 AdjustWindowRectEx(&rect, WS_OVERLAPPEDWINDOW, FALSE, 0);
130 HWND hwnd = CreateWindowExW(
137 rect.right - rect.left,
138 rect.bottom - rect.top,
161 window->
width = width;
166 window->
input = input;
171 wcsncpy(window->
className, wc.lpszClassName, 255);
174 SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)window);
176 ShowWindow(hwnd, SW_SHOW);
186 RAWINPUTDEVICE rid = {
189 .dwFlags = RIDEV_REMOVE,
192 RegisterRawInputDevices(&rid, 1,
sizeof(rid));
196 DestroyWindow(window->
hwnd);
212 if (w) *w = window->
width;
213 if (h) *h = window->
height;
246 RAWINPUTDEVICE rid = {
249 .dwFlags = RIDEV_NOLEGACY | RIDEV_CAPTUREMOUSE,
250 .hwndTarget = window->
hwnd
252 if (!RegisterRawInputDevices(&rid, 1,
sizeof(rid))) {
259 GetClientRect(window->
hwnd, &rect);
260 ClientToScreen(window->
hwnd, (POINT*)&rect.left);
261 ClientToScreen(window->
hwnd, (POINT*)&rect.right);
270 int centerX = window->
width / 2;
271 int centerY = window->
height / 2;
272 POINT p = { centerX, centerY };
273 ClientToScreen(window->
hwnd, &p);
274 SetCursorPos(p.x, p.y);
277 RAWINPUTDEVICE rid = {
280 .dwFlags = RIDEV_REMOVE,
283 RegisterRawInputDevices(&rid, 1,
sizeof(rid));
297 return window ? window->
focused :
false;
302 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
303 TranslateMessage(&msg);
304 DispatchMessage(&msg);
315 QueryPerformanceCounter(&count);
316 return (uint64_t)count.QuadPart;
322 QueryPerformanceFrequency(&freq);
323 return (uint64_t)freq.QuadPart;
327 return window ? (
void*)window->
hwnd : NULL;
331 return window ? (
void*)window->
hinstance : NULL;
Arena allocator implementation.
#define SBL_ARENA_PUSH_STRUCT_ZERO(arena, type)
bool sbgl_os_WasWindowResized(sbgl_Window *window)
Checks if the window has been resized since the last check.
uint64_t sbgl_os_GetPerfCount(sbgl_Window *window)
Gets the high-resolution performance counter.
void sbgl_os_PollEvents(sbgl_Window *window)
Dispatches OS events (messages/protocol requests).
void sbgl_os_SetCursorLocked(sbgl_Window *window, bool locked)
Locks or unlocks the cursor within the window bounds.
uint64_t sbgl_os_GetPerfFreq(sbgl_Window *window)
Gets the performance counter frequency.
void * sbgl_os_GetNativeWindowHandle(sbgl_Window *window)
Retrieves the raw window handle for Vulkan surface creation.
void sbgl_os_SetCursorVisible(sbgl_Window *window, bool visible)
Sets the visibility of the OS cursor for the given window.
sbgl_Window * sbgl_os_CreateWindow(struct SblArena *arena, sbgl_InputState *input, int width, int height, const char *title)
bool sbgl_os_WindowShouldClose(sbgl_Window *window)
Checks the window's close flag.
void sbgl_os_GetWindowSize(sbgl_Window *window, int *w, int *h)
Retrieves the current client area size.
static void win32_report_error(const wchar_t *message)
Reports errors to both debugger output and stderr.
static LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
bool sbgl_os_IsWindowFocused(sbgl_Window *window)
Checks if the window currently has input focus.
void * sbgl_os_GetNativeDisplayHandle(sbgl_Window *window)
Retrieves the native display handle (Linux specific).
void * sbgl_os_GetNativeInstanceHandle(sbgl_Window *window)
Retrieves the native instance handle (Win32 specific).
void sbgl_os_DestroyWindow(sbgl_Window *window)
Destroys a native window.