#pragma once #include "../defines.hpp" #include #include "WLClasses.hpp" #include #include #include #include #include "Timer.hpp" #include "math/Math.hpp" #include #include "signal/Signal.hpp" #include "DamageRing.hpp" #include #include // Enum for the different types of auto directions, e.g. auto-left, auto-up. enum eAutoDirs { DIR_AUTO_NONE = 0, /* None will be treated as right. */ DIR_AUTO_UP, DIR_AUTO_DOWN, DIR_AUTO_LEFT, DIR_AUTO_RIGHT }; struct SMonitorRule { eAutoDirs autoDir = DIR_AUTO_NONE; std::string name = ""; Vector2D resolution = Vector2D(1280, 720); Vector2D offset = Vector2D(0, 0); float scale = 1; float refreshRate = 60; bool disabled = false; wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL; std::string mirrorOf = ""; bool enable10bit = false; drmModeModeInfo drmMode = {}; std::optional vrr; }; class CMonitor; class CSyncTimeline; class CMonitorState { public: CMonitorState(CMonitor* owner); ~CMonitorState(); bool commit(); bool test(); bool updateSwapchain(); private: void ensureBufferPresent(); CMonitor* m_pOwner; }; class CMonitor { public: CMonitor(SP output); ~CMonitor(); Vector2D vecPosition = Vector2D(-1, -1); // means unset Vector2D vecXWaylandPosition = Vector2D(-1, -1); // means unset Vector2D vecSize = Vector2D(0, 0); Vector2D vecPixelSize = Vector2D(0, 0); Vector2D vecTransformedSize = Vector2D(0, 0); bool primary = false; MONITORID ID = MONITOR_INVALID; PHLWORKSPACE activeWorkspace = nullptr; PHLWORKSPACE activeSpecialWorkspace = nullptr; float setScale = 1; // scale set by cfg float scale = 1; // real scale std::string szName = ""; std::string szDescription = ""; std::string szShortDescription = ""; Vector2D vecReservedTopLeft = Vector2D(0, 0); Vector2D vecReservedBottomRight = Vector2D(0, 0); drmModeModeInfo customDrmMode = {}; CMonitorState state; CDamageRing damage; SP output; float refreshRate = 60; int framesToSkip = 0; int forceFullFrames = 0; bool noFrameSchedule = false; bool scheduledRecalc = false; wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL; float xwaylandScale = 1.f; Mat3x3 projMatrix; std::optional forceSize; SP currentMode; SP cursorSwapchain; uint32_t drmFormat = DRM_FORMAT_INVALID; uint32_t prevDrmFormat = DRM_FORMAT_INVALID; bool dpmsStatus = true; bool vrrActive = false; // this can be TRUE even if VRR is not active in the case that this display does not support it. bool enabled10bit = false; // as above, this can be TRUE even if 10 bit failed. bool createdByUser = false; bool isUnsafeFallback = false; bool pendingFrame = false; // if we schedule a frame during rendering, reschedule it after bool renderingActive = false; wl_event_source* renderTimer = nullptr; // for RAT bool RATScheduled = false; CTimer lastPresentationTimer; bool isBeingLeased = false; SMonitorRule activeMonitorRule; // explicit sync SP inTimeline; SP outTimeline; uint64_t commitSeq = 0; WP self; // mirroring CMonitor* pMirrorOf = nullptr; std::vector mirrors; // ctm Mat3x3 ctm = Mat3x3::identity(); bool ctmUpdated = false; // for tearing PHLWINDOWREF solitaryClient; // for direct scanout PHLWINDOWREF lastScanout; struct { bool canTear = false; bool nextRenderTorn = false; bool activelyTearing = false; bool busy = false; bool frameScheduledWhileBusy = false; } tearingState; struct { CSignal destroy; CSignal connect; CSignal disconnect; CSignal dpmsChanged; CSignal modeChanged; } events; std::array, 4> m_aLayerSurfaceLayers; // methods void onConnect(bool noRule); void onDisconnect(bool destroy = false); void addDamage(const pixman_region32_t* rg); void addDamage(const CRegion* rg); void addDamage(const CBox* box); bool shouldSkipScheduleFrameOnMouseEvent(); void setMirror(const std::string&); bool isMirror(); bool matchesStaticSelector(const std::string& selector) const; float getDefaultScale(); void changeWorkspace(const PHLWORKSPACE& pWorkspace, bool internal = false, bool noMouseMove = false, bool noFocus = false); void changeWorkspace(const WORKSPACEID& id, bool internal = false, bool noMouseMove = false, bool noFocus = false); void setSpecialWorkspace(const PHLWORKSPACE& pWorkspace); void setSpecialWorkspace(const WORKSPACEID& id); void moveTo(const Vector2D& pos); Vector2D middle(); void updateMatrix(); WORKSPACEID activeWorkspaceID(); WORKSPACEID activeSpecialWorkspaceID(); CBox logicalBox(); void scheduleDone(); bool attemptDirectScanout(); void setCTM(const Mat3x3& ctm); void debugLastPresentation(const std::string& message); void onMonitorFrame(); bool m_bEnabled = false; bool m_bRenderingInitPassed = false; // For the list lookup bool operator==(const CMonitor& rhs) { return vecPosition == rhs.vecPosition && vecSize == rhs.vecSize && szName == rhs.szName; } private: void setupDefaultWS(const SMonitorRule&); WORKSPACEID findAvailableDefaultWS(); bool doneScheduled = false; struct { CHyprSignalListener frame; CHyprSignalListener destroy; CHyprSignalListener state; CHyprSignalListener needsFrame; CHyprSignalListener presented; CHyprSignalListener commit; } listeners; };