83 lines
2.2 KiB
C++
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");
|
|
}
|
|
}
|