fix ui widgets

This commit is contained in:
2026-02-25 16:40:14 -05:00
parent 12dae774e4
commit 68235b57ce
6 changed files with 759 additions and 27 deletions

View File

@@ -3,6 +3,46 @@
#include <stdint.h>
#include <stdbool.h>
////////////////////////////////
// Input event buffer
// Accumulated per frame, consumed by the app each tick.
#define PLATFORM_MAX_CHARS_PER_FRAME 64
#define PLATFORM_MAX_KEYS_PER_FRAME 32
// Virtual key codes (subset matching Win32 VK_ codes)
enum {
PKEY_BACKSPACE = 0x08,
PKEY_TAB = 0x09,
PKEY_RETURN = 0x0D,
PKEY_ESCAPE = 0x1B,
PKEY_DELETE = 0x2E,
PKEY_LEFT = 0x25,
PKEY_UP = 0x26,
PKEY_RIGHT = 0x27,
PKEY_DOWN = 0x28,
PKEY_HOME = 0x24,
PKEY_END = 0x23,
PKEY_A = 0x41,
PKEY_C = 0x43,
PKEY_V = 0x56,
PKEY_X = 0x58,
};
struct PlatformInputEvents {
// Typed characters (UTF-16 code units, printable only)
uint16_t chars[PLATFORM_MAX_CHARS_PER_FRAME];
int32_t char_count;
// Key-down events (virtual key codes)
uint8_t keys[PLATFORM_MAX_KEYS_PER_FRAME];
int32_t key_count;
// Modifier state at time of last key event
bool ctrl_held;
bool shift_held;
};
struct PlatformWindow;
struct PlatformWindowDesc {
@@ -36,3 +76,6 @@ void *platform_get_native_handle(PlatformWindow *window);
void platform_set_frame_callback(PlatformWindow *window, PlatformFrameCallback cb, void *user_data);
void platform_set_menu(PlatformWindow *window, PlatformMenu *menus, int32_t menu_count);
int32_t platform_poll_menu_command(PlatformWindow *window);
// Returns accumulated input events since last call, then clears the buffer.
PlatformInputEvents platform_get_input_events(PlatformWindow *window);

View File

@@ -14,6 +14,7 @@ struct PlatformWindow {
int32_t pending_menu_cmd;
PlatformFrameCallback frame_callback;
void *frame_callback_user_data;
PlatformInputEvents input_events;
};
static PlatformWindow *g_current_window = nullptr;
@@ -31,10 +32,36 @@ static LRESULT CALLBACK win32_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM
}
}
return 0;
case WM_CHAR:
if (g_current_window && wparam >= 32 && wparam < 0xFFFF) {
PlatformInputEvents *ev = &g_current_window->input_events;
if (ev->char_count < PLATFORM_MAX_CHARS_PER_FRAME)
ev->chars[ev->char_count++] = (uint16_t)wparam;
}
return 0;
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
if (g_current_window) {
PlatformInputEvents *ev = &g_current_window->input_events;
if (ev->key_count < PLATFORM_MAX_KEYS_PER_FRAME)
ev->keys[ev->key_count++] = (uint8_t)wparam;
ev->ctrl_held = (GetKeyState(VK_CONTROL) & 0x8000) != 0;
ev->shift_held = (GetKeyState(VK_SHIFT) & 0x8000) != 0;
}
break; // fall through to DefWindowProc for system keys
case WM_COMMAND:
if (g_current_window && HIWORD(wparam) == 0)
g_current_window->pending_menu_cmd = (int32_t)LOWORD(wparam);
return 0;
case WM_SETCURSOR:
// When the cursor is in our client area, force it to an arrow.
// Without this, moving from a resize border back into the client
// area would leave the resize cursor shape stuck.
if (LOWORD(lparam) == HTCLIENT) {
SetCursor(LoadCursor(nullptr, IDC_ARROW));
return TRUE;
}
break;
case WM_CLOSE:
if (g_current_window)
g_current_window->should_close = true;
@@ -56,6 +83,7 @@ PlatformWindow *platform_create_window(PlatformWindowDesc *desc) {
wc.style = CS_CLASSDC;
wc.lpfnWndProc = win32_wndproc;
wc.hInstance = GetModuleHandleW(nullptr);
wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
wc.lpszClassName = L"autosample_wc";
RegisterClassExW(&wc);
@@ -172,3 +200,9 @@ int32_t platform_poll_menu_command(PlatformWindow *window) {
window->pending_menu_cmd = 0;
return cmd;
}
PlatformInputEvents platform_get_input_events(PlatformWindow *window) {
PlatformInputEvents result = window->input_events;
window->input_events = {};
return result;
}