#pragma once #include #include #include #include #include "WaylandProtocol.hpp" #include "xdg-shell.hpp" #include "../helpers/math/Math.hpp" #include "../helpers/signal/Signal.hpp" #include "types/SurfaceRole.hpp" class CXDGWMBase; class CXDGPositionerResource; class CXDGSurfaceResource; class CXDGToplevelResource; class CXDGPopupResource; class CSeatGrab; class CWLSurfaceResource; class CXDGDialogV1Resource; struct SXDGPositionerState { Vector2D requestedSize; CBox anchorRect; CEdges anchor; CEdges gravity; uint32_t constraintAdjustment = 0; Vector2D offset; bool reactive = false; Vector2D parentSize; void setAnchor(xdgPositionerAnchor edges); void setGravity(xdgPositionerGravity edges); }; class CXDGPositionerRules { public: CXDGPositionerRules(SP positioner); CBox getPosition(CBox constraint, const Vector2D& parentPos); private: SXDGPositionerState m_state; }; class CXDGPopupResource { public: CXDGPopupResource(SP resource_, SP parent_, SP surface_, SP positioner_); ~CXDGPopupResource(); static SP fromResource(wl_resource*); bool good(); void applyPositioning(const CBox& availableBox, const Vector2D& t1coord /* relative to box */); WP m_surface; WP m_parent; WP m_self; bool m_taken = false; CBox m_geometry; struct { CSignalT<> reposition; CSignalT<> dismissed; CSignalT<> destroy; // only the role } m_events; // schedules a configure event void configure(const CBox& box); void done(); void repositioned(); private: SP m_resource; uint32_t m_lastRepositionToken = 0; Vector2D accumulateParentOffset(); CXDGPositionerRules m_positionerRules; }; class CXDGToplevelResource { public: CXDGToplevelResource(SP resource_, SP owner_); ~CXDGToplevelResource(); static SP fromResource(wl_resource*); WP m_owner; WP m_self; PHLWINDOWREF m_window; bool good(); Vector2D layoutMinSize(); Vector2D layoutMaxSize(); // schedule a configure event uint32_t setSize(const Vector2D& size); uint32_t setMaximized(bool maximized); uint32_t setFullscreen(bool fullscreen); uint32_t setActive(bool active); uint32_t setSuspeneded(bool sus); void close(); struct { CSignalT<> sizeLimitsChanged; CSignalT<> stateChanged; // maximized, fs, minimized, etc. CSignalT<> metadataChanged; // title, appid CSignalT<> destroy; // only the role } m_events; struct { std::string title; std::string appid; // volatile state: is reset after the stateChanged signal fires std::optional requestsMaximize; std::optional requestsFullscreen; std::optional requestsFullscreenMonitor; std::optional requestsMinimize; } m_state; struct { Vector2D size; std::vector states; } m_pendingApply; struct { Vector2D minSize = {1, 1}; Vector2D maxSize = {1337420, 694200}; } m_pending, m_current; WP m_parent; WP m_dialog; std::optional m_toplevelTag; std::optional m_toplevelDescription; bool anyChildModal(); std::vector> m_children; private: SP m_resource; void applyState(); }; class CXDGSurfaceRole : public ISurfaceRole { public: CXDGSurfaceRole(SP xdg); virtual eSurfaceRole role() { return SURFACE_ROLE_XDG_SHELL; } WP m_xdgSurface; }; class CXDGSurfaceResource { public: CXDGSurfaceResource(SP resource_, SP owner_, SP surface_); ~CXDGSurfaceResource(); static SP fromResource(wl_resource*); bool good(); WP m_owner; WP m_surface; WP m_toplevel; WP m_popup; WP m_self; struct { CBox geometry; } m_pending, m_current; struct { CSignalT ack; CSignalT<> commit; CSignalT<> map; CSignalT<> unmap; CSignalT<> destroy; CSignalT> newPopup; } m_events; bool m_initialCommit = true; bool m_mapped = false; uint32_t scheduleConfigure(); // do not call directly void configure(); private: SP m_resource; uint32_t m_lastConfigureSerial = 0; uint32_t m_scheduledSerial = 0; wl_event_source* m_configureSource = nullptr; // std::vector> m_popups; struct { CHyprSignalListener surfaceDestroy; CHyprSignalListener surfaceCommit; } m_listeners; friend class CXDGPopupResource; friend class CXDGToplevelResource; }; class CXDGPositionerResource { public: CXDGPositionerResource(SP resource_, SP owner_); static SP fromResource(wl_resource*); bool good(); SXDGPositionerState m_state; WP m_owner; WP m_self; private: SP m_resource; }; class CXDGWMBase { public: CXDGWMBase(SP resource_); bool good(); wl_client* client(); void ping(); std::vector> m_positioners; std::vector> m_surfaces; WP m_self; struct { CSignalT<> pong; } m_events; private: SP m_resource; wl_client* m_client = nullptr; }; class CXDGShellProtocol : public IWaylandProtocol { public: CXDGShellProtocol(const wl_interface* iface, const int& ver, const std::string& name); virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); private: void destroyResource(CXDGWMBase* resource); void destroyResource(CXDGPositionerResource* resource); void destroyResource(CXDGSurfaceResource* resource); void destroyResource(CXDGToplevelResource* resource); void destroyResource(CXDGPopupResource* resource); // std::vector> m_wmBases; std::vector> m_positioners; std::vector> m_surfaces; std::vector> m_toplevels; std::vector> m_popups; // current popup grab WP m_grabOwner; SP m_grab; std::vector> m_grabbed; void addOrStartGrab(SP popup); void onPopupDestroy(WP popup); friend class CXDGWMBase; friend class CXDGPositionerResource; friend class CXDGSurfaceResource; friend class CXDGToplevelResource; friend class CXDGPopupResource; }; namespace PROTO { inline UP xdgShell; };