diff --git a/src/Compositor.cpp b/src/Compositor.cpp index e28d86c7706d..9609cbd1a1e8 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2418,10 +2418,7 @@ void CCompositor::warpCursorTo(const Vector2D& pos, bool force) { if (*PNOWARPS && !force) return; - if (!m_sSeat.mouse) - return; - - wlr_cursor_warp(m_sWLRCursor, m_sSeat.mouse->mouse, pos.x, pos.y); + wlr_cursor_warp(m_sWLRCursor, nullptr, pos.x, pos.y); const auto PMONITORNEW = getMonitorFromVector(pos); if (PMONITORNEW != m_pLastMonitor) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index d4e1164a3919..7f0345705525 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -19,6 +19,9 @@ #include "../config/ConfigValue.hpp" #include "../managers/CursorManager.hpp" #include "../hyprerror/HyprError.hpp" +#include "../devices/IPointer.hpp" +#include "../devices/IKeyboard.hpp" +#include "../devices/ITouch.hpp" static void trimTrailingComma(std::string& str) { if (!str.empty() && str.back() == ',') @@ -514,23 +517,24 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) { result += "{\n"; result += "\"mice\": [\n"; - for (auto& m : g_pInputManager->m_lMice) { + for (auto& m : g_pInputManager->m_vPointers) { result += std::format( R"#( {{ "address": "0x{:x}", "name": "{}", "defaultSpeed": {:.5f} }},)#", - (uintptr_t)&m, escapeJSONStrings(m.name), - wlr_input_device_is_libinput(m.mouse) ? libinput_device_config_accel_get_default_speed((libinput_device*)wlr_libinput_get_device_handle(m.mouse)) : 0.f); + (uintptr_t)m.get(), escapeJSONStrings(m->hlName), + wlr_input_device_is_libinput(&m->wlr()->base) ? libinput_device_config_accel_get_default_speed((libinput_device*)wlr_libinput_get_device_handle(&m->wlr()->base)) : + 0.f); } trimTrailingComma(result); result += "\n],\n"; result += "\"keyboards\": [\n"; - for (auto& k : g_pInputManager->m_lKeyboards) { - const auto KM = g_pInputManager->getActiveLayoutForKeyboard(&k); + for (auto& k : g_pInputManager->m_vKeyboards) { + const auto KM = k->getActiveLayout(); result += std::format( R"#( {{ "address": "0x{:x}", @@ -543,9 +547,9 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) { "active_keymap": "{}", "main": {} }},)#", - (uintptr_t)&k, escapeJSONStrings(k.name), escapeJSONStrings(k.currentRules.rules), escapeJSONStrings(k.currentRules.model), - escapeJSONStrings(k.currentRules.layout), escapeJSONStrings(k.currentRules.variant), escapeJSONStrings(k.currentRules.options), escapeJSONStrings(KM), - (k.active ? "true" : "false")); + (uintptr_t)k.get(), escapeJSONStrings(k->hlName), escapeJSONStrings(k->currentRules.rules), escapeJSONStrings(k->currentRules.model), + escapeJSONStrings(k->currentRules.layout), escapeJSONStrings(k->currentRules.variant), escapeJSONStrings(k->currentRules.options), escapeJSONStrings(KM), + (k->active ? "true" : "false")); } trimTrailingComma(result); @@ -590,13 +594,13 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) { result += "\"touch\": [\n"; - for (auto& d : g_pInputManager->m_lTouchDevices) { + for (auto& d : g_pInputManager->m_vTouches) { result += std::format( R"#( {{ "address": "0x{:x}", "name": "{}" }},)#", - (uintptr_t)&d, escapeJSONStrings(d.name)); + (uintptr_t)d.get(), escapeJSONStrings(d->hlName)); } trimTrailingComma(result); @@ -621,19 +625,20 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) { } else { result += "mice:\n"; - for (auto& m : g_pInputManager->m_lMice) { - result += std::format( - "\tMouse at {:x}:\n\t\t{}\n\t\t\tdefault speed: {:.5f}\n", (uintptr_t)&m, m.name, - (wlr_input_device_is_libinput(m.mouse) ? libinput_device_config_accel_get_default_speed((libinput_device*)wlr_libinput_get_device_handle(m.mouse)) : 0.f)); + for (auto& m : g_pInputManager->m_vPointers) { + result += std::format("\tMouse at {:x}:\n\t\t{}\n\t\t\tdefault speed: {:.5f}\n", (uintptr_t)m.get(), m->hlName, + (wlr_input_device_is_libinput(&m->wlr()->base) ? + libinput_device_config_accel_get_default_speed((libinput_device*)wlr_libinput_get_device_handle(&m->wlr()->base)) : + 0.f)); } result += "\n\nKeyboards:\n"; - for (auto& k : g_pInputManager->m_lKeyboards) { - const auto KM = g_pInputManager->getActiveLayoutForKeyboard(&k); + for (auto& k : g_pInputManager->m_vKeyboards) { + const auto KM = k->getActiveLayout(); result += std::format("\tKeyboard at {:x}:\n\t\t{}\n\t\t\trules: r \"{}\", m \"{}\", l \"{}\", v \"{}\", o \"{}\"\n\t\t\tactive keymap: {}\n\t\t\tmain: {}\n", - (uintptr_t)&k, k.name, k.currentRules.rules, k.currentRules.model, k.currentRules.layout, k.currentRules.variant, k.currentRules.options, KM, - (k.active ? "yes" : "no")); + (uintptr_t)k.get(), k->hlName, k->currentRules.rules, k->currentRules.model, k->currentRules.layout, k->currentRules.variant, + k->currentRules.options, KM, (k->active ? "yes" : "no")); } result += "\n\nTablets:\n"; @@ -652,8 +657,8 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) { result += "\n\nTouch:\n"; - for (auto& d : g_pInputManager->m_lTouchDevices) { - result += std::format("\tTouch Device at {:x}:\n\t\t{}\n", (uintptr_t)&d, d.name); + for (auto& d : g_pInputManager->m_vTouches) { + result += std::format("\tTouch Device at {:x}:\n\t\t{}\n", (uintptr_t)d.get(), d->hlName); } result += "\n\nSwitches:\n"; @@ -1069,13 +1074,13 @@ std::string switchXKBLayoutRequest(eHyprCtlOutputFormat format, std::string requ const auto CMD = vars[2]; // get kb - const auto PKEYBOARD = std::find_if(g_pInputManager->m_lKeyboards.begin(), g_pInputManager->m_lKeyboards.end(), - [&](const SKeyboard& other) { return other.name == g_pInputManager->deviceNameToInternalString(KB); }); + const auto PKEYBOARD = std::find_if(g_pInputManager->m_vKeyboards.begin(), g_pInputManager->m_vKeyboards.end(), + [&](const auto& other) { return other->hlName == g_pInputManager->deviceNameToInternalString(KB); }); - if (PKEYBOARD == g_pInputManager->m_lKeyboards.end()) + if (PKEYBOARD == g_pInputManager->m_vKeyboards.end()) return "device not found"; - const auto PWLRKEYBOARD = wlr_keyboard_from_input_device(PKEYBOARD->keyboard); + const auto PWLRKEYBOARD = (*PKEYBOARD)->wlr(); const auto LAYOUTS = xkb_keymap_num_layouts(PWLRKEYBOARD->keymap); xkb_layout_index_t activeLayout = 0; while (activeLayout < LAYOUTS) { diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp index ec899dd1db46..dd2cfb7d0486 100644 --- a/src/desktop/LayerSurface.cpp +++ b/src/desktop/LayerSurface.cpp @@ -196,7 +196,7 @@ void CLayerSurface::onMap() { const bool GRABSFOCUS = layerSurface->current.keyboard_interactive != ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE && // don't focus if constrained - (!g_pCompositor->m_sSeat.mouse || !g_pInputManager->isConstrained()); + (g_pCompositor->m_sSeat.mouse.expired() || !g_pInputManager->isConstrained()); if (GRABSFOCUS) { g_pInputManager->releaseAllMouseButtons(); @@ -383,7 +383,7 @@ void CLayerSurface::onCommit() { realSize.setValueAndWarp(geometry.size()); } - if (layerSurface->current.keyboard_interactive && (!g_pCompositor->m_sSeat.mouse || !g_pInputManager->isConstrained()) // don't focus if constrained + if (layerSurface->current.keyboard_interactive && (g_pCompositor->m_sSeat.mouse.expired() || !g_pInputManager->isConstrained()) // don't focus if constrained && !keyboardExclusive && mapped) { g_pCompositor->focusSurface(layerSurface->surface); @@ -391,7 +391,7 @@ void CLayerSurface::onCommit() { wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, layerSurface->surface, LOCAL.x, LOCAL.y); wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, 0, LOCAL.x, LOCAL.y); g_pInputManager->m_bEmptyFocusCursorSet = false; - } else if (!layerSurface->current.keyboard_interactive && (!g_pCompositor->m_sSeat.mouse || !g_pInputManager->isConstrained()) && keyboardExclusive) { + } else if (!layerSurface->current.keyboard_interactive && (g_pCompositor->m_sSeat.mouse.expired() || !g_pInputManager->isConstrained()) && keyboardExclusive) { g_pInputManager->refocus(); } diff --git a/src/devices/IHID.hpp b/src/devices/IHID.hpp new file mode 100644 index 000000000000..c2b397c79654 --- /dev/null +++ b/src/devices/IHID.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include +#include +#include "../helpers/signal/Signal.hpp" + +enum eHIDCapabilityType : uint32_t { + HID_INPUT_CAPABILITY_KEYBOARD = (1 << 0), + HID_INPUT_CAPABILITY_POINTER = (1 << 1), + HID_INPUT_CAPABILITY_TOUCH = (1 << 2), +}; + +/* + Base class for a HID device. + This could be a keyboard, a mouse, or a touchscreen. +*/ +class IHID { + public: + virtual uint32_t getCapabilities() = 0; + + struct { + CSignal destroy; + } events; + + std::string deviceName; +}; \ No newline at end of file diff --git a/src/devices/IKeyboard.cpp b/src/devices/IKeyboard.cpp new file mode 100644 index 000000000000..790766bc7e86 --- /dev/null +++ b/src/devices/IKeyboard.cpp @@ -0,0 +1,134 @@ +#include "IKeyboard.hpp" +#include "../defines.hpp" +#include "../helpers/VarList.hpp" +#include "../managers/input/InputManager.hpp" + +uint32_t IKeyboard::getCapabilities() { + return HID_INPUT_CAPABILITY_KEYBOARD; +} + +IKeyboard::~IKeyboard() { + events.destroy.emit(); + + if (!xkbTranslationState) + return; + + xkb_state_unref(xkbTranslationState); + xkbTranslationState = nullptr; +} + +void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) { + + if (xkbTranslationState) + xkb_state_unref(xkbTranslationState); + + if (keymap) { + Debug::log(LOG, "Updating keyboard {:x}'s translation state from a provided keymap", (uintptr_t)this); + xkbTranslationState = xkb_state_new(keymap); + return; + } + + const auto WLRKB = wlr(); + const auto KEYMAP = WLRKB->keymap; + const auto STATE = WLRKB->xkb_state; + const auto LAYOUTSNUM = xkb_keymap_num_layouts(KEYMAP); + + const auto PCONTEXT = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + + for (uint32_t i = 0; i < LAYOUTSNUM; ++i) { + if (xkb_state_layout_index_is_active(STATE, i, XKB_STATE_LAYOUT_EFFECTIVE)) { + Debug::log(LOG, "Updating keyboard {:x}'s translation state from an active index {}", (uintptr_t)this, i); + + CVarList keyboardLayouts(currentRules.layout, 0, ','); + CVarList keyboardModels(currentRules.model, 0, ','); + CVarList keyboardVariants(currentRules.variant, 0, ','); + + xkb_rule_names rules = {.rules = "", .model = "", .layout = "", .variant = "", .options = ""}; + + std::string layout, model, variant; + layout = keyboardLayouts[i % keyboardLayouts.size()]; + model = keyboardModels[i % keyboardModels.size()]; + variant = keyboardVariants[i % keyboardVariants.size()]; + + rules.layout = layout.c_str(); + rules.model = model.c_str(); + rules.variant = variant.c_str(); + + auto KEYMAP = xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); + + if (!KEYMAP) { + Debug::log(ERR, "updateXKBTranslationState: keymap failed 1, fallback without model/variant"); + rules.model = ""; + rules.variant = ""; + KEYMAP = xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); + } + + if (!KEYMAP) { + Debug::log(ERR, "updateXKBTranslationState: keymap failed 2, fallback to us"); + rules.layout = "us"; + KEYMAP = xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); + } + + xkbTranslationState = xkb_state_new(KEYMAP); + + xkb_keymap_unref(KEYMAP); + xkb_context_unref(PCONTEXT); + + return; + } + } + + Debug::log(LOG, "Updating keyboard {:x}'s translation state from an unknown index", (uintptr_t)this); + + xkb_rule_names rules = { + .rules = currentRules.rules.c_str(), + .model = currentRules.model.c_str(), + .layout = currentRules.layout.c_str(), + .variant = currentRules.variant.c_str(), + .options = currentRules.options.c_str(), + }; + + const auto NEWKEYMAP = xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); + + xkbTranslationState = xkb_state_new(NEWKEYMAP); + + xkb_keymap_unref(NEWKEYMAP); + xkb_context_unref(PCONTEXT); +} + +std::string IKeyboard::getActiveLayout() { + const auto WLRKB = wlr(); + const auto KEYMAP = WLRKB->keymap; + const auto STATE = WLRKB->xkb_state; + const auto LAYOUTSNUM = xkb_keymap_num_layouts(KEYMAP); + + for (uint32_t i = 0; i < LAYOUTSNUM; ++i) { + if (xkb_state_layout_index_is_active(STATE, i, XKB_STATE_LAYOUT_EFFECTIVE)) { + const auto LAYOUTNAME = xkb_keymap_layout_get_name(KEYMAP, i); + + if (LAYOUTNAME) + return std::string(LAYOUTNAME); + return "error"; + } + } + + return "none"; +} + +void IKeyboard::updateLEDs() { + auto keyboard = wlr(); + + if (keyboard->xkb_state == nullptr) + return; + + uint32_t leds = 0; + for (uint32_t i = 0; i < WLR_LED_COUNT; ++i) { + if (xkb_state_led_index_is_active(keyboard->xkb_state, keyboard->led_indexes[i])) + leds |= (1 << i); + } + + if (isVirtual() && g_pInputManager->shouldIgnoreVirtualKeyboard(self.lock())) + return; + + wlr_keyboard_led_update(wlr(), leds); +} diff --git a/src/devices/IKeyboard.hpp b/src/devices/IKeyboard.hpp new file mode 100644 index 000000000000..35ccd8cb739d --- /dev/null +++ b/src/devices/IKeyboard.hpp @@ -0,0 +1,61 @@ +#pragma once + +#include "IHID.hpp" +#include "../helpers/WLListener.hpp" +#include "../macros.hpp" +#include "../helpers/Vector2D.hpp" + +#include + +struct wlr_keyboard; + +class IKeyboard : public IHID { + public: + virtual ~IKeyboard(); + virtual uint32_t getCapabilities(); + virtual bool isVirtual() = 0; + virtual wlr_keyboard* wlr() = 0; + + struct SKeyEvent { + uint32_t timeMs = 0; + uint32_t keycode = 0; + bool updateMods = false; + wl_keyboard_key_state state = WL_KEYBOARD_KEY_STATE_PRESSED; + }; + + struct { + CSignal key; + CSignal modifiers; + CSignal keymap; + CSignal repeatInfo; + } keyboardEvents; + + struct SStringRuleNames { + std::string layout = ""; + std::string model = ""; + std::string variant = ""; + std::string options = ""; + std::string rules = ""; + }; + + void updateXKBTranslationState(xkb_keymap* const keymap = nullptr); + std::string getActiveLayout(); + void updateLEDs(); + + bool active = false; + bool enabled = true; + + xkb_layout_index_t activeLayout = 0; + xkb_state* xkbTranslationState = nullptr; + + std::string hlName = ""; + std::string xkbFilePath = ""; + + SStringRuleNames currentRules; + int repeatRate = 0; + int repeatDelay = 0; + int numlockOn = -1; + bool resolveBindsBySym = false; + + WP self; +}; diff --git a/src/devices/IPointer.cpp b/src/devices/IPointer.cpp new file mode 100644 index 000000000000..9eb507b26def --- /dev/null +++ b/src/devices/IPointer.cpp @@ -0,0 +1,5 @@ +#include "IPointer.hpp" + +uint32_t IPointer::getCapabilities() { + return HID_INPUT_CAPABILITY_POINTER; +} diff --git a/src/devices/IPointer.hpp b/src/devices/IPointer.hpp new file mode 100644 index 000000000000..eda7da2c2002 --- /dev/null +++ b/src/devices/IPointer.hpp @@ -0,0 +1,110 @@ +#pragma once + +#include "IHID.hpp" +#include "../helpers/WLListener.hpp" +#include "../macros.hpp" +#include "../helpers/Vector2D.hpp" + +struct wlr_pointer; + +/* + Base class for a pointer. +*/ +class IPointer : public IHID { + public: + virtual uint32_t getCapabilities(); + virtual bool isVirtual() = 0; + virtual wlr_pointer* wlr() = 0; + + struct SMotionEvent { + uint32_t timeMs = 0; + Vector2D delta, unaccel; + }; + + struct SMotionAbsoluteEvent { + uint32_t timeMs = 0; + Vector2D absolute; // 0.0 - 1.0 + }; + + struct SButtonEvent { + uint32_t timeMs = 0; + uint32_t button = 0; + wl_pointer_button_state state = WL_POINTER_BUTTON_STATE_PRESSED; + }; + + struct SAxisEvent { + uint32_t timeMs = 0; + wl_pointer_axis_source source = WL_POINTER_AXIS_SOURCE_WHEEL; + wl_pointer_axis axis = WL_POINTER_AXIS_VERTICAL_SCROLL; + wl_pointer_axis_relative_direction relativeDirection = WL_POINTER_AXIS_RELATIVE_DIRECTION_IDENTICAL; + double delta = 0.0; + int32_t deltaDiscrete = 0; + }; + + struct SSwipeBeginEvent { + uint32_t timeMs = 0; + uint32_t fingers = 0; + }; + + struct SSwipeUpdateEvent { + uint32_t timeMs = 0; + uint32_t fingers = 0; + Vector2D delta; + }; + + struct SSwipeEndEvent { + uint32_t timeMs = 0; + bool cancelled = false; + }; + + struct SPinchBeginEvent { + uint32_t timeMs = 0; + uint32_t fingers = 0; + }; + + struct SPinchUpdateEvent { + uint32_t timeMs = 0; + uint32_t fingers = 0; + Vector2D delta; + double scale = 1.0, rotation = 0.0; + }; + + struct SPinchEndEvent { + uint32_t timeMs = 0; + bool cancelled = false; + }; + + struct SHoldBeginEvent { + uint32_t timeMs = 0; + uint32_t fingers = 0; + }; + + struct SHoldEndEvent { + uint32_t timeMs = 0; + bool cancelled = false; + }; + + struct { + CSignal motion; + CSignal motionAbsolute; + CSignal button; + CSignal axis; + CSignal frame; + + CSignal swipeBegin; + CSignal swipeEnd; + CSignal swipeUpdate; + + CSignal pinchBegin; + CSignal pinchEnd; + CSignal pinchUpdate; + + CSignal holdBegin; + CSignal holdEnd; + } pointerEvents; + + std::string hlName; + bool connected = false; // means connected to the cursor + + WP self; +}; diff --git a/src/devices/ITouch.cpp b/src/devices/ITouch.cpp new file mode 100644 index 000000000000..3fa347fdda6b --- /dev/null +++ b/src/devices/ITouch.cpp @@ -0,0 +1,5 @@ +#include "ITouch.hpp" + +uint32_t ITouch::getCapabilities() { + return HID_INPUT_CAPABILITY_TOUCH; +} \ No newline at end of file diff --git a/src/devices/ITouch.hpp b/src/devices/ITouch.hpp new file mode 100644 index 000000000000..7a109becd1dc --- /dev/null +++ b/src/devices/ITouch.hpp @@ -0,0 +1,50 @@ +#pragma once + +#include "IHID.hpp" +#include "../helpers/WLListener.hpp" +#include "../macros.hpp" +#include "../helpers/Vector2D.hpp" + +struct wlr_touch; + +class ITouch : public IHID { + public: + virtual uint32_t getCapabilities(); + virtual bool isVirtual() = 0; + virtual wlr_touch* wlr() = 0; + + struct SDownEvent { + uint32_t timeMs = 0; + int32_t touchID = 0; + Vector2D pos; + }; + + struct SUpEvent { + uint32_t timeMs = 0; + int32_t touchID = 0; + }; + + struct SMotionEvent { + uint32_t timeMs = 0; + int32_t touchID = 0; + Vector2D pos; + }; + + struct SCancelEvent { + uint32_t timeMs = 0; + int32_t touchID = 0; + }; + + struct { + CSignal down; + CSignal up; + CSignal motion; + CSignal cancel; + CSignal frame; + } touchEvents; + + std::string hlName = ""; + std::string boundOutput = ""; + + WP self; +}; \ No newline at end of file diff --git a/src/devices/Keyboard.cpp b/src/devices/Keyboard.cpp new file mode 100644 index 000000000000..11257a74ee2d --- /dev/null +++ b/src/devices/Keyboard.cpp @@ -0,0 +1,64 @@ +#include "Keyboard.hpp" +#include "../defines.hpp" + +SP CKeyboard::create(wlr_keyboard* keeb) { + SP pKeeb = SP(new CKeyboard(keeb)); + + pKeeb->self = pKeeb; + + return pKeeb; +} + +bool CKeyboard::isVirtual() { + return false; +} + +wlr_keyboard* CKeyboard::wlr() { + return keyboard; +} + +CKeyboard::CKeyboard(wlr_keyboard* keeb) : keyboard(keeb) { + if (!keeb) + return; + + // clang-format off + hyprListener_destroy.initCallback(&keeb->base.events.destroy, [this] (void* owner, void* data) { + events.destroy.emit(); + disconnectCallbacks(); + keyboard = nullptr; + }, this, "CKeyboard"); + + hyprListener_key.initCallback(&keeb->events.key, [this] (void* owner, void* data) { + auto E = (wlr_keyboard_key_event*)data; + + keyboardEvents.key.emit(SKeyEvent{ + .timeMs = E->time_msec, + .keycode = E->keycode, + .updateMods = E->update_state, + .state = E->state, + }); + }, this, "CKeyboard"); + + hyprListener_keymap.initCallback(&keeb->events.keymap, [this] (void* owner, void* data) { + keyboardEvents.keymap.emit(); + }, this, "CKeyboard"); + + hyprListener_modifiers.initCallback(&keeb->events.modifiers, [this] (void* owner, void* data) { + keyboardEvents.modifiers.emit(); + }, this, "CKeyboard"); + + hyprListener_repeatInfo.initCallback(&keeb->events.repeat_info, [this] (void* owner, void* data) { + keyboardEvents.repeatInfo.emit(); + }, this, "CKeyboard"); + // clang-format on + + deviceName = keeb->base.name ? keeb->base.name : "UNKNOWN"; +} + +void CKeyboard::disconnectCallbacks() { + hyprListener_destroy.removeCallback(); + hyprListener_key.removeCallback(); + hyprListener_keymap.removeCallback(); + hyprListener_repeatInfo.removeCallback(); + hyprListener_modifiers.removeCallback(); +} diff --git a/src/devices/Keyboard.hpp b/src/devices/Keyboard.hpp new file mode 100644 index 000000000000..cf01a9a7a663 --- /dev/null +++ b/src/devices/Keyboard.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include "IKeyboard.hpp" + +class CKeyboard : public IKeyboard { + public: + static SP create(wlr_keyboard* keeb); + + virtual bool isVirtual(); + virtual wlr_keyboard* wlr(); + + private: + CKeyboard(wlr_keyboard* keeb); + + wlr_keyboard* keyboard = nullptr; + + void disconnectCallbacks(); + + DYNLISTENER(destroy); + DYNLISTENER(key); + DYNLISTENER(modifiers); + DYNLISTENER(keymap); + DYNLISTENER(repeatInfo); +}; \ No newline at end of file diff --git a/src/devices/Mouse.cpp b/src/devices/Mouse.cpp new file mode 100644 index 000000000000..e2a6f4ede229 --- /dev/null +++ b/src/devices/Mouse.cpp @@ -0,0 +1,169 @@ +#include "Mouse.hpp" +#include "../defines.hpp" + +SP CMouse::create(wlr_pointer* mouse) { + SP pMouse = SP(new CMouse(mouse)); + + pMouse->self = pMouse; + + return pMouse; +} + +CMouse::CMouse(wlr_pointer* mouse_) : mouse(mouse_) { + if (!mouse) + return; + + // clang-format off + hyprListener_destroy.initCallback(&mouse->base.events.destroy, [this] (void* owner, void* data) { + disconnectCallbacks(); + mouse = nullptr; + events.destroy.emit(); + }, this, "CMouse"); + + hyprListener_motion.initCallback(&mouse->events.motion, [this] (void* owner, void* data) { + auto E = (wlr_pointer_motion_event*)data; + + pointerEvents.motion.emit(SMotionEvent{ + .timeMs = E->time_msec, + .delta = {E->delta_x, E->delta_y}, + .unaccel = {E->unaccel_dx, E->unaccel_dy}, + }); + }, this, "CMouse"); + + hyprListener_motionAbsolute.initCallback(&mouse->events.motion_absolute, [this] (void* owner, void* data) { + auto E = (wlr_pointer_motion_absolute_event*)data; + + pointerEvents.motionAbsolute.emit(SMotionAbsoluteEvent{ + .timeMs = E->time_msec, + .absolute = {E->x, E->y}, + }); + }, this, "CMouse"); + + hyprListener_button.initCallback(&mouse->events.button, [this] (void* owner, void* data) { + auto E = (wlr_pointer_button_event*)data; + + pointerEvents.button.emit(SButtonEvent{ + .timeMs = E->time_msec, + .button = E->button, + .state = (wl_pointer_button_state)E->state, + }); + }, this, "CMouse"); + + hyprListener_axis.initCallback(&mouse->events.axis, [this] (void* owner, void* data) { + auto E = (wlr_pointer_axis_event*)data; + + pointerEvents.axis.emit(SAxisEvent{ + .timeMs = E->time_msec, + .source = E->source, + .axis = E->orientation, + .relativeDirection = E->relative_direction, + .delta = E->delta, + .deltaDiscrete = E->delta_discrete, + }); + }, this, "CMouse"); + + hyprListener_swipeBegin.initCallback(&mouse->events.swipe_begin, [this] (void* owner, void* data) { + auto E = (wlr_pointer_swipe_begin_event*)data; + + pointerEvents.swipeBegin.emit(SSwipeBeginEvent{ + .timeMs = E->time_msec, + .fingers = E->fingers, + }); + }, this, "CMouse"); + + hyprListener_swipeEnd.initCallback(&mouse->events.swipe_end, [this] (void* owner, void* data) { + auto E = (wlr_pointer_swipe_end_event*)data; + + pointerEvents.swipeEnd.emit(SSwipeEndEvent{ + .timeMs = E->time_msec, + .cancelled = E->cancelled, + }); + }, this, "CMouse"); + + hyprListener_swipeUpdate.initCallback(&mouse->events.swipe_update, [this] (void* owner, void* data) { + auto E = (wlr_pointer_swipe_update_event*)data; + + pointerEvents.swipeUpdate.emit(SSwipeUpdateEvent{ + .timeMs = E->time_msec, + .fingers = E->fingers, + .delta = {E->dx, E->dy}, + }); + }, this, "CMouse"); + + hyprListener_pinchBegin.initCallback(&mouse->events.pinch_begin, [this] (void* owner, void* data) { + auto E = (wlr_pointer_pinch_begin_event*)data; + + pointerEvents.pinchBegin.emit(SPinchBeginEvent{ + .timeMs = E->time_msec, + .fingers = E->fingers, + }); + }, this, "CMouse"); + + hyprListener_pinchEnd.initCallback(&mouse->events.pinch_end, [this] (void* owner, void* data) { + auto E = (wlr_pointer_pinch_end_event*)data; + + pointerEvents.pinchEnd.emit(SPinchEndEvent{ + .timeMs = E->time_msec, + .cancelled = E->cancelled, + }); + }, this, "CMouse"); + + hyprListener_pinchUpdate.initCallback(&mouse->events.pinch_update, [this] (void* owner, void* data) { + auto E = (wlr_pointer_pinch_update_event*)data; + + pointerEvents.pinchUpdate.emit(SPinchUpdateEvent{ + .timeMs = E->time_msec, + .fingers = E->fingers, + .delta = {E->dx, E->dy}, + .scale = E->scale, + .rotation = E->rotation, + }); + }, this, "CMouse"); + + hyprListener_holdBegin.initCallback(&mouse->events.hold_begin, [this] (void* owner, void* data) { + auto E = (wlr_pointer_hold_begin_event*)data; + + pointerEvents.holdBegin.emit(SHoldBeginEvent{ + .timeMs = E->time_msec, + .fingers = E->fingers, + }); + }, this, "CMouse"); + + hyprListener_holdEnd.initCallback(&mouse->events.hold_end, [this] (void* owner, void* data) { + auto E = (wlr_pointer_hold_end_event*)data; + + pointerEvents.holdEnd.emit(SHoldEndEvent{ + .timeMs = E->time_msec, + .cancelled = E->cancelled, + }); + }, this, "CMouse"); + + // clang-format on + + deviceName = mouse->base.name ? mouse->base.name : "UNKNOWN"; +} + +void CMouse::disconnectCallbacks() { + hyprListener_destroy.removeCallback(); + hyprListener_motion.removeCallback(); + hyprListener_motionAbsolute.removeCallback(); + hyprListener_button.removeCallback(); + hyprListener_axis.removeCallback(); + hyprListener_frame.removeCallback(); + hyprListener_swipeBegin.removeCallback(); + hyprListener_swipeEnd.removeCallback(); + hyprListener_swipeUpdate.removeCallback(); + hyprListener_pinchBegin.removeCallback(); + hyprListener_pinchEnd.removeCallback(); + hyprListener_pinchUpdate.removeCallback(); + hyprListener_holdBegin.removeCallback(); + hyprListener_holdEnd.removeCallback(); +} + +bool CMouse::isVirtual() { + return false; +} + +wlr_pointer* CMouse::wlr() { + return mouse; +} diff --git a/src/devices/Mouse.hpp b/src/devices/Mouse.hpp new file mode 100644 index 000000000000..40a65ca8fbd8 --- /dev/null +++ b/src/devices/Mouse.hpp @@ -0,0 +1,36 @@ +#pragma once + +#include "IPointer.hpp" + +class CMouse : public IPointer { + public: + static SP create(wlr_pointer* mouse); + + virtual bool isVirtual(); + virtual wlr_pointer* wlr(); + + private: + CMouse(wlr_pointer* mouse); + + wlr_pointer* mouse = nullptr; + + void disconnectCallbacks(); + + DYNLISTENER(destroy); + DYNLISTENER(motion); + DYNLISTENER(motionAbsolute); + DYNLISTENER(button); + DYNLISTENER(axis); + DYNLISTENER(frame); + + DYNLISTENER(swipeBegin); + DYNLISTENER(swipeEnd); + DYNLISTENER(swipeUpdate); + + DYNLISTENER(pinchBegin); + DYNLISTENER(pinchEnd); + DYNLISTENER(pinchUpdate); + + DYNLISTENER(holdBegin); + DYNLISTENER(holdEnd); +}; diff --git a/src/devices/TouchDevice.cpp b/src/devices/TouchDevice.cpp new file mode 100644 index 000000000000..20a3c55f2c4d --- /dev/null +++ b/src/devices/TouchDevice.cpp @@ -0,0 +1,85 @@ +#include "TouchDevice.hpp" +#include + +SP CTouchDevice::create(wlr_touch* touch) { + SP pTouch = SP(new CTouchDevice(touch)); + + pTouch->self = pTouch; + + return pTouch; +} + +CTouchDevice::CTouchDevice(wlr_touch* touch_) : touch(touch_) { + if (!touch) + return; + + // clang-format off + hyprListener_destroy.initCallback(&touch->base.events.destroy, [this] (void* owner, void* data) { + events.destroy.emit(); + disconnectCallbacks(); + touch = nullptr; + }, this, "CTouchDevice"); + + hyprListener_down.initCallback(&touch->events.down, [this] (void* owner, void* data) { + auto E = (wlr_touch_down_event*)data; + + touchEvents.down.emit(SDownEvent{ + .timeMs = E->time_msec, + .touchID = E->touch_id, + .pos = {E->x, E->y}, + }); + }, this, "CTouchDevice"); + + hyprListener_up.initCallback(&touch->events.up, [this] (void* owner, void* data) { + auto E = (wlr_touch_up_event*)data; + + touchEvents.up.emit(SUpEvent{ + .timeMs = E->time_msec, + .touchID = E->touch_id + }); + }, this, "CTouchDevice"); + + hyprListener_motion.initCallback(&touch->events.motion, [this] (void* owner, void* data) { + auto E = (wlr_touch_motion_event*)data; + + touchEvents.motion.emit(SMotionEvent{ + .timeMs = E->time_msec, + .touchID = E->touch_id, + .pos = {E->x, E->y}, + }); + }, this, "CTouchDevice"); + + hyprListener_cancel.initCallback(&touch->events.cancel, [this] (void* owner, void* data) { + auto E = (wlr_touch_cancel_event*)data; + + touchEvents.cancel.emit(SCancelEvent{ + .timeMs = E->time_msec, + .touchID = E->touch_id + }); + }, this, "CTouchDevice"); + + hyprListener_frame.initCallback(&touch->events.frame, [this] (void* owner, void* data) { + touchEvents.frame.emit(); + }, this, "CTouchDevice"); + + // clang-format on + + deviceName = touch->base.name ? touch->base.name : "UNKNOWN"; +} + +bool CTouchDevice::isVirtual() { + return false; +} + +wlr_touch* CTouchDevice::wlr() { + return touch; +} + +void CTouchDevice::disconnectCallbacks() { + hyprListener_destroy.removeCallback(); + hyprListener_down.removeCallback(); + hyprListener_up.removeCallback(); + hyprListener_motion.removeCallback(); + hyprListener_cancel.removeCallback(); + hyprListener_frame.removeCallback(); +} diff --git a/src/devices/TouchDevice.hpp b/src/devices/TouchDevice.hpp new file mode 100644 index 000000000000..51eb76d47bfb --- /dev/null +++ b/src/devices/TouchDevice.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include "ITouch.hpp" + +class CTouchDevice : public ITouch { + public: + static SP create(wlr_touch* touch); + + virtual bool isVirtual(); + virtual wlr_touch* wlr(); + + private: + CTouchDevice(wlr_touch* touch); + + wlr_touch* touch = nullptr; + + void disconnectCallbacks(); + + DYNLISTENER(destroy); + DYNLISTENER(down); + DYNLISTENER(up); + DYNLISTENER(motion); + DYNLISTENER(cancel); + DYNLISTENER(frame); +}; \ No newline at end of file diff --git a/src/devices/VirtualKeyboard.cpp b/src/devices/VirtualKeyboard.cpp new file mode 100644 index 000000000000..ca6156b7a106 --- /dev/null +++ b/src/devices/VirtualKeyboard.cpp @@ -0,0 +1,71 @@ +#include "VirtualKeyboard.hpp" +#include "../defines.hpp" +#include "../protocols/VirtualKeyboard.hpp" + +SP CVirtualKeyboard::create(SP keeb) { + SP pKeeb = SP(new CVirtualKeyboard(keeb)); + + pKeeb->self = pKeeb; + + return pKeeb; +} + +CVirtualKeyboard::CVirtualKeyboard(SP keeb_) : keyboard(keeb_) { + if (!keeb_) + return; + + auto keeb = keeb_->wlr(); + + // clang-format off + hyprListener_destroy.initCallback(&keeb->base.events.destroy, [this] (void* owner, void* data) { + events.destroy.emit(); + disconnectCallbacks(); + keyboard.reset(); + }, this, "CVirtualKeyboard"); + + hyprListener_key.initCallback(&keeb->events.key, [this] (void* owner, void* data) { + auto E = (wlr_keyboard_key_event*)data; + + keyboardEvents.key.emit(SKeyEvent{ + .timeMs = E->time_msec, + .keycode = E->keycode, + .updateMods = E->update_state, + .state = E->state, + }); + }, this, "CVirtualKeyboard"); + + hyprListener_keymap.initCallback(&keeb->events.keymap, [this] (void* owner, void* data) { + keyboardEvents.keymap.emit(); + }, this, "CVirtualKeyboard"); + + hyprListener_modifiers.initCallback(&keeb->events.modifiers, [this] (void* owner, void* data) { + keyboardEvents.modifiers.emit(); + }, this, "CVirtualKeyboard"); + + hyprListener_repeatInfo.initCallback(&keeb->events.repeat_info, [this] (void* owner, void* data) { + keyboardEvents.repeatInfo.emit(); + }, this, "CVirtualKeyboard"); + // clang-format on + + deviceName = keeb->base.name ? keeb->base.name : "UNKNOWN"; +} + +bool CVirtualKeyboard::isVirtual() { + return true; +} + +wlr_keyboard* CVirtualKeyboard::wlr() { + return keyboard.lock()->wlr(); +} + +void CVirtualKeyboard::disconnectCallbacks() { + hyprListener_destroy.removeCallback(); + hyprListener_key.removeCallback(); + hyprListener_keymap.removeCallback(); + hyprListener_repeatInfo.removeCallback(); + hyprListener_modifiers.removeCallback(); +} + +wl_client* CVirtualKeyboard::getClient() { + return keyboard.lock()->client(); +} diff --git a/src/devices/VirtualKeyboard.hpp b/src/devices/VirtualKeyboard.hpp new file mode 100644 index 000000000000..5ef88dd3f3e5 --- /dev/null +++ b/src/devices/VirtualKeyboard.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include "IKeyboard.hpp" + +class CVirtualKeyboardV1Resource; + +class CVirtualKeyboard : public IKeyboard { + public: + static SP create(SP keeb); + + virtual bool isVirtual(); + virtual wlr_keyboard* wlr(); + + wl_client* getClient(); + + private: + CVirtualKeyboard(SP keeb); + + WP keyboard; + + void disconnectCallbacks(); + + DYNLISTENER(destroy); + DYNLISTENER(key); + DYNLISTENER(modifiers); + DYNLISTENER(keymap); + DYNLISTENER(repeatInfo); +}; diff --git a/src/devices/VirtualPointer.cpp b/src/devices/VirtualPointer.cpp new file mode 100644 index 000000000000..8f8699a2c40a --- /dev/null +++ b/src/devices/VirtualPointer.cpp @@ -0,0 +1,170 @@ +#include "VirtualPointer.hpp" +#include "../protocols/VirtualPointer.hpp" + +SP CVirtualPointer::create(SP resource) { + SP pPointer = SP(new CVirtualPointer(resource)); + + pPointer->self = pPointer; + + return pPointer; +} + +CVirtualPointer::CVirtualPointer(SP resource) : pointer(resource) { + if (!resource->good()) + return; + + auto mouse = resource->wlr(); + + // clang-format off + hyprListener_destroy.initCallback(&mouse->base.events.destroy, [this] (void* owner, void* data) { + disconnectCallbacks(); + events.destroy.emit(); + }, this, "CVirtualPointer"); + + hyprListener_motion.initCallback(&mouse->events.motion, [this] (void* owner, void* data) { + auto E = (wlr_pointer_motion_event*)data; + + pointerEvents.motion.emit(SMotionEvent{ + .timeMs = E->time_msec, + .delta = {E->delta_x, E->delta_y}, + .unaccel = {E->unaccel_dx, E->unaccel_dy}, + }); + }, this, "CVirtualPointer"); + + hyprListener_motionAbsolute.initCallback(&mouse->events.motion_absolute, [this] (void* owner, void* data) { + auto E = (wlr_pointer_motion_absolute_event*)data; + + pointerEvents.motionAbsolute.emit(SMotionAbsoluteEvent{ + .timeMs = E->time_msec, + .absolute = {E->x, E->y}, + }); + }, this, "CVirtualPointer"); + + hyprListener_button.initCallback(&mouse->events.button, [this] (void* owner, void* data) { + auto E = (wlr_pointer_button_event*)data; + + pointerEvents.button.emit(SButtonEvent{ + .timeMs = E->time_msec, + .button = E->button, + .state = (wl_pointer_button_state)E->state, + }); + }, this, "CVirtualPointer"); + + hyprListener_axis.initCallback(&mouse->events.axis, [this] (void* owner, void* data) { + auto E = (wlr_pointer_axis_event*)data; + + pointerEvents.axis.emit(SAxisEvent{ + .timeMs = E->time_msec, + .source = E->source, + .axis = E->orientation, + .relativeDirection = E->relative_direction, + .delta = E->delta, + .deltaDiscrete = E->delta_discrete, + }); + }, this, "CVirtualPointer"); + + hyprListener_swipeBegin.initCallback(&mouse->events.swipe_begin, [this] (void* owner, void* data) { + auto E = (wlr_pointer_swipe_begin_event*)data; + + pointerEvents.swipeBegin.emit(SSwipeBeginEvent{ + .timeMs = E->time_msec, + .fingers = E->fingers, + }); + }, this, "CVirtualPointer"); + + hyprListener_swipeEnd.initCallback(&mouse->events.swipe_end, [this] (void* owner, void* data) { + auto E = (wlr_pointer_swipe_end_event*)data; + + pointerEvents.swipeEnd.emit(SSwipeEndEvent{ + .timeMs = E->time_msec, + .cancelled = E->cancelled, + }); + }, this, "CVirtualPointer"); + + hyprListener_swipeUpdate.initCallback(&mouse->events.swipe_update, [this] (void* owner, void* data) { + auto E = (wlr_pointer_swipe_update_event*)data; + + pointerEvents.swipeUpdate.emit(SSwipeUpdateEvent{ + .timeMs = E->time_msec, + .fingers = E->fingers, + .delta = {E->dx, E->dy}, + }); + }, this, "CVirtualPointer"); + + hyprListener_pinchBegin.initCallback(&mouse->events.pinch_begin, [this] (void* owner, void* data) { + auto E = (wlr_pointer_pinch_begin_event*)data; + + pointerEvents.pinchBegin.emit(SPinchBeginEvent{ + .timeMs = E->time_msec, + .fingers = E->fingers, + }); + }, this, "CVirtualPointer"); + + hyprListener_pinchEnd.initCallback(&mouse->events.pinch_end, [this] (void* owner, void* data) { + auto E = (wlr_pointer_pinch_end_event*)data; + + pointerEvents.pinchEnd.emit(SPinchEndEvent{ + .timeMs = E->time_msec, + .cancelled = E->cancelled, + }); + }, this, "CVirtualPointer"); + + hyprListener_pinchUpdate.initCallback(&mouse->events.pinch_update, [this] (void* owner, void* data) { + auto E = (wlr_pointer_pinch_update_event*)data; + + pointerEvents.pinchUpdate.emit(SPinchUpdateEvent{ + .timeMs = E->time_msec, + .fingers = E->fingers, + .delta = {E->dx, E->dy}, + .scale = E->scale, + .rotation = E->rotation, + }); + }, this, "CVirtualPointer"); + + hyprListener_holdBegin.initCallback(&mouse->events.hold_begin, [this] (void* owner, void* data) { + auto E = (wlr_pointer_hold_begin_event*)data; + + pointerEvents.holdBegin.emit(SHoldBeginEvent{ + .timeMs = E->time_msec, + .fingers = E->fingers, + }); + }, this, "CVirtualPointer"); + + hyprListener_holdEnd.initCallback(&mouse->events.hold_end, [this] (void* owner, void* data) { + auto E = (wlr_pointer_hold_end_event*)data; + + pointerEvents.holdEnd.emit(SHoldEndEvent{ + .timeMs = E->time_msec, + .cancelled = E->cancelled, + }); + }, this, "CVirtualPointer"); + + // clang-format on + + deviceName = mouse->base.name ? mouse->base.name : "UNKNOWN"; +} + +bool CVirtualPointer::isVirtual() { + return true; +} + +void CVirtualPointer::disconnectCallbacks() { + hyprListener_destroy.removeCallback(); + hyprListener_motion.removeCallback(); + hyprListener_motionAbsolute.removeCallback(); + hyprListener_button.removeCallback(); + hyprListener_axis.removeCallback(); + hyprListener_frame.removeCallback(); + hyprListener_swipeBegin.removeCallback(); + hyprListener_swipeEnd.removeCallback(); + hyprListener_swipeUpdate.removeCallback(); + hyprListener_pinchBegin.removeCallback(); + hyprListener_pinchEnd.removeCallback(); + hyprListener_pinchUpdate.removeCallback(); + hyprListener_holdBegin.removeCallback(); + hyprListener_holdEnd.removeCallback(); +} + +wlr_pointer* CVirtualPointer::wlr() { + return pointer.lock()->wlr(); +} diff --git a/src/devices/VirtualPointer.hpp b/src/devices/VirtualPointer.hpp new file mode 100644 index 000000000000..b22c8bf2d082 --- /dev/null +++ b/src/devices/VirtualPointer.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include "IPointer.hpp" + +class CVirtualPointerV1Resource; + +class CVirtualPointer : public IPointer { + public: + static SP create(SP resource); + + virtual bool isVirtual(); + virtual wlr_pointer* wlr(); + + private: + CVirtualPointer(SP); + + WP pointer; + + void disconnectCallbacks(); + + DYNLISTENER(destroy); + DYNLISTENER(motion); + DYNLISTENER(motionAbsolute); + DYNLISTENER(button); + DYNLISTENER(axis); + DYNLISTENER(frame); + + DYNLISTENER(swipeBegin); + DYNLISTENER(swipeEnd); + DYNLISTENER(swipeUpdate); + + DYNLISTENER(pinchBegin); + DYNLISTENER(pinchEnd); + DYNLISTENER(pinchUpdate); + + DYNLISTENER(holdBegin); + DYNLISTENER(holdEnd); +}; \ No newline at end of file diff --git a/src/events/Devices.cpp b/src/events/Devices.cpp index ec0b14c4cd86..1de1b7685996 100644 --- a/src/events/Devices.cpp +++ b/src/events/Devices.cpp @@ -16,23 +16,6 @@ // // // ---------------------------------------------------- // -void Events::listener_keyboardDestroy(void* owner, void* data) { - SKeyboard* PKEYBOARD = (SKeyboard*)owner; - g_pInputManager->destroyKeyboard(PKEYBOARD); - - Debug::log(LOG, "Destroyed keyboard {:x}", (uintptr_t)PKEYBOARD); -} - -void Events::listener_keyboardKey(void* owner, void* data) { - SKeyboard* PKEYBOARD = (SKeyboard*)owner; - g_pInputManager->onKeyboardKey((wlr_keyboard_key_event*)data, PKEYBOARD); -} - -void Events::listener_keyboardMod(void* owner, void* data) { - SKeyboard* PKEYBOARD = (SKeyboard*)owner; - g_pInputManager->onKeyboardMod(data, PKEYBOARD); -} - void Events::listener_mouseFrame(wl_listener* listener, void* data) { wlr_seat_pointer_notify_frame(g_pCompositor->m_sSeat.seat); } @@ -93,12 +76,6 @@ void Events::listener_newInput(wl_listener* listener, void* data) { g_pInputManager->updateCapabilities(); } -void Events::listener_destroyMouse(void* owner, void* data) { - const auto PMOUSE = (SMouse*)owner; - - g_pInputManager->destroyMouse(PMOUSE->mouse); -} - void Events::listener_swipeBegin(wl_listener* listener, void* data) { const auto EVENT = (wlr_pointer_swipe_begin_event*)data; diff --git a/src/events/Events.hpp b/src/events/Events.hpp index 5fa93c49b536..830ca8d10567 100644 --- a/src/events/Events.hpp +++ b/src/events/Events.hpp @@ -54,11 +54,6 @@ namespace Events { // Virt Ptr LISTENER(newVirtPtr); - DYNLISTENFUNC(destroyMouse); - - DYNLISTENFUNC(keyboardKey); - DYNLISTENFUNC(keyboardMod); - DYNLISTENFUNC(keyboardDestroy); // Various LISTENER(requestMouse); diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index dfc694c09e73..e3d06691d345 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -667,7 +667,7 @@ void Events::listener_mapWindow(void* owner, void* data) { g_pCompositor->setPreferredScaleForSurface(PWINDOW->m_pWLSurface.wlr(), PMONITOR->scale); g_pCompositor->setPreferredTransformForSurface(PWINDOW->m_pWLSurface.wlr(), PMONITOR->transform); - if (!g_pCompositor->m_sSeat.mouse || !g_pInputManager->isConstrained()) + if (g_pCompositor->m_sSeat.mouse.expired() || !g_pInputManager->isConstrained()) g_pInputManager->sendMotionEventsToFocused(); // fix some xwayland apps that don't behave nicely diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index ffa8b7d86e77..1369244d7130 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -3,6 +3,7 @@ #include "../Compositor.hpp" #include "../config/ConfigValue.hpp" #include "../protocols/GammaControl.hpp" +#include "../devices/ITouch.hpp" int ratHandler(void* data) { g_pHyprRenderer->renderMonitor((CMonitor*)data); @@ -145,10 +146,10 @@ void CMonitor::onConnect(bool noRule) { if (!noRule) g_pHyprRenderer->applyMonitorRule(this, &monitorRule, true); - for (const auto& PTOUCHDEV : g_pInputManager->m_lTouchDevices) { - if (matchesStaticSelector(PTOUCHDEV.boundOutput)) { - Debug::log(LOG, "Binding touch device {} to output {}", PTOUCHDEV.name, szName); - wlr_cursor_map_input_to_output(g_pCompositor->m_sWLRCursor, PTOUCHDEV.pWlrDevice, output); + for (const auto& PTOUCHDEV : g_pInputManager->m_vTouches) { + if (matchesStaticSelector(PTOUCHDEV->boundOutput)) { + Debug::log(LOG, "Binding touch device {} to output {}", PTOUCHDEV->hlName, szName); + wlr_cursor_map_input_to_output(g_pCompositor->m_sWLRCursor, &PTOUCHDEV->wlr()->base, output); } } diff --git a/src/helpers/WLClasses.cpp b/src/helpers/WLClasses.cpp index 4cdde4a095e4..61ab1133063c 100644 --- a/src/helpers/WLClasses.cpp +++ b/src/helpers/WLClasses.cpp @@ -1,78 +1 @@ #include "WLClasses.hpp" - -void SKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) { - xkb_state_unref(xkbTranslationState); - - if (keymap) { - Debug::log(LOG, "Updating keyboard {:x}'s translation state from a provided keymap", (uintptr_t)this); - xkbTranslationState = xkb_state_new(keymap); - return; - } - - const auto WLRKB = wlr_keyboard_from_input_device(keyboard); - const auto KEYMAP = WLRKB->keymap; - const auto STATE = WLRKB->xkb_state; - const auto LAYOUTSNUM = xkb_keymap_num_layouts(KEYMAP); - - const auto PCONTEXT = xkb_context_new(XKB_CONTEXT_NO_FLAGS); - - for (uint32_t i = 0; i < LAYOUTSNUM; ++i) { - if (xkb_state_layout_index_is_active(STATE, i, XKB_STATE_LAYOUT_EFFECTIVE)) { - Debug::log(LOG, "Updating keyboard {:x}'s translation state from an active index {}", (uintptr_t)this, i); - - CVarList keyboardLayouts(currentRules.layout, 0, ','); - CVarList keyboardModels(currentRules.model, 0, ','); - CVarList keyboardVariants(currentRules.variant, 0, ','); - - xkb_rule_names rules = {.rules = "", .model = "", .layout = "", .variant = "", .options = ""}; - - std::string layout, model, variant; - layout = keyboardLayouts[i % keyboardLayouts.size()]; - model = keyboardModels[i % keyboardModels.size()]; - variant = keyboardVariants[i % keyboardVariants.size()]; - - rules.layout = layout.c_str(); - rules.model = model.c_str(); - rules.variant = variant.c_str(); - - auto KEYMAP = xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); - - if (!KEYMAP) { - Debug::log(ERR, "updateXKBTranslationState: keymap failed 1, fallback without model/variant"); - rules.model = ""; - rules.variant = ""; - KEYMAP = xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); - } - - if (!KEYMAP) { - Debug::log(ERR, "updateXKBTranslationState: keymap failed 2, fallback to us"); - rules.layout = "us"; - KEYMAP = xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); - } - - xkbTranslationState = xkb_state_new(KEYMAP); - - xkb_keymap_unref(KEYMAP); - xkb_context_unref(PCONTEXT); - - return; - } - } - - Debug::log(LOG, "Updating keyboard {:x}'s translation state from an unknown index", (uintptr_t)this); - - xkb_rule_names rules = { - .rules = currentRules.rules.c_str(), - .model = currentRules.model.c_str(), - .layout = currentRules.layout.c_str(), - .variant = currentRules.variant.c_str(), - .options = currentRules.options.c_str(), - }; - - const auto NEWKEYMAP = xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); - - xkbTranslationState = xkb_state_new(NEWKEYMAP); - - xkb_keymap_unref(NEWKEYMAP); - xkb_context_unref(PCONTEXT); -} diff --git a/src/helpers/WLClasses.hpp b/src/helpers/WLClasses.hpp index c625aae0f776..bed2b9151312 100644 --- a/src/helpers/WLClasses.hpp +++ b/src/helpers/WLClasses.hpp @@ -11,8 +11,8 @@ #include "Region.hpp" class CMonitor; -class CVirtualKeyboard; -class CVirtualPointer; +class IPointer; +class IKeyboard; struct SRenderData { CMonitor* pMonitor; @@ -58,86 +58,12 @@ struct SExtensionFindingData { wlr_surface** found; }; -struct SStringRuleNames { - std::string layout = ""; - std::string model = ""; - std::string variant = ""; - std::string options = ""; - std::string rules = ""; -}; - -struct SKeyboard { - wlr_input_device* keyboard; - - DYNLISTENER(keyboardMod); - DYNLISTENER(keyboardKey); - DYNLISTENER(keyboardKeymap); - DYNLISTENER(keyboardDestroy); - - bool isVirtual = false; - bool active = false; - bool enabled = true; - - WP virtKeyboard; - - xkb_layout_index_t activeLayout = 0; - xkb_state* xkbTranslationState = nullptr; - - std::string name = ""; - std::string xkbFilePath = ""; - - SStringRuleNames currentRules; - int repeatRate = 0; - int repeatDelay = 0; - int numlockOn = -1; - bool resolveBindsBySym = false; - - void updateXKBTranslationState(xkb_keymap* const keymap = nullptr); - - struct { - CHyprSignalListener destroyVKeyboard; - } listeners; - - // For the list lookup - bool operator==(const SKeyboard& rhs) const { - return keyboard == rhs.keyboard; - } - - ~SKeyboard() { - if (xkbTranslationState) - xkb_state_unref(xkbTranslationState); - } -}; - -struct SMouse { - wlr_input_device* mouse = nullptr; - - std::string name = ""; - - bool virt = false; - - bool connected = false; // means connected to the cursor - - WP virtualPointer; - - struct { - CHyprSignalListener destroyMouse; - } listeners; - - DYNLISTENER(destroyMouse); - - bool operator==(const SMouse& b) const { - return mouse == b.mouse; - } -}; - -class CMonitor; - struct SSeat { - wlr_seat* seat = nullptr; - wl_client* exclusiveClient = nullptr; + wlr_seat* seat = nullptr; + wl_client* exclusiveClient = nullptr; - SMouse* mouse = nullptr; + WP mouse; + WP keyboard; }; struct SDrag { @@ -238,20 +164,6 @@ struct SSwipeGesture { CMonitor* pMonitor = nullptr; }; -struct STouchDevice { - wlr_input_device* pWlrDevice = nullptr; - - std::string name = ""; - - std::string boundOutput = ""; - - DYNLISTENER(destroy); - - bool operator==(const STouchDevice& other) const { - return pWlrDevice == other.pWlrDevice; - } -}; - struct SSwitchDevice { wlr_input_device* pWlrDevice = nullptr; diff --git a/src/helpers/signal/Listener.cpp b/src/helpers/signal/Listener.cpp index ae5063430b1b..4023477fde7c 100644 --- a/src/helpers/signal/Listener.cpp +++ b/src/helpers/signal/Listener.cpp @@ -11,3 +11,11 @@ void CSignalListener::emit(std::any data) { m_fHandler(data); } + +CStaticSignalListener::CStaticSignalListener(std::function handler, void* owner) : m_pOwner(owner), m_fHandler(handler) { + ; +} + +void CStaticSignalListener::emit(std::any data) { + m_fHandler(m_pOwner, data); +} diff --git a/src/helpers/signal/Listener.hpp b/src/helpers/signal/Listener.hpp index d2edb2536182..7ca96e87e0ec 100644 --- a/src/helpers/signal/Listener.hpp +++ b/src/helpers/signal/Listener.hpp @@ -22,3 +22,19 @@ class CSignalListener { }; typedef std::shared_ptr CHyprSignalListener; + +class CStaticSignalListener { + public: + CStaticSignalListener(std::function handler, void* owner); + + CStaticSignalListener(CStaticSignalListener&&) = delete; + CStaticSignalListener(CStaticSignalListener&) = delete; + CStaticSignalListener(const CStaticSignalListener&) = delete; + CStaticSignalListener(const CStaticSignalListener&&) = delete; + + void emit(std::any data); + + private: + void* m_pOwner = nullptr; + std::function m_fHandler; +}; \ No newline at end of file diff --git a/src/helpers/signal/Signal.cpp b/src/helpers/signal/Signal.cpp index 204aaf0004b2..d105eb78252c 100644 --- a/src/helpers/signal/Signal.cpp +++ b/src/helpers/signal/Signal.cpp @@ -11,6 +11,10 @@ void CSignal::emit(std::any data) { dirty = true; } + for (auto& l : m_vStaticListeners) { + l->emit(data); + } + if (dirty) std::erase_if(m_vListeners, [](const auto& other) { return other.expired(); }); } @@ -20,3 +24,7 @@ CHyprSignalListener CSignal::registerListener(std::function hand m_vListeners.emplace_back(std::weak_ptr(listener)); return listener; } + +void CSignal::registerStaticListener(std::function handler, void* owner) { + m_vStaticListeners.emplace_back(std::make_unique(handler, owner)); +} \ No newline at end of file diff --git a/src/helpers/signal/Signal.hpp b/src/helpers/signal/Signal.hpp index f12d0dc4d837..8938a70c7d12 100644 --- a/src/helpers/signal/Signal.hpp +++ b/src/helpers/signal/Signal.hpp @@ -14,6 +14,11 @@ class CSignal { // [[nodiscard("Listener is unregistered when the ptr is lost")]] CHyprSignalListener registerListener(std::function handler); + // this is for static listeners. They die with this signal. + // TODO: can we somehow rid of the void* data and make it a custom this? + void registerStaticListener(std::function handler, void* owner); + private: - std::vector> m_vListeners; + std::vector> m_vListeners; + std::vector> m_vStaticListeners; }; diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 4e98a3010341..7708a77a596e 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -5,6 +5,7 @@ #include "../config/ConfigValue.hpp" #include "TokenManager.hpp" #include "../protocols/ShortcutsInhibit.hpp" +#include "../devices/IKeyboard.hpp" #include #include @@ -323,7 +324,7 @@ void CKeybindManager::switchToWindow(PHLWINDOW PWINDOWTOCHANGETO) { } }; -bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard) { +bool CKeybindManager::onKeyEvent(std::any event, SP pKeyboard) { if (!g_pCompositor->m_bSessionActive || g_pCompositor->m_bUnsafeState) { m_dPressedKeys.clear(); return true; @@ -337,17 +338,19 @@ bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard return true; } - const auto KEYCODE = e->keycode + 8; // Because to xkbcommon it's +8 from libinput + auto e = std::any_cast(event); + + const auto KEYCODE = e.keycode + 8; // Because to xkbcommon it's +8 from libinput const xkb_keysym_t keysym = xkb_state_key_get_one_sym(pKeyboard->resolveBindsBySym ? pKeyboard->xkbTranslationState : m_pXKBTranslationState, KEYCODE); - const xkb_keysym_t internalKeysym = xkb_state_key_get_one_sym(wlr_keyboard_from_input_device(pKeyboard->keyboard)->xkb_state, KEYCODE); + const xkb_keysym_t internalKeysym = xkb_state_key_get_one_sym(pKeyboard->wlr()->xkb_state, KEYCODE); if (handleInternalKeybinds(internalKeysym)) return true; const auto MODS = g_pInputManager->accumulateModsFromAllKBs(); - m_uTimeLastMs = e->time_msec; + m_uTimeLastMs = e.timeMs; m_uLastCode = KEYCODE; m_uLastMouseCode = 0; @@ -368,7 +371,7 @@ bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard } bool suppressEvent = false; - if (e->state == WL_KEYBOARD_KEY_STATE_PRESSED) { + if (e.state == WL_KEYBOARD_KEY_STATE_PRESSED) { m_dPressedKeys.push_back(KEY); @@ -521,7 +524,7 @@ void CKeybindManager::onSwitchOffEvent(const std::string& switchName) { int repeatKeyHandler(void* data) { SKeybind** ppActiveKeybind = (SKeybind**)data; - if (!*ppActiveKeybind) + if (!*ppActiveKeybind || g_pCompositor->m_sSeat.keyboard.expired()) return 0; const auto DISPATCHER = g_pKeybindManager->m_mDispatchers.find((*ppActiveKeybind)->handler); @@ -529,7 +532,7 @@ int repeatKeyHandler(void* data) { Debug::log(LOG, "Keybind repeat triggered, calling dispatcher."); DISPATCHER->second((*ppActiveKeybind)->arg); - wl_event_source_timer_update(g_pKeybindManager->m_pActiveKeybindEventSource, 1000 / g_pInputManager->m_pActiveKeyboard->repeatRate); + wl_event_source_timer_update(g_pKeybindManager->m_pActiveKeybindEventSource, 1000 / g_pCompositor->m_sSeat.keyboard.lock()->repeatRate); return 0; } @@ -650,7 +653,7 @@ bool CKeybindManager::handleKeybinds(const uint32_t modmask, const SPressedKeyWi m_pActiveKeybind = &k; m_pActiveKeybindEventSource = wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, repeatKeyHandler, &m_pActiveKeybind); - const auto PACTIVEKEEB = g_pInputManager->m_pActiveKeyboard; + const auto PACTIVEKEEB = g_pCompositor->m_sSeat.keyboard.lock(); wl_event_source_timer_update(m_pActiveKeybindEventSource, PACTIVEKEEB->repeatDelay); } @@ -1440,22 +1443,20 @@ void CKeybindManager::moveCursorToCorner(std::string arg) { switch (CORNER) { case 0: // bottom left - wlr_cursor_warp(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, PWINDOW->m_vRealPosition.value().x, - PWINDOW->m_vRealPosition.value().y + PWINDOW->m_vRealSize.value().y); + wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, PWINDOW->m_vRealPosition.value().x, PWINDOW->m_vRealPosition.value().y + PWINDOW->m_vRealSize.value().y); break; case 1: // bottom right - wlr_cursor_warp(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, PWINDOW->m_vRealPosition.value().x + PWINDOW->m_vRealSize.value().x, + wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, PWINDOW->m_vRealPosition.value().x + PWINDOW->m_vRealSize.value().x, PWINDOW->m_vRealPosition.value().y + PWINDOW->m_vRealSize.value().y); break; case 2: // top right - wlr_cursor_warp(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, PWINDOW->m_vRealPosition.value().x + PWINDOW->m_vRealSize.value().x, - PWINDOW->m_vRealPosition.value().y); + wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, PWINDOW->m_vRealPosition.value().x + PWINDOW->m_vRealSize.value().x, PWINDOW->m_vRealPosition.value().y); break; case 3: // top left - wlr_cursor_warp(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, PWINDOW->m_vRealPosition.value().x, PWINDOW->m_vRealPosition.value().y); + wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, PWINDOW->m_vRealPosition.value().x, PWINDOW->m_vRealPosition.value().y); break; } } @@ -1485,7 +1486,7 @@ void CKeybindManager::moveCursor(std::string args) { x = std::stoi(x_str); y = std::stoi(y_str); - wlr_cursor_warp(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, x, y); + wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, x, y); } void CKeybindManager::workspaceOpt(std::string args) { diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index 24e71c6a055b..c382f3eb4734 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -9,6 +9,7 @@ class CInputManager; class CConfigManager; class CPluginSystem; +class IKeyboard; struct SKeybind { std::string key = ""; @@ -60,7 +61,7 @@ class CKeybindManager { CKeybindManager(); ~CKeybindManager(); - bool onKeyEvent(wlr_keyboard_key_event*, SKeyboard*); + bool onKeyEvent(std::any, SP); bool onAxisEvent(wlr_pointer_axis_event*); bool onMouseEvent(wlr_pointer_button_event*); void resizeWithBorder(wlr_pointer_button_event*); diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index fb9d2b8abdfe..10b124048869 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -14,6 +14,12 @@ #include "../../protocols/VirtualKeyboard.hpp" #include "../../protocols/VirtualPointer.hpp" +#include "../../devices/Mouse.hpp" +#include "../../devices/VirtualPointer.hpp" +#include "../../devices/Keyboard.hpp" +#include "../../devices/VirtualKeyboard.hpp" +#include "../../devices/TouchDevice.hpp" + CInputManager::CInputManager() { m_sListeners.setCursorShape = PROTO::cursorShape->events.setShape.registerListener([this](std::any data) { if (!cursorImageUnlocked()) @@ -40,20 +46,20 @@ 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>(data)); }); + PROTO::virtualKeyboard->events.newKeyboard.registerListener([this](std::any data) { this->newVirtualKeyboard(std::any_cast>(data)); }); m_sListeners.newVirtualMouse = - PROTO::virtualPointer->events.newPointer.registerListener([this](std::any data) { this->newVirtualMouse(std::any_cast>(data)); }); + PROTO::virtualPointer->events.newPointer.registerListener([this](std::any data) { this->newVirtualMouse(std::any_cast>(data)); }); } CInputManager::~CInputManager() { m_vConstraints.clear(); - m_lKeyboards.clear(); - m_lMice.clear(); + m_vKeyboards.clear(); + m_vPointers.clear(); + m_vTouches.clear(); m_lTablets.clear(); m_lTabletTools.clear(); m_lTabletPads.clear(); m_vIdleInhibitors.clear(); - m_lTouchDevices.clear(); m_lSwitches.clear(); } @@ -181,7 +187,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { } // constraints - if (g_pCompositor->m_sSeat.mouse && isConstrained()) { + if (!g_pCompositor->m_sSeat.mouse.expired() && isConstrained()) { const auto SURF = CWLSurface::surfaceFromWlr(g_pCompositor->m_pLastFocus); const auto CONSTRAINT = SURF->constraint(); @@ -651,7 +657,7 @@ void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) { if (*PFOLLOWMOUSE == 3) // don't refocus on full loose break; - if ((!g_pCompositor->m_sSeat.mouse || !isConstrained()) /* No constraints */ + if ((g_pCompositor->m_sSeat.mouse.expired() || !isConstrained()) /* No constraints */ && (w && g_pCompositor->m_pLastWindow.lock() != w) /* window should change */) { // a bit hacky // if we only pressed one button, allow us to refocus. m_lCurrentlyHeldButtons.size() > 0 will stick the focus @@ -754,105 +760,84 @@ Vector2D CInputManager::getMouseCoordsInternal() { } void CInputManager::newKeyboard(wlr_input_device* keyboard) { - const auto PNEWKEYBOARD = &m_lKeyboards.emplace_back(); - - PNEWKEYBOARD->keyboard = keyboard; - - try { - PNEWKEYBOARD->name = getNameForNewDevice(keyboard->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_keyboardKeymap.initCallback( - &wlr_keyboard_from_input_device(keyboard)->events.keymap, - [&](void* owner, void* data) { - const auto PKEYBOARD = (SKeyboard*)owner; - const auto LAYOUT = getActiveLayoutForKeyboard(PKEYBOARD); + const auto PNEWKEYBOARD = m_vKeyboards.emplace_back(CKeyboard::create(wlr_keyboard_from_input_device(keyboard))); - g_pEventManager->postEvent(SHyprIPCEvent{"activelayout", PKEYBOARD->name + "," + LAYOUT}); - EMIT_HOOK_EVENT("activeLayout", (std::vector{PKEYBOARD, (void*)&LAYOUT})); - }, - PNEWKEYBOARD, "Keyboard"); - - disableAllKeyboards(false); + setupKeyboard(PNEWKEYBOARD); - m_pActiveKeyboard = PNEWKEYBOARD; - - PNEWKEYBOARD->active = true; + Debug::log(LOG, "New keyboard created, pointers Hypr: {:x} and WLR: {:x}", (uintptr_t)PNEWKEYBOARD.get(), (uintptr_t)keyboard); +} - applyConfigToKeyboard(PNEWKEYBOARD); +void CInputManager::newVirtualKeyboard(SP keyboard) { + const auto PNEWKEYBOARD = m_vKeyboards.emplace_back(CVirtualKeyboard::create(keyboard)); - wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, wlr_keyboard_from_input_device(keyboard)); + setupKeyboard(PNEWKEYBOARD); - Debug::log(LOG, "New 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.get(), (uintptr_t)keyboard->wlr()); } -void CInputManager::newVirtualKeyboard(SP keyboard) { - const auto PNEWKEYBOARD = &m_lKeyboards.emplace_back(); - - PNEWKEYBOARD->keyboard = &keyboard->wlr()->base; - PNEWKEYBOARD->isVirtual = true; - PNEWKEYBOARD->virtKeyboard = keyboard; - +void CInputManager::setupKeyboard(SP keeb) { try { - PNEWKEYBOARD->name = getNameForNewDevice(keyboard->wlr()->base.name); + keeb->hlName = getNameForNewDevice(keeb->wlr()->base.name); } catch (std::exception& e) { Debug::log(ERR, "Keyboard had no name???"); // logic error } - 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( - &keyboard->wlr()->events.keymap, - [&](void* owner, void* data) { - const auto PKEYBOARD = (SKeyboard*)owner; - const auto LAYOUT = getActiveLayoutForKeyboard(PKEYBOARD); + keeb->events.destroy.registerStaticListener( + [this](void* owner, std::any data) { + auto PKEEB = ((IKeyboard*)owner)->self.lock(); + destroyKeyboard(PKEEB); + Debug::log(LOG, "Destroyed keyboard {:x}", (uintptr_t)owner); + }, + keeb.get()); - g_pEventManager->postEvent(SHyprIPCEvent{"activelayout", PKEYBOARD->name + "," + LAYOUT}); - EMIT_HOOK_EVENT("activeLayout", (std::vector{PKEYBOARD, (void*)&LAYOUT})); + keeb->keyboardEvents.key.registerStaticListener( + [this](void* owner, std::any data) { + auto PKEEB = ((IKeyboard*)owner)->self.lock(); + onKeyboardKey(data, PKEEB); }, - PNEWKEYBOARD, "VKeyboard"); + keeb.get()); - // TODO: this pointer pass sucks. - PNEWKEYBOARD->listeners.destroyVKeyboard = keyboard->events.destroy.registerListener([this, PNEWKEYBOARD](std::any data) { destroyKeyboard(PNEWKEYBOARD); }); + keeb->keyboardEvents.modifiers.registerStaticListener( + [this](void* owner, std::any data) { + auto PKEEB = ((IKeyboard*)owner)->self.lock(); + onKeyboardMod(PKEEB); + }, + keeb.get()); - disableAllKeyboards(true); + keeb->keyboardEvents.keymap.registerStaticListener( + [this](void* owner, std::any data) { + auto PKEEB = ((IKeyboard*)owner)->self.lock(); + const auto LAYOUT = PKEEB->getActiveLayout(); - m_pActiveKeyboard = PNEWKEYBOARD; + g_pEventManager->postEvent(SHyprIPCEvent{"activelayout", PKEEB->hlName + "," + LAYOUT}); + EMIT_HOOK_EVENT("activeLayout", (std::vector{PKEEB, LAYOUT})); + }, + keeb.get()); + + disableAllKeyboards(false); - PNEWKEYBOARD->active = true; + g_pCompositor->m_sSeat.keyboard = keeb; - applyConfigToKeyboard(PNEWKEYBOARD); + keeb->active = true; - wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, keyboard->wlr()); + applyConfigToKeyboard(keeb); - Debug::log(LOG, "New virtual keyboard created, pointers Hypr: {:x} and WLR: {:x}", (uintptr_t)PNEWKEYBOARD, (uintptr_t)keyboard->wlr()); + wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, keeb->wlr()); } void CInputManager::setKeyboardLayout() { - for (auto& k : m_lKeyboards) - applyConfigToKeyboard(&k); + for (auto& k : m_vKeyboards) + applyConfigToKeyboard(k); g_pKeybindManager->updateXKBTranslationState(); } -void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) { - auto devname = pKeyboard->name; +void CInputManager::applyConfigToKeyboard(SP pKeyboard) { + auto devname = pKeyboard->hlName; const auto HASCONFIG = g_pConfigManager->deviceConfigExists(devname); - Debug::log(LOG, "ApplyConfigToKeyboard for \"{}\", hasconfig: {}", pKeyboard->name, (int)HASCONFIG); - - ASSERT(pKeyboard); - - if (!wlr_keyboard_from_input_device(pKeyboard->keyboard)) - return; + Debug::log(LOG, "ApplyConfigToKeyboard for \"{}\", hasconfig: {}", devname, (int)HASCONFIG); const auto REPEATRATE = g_pConfigManager->getDeviceInt(devname, "repeat_rate", "input:repeat_rate"); const auto REPEATDELAY = g_pConfigManager->getDeviceInt(devname, "repeat_delay", "input:repeat_delay"); @@ -884,7 +869,7 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) { // we can ignore those and just apply } - wlr_keyboard_set_repeat_info(wlr_keyboard_from_input_device(pKeyboard->keyboard), std::max(0, REPEATRATE), std::max(0, REPEATDELAY)); + wlr_keyboard_set_repeat_info(pKeyboard->wlr(), std::max(0, REPEATRATE), std::max(0, REPEATDELAY)); pKeyboard->repeatDelay = REPEATDELAY; pKeyboard->repeatRate = REPEATRATE; @@ -942,7 +927,7 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) { KEYMAP = xkb_keymap_new_from_names(CONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); } - wlr_keyboard_set_keymap(wlr_keyboard_from_input_device(pKeyboard->keyboard), KEYMAP); + wlr_keyboard_set_keymap(pKeyboard->wlr(), KEYMAP); pKeyboard->updateXKBTranslationState(); @@ -957,105 +942,87 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) { } if (wlrMods.locked != 0) - wlr_keyboard_notify_modifiers(wlr_keyboard_from_input_device(pKeyboard->keyboard), 0, 0, wlrMods.locked, 0); + wlr_keyboard_notify_modifiers(pKeyboard->wlr(), 0, 0, wlrMods.locked, 0); xkb_keymap_unref(KEYMAP); xkb_context_unref(CONTEXT); - const auto LAYOUTSTR = getActiveLayoutForKeyboard(pKeyboard); + const auto LAYOUTSTR = pKeyboard->getActiveLayout(); - g_pEventManager->postEvent(SHyprIPCEvent{"activelayout", pKeyboard->name + "," + LAYOUTSTR}); - EMIT_HOOK_EVENT("activeLayout", (std::vector{pKeyboard, (void*)&LAYOUTSTR})); + g_pEventManager->postEvent(SHyprIPCEvent{"activelayout", pKeyboard->hlName + "," + LAYOUTSTR}); + EMIT_HOOK_EVENT("activeLayout", (std::vector{pKeyboard, LAYOUTSTR})); - Debug::log(LOG, "Set the keyboard layout to {} and variant to {} for keyboard \"{}\"", pKeyboard->currentRules.layout, pKeyboard->currentRules.variant, - pKeyboard->keyboard->name); + Debug::log(LOG, "Set the keyboard layout to {} and variant to {} for keyboard \"{}\"", pKeyboard->currentRules.layout, pKeyboard->currentRules.variant, pKeyboard->hlName); } -void CInputManager::newVirtualMouse(SP mouse) { - const auto PMOUSE = &m_lMice.emplace_back(); +void CInputManager::newVirtualMouse(SP mouse) { + const auto PMOUSE = m_vPointers.emplace_back(CVirtualPointer::create(mouse)); - PMOUSE->mouse = &mouse->wlr()->base; - PMOUSE->virtualPointer = mouse; - PMOUSE->virt = true; - try { - PMOUSE->name = getNameForNewDevice(mouse->wlr()->base.name); - } catch (std::exception& e) { - Debug::log(ERR, "Mouse had no name???"); // logic error - } - - wlr_cursor_attach_input_device(g_pCompositor->m_sWLRCursor, &mouse->wlr()->base); - - PMOUSE->connected = true; - - setPointerConfigs(); - - PMOUSE->hyprListener_destroyMouse.initCallback(&mouse->wlr()->base.events.destroy, &Events::listener_destroyMouse, PMOUSE, "Mouse"); - - // TODO: this pointer pass sucks. - PMOUSE->listeners.destroyMouse = mouse->events.destroy.registerListener([this, PMOUSE](std::any data) { destroyMouse(PMOUSE->mouse); }); - - g_pCompositor->m_sSeat.mouse = PMOUSE; - - m_tmrLastCursorMovement.reset(); + setupMouse(PMOUSE); Debug::log(LOG, "New virtual mouse created, pointer WLR: {:x}", (uintptr_t)mouse->wlr()); } void CInputManager::newMouse(wlr_input_device* mouse) { - m_lMice.emplace_back(); - const auto PMOUSE = &m_lMice.back(); + const auto PMOUSE = m_vPointers.emplace_back(CMouse::create(wlr_pointer_from_input_device(mouse))); - PMOUSE->mouse = mouse; + setupMouse(PMOUSE); + + Debug::log(LOG, "New mouse created, pointer WLR: {:x}", (uintptr_t)mouse); +} + +void CInputManager::setupMouse(SP mauz) { try { - PMOUSE->name = getNameForNewDevice(mouse->name); + mauz->hlName = getNameForNewDevice(mauz->wlr()->base.name); } catch (std::exception& e) { Debug::log(ERR, "Mouse had no name???"); // logic error } - if (wlr_input_device_is_libinput(mouse)) { - const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(mouse); + if (wlr_input_device_is_libinput(&mauz->wlr()->base)) { + const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(&mauz->wlr()->base); Debug::log(LOG, "New mouse has libinput sens {:.2f} ({:.2f}) with accel profile {} ({})", libinput_device_config_accel_get_speed(LIBINPUTDEV), libinput_device_config_accel_get_default_speed(LIBINPUTDEV), (int)libinput_device_config_accel_get_profile(LIBINPUTDEV), (int)libinput_device_config_accel_get_default_profile(LIBINPUTDEV)); } - wlr_cursor_attach_input_device(g_pCompositor->m_sWLRCursor, mouse); + wlr_cursor_attach_input_device(g_pCompositor->m_sWLRCursor, &mauz->wlr()->base); - PMOUSE->connected = true; + mauz->connected = true; setPointerConfigs(); - PMOUSE->hyprListener_destroyMouse.initCallback(&mouse->events.destroy, &Events::listener_destroyMouse, PMOUSE, "Mouse"); + mauz->events.destroy.registerStaticListener( + [this](void* mouse, std::any data) { + const auto PMOUSE = (IPointer*)mouse; + destroyPointer(PMOUSE->self.lock()); + }, + mauz.get()); - g_pCompositor->m_sSeat.mouse = PMOUSE; + g_pCompositor->m_sSeat.mouse = mauz; m_tmrLastCursorMovement.reset(); - - Debug::log(LOG, "New mouse created, pointer WLR: {:x}", (uintptr_t)mouse); } void CInputManager::setPointerConfigs() { - for (auto& m : m_lMice) { - const auto PPOINTER = &m; - - auto devname = PPOINTER->name; + for (auto& m : m_vPointers) { + auto devname = m->hlName; const auto HASCONFIG = g_pConfigManager->deviceConfigExists(devname); if (HASCONFIG) { const auto ENABLED = g_pConfigManager->getDeviceInt(devname, "enabled"); - if (ENABLED && !m.connected) { - wlr_cursor_attach_input_device(g_pCompositor->m_sWLRCursor, m.mouse); - m.connected = true; - } else if (!ENABLED && m.connected) { - wlr_cursor_detach_input_device(g_pCompositor->m_sWLRCursor, m.mouse); - m.connected = false; + if (ENABLED && !m->connected) { + wlr_cursor_attach_input_device(g_pCompositor->m_sWLRCursor, &m->wlr()->base); + m->connected = true; + } else if (!ENABLED && m->connected) { + wlr_cursor_detach_input_device(g_pCompositor->m_sWLRCursor, &m->wlr()->base); + m->connected = false; } } - if (wlr_input_device_is_libinput(m.mouse)) { - const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(m.mouse); + if (wlr_input_device_is_libinput(&m->wlr()->base)) { + const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(&m->wlr()->base); double touchw = 0, touchh = 0; const auto ISTOUCHPAD = libinput_device_has_capability(LIBINPUTDEV, LIBINPUT_DEVICE_CAP_POINTER) && @@ -1184,73 +1151,50 @@ void CInputManager::setPointerConfigs() { libinput_device_config_scroll_set_button_lock(LIBINPUTDEV, SCROLLBUTTONLOCK == 0 ? LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_DISABLED : LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_ENABLED); - Debug::log(LOG, "Applied config to mouse {}, sens {:.2f}", m.name, LIBINPUTSENS); + Debug::log(LOG, "Applied config to mouse {}, sens {:.2f}", m->hlName, LIBINPUTSENS); } } } -void CInputManager::destroyKeyboard(SKeyboard* pKeyboard) { - pKeyboard->hyprListener_keyboardDestroy.removeCallback(); - pKeyboard->hyprListener_keyboardMod.removeCallback(); - pKeyboard->hyprListener_keyboardKey.removeCallback(); - - xkb_state_unref(pKeyboard->xkbTranslationState); +void CInputManager::destroyKeyboard(SP pKeyboard) { + if (pKeyboard->xkbTranslationState) + xkb_state_unref(pKeyboard->xkbTranslationState); pKeyboard->xkbTranslationState = nullptr; - m_lKeyboards.remove(*pKeyboard); + std::erase_if(m_vKeyboards, [pKeyboard](const auto& other) { return other == pKeyboard; }); - if (m_lKeyboards.size() > 0) { - m_pActiveKeyboard = &m_lKeyboards.back(); - m_pActiveKeyboard->active = true; - wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, wlr_keyboard_from_input_device(m_pActiveKeyboard->keyboard)); + if (m_vKeyboards.size() > 0) { + g_pCompositor->m_sSeat.keyboard = m_vKeyboards.back(); + g_pCompositor->m_sSeat.keyboard.lock()->active = true; + wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, g_pCompositor->m_sSeat.keyboard.lock()->wlr()); } else { - m_pActiveKeyboard = nullptr; + g_pCompositor->m_sSeat.keyboard.reset(); wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, nullptr); } } -void CInputManager::destroyMouse(wlr_input_device* mouse) { - for (auto& m : m_lMice) { - if (m.mouse == mouse) { - m_lMice.remove(m); - break; - } - } +void CInputManager::destroyPointer(SP mouse) { + std::erase_if(m_vPointers, [mouse](const auto& other) { return other == mouse; }); - g_pCompositor->m_sSeat.mouse = m_lMice.size() > 0 ? &m_lMice.front() : nullptr; + g_pCompositor->m_sSeat.mouse = m_vPointers.size() > 0 ? m_vPointers.front() : nullptr; - if (g_pCompositor->m_sSeat.mouse) + if (!g_pCompositor->m_sSeat.mouse.expired()) unconstrainMouse(); } -void CInputManager::updateKeyboardsLeds(wlr_input_device* pKeyboard) { - auto keyboard = wlr_keyboard_from_input_device(pKeyboard); - - if (keyboard->xkb_state == NULL) { - return; - } - - uint32_t leds = 0; - for (uint32_t i = 0; i < WLR_LED_COUNT; ++i) { - if (xkb_state_led_index_is_active(keyboard->xkb_state, keyboard->led_indexes[i])) - leds |= (1 << i); - } +void CInputManager::destroyTouchDevice(SP touch) { + Debug::log(LOG, "Touch device at {:x} removed", (uintptr_t)touch.get()); - for (auto& kb : m_lKeyboards) { - if ((kb.isVirtual && shouldIgnoreVirtualKeyboard(&kb)) || kb.keyboard == pKeyboard) - continue; - - wlr_keyboard_led_update(wlr_keyboard_from_input_device(kb.keyboard), leds); - } + std::erase_if(m_vTouches, [touch](const auto& other) { return other == touch; }); } -void CInputManager::onKeyboardKey(wlr_keyboard_key_event* e, SKeyboard* pKeyboard) { +void CInputManager::onKeyboardKey(std::any event, SP pKeyboard) { if (!pKeyboard->enabled) return; - const bool DISALLOWACTION = pKeyboard->isVirtual && shouldIgnoreVirtualKeyboard(pKeyboard); + const bool DISALLOWACTION = pKeyboard->isVirtual() && shouldIgnoreVirtualKeyboard(pKeyboard); - const auto EMAP = std::unordered_map{{"keyboard", pKeyboard}, {"event", e}}; + const auto EMAP = std::unordered_map{{"keyboard", pKeyboard}, {"event", event}}; EMIT_HOOK_EVENT_CANCELLABLE("keyPress", EMAP); static auto PDPMS = CConfigValue("misc:key_press_enables_dpms"); @@ -1259,7 +1203,9 @@ void CInputManager::onKeyboardKey(wlr_keyboard_key_event* e, SKeyboard* pKeyboar g_pKeybindManager->dpms("on"); } - bool passEvent = DISALLOWACTION || g_pKeybindManager->onKeyEvent(e, pKeyboard); + bool passEvent = DISALLOWACTION || g_pKeybindManager->onKeyEvent(event, pKeyboard); + + auto e = std::any_cast(event); PROTO::idle->onActivity(); @@ -1267,59 +1213,64 @@ void CInputManager::onKeyboardKey(wlr_keyboard_key_event* e, SKeyboard* pKeyboar const auto IME = m_sIMERelay.m_pIME.lock(); if (IME && IME->hasGrab() && !DISALLOWACTION) { - IME->setKeyboard(wlr_keyboard_from_input_device(pKeyboard->keyboard)); - IME->sendKey(e->time_msec, e->keycode, e->state); + IME->setKeyboard(pKeyboard->wlr()); + IME->sendKey(e.timeMs, e.keycode, e.state); } else { - wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, wlr_keyboard_from_input_device(pKeyboard->keyboard)); - wlr_seat_keyboard_notify_key(g_pCompositor->m_sSeat.seat, e->time_msec, e->keycode, e->state); + wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, pKeyboard->wlr()); + wlr_seat_keyboard_notify_key(g_pCompositor->m_sSeat.seat, e.timeMs, e.keycode, e.state); } - updateKeyboardsLeds(pKeyboard->keyboard); + for (auto& k : m_vKeyboards) { + k->updateLEDs(); + } } } -void CInputManager::onKeyboardMod(void* data, SKeyboard* pKeyboard) { +void CInputManager::onKeyboardMod(SP pKeyboard) { if (!pKeyboard->enabled) return; - const bool DISALLOWACTION = pKeyboard->isVirtual && shouldIgnoreVirtualKeyboard(pKeyboard); + const bool DISALLOWACTION = pKeyboard->isVirtual() && shouldIgnoreVirtualKeyboard(pKeyboard); const auto ALLMODS = accumulateModsFromAllKBs(); + const auto PWLRKB = pKeyboard->wlr(); - auto MODS = wlr_keyboard_from_input_device(pKeyboard->keyboard)->modifiers; + auto MODS = PWLRKB->modifiers; MODS.depressed = ALLMODS; const auto IME = m_sIMERelay.m_pIME.lock(); if (IME && IME->hasGrab() && !DISALLOWACTION) { - IME->setKeyboard(wlr_keyboard_from_input_device(pKeyboard->keyboard)); + IME->setKeyboard(PWLRKB); IME->sendMods(MODS.depressed, MODS.latched, MODS.locked, MODS.group); } else { - wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, wlr_keyboard_from_input_device(pKeyboard->keyboard)); + wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, PWLRKB); wlr_seat_keyboard_notify_modifiers(g_pCompositor->m_sSeat.seat, &MODS); } - updateKeyboardsLeds(pKeyboard->keyboard); - - const auto PWLRKB = wlr_keyboard_from_input_device(pKeyboard->keyboard); + for (auto& k : m_vKeyboards) { + k->updateLEDs(); + } if (PWLRKB->modifiers.group != pKeyboard->activeLayout) { pKeyboard->activeLayout = PWLRKB->modifiers.group; - const auto LAYOUT = getActiveLayoutForKeyboard(pKeyboard); + const auto LAYOUT = pKeyboard->getActiveLayout(); pKeyboard->updateXKBTranslationState(); - g_pEventManager->postEvent(SHyprIPCEvent{"activelayout", pKeyboard->name + "," + LAYOUT}); - EMIT_HOOK_EVENT("activeLayout", (std::vector{pKeyboard, (void*)&LAYOUT})); + g_pEventManager->postEvent(SHyprIPCEvent{"activelayout", pKeyboard->hlName + "," + LAYOUT}); + EMIT_HOOK_EVENT("activeLayout", (std::vector{pKeyboard, LAYOUT})); } } -bool CInputManager::shouldIgnoreVirtualKeyboard(SKeyboard* pKeyboard) { - if (!pKeyboard->isVirtual) +bool CInputManager::shouldIgnoreVirtualKeyboard(SP pKeyboard) { + if (!pKeyboard->isVirtual()) return false; - return !pKeyboard || (!m_sIMERelay.m_pIME.expired() && m_sIMERelay.m_pIME.lock()->grabClient() == pKeyboard->virtKeyboard.lock()->client()); + CVirtualKeyboard* vk = (CVirtualKeyboard*)pKeyboard.get(); + + return !pKeyboard || (!m_sIMERelay.m_pIME.expired() && m_sIMERelay.m_pIME.lock()->grabClient() == vk->getClient()); } void CInputManager::refocus() { @@ -1343,7 +1294,7 @@ void CInputManager::updateDragIcon() { } void CInputManager::unconstrainMouse() { - if (!g_pCompositor->m_sSeat.mouse) + if (g_pCompositor->m_sSeat.mouse.expired()) return; for (auto& c : m_vConstraints) { @@ -1378,11 +1329,11 @@ bool CInputManager::isConstrained() { void CInputManager::updateCapabilities() { uint32_t caps = 0; - if (!m_lKeyboards.empty()) + if (!m_vKeyboards.empty()) caps |= WL_SEAT_CAPABILITY_KEYBOARD; - if (!m_lMice.empty()) + if (!m_vPointers.empty()) caps |= WL_SEAT_CAPABILITY_POINTER; - if (!m_lTouchDevices.empty()) + if (!m_vTouches.empty()) caps |= WL_SEAT_CAPABILITY_TOUCH; if (!m_lTabletTools.empty()) caps |= WL_SEAT_CAPABILITY_POINTER; @@ -1395,54 +1346,34 @@ uint32_t CInputManager::accumulateModsFromAllKBs() { uint32_t finalMask = 0; - for (auto& kb : m_lKeyboards) { - if (kb.isVirtual && shouldIgnoreVirtualKeyboard(&kb)) + for (auto& kb : m_vKeyboards) { + if (kb->isVirtual() && shouldIgnoreVirtualKeyboard(kb)) continue; - if (!kb.enabled) + if (!kb->enabled) continue; - finalMask |= wlr_keyboard_get_modifiers(wlr_keyboard_from_input_device(kb.keyboard)); + finalMask |= wlr_keyboard_get_modifiers(kb->wlr()); } return finalMask; } -std::string CInputManager::getActiveLayoutForKeyboard(SKeyboard* pKeyboard) { - const auto WLRKB = wlr_keyboard_from_input_device(pKeyboard->keyboard); - const auto KEYMAP = WLRKB->keymap; - const auto STATE = WLRKB->xkb_state; - const auto LAYOUTSNUM = xkb_keymap_num_layouts(KEYMAP); - - for (uint32_t i = 0; i < LAYOUTSNUM; ++i) { - if (xkb_state_layout_index_is_active(STATE, i, XKB_STATE_LAYOUT_EFFECTIVE)) { - const auto LAYOUTNAME = xkb_keymap_layout_get_name(KEYMAP, i); - - if (LAYOUTNAME) - return std::string(LAYOUTNAME); - return "error"; - } - } - - return "none"; -} - void CInputManager::disableAllKeyboards(bool virt) { - for (auto& k : m_lKeyboards) { - if (k.isVirtual != virt) + for (auto& k : m_vKeyboards) { + if (k->isVirtual() != virt) continue; - k.active = false; + k->active = false; } } void CInputManager::newTouchDevice(wlr_input_device* pDevice) { - const auto PNEWDEV = &m_lTouchDevices.emplace_back(); - PNEWDEV->pWlrDevice = pDevice; + const auto PNEWDEV = m_vTouches.emplace_back(CTouchDevice::create(wlr_touch_from_input_device(pDevice))); try { - PNEWDEV->name = getNameForNewDevice(pDevice->name); + PNEWDEV->hlName = getNameForNewDevice(pDevice->name); } catch (std::exception& e) { Debug::log(ERR, "Touch Device had no name???"); // logic error } @@ -1450,32 +1381,36 @@ void CInputManager::newTouchDevice(wlr_input_device* pDevice) { setTouchDeviceConfigs(PNEWDEV); wlr_cursor_attach_input_device(g_pCompositor->m_sWLRCursor, pDevice); - Debug::log(LOG, "New touch device added at {:x}", (uintptr_t)PNEWDEV); + PNEWDEV->events.destroy.registerStaticListener( + [this](void* owner, std::any data) { + auto PDEV = ((ITouch*)owner)->self.lock(); + destroyTouchDevice(PDEV); + }, + PNEWDEV.get()); - PNEWDEV->hyprListener_destroy.initCallback( - &pDevice->events.destroy, [&](void* owner, void* data) { destroyTouchDevice((STouchDevice*)data); }, PNEWDEV, "TouchDevice"); + Debug::log(LOG, "New touch device added at {:x}", (uintptr_t)PNEWDEV.get()); } -void CInputManager::setTouchDeviceConfigs(STouchDevice* dev) { - auto setConfig = [&](STouchDevice* const PTOUCHDEV) -> void { - if (wlr_input_device_is_libinput(PTOUCHDEV->pWlrDevice)) { - const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(PTOUCHDEV->pWlrDevice); +void CInputManager::setTouchDeviceConfigs(SP dev) { + auto setConfig = [&](SP PTOUCHDEV) -> void { + if (wlr_input_device_is_libinput(&PTOUCHDEV->wlr()->base)) { + const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(&PTOUCHDEV->wlr()->base); - const auto ENABLED = g_pConfigManager->getDeviceInt(PTOUCHDEV->name, "enabled", "input:touchdevice:enabled"); + const auto ENABLED = g_pConfigManager->getDeviceInt(PTOUCHDEV->hlName, "enabled", "input:touchdevice:enabled"); const auto mode = ENABLED ? LIBINPUT_CONFIG_SEND_EVENTS_ENABLED : LIBINPUT_CONFIG_SEND_EVENTS_DISABLED; if (libinput_device_config_send_events_get_mode(LIBINPUTDEV) != mode) libinput_device_config_send_events_set_mode(LIBINPUTDEV, mode); - const int ROTATION = std::clamp(g_pConfigManager->getDeviceInt(PTOUCHDEV->name, "transform", "input:touchdevice:transform"), 0, 7); - Debug::log(LOG, "Setting calibration matrix for device {}", PTOUCHDEV->name); + const int ROTATION = std::clamp(g_pConfigManager->getDeviceInt(PTOUCHDEV->hlName, "transform", "input:touchdevice:transform"), 0, 7); + Debug::log(LOG, "Setting calibration matrix for device {}", PTOUCHDEV->hlName); if (libinput_device_config_calibration_has_matrix(LIBINPUTDEV)) libinput_device_config_calibration_set_matrix(LIBINPUTDEV, MATRICES[ROTATION]); - auto output = g_pConfigManager->getDeviceString(PTOUCHDEV->name, "output", "input:touchdevice:output"); + auto output = g_pConfigManager->getDeviceString(PTOUCHDEV->hlName, "output", "input:touchdevice:output"); bool bound = !output.empty() && output != STRVAL_EMPTY; const bool AUTODETECT = output == "[[Auto]]"; if (!bound && AUTODETECT) { - const auto DEFAULTOUTPUT = wlr_touch_from_input_device(PTOUCHDEV->pWlrDevice)->output_name; + const auto DEFAULTOUTPUT = PTOUCHDEV->wlr()->output_name; if (DEFAULTOUTPUT) { output = DEFAULTOUTPUT; bound = true; @@ -1484,10 +1419,10 @@ void CInputManager::setTouchDeviceConfigs(STouchDevice* dev) { PTOUCHDEV->boundOutput = bound ? output : ""; const auto PMONITOR = bound ? g_pCompositor->getMonitorFromName(output) : nullptr; if (PMONITOR) { - Debug::log(LOG, "Binding touch device {} to output {}", PTOUCHDEV->name, PMONITOR->szName); - wlr_cursor_map_input_to_output(g_pCompositor->m_sWLRCursor, PTOUCHDEV->pWlrDevice, PMONITOR->output); + Debug::log(LOG, "Binding touch device {} to output {}", PTOUCHDEV->hlName, PMONITOR->szName); + wlr_cursor_map_input_to_output(g_pCompositor->m_sWLRCursor, &PTOUCHDEV->wlr()->base, PMONITOR->output); } else if (bound) - Debug::log(ERR, "Failed to bind touch device {} to output '{}': monitor not found", PTOUCHDEV->name, output); + Debug::log(ERR, "Failed to bind touch device {} to output '{}': monitor not found", PTOUCHDEV->hlName, output); } }; @@ -1496,10 +1431,8 @@ void CInputManager::setTouchDeviceConfigs(STouchDevice* dev) { return; } - for (auto& m : m_lTouchDevices) { - const auto PTOUCHDEV = &m; - - setConfig(PTOUCHDEV); + for (auto& m : m_vTouches) { + setConfig(m); } } @@ -1546,12 +1479,6 @@ void CInputManager::setTabletConfigs() { } } -void CInputManager::destroyTouchDevice(STouchDevice* pDevice) { - Debug::log(LOG, "Touch device at {:x} removed", (uintptr_t)pDevice); - - m_lTouchDevices.remove(*pDevice); -} - void CInputManager::newSwitch(wlr_input_device* pDevice) { const auto PNEWDEV = &m_lSwitches.emplace_back(); PNEWDEV->pWlrDevice = pDevice; @@ -1623,16 +1550,16 @@ std::string CInputManager::getNameForNewDevice(std::string internalName) { auto proposedNewName = deviceNameToInternalString(internalName); int dupeno = 0; - while (std::find_if(m_lKeyboards.begin(), m_lKeyboards.end(), - [&](const SKeyboard& other) { return other.name == proposedNewName + (dupeno == 0 ? "" : ("-" + std::to_string(dupeno))); }) != m_lKeyboards.end()) + while (std::find_if(m_vKeyboards.begin(), m_vKeyboards.end(), + [&](const auto& other) { return other->hlName == proposedNewName + (dupeno == 0 ? "" : ("-" + std::to_string(dupeno))); }) != m_vKeyboards.end()) dupeno++; - while (std::find_if(m_lMice.begin(), m_lMice.end(), [&](const SMouse& other) { return other.name == proposedNewName + (dupeno == 0 ? "" : ("-" + std::to_string(dupeno))); }) != - m_lMice.end()) + while (std::find_if(m_vPointers.begin(), m_vPointers.end(), + [&](const auto& other) { return other->hlName == proposedNewName + (dupeno == 0 ? "" : ("-" + std::to_string(dupeno))); }) != m_vPointers.end()) dupeno++; - while (std::find_if(m_lTouchDevices.begin(), m_lTouchDevices.end(), - [&](const STouchDevice& other) { return other.name == proposedNewName + (dupeno == 0 ? "" : ("-" + std::to_string(dupeno))); }) != m_lTouchDevices.end()) + while (std::find_if(m_vTouches.begin(), m_vTouches.end(), + [&](const auto& other) { return other->hlName == proposedNewName + (dupeno == 0 ? "" : ("-" + std::to_string(dupeno))); }) != m_vTouches.end()) dupeno++; while (std::find_if(m_lTabletPads.begin(), m_lTabletPads.end(), diff --git a/src/managers/input/InputManager.hpp b/src/managers/input/InputManager.hpp index 6a3380880cf3..98032dd4f571 100644 --- a/src/managers/input/InputManager.hpp +++ b/src/managers/input/InputManager.hpp @@ -11,8 +11,11 @@ class CPointerConstraint; class CWindow; class CIdleInhibitor; -class CVirtualKeyboard; -class CVirtualPointer; +class CVirtualKeyboardV1Resource; +class CVirtualPointerV1Resource; +class IPointer; +class IKeyboard; +class ITouch; enum eClickBehaviorMode { CLICKMODE_DEFAULT = 0, @@ -75,23 +78,22 @@ class CInputManager { void onMouseWarp(wlr_pointer_motion_absolute_event*); void onMouseButton(wlr_pointer_button_event*); void onMouseWheel(wlr_pointer_axis_event*); - void onKeyboardKey(wlr_keyboard_key_event*, SKeyboard*); - void onKeyboardMod(void*, SKeyboard*); + void onKeyboardKey(std::any, SP); + void onKeyboardMod(SP); void newKeyboard(wlr_input_device*); - void newVirtualKeyboard(SP); + void newVirtualKeyboard(SP); void newMouse(wlr_input_device*); - void newVirtualMouse(SP); + void newVirtualMouse(SP); void newTouchDevice(wlr_input_device*); void newSwitch(wlr_input_device*); - void destroyTouchDevice(STouchDevice*); - void destroyKeyboard(SKeyboard*); - void destroyMouse(wlr_input_device*); + void destroyTouchDevice(SP); + void destroyKeyboard(SP); + void destroyPointer(SP); void destroySwitch(SSwitchDevice*); void unconstrainMouse(); bool isConstrained(); - std::string getActiveLayoutForKeyboard(SKeyboard*); Vector2D getMouseCoordsInternal(); void refocus(); @@ -100,7 +102,7 @@ class CInputManager { void setKeyboardLayout(); void setPointerConfigs(); - void setTouchDeviceConfigs(STouchDevice* dev = nullptr); + void setTouchDeviceConfigs(SP dev = nullptr); void setTabletConfigs(); void updateDragIcon(); @@ -122,21 +124,19 @@ class CInputManager { bool m_bWasDraggingWindow = false; // for refocus to be forced - PHLWINDOWREF m_pForcedFocus; + PHLWINDOWREF m_pForcedFocus; - SDrag m_sDrag; + SDrag m_sDrag; - std::list m_lKeyboards; - std::list m_lMice; + std::vector> m_vKeyboards; + std::vector> m_vPointers; + std::vector> m_vTouches; // tablets std::list m_lTablets; std::list m_lTabletTools; std::list m_lTabletPads; - // Touch devices - std::list m_lTouchDevices; - // Switches std::list m_lSwitches; @@ -159,19 +159,15 @@ class CInputManager { SSwipeGesture m_sActiveSwipe; - SKeyboard* m_pActiveKeyboard = nullptr; - CTimer m_tmrLastCursorMovement; CInputMethodRelay m_sIMERelay; - void updateKeyboardsLeds(wlr_input_device* pKeyboard); - // for shared mods uint32_t accumulateModsFromAllKBs(); // for virtual keyboards: whether we should respect them as normal ones - bool shouldIgnoreVirtualKeyboard(SKeyboard*); + bool shouldIgnoreVirtualKeyboard(SP); // for special cursors that we choose void setCursorImageUntilUnset(std::string); @@ -213,6 +209,9 @@ class CInputManager { eClickBehaviorMode m_ecbClickBehavior = CLICKMODE_DEFAULT; Vector2D m_vLastCursorPosFloored = Vector2D(); + void setupKeyboard(SP keeb); + void setupMouse(SP mauz); + void processMouseDownNormal(wlr_pointer_button_event* e); void processMouseDownKill(wlr_pointer_button_event* e); @@ -226,7 +225,7 @@ class CInputManager { STabletTool* ensureTabletToolPresent(wlr_tablet_tool*); - void applyConfigToKeyboard(SKeyboard*); + void applyConfigToKeyboard(SP); // this will be set after a refocus() wlr_surface* m_pFoundSurfaceToFocus = nullptr; diff --git a/src/managers/input/Touch.cpp b/src/managers/input/Touch.cpp index 91f4ada63947..8f6e2226ec8c 100644 --- a/src/managers/input/Touch.cpp +++ b/src/managers/input/Touch.cpp @@ -2,6 +2,7 @@ #include "../../Compositor.hpp" #include "../../config/ConfigValue.hpp" #include "../../protocols/IdleNotify.hpp" +#include "../../devices/ITouch.hpp" void CInputManager::onTouchDown(wlr_touch_down_event* e) { static auto PSWIPETOUCH = CConfigValue("gestures:workspace_swipe_touch"); @@ -15,10 +16,10 @@ void CInputManager::onTouchDown(wlr_touch_down_event* e) { auto PMONITOR = g_pCompositor->getMonitorFromName(e->touch->output_name ? e->touch->output_name : ""); - const auto PDEVIT = std::find_if(m_lTouchDevices.begin(), m_lTouchDevices.end(), [&](const STouchDevice& other) { return other.pWlrDevice == &e->touch->base; }); + const auto PDEVIT = std::find_if(m_vTouches.begin(), m_vTouches.end(), [&](const auto& other) { return other->wlr() == e->touch; }); - if (PDEVIT != m_lTouchDevices.end() && !PDEVIT->boundOutput.empty()) - PMONITOR = g_pCompositor->getMonitorFromName(PDEVIT->boundOutput); + if (PDEVIT != m_vTouches.end() && !(*PDEVIT)->boundOutput.empty()) + PMONITOR = g_pCompositor->getMonitorFromName((*PDEVIT)->boundOutput); PMONITOR = PMONITOR ? PMONITOR : g_pCompositor->m_pLastMonitor; diff --git a/src/protocols/VirtualKeyboard.cpp b/src/protocols/VirtualKeyboard.cpp index fa364a96b497..1cc76447189d 100644 --- a/src/protocols/VirtualKeyboard.cpp +++ b/src/protocols/VirtualKeyboard.cpp @@ -7,7 +7,7 @@ static const struct wlr_keyboard_impl virtualKeyboardImpl = { .name = "virtual-keyboard", }; -CVirtualKeyboard::CVirtualKeyboard(SP resource_) : resource(resource_) { +CVirtualKeyboardV1Resource::CVirtualKeyboardV1Resource(SP resource_) : resource(resource_) { if (!good()) return; @@ -84,20 +84,20 @@ CVirtualKeyboard::CVirtualKeyboard(SP resource_) : resour wlr_keyboard_init(&keyboard, &virtualKeyboardImpl, "CVirtualKeyboard"); } -CVirtualKeyboard::~CVirtualKeyboard() { +CVirtualKeyboardV1Resource::~CVirtualKeyboardV1Resource() { wlr_keyboard_finish(&keyboard); events.destroy.emit(); } -bool CVirtualKeyboard::good() { +bool CVirtualKeyboardV1Resource::good() { return resource->resource(); } -wlr_keyboard* CVirtualKeyboard::wlr() { +wlr_keyboard* CVirtualKeyboardV1Resource::wlr() { return &keyboard; } -wl_client* CVirtualKeyboard::client() { +wl_client* CVirtualKeyboardV1Resource::client() { return resource->client(); } @@ -116,13 +116,13 @@ void CVirtualKeyboardProtocol::onManagerResourceDestroy(wl_resource* res) { std::erase_if(m_vManagers, [&](const auto& other) { return other->resource() == res; }); } -void CVirtualKeyboardProtocol::destroyResource(CVirtualKeyboard* keeb) { +void CVirtualKeyboardProtocol::destroyResource(CVirtualKeyboardV1Resource* 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(std::make_shared(pMgr->client(), pMgr->version(), id))); + const auto RESOURCE = m_vKeyboards.emplace_back(std::make_shared(std::make_shared(pMgr->client(), pMgr->version(), id))); if (!RESOURCE->good()) { pMgr->noMemory(); diff --git a/src/protocols/VirtualKeyboard.hpp b/src/protocols/VirtualKeyboard.hpp index b922b0c5e39f..5ce3d7481868 100644 --- a/src/protocols/VirtualKeyboard.hpp +++ b/src/protocols/VirtualKeyboard.hpp @@ -7,10 +7,10 @@ #include "virtual-keyboard-unstable-v1.hpp" #include "../helpers/signal/Signal.hpp" -class CVirtualKeyboard { +class CVirtualKeyboardV1Resource { public: - CVirtualKeyboard(SP resource_); - ~CVirtualKeyboard(); + CVirtualKeyboardV1Resource(SP resource_); + ~CVirtualKeyboardV1Resource(); struct { CSignal destroy; @@ -39,14 +39,14 @@ class CVirtualKeyboardProtocol : public IWaylandProtocol { private: void onManagerResourceDestroy(wl_resource* res); - void destroyResource(CVirtualKeyboard* keeb); + void destroyResource(CVirtualKeyboardV1Resource* keeb); void onCreateKeeb(CZwpVirtualKeyboardManagerV1* pMgr, wl_resource* seat, uint32_t id); // std::vector> m_vManagers; - std::vector> m_vKeyboards; + std::vector> m_vKeyboards; - friend class CVirtualKeyboard; + friend class CVirtualKeyboardV1Resource; }; namespace PROTO { diff --git a/src/protocols/VirtualPointer.cpp b/src/protocols/VirtualPointer.cpp index 287e7bad2bdd..cad8af6751a6 100644 --- a/src/protocols/VirtualPointer.cpp +++ b/src/protocols/VirtualPointer.cpp @@ -6,7 +6,7 @@ static const wlr_pointer_impl pointerImpl = { .name = "virtual-pointer-v1", }; -CVirtualPointer::CVirtualPointer(SP resource_) : resource(resource_) { +CVirtualPointerV1Resource::CVirtualPointerV1Resource(SP resource_) : resource(resource_) { if (!good()) return; @@ -19,7 +19,7 @@ CVirtualPointer::CVirtualPointer(SP resource_) : resource PROTO::virtualPointer->destroyResource(this); }); - wlr_pointer_init(&pointer, &pointerImpl, "CVirtualPointer"); + wlr_pointer_init(&pointer, &pointerImpl, "CVirtualPointerV1Resource"); resource->setMotion([this](CZwlrVirtualPointerV1* r, uint32_t timeMs, wl_fixed_t dx, wl_fixed_t dy) { wlr_pointer_motion_event event = { @@ -108,20 +108,20 @@ CVirtualPointer::CVirtualPointer(SP resource_) : resource }); } -CVirtualPointer::~CVirtualPointer() { +CVirtualPointerV1Resource::~CVirtualPointerV1Resource() { wlr_pointer_finish(&pointer); events.destroy.emit(); } -bool CVirtualPointer::good() { +bool CVirtualPointerV1Resource::good() { return resource->resource(); } -wlr_pointer* CVirtualPointer::wlr() { +wlr_pointer* CVirtualPointerV1Resource::wlr() { return &pointer; } -wl_client* CVirtualPointer::client() { +wl_client* CVirtualPointerV1Resource::client() { return resource->client(); } @@ -145,13 +145,13 @@ void CVirtualPointerProtocol::onManagerResourceDestroy(wl_resource* res) { std::erase_if(m_vManagers, [&](const auto& other) { return other->resource() == res; }); } -void CVirtualPointerProtocol::destroyResource(CVirtualPointer* pointer) { +void CVirtualPointerProtocol::destroyResource(CVirtualPointerV1Resource* pointer) { std::erase_if(m_vPointers, [&](const auto& other) { return other.get() == pointer; }); } void CVirtualPointerProtocol::onCreatePointer(CZwlrVirtualPointerManagerV1* pMgr, wl_resource* seat, uint32_t id) { - const auto RESOURCE = m_vPointers.emplace_back(std::make_shared(std::make_shared(pMgr->client(), pMgr->version(), id))); + const auto RESOURCE = m_vPointers.emplace_back(std::make_shared(std::make_shared(pMgr->client(), pMgr->version(), id))); if (!RESOURCE->good()) { pMgr->noMemory(); diff --git a/src/protocols/VirtualPointer.hpp b/src/protocols/VirtualPointer.hpp index 4528b49190d6..59a7e7395e55 100644 --- a/src/protocols/VirtualPointer.hpp +++ b/src/protocols/VirtualPointer.hpp @@ -8,10 +8,10 @@ #include "wlr-virtual-pointer-unstable-v1.hpp" #include "../helpers/signal/Signal.hpp" -class CVirtualPointer { +class CVirtualPointerV1Resource { public: - CVirtualPointer(SP resource_); - ~CVirtualPointer(); + CVirtualPointerV1Resource(SP resource_); + ~CVirtualPointerV1Resource(); struct { CSignal destroy; @@ -37,19 +37,19 @@ class CVirtualPointerProtocol : public IWaylandProtocol { virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); struct { - CSignal newPointer; // SP + CSignal newPointer; // SP } events; private: void onManagerResourceDestroy(wl_resource* res); - void destroyResource(CVirtualPointer* pointer); + void destroyResource(CVirtualPointerV1Resource* pointer); void onCreatePointer(CZwlrVirtualPointerManagerV1* pMgr, wl_resource* seat, uint32_t id); // std::vector> m_vManagers; - std::vector> m_vPointers; + std::vector> m_vPointers; - friend class CVirtualPointer; + friend class CVirtualPointerV1Resource; }; namespace PROTO {