From 30e4b404f2a30230f57c946b655c2365b3bf8e3d Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 21 Apr 2024 01:47:38 +0100 Subject: [PATCH] cursor-shape: move to new impl --- CMakeLists.txt | 2 +- protocols/meson.build | 2 +- src/Compositor.cpp | 10 +-- src/Compositor.hpp | 1 - src/events/Events.hpp | 3 - src/events/Misc.cpp | 6 -- src/includes.hpp | 1 - src/managers/ProtocolManager.cpp | 9 ++- src/managers/input/InputManager.cpp | 40 +++++++----- src/managers/input/InputManager.hpp | 8 ++- src/protocols/CursorShape.cpp | 98 +++++++++++++++++++++++++++++ src/protocols/CursorShape.hpp | 42 +++++++++++++ 12 files changed, 181 insertions(+), 41 deletions(-) create mode 100644 src/protocols/CursorShape.cpp create mode 100644 src/protocols/CursorShape.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 5b88440b..e134f9c6 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -261,10 +261,10 @@ protocol("subprojects/hyprland-protocols/protocols/hyprland-toplevel-export-v1.x protocol("stable/xdg-shell/xdg-shell.xml" "xdg-shell" false) protocol("unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml" "linux-dmabuf-unstable-v1" false) protocol("unstable/text-input/text-input-unstable-v1.xml" "text-input-unstable-v1" false) -protocol("staging/cursor-shape/cursor-shape-v1.xml" "cursor-shape-v1" false) protocolNew("staging/tearing-control/tearing-control-v1.xml" "tearing-control-v1" false) protocolNew("staging/fractional-scale/fractional-scale-v1.xml" "fractional-scale-v1" false) protocolNew("unstable/xdg-output/xdg-output-unstable-v1.xml" "xdg-output-unstable-v1" false) +protocolNew("staging/cursor-shape/cursor-shape-v1.xml" "cursor-shape-v1" false) # tools add_subdirectory(hyprctl) diff --git a/protocols/meson.build b/protocols/meson.build index 150ea55f..009643f9 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -27,7 +27,6 @@ protocols = [ [wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'], [wl_protocol_dir, 'unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml'], [wl_protocol_dir, 'unstable/text-input/text-input-unstable-v1.xml'], - [wl_protocol_dir, 'staging/cursor-shape/cursor-shape-v1.xml'], ['wlr-foreign-toplevel-management-unstable-v1.xml'], ['wlr-layer-shell-unstable-v1.xml'], ['wlr-output-power-management-unstable-v1.xml'], @@ -43,6 +42,7 @@ new_protocols = [ [wl_protocol_dir, 'staging/tearing-control/tearing-control-v1.xml'], [wl_protocol_dir, 'staging/fractional-scale/fractional-scale-v1.xml'], [wl_protocol_dir, 'unstable/xdg-output/xdg-output-unstable-v1.xml'], + [wl_protocol_dir, 'staging/cursor-shape/cursor-shape-v1.xml'], ] wl_protos_src = [] diff --git a/src/Compositor.cpp b/src/Compositor.cpp index edf7c25d..157a70d6 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -252,8 +252,6 @@ void CCompositor::initServer() { m_sWLRSessionLockMgr = wlr_session_lock_manager_v1_create(m_sWLDisplay); - m_sWLRCursorShapeMgr = wlr_cursor_shape_manager_v1_create(m_sWLDisplay, 1); - if (!m_sWLRHeadlessBackend) { Debug::log(CRIT, "Couldn't create the headless backend"); throwError("wlr_headless_backend_create() failed!"); @@ -309,7 +307,6 @@ void CCompositor::initAllSignals() { addWLSignal(&m_sWLRActivation->events.request_activate, &Events::listen_activateXDG, m_sWLRActivation, "ActivationV1"); addWLSignal(&m_sWLRSessionLockMgr->events.new_lock, &Events::listen_newSessionLock, m_sWLRSessionLockMgr, "SessionLockMgr"); addWLSignal(&m_sWLRGammaCtrlMgr->events.set_gamma, &Events::listen_setGamma, m_sWLRGammaCtrlMgr, "GammaCtrlMgr"); - addWLSignal(&m_sWLRCursorShapeMgr->events.request_set_shape, &Events::listen_setCursorShape, m_sWLRCursorShapeMgr, "CursorShapeMgr"); addWLSignal(&m_sWLRKbShInhibitMgr->events.new_inhibitor, &Events::listen_newShortcutInhibitor, m_sWLRKbShInhibitMgr, "ShortcutInhibitMgr"); if (m_sWRLDRMLeaseMgr) @@ -362,7 +359,6 @@ void CCompositor::removeAllSignals() { removeWLSignal(&Events::listen_activateXDG); removeWLSignal(&Events::listen_newSessionLock); removeWLSignal(&Events::listen_setGamma); - removeWLSignal(&Events::listen_setCursorShape); removeWLSignal(&Events::listen_newShortcutInhibitor); if (m_sWRLDRMLeaseMgr) @@ -455,6 +451,9 @@ void CCompositor::initManagers(eManagersInitStage stage) { Debug::log(LOG, "Creating the HookSystem!"); g_pHookSystem = std::make_unique(); + Debug::log(LOG, "Creating the ProtocolManager!"); + g_pProtocolManager = std::make_unique(); + Debug::log(LOG, "Creating the KeybindManager!"); g_pKeybindManager = std::make_unique(); @@ -492,9 +491,6 @@ void CCompositor::initManagers(eManagersInitStage stage) { Debug::log(LOG, "Creating the XWaylandManager!"); g_pXWaylandManager = std::make_unique(); - Debug::log(LOG, "Creating the ProtocolManager!"); - g_pProtocolManager = std::make_unique(); - Debug::log(LOG, "Creating the SessionLockManager!"); g_pSessionLockManager = std::make_unique(); diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 9244c673..8cca11c2 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -81,7 +81,6 @@ class CCompositor { wlr_backend* m_sWLRHeadlessBackend; wlr_session_lock_manager_v1* m_sWLRSessionLockMgr; wlr_gamma_control_manager_v1* m_sWLRGammaCtrlMgr; - wlr_cursor_shape_manager_v1* m_sWLRCursorShapeMgr; // ------------------------------------------------- // std::string m_szWLDisplaySocket = ""; diff --git a/src/events/Events.hpp b/src/events/Events.hpp index 4c4503ad..445b884c 100644 --- a/src/events/Events.hpp +++ b/src/events/Events.hpp @@ -141,9 +141,6 @@ namespace Events { // Gamma control LISTENER(setGamma); - // Cursor shape - LISTENER(setCursorShape); - // Shortcut inhibitor LISTENER(newShortcutInhibitor); }; diff --git a/src/events/Misc.cpp b/src/events/Misc.cpp index 53bd6f9f..3952920a 100644 --- a/src/events/Misc.cpp +++ b/src/events/Misc.cpp @@ -239,12 +239,6 @@ void Events::listener_setGamma(wl_listener* listener, void* data) { g_pCompositor->scheduleFrameForMonitor(PMONITOR); } -void Events::listener_setCursorShape(wl_listener* listener, void* data) { - const auto E = (wlr_cursor_shape_manager_v1_request_set_shape_event*)data; - - g_pInputManager->processMouseRequest(E); -} - void Events::listener_newShortcutInhibitor(wl_listener* listener, void* data) { const auto INHIBITOR = (wlr_keyboard_shortcuts_inhibitor_v1*)data; diff --git a/src/includes.hpp b/src/includes.hpp index c43c2eaf..23e96425 100644 --- a/src/includes.hpp +++ b/src/includes.hpp @@ -102,7 +102,6 @@ extern "C" { #include #include #include -#include #include #include #include diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index 873d1a17..67b3bdeb 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -3,16 +3,19 @@ #include "../protocols/TearingControl.hpp" #include "../protocols/FractionalScale.hpp" #include "../protocols/XDGOutput.hpp" +#include "../protocols/CursorShape.hpp" #include "tearing-control-v1.hpp" #include "fractional-scale-v1.hpp" #include "xdg-output-unstable-v1.hpp" +#include "cursor-shape-v1.hpp" CProtocolManager::CProtocolManager() { - PROTO::tearing = std::make_unique(&wp_tearing_control_manager_v1_interface, 1, "TearingControl"); - PROTO::fractional = std::make_unique(&wp_fractional_scale_manager_v1_interface, 1, "FractionalScale"); - PROTO::xdgOutput = std::make_unique(&zxdg_output_manager_v1_interface, 3, "XDGOutput"); + PROTO::tearing = std::make_unique(&wp_tearing_control_manager_v1_interface, 1, "TearingControl"); + PROTO::fractional = std::make_unique(&wp_fractional_scale_manager_v1_interface, 1, "FractionalScale"); + PROTO::xdgOutput = std::make_unique(&zxdg_output_manager_v1_interface, 3, "XDGOutput"); + PROTO::cursorShape = std::make_unique(&wp_cursor_shape_manager_v1_interface, 1, "CursorShape"); // Old protocol implementations. // TODO: rewrite them to use hyprwayland-scanner. diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 60e4270d..4a7fc11a 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -4,6 +4,29 @@ #include #include "../../config/ConfigValue.hpp" #include "../../desktop/Window.hpp" +#include "../../protocols/CursorShape.hpp" + +CInputManager::CInputManager() { + m_sListeners.setCursorShape = PROTO::cursorShape->events.setShape.registerListener([this](std::any data) { + if (!cursorImageUnlocked()) + return; + + auto event = std::any_cast(data); + + if (wl_resource_get_client(event.pMgr->resource()) != g_pCompositor->m_sSeat.seat->pointer_state.focused_client->client) + return; + + Debug::log(LOG, "cursorImage request: shape {} -> {}", (uint32_t)event.shape, event.shapeName); + + m_sCursorSurfaceInfo.wlSurface.unassign(); + m_sCursorSurfaceInfo.vHotspot = {}; + m_sCursorSurfaceInfo.name = event.shapeName; + m_sCursorSurfaceInfo.hidden = false; + + m_sCursorSurfaceInfo.inUse = true; + g_pHyprRenderer->setCursorFromName(m_sCursorSurfaceInfo.name); + }); +} CInputManager::~CInputManager() { m_vConstraints.clear(); @@ -509,23 +532,6 @@ void CInputManager::processMouseRequest(wlr_seat_pointer_request_set_cursor_even } } -void CInputManager::processMouseRequest(wlr_cursor_shape_manager_v1_request_set_shape_event* e) { - if (!cursorImageUnlocked()) - return; - - Debug::log(LOG, "cursorImage request: shape {}", (uint32_t)e->shape); - - if (e->seat_client == g_pCompositor->m_sSeat.seat->pointer_state.focused_client) { - m_sCursorSurfaceInfo.wlSurface.unassign(); - m_sCursorSurfaceInfo.vHotspot = {}; - m_sCursorSurfaceInfo.name = wlr_cursor_shape_v1_name(e->shape); - m_sCursorSurfaceInfo.hidden = false; - - m_sCursorSurfaceInfo.inUse = true; - g_pHyprRenderer->setCursorFromName(m_sCursorSurfaceInfo.name); - } -} - void CInputManager::restoreCursorIconToApp() { if (m_sCursorSurfaceInfo.inUse) return; diff --git a/src/managers/input/InputManager.hpp b/src/managers/input/InputManager.hpp index f1c322ca..dd8f5c63 100644 --- a/src/managers/input/InputManager.hpp +++ b/src/managers/input/InputManager.hpp @@ -5,6 +5,7 @@ #include "../../helpers/WLClasses.hpp" #include "../../helpers/Timer.hpp" #include "InputMethodRelay.hpp" +#include "../../helpers/signal/Listener.hpp" class CConstraint; class CWindow; @@ -63,6 +64,7 @@ class CKeybindManager; class CInputManager { public: + CInputManager(); ~CInputManager(); void onMouseMoved(wlr_pointer_motion_event*); @@ -102,7 +104,6 @@ class CInputManager { void setClickMode(eClickBehaviorMode); eClickBehaviorMode getClickMode(); void processMouseRequest(wlr_seat_pointer_request_set_cursor_event* e); - void processMouseRequest(wlr_cursor_shape_manager_v1_request_set_shape_event* e); void onTouchDown(wlr_touch_down_event*); void onTouchUp(wlr_touch_up_event*); @@ -197,6 +198,11 @@ class CInputManager { bool m_bEmptyFocusCursorSet = false; private: + // Listeners + struct { + CHyprSignalListener setCursorShape; + } m_sListeners; + bool m_bCursorImageOverridden = false; eBorderIconDirection m_eBorderIconDirection = BORDERICON_NONE; diff --git a/src/protocols/CursorShape.cpp b/src/protocols/CursorShape.cpp new file mode 100644 index 00000000..da27dbda --- /dev/null +++ b/src/protocols/CursorShape.cpp @@ -0,0 +1,98 @@ +#include "CursorShape.hpp" + +// clang-format off +constexpr const char* SHAPE_NAMES[] = { + "invalid", + "default", + "context_menu", + "help", + "pointer", + "progress", + "wait", + "cell", + "crosshair", + "text", + "vertical_text", + "alias", + "copy", + "move", + "no_drop", + "not_allowed", + "grab", + "grabbing", + "e_resize", + "n_resize", + "ne_resize", + "nw_resize", + "s_resize", + "se_resize", + "sw_resize", + "w_resize", + "ew_resize", + "ns_resize", + "nesw_resize", + "nwse_resize", + "col_resize", + "row_resize", + "all_scroll", + "zoom_in", + "zoom_out", +}; +// clang-format on + +CCursorShapeProtocol::CCursorShapeProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { + ; +} + +void CCursorShapeProtocol::onManagerResourceDestroy(wl_resource* res) { + std::erase_if(m_vManagers, [&](const auto& other) { return other->resource() == res; }); +} + +void CCursorShapeProtocol::onDeviceResourceDestroy(wl_resource* res) { + m_mDevices.erase(res); +} + +void CCursorShapeProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { + const auto RESOURCE = m_vManagers.emplace_back(std::make_unique(client, ver, id)).get(); + RESOURCE->setOnDestroy([this](CWpCursorShapeManagerV1* p) { this->onManagerResourceDestroy(p->resource()); }); + + RESOURCE->setDestroy([this](CWpCursorShapeManagerV1* pMgr) { this->onManagerResourceDestroy(pMgr->resource()); }); + RESOURCE->setGetPointer([this](CWpCursorShapeManagerV1* pMgr, uint32_t id, wl_resource* pointer) { this->onGetPointer(pMgr, id, pointer); }); + RESOURCE->setGetTabletToolV2([this](CWpCursorShapeManagerV1* pMgr, uint32_t id, wl_resource* tablet) { this->onGetTabletToolV2(pMgr, id, tablet); }); +} + +void CCursorShapeProtocol::onGetPointer(CWpCursorShapeManagerV1* pMgr, uint32_t id, wl_resource* pointer) { + createCursorShapeDevice(pMgr, id, pointer); +} + +void CCursorShapeProtocol::onGetTabletToolV2(CWpCursorShapeManagerV1* pMgr, uint32_t id, wl_resource* tablet) { + createCursorShapeDevice(pMgr, id, tablet); +} + +void CCursorShapeProtocol::createCursorShapeDevice(CWpCursorShapeManagerV1* pMgr, uint32_t id, wl_resource* resource) { + if (m_mDevices.contains(resource)) { + wl_resource_post_error(resource, 0, "Device already exists"); + return; + } + + const auto CLIENT = wl_resource_get_client(pMgr->resource()); + const auto RESOURCE = m_mDevices.emplace(resource, std::make_shared(CLIENT, wl_resource_get_version(pMgr->resource()), id)).first->second.get(); + RESOURCE->setOnDestroy([this](CWpCursorShapeDeviceV1* p) { this->onDeviceResourceDestroy(p->resource()); }); + + RESOURCE->setDestroy([this](CWpCursorShapeDeviceV1* p) { this->onDeviceResourceDestroy(p->resource()); }); + RESOURCE->setSetShape([this](CWpCursorShapeDeviceV1* p, uint32_t serial, wpCursorShapeDeviceV1Shape shape) { this->onSetShape(p, serial, shape); }); +} + +void CCursorShapeProtocol::onSetShape(CWpCursorShapeDeviceV1* pMgr, uint32_t serial, wpCursorShapeDeviceV1Shape shape) { + if ((uint32_t)shape == 0 || (uint32_t)shape > sizeof(SHAPE_NAMES)) { + wl_resource_post_error(pMgr->resource(), ERROR_INVALID_SHAPE, "The shape is invalid"); + return; + } + + SSetShapeEvent event; + event.pMgr = pMgr; + event.shape = shape; + event.shapeName = SHAPE_NAMES[shape]; + + events.setShape.emit(event); +} \ No newline at end of file diff --git a/src/protocols/CursorShape.hpp b/src/protocols/CursorShape.hpp new file mode 100644 index 00000000..f410bf5b --- /dev/null +++ b/src/protocols/CursorShape.hpp @@ -0,0 +1,42 @@ +#pragma once + +#include +#include +#include "WaylandProtocol.hpp" +#include "../helpers/signal/Signal.hpp" +#include "cursor-shape-v1.hpp" + +class CCursorShapeProtocol : public IWaylandProtocol { + public: + CCursorShapeProtocol(const wl_interface* iface, const int& ver, const std::string& name); + + virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); + + void onManagerResourceDestroy(wl_resource* res); + void onDeviceResourceDestroy(wl_resource* res); + + void onGetPointer(CWpCursorShapeManagerV1* pMgr, uint32_t id, wl_resource* pointer); + void onGetTabletToolV2(CWpCursorShapeManagerV1* pMgr, uint32_t id, wl_resource* tablet); + + void onSetShape(CWpCursorShapeDeviceV1* pMgr, uint32_t serial, wpCursorShapeDeviceV1Shape shape); + + struct SSetShapeEvent { + CWpCursorShapeDeviceV1* pMgr = nullptr; + wpCursorShapeDeviceV1Shape shape; + std::string shapeName; + }; + + struct { + CSignal setShape; + } events; + + private: + void createCursorShapeDevice(CWpCursorShapeManagerV1* pMgr, uint32_t id, wl_resource* resource); + + std::unordered_map> m_mDevices; + std::vector> m_vManagers; +}; + +namespace PROTO { + inline UP cursorShape; +}; \ No newline at end of file