diff options
| author | JS Deck <jsdeckerido@gmail.com> | 2025-08-04 16:29:39 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-08-04 21:29:39 +0200 |
| commit | 2be309de1df5e4262175fbcc58e6dd8de4e0e6d3 (patch) | |
| tree | 866629ba5a4b9b45d8720383e4332726444f3566 /src | |
| parent | 6491bb4fb7c7e86d9168a104d5b87ace4e1b978d (diff) | |
virtualkeyboard: Add options to skip releasing pressed keys on close and to skip sharing key states (#11214)
Diffstat (limited to 'src')
| -rw-r--r-- | src/config/ConfigDescriptions.hpp | 23 | ||||
| -rw-r--r-- | src/config/ConfigManager.cpp | 5 | ||||
| -rw-r--r-- | src/debug/HyprCtl.cpp | 2 | ||||
| -rw-r--r-- | src/devices/IKeyboard.cpp | 37 | ||||
| -rw-r--r-- | src/devices/IKeyboard.hpp | 19 | ||||
| -rw-r--r-- | src/devices/Keyboard.cpp | 5 | ||||
| -rw-r--r-- | src/devices/VirtualKeyboard.cpp | 10 | ||||
| -rw-r--r-- | src/devices/VirtualKeyboard.hpp | 2 | ||||
| -rw-r--r-- | src/helpers/MiscFunctions.cpp | 52 | ||||
| -rw-r--r-- | src/helpers/MiscFunctions.hpp | 45 | ||||
| -rw-r--r-- | src/managers/KeybindManager.cpp | 8 | ||||
| -rw-r--r-- | src/managers/SeatManager.cpp | 18 | ||||
| -rw-r--r-- | src/managers/input/InputManager.cpp | 92 | ||||
| -rw-r--r-- | src/managers/input/InputManager.hpp | 10 | ||||
| -rw-r--r-- | src/managers/permissions/DynamicPermissionManager.cpp | 45 | ||||
| -rw-r--r-- | src/protocols/VirtualKeyboard.cpp | 51 | ||||
| -rw-r--r-- | src/protocols/VirtualKeyboard.hpp | 1 | ||||
| -rw-r--r-- | src/protocols/core/Seat.cpp | 21 | ||||
| -rw-r--r-- | src/protocols/core/Seat.hpp | 3 |
19 files changed, 313 insertions, 136 deletions
diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 852a86d0..aeff3906 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -677,6 +677,23 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = { }, /* + * input:virtualkeyboard: + */ + + SConfigOptionDescription{ + .value = "input:virtualkeyboard:share_states", + .description = "Unify key down states and modifier states with other keyboards", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + SConfigOptionDescription{ + .value = "input:virtualkeyboard:release_pressed_on_close", + .description = "Release all pressed keys by virtual keyboard on close.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{false}, + }, + + /* * input:tablet: */ @@ -1151,6 +1168,12 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = { .data = SConfigOptionDescription::SBoolData{false}, }, SConfigOptionDescription{ + .value = "misc:name_vk_after_proc", + .description = "Name virtual keyboards after the processes that create them. E.g. /usr/bin/fcitx5 will have hl-virtual-keyboard-fcitx5.", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, + SConfigOptionDescription{ .value = "misc:always_follow_on_dnd", .description = "Will make mouse focus follow the mouse when drag and dropping. Recommended to leave it enabled, especially for people using focus follows mouse at 0.", .type = CONFIG_OPTION_BOOL, diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index d49add0e..337682dc 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -473,6 +473,7 @@ CConfigManager::CConfigManager() { registerConfigVar("misc:vrr", Hyprlang::INT{0}); registerConfigVar("misc:mouse_move_enables_dpms", Hyprlang::INT{0}); registerConfigVar("misc:key_press_enables_dpms", Hyprlang::INT{0}); + registerConfigVar("misc:name_vk_after_proc", Hyprlang::INT{1}); registerConfigVar("misc:always_follow_on_dnd", Hyprlang::INT{1}); registerConfigVar("misc:layers_hog_keyboard_focus", Hyprlang::INT{1}); registerConfigVar("misc:animate_manual_resizes", Hyprlang::INT{0}); @@ -662,6 +663,8 @@ CConfigManager::CConfigManager() { registerConfigVar("input:touchdevice:transform", Hyprlang::INT{-1}); registerConfigVar("input:touchdevice:output", {"[[Auto]]"}); registerConfigVar("input:touchdevice:enabled", Hyprlang::INT{1}); + registerConfigVar("input:virtualkeyboard:share_states", Hyprlang::INT{0}); + registerConfigVar("input:virtualkeyboard:release_pressed_on_close", Hyprlang::INT{0}); registerConfigVar("input:tablet:transform", Hyprlang::INT{0}); registerConfigVar("input:tablet:output", {STRVAL_EMPTY}); registerConfigVar("input:tablet:region_position", Hyprlang::VEC2{0, 0}); @@ -797,6 +800,8 @@ CConfigManager::CConfigManager() { m_config->addSpecialConfigValue("device", "flip_y", Hyprlang::INT{0}); // only for touchpads m_config->addSpecialConfigValue("device", "drag_3fg", Hyprlang::INT{0}); // only for touchpads m_config->addSpecialConfigValue("device", "keybinds", Hyprlang::INT{1}); // enable/disable keybinds + m_config->addSpecialConfigValue("device", "share_states", Hyprlang::INT{0}); // only for virtualkeyboards + m_config->addSpecialConfigValue("device", "release_pressed_on_close", Hyprlang::INT{0}); // only for virtualkeyboards m_config->addSpecialCategory("monitorv2", {.key = "output"}); m_config->addSpecialConfigValue("monitorv2", "disabled", Hyprlang::INT{0}); diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 7cdd8ac0..cec41087 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -1342,7 +1342,7 @@ static std::string switchXKBLayoutRequest(eHyprCtlOutputFormat format, std::stri } return result.empty() ? "ok" : result; } else { - auto k = std::ranges::find_if(g_pInputManager->m_keyboards, [&](const auto& other) { return other->m_hlName == g_pInputManager->deviceNameToInternalString(KB); }); + auto k = std::ranges::find_if(g_pInputManager->m_keyboards, [&](const auto& other) { return other->m_hlName == deviceNameToInternalString(KB); }); if (k == g_pInputManager->m_keyboards.end()) return "device not found"; diff --git a/src/devices/IKeyboard.cpp b/src/devices/IKeyboard.cpp index 89ad8c16..0a22eb6e 100644 --- a/src/devices/IKeyboard.cpp +++ b/src/devices/IKeyboard.cpp @@ -378,19 +378,6 @@ bool IKeyboard::updateModifiersState() { } void IKeyboard::updateXkbStateWithKey(uint32_t xkbKey, bool pressed) { - - const auto contains = std::ranges::find(m_pressedXKB, xkbKey) != m_pressedXKB.end(); - - if (contains && pressed) - return; - if (!contains && !pressed) - return; - - if (contains) - std::erase(m_pressedXKB, xkbKey); - else - m_pressedXKB.emplace_back(xkbKey); - xkb_state_update_key(m_xkbState, xkbKey, pressed ? XKB_KEY_DOWN : XKB_KEY_UP); if (updateModifiersState()) { @@ -405,3 +392,27 @@ void IKeyboard::updateXkbStateWithKey(uint32_t xkbKey, bool pressed) { }); } } + +bool IKeyboard::updatePressed(uint32_t key, bool pressed) { + const auto contains = getPressed(key); + + if (contains && pressed) + return false; + if (!contains && !pressed) + return false; + + if (contains) + std::erase(m_pressed, key); + else + m_pressed.emplace_back(key); + + return true; +} + +bool IKeyboard::getPressed(uint32_t key) { + return std::ranges::contains(m_pressed, key); +} + +bool IKeyboard::shareStates() { + return m_shareStates; +} diff --git a/src/devices/IKeyboard.hpp b/src/devices/IKeyboard.hpp index 25a7efd1..f4fb667b 100644 --- a/src/devices/IKeyboard.hpp +++ b/src/devices/IKeyboard.hpp @@ -24,10 +24,13 @@ enum eKeyboardModifiers { class IKeyboard : public IHID { public: virtual ~IKeyboard(); - virtual uint32_t getCapabilities(); - virtual eHIDType getType(); - virtual bool isVirtual() = 0; - virtual SP<Aquamarine::IKeyboard> aq() = 0; + virtual uint32_t getCapabilities(); + virtual eHIDType getType(); + virtual bool isVirtual() = 0; + virtual wl_client* getClient() { + return nullptr; + }; + virtual SP<Aquamarine::IKeyboard> aq() = 0; struct SKeyEvent { uint32_t timeMs = 0; @@ -73,6 +76,8 @@ class IKeyboard : public IHID { bool updateModifiersState(); // rets whether changed void updateXkbStateWithKey(uint32_t xkbKey, bool pressed); void updateKeymapFD(); + bool getPressed(uint32_t key); + bool shareStates(); bool m_active = false; bool m_enabled = true; @@ -118,5 +123,9 @@ class IKeyboard : public IHID { private: void clearManuallyAllocd(); - std::vector<uint32_t> m_pressedXKB; + std::vector<uint32_t> m_pressed; + + protected: + bool updatePressed(uint32_t key, bool pressed); + bool m_shareStates = true; }; diff --git a/src/devices/Keyboard.cpp b/src/devices/Keyboard.cpp index 9ce37e6b..80f76c17 100644 --- a/src/devices/Keyboard.cpp +++ b/src/devices/Keyboard.cpp @@ -29,13 +29,16 @@ CKeyboard::CKeyboard(SP<Aquamarine::IKeyboard> keeb) : m_keyboard(keeb) { }); m_listeners.key = keeb->events.key.listen([this](const Aquamarine::IKeyboard::SKeyEvent& event) { + const auto UPDATED = updatePressed(event.key, event.pressed); + m_keyboardEvents.key.emit(SKeyEvent{ .timeMs = event.timeMs, .keycode = event.key, .state = event.pressed ? WL_KEYBOARD_KEY_STATE_PRESSED : WL_KEYBOARD_KEY_STATE_RELEASED, }); - updateXkbStateWithKey(event.key + 8, event.pressed); + if (UPDATED) + updateXkbStateWithKey(event.key + 8, event.pressed); }); m_listeners.modifiers = keeb->events.modifiers.listen([this] { diff --git a/src/devices/VirtualKeyboard.cpp b/src/devices/VirtualKeyboard.cpp index ea21a22b..97b7626a 100644 --- a/src/devices/VirtualKeyboard.cpp +++ b/src/devices/VirtualKeyboard.cpp @@ -1,6 +1,8 @@ #include "VirtualKeyboard.hpp" #include "../defines.hpp" #include "../protocols/VirtualKeyboard.hpp" +#include "../config/ConfigManager.hpp" +#include <wayland-server-protocol.h> SP<CVirtualKeyboard> CVirtualKeyboard::create(SP<CVirtualKeyboardV1Resource> keeb) { SP<CVirtualKeyboard> pKeeb = SP<CVirtualKeyboard>(new CVirtualKeyboard(keeb)); @@ -19,7 +21,10 @@ CVirtualKeyboard::CVirtualKeyboard(SP<CVirtualKeyboardV1Resource> keeb_) : m_key m_events.destroy.emit(); }); - m_listeners.key = keeb_->m_events.key.listen([this](const auto& event) { m_keyboardEvents.key.emit(event); }); + m_listeners.key = keeb_->m_events.key.listen([this](const auto& event) { + updatePressed(event.keycode, event.state == WL_KEYBOARD_KEY_STATE_PRESSED); + m_keyboardEvents.key.emit(event); + }); m_listeners.modifiers = keeb_->m_events.modifiers.listen([this](const SModifiersEvent& event) { updateModifiers(event.depressed, event.latched, event.locked, event.group); m_keyboardEvents.modifiers.emit(SModifiersEvent{ @@ -39,7 +44,8 @@ CVirtualKeyboard::CVirtualKeyboard(SP<CVirtualKeyboardV1Resource> keeb_) : m_key m_keyboardEvents.keymap.emit(event); }); - m_deviceName = keeb_->m_name; + m_deviceName = keeb_->m_name; + m_shareStates = g_pConfigManager->getDeviceInt(m_deviceName, "share_states", "input:virtualkeyboard:share_states"); } bool CVirtualKeyboard::isVirtual() { diff --git a/src/devices/VirtualKeyboard.hpp b/src/devices/VirtualKeyboard.hpp index 05e0a255..a0783d93 100644 --- a/src/devices/VirtualKeyboard.hpp +++ b/src/devices/VirtualKeyboard.hpp @@ -11,7 +11,7 @@ class CVirtualKeyboard : public IKeyboard { virtual bool isVirtual(); virtual SP<Aquamarine::IKeyboard> aq(); - wl_client* getClient(); + virtual wl_client* getClient(); private: CVirtualKeyboard(SP<CVirtualKeyboardV1Resource> keeb); diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index 90383ca5..721855fd 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -876,3 +876,55 @@ bool isNvidiaDriverVersionAtLeast(int threshold) { return driverMajor >= threshold; } + +std::expected<std::string, std::string> binaryNameForWlClient(wl_client* client) { + if (!client) + return std::unexpected("client unknown"); + + pid_t pid = 0; + wl_client_get_credentials(client, &pid, nullptr, nullptr); + + return binaryNameForPid(pid); +} + +std::expected<std::string, std::string> binaryNameForPid(pid_t pid) { + if (pid <= 0) + return std::unexpected("No pid for client"); + +#if defined(KERN_PROC_PATHNAME) + int mib[] = { + CTL_KERN, +#if defined(__NetBSD__) + KERN_PROC_ARGS, + pid, + KERN_PROC_PATHNAME, +#else + KERN_PROC, + KERN_PROC_PATHNAME, + pid, +#endif + }; + u_int miblen = sizeof(mib) / sizeof(mib[0]); + char exe[PATH_MAX] = "/nonexistent"; + size_t sz = sizeof(exe); + sysctl(mib, miblen, &exe, &sz, NULL, 0); + std::string path = exe; +#else + std::string path = std::format("/proc/{}/exe", (uint64_t)pid); +#endif + std::error_code ec; + + std::string fullPath = std::filesystem::canonical(path, ec); + + if (ec) + return std::unexpected("canonical failed"); + + return fullPath; +} + +std::string deviceNameToInternalString(std::string in) { + std::ranges::replace(in, ' ', '-'); + std::ranges::replace(in, '\n', '-'); + std::ranges::transform(in, in.begin(), ::tolower); + return in; +} diff --git a/src/helpers/MiscFunctions.hpp b/src/helpers/MiscFunctions.hpp index f361313b..8e507b6b 100644 --- a/src/helpers/MiscFunctions.hpp +++ b/src/helpers/MiscFunctions.hpp @@ -19,27 +19,30 @@ struct SWorkspaceIDName { std::string name; }; -std::string absolutePath(const std::string&, const std::string&); -std::string escapeJSONStrings(const std::string& str); -bool isDirection(const std::string&); -bool isDirection(const char&); -SWorkspaceIDName getWorkspaceIDNameFromString(const std::string&); -std::optional<std::string> cleanCmdForWorkspace(const std::string&, std::string); -float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Vector2D& p2); -void logSystemInfo(); -std::string execAndGet(const char*); -int64_t getPPIDof(int64_t pid); -std::expected<int64_t, std::string> configStringToInt(const std::string&); -Vector2D configStringToVector2D(const std::string&); -std::optional<float> getPlusMinusKeywordResult(std::string in, float relative); -double normalizeAngleRad(double ang); -std::vector<SCallstackFrameInfo> getBacktrace(); -void throwError(const std::string& err); -bool envEnabled(const std::string& env); -Hyprutils::OS::CFileDescriptor allocateSHMFile(size_t len); -bool allocateSHMFilePair(size_t size, Hyprutils::OS::CFileDescriptor& rw_fd_ptr, Hyprutils::OS::CFileDescriptor& ro_fd_ptr); -float stringToPercentage(const std::string& VALUE, const float REL); -bool isNvidiaDriverVersionAtLeast(int threshold); +std::string absolutePath(const std::string&, const std::string&); +std::string escapeJSONStrings(const std::string& str); +bool isDirection(const std::string&); +bool isDirection(const char&); +SWorkspaceIDName getWorkspaceIDNameFromString(const std::string&); +std::optional<std::string> cleanCmdForWorkspace(const std::string&, std::string); +float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Vector2D& p2); +void logSystemInfo(); +std::string execAndGet(const char*); +int64_t getPPIDof(int64_t pid); +std::expected<int64_t, std::string> configStringToInt(const std::string&); +Vector2D configStringToVector2D(const std::string&); +std::optional<float> getPlusMinusKeywordResult(std::string in, float relative); +double normalizeAngleRad(double ang); +std::vector<SCallstackFrameInfo> getBacktrace(); +void throwError(const std::string& err); +bool envEnabled(const std::string& env); +Hyprutils::OS::CFileDescriptor allocateSHMFile(size_t len); +bool allocateSHMFilePair(size_t size, Hyprutils::OS::CFileDescriptor& rw_fd_ptr, Hyprutils::OS::CFileDescriptor& ro_fd_ptr); +float stringToPercentage(const std::string& VALUE, const float REL); +bool isNvidiaDriverVersionAtLeast(int threshold); +std::expected<std::string, std::string> binaryNameForWlClient(wl_client* client); +std::expected<std::string, std::string> binaryNameForPid(pid_t pid); +std::string deviceNameToInternalString(std::string in); template <typename... Args> [[deprecated("use std::format instead")]] std::string getFormat(std::format_string<Args...> fmt, Args&&... args) { diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index d9b2bc1f..27b6f4b9 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -457,7 +457,7 @@ bool CKeybindManager::onKeyEvent(std::any event, SP<IKeyboard> pKeyboard) { if (handleInternalKeybinds(internalKeysym)) return false; - const auto MODS = g_pInputManager->accumulateModsFromAllKBs(); + const auto MODS = g_pInputManager->getModsFromAllKBs(); m_timeLastMs = e.timeMs; m_lastCode = KEYCODE; @@ -515,7 +515,7 @@ bool CKeybindManager::onKeyEvent(std::any event, SP<IKeyboard> pKeyboard) { } bool CKeybindManager::onAxisEvent(const IPointer::SAxisEvent& e) { - const auto MODS = g_pInputManager->accumulateModsFromAllKBs(); + const auto MODS = g_pInputManager->getModsFromAllKBs(); static auto PDELAY = CConfigValue<Hyprlang::INT>("binds:scroll_event_delay"); @@ -546,7 +546,7 @@ bool CKeybindManager::onAxisEvent(const IPointer::SAxisEvent& e) { } bool CKeybindManager::onMouseEvent(const IPointer::SButtonEvent& e) { - const auto MODS = g_pInputManager->accumulateModsFromAllKBs(); + const auto MODS = g_pInputManager->getModsFromAllKBs(); bool suppressEvent = false; @@ -2454,7 +2454,7 @@ SDispatchResult CKeybindManager::pass(std::string regexp) { g_pSeatManager->setPointerFocus(PWINDOW->m_wlSurface->resource(), {1, 1}); } - g_pSeatManager->sendKeyboardMods(g_pInputManager->accumulateModsFromAllKBs(), 0, 0, 0); + g_pSeatManager->sendKeyboardMods(g_pInputManager->getModsFromAllKBs(), 0, 0, 0); if (g_pKeybindManager->m_passPressed == 1) { if (g_pKeybindManager->m_lastCode != 0) diff --git a/src/managers/SeatManager.cpp b/src/managers/SeatManager.cpp index 76217238..67752e2a 100644 --- a/src/managers/SeatManager.cpp +++ b/src/managers/SeatManager.cpp @@ -11,7 +11,11 @@ #include "../managers/HookSystemManager.hpp" #include "wlr-layer-shell-unstable-v1.hpp" #include <algorithm> +#include <hyprutils/utils/ScopeGuard.hpp> #include <ranges> +#include <cstring> + +using namespace Hyprutils::Utils; CSeatManager::CSeatManager() { m_listeners.newSeatResource = PROTO::seat->m_events.newSeatResource.listen([this](const auto& resource) { onNewSeatResource(resource); }); @@ -136,6 +140,18 @@ void CSeatManager::setKeyboardFocus(SP<CWLSurfaceResource> surf) { return; } + wl_array keys; + wl_array_init(&keys); + CScopeGuard x([&keys] { wl_array_release(&keys); }); + + const auto& PRESSED = g_pInputManager->getKeysFromAllKBs(); + static_assert(std::is_same_v<std::decay_t<decltype(PRESSED)>::value_type, uint32_t>, "Element type different from keycode type uint32_t"); + + const auto PRESSEDARRSIZE = PRESSED.size() * sizeof(uint32_t); + const auto PKEYS = wl_array_add(&keys, PRESSEDARRSIZE); + if (PKEYS) + memcpy(PKEYS, PRESSED.data(), PRESSEDARRSIZE); + auto client = surf->client(); for (auto const& r : m_seatResources | std::views::reverse) { if (r->resource->client() != client) @@ -146,7 +162,7 @@ void CSeatManager::setKeyboardFocus(SP<CWLSurfaceResource> surf) { if (!k) continue; - k->sendEnter(surf); + k->sendEnter(surf, &keys); k->sendMods(m_keyboard->m_modifiersState.depressed, m_keyboard->m_modifiersState.latched, m_keyboard->m_modifiersState.locked, m_keyboard->m_modifiersState.group); } } diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 6c23c493..cbb4c3cc 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -39,6 +39,7 @@ #include "../../managers/permissions/DynamicPermissionManager.hpp" #include "../../helpers/time/Time.hpp" +#include "../../helpers/MiscFunctions.hpp" #include <aquamarine/input/Input.hpp> @@ -931,6 +932,14 @@ Vector2D CInputManager::getMouseCoordsInternal() { return g_pPointerManager->position(); } +void CInputManager::newKeyboard(SP<IKeyboard> keeb) { + const auto PNEWKEYBOARD = m_keyboards.emplace_back(keeb); + + setupKeyboard(PNEWKEYBOARD); + + Debug::log(LOG, "New keyboard created, pointers Hypr: {:x}", (uintptr_t)PNEWKEYBOARD.get()); +} + void CInputManager::newKeyboard(SP<Aquamarine::IKeyboard> keyboard) { const auto PNEWKEYBOARD = m_keyboards.emplace_back(CKeyboard::create(keyboard)); @@ -1398,18 +1407,36 @@ void CInputManager::onKeyboardKey(const IKeyboard::SKeyEvent& event, SP<IKeyboar const bool DISALLOWACTION = pKeyboard->isVirtual() && shouldIgnoreVirtualKeyboard(pKeyboard); + const auto IME = m_relay.m_inputMethod.lock(); + const bool HASIME = IME && IME->hasGrab(); + const bool USEIME = HASIME && !DISALLOWACTION; + const auto EMAP = std::unordered_map<std::string, std::any>{{"keyboard", pKeyboard}, {"event", event}}; EMIT_HOOK_EVENT_CANCELLABLE("keyPress", EMAP); - bool passEvent = DISALLOWACTION || g_pKeybindManager->onKeyEvent(event, pKeyboard); + bool passEvent = DISALLOWACTION; - if (passEvent) { - const auto IME = m_relay.m_inputMethod.lock(); + if (!DISALLOWACTION) + passEvent = g_pKeybindManager->onKeyEvent(event, pKeyboard); - if (IME && IME->hasGrab() && !DISALLOWACTION) { + if (passEvent) { + if (USEIME) { IME->setKeyboard(pKeyboard); IME->sendKey(event.timeMs, event.keycode, event.state); } else { + const auto PRESSED = shareKeyFromAllKBs(event.keycode, event.state == WL_KEYBOARD_KEY_STATE_PRESSED); + const auto CONTAINS = std::ranges::contains(m_pressed, event.keycode); + + if (CONTAINS && PRESSED) + return; + if (!CONTAINS && !PRESSED) + return; + + if (CONTAINS) + std::erase(m_pressed, event.keycode); + else + m_pressed.emplace_back(event.keycode); + g_pSeatManager->setKeyboard(pKeyboard); g_pSeatManager->sendKeyboardKey(event.timeMs, event.keycode, event.state); } @@ -1424,10 +1451,9 @@ void CInputManager::onKeyboardMod(SP<IKeyboard> pKeyboard) { const bool DISALLOWACTION = pKeyboard->isVirtual() && shouldIgnoreVirtualKeyboard(pKeyboard); - const auto ALLMODS = accumulateModsFromAllKBs(); - - auto MODS = pKeyboard->m_modifiersState; - MODS.depressed = ALLMODS; + auto MODS = pKeyboard->m_modifiersState; + const auto ALLMODS = shareModsFromAllKBs(MODS.depressed); + MODS.depressed = ALLMODS; const auto IME = m_relay.m_inputMethod.lock(); @@ -1437,6 +1463,7 @@ void CInputManager::onKeyboardMod(SP<IKeyboard> pKeyboard) { } else { g_pSeatManager->setKeyboard(pKeyboard); g_pSeatManager->sendKeyboardMods(MODS.depressed, MODS.latched, MODS.locked, MODS.group); + m_lastMods = MODS.depressed; } updateKeyboardsLeds(pKeyboard); @@ -1457,9 +1484,9 @@ bool CInputManager::shouldIgnoreVirtualKeyboard(SP<IKeyboard> pKeyboard) { if (!pKeyboard->isVirtual()) return false; - CVirtualKeyboard* vk = (CVirtualKeyboard*)pKeyboard.get(); + auto client = pKeyboard->getClient(); - return !pKeyboard || (!m_relay.m_inputMethod.expired() && m_relay.m_inputMethod->grabClient() == vk->getClient()); + return !pKeyboard || (client && !m_relay.m_inputMethod.expired() && m_relay.m_inputMethod->grabClient() == client); } void CInputManager::refocus() { @@ -1564,11 +1591,45 @@ void CInputManager::updateCapabilities() { m_capabilities = caps; } -uint32_t CInputManager::accumulateModsFromAllKBs() { +const std::vector<uint32_t>& CInputManager::getKeysFromAllKBs() { + return m_pressed; +} + +uint32_t CInputManager::getModsFromAllKBs() { + return m_lastMods; +} + +bool CInputManager::shareKeyFromAllKBs(uint32_t key, bool pressed) { + bool finalState = pressed; - uint32_t finalMask = 0; + if (finalState) + return finalState; for (auto const& kb : m_keyboards) { + if (!kb->shareStates()) + continue; + + if (kb->isVirtual() && shouldIgnoreVirtualKeyboard(kb)) + continue; + + if (!kb->m_enabled) + continue; + + const bool PRESSED = kb->getPressed(key); + if (PRESSED) + return PRESSED; + } + + return finalState; +} + +uint32_t CInputManager::shareModsFromAllKBs(uint32_t depressed) { + uint32_t finalMask = depressed; + + for (auto const& kb : m_keyboards) { + if (!kb->shareStates()) + continue; + if (kb->isVirtual() && shouldIgnoreVirtualKeyboard(kb)) continue; @@ -1751,13 +1812,6 @@ void CInputManager::unsetCursorImage() { restoreCursorIconToApp(); } -std::string CInputManager::deviceNameToInternalString(std::string in) { - std::ranges::replace(in, ' ', '-'); - std::ranges::replace(in, '\n', '-'); - std::ranges::transform(in, in.begin(), ::tolower); - return in; -} - std::string CInputManager::getNameForNewDevice(std::string internalName) { auto proposedNewName = deviceNameToInternalString(internalName); diff --git a/src/managers/input/InputManager.hpp b/src/managers/input/InputManager.hpp index 1696dd0a..73a0dc48 100644 --- a/src/managers/input/InputManager.hpp +++ b/src/managers/input/InputManager.hpp @@ -94,6 +94,7 @@ class CInputManager { void onKeyboardKey(const IKeyboard::SKeyEvent&, SP<IKeyboard>); void onKeyboardMod(SP<IKeyboard>); + void newKeyboard(SP<IKeyboard>); void newKeyboard(SP<Aquamarine::IKeyboard>); void newVirtualKeyboard(SP<CVirtualKeyboardV1Resource>); void newMouse(SP<Aquamarine::IPointer>); @@ -185,7 +186,8 @@ class CInputManager { CInputMethodRelay m_relay; // for shared mods - uint32_t accumulateModsFromAllKBs(); + const std::vector<uint32_t>& getKeysFromAllKBs(); + uint32_t getModsFromAllKBs(); // for virtual keyboards: whether we should respect them as normal ones bool shouldIgnoreVirtualKeyboard(SP<IKeyboard>); @@ -194,7 +196,6 @@ class CInputManager { void setCursorImageUntilUnset(std::string); void unsetCursorImage(); - std::string deviceNameToInternalString(std::string); std::string getNameForNewDevice(std::string); void releaseAllMouseButtons(); @@ -305,6 +306,11 @@ class CInputManager { uint32_t accumulatedScroll = 0; } m_scrollWheelState; + bool shareKeyFromAllKBs(uint32_t key, bool pressed); + uint32_t shareModsFromAllKBs(uint32_t depressed); + std::vector<uint32_t> m_pressed; + uint32_t m_lastMods = 0; + friend class CKeybindManager; friend class CWLSurface; }; diff --git a/src/managers/permissions/DynamicPermissionManager.cpp b/src/managers/permissions/DynamicPermissionManager.cpp index 235336b7..2f4690fc 100644 --- a/src/managers/permissions/DynamicPermissionManager.cpp +++ b/src/managers/permissions/DynamicPermissionManager.cpp @@ -2,10 +2,9 @@ #include "DynamicPermissionManager.hpp" #include <algorithm> #include <wayland-server-core.h> -#include <expected> -#include <filesystem> #include "../../Compositor.hpp" #include "../../config/ConfigValue.hpp" +#include "../../helpers/MiscFunctions.hpp" #include <hyprutils/string/String.hpp> using namespace Hyprutils::String; @@ -76,48 +75,6 @@ static const char* specialPidToString(eSpecialPidTypes type) { } } -static std::expected<std::string, std::string> binaryNameForPid(pid_t pid) { - if (pid <= 0) - return std::unexpected("No pid for client"); - -#if defined(KERN_PROC_PATHNAME) - int mib[] = { - CTL_KERN, -#if defined(__NetBSD__) - KERN_PROC_ARGS, - pid, - KERN_PROC_PATHNAME, -#else - KERN_PROC, - KERN_PROC_PATHNAME, - pid, -#endif - }; - u_int miblen = sizeof(mib) / sizeof(mib[0]); - char exe[PATH_MAX] = "/nonexistent"; - size_t sz = sizeof(exe); - sysctl(mib, miblen, &exe, &sz, NULL, 0); - std::string path = exe; -#else - std::string path = std::format("/proc/{}/exe", (uint64_t)pid); -#endif - std::error_code ec; - - std::string fullPath = std::filesystem::canonical(path, ec); - - if (ec) - return std::unexpected("canonical failed"); - - return fullPath; -} - -static std::expected<std::string, std::string> binaryNameForWlClient(wl_client* client) { - pid_t pid = 0; - wl_client_get_credentials(client, &pid, nullptr, nullptr); - - return binaryNameForPid(pid); -} - void CDynamicPermissionManager::clearConfigPermissions() { std::erase_if(m_rules, [](const auto& e) { return e->m_source == PERMISSION_RULE_SOURCE_CONFIG; }); } diff --git a/src/protocols/VirtualKeyboard.cpp b/src/protocols/VirtualKeyboard.cpp index 7512f9bd..3dc15d83 100644 --- a/src/protocols/VirtualKeyboard.cpp +++ b/src/protocols/VirtualKeyboard.cpp @@ -1,23 +1,42 @@ #include "VirtualKeyboard.hpp" +#include <filesystem> #include <sys/mman.h> +#include "../config/ConfigValue.hpp" +#include "../config/ConfigManager.hpp" #include "../devices/IKeyboard.hpp" #include "../helpers/time/Time.hpp" +#include "../helpers/MiscFunctions.hpp" using namespace Hyprutils::OS; +static std::string virtualKeyboardNameForWlClient(wl_client* client) { + std::string name = "hl-virtual-keyboard"; + + static auto PVKNAMEPROC = CConfigValue<Hyprlang::INT>("misc:name_vk_after_proc"); + if (!*PVKNAMEPROC) + return name; + + name += "-"; + const auto CLIENTNAME = binaryNameForWlClient(client); + if (CLIENTNAME.has_value()) { + const auto PATH = std::filesystem::path(CLIENTNAME.value()); + if (PATH.has_filename()) { + const auto FILENAME = PATH.filename(); + const auto NAME = deviceNameToInternalString(FILENAME); + name += NAME; + return name; + } + } + + name += "unknown"; + return name; +} + CVirtualKeyboardV1Resource::CVirtualKeyboardV1Resource(SP<CZwpVirtualKeyboardV1> resource_) : m_resource(resource_) { if UNLIKELY (!good()) return; - m_resource->setDestroy([this](CZwpVirtualKeyboardV1* r) { - releasePressed(); - m_events.destroy.emit(); - PROTO::virtualKeyboard->destroyResource(this); - }); - m_resource->setOnDestroy([this](CZwpVirtualKeyboardV1* r) { - releasePressed(); - m_events.destroy.emit(); - PROTO::virtualKeyboard->destroyResource(this); - }); + m_resource->setDestroy([this](CZwpVirtualKeyboardV1* r) { destroy(); }); + m_resource->setOnDestroy([this](CZwpVirtualKeyboardV1* r) { destroy(); }); m_resource->setKey([this](CZwpVirtualKeyboardV1* r, uint32_t timeMs, uint32_t key, uint32_t state) { if UNLIKELY (!m_hasKeymap) { @@ -31,7 +50,7 @@ CVirtualKeyboardV1Resource::CVirtualKeyboardV1Resource(SP<CZwpVirtualKeyboardV1> .state = (wl_keyboard_key_state)state, }); - const bool CONTAINS = std::ranges::find(m_pressed, key) != m_pressed.end(); + const bool CONTAINS = std::ranges::contains(m_pressed, key); if (state && !CONTAINS) m_pressed.emplace_back(key); else if (!state && CONTAINS) @@ -88,7 +107,7 @@ CVirtualKeyboardV1Resource::CVirtualKeyboardV1Resource(SP<CZwpVirtualKeyboardV1> xkb_context_unref(xkbContext); }); - m_name = "hl-virtual-keyboard"; + m_name = virtualKeyboardNameForWlClient(resource_->client()); } CVirtualKeyboardV1Resource::~CVirtualKeyboardV1Resource() { @@ -115,6 +134,14 @@ void CVirtualKeyboardV1Resource::releasePressed() { m_pressed.clear(); } +void CVirtualKeyboardV1Resource::destroy() { + const auto RELEASEPRESSED = g_pConfigManager->getDeviceInt(m_name, "release_pressed_on_close", "input:virtualkeyboard:release_pressed_on_close"); + if (RELEASEPRESSED) + releasePressed(); + m_events.destroy.emit(); + PROTO::virtualKeyboard->destroyResource(this); +} + CVirtualKeyboardProtocol::CVirtualKeyboardProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { ; } diff --git a/src/protocols/VirtualKeyboard.hpp b/src/protocols/VirtualKeyboard.hpp index c601c0fb..1ff9f161 100644 --- a/src/protocols/VirtualKeyboard.hpp +++ b/src/protocols/VirtualKeyboard.hpp @@ -30,6 +30,7 @@ class CVirtualKeyboardV1Resource { SP<CZwpVirtualKeyboardV1> m_resource; void releasePressed(); + void destroy(); bool m_hasKeymap = false; diff --git a/src/protocols/core/Seat.cpp b/src/protocols/core/Seat.cpp index 53123abe..8aa2f36a 100644 --- a/src/protocols/core/Seat.cpp +++ b/src/protocols/core/Seat.cpp @@ -305,8 +305,14 @@ CWLKeyboardResource::CWLKeyboardResource(SP<CWlKeyboard> resource_, SP<CWLSeatRe sendKeymap(g_pSeatManager->m_keyboard.lock()); repeatInfo(g_pSeatManager->m_keyboard->m_repeatRate, g_pSeatManager->m_keyboard->m_repeatDelay); - if (g_pSeatManager->m_state.keyboardFocus && g_pSeatManager->m_state.keyboardFocus->client() == m_resource->client()) - sendEnter(g_pSeatManager->m_state.keyboardFocus.lock()); + if (g_pSeatManager->m_state.keyboardFocus && g_pSeatManager->m_state.keyboardFocus->client() == m_resource->client()) { + wl_array keys; + wl_array_init(&keys); + + sendEnter(g_pSeatManager->m_state.keyboardFocus.lock(), &keys); + + wl_array_release(&keys); + } } bool CWLKeyboardResource::good() { @@ -334,7 +340,9 @@ void CWLKeyboardResource::sendKeymap(SP<IKeyboard> keyboard) { m_resource->sendKeymap(format, fd.get(), size); } -void CWLKeyboardResource::sendEnter(SP<CWLSurfaceResource> surface) { +void CWLKeyboardResource::sendEnter(SP<CWLSurfaceResource> surface, wl_array* keys) { + ASSERT(keys); + if (!m_owner || m_currentSurface == surface || !surface->getResource()->resource()) return; @@ -351,12 +359,7 @@ void CWLKeyboardResource::sendEnter(SP<CWLSurfaceResource> surface) { m_currentSurface = surface; m_listeners.destroySurface = surface->m_events.destroy.listen([this] { sendLeave(); }); - wl_array arr; - wl_array_init(&arr); - - m_resource->sendEnter(g_pSeatManager->nextSerial(m_owner.lock()), surface->getResource().get(), &arr); - - wl_array_release(&arr); + m_resource->sendEnter(g_pSeatManager->nextSerial(m_owner.lock()), surface->getResource().get(), keys); } void CWLKeyboardResource::sendLeave() { diff --git a/src/protocols/core/Seat.hpp b/src/protocols/core/Seat.hpp index 0c14e52a..8b8f6004 100644 --- a/src/protocols/core/Seat.hpp +++ b/src/protocols/core/Seat.hpp @@ -12,6 +12,7 @@ #include <cstdint> #include "../WaylandProtocol.hpp" #include <wayland-server-protocol.h> +#include <wayland-util.h> #include "wayland.hpp" #include "../../helpers/signal/Signal.hpp" #include "../../helpers/math/Math.hpp" @@ -104,7 +105,7 @@ class CWLKeyboardResource { bool good(); void sendKeymap(SP<IKeyboard> keeb); - void sendEnter(SP<CWLSurfaceResource> surface); + void sendEnter(SP<CWLSurfaceResource> surface, wl_array* keys); void sendLeave(); void sendKey(uint32_t timeMs, uint32_t key, wl_keyboard_key_state state); void sendMods(uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group); |
