#pragma once #include "../devices/IPointer.hpp" #include "../devices/ITouch.hpp" #include "../devices/Tablet.hpp" #include "../helpers/math/Math.hpp" #include "../helpers/math/Math.hpp" #include "../desktop/WLSurface.hpp" #include "../helpers/sync/SyncTimeline.hpp" #include 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 pointer); void attachTouch(SP touch); void attachTablet(SP tablet); void detachPointer(SP pointer); void detachTouch(SP touch); void detachTablet(SP tablet); // only clamps to the layout. void warpTo(const Vector2D& logical); void move(const Vector2D& deltaLogical); void warpAbsolute(Vector2D abs, SP dev); void setCursorBuffer(SP buf, const Vector2D& hotspot, const float& scale); void setCursorSurface(SP 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 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 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 pointer; }; std::vector> pointerListeners; struct STouchListener { CHyprSignalListener destroy; CHyprSignalListener down; CHyprSignalListener up; CHyprSignalListener motion; CHyprSignalListener cancel; CHyprSignalListener frame; WP touch; }; std::vector> touchListeners; struct STabletListener { CHyprSignalListener destroy; CHyprSignalListener axis; CHyprSignalListener proximity; CHyprSignalListener tip; CHyprSignalListener button; WP tablet; }; std::vector> tabletListeners; struct { std::vector monitorBoxes; } currentMonitorLayout; struct { SP pBuffer; SP bufferTex; WP surface; Vector2D hotspot; Vector2D size; float scale = 1.F; CHyprSignalListener destroySurface; CHyprSignalListener commitSurface; SP waitTimeline = nullptr; uint64_t waitPoint = 0; } 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(PHLMONITOR m) : monitor(m) {} ~SMonitorPointerState() {} PHLMONITORREF monitor; int softwareLocks = 0; bool hardwareFailed = false; CBox box; // logical bool entered = false; bool hwApplied = false; bool cursorRendered = false; SP cursorFrontBuffer; }; std::vector> monitorStates; SP stateFor(PHLMONITOR mon); bool attemptHardwareCursor(SP state); SP renderHWCursorBuffer(SP state, SP texture); bool setHWCursorBuffer(SP state, SP buf); struct { SP monitorAdded; SP monitorPreRender; } hooks; }; inline UP g_pPointerManager;