// ::Platform::Linux::Globals::Start:: static PlatformWindow linux_window = { .w = 1920, .h = 1080, }; b32 global_quit = false; // ::Platform::Linux::Globals::End:: // ::Platform::Linux::Print::Functions::Start:: i32 WriteStdOut(rawptr buf, i32 len) { return (i32)write(STDOUT, buf, len); } i32 WriteStdErr(rawptr buf, i32 len) { return (i32)write(STDERR, buf, len); } // ::Platform::Linux::Window::Functions::Start:: void GetWindowEvents(GameInput *inputs, u32 *i_count) { HandleWindowEvent(inputs, i_count, false); } b32 WaitForWindowEvent(GameInput *input) { u32 i_count; HandleWindowEvent(input, &i_count, true); return i_count > 0; } void HandleWindowEvent(GameInput *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); KeyboardInput input = ConvertInputEvent(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; MouseInput 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); } KeyboardInput ConvertInputEvent(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 CheckSyscallErr(void *ptr) { return (isize)ptr == SYS_ERR ? true : false; } // ::Platform::Linux::Utils::Functions::End:: // ::Platform::Linux::Includes::CFile:: #include "platform_linux_public.c"