diff options
| author | Vaxry <vaxry@vaxry.net> | 2024-05-03 00:31:48 +0100 |
|---|---|---|
| committer | Vaxry <vaxry@vaxry.net> | 2024-05-03 00:31:48 +0100 |
| commit | 6aa2d123ae2a601a1775486f6988385124de9369 (patch) | |
| tree | b72c13eb2e3b1834793886d1ba744f3a6116185b /src/protocols/VirtualKeyboard.cpp | |
| parent | a3ca016d42283ce1d2d5ffca40b93123b4290f4b (diff) | |
virtual-keyboard: move to new impl
Diffstat (limited to 'src/protocols/VirtualKeyboard.cpp')
| -rw-r--r-- | src/protocols/VirtualKeyboard.cpp | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/src/protocols/VirtualKeyboard.cpp b/src/protocols/VirtualKeyboard.cpp new file mode 100644 index 00000000..fa364a96 --- /dev/null +++ b/src/protocols/VirtualKeyboard.cpp @@ -0,0 +1,136 @@ +#include "VirtualKeyboard.hpp" +#include <sys/mman.h> + +#define LOGM PROTO::virtualKeyboard->protoLog + +static const struct wlr_keyboard_impl virtualKeyboardImpl = { + .name = "virtual-keyboard", +}; + +CVirtualKeyboard::CVirtualKeyboard(SP<CZwpVirtualKeyboardV1> resource_) : resource(resource_) { + if (!good()) + return; + + resource->setDestroy([this](CZwpVirtualKeyboardV1* r) { + events.destroy.emit(); + PROTO::virtualKeyboard->destroyResource(this); + }); + resource->setOnDestroy([this](CZwpVirtualKeyboardV1* r) { + events.destroy.emit(); + PROTO::virtualKeyboard->destroyResource(this); + }); + + resource->setKey([this](CZwpVirtualKeyboardV1* r, uint32_t timeMs, uint32_t key, uint32_t state) { + if (!hasKeymap) { + r->error(ZWP_VIRTUAL_KEYBOARD_V1_ERROR_NO_KEYMAP, "Key event received before a keymap was set"); + return; + } + + wlr_keyboard_key_event event = { + .time_msec = timeMs, + .keycode = key, + .update_state = false, + .state = (wl_keyboard_key_state)state, + }; + wlr_keyboard_notify_key(&keyboard, &event); + }); + + resource->setModifiers([this](CZwpVirtualKeyboardV1* r, uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group) { + if (!hasKeymap) { + r->error(ZWP_VIRTUAL_KEYBOARD_V1_ERROR_NO_KEYMAP, "Mods event received before a keymap was set"); + return; + } + + wlr_keyboard_notify_modifiers(&keyboard, depressed, latched, locked, group); + }); + + resource->setKeymap([this](CZwpVirtualKeyboardV1* r, uint32_t fmt, int32_t fd, uint32_t len) { + auto xkbContext = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + if (!xkbContext) { + LOGM(ERR, "xkbContext creation failed"); + r->noMemory(); + close(fd); + return; + } + + auto keymapData = mmap(nullptr, len, PROT_READ, MAP_PRIVATE, fd, 0); + if (keymapData == MAP_FAILED) { + LOGM(ERR, "keymapData alloc failed"); + xkb_context_unref(xkbContext); + r->noMemory(); + close(fd); + return; + } + + auto xkbKeymap = xkb_keymap_new_from_string(xkbContext, (const char*)keymapData, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS); + munmap(keymapData, len); + + if (!xkbKeymap) { + LOGM(ERR, "xkbKeymap creation failed"); + xkb_context_unref(xkbContext); + r->noMemory(); + close(fd); + return; + } + + wlr_keyboard_set_keymap(&keyboard, xkbKeymap); + hasKeymap = true; + + xkb_keymap_unref(xkbKeymap); + xkb_context_unref(xkbContext); + close(fd); + }); + + wlr_keyboard_init(&keyboard, &virtualKeyboardImpl, "CVirtualKeyboard"); +} + +CVirtualKeyboard::~CVirtualKeyboard() { + wlr_keyboard_finish(&keyboard); + events.destroy.emit(); +} + +bool CVirtualKeyboard::good() { + return resource->resource(); +} + +wlr_keyboard* CVirtualKeyboard::wlr() { + return &keyboard; +} + +wl_client* CVirtualKeyboard::client() { + return resource->client(); +} + +CVirtualKeyboardProtocol::CVirtualKeyboardProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { + ; +} + +void CVirtualKeyboardProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { + const auto RESOURCE = m_vManagers.emplace_back(std::make_unique<CZwpVirtualKeyboardManagerV1>(client, ver, id)).get(); + RESOURCE->setOnDestroy([this](CZwpVirtualKeyboardManagerV1* p) { this->onManagerResourceDestroy(p->resource()); }); + + RESOURCE->setCreateVirtualKeyboard([this](CZwpVirtualKeyboardManagerV1* pMgr, wl_resource* seat, uint32_t id) { this->onCreateKeeb(pMgr, seat, id); }); +} + +void CVirtualKeyboardProtocol::onManagerResourceDestroy(wl_resource* res) { + std::erase_if(m_vManagers, [&](const auto& other) { return other->resource() == res; }); +} + +void CVirtualKeyboardProtocol::destroyResource(CVirtualKeyboard* keeb) { + std::erase_if(m_vKeyboards, [&](const auto& other) { return other.get() == keeb; }); +} + +void CVirtualKeyboardProtocol::onCreateKeeb(CZwpVirtualKeyboardManagerV1* pMgr, wl_resource* seat, uint32_t id) { + + const auto RESOURCE = m_vKeyboards.emplace_back(std::make_shared<CVirtualKeyboard>(std::make_shared<CZwpVirtualKeyboardV1>(pMgr->client(), pMgr->version(), id))); + + if (!RESOURCE->good()) { + pMgr->noMemory(); + m_vKeyboards.pop_back(); + return; + } + + LOGM(LOG, "New VKeyboard at id {}", id); + + events.newKeyboard.emit(RESOURCE); +}
\ No newline at end of file |
