mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-06-24 20:54:59 -07:00
703 lines
21 KiB
C
703 lines
21 KiB
C
// Copyright (c) 2024 Epic Games Tools
|
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
|
|
|
////////////////////////////////
|
|
//~ rjf: Helpers
|
|
|
|
internal OS_LNX_Window *
|
|
os_lnx_window_from_x11window(Window window)
|
|
{
|
|
OS_LNX_Window *result = 0;
|
|
for(OS_LNX_Window *w = os_lnx_gfx_state->first_window; w != 0; w = w->next)
|
|
{
|
|
if(w->window == window)
|
|
{
|
|
result = w;
|
|
break;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
////////////////////////////////
|
|
//~ rjf: @os_hooks Main Initialization API (Implemented Per-OS)
|
|
|
|
internal void
|
|
os_gfx_init(void)
|
|
{
|
|
//- rjf: initialize basics
|
|
Arena *arena = arena_alloc();
|
|
os_lnx_gfx_state = push_array(arena, OS_LNX_GfxState, 1);
|
|
os_lnx_gfx_state->arena = arena;
|
|
os_lnx_gfx_state->display = XOpenDisplay(0);
|
|
|
|
//- rjf: calculate atoms
|
|
os_lnx_gfx_state->wm_delete_window_atom = XInternAtom(os_lnx_gfx_state->display, "WM_DELETE_WINDOW", 0);
|
|
os_lnx_gfx_state->wm_sync_request_atom = XInternAtom(os_lnx_gfx_state->display, "_NET_WM_SYNC_REQUEST", 0);
|
|
os_lnx_gfx_state->wm_sync_request_counter_atom = XInternAtom(os_lnx_gfx_state->display, "_NET_WM_SYNC_REQUEST_COUNTER", 0);
|
|
|
|
//- rjf: open im
|
|
os_lnx_gfx_state->xim = XOpenIM(os_lnx_gfx_state->display, 0, 0, 0);
|
|
|
|
//- rjf: fill out gfx info
|
|
os_lnx_gfx_state->gfx_info.double_click_time = 0.5f;
|
|
os_lnx_gfx_state->gfx_info.caret_blink_time = 0.5f;
|
|
os_lnx_gfx_state->gfx_info.default_refresh_rate = 60.f;
|
|
|
|
//- rjf: fill out cursors
|
|
{
|
|
struct
|
|
{
|
|
OS_Cursor cursor;
|
|
unsigned int id;
|
|
}
|
|
map[] =
|
|
{
|
|
{OS_Cursor_Pointer, XC_left_ptr},
|
|
{OS_Cursor_IBar, XC_xterm},
|
|
{OS_Cursor_LeftRight, XC_sb_h_double_arrow},
|
|
{OS_Cursor_UpDown, XC_sb_v_double_arrow},
|
|
{OS_Cursor_DownRight, XC_bottom_right_corner},
|
|
{OS_Cursor_UpRight, XC_top_right_corner},
|
|
{OS_Cursor_UpDownLeftRight, XC_fleur},
|
|
{OS_Cursor_HandPoint, XC_hand1},
|
|
{OS_Cursor_Disabled, XC_X_cursor},
|
|
};
|
|
for EachElement(idx, map)
|
|
{
|
|
os_lnx_gfx_state->cursors[map[idx].cursor] = XCreateFontCursor(os_lnx_gfx_state->display, map[idx].id);
|
|
}
|
|
}
|
|
}
|
|
|
|
////////////////////////////////
|
|
//~ rjf: @os_hooks Graphics System Info (Implemented Per-OS)
|
|
|
|
internal OS_GfxInfo *
|
|
os_get_gfx_info(void)
|
|
{
|
|
return &os_lnx_gfx_state->gfx_info;
|
|
}
|
|
|
|
////////////////////////////////
|
|
//~ rjf: @os_hooks Clipboards (Implemented Per-OS)
|
|
|
|
internal void
|
|
os_set_clipboard_text(String8 string)
|
|
{
|
|
|
|
}
|
|
|
|
internal String8
|
|
os_get_clipboard_text(Arena *arena)
|
|
{
|
|
String8 result = {0};
|
|
return result;
|
|
}
|
|
|
|
////////////////////////////////
|
|
//~ rjf: @os_hooks Windows (Implemented Per-OS)
|
|
|
|
internal OS_Handle
|
|
os_window_open(Rng2F32 rect, OS_WindowFlags flags, String8 title)
|
|
{
|
|
Vec2F32 resolution = dim_2f32(rect);
|
|
|
|
//- rjf: allocate window
|
|
OS_LNX_Window *w = os_lnx_gfx_state->free_window;
|
|
if(w)
|
|
{
|
|
SLLStackPop(os_lnx_gfx_state->free_window);
|
|
}
|
|
else
|
|
{
|
|
w = push_array_no_zero(os_lnx_gfx_state->arena, OS_LNX_Window, 1);
|
|
}
|
|
MemoryZeroStruct(w);
|
|
DLLPushBack(os_lnx_gfx_state->first_window, os_lnx_gfx_state->last_window, w);
|
|
|
|
//- rjf: create window & equip with x11 info
|
|
w->window = XCreateWindow(os_lnx_gfx_state->display,
|
|
XDefaultRootWindow(os_lnx_gfx_state->display),
|
|
0, 0, resolution.x, resolution.y,
|
|
0,
|
|
CopyFromParent,
|
|
InputOutput,
|
|
CopyFromParent,
|
|
0,
|
|
0);
|
|
XSelectInput(os_lnx_gfx_state->display, w->window,
|
|
ExposureMask|
|
|
PointerMotionMask|
|
|
ButtonPressMask|
|
|
ButtonReleaseMask|
|
|
KeyPressMask|
|
|
KeyReleaseMask|
|
|
FocusChangeMask);
|
|
Atom protocols[] =
|
|
{
|
|
os_lnx_gfx_state->wm_delete_window_atom,
|
|
os_lnx_gfx_state->wm_sync_request_atom,
|
|
};
|
|
XSetWMProtocols(os_lnx_gfx_state->display, w->window, protocols, ArrayCount(protocols));
|
|
{
|
|
XSyncValue initial_value;
|
|
XSyncIntToValue(&initial_value, 0);
|
|
w->counter_xid = XSyncCreateCounter(os_lnx_gfx_state->display, initial_value);
|
|
}
|
|
XChangeProperty(os_lnx_gfx_state->display, w->window, os_lnx_gfx_state->wm_sync_request_counter_atom, XA_CARDINAL, 32, PropModeReplace, (U8 *)&w->counter_xid, 1);
|
|
|
|
//- rjf: create xic
|
|
w->xic = XCreateIC(os_lnx_gfx_state->xim,
|
|
XNInputStyle, XIMPreeditNothing|XIMStatusNothing,
|
|
XNClientWindow, w->window,
|
|
XNFocusWindow, w->window,
|
|
NULL);
|
|
|
|
//- rjf: attach name
|
|
Temp scratch = scratch_begin(0, 0);
|
|
String8 title_copy = push_str8_copy(scratch.arena, title);
|
|
XStoreName(os_lnx_gfx_state->display, w->window, (char *)title_copy.str);
|
|
scratch_end(scratch);
|
|
|
|
//- rjf: convert to handle & return
|
|
OS_Handle handle = {(U64)w};
|
|
return handle;
|
|
}
|
|
|
|
internal void
|
|
os_window_close(OS_Handle handle)
|
|
{
|
|
if(os_handle_match(handle, os_handle_zero())) {return;}
|
|
OS_LNX_Window *w = (OS_LNX_Window *)handle.u64[0];
|
|
XDestroyWindow(os_lnx_gfx_state->display, w->window);
|
|
}
|
|
|
|
internal void
|
|
os_window_set_title(OS_Handle handle, String8 title)
|
|
{
|
|
if(os_handle_match(handle, os_handle_zero())) {return;}
|
|
Temp scratch = scratch_begin(0, 0);
|
|
OS_LNX_Window *w = (OS_LNX_Window *)handle.u64[0];
|
|
String8 title_copy = push_str8_copy(scratch.arena, title);
|
|
XStoreName(os_lnx_gfx_state->display, w->window, (char *)title_copy.str);
|
|
scratch_end(scratch);
|
|
}
|
|
|
|
internal void
|
|
os_window_first_paint(OS_Handle handle)
|
|
{
|
|
if(os_handle_match(handle, os_handle_zero())) {return;}
|
|
OS_LNX_Window *w = (OS_LNX_Window *)handle.u64[0];
|
|
XMapWindow(os_lnx_gfx_state->display, w->window);
|
|
}
|
|
|
|
internal void
|
|
os_window_focus(OS_Handle handle)
|
|
{
|
|
if(os_handle_match(handle, os_handle_zero())) {return;}
|
|
OS_LNX_Window *w = (OS_LNX_Window *)handle.u64[0];
|
|
XSetInputFocus(os_lnx_gfx_state->display, w->window, RevertToNone, CurrentTime);
|
|
}
|
|
|
|
internal B32
|
|
os_window_is_focused(OS_Handle handle)
|
|
{
|
|
if(os_handle_match(handle, os_handle_zero())) {return 0;}
|
|
OS_LNX_Window *w = (OS_LNX_Window *)handle.u64[0];
|
|
Window focused_window = 0;
|
|
int revert_to = 0;
|
|
XGetInputFocus(os_lnx_gfx_state->display, &focused_window, &revert_to);
|
|
B32 result = (w->window == focused_window);
|
|
return result;
|
|
}
|
|
|
|
internal B32
|
|
os_window_is_fullscreen(OS_Handle handle)
|
|
{
|
|
if(os_handle_match(handle, os_handle_zero())) {return 0;}
|
|
// TODO(rjf)
|
|
return 0;
|
|
}
|
|
|
|
internal void
|
|
os_window_set_fullscreen(OS_Handle handle, B32 fullscreen)
|
|
{
|
|
if(os_handle_match(handle, os_handle_zero())) {return;}
|
|
// TODO(rjf)
|
|
}
|
|
|
|
internal B32
|
|
os_window_is_maximized(OS_Handle handle)
|
|
{
|
|
if(os_handle_match(handle, os_handle_zero())) {return 0;}
|
|
// TODO(rjf)
|
|
return 0;
|
|
}
|
|
|
|
internal void
|
|
os_window_set_maximized(OS_Handle handle, B32 maximized)
|
|
{
|
|
if(os_handle_match(handle, os_handle_zero())) {return;}
|
|
// TODO(rjf)
|
|
}
|
|
|
|
internal B32
|
|
os_window_is_minimized(OS_Handle handle)
|
|
{
|
|
if(os_handle_match(handle, os_handle_zero())) {return 0;}
|
|
// TODO(rjf)
|
|
return 0;
|
|
}
|
|
|
|
internal void
|
|
os_window_set_minimized(OS_Handle handle, B32 minimized)
|
|
{
|
|
if(os_handle_match(handle, os_handle_zero())) {return;}
|
|
// TODO(rjf)
|
|
}
|
|
|
|
internal void
|
|
os_window_bring_to_front(OS_Handle handle)
|
|
{
|
|
if(os_handle_match(handle, os_handle_zero())) {return;}
|
|
// TODO(rjf)
|
|
}
|
|
|
|
internal void
|
|
os_window_set_monitor(OS_Handle handle, OS_Handle monitor)
|
|
{
|
|
if(os_handle_match(handle, os_handle_zero())) {return;}
|
|
// TODO(rjf)
|
|
}
|
|
|
|
internal void
|
|
os_window_clear_custom_border_data(OS_Handle handle)
|
|
{
|
|
if(os_handle_match(handle, os_handle_zero())) {return;}
|
|
// TODO(rjf)
|
|
}
|
|
|
|
internal void
|
|
os_window_push_custom_title_bar(OS_Handle handle, F32 thickness)
|
|
{
|
|
if(os_handle_match(handle, os_handle_zero())) {return;}
|
|
// TODO(rjf)
|
|
}
|
|
|
|
internal void
|
|
os_window_push_custom_edges(OS_Handle handle, F32 thickness)
|
|
{
|
|
if(os_handle_match(handle, os_handle_zero())) {return;}
|
|
// TODO(rjf)
|
|
}
|
|
|
|
internal void
|
|
os_window_push_custom_title_bar_client_area(OS_Handle handle, Rng2F32 rect)
|
|
{
|
|
if(os_handle_match(handle, os_handle_zero())) {return;}
|
|
// TODO(rjf)
|
|
}
|
|
|
|
internal Rng2F32
|
|
os_rect_from_window(OS_Handle handle)
|
|
{
|
|
if(os_handle_match(handle, os_handle_zero())) {return r2f32p(0, 0, 0, 0);}
|
|
OS_LNX_Window *w = (OS_LNX_Window *)handle.u64[0];
|
|
XWindowAttributes atts = {0};
|
|
Status s = XGetWindowAttributes(os_lnx_gfx_state->display, w->window, &atts);
|
|
Rng2F32 result = r2f32p((F32)atts.x, (F32)atts.y, (F32)atts.x + (F32)atts.width, (F32)atts.y + (F32)atts.height);
|
|
return result;
|
|
}
|
|
|
|
internal Rng2F32
|
|
os_client_rect_from_window(OS_Handle handle)
|
|
{
|
|
OS_LNX_Window *w = (OS_LNX_Window *)handle.u64[0];
|
|
XWindowAttributes atts = {0};
|
|
Status s = XGetWindowAttributes(os_lnx_gfx_state->display, w->window, &atts);
|
|
Rng2F32 result = r2f32p(0, 0, (F32)atts.width, (F32)atts.height);
|
|
return result;
|
|
}
|
|
|
|
internal F32
|
|
os_dpi_from_window(OS_Handle handle)
|
|
{
|
|
// TODO(rjf)
|
|
return 96.f;
|
|
}
|
|
|
|
////////////////////////////////
|
|
//~ rjf: @os_hooks Monitors (Implemented Per-OS)
|
|
|
|
internal OS_HandleArray
|
|
os_push_monitors_array(Arena *arena)
|
|
{
|
|
OS_HandleArray result = {0};
|
|
// TODO(rjf)
|
|
return result;
|
|
}
|
|
|
|
internal OS_Handle
|
|
os_primary_monitor(void)
|
|
{
|
|
OS_Handle result = {0};
|
|
// TODO(rjf)
|
|
return result;
|
|
}
|
|
|
|
internal OS_Handle
|
|
os_monitor_from_window(OS_Handle window)
|
|
{
|
|
OS_Handle result = {0};
|
|
// TODO(rjf)
|
|
return result;
|
|
}
|
|
|
|
internal String8
|
|
os_name_from_monitor(Arena *arena, OS_Handle monitor)
|
|
{
|
|
// TODO(rjf)
|
|
return str8_zero();
|
|
}
|
|
|
|
internal Vec2F32
|
|
os_dim_from_monitor(OS_Handle monitor)
|
|
{
|
|
// TODO(rjf)
|
|
return v2f32(0, 0);
|
|
}
|
|
|
|
internal F32
|
|
os_dpi_from_monitor(OS_Handle monitor)
|
|
{
|
|
// TODO(rjf)
|
|
return 96.f;
|
|
}
|
|
|
|
////////////////////////////////
|
|
//~ rjf: @os_hooks Events (Implemented Per-OS)
|
|
|
|
internal void
|
|
os_send_wakeup_event(void)
|
|
{
|
|
// TODO(rjf)
|
|
}
|
|
|
|
internal OS_EventList
|
|
os_get_events(Arena *arena, B32 wait)
|
|
{
|
|
OS_EventList evts = {0};
|
|
for(;XPending(os_lnx_gfx_state->display) > 0 || (wait && evts.count == 0);)
|
|
{
|
|
XEvent evt = {0};
|
|
XNextEvent(os_lnx_gfx_state->display, &evt);
|
|
B32 set_mouse_cursor = 0;
|
|
switch(evt.type)
|
|
{
|
|
default:{}break;
|
|
|
|
//- rjf: key presses/releases
|
|
case KeyPress:
|
|
case KeyRelease:
|
|
{
|
|
// rjf: determine flags
|
|
OS_Modifiers modifiers = 0;
|
|
if(evt.xkey.state & ShiftMask) { modifiers |= OS_Modifier_Shift; }
|
|
if(evt.xkey.state & ControlMask) { modifiers |= OS_Modifier_Ctrl; }
|
|
if(evt.xkey.state & Mod1Mask) { modifiers |= OS_Modifier_Alt; }
|
|
|
|
// rjf: map keycode -> keysym & codepoint
|
|
OS_LNX_Window *window = os_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 -> OS_Key
|
|
B32 is_right_sided = 0;
|
|
OS_Key key = OS_Key_Null;
|
|
switch(keysym)
|
|
{
|
|
default:
|
|
{
|
|
if(0){}
|
|
else if(XK_F1 <= keysym && keysym <= XK_F24) { key = (OS_Key)(OS_Key_F1 + (keysym - XK_F1)); }
|
|
else if('0' <= keysym && keysym <= '9') { key = OS_Key_0 + (keysym-'0'); }
|
|
}break;
|
|
case XK_Escape:{key = OS_Key_Esc;};break;
|
|
case XK_BackSpace:{key = OS_Key_Backspace;}break;
|
|
case XK_Delete:{key = OS_Key_Delete;}break;
|
|
case XK_Return:{key = OS_Key_Return;}break;
|
|
case XK_Pause:{key = OS_Key_Pause;}break;
|
|
case XK_Tab:{key = OS_Key_Tab;}break;
|
|
case XK_Left:{key = OS_Key_Left;}break;
|
|
case XK_Right:{key = OS_Key_Right;}break;
|
|
case XK_Up:{key = OS_Key_Up;}break;
|
|
case XK_Down:{key = OS_Key_Down;}break;
|
|
case XK_Home:{key = OS_Key_Home;}break;
|
|
case XK_End:{key = OS_Key_End;}break;
|
|
case XK_Page_Up:{key = OS_Key_PageUp;}break;
|
|
case XK_Page_Down:{key = OS_Key_PageDown;}break;
|
|
case XK_Alt_L:{ key = OS_Key_Alt; }break;
|
|
case XK_Alt_R:{ key = OS_Key_Alt; is_right_sided = 1;}break;
|
|
case XK_Shift_L:{ key = OS_Key_Shift; }break;
|
|
case XK_Shift_R:{ key = OS_Key_Shift; is_right_sided = 1;}break;
|
|
case XK_Control_L:{ key = OS_Key_Ctrl; }break;
|
|
case XK_Control_R:{ key = OS_Key_Ctrl; is_right_sided = 1;}break;
|
|
case '-':{key = OS_Key_Minus;}break;
|
|
case '=':{key = OS_Key_Equal;}break;
|
|
case '[':{key = OS_Key_LeftBracket;}break;
|
|
case ']':{key = OS_Key_RightBracket;}break;
|
|
case ';':{key = OS_Key_Semicolon;}break;
|
|
case '\'':{key = OS_Key_Quote;}break;
|
|
case '.':{key = OS_Key_Period;}break;
|
|
case ',':{key = OS_Key_Comma;}break;
|
|
case '/':{key = OS_Key_Slash;}break;
|
|
case '\\':{key = OS_Key_BackSlash;}break;
|
|
case '\t':{key = OS_Key_Tab;}break;
|
|
case 'a':case 'A':{key = OS_Key_A;}break;
|
|
case 'b':case 'B':{key = OS_Key_B;}break;
|
|
case 'c':case 'C':{key = OS_Key_C;}break;
|
|
case 'd':case 'D':{key = OS_Key_D;}break;
|
|
case 'e':case 'E':{key = OS_Key_E;}break;
|
|
case 'f':case 'F':{key = OS_Key_F;}break;
|
|
case 'g':case 'G':{key = OS_Key_G;}break;
|
|
case 'h':case 'H':{key = OS_Key_H;}break;
|
|
case 'i':case 'I':{key = OS_Key_I;}break;
|
|
case 'j':case 'J':{key = OS_Key_J;}break;
|
|
case 'k':case 'K':{key = OS_Key_K;}break;
|
|
case 'l':case 'L':{key = OS_Key_L;}break;
|
|
case 'm':case 'M':{key = OS_Key_M;}break;
|
|
case 'n':case 'N':{key = OS_Key_N;}break;
|
|
case 'o':case 'O':{key = OS_Key_O;}break;
|
|
case 'p':case 'P':{key = OS_Key_P;}break;
|
|
case 'q':case 'Q':{key = OS_Key_Q;}break;
|
|
case 'r':case 'R':{key = OS_Key_R;}break;
|
|
case 's':case 'S':{key = OS_Key_S;}break;
|
|
case 't':case 'T':{key = OS_Key_T;}break;
|
|
case 'u':case 'U':{key = OS_Key_U;}break;
|
|
case 'v':case 'V':{key = OS_Key_V;}break;
|
|
case 'w':case 'W':{key = OS_Key_W;}break;
|
|
case 'x':case 'X':{key = OS_Key_X;}break;
|
|
case 'y':case 'Y':{key = OS_Key_Y;}break;
|
|
case 'z':case 'Z':{key = OS_Key_Z;}break;
|
|
case ' ':{key = OS_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'))
|
|
{
|
|
OS_Event *e = os_event_list_push_new(arena, &evts, OS_EventKind_Text);
|
|
e->window.u64[0] = (U64)window;
|
|
e->character = decode.codepoint;
|
|
}
|
|
if(decode.inc == 0)
|
|
{
|
|
break;
|
|
}
|
|
off += decode.inc;
|
|
}
|
|
}
|
|
|
|
// rjf: push key event
|
|
{
|
|
OS_Event *e = os_event_list_push_new(arena, &evts, evt.type == KeyPress ? OS_EventKind_Press : OS_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
|
|
OS_Modifiers modifiers = 0;
|
|
if(evt.xbutton.state & ShiftMask) { modifiers |= OS_Modifier_Shift; }
|
|
if(evt.xbutton.state & ControlMask) { modifiers |= OS_Modifier_Ctrl; }
|
|
if(evt.xbutton.state & Mod1Mask) { modifiers |= OS_Modifier_Alt; }
|
|
|
|
// rjf: map button -> OS_Key
|
|
OS_Key key = OS_Key_Null;
|
|
switch(evt.xbutton.button)
|
|
{
|
|
default:{}break;
|
|
case Button1:{key = OS_Key_LeftMouseButton;}break;
|
|
case Button2:{key = OS_Key_MiddleMouseButton;}break;
|
|
case Button3:{key = OS_Key_RightMouseButton;}break;
|
|
}
|
|
|
|
// rjf: push event
|
|
OS_LNX_Window *window = os_lnx_window_from_x11window(evt.xbutton.window);
|
|
if(key != OS_Key_Null)
|
|
{
|
|
OS_Event *e = os_event_list_push_new(arena, &evts, evt.type == ButtonPress ? OS_EventKind_Press : OS_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)
|
|
{
|
|
OS_Event *e = os_event_list_push_new(arena, &evts, OS_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:
|
|
{
|
|
OS_LNX_Window *window = os_lnx_window_from_x11window(evt.xclient.window);
|
|
OS_Event *e = os_event_list_push_new(arena, &evts, OS_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:
|
|
{
|
|
OS_LNX_Window *window = os_lnx_window_from_x11window(evt.xfocus.window);
|
|
OS_Event *e = os_event_list_push_new(arena, &evts, OS_EventKind_WindowLoseFocus);
|
|
e->window.u64[0] = (U64)window;
|
|
}break;
|
|
|
|
//- rjf: client messages
|
|
case ClientMessage:
|
|
{
|
|
if((Atom)evt.xclient.data.l[0] == os_lnx_gfx_state->wm_delete_window_atom)
|
|
{
|
|
OS_LNX_Window *window = os_lnx_window_from_x11window(evt.xclient.window);
|
|
OS_Event *e = os_event_list_push_new(arena, &evts, OS_EventKind_WindowClose);
|
|
e->window.u64[0] = (U64)window;
|
|
}
|
|
else if((Atom)evt.xclient.data.l[0] == os_lnx_gfx_state->wm_sync_request_atom)
|
|
{
|
|
OS_LNX_Window *window = os_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(os_lnx_gfx_state->display, window->counter_xid, value);
|
|
}
|
|
}
|
|
}break;
|
|
}
|
|
if(set_mouse_cursor)
|
|
{
|
|
Window root_window = 0;
|
|
Window child_window = 0;
|
|
int root_rel_x = 0;
|
|
int root_rel_y = 0;
|
|
int child_rel_x = 0;
|
|
int child_rel_y = 0;
|
|
unsigned int mask = 0;
|
|
if(XQueryPointer(os_lnx_gfx_state->display, XDefaultRootWindow(os_lnx_gfx_state->display), &root_window, &child_window, &root_rel_x, &root_rel_y, &child_rel_x, &child_rel_y, &mask))
|
|
{
|
|
XDefineCursor(os_lnx_gfx_state->display, root_window, os_lnx_gfx_state->cursors[os_lnx_gfx_state->last_set_cursor]);
|
|
XFlush(os_lnx_gfx_state->display);
|
|
}
|
|
}
|
|
}
|
|
return evts;
|
|
}
|
|
|
|
internal OS_Modifiers
|
|
os_get_modifiers(void)
|
|
{
|
|
// TODO(rjf)
|
|
return 0;
|
|
}
|
|
|
|
internal B32
|
|
os_key_is_down(OS_Key key)
|
|
{
|
|
// TODO(rjf)
|
|
return 0;
|
|
}
|
|
|
|
internal Vec2F32
|
|
os_mouse_from_window(OS_Handle handle)
|
|
{
|
|
if(os_handle_match(handle, os_handle_zero())) {return v2f32(0, 0);}
|
|
OS_LNX_Window *w = (OS_LNX_Window *)handle.u64[0];
|
|
Vec2F32 result = {0};
|
|
{
|
|
Window root_window = 0;
|
|
Window child_window = 0;
|
|
int root_rel_x = 0;
|
|
int root_rel_y = 0;
|
|
int child_rel_x = 0;
|
|
int child_rel_y = 0;
|
|
unsigned int mask = 0;
|
|
if(XQueryPointer(os_lnx_gfx_state->display, w->window, &root_window, &child_window, &root_rel_x, &root_rel_y, &child_rel_x, &child_rel_y, &mask))
|
|
{
|
|
result.x = child_rel_x;
|
|
result.y = child_rel_y;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
////////////////////////////////
|
|
//~ rjf: @os_hooks Cursors (Implemented Per-OS)
|
|
|
|
internal void
|
|
os_set_cursor(OS_Cursor cursor)
|
|
{
|
|
os_lnx_gfx_state->last_set_cursor = cursor;
|
|
}
|
|
|
|
////////////////////////////////
|
|
//~ rjf: @os_hooks Native User-Facing Graphical Messages (Implemented Per-OS)
|
|
|
|
internal void
|
|
os_graphical_message(B32 error, String8 title, String8 message)
|
|
{
|
|
if(error)
|
|
{
|
|
fprintf(stderr, "[X] ");
|
|
}
|
|
fprintf(stderr, "%.*s\n", str8_varg(title));
|
|
fprintf(stderr, "%.*s\n\n", str8_varg(message));
|
|
}
|
|
|
|
internal String8
|
|
os_graphical_pick_file(Arena *arena, String8 initial_path)
|
|
{
|
|
return str8_zero();
|
|
}
|
|
|
|
////////////////////////////////
|
|
//~ rjf: @os_hooks Shell Operations
|
|
|
|
internal void
|
|
os_show_in_filesystem_ui(String8 path)
|
|
{
|
|
// TODO(rjf)
|
|
}
|
|
|
|
internal void
|
|
os_open_in_browser(String8 url)
|
|
{
|
|
// TODO(rjf)
|
|
}
|