Gears-C/src/platform/platform_linux.c
2025-05-18 06:47:28 +10:00

336 lines
8.4 KiB
C

// ::Platform::Linux::Globals::Start::
static pPlatformWindow linux_window = {
.w = 1920,
.h = 1080,
};
b32 global_quit = false;
// ::Platform::Linux::Globals::End::
// ::Platform::Linux::Print::Functions::Start::
i32 pWriteStdOut(rawptr buf, i32 len)
{
return (i32)write(STDOUT, buf, len);
}
i32 pWriteStdErr(rawptr buf, i32 len)
{
return (i32)write(STDERR, buf, len);
}
// ::Platform::Linux::Window::Functions::Start::
void pWindowEventsGet(pGameInput *inputs, u32 *i_count)
{
pWindowEventHandle(inputs, i_count, false);
}
b32 pWindowEventWaitFor(pGameInput *input)
{
u32 i_count;
pWindowEventHandle(input, &i_count, true);
return i_count > 0;
}
void pWindowEventHandle(pGameInput *inputs, u32 *i_count, b32 wait_for_event)
{
b32 has_max_inputs = false;
*i_count = 0;
do
{
xcb_generic_event_t *e;
if (wait_for_event)
e = xcb_wait_for_event(linux_window.connection);
else
e = xcb_poll_for_event(linux_window.connection);
// XCB_UNMAP_NOTIFY
if (e != NULL)
{
switch (e->response_type & ~0x80)
{
case XCB_CLIENT_MESSAGE:
{
xcb_client_message_event_t *msg = (xcb_client_message_event_t *)e;
if (msg->window != linux_window.window)
break;
if (msg->data.data32[0] == linux_window.close_event)
global_quit = true;
} break;
case XCB_CONFIGURE_NOTIFY:
{
xcb_configure_notify_event_t *configure_event = (xcb_configure_notify_event_t *)e;
if (linux_window.w != configure_event->width || linux_window.h != configure_event->height)
{
linux_window.w = configure_event->width;
linux_window.h = configure_event->height;
}
} break;
case XCB_KEY_RELEASE:
case XCB_KEY_PRESS:
{
xcb_key_press_event_t *keyboard_e = (xcb_key_press_event_t *)e;
b8 pressed = e->response_type == XCB_KEY_PRESS;
xcb_keycode_t code = keyboard_e->detail;
KeySym keysym = XkbKeycodeToKeysym(linux_window.display, (KeyCode)code, 0, 0);
pKeyboardInput input = pInputEventConvert(keysym);
if (input != KB_NONE)
{
inputs[*i_count].kb_code = input;
inputs[*i_count].pressed = pressed;
inputs[*i_count].type = GI_KEYBOARD;
*i_count += 1;
if (*i_count == 10)
has_max_inputs = true;
}
} break;
case XCB_BUTTON_PRESS:
case XCB_BUTTON_RELEASE:
{
xcb_button_press_event_t *mouse_ev = (xcb_button_press_event_t *)e;
b8 pressed = e->response_type == XCB_BUTTON_PRESS;
pMouseInput input = M_NONE;
if (mouse_ev->detail == XCB_BUTTON_INDEX_1)
input = M_LEFT_CLICK;
else if (mouse_ev->detail == XCB_BUTTON_INDEX_2)
input = M_MIDDLE_CLICK;
else if (mouse_ev->detail == XCB_BUTTON_INDEX_3)
input = M_RIGHT_CLICK;
if (input != M_NONE)
{
inputs[*i_count].m_code = input;
inputs[*i_count].pressed = pressed;
inputs[*i_count].type = GI_MOUSE;
*i_count += 1;
if (*i_count == 10)
has_max_inputs = true;
}
} break;
case XCB_MOTION_NOTIFY:
{
xcb_motion_notify_event_t *move_ev = (xcb_motion_notify_event_t *)e;
if (move_ev->event_x > 0 || move_ev->event_y > 0)
{
inputs[*i_count].motion_ev.x = move_ev->event_x;
inputs[*i_count].motion_ev.y = move_ev->event_y;
inputs[*i_count].type = GI_MOTION;
*i_count += 1;
if (*i_count == 10)
has_max_inputs = true;
}
}
default:
break;
}
free(e);
}
else
{
break;
}
} while(!wait_for_event && !has_max_inputs);
}
pKeyboardInput pInputEventConvert(u32 x_key)
{
switch (x_key)
{
case XK_BackSpace: return KB_BACKSPACE;
case XK_Return: return KB_ENTER;
case XK_Tab: return KB_TAB;
case XK_Pause: return KB_PAUSE;
case XK_Caps_Lock: return KB_CAPS_LOCK;
case XK_Escape: return KB_ESC;
case XK_space: return KB_SPACE;
case XK_Prior: return KB_PAGE_UP;
case XK_Next: return KB_PAGE_DOWN;
case XK_End: return KB_END;
case XK_Home: return KB_HOME;
case XK_Left: return KB_LEFT;
case XK_Up: return KB_UP;
case XK_Right: return KB_RIGHT;
case XK_Down: return KB_DOWN;
case XK_Print: return KB_PRINT_SCREEN;
case XK_Insert: return KB_INSERT;
case XK_Delete: return KB_DELETE;
case XK_Meta_L:
case XK_Super_L: return KB_LEFT_SUPER;
case XK_Meta_R:
case XK_Super_R: return KB_RIGHT_SUPER;
case XK_KP_0: return KB_NUM_0;
case XK_KP_1: return KB_NUM_1;
case XK_KP_2: return KB_NUM_2;
case XK_KP_3: return KB_NUM_3;
case XK_KP_4: return KB_NUM_4;
case XK_KP_5: return KB_NUM_5;
case XK_KP_6: return KB_NUM_6;
case XK_KP_7: return KB_NUM_7;
case XK_KP_8: return KB_NUM_8;
case XK_KP_9: return KB_NUM_9;
case XK_multiply: return KB_NUM_STAR;
case XK_KP_Subtract: return KB_NUM_MINUS;
case XK_KP_Decimal: return KB_NUM_PERIOD;
case XK_KP_Divide: return KB_NUM_SLASH;
case XK_KP_Add: return KB_NUM_PLUS;
case XK_F1: return KB_F1;
case XK_F2: return KB_F2;
case XK_F3: return KB_F3;
case XK_F4: return KB_F4;
case XK_F5: return KB_F5;
case XK_F6: return KB_F6;
case XK_F7: return KB_F7;
case XK_F8: return KB_F8;
case XK_F9: return KB_F9;
case XK_F10: return KB_F10;
case XK_F11: return KB_F11;
case XK_F12: return KB_F12;
case XK_Num_Lock: return KB_NUM_LOCK;
case XK_Scroll_Lock: return KB_SCROLL_LOCK;
case XK_Shift_L: return KB_LEFT_SHIFT;
case XK_Shift_R: return KB_RIGHT_SHIFT;
case XK_Control_L: return KB_LEFT_CTRL;
case XK_Control_R: return KB_RIGHT_CTRL;
case XK_Alt_L: return KB_LEFT_ALT;
case XK_Alt_R: return KB_RIGHT_ALT;
case XK_semicolon: return KB_SEMICOLON;
case XK_bracketleft: return KB_LEFT_BRACE;
case XK_bracketright: return KB_RIGHT_BRACE;
case XK_plus: return KB_PLUS;
case XK_comma: return KB_COMMA;
case XK_minus: return KB_MINUS;
case XK_backslash: return KB_BACK_SLASH;
case XK_slash: return KB_FORWARD_SLASH;
case XK_grave: return KB_TILDE;
case XK_0: return KB_0;
case XK_1: return KB_1;
case XK_2: return KB_2;
case XK_3: return KB_3;
case XK_4: return KB_4;
case XK_5: return KB_5;
case XK_6: return KB_6;
case XK_7: return KB_7;
case XK_8: return KB_8;
case XK_9: return KB_9;
case XK_a:
case XK_A: return KB_A;
case XK_b:
case XK_B: return KB_B;
case XK_c:
case XK_C: return KB_C;
case XK_d:
case XK_D: return KB_D;
case XK_e:
case XK_E: return KB_E;
case XK_f:
case XK_F: return KB_F;
case XK_g:
case XK_G: return KB_G;
case XK_h:
case XK_H: return KB_H;
case XK_i:
case XK_I: return KB_I;
case XK_j:
case XK_J: return KB_J;
case XK_k:
case XK_K: return KB_K;
case XK_l:
case XK_L: return KB_L;
case XK_m:
case XK_M: return KB_M;
case XK_n:
case XK_N: return KB_N;
case XK_o:
case XK_O: return KB_O;
case XK_p:
case XK_P: return KB_P;
case XK_q:
case XK_Q: return KB_Q;
case XK_r:
case XK_R: return KB_R;
case XK_s:
case XK_S: return KB_S;
case XK_t:
case XK_T: return KB_T;
case XK_u:
case XK_U: return KB_U;
case XK_v:
case XK_V: return KB_V;
case XK_w:
case XK_W: return KB_W;
case XK_x:
case XK_X: return KB_X;
case XK_y:
case XK_Y: return KB_Y;
case XK_z:
case XK_Z: return KB_Z;
default: return KB_NONE;
}
}
// ::Platform::Linux::Window::Functions::Start::
// ::Platform::Linux::Utils::Functions::Start::
b32 pSyscallErrCheck(void *ptr)
{
return (isize)ptr == SYS_ERR ? true : false;
}
// ::Platform::Linux::Utils::Functions::End::
// ::Platform::Linux::Async::Start::
static pThread pThreadInit(pThreadProc proc, rawptr param)
{
pThread thread = {0};
pthread_mutex_init(&thread.mut, NULL);
pthread_create(&thread.handle, NULL, proc, param);
return thread;
}
static void pThreadSuspend(pThread *thread)
{
pthread_mutex_lock(&thread->mut);
pthread_cond_wait(&thread->cond, &thread->mut);
pthread_mutex_unlock(&thread->mut);
}
static void pThreadWake(pThread *thread)
{
pthread_cond_signal(&thread->cond);
}
static void pThreadKill()
{
pthread_exit(NULL);
}
// ::Platform::Linux::Async::Start::
// ::Platform::Linux::Includes::CFile::
#include "platform_linux_public.c"