started window management

This commit is contained in:
Patedam committed 2026-10-20 23:15:56 -04:00
1 parent 575379e264
commit 886e722c71
19 files changed
+619 -2

No files matched your search

+15 -1
View File
@@ -1,10 +1,24 @@
// clang-format off
// ========================================================================= //
// Includes
// Headers
#include "core/core_inc.h"
#include "window_manager/window_manager_inc.h"
#include "render/render_inc.h"
// C
#include "core/core_inc.c"
#include "window_manager/window_manager_inc.c"
#include "render/render_inc.c"
// clang-format on
internal void entry_point() {}
internal bool32 frame()
{
return 0;
}
internal void entry_point()
{
wm_init();
}
+27 -1
View File
@@ -36,6 +36,7 @@
#define KB(d) ((uint64)(d) << 10)
#define MB(d) ((uint64)(d) << 20)
#define GB(d) ((uint64)(d) << 30)
#define Million(n) ((n) * 1000000)
// =============================================================================
// Branch predictor hints
@@ -105,12 +106,30 @@
#define StaticAssert(cond, ID) global uint8 GLUE(ID, __LINE__)[(cond) ? 1 : -1]
// =============================================================================
// Linked List helpers
// Linked List macro
// Linked list macro helpers
#define CheckNil(nil, ptr) ((ptr) == 0 || (ptr) == nil)
#define SetNil(nil, ptr) ((ptr) = nil)
// clang-format off
#define DLL_insert_NPZ(nil, first, last, ptr, node, next, previous) \
(CheckNil(nil, first) ? ((first) = (last) = (node), SetNil(nil, (node)->next), SetNil(nil, (node)->previous)) \
: CheckNil(nil, ptr) ? ((node)->next = (first), (first)->previous = (node), (first) = (node), SetNil(nil, (node)->previous)) \
: ((ptr) == (last)) ? ((last)->next = (node), (node )->previous = (last), (last ) = (node), SetNil(nil, (node)->next)) \
: (((CheckNil(nil, ptr) && CheckNil(nil, (ptr)->next)) ? (0) : ((ptr)->next->previous = (node))), \
((node)->next = (ptr)->next), ((ptr)->next = (node)), ((node)->previous = (ptr))))
// clang-format on
#define DLL_push_back_NPZ(nil, first, last, node, next, previous) \
DLL_insert_NPZ(nil, first, last, last, node, next, previous)
// Single (link & head) lists (= stacks)
#define SLL_stack_push_node(first, node, next) ((node)->next = (first), (first) = (node))
#define SLL_stack_pop_node(first, next) ((first) = (first)->next);
// Double linked list helpers
#define DLL_push_back(first, last, node) DLL_push_back_NPZ(0, first, last, node, next, previous)
// =============================================================================
// Helpers
@@ -135,6 +154,8 @@ typedef int8_t int8;
typedef int16_t int16;
typedef int32_t int32;
typedef int64_t int64;
typedef float float32;
typedef double float64;
typedef int8 bool8;
typedef int16 bool16;
@@ -226,3 +247,8 @@ global const uint32 bit32 = (1 << 31);
internal uint16 safe_cast_uint16(uint32 val);
internal uint32 safe_cast_uint32(uint64 val);
internal int32 safe_cast_int32(int64 val);
// =============================================================================
// Time functions
internal uint64 now_time_us();
+6
View File
@@ -5,3 +5,9 @@ internal void main_thread_core_entry_point(int argc, char** argv)
ThreadNameF("main_thread");
entry_point();
}
internal bool32 update()
{
bool32 result = frame();
return result;
}
+1
View File
@@ -1,3 +1,4 @@
#pragma once
internal void main_thread_core_entry_point(int argc, char** argv);
internal bool32 update();
View File
Whitespace-only changes.
+1
View File
@@ -0,0 +1 @@
#pragma once
View File
Whitespace-only changes.
+1
View File
@@ -0,0 +1 @@
#pragma once
+5
View File
@@ -0,0 +1,5 @@
#include "render.c"
#if R_BACKEND == R_BACKEND_D3D12
# include "d3d12/render_d3d12.c"
#endif
+15
View File
@@ -0,0 +1,15 @@
#pragma once
#define R_BACKEND_D3D12 0
#if !defined(R_BACKEND)
# define R_BACKEND R_BACKEND_D3D12
#endif
#include "render.h"
#if R_BACKEND == R_BACKEND_D3D12
# include "d3d12/render_d3d12.h"
#else
# error Renderer backend non specified
#endif
+23
View File
@@ -6,6 +6,20 @@ typedef HRESULT W32_SetThreadDescription_Type(HANDLE hThread, PCWSTR lpThreadDes
W32_KERNEL32_EXT_X_LIST
#undef X
// =============================================================================
// Time functions
internal uint64 now_time_us()
{
uint64 result = 0;
LARGE_INTEGER large_int_counter;
if (QueryPerformanceCounter(&large_int_counter))
{
result = (large_int_counter.QuadPart * Million(1)) / w32_state.microsecond_resolution;
}
return result;
}
// =============================================================================
// System
@@ -133,6 +147,15 @@ internal void w32_entry_point(int argc, WCHAR** wargv)
SYSTEM_INFO sys_info = { 0 };
GetSystemInfo(&sys_info);
{
w32_state.microsecond_resolution = 1;
LARGE_INTEGER large_int_resolution;
if (QueryPerformanceCounter(&large_int_resolution))
{
w32_state.microsecond_resolution = large_int_resolution.QuadPart;
}
}
SystemInfo* info = &w32_state.system_info;
info->page_size = sys_info.dwPageSize;
info->large_page_size = GetLargePageMinimum();
+5
View File
@@ -1,13 +1,18 @@
#pragma once
// clang-format off
#include <windows.h>
#include <windowsx.h>
#pragma comment(lib, "user32")
// clang-format on
typedef struct W32_State W32_State;
struct W32_State
{
Arena* arena;
SystemInfo system_info;
uint64 microsecond_resolution;
};
global W32_State w32_state = { 0 };
@@ -0,0 +1,186 @@
// Windows SDK function than can be missing
typedef BOOL w32_SetProcessDpiAwarenessContext_Type(void* value);
typedef UINT w32_GetDpiForWindow_Type(HWND hwnd);
typedef HRESULT w32_GetDpiForMonitor_Type(HMONITOR hmonitor, MONITOR_DPI_TYPE dpiType, UINT* dpiX, UINT* dpiY);
typedef int w32_GetSystemMetricsForDpi_Type(int nIndex, UINT dpi);
#define w32_DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 ((void*)-4)
global w32_GetDpiForWindow_Type* w32_GetDpiForWindow_func = 0;
global w32_GetDpiForMonitor_Type* w32_GetDpiForMonitor_func = 0;
global w32_GetSystemMetricsForDpi_Type* w32_GetSystemMetricsForDpi_func = 0;
// =============================================================================
// Windows
internal WM_Window w32_wm_handle_from_window(W32_WM_Window* window)
{
WM_Window handle = { (uint64)window };
return handle;
}
internal W32_WM_Window* w32_wm_window_from_handle(WM_Window handle)
{
W32_WM_Window* window = (W32_WM_Window*)handle.handle[0];
return window;
}
internal W32_WM_Window* w32_wm_window_from_hwnd(HWND hwnd)
{
W32_WM_Window* result = 0;
for (W32_WM_Window* cw = w32_wm_state->first_window; cw; cw = cw->next)
{
if (cw->hwnd == hwnd)
{
result = cw;
break;
}
}
return result;
}
internal WM_Event* w32_wm_push_event(WM_EventKind kind, W32_WM_Window* window)
{
WM_Event* result = 0;
result->window = w32_wm_handle_from_window(window);
result->modifiers = wm_get_modifiers();
return result;
}
internal LRESULT w32_wm_wnd_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LRESULT result = 0;
bool32 good = 1;
if (w32_wm_event_arena == 0)
{
result = DefWindowProcW(hwnd, uMsg, wParam, lParam);
good = 0;
}
if (good)
{
W32_WM_Window* window = w32_wm_window_from_hwnd(hwnd);
WM_Window window_handle = w32_wm_handle_from_window(window);
bool32 release = 0;
switch (uMsg)
{
default:
{
result = DefWindowProcW(hwnd, uMsg, wParam, lParam);
break;
}
case WM_ENTERSIZEMOVE:
{
w32_wm_resizing = 1;
break;
}
case WM_EXITSIZEMOVE:
{
w32_wm_resizing = 0;
break;
}
case WM_SIZE:
case WM_PAINT:
{
PAINTSTRUCT ps = { 0 };
BeginPaint(hwnd, &ps);
update();
EndPaint(hwnd, &ps);
DwmFlush();
break;
}
case WM_CLOSE:
{
w32_wm_push_event(WM_EventKind_WindowClose, window);
break;
}
}
}
return result;
}
internal void wm_init()
{
// Setup based state
Arena* arena = arena_alloc();
w32_wm_state = push_array(arena, W32_WM_State, 1);
w32_wm_state->arena = arena;
w32_wm_state->gfx_thread_tid = (uint32)GetCurrentThreadId();
w32_wm_state->hIstance = GetModuleHandle(0);
// Set dpi awareness
w32_SetProcessDpiAwarenessContext_Type* SetProcessDpiAwarenessContext_func = 0;
HMODULE module = LoadLibraryA("user32.dll");
if (module != 0)
{
SetProcessDpiAwarenessContext_func =
(w32_SetProcessDpiAwarenessContext_Type*)GetProcAddress(module, "SetProcessDpiAwarenessContext");
w32_GetDpiForWindow_func = (w32_GetDpiForWindow_Type*)GetProcAddress(module, "GetDpiForWindow");
w32_GetDpiForMonitor_func = (w32_GetDpiForMonitor_Type*)GetProcAddress(module, "GetDpiForMonitor");
w32_GetSystemMetricsForDpi_func =
(w32_GetSystemMetricsForDpi_Type*)GetProcAddress(module, "GetSystemMetricsForDpi");
FreeLibrary(module);
}
if (SetProcessDpiAwarenessContext_func != 0)
{
SetProcessDpiAwarenessContext_func(w32_DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
}
else
{
HMODULE shcore = LoadLibraryA("shcore.dll");
if (shcore)
{
typedef HRESULT(WINAPI * SetProcessDpiAwareness_t)(int);
SetProcessDpiAwareness_t SetProcessDpiAwareness = (void*)GetProcAddress(shcore, "SetProcessDpiAwareness");
if (SetProcessDpiAwareness)
{
SetProcessDpiAwareness(2);
}
FreeLibrary(shcore);
}
SetProcessDPIAware();
}
// Window class
{
WNDCLASSEXW wndclass = { sizeof(wndclass) };
wndclass.lpfnWndProc = w32_wm_wnd_proc;
wndclass.hInstance = w32_wm_state->hIstance;
wndclass.lpszClassName = L"juliet-window";
wndclass.hCursor = LoadCursorA(0, IDC_ARROW);
wndclass.hIcon = LoadIcon(w32_wm_state->hIstance, MAKEINTRESOURCE(1));
wndclass.style = CS_VREDRAW | CS_HREDRAW;
ATOM wndatom = RegisterClassExW(&wndclass);
(void)wndatom;
}
// Get gfx system info
w32_wm_state->gfx_info.double_click_time = GetDoubleClickTime() / 1000.f;
w32_wm_state->gfx_info.caret_blink_time = GetCaretBlinkTime() / 1000.f;
DEVMODEW devmodew = { 0 };
if (EnumDisplaySettingsW(0, ENUM_CURRENT_SETTINGS, &devmodew))
{
w32_wm_state->gfx_info.default_refresh_rate = (float32)devmodew.dmDisplayFrequency;
}
}
internal WM_Modifiers wm_get_modifiers()
{
WM_Modifiers modifiers = 0;
if (GetKeyState(VK_CONTROL) * 0x8000)
{
modifiers |= WM_Modifier_Ctrl;
}
if (GetKeyState(VK_SHIFT) * 0x8000)
{
modifiers |= WM_Modifier_Shift;
}
if (GetKeyState(VK_MENU) * 0x8000)
{
modifiers |= WM_Modifier_Alt;
}
return modifiers;
}
@@ -0,0 +1,54 @@
#pragma once
// clang-format off
#include <dwmapi.h>
#include <shellscalingapi.h>
#pragma comment(lib, "dwmapi")
// clang-format on
// =============================================================================
// Windows Type
typedef struct W32_WM_Window W32_WM_Window;
struct W32_WM_Window
{
W32_WM_Window* next;
W32_WM_Window* previous;
HWND hwnd;
HDC hdc;
WINDOWPLACEMENT last_window_placement;
float32 dpi;
};
// =============================================================================
// Windows Global State
typedef struct W32_WM_State W32_WM_State;
struct W32_WM_State
{
Arena* arena;
uint32 gfx_thread_tid;
HINSTANCE hIstance;
HCURSOR hCursor;
WM_SystemInfo gfx_info;
W32_WM_Window* first_window;
W32_WM_Window* last_window;
W32_WM_Window* free_window;
WM_Key key_from_vkey_table[256];
};
// =============================================================================
// Globals
global W32_WM_State* w32_wm_state = 0;
global WM_EventList w32_wm_event_list = { 0 };
global Arena* w32_wm_event_arena = 0;
global bool32 w32_wm_resizing = 0;
// =============================================================================
// Windows
internal WM_Window w32_wm_handle_from_window(W32_WM_Window* window);
internal W32_WM_Window* w32_wm_window_from_handle(WM_Window handle);
internal W32_WM_Window* w32_wm_window_from_hwnd(HWND hwnd);
internal WM_Event* w32_wm_push_event(WM_EventKind kind, W32_WM_Window* window);
+12
View File
@@ -0,0 +1,12 @@
// =============================================================================
// Event Functions
internal WM_Event* wm_event_list_push_new(Arena* arena, WM_EventList* events, WM_EventKind kind)
{
WM_Event* evt = push_array(arena, WM_Event, 1);
DLL_push_back(events->first, events->last, evt);
events->count += 1;
evt->timestamp_us = now_time_us();
evt->kind = kind;
return evt;
}
+102
View File
@@ -0,0 +1,102 @@
#pragma once
// =============================================================================
// System Types
typedef struct WM_SystemInfo WM_SystemInfo;
struct WM_SystemInfo
{
float32 double_click_time;
float32 caret_blink_time;
float32 default_refresh_rate;
};
// =============================================================================
// Window Types
typedef struct WM_Window WM_Window;
struct WM_Window
{
uint64 handle[1];
};
// =============================================================================
// Monitor Types
typedef struct WM_Monitor WM_Monitor;
struct WM_Monitor
{
uint64 handle[1];
};
typedef struct WM_MonitorArray WM_MonitorArray;
struct WM_MonitorArray
{
WM_Monitor* ptr;
uint64 count;
};
#include "window_manager_key.h"
// =============================================================================
// Event Types
typedef enum WM_EventKind
{
WM_EventKind_Null,
WM_EventKind_Press,
WM_EventKind_Release,
WM_EventKind_MouseMove,
WM_EventKind_WindowClose,
WM_EventKind_COUNT
} WM_EventKind;
typedef uint32 WM_Modifiers;
enum
{
WM_Modifier_Ctrl = (1 << 0),
WM_Modifier_Shift = (1 << 1),
WM_Modifier_Alt = (1 << 2),
};
typedef struct WM_Event WM_Event;
struct WM_Event
{
WM_Event* next;
WM_Event* previous;
uint64 timestamp_us;
WM_Window window;
WM_EventKind kind;
WM_Modifiers modifiers;
WM_Key key;
};
typedef struct WM_EventList WM_EventList;
struct WM_EventList
{
uint64 count;
WM_Event* first;
WM_Event* last;
};
// =============================================================================
// Application defined frame hook
internal bool32 frame();
// =============================================================================
// Event Functions
internal WM_Event* wm_event_list_push_new(Arena* arena, WM_EventList* events, WM_EventKind kind);
// =============================================================================
// Windows Management Functions
// =============================================================================
// Main Initialization API
internal void wm_init();
// =============================================================================
// Events
internal WM_Modifiers wm_get_modifiers();
@@ -0,0 +1,7 @@
#include "window_manager.c"
#if OS_WINDOWS
# include "win32/window_manager/window_manager.c"
#else
# error No window manager for this operating system
#endif
@@ -0,0 +1,10 @@
#pragma once
#include "window_manager.h"
#include "window_manager_key.h"
#if OS_WINDOWS
# include "win32/window_manager/window_manager.h"
#else
# error No Window manager for this operating system
#endif
+149
View File
@@ -0,0 +1,149 @@
#pragma once
typedef enum WM_Key
{
WM_Key_Null,
WM_Key_Esc,
WM_Key_F1,
WM_Key_F2,
WM_Key_F3,
WM_Key_F4,
WM_Key_F5,
WM_Key_F6,
WM_Key_F7,
WM_Key_F8,
WM_Key_F9,
WM_Key_F10,
WM_Key_F11,
WM_Key_F12,
WM_Key_F13,
WM_Key_F14,
WM_Key_F15,
WM_Key_F16,
WM_Key_F17,
WM_Key_F18,
WM_Key_F19,
WM_Key_F20,
WM_Key_F21,
WM_Key_F22,
WM_Key_F23,
WM_Key_F24,
WM_Key_Tick,
WM_Key_0,
WM_Key_1,
WM_Key_2,
WM_Key_3,
WM_Key_4,
WM_Key_5,
WM_Key_6,
WM_Key_7,
WM_Key_8,
WM_Key_9,
WM_Key_Minus,
WM_Key_Equal,
WM_Key_Backspace,
WM_Key_Tab,
WM_Key_Q,
WM_Key_W,
WM_Key_E,
WM_Key_R,
WM_Key_T,
WM_Key_Y,
WM_Key_U,
WM_Key_I,
WM_Key_O,
WM_Key_P,
WM_Key_LeftBracket,
WM_Key_RightBracket,
WM_Key_BackSlash,
WM_Key_CapsLock,
WM_Key_A,
WM_Key_S,
WM_Key_D,
WM_Key_F,
WM_Key_G,
WM_Key_H,
WM_Key_J,
WM_Key_K,
WM_Key_L,
WM_Key_Semicolon,
WM_Key_Quote,
WM_Key_Return,
WM_Key_Shift,
WM_Key_Z,
WM_Key_X,
WM_Key_C,
WM_Key_V,
WM_Key_B,
WM_Key_N,
WM_Key_M,
WM_Key_Comma,
WM_Key_Period,
WM_Key_Slash,
WM_Key_Ctrl,
WM_Key_Alt,
WM_Key_Space,
WM_Key_Menu,
WM_Key_ScrollLock,
WM_Key_Pause,
WM_Key_Insert,
WM_Key_Home,
WM_Key_PageUp,
WM_Key_Delete,
WM_Key_End,
WM_Key_PageDown,
WM_Key_Up,
WM_Key_Left,
WM_Key_Down,
WM_Key_Right,
WM_Key_Ex0,
WM_Key_Ex1,
WM_Key_Ex2,
WM_Key_Ex3,
WM_Key_Ex4,
WM_Key_Ex5,
WM_Key_Ex6,
WM_Key_Ex7,
WM_Key_Ex8,
WM_Key_Ex9,
WM_Key_Ex10,
WM_Key_Ex11,
WM_Key_Ex12,
WM_Key_Ex13,
WM_Key_Ex14,
WM_Key_Ex15,
WM_Key_Ex16,
WM_Key_Ex17,
WM_Key_Ex18,
WM_Key_Ex19,
WM_Key_Ex20,
WM_Key_Ex21,
WM_Key_Ex22,
WM_Key_Ex23,
WM_Key_Ex24,
WM_Key_Ex25,
WM_Key_Ex26,
WM_Key_Ex27,
WM_Key_Ex28,
WM_Key_Ex29,
WM_Key_NumLock,
WM_Key_NumSlash,
WM_Key_NumStar,
WM_Key_NumMinus,
WM_Key_NumPlus,
WM_Key_NumPeriod,
WM_Key_Num0,
WM_Key_Num1,
WM_Key_Num2,
WM_Key_Num3,
WM_Key_Num4,
WM_Key_Num5,
WM_Key_Num6,
WM_Key_Num7,
WM_Key_Num8,
WM_Key_Num9,
WM_Key_LeftMouseButton,
WM_Key_MiddleMouseButton,
WM_Key_RightMouseButton,
WM_Key_COUNT,
} WM_Key;