Add XKB interface for x11

This commit is contained in:
James Grogan 2022-11-17 11:28:18 +00:00
parent 7ad237edc1
commit cf9bace272
15 changed files with 232 additions and 31 deletions

View file

@ -1,25 +1,83 @@
#include "XcbKeyboard.h"
XcbKeyboard::XcbKeyboard()
: Keyboard()
// Header is c-like, uses explicit as a var
#define explicit explicit_
#include <xcb/xkb.h>
#undef explicit
#include <xkbcommon/xkbcommon-x11.h>
#include "FileLogger.h"
XcbKeyboard::XcbKeyboard(xcb_connection_t* connection)
: Keyboard(),
mConnection(connection)
{
mKeyMap = {{10, "1"}, {11, "2"}, {12, "3"}, {13, "4"}, {14, "5"}, {15, "6"},
{16, "7"}, {17, "8"}, {18, "9"}, {19, "0"}, {20, "-"}, {21, "+"}, {22, "KEY_BACK"},
{24, "q"}, {25, "w"}, {26, "e"}, {27, "r"}, {28, "t"}, {29, "y"},
{30, "u"}, {31, "i"}, {32, "o"}, {33, "p"}, {34, "["}, {35, "]"}, {36, "KEY_RETURN"},
{38, "a"}, {39, "s"}, {40, "d"}, {41, "f"}, {42, "g"}, {43, "h"},
{44, "j"}, {45, "k"}, {46, "l"}, {47, ":"}, {48, "'"}, {49, "#"},
{52, "z"}, {53, "x"}, {54, "c"}, {55, "v"}, {56, "b"},
{57, "n"}, {58, "m"}, {59, ","}, {60, "."}, {61, "/"},
{65, "KEY_SPACE"}, {66, "KEY_CAPS"}};
mXkbContext = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
if (!mXkbContext)
{
MLOG_ERROR("Failed to get XKB context");
}
}
std::unique_ptr<XcbKeyboard> XcbKeyboard::Create()
std::unique_ptr<XcbKeyboard> XcbKeyboard::Create(xcb_connection_t* connection)
{
return std::make_unique<XcbKeyboard>();
return std::make_unique<XcbKeyboard>(connection);
}
std::string XcbKeyboard::GetKeyString(KeyCode keyCode)
void XcbKeyboard::updateState(xcb_xkb_state_notify_event_t *state)
{
return mKeyMap[keyCode];
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");
}
}