virtual-keyboard: move to new impl

This commit is contained in:
Vaxry 2024-05-03 00:31:48 +01:00
parent a3ca016d42
commit 6aa2d123ae
14 changed files with 370 additions and 67 deletions

View file

@ -245,8 +245,6 @@ void CCompositor::initServer() {
m_sWLROutputMgr = wlr_output_manager_v1_create(m_sWLDisplay);
m_sWLRVKeyboardMgr = wlr_virtual_keyboard_manager_v1_create(m_sWLDisplay);
m_sWLRVirtPtrMgr = wlr_virtual_pointer_manager_v1_create(m_sWLDisplay);
m_sWRLDRMLeaseMgr = wlr_drm_lease_v1_manager_create(m_sWLDisplay, m_sWLRBackend);
@ -308,7 +306,6 @@ void CCompositor::initAllSignals() {
addWLSignal(&m_sWLROutputMgr->events.apply, &Events::listen_outputMgrApply, m_sWLROutputMgr, "OutputMgr");
addWLSignal(&m_sWLROutputMgr->events.test, &Events::listen_outputMgrTest, m_sWLROutputMgr, "OutputMgr");
addWLSignal(&m_sWLRVirtPtrMgr->events.new_virtual_pointer, &Events::listen_newVirtPtr, m_sWLRVirtPtrMgr, "VirtPtrMgr");
addWLSignal(&m_sWLRVKeyboardMgr->events.new_virtual_keyboard, &Events::listen_newVirtualKeyboard, m_sWLRVKeyboardMgr, "VKeyboardMgr");
addWLSignal(&m_sWLRRenderer->events.destroy, &Events::listen_RendererDestroy, m_sWLRRenderer, "WLRRenderer");
if (m_sWRLDRMLeaseMgr)
@ -350,7 +347,6 @@ void CCompositor::removeAllSignals() {
removeWLSignal(&Events::listen_outputMgrApply);
removeWLSignal(&Events::listen_outputMgrTest);
removeWLSignal(&Events::listen_newVirtPtr);
removeWLSignal(&Events::listen_newVirtualKeyboard);
removeWLSignal(&Events::listen_RendererDestroy);
if (m_sWRLDRMLeaseMgr)

View file

@ -40,32 +40,31 @@ class CCompositor {
~CCompositor();
// ------------------ WLR BASICS ------------------ //
wl_display* m_sWLDisplay;
wl_event_loop* m_sWLEventLoop;
wlr_backend* m_sWLRBackend;
wlr_session* m_sWLRSession;
wlr_renderer* m_sWLRRenderer;
wlr_allocator* m_sWLRAllocator;
wlr_compositor* m_sWLRCompositor;
wlr_subcompositor* m_sWLRSubCompositor;
wlr_data_device_manager* m_sWLRDataDevMgr;
wlr_drm* m_sWRLDRM;
wlr_drm_lease_v1_manager* m_sWRLDRMLeaseMgr;
wlr_output_layout* m_sWLROutputLayout;
wlr_layer_shell_v1* m_sWLRLayerShell;
wlr_xdg_shell* m_sWLRXDGShell;
wlr_cursor* m_sWLRCursor;
wlr_virtual_keyboard_manager_v1* m_sWLRVKeyboardMgr;
wlr_output_manager_v1* m_sWLROutputMgr;
wlr_presentation* m_sWLRPresentation;
wlr_egl* m_sWLREGL;
int m_iDRMFD;
wlr_server_decoration_manager* m_sWLRServerDecoMgr;
wlr_virtual_pointer_manager_v1* m_sWLRVirtPtrMgr;
wlr_tablet_manager_v2* m_sWLRTabletManager;
wlr_xdg_foreign_registry* m_sWLRForeignRegistry;
wlr_linux_dmabuf_v1* m_sWLRLinuxDMABuf;
wlr_backend* m_sWLRHeadlessBackend;
wl_display* m_sWLDisplay;
wl_event_loop* m_sWLEventLoop;
wlr_backend* m_sWLRBackend;
wlr_session* m_sWLRSession;
wlr_renderer* m_sWLRRenderer;
wlr_allocator* m_sWLRAllocator;
wlr_compositor* m_sWLRCompositor;
wlr_subcompositor* m_sWLRSubCompositor;
wlr_data_device_manager* m_sWLRDataDevMgr;
wlr_drm* m_sWRLDRM;
wlr_drm_lease_v1_manager* m_sWRLDRMLeaseMgr;
wlr_output_layout* m_sWLROutputLayout;
wlr_layer_shell_v1* m_sWLRLayerShell;
wlr_xdg_shell* m_sWLRXDGShell;
wlr_cursor* m_sWLRCursor;
wlr_output_manager_v1* m_sWLROutputMgr;
wlr_presentation* m_sWLRPresentation;
wlr_egl* m_sWLREGL;
int m_iDRMFD;
wlr_server_decoration_manager* m_sWLRServerDecoMgr;
wlr_virtual_pointer_manager_v1* m_sWLRVirtPtrMgr;
wlr_tablet_manager_v2* m_sWLRTabletManager;
wlr_xdg_foreign_registry* m_sWLRForeignRegistry;
wlr_linux_dmabuf_v1* m_sWLRLinuxDMABuf;
wlr_backend* m_sWLRHeadlessBackend;
// ------------------------------------------------- //
std::string m_szHyprTempDataRoot = "";

View file

@ -140,12 +140,6 @@ void Events::listener_pinchEnd(wl_listener* listener, void* data) {
PROTO::pointerGestures->pinchEnd(EV->time_msec, EV->cancelled);
}
void Events::listener_newVirtualKeyboard(wl_listener* listener, void* data) {
const auto WLRKB = (wlr_virtual_keyboard_v1*)data;
g_pInputManager->newVirtualKeyboard(&WLRKB->keyboard.base);
}
void Events::listener_touchBegin(wl_listener* listener, void* data) {
g_pInputManager->onTouchDown((wlr_touch_down_event*)data);
}

View file

@ -106,9 +106,6 @@ namespace Events {
LISTENER(pinchUpdate);
LISTENER(pinchEnd);
// IME
LISTENER(newVirtualKeyboard);
// Touch
LISTENER(touchBegin);
LISTENER(touchEnd);

View file

@ -10,6 +10,7 @@
#include "Region.hpp"
class CMonitor;
class CVirtualKeyboard;
struct SRenderData {
CMonitor* pMonitor;
@ -71,23 +72,25 @@ struct SKeyboard {
DYNLISTENER(keyboardKeymap);
DYNLISTENER(keyboardDestroy);
bool isVirtual = false;
bool active = false;
bool enabled = true;
bool isVirtual = false;
bool active = false;
bool enabled = true;
xkb_layout_index_t activeLayout = 0;
xkb_state* xkbTranslationState = nullptr;
WP<CVirtualKeyboard> virtKeyboard;
std::string name = "";
std::string xkbFilePath = "";
xkb_layout_index_t activeLayout = 0;
xkb_state* xkbTranslationState = nullptr;
SStringRuleNames currentRules;
int repeatRate = 0;
int repeatDelay = 0;
int numlockOn = -1;
bool resolveBindsBySym = false;
std::string name = "";
std::string xkbFilePath = "";
void updateXKBTranslationState(xkb_keymap* const keymap = nullptr);
SStringRuleNames currentRules;
int repeatRate = 0;
int repeatDelay = 0;
int numlockOn = -1;
bool resolveBindsBySym = false;
void updateXKBTranslationState(xkb_keymap* const keymap = nullptr);
// For the list lookup
bool operator==(const SKeyboard& rhs) const {

View file

@ -62,7 +62,6 @@ extern "C" {
#include <wlr/types/wlr_seat.h>
#include <wlr/types/wlr_server_decoration.h>
#include <wlr/types/wlr_viewporter.h>
#include <wlr/types/wlr_virtual_keyboard_v1.h>
#include <wlr/types/wlr_xdg_output_v1.h>
#include <wlr/types/wlr_xdg_shell.h>
#include <wlr/types/wlr_subcompositor.h>

View file

@ -20,6 +20,7 @@
#include "../protocols/IdleNotify.hpp"
#include "../protocols/SessionLock.hpp"
#include "../protocols/InputMethodV2.hpp"
#include "../protocols/VirtualKeyboard.hpp"
CProtocolManager::CProtocolManager() {
@ -43,6 +44,7 @@ CProtocolManager::CProtocolManager() {
PROTO::idle = std::make_unique<CIdleNotifyProtocol>(&ext_idle_notifier_v1_interface, 1, "IdleNotify");
PROTO::sessionLock = std::make_unique<CSessionLockProtocol>(&ext_session_lock_manager_v1_interface, 1, "SessionLock");
PROTO::ime = std::make_unique<CInputMethodV2Protocol>(&zwp_input_method_manager_v2_interface, 1, "IMEv2");
PROTO::virtualKeyboard = std::make_unique<CVirtualKeyboardProtocol>(&zwp_virtual_keyboard_manager_v1_interface, 1, "VirtualKeyboard");
// Old protocol implementations.
// TODO: rewrite them to use hyprwayland-scanner.

View file

@ -11,6 +11,7 @@
#include "../../protocols/IdleNotify.hpp"
#include "../../protocols/SessionLock.hpp"
#include "../../protocols/InputMethodV2.hpp"
#include "../../protocols/VirtualKeyboard.hpp"
CInputManager::CInputManager() {
m_sListeners.setCursorShape = PROTO::cursorShape->events.setShape.registerListener([this](std::any data) {
@ -37,6 +38,8 @@ CInputManager::CInputManager() {
});
m_sListeners.newIdleInhibitor = PROTO::idleInhibit->events.newIdleInhibitor.registerListener([this](std::any data) { this->newIdleInhibitor(data); });
m_sListeners.newVirtualKeyboard =
PROTO::virtualKeyboard->events.newKeyboard.registerListener([this](std::any data) { this->newVirtualKeyboard(std::any_cast<SP<CVirtualKeyboard>>(data)); });
}
CInputManager::~CInputManager() {
@ -786,23 +789,24 @@ void CInputManager::newKeyboard(wlr_input_device* keyboard) {
Debug::log(LOG, "New keyboard created, pointers Hypr: {:x} and WLR: {:x}", (uintptr_t)PNEWKEYBOARD, (uintptr_t)keyboard);
}
void CInputManager::newVirtualKeyboard(wlr_input_device* keyboard) {
void CInputManager::newVirtualKeyboard(SP<CVirtualKeyboard> keyboard) {
const auto PNEWKEYBOARD = &m_lKeyboards.emplace_back();
PNEWKEYBOARD->keyboard = keyboard;
PNEWKEYBOARD->isVirtual = true;
PNEWKEYBOARD->keyboard = &keyboard->wlr()->base;
PNEWKEYBOARD->isVirtual = true;
PNEWKEYBOARD->virtKeyboard = keyboard;
try {
PNEWKEYBOARD->name = getNameForNewDevice(keyboard->name);
PNEWKEYBOARD->name = getNameForNewDevice(keyboard->wlr()->base.name);
} catch (std::exception& e) {
Debug::log(ERR, "Keyboard had no name???"); // logic error
}
PNEWKEYBOARD->hyprListener_keyboardMod.initCallback(&wlr_keyboard_from_input_device(keyboard)->events.modifiers, &Events::listener_keyboardMod, PNEWKEYBOARD, "Keyboard");
PNEWKEYBOARD->hyprListener_keyboardKey.initCallback(&wlr_keyboard_from_input_device(keyboard)->events.key, &Events::listener_keyboardKey, PNEWKEYBOARD, "Keyboard");
PNEWKEYBOARD->hyprListener_keyboardDestroy.initCallback(&keyboard->events.destroy, &Events::listener_keyboardDestroy, PNEWKEYBOARD, "Keyboard");
PNEWKEYBOARD->hyprListener_keyboardMod.initCallback(&keyboard->wlr()->events.modifiers, &Events::listener_keyboardMod, PNEWKEYBOARD, "VKeyboard");
PNEWKEYBOARD->hyprListener_keyboardKey.initCallback(&keyboard->wlr()->events.key, &Events::listener_keyboardKey, PNEWKEYBOARD, "VKeyboard");
PNEWKEYBOARD->hyprListener_keyboardDestroy.initCallback(&keyboard->wlr()->base.events.destroy, &Events::listener_keyboardDestroy, PNEWKEYBOARD, "VKeyboard");
PNEWKEYBOARD->hyprListener_keyboardKeymap.initCallback(
&wlr_keyboard_from_input_device(keyboard)->events.keymap,
&keyboard->wlr()->events.keymap,
[&](void* owner, void* data) {
const auto PKEYBOARD = (SKeyboard*)owner;
const auto LAYOUT = getActiveLayoutForKeyboard(PKEYBOARD);
@ -810,7 +814,7 @@ void CInputManager::newVirtualKeyboard(wlr_input_device* keyboard) {
g_pEventManager->postEvent(SHyprIPCEvent{"activelayout", PKEYBOARD->name + "," + LAYOUT});
EMIT_HOOK_EVENT("activeLayout", (std::vector<void*>{PKEYBOARD, (void*)&LAYOUT}));
},
PNEWKEYBOARD, "Keyboard");
PNEWKEYBOARD, "VKeyboard");
disableAllKeyboards(true);
@ -820,9 +824,9 @@ void CInputManager::newVirtualKeyboard(wlr_input_device* keyboard) {
applyConfigToKeyboard(PNEWKEYBOARD);
wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, wlr_keyboard_from_input_device(keyboard));
wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, keyboard->wlr());
Debug::log(LOG, "New virtual keyboard created, pointers Hypr: {:x} and WLR: {:x}", (uintptr_t)PNEWKEYBOARD, (uintptr_t)keyboard);
Debug::log(LOG, "New virtual keyboard created, pointers Hypr: {:x} and WLR: {:x}", (uintptr_t)PNEWKEYBOARD, (uintptr_t)keyboard->wlr());
}
void CInputManager::setKeyboardLayout() {
@ -1276,8 +1280,10 @@ void CInputManager::onKeyboardMod(void* data, SKeyboard* pKeyboard) {
}
bool CInputManager::shouldIgnoreVirtualKeyboard(SKeyboard* pKeyboard) {
return !pKeyboard ||
(!m_sIMERelay.m_pIME.expired() && m_sIMERelay.m_pIME.lock()->grabClient() == wl_resource_get_client(wlr_input_device_get_virtual_keyboard(pKeyboard->keyboard)->resource));
if (!pKeyboard->isVirtual)
return false;
return !pKeyboard || (!m_sIMERelay.m_pIME.expired() && m_sIMERelay.m_pIME.lock()->grabClient() == pKeyboard->virtKeyboard.lock()->client());
}
void CInputManager::refocus() {

View file

@ -11,6 +11,7 @@
class CPointerConstraint;
class CWindow;
class CIdleInhibitor;
class CVirtualKeyboard;
enum eClickBehaviorMode {
CLICKMODE_DEFAULT = 0,
@ -77,7 +78,7 @@ class CInputManager {
void onKeyboardMod(void*, SKeyboard*);
void newKeyboard(wlr_input_device*);
void newVirtualKeyboard(wlr_input_device*);
void newVirtualKeyboard(SP<CVirtualKeyboard>);
void newMouse(wlr_input_device*, bool virt = false);
void newTouchDevice(wlr_input_device*);
void newSwitch(wlr_input_device*);
@ -199,6 +200,7 @@ class CInputManager {
struct {
CHyprSignalListener setCursorShape;
CHyprSignalListener newIdleInhibitor;
CHyprSignalListener newVirtualKeyboard;
} m_sListeners;
bool m_bCursorImageOverridden = false;

View file

@ -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);
}

View file

@ -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;
};