#pragma once #include #include "../helpers/WLListener.hpp" #include "../macros.hpp" #include "../helpers/signal/Signal.hpp" #include "../helpers/Vector2D.hpp" #include "../protocols/types/DataDevice.hpp" #include constexpr size_t MAX_SERIAL_STORE_LEN = 100; struct wlr_surface; 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(wlr_surface* surf); void add(wlr_surface* surf); void remove(wlr_surface* 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; // read-only 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 setKeyboardFocus(wlr_surface* 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(wlr_surface* 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, wl_pointer_axis_source source, wl_pointer_axis_relative_direction relative); void sendTouchDown(wlr_surface* 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, wlr_surface* surf, const Vector2D& hotspot); SP seatResourceForClient(wl_client* client); struct { wlr_surface* keyboardFocus = nullptr; WP keyboardFocusResource; wlr_surface* pointerFocus = nullptr; WP pointerFocusResource; wlr_surface* touchFocus = nullptr; WP touchFocusResource; } state; struct SSetCursorEvent { wlr_surface* surf = nullptr; Vector2D hotspot; }; struct { CSignal keyboardFocusChange; CSignal pointerFocusChange; CSignal touchFocusChange; CSignal setCursor; // SSetCursorEvent } 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; } listeners; Vector2D lastLocalCoords; DYNLISTENER(keyboardSurfaceDestroy); DYNLISTENER(pointerSurfaceDestroy); DYNLISTENER(touchSurfaceDestroy); friend struct SSeatResourceContainer; friend class CSeatGrab; }; inline UP g_pSeatManager;