#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 class CMonitor; struct wlr_input_device; class IHID; class CTexture; /* 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(wlr_buffer* buf, const Vector2D& hotspot, const float& scale); void setCursorSurface(SP buf, const Vector2D& hotspot); void resetCursorImage(bool apply = true); void lockSoftwareForMonitor(SP pMonitor); void unlockSoftwareForMonitor(SP pMonitor); void lockSoftwareForMonitor(CMonitor* pMonitor); void unlockSoftwareForMonitor(CMonitor* pMonitor); void lockSoftwareAll(); void unlockSoftwareAll(); void renderSoftwareCursorsFor(SP 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(SP pMonitor); // Vector2D position(); Vector2D cursorSizeLogical(); private: void recheckPointerPosition(); void onMonitorLayoutChange(); void onMonitorDisconnect(); void updateCursorBackend(); void onCursorMoved(); bool hasCursor(); void damageIfSoftware(); void recheckEnteredOutputs(); // 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(SP pMonitor); // returns the thing in logical coordinates of the monitor CBox getCursorBoxLogicalForMonitor(SP pMonitor); // returns the thing in global coords CBox getCursorBoxGlobal(); Vector2D transformedHotspot(SP 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 { wlr_buffer* pBuffer = nullptr; SP bufferTex; WP surface; wlr_texture* pBufferTexture = nullptr; Vector2D hotspot; Vector2D size; float scale = 1.F; CHyprSignalListener destroySurface; CHyprSignalListener commitSurface; DYNLISTENER(destroyBuffer); } currentCursorImage; // TODO: support various sizes per-output so we can have pixel-perfect cursors Vector2D pointerPos = {0, 0}; struct SMonitorPointerState { SMonitorPointerState(SP m) : monitor(m) {} ~SMonitorPointerState() { if (cursorFrontBuffer) wlr_buffer_unlock(cursorFrontBuffer); } WP monitor; int softwareLocks = 0; bool hardwareFailed = false; CBox box; // logical bool entered = false; bool hwApplied = false; wlr_buffer* cursorFrontBuffer = nullptr; }; std::vector> monitorStates; SP stateFor(SP mon); bool attemptHardwareCursor(SP state); wlr_buffer* renderHWCursorBuffer(SP state, SP texture); bool setHWCursorBuffer(SP state, wlr_buffer* buf); struct { SP monitorAdded; } hooks; }; inline UP g_pPointerManager;