2024-05-05 23:18:10 +02:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "../devices/IPointer.hpp"
|
|
|
|
#include "../devices/ITouch.hpp"
|
2024-05-06 03:15:26 +02:00
|
|
|
#include "../devices/Tablet.hpp"
|
2024-06-19 16:20:06 +02:00
|
|
|
#include "../helpers/math/Math.hpp"
|
|
|
|
#include "../helpers/math/Math.hpp"
|
2024-05-05 23:18:10 +02:00
|
|
|
#include "../desktop/WLSurface.hpp"
|
2024-07-21 13:09:54 +02:00
|
|
|
#include "../helpers/sync/SyncTimeline.hpp"
|
2024-05-05 23:18:10 +02:00
|
|
|
#include <tuple>
|
|
|
|
|
|
|
|
class CMonitor;
|
|
|
|
class IHID;
|
2024-06-08 10:07:59 +02:00
|
|
|
class CTexture;
|
2024-05-05 23:18:10 +02:00
|
|
|
|
2024-07-21 13:09:54 +02:00
|
|
|
AQUAMARINE_FORWARD(IBuffer);
|
|
|
|
|
2024-05-05 23:18:10 +02:00
|
|
|
/*
|
|
|
|
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);
|
2024-05-06 03:15:26 +02:00
|
|
|
void attachTablet(SP<CTablet> tablet);
|
2024-05-05 23:18:10 +02:00
|
|
|
|
|
|
|
void detachPointer(SP<IPointer> pointer);
|
|
|
|
void detachTouch(SP<ITouch> touch);
|
2024-05-06 03:15:26 +02:00
|
|
|
void detachTablet(SP<CTablet> tablet);
|
2024-05-05 23:18:10 +02:00
|
|
|
|
|
|
|
// only clamps to the layout.
|
|
|
|
void warpTo(const Vector2D& logical);
|
|
|
|
void move(const Vector2D& deltaLogical);
|
2024-05-06 03:15:26 +02:00
|
|
|
void warpAbsolute(Vector2D abs, SP<IHID> dev);
|
2024-05-05 23:18:10 +02:00
|
|
|
|
2024-07-21 13:09:54 +02:00
|
|
|
void setCursorBuffer(SP<Aquamarine::IBuffer> buf, const Vector2D& hotspot, const float& scale);
|
2024-06-08 10:07:59 +02:00
|
|
|
void setCursorSurface(SP<CWLSurface> buf, const Vector2D& hotspot);
|
2024-05-05 23:18:10 +02:00
|
|
|
void resetCursorImage(bool apply = true);
|
|
|
|
|
|
|
|
void lockSoftwareForMonitor(SP<CMonitor> pMonitor);
|
|
|
|
void unlockSoftwareForMonitor(SP<CMonitor> pMonitor);
|
2024-06-12 19:28:52 +02:00
|
|
|
void lockSoftwareAll();
|
|
|
|
void unlockSoftwareAll();
|
2024-07-21 13:09:54 +02:00
|
|
|
bool softwareLockedFor(SP<CMonitor> pMonitor);
|
2024-05-05 23:18:10 +02:00
|
|
|
|
|
|
|
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();
|
2024-05-11 18:13:20 +02:00
|
|
|
Vector2D cursorSizeLogical();
|
2024-10-12 02:29:51 +02:00
|
|
|
void storeMovement(uint64_t time, const Vector2D& delta, const Vector2D& deltaUnaccel);
|
|
|
|
void setStoredMovement(uint64_t time, const Vector2D& delta, const Vector2D& deltaUnaccel);
|
|
|
|
void sendStoredMovement();
|
2024-05-05 23:18:10 +02:00
|
|
|
|
2024-06-25 12:55:54 +02:00
|
|
|
void recheckEnteredOutputs();
|
|
|
|
|
2024-05-05 23:18:10 +02:00
|
|
|
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(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);
|
|
|
|
|
2024-06-08 10:07:59 +02:00
|
|
|
SP<CTexture> getCurrentCursorTexture();
|
2024-05-05 23:18:10 +02:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
2024-05-06 03:15:26 +02:00
|
|
|
struct STabletListener {
|
|
|
|
CHyprSignalListener destroy;
|
|
|
|
CHyprSignalListener axis;
|
|
|
|
CHyprSignalListener proximity;
|
|
|
|
CHyprSignalListener tip;
|
|
|
|
CHyprSignalListener button;
|
|
|
|
|
|
|
|
WP<CTablet> tablet;
|
|
|
|
};
|
|
|
|
std::vector<SP<STabletListener>> tabletListeners;
|
|
|
|
|
2024-05-05 23:18:10 +02:00
|
|
|
struct {
|
|
|
|
std::vector<CBox> monitorBoxes;
|
|
|
|
} currentMonitorLayout;
|
|
|
|
|
|
|
|
struct {
|
2024-07-21 13:09:54 +02:00
|
|
|
SP<Aquamarine::IBuffer> pBuffer;
|
|
|
|
SP<CTexture> bufferTex;
|
|
|
|
WP<CWLSurface> surface;
|
|
|
|
|
|
|
|
Vector2D hotspot;
|
|
|
|
Vector2D size;
|
|
|
|
float scale = 1.F;
|
|
|
|
|
|
|
|
CHyprSignalListener destroySurface;
|
|
|
|
CHyprSignalListener commitSurface;
|
|
|
|
SP<CSyncTimeline> waitTimeline = nullptr;
|
|
|
|
uint64_t waitPoint = 0;
|
2024-05-05 23:18:10 +02:00
|
|
|
} currentCursorImage; // TODO: support various sizes per-output so we can have pixel-perfect cursors
|
|
|
|
|
|
|
|
Vector2D pointerPos = {0, 0};
|
|
|
|
|
2024-10-12 02:29:51 +02:00
|
|
|
uint64_t storedTime = 0;
|
|
|
|
Vector2D storedDelta = {0, 0};
|
|
|
|
Vector2D storedUnaccel = {0, 0};
|
|
|
|
|
2024-05-05 23:18:10 +02:00
|
|
|
struct SMonitorPointerState {
|
|
|
|
SMonitorPointerState(SP<CMonitor> m) : monitor(m) {}
|
2024-07-21 13:09:54 +02:00
|
|
|
~SMonitorPointerState() {}
|
2024-06-06 20:27:09 +02:00
|
|
|
|
2024-07-21 13:09:54 +02:00
|
|
|
WP<CMonitor> monitor;
|
2024-05-05 23:18:10 +02:00
|
|
|
|
2024-07-21 13:09:54 +02:00
|
|
|
int softwareLocks = 0;
|
|
|
|
bool hardwareFailed = false;
|
|
|
|
CBox box; // logical
|
2024-07-22 19:19:37 +02:00
|
|
|
bool entered = false;
|
|
|
|
bool hwApplied = false;
|
|
|
|
bool cursorRendered = false;
|
2024-05-05 23:18:10 +02:00
|
|
|
|
2024-07-21 13:09:54 +02:00
|
|
|
SP<Aquamarine::IBuffer> cursorFrontBuffer;
|
2024-05-05 23:18:10 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
std::vector<SP<SMonitorPointerState>> monitorStates;
|
|
|
|
SP<SMonitorPointerState> stateFor(SP<CMonitor> mon);
|
|
|
|
bool attemptHardwareCursor(SP<SMonitorPointerState> state);
|
2024-07-21 13:09:54 +02:00
|
|
|
SP<Aquamarine::IBuffer> renderHWCursorBuffer(SP<SMonitorPointerState> state, SP<CTexture> texture);
|
|
|
|
bool setHWCursorBuffer(SP<SMonitorPointerState> state, SP<Aquamarine::IBuffer> buf);
|
2024-05-05 23:18:10 +02:00
|
|
|
|
|
|
|
struct {
|
|
|
|
SP<HOOK_CALLBACK_FN> monitorAdded;
|
2024-07-22 19:19:37 +02:00
|
|
|
SP<HOOK_CALLBACK_FN> monitorPreRender;
|
2024-05-05 23:18:10 +02:00
|
|
|
} hooks;
|
|
|
|
};
|
|
|
|
|
|
|
|
inline UP<CPointerManager> g_pPointerManager;
|