#include "XcbKeyboard.h" // Header is c-like, uses explicit as a var #define explicit explicit_ #include #undef explicit #include #include "FileLogger.h" XcbKeyboard::XcbKeyboard(xcb_connection_t* connection) : Keyboard(), mConnection(connection) { mXkbContext = xkb_context_new(XKB_CONTEXT_NO_FLAGS); if (!mXkbContext) { MLOG_ERROR("Failed to get XKB context"); } } std::unique_ptr XcbKeyboard::Create(xcb_connection_t* connection) { return std::make_unique(connection); } void XcbKeyboard::updateState(xcb_xkb_state_notify_event_t *state) { xkb_state_update_mask(mXkbState, state->baseMods, state->latchedMods, state->lockedMods, state->baseGroup, state->latchedGroup, state->lockedGroup); } std::string XcbKeyboard::getKeyString(KeyCode keyCode) { if (!mXkbState) { getKeyMap(); } auto size = xkb_state_key_get_utf8(mXkbState, keyCode, nullptr, 0) + 1; if (size <= 1) { return {}; } char buffer[size]; xkb_state_key_get_utf8(mXkbState, keyCode, buffer, size); std::string ret(buffer); return ret; } void XcbKeyboard::getKeyMap() { auto device_id = xkb_x11_get_core_keyboard_device_id(mConnection); if (device_id == -1) { MLOG_ERROR("Failed to get connection for keymap"); } auto xkb_keymap = xkb_x11_keymap_new_from_device(mXkbContext, mConnection, device_id, XKB_KEYMAP_COMPILE_NO_FLAGS); struct xkb_state* xkb_state = xkb_x11_state_new_from_device(xkb_keymap, mConnection, device_id); xkb_keymap_unref(mXkbKeymap); xkb_state_unref(mXkbState); mXkbKeymap = xkb_keymap; mXkbState = xkb_state; xcb_xkb_select_events_details_t details; auto cookie = xcb_xkb_select_events(mConnection, XCB_XKB_ID_USE_CORE_KBD, XCB_XKB_EVENT_TYPE_STATE_NOTIFY, 0, XCB_XKB_EVENT_TYPE_STATE_NOTIFY, 0, 0, &details); // Check errors auto error = xcb_request_check(mConnection, cookie); if (error) { MLOG_ERROR("Failed to select XKB events"); } }