#pragma once #include "../devices/IPointer.hpp" #include "../devices/ITouch.hpp" #include "../devices/Tablet.hpp" #include "../helpers/math/Math.hpp" #include "../desktop/WLSurface.hpp" #include "../helpers/sync/SyncTimeline.hpp" #include <tuple> class CMonitor; class IHID; class CTexture; AQUAMARINE_FORWARD(IBuffer); /* The naming here is a bit confusing. CPointerManager manages the _position_ and _displaying_ of the cursor, but the CCursorManager _only_ manages the actual image (texture) and size of the cursor. */ class CPointerManager { public: CPointerManager(); void attachPointer(SP<IPointer> pointer); void attachTouch(SP<ITouch> touch); void attachTablet(SP<CTablet> tablet); void detachPointer(SP<IPointer> pointer); void detachTouch(SP<ITouch> touch); void detachTablet(SP<CTablet> tablet); // only clamps to the layout. void warpTo(const Vector2D& logical); void move(const Vector2D& deltaLogical); void warpAbsolute(Vector2D abs, SP<IHID> dev); void setCursorBuffer(SP<Aquamarine::IBuffer> buf, const Vector2D& hotspot, const float& scale); void setCursorSurface(SP<CWLSurface> buf, const Vector2D& hotspot); void resetCursorImage(bool apply = true); void lockSoftwareForMonitor(PHLMONITOR pMonitor); void unlockSoftwareForMonitor(PHLMONITOR pMonitor); void lockSoftwareAll(); void unlockSoftwareAll(); bool softwareLockedFor(PHLMONITOR pMonitor); void renderSoftwareCursorsFor(PHLMONITOR pMonitor, timespec* now, CRegion& damage /* logical */, std::optional<Vector2D> overridePos = {} /* monitor-local */); // this is needed e.g. during screensharing where // the software cursors aren't locked during the cursor move, but they // are rendered later. void damageCursor(PHLMONITOR pMonitor); // Vector2D position(); Vector2D cursorSizeLogical(); void storeMovement(uint64_t time, const Vector2D& delta, const Vector2D& deltaUnaccel); void setStoredMovement(uint64_t time, const Vector2D& delta, const Vector2D& deltaUnaccel); void sendStoredMovement(); void recheckEnteredOutputs(); private: void recheckPointerPosition(); void onMonitorLayoutChange(); void onMonitorDisconnect(); void updateCursorBackend(); void onCursorMoved(); bool hasCursor(); void damageIfSoftware(); // closest valid point to a given one Vector2D closestValid(const Vector2D& pos); // returns the thing in device coordinates. Is NOT offset by the hotspot, relies on set_cursor with hotspot. Vector2D getCursorPosForMonitor(PHLMONITOR pMonitor); // returns the thing in logical coordinates of the monitor CBox getCursorBoxLogicalForMonitor(PHLMONITOR pMonitor); // returns the thing in global coords CBox getCursorBoxGlobal(); Vector2D transformedHotspot(PHLMONITOR pMonitor); SP<CTexture> getCurrentCursorTexture(); struct SPointerListener { CHyprSignalListener destroy; CHyprSignalListener motion; CHyprSignalListener motionAbsolute; CHyprSignalListener button; CHyprSignalListener axis; CHyprSignalListener frame; CHyprSignalListener swipeBegin; CHyprSignalListener swipeEnd; CHyprSignalListener swipeUpdate; CHyprSignalListener pinchBegin; CHyprSignalListener pinchEnd; CHyprSignalListener pinchUpdate; CHyprSignalListener holdBegin; CHyprSignalListener holdEnd; WP<IPointer> pointer; }; std::vector<SP<SPointerListener>> pointerListeners; struct STouchListener { CHyprSignalListener destroy; CHyprSignalListener down; CHyprSignalListener up; CHyprSignalListener motion; CHyprSignalListener cancel; CHyprSignalListener frame; WP<ITouch> touch; }; std::vector<SP<STouchListener>> touchListeners; struct STabletListener { CHyprSignalListener destroy; CHyprSignalListener axis; CHyprSignalListener proximity; CHyprSignalListener tip; CHyprSignalListener button; WP<CTablet> tablet; }; std::vector<SP<STabletListener>> tabletListeners; struct { std::vector<CBox> monitorBoxes; } currentMonitorLayout; struct { SP<Aquamarine::IBuffer> pBuffer; SP<CTexture> bufferTex; WP<CWLSurface> surface; Vector2D hotspot; Vector2D size; float scale = 1.F; CHyprSignalListener destroySurface; CHyprSignalListener commitSurface; } currentCursorImage; // TODO: support various sizes per-output so we can have pixel-perfect cursors Vector2D pointerPos = {0, 0}; uint64_t storedTime = 0; Vector2D storedDelta = {0, 0}; Vector2D storedUnaccel = {0, 0}; struct SMonitorPointerState { SMonitorPointerState(const PHLMONITOR& m) : monitor(m) {} ~SMonitorPointerState() = default; PHLMONITORREF monitor; int softwareLocks = 0; bool hardwareFailed = false; CBox box; // logical bool entered = false; bool hwApplied = false; bool cursorRendered = false; SP<Aquamarine::IBuffer> cursorFrontBuffer; }; std::vector<SP<SMonitorPointerState>> monitorStates; SP<SMonitorPointerState> stateFor(PHLMONITOR mon); bool attemptHardwareCursor(SP<SMonitorPointerState> state); SP<Aquamarine::IBuffer> renderHWCursorBuffer(SP<SMonitorPointerState> state, SP<CTexture> texture); bool setHWCursorBuffer(SP<SMonitorPointerState> state, SP<Aquamarine::IBuffer> buf); struct { SP<HOOK_CALLBACK_FN> monitorAdded; SP<HOOK_CALLBACK_FN> monitorPreRender; } hooks; }; inline UP<CPointerManager> g_pPointerManager;