summaryrefslogtreecommitdiff
path: root/src/managers/PointerManager.hpp
diff options
context:
space:
mode:
authorVaxry <vaxry@vaxry.net>2024-05-05 22:18:10 +0100
committerVaxry <43317083+vaxerski@users.noreply.github.com>2024-05-09 13:37:39 +0100
commited411f53bdcf8d455f9e6ca769693aa84dc8372f (patch)
treeaacedb349acdd1022975d7b622dc7cfe11388223 /src/managers/PointerManager.hpp
parente4e84064f2d07810e0c150bce1369a0a00503e9a (diff)
cursor: move to a hyprland impl
This moves wlr_cursor to a completely new impl mostly under CPointerManager Also adds beginSimple to OpenGL for simple render passes (e.g. cursor)
Diffstat (limited to 'src/managers/PointerManager.hpp')
-rw-r--r--src/managers/PointerManager.hpp158
1 files changed, 158 insertions, 0 deletions
diff --git a/src/managers/PointerManager.hpp b/src/managers/PointerManager.hpp
new file mode 100644
index 00000000..2446cde7
--- /dev/null
+++ b/src/managers/PointerManager.hpp
@@ -0,0 +1,158 @@
+#pragma once
+
+#include "../devices/IPointer.hpp"
+#include "../devices/ITouch.hpp"
+#include "../helpers/Box.hpp"
+#include "../helpers/Region.hpp"
+#include "../desktop/WLSurface.hpp"
+#include <tuple>
+
+class CMonitor;
+struct wlr_input_device;
+class IHID;
+
+/*
+ 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();
+
+ // pointers will move the cursor on their respective events
+ void attachPointer(SP<IPointer> pointer);
+ // touch inputs won't move the cursor, it needs to be done manually
+ void attachTouch(SP<ITouch> touch);
+
+ void detachPointer(SP<IPointer> pointer);
+ void detachTouch(SP<ITouch> touch);
+
+ // only clamps to the layout.
+ void warpTo(const Vector2D& logical);
+ void move(const Vector2D& deltaLogical);
+ void warpAbsolute(const Vector2D& abs, SP<IHID> dev);
+
+ void setCursorBuffer(wlr_buffer* buf, const Vector2D& hotspot, const float& scale);
+ void setCursorSurface(CWLSurface* buf, const Vector2D& hotspot);
+ void resetCursorImage(bool apply = true);
+
+ void lockSoftwareForMonitor(SP<CMonitor> pMonitor);
+ void unlockSoftwareForMonitor(SP<CMonitor> pMonitor);
+
+ void renderSoftwareCursorsFor(SP<CMonitor> 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(SP<CMonitor> pMonitor);
+
+ //
+ Vector2D position();
+
+ 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<CMonitor> pMonitor);
+ // returns the thing in logical coordinates of the monitor
+ CBox getCursorBoxLogicalForMonitor(SP<CMonitor> pMonitor);
+ // returns the thing in global coords
+ CBox getCursorBoxGlobal();
+
+ Vector2D transformedHotspot(SP<CMonitor> pMonitor);
+
+ wlr_texture* 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 {
+ std::vector<CBox> monitorBoxes;
+ } currentMonitorLayout;
+
+ struct {
+ wlr_buffer* pBuffer = nullptr;
+ CWLSurface* surface = nullptr;
+ wlr_texture* pBufferTexture = nullptr;
+
+ Vector2D hotspot;
+ Vector2D size;
+ float scale = 1.F;
+
+ CHyprSignalListener destroySurface;
+ DYNLISTENER(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<CMonitor> m) : monitor(m) {}
+ WP<CMonitor> monitor;
+
+ int softwareLocks = 0;
+ bool hardwareFailed = false;
+ CBox box; // logical
+ bool entered = false;
+ bool hwApplied = false;
+
+ wlr_buffer* cursorFrontBuffer = nullptr;
+ };
+
+ std::vector<SP<SMonitorPointerState>> monitorStates;
+ SP<SMonitorPointerState> stateFor(SP<CMonitor> mon);
+ bool attemptHardwareCursor(SP<SMonitorPointerState> state);
+ wlr_buffer* renderHWCursorBuffer(SP<SMonitorPointerState> state, wlr_texture* texture);
+ bool setHWCursorBuffer(SP<SMonitorPointerState> state, wlr_buffer* buf);
+
+ struct {
+ SP<HOOK_CALLBACK_FN> monitorAdded;
+ } hooks;
+};
+
+inline UP<CPointerManager> g_pPointerManager;