aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rwxr-xr-xCMakeLists.txt1
-rw-r--r--protocols/meson.build1
-rw-r--r--protocols/virtual-keyboard-unstable-v1.xml113
-rw-r--r--src/Compositor.cpp4
-rw-r--r--src/Compositor.hpp51
-rw-r--r--src/events/Devices.cpp6
-rw-r--r--src/events/Events.hpp3
-rw-r--r--src/helpers/WLClasses.hpp29
-rw-r--r--src/includes.hpp1
-rw-r--r--src/managers/ProtocolManager.cpp2
-rw-r--r--src/managers/input/InputManager.cpp32
-rw-r--r--src/managers/input/InputManager.hpp4
-rw-r--r--src/protocols/VirtualKeyboard.cpp136
-rw-r--r--src/protocols/VirtualKeyboard.hpp54
14 files changed, 370 insertions, 67 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 675844e0..d485977c 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -261,6 +261,7 @@ protocol("unstable/text-input/text-input-unstable-v1.xml" "text-input-unstable-v
protocolNew("protocols/wlr-gamma-control-unstable-v1.xml" "wlr-gamma-control-unstable-v1" true)
protocolNew("protocols/wlr-foreign-toplevel-management-unstable-v1.xml" "wlr-foreign-toplevel-management-unstable-v1" true)
protocolNew("protocols/wlr-output-power-management-unstable-v1.xml" "wlr-output-power-management-unstable-v1" true)
+protocolNew("protocols/virtual-keyboard-unstable-v1.xml" "virtual-keyboard-unstable-v1" true)
protocolNew("protocols/input-method-unstable-v2.xml" "input-method-unstable-v2" true)
protocolNew("staging/tearing-control/tearing-control-v1.xml" "tearing-control-v1" false)
protocolNew("staging/fractional-scale/fractional-scale-v1.xml" "fractional-scale-v1" false)
diff --git a/protocols/meson.build b/protocols/meson.build
index 4017ff27..57bca3d1 100644
--- a/protocols/meson.build
+++ b/protocols/meson.build
@@ -39,6 +39,7 @@ new_protocols = [
['wlr-foreign-toplevel-management-unstable-v1.xml'],
['wlr-output-power-management-unstable-v1.xml'],
['input-method-unstable-v2.xml'],
+ ['virtual-keyboard-unstable-v1.xml'],
[wl_protocol_dir, 'staging/tearing-control/tearing-control-v1.xml'],
[wl_protocol_dir, 'staging/fractional-scale/fractional-scale-v1.xml'],
[wl_protocol_dir, 'unstable/xdg-output/xdg-output-unstable-v1.xml'],
diff --git a/protocols/virtual-keyboard-unstable-v1.xml b/protocols/virtual-keyboard-unstable-v1.xml
new file mode 100644
index 00000000..5095c91b
--- /dev/null
+++ b/protocols/virtual-keyboard-unstable-v1.xml
@@ -0,0 +1,113 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="virtual_keyboard_unstable_v1">
+ <copyright>
+ Copyright © 2008-2011 Kristian Høgsberg
+ Copyright © 2010-2013 Intel Corporation
+ Copyright © 2012-2013 Collabora, Ltd.
+ Copyright © 2018 Purism SPC
+
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of this software and associated documentation files (the "Software"),
+ to deal in the Software without restriction, including without limitation
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ and/or sell copies of the Software, and to permit persons to whom the
+ Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice (including the next
+ paragraph) shall be included in all copies or substantial portions of the
+ Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+ </copyright>
+
+ <interface name="zwp_virtual_keyboard_v1" version="1">
+ <description summary="virtual keyboard">
+ The virtual keyboard provides an application with requests which emulate
+ the behaviour of a physical keyboard.
+
+ This interface can be used by clients on its own to provide raw input
+ events, or it can accompany the input method protocol.
+ </description>
+
+ <request name="keymap">
+ <description summary="keyboard mapping">
+ Provide a file descriptor to the compositor which can be
+ memory-mapped to provide a keyboard mapping description.
+
+ Format carries a value from the keymap_format enumeration.
+ </description>
+ <arg name="format" type="uint" summary="keymap format"/>
+ <arg name="fd" type="fd" summary="keymap file descriptor"/>
+ <arg name="size" type="uint" summary="keymap size, in bytes"/>
+ </request>
+
+ <enum name="error">
+ <entry name="no_keymap" value="0" summary="No keymap was set"/>
+ </enum>
+
+ <request name="key">
+ <description summary="key event">
+ A key was pressed or released.
+ The time argument is a timestamp with millisecond granularity, with an
+ undefined base. All requests regarding a single object must share the
+ same clock.
+
+ Keymap must be set before issuing this request.
+
+ State carries a value from the key_state enumeration.
+ </description>
+ <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
+ <arg name="key" type="uint" summary="key that produced the event"/>
+ <arg name="state" type="uint" summary="physical state of the key"/>
+ </request>
+
+ <request name="modifiers">
+ <description summary="modifier and group state">
+ Notifies the compositor that the modifier and/or group state has
+ changed, and it should update state.
+
+ The client should use wl_keyboard.modifiers event to synchronize its
+ internal state with seat state.
+
+ Keymap must be set before issuing this request.
+ </description>
+ <arg name="mods_depressed" type="uint" summary="depressed modifiers"/>
+ <arg name="mods_latched" type="uint" summary="latched modifiers"/>
+ <arg name="mods_locked" type="uint" summary="locked modifiers"/>
+ <arg name="group" type="uint" summary="keyboard layout"/>
+ </request>
+
+ <request name="destroy" type="destructor" since="1">
+ <description summary="destroy the virtual keyboard keyboard object"/>
+ </request>
+ </interface>
+
+ <interface name="zwp_virtual_keyboard_manager_v1" version="1">
+ <description summary="virtual keyboard manager">
+ A virtual keyboard manager allows an application to provide keyboard
+ input events as if they came from a physical keyboard.
+ </description>
+
+ <enum name="error">
+ <entry name="unauthorized" value="0" summary="client not authorized to use the interface"/>
+ </enum>
+
+ <request name="create_virtual_keyboard">
+ <description summary="Create a new virtual keyboard">
+ Creates a new virtual keyboard associated to a seat.
+
+ If the compositor enables a keyboard to perform arbitrary actions, it
+ should present an error when an untrusted client requests a new
+ keyboard.
+ </description>
+ <arg name="seat" type="object" interface="wl_seat"/>
+ <arg name="id" type="new_id" interface="zwp_virtual_keyboard_v1"/>
+ </request>
+ </interface>
+</protocol>
diff --git a/src/Compositor.cpp b/src/Compositor.cpp
index 9ed0ea38..80e61a25 100644
--- a/src/Compositor.cpp
+++ b/src/Compositor.cpp
@@ -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)
diff --git a/src/Compositor.hpp b/src/Compositor.hpp
index b867742b..175688c7 100644
--- a/src/Compositor.hpp
+++ b/src/Compositor.hpp
@@ -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 = "";
diff --git a/src/events/Devices.cpp b/src/events/Devices.cpp
index 43433ba2..bf72d89f 100644
--- a/src/events/Devices.cpp
+++ b/src/events/Devices.cpp
@@ -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);
}
diff --git a/src/events/Events.hpp b/src/events/Events.hpp
index 2dabac11..c7e98e65 100644
--- a/src/events/Events.hpp
+++ b/src/events/Events.hpp
@@ -106,9 +106,6 @@ namespace Events {
LISTENER(pinchUpdate);
LISTENER(pinchEnd);
- // IME
- LISTENER(newVirtualKeyboard);
-
// Touch
LISTENER(touchBegin);
LISTENER(touchEnd);
diff --git a/src/helpers/WLClasses.hpp b/src/helpers/WLClasses.hpp
index 2f14059b..d9b3ba20 100644
--- a/src/helpers/WLClasses.hpp
+++ b/src/helpers/WLClasses.hpp
@@ -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 {
diff --git a/src/includes.hpp b/src/includes.hpp
index 15d5c1aa..052c973e 100644
--- a/src/includes.hpp
+++ b/src/includes.hpp
@@ -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>
diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp
index 09ca5206..122e2ff1 100644
--- a/src/managers/ProtocolManager.cpp
+++ b/src/managers/ProtocolManager.cpp
@@ -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.
diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp
index 7d14719f..7b851d88 100644
--- a/src/managers/input/InputManager.cpp
+++ b/src/managers/input/InputManager.cpp
@@ -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() {
diff --git a/src/managers/input/InputManager.hpp b/src/managers/input/InputManager.hpp
index 08e9e831..27551249 100644
--- a/src/managers/input/InputManager.hpp
+++ b/src/managers/input/InputManager.hpp
@@ -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;
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;
+};