#pragma once #include "../defines.hpp" #include #include #include "../SharedDefs.hpp" #include "MiscFunctions.hpp" #include "WLClasses.hpp" #include #include "AnimatedVariable.hpp" #include #include "time/Timer.hpp" #include "math/Math.hpp" #include #include "../protocols/types/ColorManagement.hpp" #include "signal/Signal.hpp" #include "DamageRing.hpp" #include #include #include // Enum for the different types of auto directions, e.g. auto-left, auto-up. enum eAutoDirs : uint8_t { DIR_AUTO_NONE = 0, /* None will be treated as right. */ DIR_AUTO_UP, DIR_AUTO_DOWN, DIR_AUTO_LEFT, DIR_AUTO_RIGHT, DIR_AUTO_CENTER_UP, DIR_AUTO_CENTER_DOWN, DIR_AUTO_CENTER_LEFT, DIR_AUTO_CENTER_RIGHT }; enum eCMType : uint8_t { CM_AUTO = 0, // subject to change. srgb for 8bpc, wide for 10bpc if supported CM_SRGB, // default, sRGB primaries CM_WIDE, // wide color gamut, BT2020 primaries CM_EDID, // primaries from edid (known to be inaccurate) CM_HDR, // wide color gamut and HDR PQ transfer function CM_HDR_EDID, // same as CM_HDR with edid primaries }; 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; // Hz bool disabled = false; wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL; std::string mirrorOf = ""; bool enable10bit = false; eCMType cmType = CM_SRGB; float sdrSaturation = 1.0f; // SDR -> HDR float sdrBrightness = 1.0f; // SDR -> HDR drmModeModeInfo drmMode = {}; std::optional vrr; }; class CMonitor; class CSyncTimeline; class CEGLSync; class CMonitorState { public: CMonitorState(CMonitor* owner); ~CMonitorState() = default; bool commit(); bool test(); bool updateSwapchain(); private: void ensureBufferPresent(); CMonitor* m_owner = nullptr; }; class CMonitor { public: CMonitor(SP output); ~CMonitor(); Vector2D m_position = Vector2D(-1, -1); // means unset Vector2D m_xwaylandPosition = Vector2D(-1, -1); // means unset eAutoDirs m_autoDir = DIR_AUTO_NONE; Vector2D m_size = Vector2D(0, 0); Vector2D m_pixelSize = Vector2D(0, 0); Vector2D m_transformedSize = Vector2D(0, 0); MONITORID m_id = MONITOR_INVALID; PHLWORKSPACE m_activeWorkspace = nullptr; PHLWORKSPACE m_activeSpecialWorkspace = nullptr; float m_setScale = 1; // scale set by cfg float m_scale = 1; // real scale std::string m_name = ""; std::string m_description = ""; std::string m_shortDescription = ""; Vector2D m_reservedTopLeft = Vector2D(0, 0); Vector2D m_reservedBottomRight = Vector2D(0, 0); drmModeModeInfo m_customDrmMode = {}; CMonitorState m_state; CDamageRing m_damage; SP m_output; float m_refreshRate = 60; // Hz int m_forceFullFrames = 0; bool m_scheduledRecalc = false; wl_output_transform m_transform = WL_OUTPUT_TRANSFORM_NORMAL; float m_xwaylandScale = 1.f; Mat3x3 m_projMatrix; std::optional m_forceSize; SP m_currentMode; SP m_cursorSwapchain; uint32_t m_drmFormat = DRM_FORMAT_INVALID; uint32_t m_prevDrmFormat = DRM_FORMAT_INVALID; bool m_dpmsStatus = true; bool m_vrrActive = false; // this can be TRUE even if VRR is not active in the case that this display does not support it. bool m_enabled10bit = false; // as above, this can be TRUE even if 10 bit failed. eCMType m_cmType = CM_SRGB; float m_sdrSaturation = 1.0f; float m_sdrBrightness = 1.0f; bool m_createdByUser = false; bool m_isUnsafeFallback = false; bool m_pendingFrame = false; // if we schedule a frame during rendering, reschedule it after bool m_renderingActive = false; wl_event_source* m_renderTimer = nullptr; // for RAT bool m_ratsScheduled = false; CTimer m_lastPresentationTimer; bool m_isBeingLeased = false; SMonitorRule m_activeMonitorRule; // explicit sync Hyprutils::OS::CFileDescriptor m_inFence; // TODO: remove when aq uses CFileDescriptor PHLMONITORREF m_self; // mirroring PHLMONITORREF m_mirrorOf; std::vector m_mirrors; // ctm Mat3x3 m_ctm = Mat3x3::identity(); bool m_ctmUpdated = false; // for tearing PHLWINDOWREF m_solitaryClient; // for direct scanout PHLWINDOWREF m_lastScanout; bool m_scanoutNeedsCursorUpdate = false; // for special fade/blur PHLANIMVAR m_specialFade; struct { bool canTear = false; bool nextRenderTorn = false; bool activelyTearing = false; bool busy = false; bool frameScheduledWhileBusy = false; } m_tearingState; struct { CSignal destroy; CSignal connect; CSignal disconnect; CSignal dpmsChanged; CSignal modeChanged; } m_events; std::array, 4> m_layerSurfaceLayers; // methods void onConnect(bool noRule); void onDisconnect(bool destroy = false); bool applyMonitorRule(SMonitorRule* pMonitorRule, bool force = 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 onCursorMovedOnMonitor(); void debugLastPresentation(const std::string& message); void onMonitorFrame(); bool m_enabled = false; bool m_renderingInitPassed = false; WP m_previousFSWindow; NColorManagement::SImageDescription m_imageDescription; // For the list lookup bool operator==(const CMonitor& rhs) { return m_position == rhs.m_position && m_size == rhs.m_size && m_name == rhs.m_name; } // workspace previous per monitor functionality SWorkspaceIDName getPrevWorkspaceIDName(const WORKSPACEID id); void addPrevWorkspaceID(const WORKSPACEID id); private: void setupDefaultWS(const SMonitorRule&); WORKSPACEID findAvailableDefaultWS(); bool m_doneScheduled = false; std::stack m_prevWorkSpaces; struct { CHyprSignalListener frame; CHyprSignalListener destroy; CHyprSignalListener state; CHyprSignalListener needsFrame; CHyprSignalListener presented; CHyprSignalListener commit; } m_listeners; };