diff --git a/Juliet/appbin/appbin_main.c b/Juliet/appbin/appbin_main.c index 14469e1..593c486 100644 --- a/Juliet/appbin/appbin_main.c +++ b/Juliet/appbin/appbin_main.c @@ -15,10 +15,26 @@ internal bool32 frame() { + { + TempArena scratch = scratch_begin(0, 0); + + WM_EventList events = { 0 }; + bool32 wait = 0; + events = wm_get_events(scratch.arena, wait); + + scratch_end(scratch); + } return 0; } internal void entry_point() { wm_init(); + + wm_window_open(rect2fp(50.f, 50.f, 1280.f, 720.f), 0, str8_literal("Hello")); + + for (bool32 quit = 0; !quit;) + { + quit = update(); + } } diff --git a/Juliet/core/core.h b/Juliet/core/core.h index e7a17c6..a40e637 100644 --- a/Juliet/core/core.h +++ b/Juliet/core/core.h @@ -11,6 +11,7 @@ #define internal static #define global static +#define local_persist static #if (COMPILER_CLANG && OS_WINDOWS) || COMPILER_MSVC # pragma section(".rdata$", read) @@ -76,6 +77,7 @@ #define MemorySet(dst, src, size) memset((dst), (src), (size)) #define MemoryZero(ptr, size) memset((ptr), 0, (size)) +#define MemoryZeroStruct(s) MemoryZero((s), sizeof(*(s))) // ============================================================================= // Asserts @@ -122,13 +124,20 @@ // clang-format on #define DLL_push_back_NPZ(nil, first, last, node, next, previous) \ DLL_insert_NPZ(nil, first, last, last, node, next, previous) +#define DLL_remove_NPZ(nil, first, last, node, next, previous) \ + (((node) == (first) ? (first) = (node)->next : (0)), ((node) == (last) ? (last) = (last)->previous : (0)), \ + (CheckNil(nil, (node)->previous) ? (0) : ((node)->previous->next = (node)->next)), \ + (CheckNil(nil, (node)->next) ? (0) : ((node)->next->previous = (node)->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); +#define SLL_stack_push(first, node) SLL_stack_push_node(first, node, next) +#define SLL_stack_pop(first) SLL_stack_pop_node(first, next) // Double linked list helpers #define DLL_push_back(first, last, node) DLL_push_back_NPZ(0, first, last, node, next, previous) +#define DLL_remove(first, last, node) DLL_remove_NPZ(0, first, last, node, next, previous) // ============================================================================= // Helpers diff --git a/Juliet/core/core_inc.c b/Juliet/core/core_inc.c index 85a2527..77b3b13 100644 --- a/Juliet/core/core_inc.c +++ b/Juliet/core/core_inc.c @@ -2,6 +2,7 @@ #include "core.c" #include "core_memory.c" #include "core_arena.c" +#include "core_math.c" #include "core_string.c" #include "core_system.c" #include "core_threads.c" diff --git a/Juliet/core/core_inc.h b/Juliet/core/core_inc.h index 1b3421b..75c0138 100644 --- a/Juliet/core/core_inc.h +++ b/Juliet/core/core_inc.h @@ -7,6 +7,7 @@ #include "core_memory.h" #include "core_processes.h" #include "core_arena.h" +#include "core_math.h" #include "core_string.h" #include "core_system.h" #include "core_threads.h" diff --git a/Juliet/core/core_math.c b/Juliet/core/core_math.c new file mode 100644 index 0000000..dd83b17 --- /dev/null +++ b/Juliet/core/core_math.c @@ -0,0 +1,33 @@ +// ============================================================================= +// Functions + +// ============================================================================= +// Vectors + +internal Vector2f vector_2f(float32 x, float32 y) +{ + Vector2f v = { x, y }; + return v; +} + +// ============================================================================= +// Rectangles + +internal Rect2f rect_2f(Vector2f min, Vector2f max) +{ + Rect2f rect = { min, max }; + return rect; +} + +internal bool32 contains_2f(Rect2f rect, Vector2f x) +{ + bool32 cond = (rect.min.x <= x.x && x.x < rect.max.x && rect.min.y <= x.y && x.y < rect.max.y); + return cond; +} + +internal Vector2f dimension_2f(Rect2f rect) +{ + Vector2f dim = { ((rect.max.x > rect.min.x) ? (rect.max.x - rect.min.x) : 0), + ((rect.max.y > rect.min.y) ? (rect.max.y - rect.min.y) : 0) }; + return dim; +} diff --git a/Juliet/core/core_math.h b/Juliet/core/core_math.h new file mode 100644 index 0000000..7c5d9dc --- /dev/null +++ b/Juliet/core/core_math.h @@ -0,0 +1,59 @@ +#pragma once + +// ============================================================================= +// Vector Types + +typedef union Vector2f Vector2f; +union Vector2f +{ + struct + { + float32 x; + float32 y; + }; + float32 v[2]; +}; + +// ============================================================================= +// Rect Types + +typedef union Rect2f Rect2f; +union Rect2f +{ + struct + { + Vector2f min; + Vector2f max; + }; + struct + { + Vector2f p0; + Vector2f p1; + }; + struct + { + float32 x0; + float32 y0; + float32 x1; + float32 y1; + }; + Vector2f v[2]; +}; + +// ============================================================================= +// Functions + +// ============================================================================= +// Vectors + +#define vector2f(x, y) vector_2f((x), (y)) +internal Vector2f vector_2f(float32 x, float32 y); + +// ============================================================================= +// Rectangles + +#define rect2f(min, max) rect_2f((min), (max)) +#define rect2fp(x, y, z, w) rect2f(vector2f((x), (y)), vector2f((z), (w))) +internal Rect2f rect_2f(Vector2f min, Vector2f max); +internal bool32 contains_2f(Rect2f rect, Vector2f x); +internal Vector2f dimension_2f(Rect2f rect); diff --git a/Juliet/core/core_string.h b/Juliet/core/core_string.h index 48e52ad..c41cfb6 100644 --- a/Juliet/core/core_string.h +++ b/Juliet/core/core_string.h @@ -43,6 +43,7 @@ internal uint64 cstring32_length(uint32* cstring); // ========================================================================== // // String Constructor +#define str8_literal(S) str8((uint8*)(S), sizeof(S) - 1) internal String8 str8(uint8* str, uint64 size); internal String8 str8_zero(); internal String16 str16(uint16* str, uint64 size); diff --git a/Juliet/win32/core/win32_core.h b/Juliet/win32/core/win32_core.h index c5083f4..e50e6c7 100644 --- a/Juliet/win32/core/win32_core.h +++ b/Juliet/win32/core/win32_core.h @@ -4,6 +4,7 @@ #include #include #pragma comment(lib, "user32") +#pragma comment(lib, "shell32") // clang-format on typedef struct W32_State W32_State; diff --git a/Juliet/win32/window_manager/window_manager.c b/Juliet/win32/window_manager/window_manager.c index a841a81..371c6e9 100644 --- a/Juliet/win32/window_manager/window_manager.c +++ b/Juliet/win32/window_manager/window_manager.c @@ -8,6 +8,19 @@ global w32_GetDpiForWindow_Type* w32_GetDpiForWindow_func = 0; global w32_GetDpiForMonitor_Type* w32_GetDpiForMonitor_func = 0; global w32_GetSystemMetricsForDpi_Type* w32_GetSystemMetricsForDpi_func = 0; +// ============================================================================= +// Helpers + +internal Rect2f w32_wm_rect2f_from_rect(RECT rect) +{ + Rect2f result = { 0 }; + result.x0 = (float32)rect.left; + result.x1 = (float32)rect.right; + result.y0 = (float32)rect.top; + result.y1 = (float32)rect.bottom; + return result; +} + // ============================================================================= // Windows @@ -37,6 +50,47 @@ internal W32_WM_Window* w32_wm_window_from_hwnd(HWND hwnd) return result; } +internal HWND w32_wm_hwnd_from_window(W32_WM_Window* window) +{ + return window->hwnd; +} + +internal W32_WM_Window* w32_wm_window_alloc(HWND hwnd) +{ + W32_WM_Window* result = w32_wm_state->free_window; + if (result) + { + SLL_stack_pop(w32_wm_state->free_window); + } + else + { + result = push_array_no_zero(w32_wm_state->arena, W32_WM_Window, 1); + } + MemoryZeroStruct(result); + if (result) + { + DLL_push_back(w32_wm_state->first_window, w32_wm_state->last_window, result); + } + result->last_window_placement.length = sizeof(WINDOWPLACEMENT); + + result->hwnd = hwnd; + result->hdc = GetDC(hwnd); + + return result; +} + +internal void w32_wm_window_release(W32_WM_Window* window) +{ + if (window->paint_arena != 0) + { + arena_release(window->paint_arena); + } + ReleaseDC(window->hwnd, window->hdc); + DestroyWindow(window->hwnd); + DLL_remove(w32_wm_state->first_window, w32_wm_state->last_window, window); + SLL_stack_push(w32_wm_state->free_window, window); +} + internal WM_Event* w32_wm_push_event(WM_EventKind kind, W32_WM_Window* window) { WM_Event* result = 0; @@ -94,6 +148,85 @@ internal LRESULT w32_wm_wnd_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lPa case WM_CLOSE: { w32_wm_push_event(WM_EventKind_WindowClose, window); + wm_send_wakeup_event(); + break; + } + + case WM_SETCURSOR: + { + Rect2f window_rect = wm_client_rect_from_window(window_handle); + Vector2f mouse = wm_mouse_from_window(window_handle); + bool32 on_border = 0; + DWORD window_style = window ? GetWindowLong(window->hwnd, GWL_STYLE) : 0; + bool32 is_fullscreen = !(window_style & WS_OVERLAPPEDWINDOW); + if (window != 0 && window->custom_border && !is_fullscreen) + { + bool32 on_border_x = (mouse.x <= window->custom_border_edge_thickness || + window_rect.x1 - window->custom_border_edge_thickness <= mouse.x); + bool32 on_border_y = (mouse.y <= window->custom_border_edge_thickness || + window_rect.y1 - window->custom_border_edge_thickness <= mouse.y); + on_border = on_border_x || on_border_y; + } + if (!w32_wm_resizing && !on_border && contains_2f(window_rect, mouse)) + { + SetCursor(w32_wm_state->hCursor); + } + else + { + result = DefWindowProcW(hwnd, uMsg, wParam, lParam); + } + break; + } + + case WM_DPICHANGED: + { + float32 new_dpi = (float32)(wParam & 0xFFFF); + RECT suggested_new_rect = *(RECT*)lParam; + window->dpi = new_dpi; + SetWindowPos(window->hwnd, 0, suggested_new_rect.left, suggested_new_rect.top, + suggested_new_rect.right - suggested_new_rect.left, + suggested_new_rect.bottom - suggested_new_rect.top, 0); + break; + } + + case WM_NCPAINT: + { + if (w32_wm_new_window_custom_border || (window != 0 && window->custom_border && !window->custom_border_composition_enabled)) + { + result = 0; + } + else + { + result = DefWindowProcW(hwnd, uMsg, wParam, lParam); + } + break; + } + + case WM_DWMCOMPOSITIONCHANGED: + { + if (window != 0 && window->custom_border) + { + BOOL enabled = 0; + DwmIsCompositionEnabled(&enabled); + window->custom_border_composition_enabled = enabled; + if (enabled) + { + MARGINS m = { 0, 0, 1, 0 }; + DwmExtendFrameIntoClientArea(hwnd, &m); + DWORD dwmncrp_enabled = DWMNCRP_ENABLED; + DwmSetWindowAttribute(hwnd, DWMWA_NCRENDERING_POLICY, &enabled, sizeof(dwmncrp_enabled)); + } + } + else + { + result = DefWindowProcW(hwnd, uMsg, wParam, lParam); + } + break; + } + + case WM_WINDOWPOSCHANGED: + { + result = 0; break; } } @@ -165,6 +298,207 @@ internal void wm_init() { w32_wm_state->gfx_info.default_refresh_rate = (float32)devmodew.dmDisplayFrequency; } + + // initial cursor + wm_set_cursor(WM_Cursor_Pointer); + + // fill the vkey to wmKey table + w32_wm_state->key_from_vkey_table[(unsigned int)'A'] = WM_Key_A; + w32_wm_state->key_from_vkey_table[(unsigned int)'B'] = WM_Key_B; + w32_wm_state->key_from_vkey_table[(unsigned int)'C'] = WM_Key_C; + w32_wm_state->key_from_vkey_table[(unsigned int)'D'] = WM_Key_D; + w32_wm_state->key_from_vkey_table[(unsigned int)'E'] = WM_Key_E; + w32_wm_state->key_from_vkey_table[(unsigned int)'F'] = WM_Key_F; + w32_wm_state->key_from_vkey_table[(unsigned int)'G'] = WM_Key_G; + w32_wm_state->key_from_vkey_table[(unsigned int)'H'] = WM_Key_H; + w32_wm_state->key_from_vkey_table[(unsigned int)'I'] = WM_Key_I; + w32_wm_state->key_from_vkey_table[(unsigned int)'J'] = WM_Key_J; + w32_wm_state->key_from_vkey_table[(unsigned int)'K'] = WM_Key_K; + w32_wm_state->key_from_vkey_table[(unsigned int)'L'] = WM_Key_L; + w32_wm_state->key_from_vkey_table[(unsigned int)'M'] = WM_Key_M; + w32_wm_state->key_from_vkey_table[(unsigned int)'N'] = WM_Key_N; + w32_wm_state->key_from_vkey_table[(unsigned int)'O'] = WM_Key_O; + w32_wm_state->key_from_vkey_table[(unsigned int)'P'] = WM_Key_P; + w32_wm_state->key_from_vkey_table[(unsigned int)'Q'] = WM_Key_Q; + w32_wm_state->key_from_vkey_table[(unsigned int)'R'] = WM_Key_R; + w32_wm_state->key_from_vkey_table[(unsigned int)'S'] = WM_Key_S; + w32_wm_state->key_from_vkey_table[(unsigned int)'T'] = WM_Key_T; + w32_wm_state->key_from_vkey_table[(unsigned int)'U'] = WM_Key_U; + w32_wm_state->key_from_vkey_table[(unsigned int)'V'] = WM_Key_V; + w32_wm_state->key_from_vkey_table[(unsigned int)'W'] = WM_Key_W; + w32_wm_state->key_from_vkey_table[(unsigned int)'X'] = WM_Key_X; + w32_wm_state->key_from_vkey_table[(unsigned int)'Y'] = WM_Key_Y; + w32_wm_state->key_from_vkey_table[(unsigned int)'Z'] = WM_Key_Z; + + // Num + for (uint64 i = '0', j = WM_Key_0; i <= '9'; ++i, ++j) + { + w32_wm_state->key_from_vkey_table[i] = (WM_Key)j; + } + // Numpad num + for (uint64 i = VK_NUMPAD0, j = WM_Key_Num0; i <= VK_NUMPAD9; ++i, ++j) + { + w32_wm_state->key_from_vkey_table[i] = (WM_Key)j; + } + // F1-24 + for (uint64 i = VK_F1, j = WM_Key_F1; i <= VK_F24; ++i, ++j) + { + w32_wm_state->key_from_vkey_table[i] = (WM_Key)j; + } + + // Other keys + w32_wm_state->key_from_vkey_table[VK_SPACE] = WM_Key_Space; + w32_wm_state->key_from_vkey_table[VK_OEM_3] = WM_Key_Tick; + w32_wm_state->key_from_vkey_table[VK_OEM_MINUS] = WM_Key_Minus; + w32_wm_state->key_from_vkey_table[VK_OEM_PLUS] = WM_Key_Equal; + w32_wm_state->key_from_vkey_table[VK_OEM_4] = WM_Key_LeftBracket; + w32_wm_state->key_from_vkey_table[VK_OEM_6] = WM_Key_RightBracket; + w32_wm_state->key_from_vkey_table[VK_OEM_1] = WM_Key_Semicolon; + w32_wm_state->key_from_vkey_table[VK_OEM_7] = WM_Key_Quote; + w32_wm_state->key_from_vkey_table[VK_OEM_COMMA] = WM_Key_Comma; + w32_wm_state->key_from_vkey_table[VK_OEM_PERIOD] = WM_Key_Period; + w32_wm_state->key_from_vkey_table[VK_OEM_2] = WM_Key_Slash; + w32_wm_state->key_from_vkey_table[VK_OEM_5] = WM_Key_BackSlash; + + w32_wm_state->key_from_vkey_table[VK_TAB] = WM_Key_Tab; + w32_wm_state->key_from_vkey_table[VK_PAUSE] = WM_Key_Pause; + w32_wm_state->key_from_vkey_table[VK_ESCAPE] = WM_Key_Esc; + + w32_wm_state->key_from_vkey_table[VK_UP] = WM_Key_Up; + w32_wm_state->key_from_vkey_table[VK_LEFT] = WM_Key_Left; + w32_wm_state->key_from_vkey_table[VK_DOWN] = WM_Key_Down; + w32_wm_state->key_from_vkey_table[VK_RIGHT] = WM_Key_Right; + + w32_wm_state->key_from_vkey_table[VK_BACK] = WM_Key_Backspace; + w32_wm_state->key_from_vkey_table[VK_RETURN] = WM_Key_Return; + + w32_wm_state->key_from_vkey_table[VK_DELETE] = WM_Key_Delete; + w32_wm_state->key_from_vkey_table[VK_INSERT] = WM_Key_Insert; + w32_wm_state->key_from_vkey_table[VK_PRIOR] = WM_Key_PageUp; + w32_wm_state->key_from_vkey_table[VK_NEXT] = WM_Key_PageDown; + w32_wm_state->key_from_vkey_table[VK_HOME] = WM_Key_Home; + w32_wm_state->key_from_vkey_table[VK_END] = WM_Key_End; + + w32_wm_state->key_from_vkey_table[VK_CAPITAL] = WM_Key_CapsLock; + w32_wm_state->key_from_vkey_table[VK_NUMLOCK] = WM_Key_NumLock; + w32_wm_state->key_from_vkey_table[VK_SCROLL] = WM_Key_ScrollLock; + w32_wm_state->key_from_vkey_table[VK_APPS] = WM_Key_Menu; + + w32_wm_state->key_from_vkey_table[VK_CONTROL] = WM_Key_Ctrl; + w32_wm_state->key_from_vkey_table[VK_LCONTROL] = WM_Key_Ctrl; + w32_wm_state->key_from_vkey_table[VK_RCONTROL] = WM_Key_Ctrl; + w32_wm_state->key_from_vkey_table[VK_SHIFT] = WM_Key_Shift; + w32_wm_state->key_from_vkey_table[VK_LSHIFT] = WM_Key_Shift; + w32_wm_state->key_from_vkey_table[VK_RSHIFT] = WM_Key_Shift; + w32_wm_state->key_from_vkey_table[VK_MENU] = WM_Key_Alt; + w32_wm_state->key_from_vkey_table[VK_LMENU] = WM_Key_Alt; + w32_wm_state->key_from_vkey_table[VK_RMENU] = WM_Key_Alt; + + w32_wm_state->key_from_vkey_table[VK_DIVIDE] = WM_Key_NumSlash; + w32_wm_state->key_from_vkey_table[VK_MULTIPLY] = WM_Key_NumStar; + w32_wm_state->key_from_vkey_table[VK_SUBTRACT] = WM_Key_NumMinus; + w32_wm_state->key_from_vkey_table[VK_ADD] = WM_Key_NumPlus; + w32_wm_state->key_from_vkey_table[VK_DECIMAL] = WM_Key_NumPeriod; + + for (uint64 i = 0xDF, j = 0; i < 0xFF; i += 1, j += 1) + { + w32_wm_state->key_from_vkey_table[i] = (WM_Key)((uint64)WM_Key_Ex0 + j); + } +} + +// ============================================================================= +// Windows + +internal WM_Window wm_window_open(Rect2f rect, WM_WindowFlags flags, String8 title) +{ + bool32 custom_border = !!(flags & WM_WindowFlag_CustomBorder); + bool32 use_default_position = !!(flags & WM_WindowFlag_UseDefaultPosition); + Vector2f position = rect.p0; + Vector2f dimension = dimension_2f(rect); + + HWND hwnd = 0; + { + TempArena scratch = scratch_begin(0, 0); + String16 titel16 = str16_from_8(scratch.arena, title); + w32_wm_new_window_custom_border = custom_border; + DWORD style_flags = WS_EX_APPWINDOW; + hwnd = CreateWindowExW(style_flags, L"juliet-window", (WCHAR*)titel16.str, WS_OVERLAPPEDWINDOW | WS_SIZEBOX, + use_default_position ? CW_USEDEFAULT : (int32)position.x, + use_default_position ? CW_USEDEFAULT : (int32)position.y, (int32)dimension.x, + (int32)dimension.y, 0, 0, w32_wm_state->hIstance, 0); + DragAcceptFiles(hwnd, 1); + w32_wm_new_window_custom_border = 0; + scratch_end(scratch); + } + + W32_WM_Window* window = w32_wm_window_alloc(hwnd); + { + if (w32_GetDpiForWindow_func != 0) + { + window->dpi = (float32)w32_GetDpiForWindow_func(hwnd); + } + else + { + window->dpi = 96.f; + } + } + + { + BOOL enabled = 0; + DwmIsCompositionEnabled(&enabled); + window->custom_border_composition_enabled = enabled; + } + + if (flags & WM_WindowFlag_CustomBorder) + { + window->custom_border = 1; + window->paint_arena = arena_alloc(); + } + + WM_Window result = w32_wm_handle_from_window(window); + return result; +} + +internal Rect2f wm_client_rect_from_window(WM_Window handle) +{ + Rect2f result = { 0 }; + W32_WM_Window* window = w32_wm_window_from_handle(handle); + if (window) + { + RECT rect = { 0 }; + GetClientRect(w32_wm_hwnd_from_window(window), &rect); + result = w32_wm_rect2f_from_rect(rect); + } + return result; +} + +// ============================================================================= +// Events + +internal void wm_send_wakeup_event() +{ + PostThreadMessageW(w32_wm_state->gfx_thread_tid, 0x401, 0, 0); +} + +internal WM_EventList wm_get_events(Arena* arena, bool32 wait) +{ + w32_wm_event_arena = arena; + MemoryZeroStruct(&w32_wm_event_list); + MSG msg = { 0 }; + if (!wait || GetMessageW(&msg, 0, 0, 0)) + { + bool32 first_wait = wait; + for (; first_wait || PeekMessageW(&msg, 0, 0, 0, PM_REMOVE); first_wait = 0) + { + TranslateMessage(&msg); + DispatchMessageW(&msg); + if (msg.message == WM_QUIT) + { + w32_wm_push_event(WM_EventKind_WindowClose, 0); + } + } + } + return w32_wm_event_list; } internal WM_Modifiers wm_get_modifiers() @@ -184,3 +518,60 @@ internal WM_Modifiers wm_get_modifiers() } return modifiers; } + +internal Vector2f wm_mouse_from_window(WM_Window handle) +{ + Vector2f result = { 0 }; + POINT p; + if (GetCursorPos(&p)) + { + W32_WM_Window* window = w32_wm_window_from_handle(handle); + ScreenToClient(window->hwnd, &p); + result.x = (float32)p.x; + result.y = (float32)p.y; + } + return result; +} + +// ============================================================================= +// Cursors + +internal void wm_set_cursor(WM_Cursor cursor) +{ + bool32 valid_cursor = 1; + HCURSOR hcursor = 0; + switch (cursor) + { + default: + { + valid_cursor = 0; + break; + }; +#define WIN32_CURSOR_X_LIST(X) X(Pointer, IDC_ARROW) +#define CURSOR_CASE(Entry, IDC) \ + case WM_Cursor_##Entry: \ + { \ + local_persist HCURSOR curs = 0; \ + if (curs == 0) \ + { \ + curs = LoadCursor(NULL, IDC); \ + } \ + hcursor = curs; \ + break; \ + } + WIN32_CURSOR_X_LIST(CURSOR_CASE) +#undef CURSOR_CASE +#undef WIN32_CURSOR_X_LIST + } + if (valid_cursor && !w32_wm_resizing) + { + if (hcursor != w32_wm_state->hCursor) + { + PostMessageW(0, WM_SETCURSOR, 0, 0); + POINT p = { 0 }; + GetCursorPos(&p); + SetCursorPos(p.x, p.y); + } + w32_wm_state->hCursor = hcursor; + } +} diff --git a/Juliet/win32/window_manager/window_manager.h b/Juliet/win32/window_manager/window_manager.h index ba90d50..e2afbc6 100644 --- a/Juliet/win32/window_manager/window_manager.h +++ b/Juliet/win32/window_manager/window_manager.h @@ -18,6 +18,11 @@ struct W32_WM_Window HDC hdc; WINDOWPLACEMENT last_window_placement; float32 dpi; + bool32 custom_border; + float32 custom_border_title_thickness; + float32 custom_border_edge_thickness; + bool32 custom_border_composition_enabled; + Arena* paint_arena; }; // ============================================================================= @@ -40,10 +45,16 @@ struct W32_WM_State // ============================================================================= // 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; +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; +global bool32 w32_wm_new_window_custom_border = 0; + +// ============================================================================= +// Helpers + +internal Rect2f w32_wm_rect2f_from_rect(RECT rect); // ============================================================================= // Windows @@ -51,4 +62,7 @@ global bool32 w32_wm_resizing = 0; 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 HWND w32_wm_hwnd_from_window(W32_WM_Window* window); +internal W32_WM_Window* w32_wm_window_alloc(HWND hwnd); internal WM_Event* w32_wm_push_event(WM_EventKind kind, W32_WM_Window* window); +internal void w32_wm_window_release(W32_WM_Window* window); diff --git a/Juliet/window_manager/window_manager.h b/Juliet/window_manager/window_manager.h index bf100be..96b6004 100644 --- a/Juliet/window_manager/window_manager.h +++ b/Juliet/window_manager/window_manager.h @@ -14,6 +14,13 @@ struct WM_SystemInfo // ============================================================================= // Window Types +typedef uint32 WM_WindowFlags; +enum +{ + WM_WindowFlag_CustomBorder = (1 << 0), + WM_WindowFlag_UseDefaultPosition = (1 << 1), +}; + typedef struct WM_Window WM_Window; struct WM_Window { @@ -38,6 +45,14 @@ struct WM_MonitorArray #include "window_manager_key.h" +// ============================================================================= +// Curosr Types +typedef enum WM_Cursor +{ + WM_Cursor_Pointer, + WM_Cursor_COUNT +} WM_Cursor; + // ============================================================================= // Event Types @@ -96,7 +111,21 @@ internal WM_Event* wm_event_list_push_new(Arena* arena, WM_EventList* events, WM internal void wm_init(); +// ============================================================================= +// Windows + +internal WM_Window wm_widow_open(Rect2f rect, WM_WindowFlags flags, String8 title); +internal Rect2f wm_client_rect_from_window(WM_Window window); + // ============================================================================= // Events +internal void wm_send_wakeup_event(); +internal WM_EventList wm_get_events(Arena* arena, bool32 wait); internal WM_Modifiers wm_get_modifiers(); +internal Vector2f wm_mouse_from_window(WM_Window window); + +// ============================================================================= +// Cursors + +internal void wm_set_cursor(WM_Cursor cursor);