major clean-up pass over unwinding/module-info abstraction, + usage in the debug engine. simplified / cleaned up DWARF helpers for unwind info & expressions. decoupling unwinding / DWARF evaluation from memory read callbacks. light module info now prepared by demon layer - debug engine no longer duplicates per-backend parsing. unwind abstraction layer now does thin abstraction over unwinding backends, debug engine only calls abstraction. clean up demon to have fewer ad-hoc 'queries' on handles, and prefer sending info over debug events when possible / when it fits the usage pattern. move DWARF enum specifications to metacode, generate enums/xlists/tables/etc. decouple raddbg/radbin completely from old parsing helpers. replace portion of DWARF dumping; pull out some new parsing helpers from converter / dumper.

This commit is contained in:
Ryan Fleury
2026-06-02 12:11:13 -07:00
parent 541d3afefa
commit d73ce364b9
88 changed files with 9899 additions and 4723 deletions
+1 -1
View File
@@ -276,7 +276,7 @@ commit_memory_large(void *ptr, U64 size)
}
////////////////////////////////
//~ rjf: @os_hooks Shared Memory
//~ rjf: @per_os_impl Shared Memory
internal SharedMemory
shared_memory_alloc(U64 size, String8 name)
+61 -41
View File
@@ -515,7 +515,6 @@ lnx_dmn_module_info_from_process_module(Arena *arena, pid_t pid, int memory_fd,
info->tls_index = tls_index;
info->tls_offset = tls_offset;
info->eh_frame_header_vaddr_range = eh_frame_header_vaddr_range;
info->cfi_rebase = module_rebase;
info->raddbg_info_voff_range = raddbg_info_voff_range;
info->raddbg_is_attached_marker_voff = raddbg_is_attached_marker_voff;
}
@@ -1016,6 +1015,7 @@ lnx_dmn_thread_alloc(LNX_DMN_Process *process, LNX_DMN_ThreadState thread_state,
thread->state = thread_state;
thread->process = process;
thread->reg_block = reg_block;
thread->dtv_base_vaddr = lnx_dmn_tls_root_vaddr_from_reg_block(process->fd, process->ctx->arch, reg_block);
if(thread_state == LNX_DMN_ThreadState_Stopped)
{
thread->is_reg_block_dirty = !lnx_dmn_thread_read_reg_block(thread);
@@ -1823,6 +1823,30 @@ lnx_dmn_set_single_step_flag(LNX_DMN_Thread *thread, B32 is_on)
return is_flag_set;
}
internal U64
lnx_dmn_tls_root_vaddr_from_reg_block(int fd, Arch arch, void *reg_block)
{
U64 result = 0;
switch(arch)
{
case Arch_x86:
case Arch_arm32:
case Arch_arm64:
case Arch_Null:
case Arch_COUNT:{}break;
case Arch_x64:
{
X64_RegBlock *reg_block_x64 = (X64_RegBlock *)reg_block;
U64 dtv_pointer = 0;
if(lnx_dmn_read_struct(fd, reg_block_x64->fsbase + 8, &dtv_pointer))
{
result = dtv_pointer;
}
}break;
}
return result;
}
internal void
lnx_dmn_thread_ptr_list_push_node(LNX_DMN_ThreadPtrList *list, LNX_DMN_ThreadPtrNode *n)
{
@@ -1896,6 +1920,8 @@ lnx_dmn_push_event_create_thread(Arena *arena, DMN_EventList *events, LNX_DMN_Th
e->thread = lnx_dmn_handle_from_thread(thread);
e->arch = thread->process->ctx->arch;
e->code = thread->tid;
// TODO(rjf): e->stack_pointer = ???;
e->tls_root_vaddr = thread->dtv_base_vaddr;
}
internal void
@@ -3239,46 +3265,6 @@ dmn_process_write(DMN_Handle process_handle, Rng1U64 range, void *src)
//- rjf: threads
internal U64
dmn_stack_base_vaddr_from_thread(DMN_Handle thread_handle)
{
return 0;
}
internal U64
dmn_tls_root_vaddr_from_thread(DMN_Handle thread_handle)
{
U64 tls_root_vaddr = max_U64;
DMN_AccessScope
{
LNX_DMN_Thread *thread = lnx_dmn_thread_from_handle(thread_handle);
if(thread)
{
switch(thread->process->ctx->arch)
{
case Arch_Null: {} break;
case Arch_x64:
{
X64_RegBlock *reg_block = thread->reg_block;
U64 dtv_pointer = 0;
if(lnx_dmn_read_struct(thread->process->fd, reg_block->fsbase + 8, &dtv_pointer))
{
tls_root_vaddr = dtv_pointer;
}
} break;
case Arch_x86:
case Arch_arm32:
case Arch_arm64:
{
NotImplemented;
} break;
default: { InvalidPath; } break;
}
}
}
return tls_root_vaddr;
}
internal B32
dmn_thread_read_reg_block(DMN_Handle thread_handle, void *reg_block)
{
@@ -3316,6 +3302,40 @@ dmn_thread_write_reg_block(DMN_Handle thread_handle, void *reg_block)
return result;
}
internal B32
dmn_thread_get_module_tls_vaddr(DMN_Handle thread_handle, DMN_Handle module_handle, U64 *vaddr_out)
{
B32 result = 0;
DMN_AccessScope
{
LNX_DMN_Thread *thread = lnx_dmn_thread_from_handle(thread_handle);
if(thread != 0)
{
LNX_DMN_Process *process = thread->process;
LNX_DMN_Module *module = lnx_dmn_module_from_handle(module_handle);
if(process != 0 && module != 0)
{
Arch arch = thread->process->ctx->arch;
U64 addr_size = byte_size_from_arch(arch);
U64 dtv_base_vaddr = thread->dtv_base_vaddr;
U64 dtv_entry_size = 2 * addr_size;
U64 module_dtv_ptr_vaddr = dtv_base_vaddr + module->tls_index * dtv_entry_size;
U64 module_dtv_vaddr = 0;
if(lnx_dmn_read(process->fd, r1u64(module_dtv_ptr_vaddr, module_dtv_ptr_vaddr+addr_size), &module_dtv_vaddr) == addr_size)
{
U64 unallocated_dtv_vaddr_marker = (addr_size == 4 ? max_U32 : max_U64);
if(module_dtv_vaddr != unallocated_dtv_vaddr_marker)
{
vaddr_out[0] = module_dtv_vaddr + module->tls_offset;
result = 1;
}
}
}
}
}
return result;
}
//- rjf: system process listing
internal void
+2
View File
@@ -176,6 +176,7 @@ typedef struct LNX_DMN_Thread
B32 pass_through_signal;
U64 pass_through_signo;
U64 orig_rax;
U64 dtv_base_vaddr;
struct LNX_DMN_Thread *next;
struct LNX_DMN_Thread *prev;
@@ -476,6 +477,7 @@ internal void lnx_dmn_thread_write_sp(LNX_DMN_Thread *thread, U64 sp);
internal B32 lnx_dmn_thread_read_reg_block(LNX_DMN_Thread *thread);
internal B32 lnx_dmn_thread_write_reg_block(LNX_DMN_Thread *thread);
internal B32 lnx_dmn_set_single_step_flag(LNX_DMN_Thread *thread, B32 is_on);
internal U64 lnx_dmn_tls_root_vaddr_from_reg_block(int fd, Arch arch, void *reg_block);
////////////////////////////////
//~ List Helpers
+201 -201
View File
@@ -20,7 +20,7 @@ lnx_window_from_x11window(Window window)
}
////////////////////////////////
//~ rjf: @os_hooks Main Initialization API (Implemented Per-OS)
//~ rjf: @per_os_impl Main Initialization API (Implemented Per-OS)
internal void
wm_init(void)
@@ -68,14 +68,14 @@ wm_init(void)
lnx_wm_state->cursors[map[idx].cursor] = XCreateFontCursor(lnx_wm_state->display, map[idx].id);
}
}
// create wakeup event for polling
lnx_wm_state->wakeup_fd = eventfd(0, EFD_CLOEXEC);
Assert(lnx_wm_state->wakeup_fd > 0);
}
////////////////////////////////
//~ rjf: @os_hooks Graphics System Info (Implemented Per-OS)
//~ rjf: @per_os_impl Graphics System Info (Implemented Per-OS)
internal WM_SystemInfo *
wm_get_system_info(void)
@@ -84,7 +84,7 @@ wm_get_system_info(void)
}
////////////////////////////////
//~ rjf: @os_hooks Clipboards (Implemented Per-OS)
//~ rjf: @per_os_impl Clipboards (Implemented Per-OS)
internal void
wm_set_clipboard_text(String8 string)
@@ -100,7 +100,7 @@ wm_get_clipboard_text(Arena *arena)
}
////////////////////////////////
//~ rjf: @os_hooks Windows (Implemented Per-OS)
//~ rjf: @per_os_impl Windows (Implemented Per-OS)
internal WM_Window
wm_window_open(Rng2F32 rect, WM_WindowFlags flags, String8 title)
@@ -342,7 +342,7 @@ wm_dpi_from_window(WM_Window handle)
}
////////////////////////////////
//~ rjf: @os_hooks External Windows (Implemented Per-OS)
//~ rjf: @per_os_impl External Windows (Implemented Per-OS)
internal WM_ExtWindow
wm_focused_external_window(void)
@@ -359,7 +359,7 @@ wm_focus_external_window(WM_ExtWindow handle)
}
////////////////////////////////
//~ rjf: @os_hooks Monitors (Implemented Per-OS)
//~ rjf: @per_os_impl Monitors (Implemented Per-OS)
internal WM_MonitorArray
wm_push_monitors_array(Arena *arena)
@@ -407,7 +407,7 @@ wm_dpi_from_monitor(WM_Monitor monitor)
}
////////////////////////////////
//~ rjf: @os_hooks Events (Implemented Per-OS)
//~ rjf: @per_os_impl Events (Implemented Per-OS)
internal void
wm_send_wakeup_event(void)
@@ -448,210 +448,210 @@ wm_get_events(Arena *arena, B32 wait)
switch(evt.type)
{
default:{}break;
//- rjf: key presses/releases
case KeyPress:
case KeyRelease:
{
// rjf: determine flags
WM_Modifiers modifiers = 0;
if(evt.xkey.state & ShiftMask) { modifiers |= WM_Modifier_Shift; }
if(evt.xkey.state & ControlMask) { modifiers |= WM_Modifier_Ctrl; }
if(evt.xkey.state & Mod1Mask) { modifiers |= WM_Modifier_Alt; }
// rjf: map keycode -> keysym & codepoint
LNX_WM_Window *window = lnx_window_from_x11window(evt.xkey.window);
KeySym keysym = 0;
U8 text[256] = {0};
U64 text_size = Xutf8LookupString(window->xic, &evt.xkey, (char *)text, sizeof(text), &keysym, 0);
// rjf: map keysym -> WM_Key
B32 is_right_sided = 0;
WM_Key key = WM_Key_Null;
switch(keysym)
//- rjf: key presses/releases
case KeyPress:
case KeyRelease:
{
default:
// rjf: determine flags
WM_Modifiers modifiers = 0;
if(evt.xkey.state & ShiftMask) { modifiers |= WM_Modifier_Shift; }
if(evt.xkey.state & ControlMask) { modifiers |= WM_Modifier_Ctrl; }
if(evt.xkey.state & Mod1Mask) { modifiers |= WM_Modifier_Alt; }
// rjf: map keycode -> keysym & codepoint
LNX_WM_Window *window = lnx_window_from_x11window(evt.xkey.window);
KeySym keysym = 0;
U8 text[256] = {0};
U64 text_size = Xutf8LookupString(window->xic, &evt.xkey, (char *)text, sizeof(text), &keysym, 0);
// rjf: map keysym -> WM_Key
B32 is_right_sided = 0;
WM_Key key = WM_Key_Null;
switch(keysym)
{
if(0){}
else if(XK_F1 <= keysym && keysym <= XK_F24) { key = (WM_Key)(WM_Key_F1 + (keysym - XK_F1)); }
else if('0' <= keysym && keysym <= '9') { key = WM_Key_0 + (keysym-'0'); }
}break;
case XK_Escape:{key = WM_Key_Esc;};break;
case XK_BackSpace:{key = WM_Key_Backspace;}break;
case XK_Delete:{key = WM_Key_Delete;}break;
case XK_Return:{key = WM_Key_Return;}break;
case XK_Pause:{key = WM_Key_Pause;}break;
case XK_Tab:{key = WM_Key_Tab;}break;
case XK_Left:{key = WM_Key_Left;}break;
case XK_Right:{key = WM_Key_Right;}break;
case XK_Up:{key = WM_Key_Up;}break;
case XK_Down:{key = WM_Key_Down;}break;
case XK_Home:{key = WM_Key_Home;}break;
case XK_End:{key = WM_Key_End;}break;
case XK_Page_Up:{key = WM_Key_PageUp;}break;
case XK_Page_Down:{key = WM_Key_PageDown;}break;
case XK_Alt_L:{ key = WM_Key_Alt; }break;
case XK_Alt_R:{ key = WM_Key_Alt; is_right_sided = 1;}break;
case XK_Shift_L:{ key = WM_Key_Shift; }break;
case XK_Shift_R:{ key = WM_Key_Shift; is_right_sided = 1;}break;
case XK_Control_L:{ key = WM_Key_Ctrl; }break;
case XK_Control_R:{ key = WM_Key_Ctrl; is_right_sided = 1;}break;
case '-':{key = WM_Key_Minus;}break;
case '=':{key = WM_Key_Equal;}break;
case '[':{key = WM_Key_LeftBracket;}break;
case ']':{key = WM_Key_RightBracket;}break;
case ';':{key = WM_Key_Semicolon;}break;
case '\'':{key = WM_Key_Quote;}break;
case '.':{key = WM_Key_Period;}break;
case ',':{key = WM_Key_Comma;}break;
case '/':{key = WM_Key_Slash;}break;
case '\\':{key = WM_Key_BackSlash;}break;
case '\t':{key = WM_Key_Tab;}break;
case 'a':case 'A':{key = WM_Key_A;}break;
case 'b':case 'B':{key = WM_Key_B;}break;
case 'c':case 'C':{key = WM_Key_C;}break;
case 'd':case 'D':{key = WM_Key_D;}break;
case 'e':case 'E':{key = WM_Key_E;}break;
case 'f':case 'F':{key = WM_Key_F;}break;
case 'g':case 'G':{key = WM_Key_G;}break;
case 'h':case 'H':{key = WM_Key_H;}break;
case 'i':case 'I':{key = WM_Key_I;}break;
case 'j':case 'J':{key = WM_Key_J;}break;
case 'k':case 'K':{key = WM_Key_K;}break;
case 'l':case 'L':{key = WM_Key_L;}break;
case 'm':case 'M':{key = WM_Key_M;}break;
case 'n':case 'N':{key = WM_Key_N;}break;
case 'o':case 'O':{key = WM_Key_O;}break;
case 'p':case 'P':{key = WM_Key_P;}break;
case 'q':case 'Q':{key = WM_Key_Q;}break;
case 'r':case 'R':{key = WM_Key_R;}break;
case 's':case 'S':{key = WM_Key_S;}break;
case 't':case 'T':{key = WM_Key_T;}break;
case 'u':case 'U':{key = WM_Key_U;}break;
case 'v':case 'V':{key = WM_Key_V;}break;
case 'w':case 'W':{key = WM_Key_W;}break;
case 'x':case 'X':{key = WM_Key_X;}break;
case 'y':case 'Y':{key = WM_Key_Y;}break;
case 'z':case 'Z':{key = WM_Key_Z;}break;
case ' ':{key = WM_Key_Space;}break;
}
// rjf: push text event
if(evt.type == KeyPress && text_size != 0)
{
for(U64 off = 0; off < text_size;)
{
UnicodeDecode decode = utf8_decode(text+off, text_size-off);
if(decode.codepoint != 0 && (decode.codepoint >= 32 || decode.codepoint == '\t'))
default:
{
WM_Event *e = wm_event_list_push_new(arena, &evts, WM_EventKind_Text);
e->window.u64[0] = (U64)window;
e->character = decode.codepoint;
}
if(decode.inc == 0)
{
break;
}
off += decode.inc;
if(0){}
else if(XK_F1 <= keysym && keysym <= XK_F24) { key = (WM_Key)(WM_Key_F1 + (keysym - XK_F1)); }
else if('0' <= keysym && keysym <= '9') { key = WM_Key_0 + (keysym-'0'); }
}break;
case XK_Escape:{key = WM_Key_Esc;};break;
case XK_BackSpace:{key = WM_Key_Backspace;}break;
case XK_Delete:{key = WM_Key_Delete;}break;
case XK_Return:{key = WM_Key_Return;}break;
case XK_Pause:{key = WM_Key_Pause;}break;
case XK_Tab:{key = WM_Key_Tab;}break;
case XK_Left:{key = WM_Key_Left;}break;
case XK_Right:{key = WM_Key_Right;}break;
case XK_Up:{key = WM_Key_Up;}break;
case XK_Down:{key = WM_Key_Down;}break;
case XK_Home:{key = WM_Key_Home;}break;
case XK_End:{key = WM_Key_End;}break;
case XK_Page_Up:{key = WM_Key_PageUp;}break;
case XK_Page_Down:{key = WM_Key_PageDown;}break;
case XK_Alt_L:{ key = WM_Key_Alt; }break;
case XK_Alt_R:{ key = WM_Key_Alt; is_right_sided = 1;}break;
case XK_Shift_L:{ key = WM_Key_Shift; }break;
case XK_Shift_R:{ key = WM_Key_Shift; is_right_sided = 1;}break;
case XK_Control_L:{ key = WM_Key_Ctrl; }break;
case XK_Control_R:{ key = WM_Key_Ctrl; is_right_sided = 1;}break;
case '-':{key = WM_Key_Minus;}break;
case '=':{key = WM_Key_Equal;}break;
case '[':{key = WM_Key_LeftBracket;}break;
case ']':{key = WM_Key_RightBracket;}break;
case ';':{key = WM_Key_Semicolon;}break;
case '\'':{key = WM_Key_Quote;}break;
case '.':{key = WM_Key_Period;}break;
case ',':{key = WM_Key_Comma;}break;
case '/':{key = WM_Key_Slash;}break;
case '\\':{key = WM_Key_BackSlash;}break;
case '\t':{key = WM_Key_Tab;}break;
case 'a':case 'A':{key = WM_Key_A;}break;
case 'b':case 'B':{key = WM_Key_B;}break;
case 'c':case 'C':{key = WM_Key_C;}break;
case 'd':case 'D':{key = WM_Key_D;}break;
case 'e':case 'E':{key = WM_Key_E;}break;
case 'f':case 'F':{key = WM_Key_F;}break;
case 'g':case 'G':{key = WM_Key_G;}break;
case 'h':case 'H':{key = WM_Key_H;}break;
case 'i':case 'I':{key = WM_Key_I;}break;
case 'j':case 'J':{key = WM_Key_J;}break;
case 'k':case 'K':{key = WM_Key_K;}break;
case 'l':case 'L':{key = WM_Key_L;}break;
case 'm':case 'M':{key = WM_Key_M;}break;
case 'n':case 'N':{key = WM_Key_N;}break;
case 'o':case 'O':{key = WM_Key_O;}break;
case 'p':case 'P':{key = WM_Key_P;}break;
case 'q':case 'Q':{key = WM_Key_Q;}break;
case 'r':case 'R':{key = WM_Key_R;}break;
case 's':case 'S':{key = WM_Key_S;}break;
case 't':case 'T':{key = WM_Key_T;}break;
case 'u':case 'U':{key = WM_Key_U;}break;
case 'v':case 'V':{key = WM_Key_V;}break;
case 'w':case 'W':{key = WM_Key_W;}break;
case 'x':case 'X':{key = WM_Key_X;}break;
case 'y':case 'Y':{key = WM_Key_Y;}break;
case 'z':case 'Z':{key = WM_Key_Z;}break;
case ' ':{key = WM_Key_Space;}break;
}
}
// rjf: push text event
if(evt.type == KeyPress && text_size != 0)
{
for(U64 off = 0; off < text_size;)
{
UnicodeDecode decode = utf8_decode(text+off, text_size-off);
if(decode.codepoint != 0 && (decode.codepoint >= 32 || decode.codepoint == '\t'))
{
WM_Event *e = wm_event_list_push_new(arena, &evts, WM_EventKind_Text);
e->window.u64[0] = (U64)window;
e->character = decode.codepoint;
}
if(decode.inc == 0)
{
break;
}
off += decode.inc;
}
}
// rjf: push key event
{
WM_Event *e = wm_event_list_push_new(arena, &evts, evt.type == KeyPress ? WM_EventKind_Press : WM_EventKind_Release);
e->window.u64[0] = (U64)window;
e->modifiers = modifiers;
e->key = key;
e->right_sided = is_right_sided;
}
}break;
// rjf: push key event
//- rjf: mouse button presses/releases
case ButtonPress:
case ButtonRelease:
{
WM_Event *e = wm_event_list_push_new(arena, &evts, evt.type == KeyPress ? WM_EventKind_Press : WM_EventKind_Release);
e->window.u64[0] = (U64)window;
e->modifiers = modifiers;
e->key = key;
e->right_sided = is_right_sided;
}
}break;
//- rjf: mouse button presses/releases
case ButtonPress:
case ButtonRelease:
{
// rjf: determine flags
WM_Modifiers modifiers = 0;
if(evt.xbutton.state & ShiftMask) { modifiers |= WM_Modifier_Shift; }
if(evt.xbutton.state & ControlMask) { modifiers |= WM_Modifier_Ctrl; }
if(evt.xbutton.state & Mod1Mask) { modifiers |= WM_Modifier_Alt; }
// rjf: determine flags
WM_Modifiers modifiers = 0;
if(evt.xbutton.state & ShiftMask) { modifiers |= WM_Modifier_Shift; }
if(evt.xbutton.state & ControlMask) { modifiers |= WM_Modifier_Ctrl; }
if(evt.xbutton.state & Mod1Mask) { modifiers |= WM_Modifier_Alt; }
// rjf: map button -> WM_Key
WM_Key key = WM_Key_Null;
switch(evt.xbutton.button)
{
default:{}break;
case Button1:{key = WM_Key_LeftMouseButton;}break;
case Button2:{key = WM_Key_MiddleMouseButton;}break;
case Button3:{key = WM_Key_RightMouseButton;}break;
}
// rjf: push event
LNX_WM_Window *window = lnx_window_from_x11window(evt.xbutton.window);
if(key != WM_Key_Null)
{
WM_Event *e = wm_event_list_push_new(arena, &evts, evt.type == ButtonPress ? WM_EventKind_Press : WM_EventKind_Release);
e->window.u64[0] = (U64)window;
e->modifiers = modifiers;
e->key = key;
e->pos = v2f32((F32)evt.xbutton.x, (F32)evt.xbutton.y);
}
else if(evt.xbutton.button == Button4 ||
evt.xbutton.button == Button5)
{
WM_Event *e = wm_event_list_push_new(arena, &evts, WM_EventKind_Scroll);
e->window.u64[0] = (U64)window;
e->modifiers = modifiers;
e->delta = v2f32(0, evt.xbutton.button == Button4 ? -1.f : +1.f);
e->pos = v2f32((F32)evt.xbutton.x, (F32)evt.xbutton.y);
}
}break;
// rjf: map button -> WM_Key
WM_Key key = WM_Key_Null;
switch(evt.xbutton.button)
{
default:{}break;
case Button1:{key = WM_Key_LeftMouseButton;}break;
case Button2:{key = WM_Key_MiddleMouseButton;}break;
case Button3:{key = WM_Key_RightMouseButton;}break;
}
// rjf: push event
LNX_WM_Window *window = lnx_window_from_x11window(evt.xbutton.window);
if(key != WM_Key_Null)
{
WM_Event *e = wm_event_list_push_new(arena, &evts, evt.type == ButtonPress ? WM_EventKind_Press : WM_EventKind_Release);
e->window.u64[0] = (U64)window;
e->modifiers = modifiers;
e->key = key;
e->pos = v2f32((F32)evt.xbutton.x, (F32)evt.xbutton.y);
}
else if(evt.xbutton.button == Button4 ||
evt.xbutton.button == Button5)
{
WM_Event *e = wm_event_list_push_new(arena, &evts, WM_EventKind_Scroll);
e->window.u64[0] = (U64)window;
e->modifiers = modifiers;
e->delta = v2f32(0, evt.xbutton.button == Button4 ? -1.f : +1.f);
e->pos = v2f32((F32)evt.xbutton.x, (F32)evt.xbutton.y);
}
}break;
//- rjf: mouse motion
case MotionNotify:
{
LNX_WM_Window *window = lnx_window_from_x11window(evt.xclient.window);
WM_Event *e = wm_event_list_push_new(arena, &evts, WM_EventKind_MouseMove);
e->window.u64[0] = (U64)window;
e->pos.x = (F32)evt.xmotion.x;
e->pos.y = (F32)evt.xmotion.y;
set_mouse_cursor = 1;
}break;
//- rjf: window focus/unfocus
case FocusIn:
{
}break;
case FocusOut:
{
LNX_WM_Window *window = lnx_window_from_x11window(evt.xfocus.window);
WM_Event *e = wm_event_list_push_new(arena, &evts, WM_EventKind_WindowLoseFocus);
e->window.u64[0] = (U64)window;
}break;
//- rjf: client messages
case ClientMessage:
{
if((Atom)evt.xclient.data.l[0] == lnx_wm_state->wm_delete_window_atom)
//- rjf: mouse motion
case MotionNotify:
{
LNX_WM_Window *window = lnx_window_from_x11window(evt.xclient.window);
WM_Event *e = wm_event_list_push_new(arena, &evts, WM_EventKind_WindowClose);
WM_Event *e = wm_event_list_push_new(arena, &evts, WM_EventKind_MouseMove);
e->window.u64[0] = (U64)window;
}
else if((Atom)evt.xclient.data.l[0] == lnx_wm_state->wm_sync_request_atom)
e->pos.x = (F32)evt.xmotion.x;
e->pos.y = (F32)evt.xmotion.y;
set_mouse_cursor = 1;
}break;
//- rjf: window focus/unfocus
case FocusIn:
{
LNX_WM_Window *window = lnx_window_from_x11window(evt.xclient.window);
if(window != 0)
}break;
case FocusOut:
{
LNX_WM_Window *window = lnx_window_from_x11window(evt.xfocus.window);
WM_Event *e = wm_event_list_push_new(arena, &evts, WM_EventKind_WindowLoseFocus);
e->window.u64[0] = (U64)window;
}break;
//- rjf: client messages
case ClientMessage:
{
if((Atom)evt.xclient.data.l[0] == lnx_wm_state->wm_delete_window_atom)
{
window->counter_value = 0;
window->counter_value |= evt.xclient.data.l[2];
window->counter_value |= (evt.xclient.data.l[3] << 32);
XSyncValue value;
XSyncIntToValue(&value, window->counter_value);
XSyncSetCounter(lnx_wm_state->display, window->counter_xid, value);
LNX_WM_Window *window = lnx_window_from_x11window(evt.xclient.window);
WM_Event *e = wm_event_list_push_new(arena, &evts, WM_EventKind_WindowClose);
e->window.u64[0] = (U64)window;
}
}
}break;
else if((Atom)evt.xclient.data.l[0] == lnx_wm_state->wm_sync_request_atom)
{
LNX_WM_Window *window = lnx_window_from_x11window(evt.xclient.window);
if(window != 0)
{
window->counter_value = 0;
window->counter_value |= evt.xclient.data.l[2];
window->counter_value |= (evt.xclient.data.l[3] << 32);
XSyncValue value;
XSyncIntToValue(&value, window->counter_value);
XSyncSetCounter(lnx_wm_state->display, window->counter_xid, value);
}
}
}break;
}
if(set_mouse_cursor)
@@ -716,7 +716,7 @@ wm_mouse_from_window(WM_Window handle)
}
////////////////////////////////
//~ rjf: @os_hooks Cursors (Implemented Per-OS)
//~ rjf: @per_os_impl Cursors (Implemented Per-OS)
internal void
wm_set_cursor(WM_Cursor cursor)
@@ -725,7 +725,7 @@ wm_set_cursor(WM_Cursor cursor)
}
////////////////////////////////
//~ rjf: @os_hooks Native User-Facing Graphical Messages (Implemented Per-OS)
//~ rjf: @per_os_impl Native User-Facing Graphical Messages (Implemented Per-OS)
internal void
wm_graphical_message(B32 error, String8 title, String8 message)
@@ -745,7 +745,7 @@ wm_graphical_pick_file(Arena *arena, String8 initial_path)
}
////////////////////////////////
//~ rjf: @os_hooks Shell Operations
//~ rjf: @per_os_impl Shell Operations
internal void
wm_show_in_filesystem_ui(String8 path)