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 | |
| parent | a3ca016d42283ce1d2d5ffca40b93123b4290f4b (diff) | |
virtual-keyboard: move to new impl
Diffstat (limited to 'src/protocols')
| -rw-r--r-- | src/protocols/VirtualKeyboard.cpp | 136 | ||||
| -rw-r--r-- | src/protocols/VirtualKeyboard.hpp | 54 |
2 files changed, 190 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 diff --git a/src/protocols/VirtualKeyboard.hpp b/src/protocols/VirtualKeyboard.hpp new file mode 100644 index 00000000..b922b0c5 --- /dev/null +++ b/src/protocols/VirtualKeyboard.hpp @@ -0,0 +1,54 @@ +#pragma once + +#include <memory> +#include <vector> +#include <cstdint> +#include "WaylandProtocol.hpp" +#include "virtual-keyboard-unstable-v1.hpp" +#include "../helpers/signal/Signal.hpp" + +class CVirtualKeyboard { + public: + CVirtualKeyboard(SP<CZwpVirtualKeyboardV1> resource_); + ~CVirtualKeyboard(); + + struct { + CSignal destroy; + } events; + + bool good(); + wlr_keyboard* wlr(); + wl_client* client(); + + private: + SP<CZwpVirtualKeyboardV1> resource; + wlr_keyboard keyboard; + + bool hasKeymap = false; +}; + +class CVirtualKeyboardProtocol : public IWaylandProtocol { + public: + CVirtualKeyboardProtocol(const wl_interface* iface, const int& ver, const std::string& name); + + virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); + + struct { + CSignal newKeyboard; // SP<CVirtualKeyboard> + } events; + + private: + void onManagerResourceDestroy(wl_resource* res); + void destroyResource(CVirtualKeyboard* keeb); + void onCreateKeeb(CZwpVirtualKeyboardManagerV1* pMgr, wl_resource* seat, uint32_t id); + + // + std::vector<UP<CZwpVirtualKeyboardManagerV1>> m_vManagers; + std::vector<SP<CVirtualKeyboard>> m_vKeyboards; + + friend class CVirtualKeyboard; +}; + +namespace PROTO { + inline UP<CVirtualKeyboardProtocol> virtualKeyboard; +}; |
