stuff-from-scratch/src/windows/ui_interfaces/x11/XcbKeyboard.cpp
2022-11-17 11:28:18 +00:00

83 lines
2.2 KiB
C++

#include "XcbKeyboard.h"
// 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)
{
mXkbContext = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
if (!mXkbContext)
{
MLOG_ERROR("Failed to get XKB context");
}
}
std::unique_ptr<XcbKeyboard> XcbKeyboard::Create(xcb_connection_t* connection)
{
return std::make_unique<XcbKeyboard>(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");
}
}