#pragma once #include #include #include "../helpers/WLListener.hpp" #include "../macros.hpp" #include "../helpers/signal/Signal.hpp" #include "../helpers/math/Math.hpp" #include "../protocols/types/DataDevice.hpp" #include constexpr size_t MAX_SERIAL_STORE_LEN = 100; class CWLSurfaceResource; class CWLSeatResource; class IPointer; class IKeyboard; /* A seat grab defines a restricted set of surfaces that can be focused. Only one grab can be active at a time when a grab is removed, refocus() will happen Different from a constraint. When first set with setGrab, SeatManager will try to find a surface that is at the mouse pointer to focus, from first added to last added. If none are, first is focused. */ class CSeatGrab { public: bool accepts(SP surf); void add(SP surf); void remove(SP surf); void setCallback(std::function onEnd_); void clear(); bool keyboard = false; bool pointer = false; bool touch = false; bool removeOnInput = true; // on hard input e.g. click outside, remove private: std::vector> surfs; std::function onEnd; friend class CSeatManager; }; class CSeatManager { public: CSeatManager(); void updateCapabilities(uint32_t capabilities); // in IHID caps void setMouse(SP mouse); void setKeyboard(SP keeb); void updateActiveKeyboardData(); // updates the clients with the keymap and repeat info void setKeyboardFocus(SP surf); void sendKeyboardKey(uint32_t timeMs, uint32_t key, wl_keyboard_key_state state); void sendKeyboardMods(uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group); void setPointerFocus(SP surf, const Vector2D& local); void sendPointerMotion(uint32_t timeMs, const Vector2D& local); void sendPointerButton(uint32_t timeMs, uint32_t key, wl_pointer_button_state state); void sendPointerFrame(); void sendPointerFrame(WP pResource); void sendPointerAxis(uint32_t timeMs, wl_pointer_axis axis, double value, int32_t discrete, int32_t value120, wl_pointer_axis_source source, wl_pointer_axis_relative_direction relative); void sendTouchDown(SP surf, uint32_t timeMs, int32_t id, const Vector2D& local); void sendTouchUp(uint32_t timeMs, int32_t id); void sendTouchMotion(uint32_t timeMs, int32_t id, const Vector2D& local); void sendTouchFrame(); void sendTouchCancel(); void sendTouchShape(int32_t id, const Vector2D& shape); void sendTouchOrientation(int32_t id, double angle); void resendEnterEvents(); uint32_t nextSerial(SP seatResource); // pops the serial if it was valid, meaning it is consumed. bool serialValid(SP seatResource, uint32_t serial); void onSetCursor(SP seatResource, uint32_t serial, SP surf, const Vector2D& hotspot); SP seatResourceForClient(wl_client* client); struct { WP keyboardFocus; WP keyboardFocusResource; WP pointerFocus; WP pointerFocusResource; WP touchFocus; WP touchFocusResource; } state; struct SSetCursorEvent { SP surf = nullptr; Vector2D hotspot; }; struct { CSignal keyboardFocusChange; CSignal pointerFocusChange; CSignal touchFocusChange; CSignal setCursor; // SSetCursorEvent CSignal setSelection; CSignal setPrimarySelection; } events; struct { WP currentSelection; CHyprSignalListener destroySelection; WP currentPrimarySelection; CHyprSignalListener destroyPrimarySelection; } selection; void setCurrentSelection(SP source); void setCurrentPrimarySelection(SP source); // do not write to directly, use set... WP mouse; WP keyboard; void setGrab(SP grab); // nullptr removes SP seatGrab; private: struct SSeatResourceContainer { SSeatResourceContainer(SP); WP resource; std::vector serials; // old -> new struct { CHyprSignalListener destroy; } listeners; }; std::vector> seatResources; void onNewSeatResource(SP resource); SP containerForResource(SP seatResource); void refocusGrab(); struct { CHyprSignalListener newSeatResource; CHyprSignalListener keyboardSurfaceDestroy; CHyprSignalListener pointerSurfaceDestroy; CHyprSignalListener touchSurfaceDestroy; } listeners; Vector2D lastLocalCoords; int touchLocks = 0; // we assume there aint like 20 touch devices at once... friend struct SSeatResourceContainer; friend class CSeatGrab; }; inline UP g_pSeatManager;