aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/helpers/Monitor.hpp
blob: 43de8d12575dab1854eb5227aca059c3bd81efdb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#pragma once

#include "../defines.hpp"
#include <deque>
#include "WLClasses.hpp"
#include <vector>
#include <array>
#include <memory>
#include <xf86drmMode.h>
#include "Timer.hpp"
#include "Region.hpp"
#include <optional>

struct SMonitorRule {
    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<int>  vrr;
};

class CMonitor;

// Class for wrapping the wlr state
class CMonitorState {
  public:
    CMonitorState(CMonitor* owner);
    ~CMonitorState();

    wlr_output_state* wlr();
    void              clear();
    // commit() will also clear()
    bool commit();
    bool test();

  private:
    wlr_output_state m_state = {0};
    CMonitor*        m_pOwner;
};

class CMonitor {
  public:
    CMonitor();
    ~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;

    uint64_t        ID              = -1;
    int             activeWorkspace = -1;
    float           setScale        = 1; // scale set by cfg
    float           scale           = 1; // real scale

    std::string     szName        = "";
    std::string     szDescription = "";

    Vector2D        vecReservedTopLeft     = Vector2D(0, 0);
    Vector2D        vecReservedBottomRight = Vector2D(0, 0);

    drmModeModeInfo customDrmMode = {};

    CMonitorState   state;

    // WLR stuff
    wlr_damage_ring      damage;
    wlr_output*          output          = nullptr;
    float                refreshRate     = 60;
    int                  framesToSkip    = 0;
    int                  forceFullFrames = 0;
    bool                 noFrameSchedule = false;
    bool                 scheduledRecalc = false;
    wl_output_transform  transform       = WL_OUTPUT_TRANSFORM_NORMAL;
    bool                 gammaChanged    = false;
    float                xwaylandScale   = 1.f;
    std::array<float, 9> projMatrix      = {0};

    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;
    uint32_t             drmFormat        = DRM_FORMAT_INVALID;
    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;

    SMonitorRule         activeMonitorRule;

    // mirroring
    CMonitor*              pMirrorOf = nullptr;
    std::vector<CMonitor*> mirrors;

    CRegion                lastFrameDamage; // stores last frame damage

    // for tearing
    CWindow* solitaryClient = nullptr;

    struct {
        bool canTear         = false;
        bool nextRenderTorn  = false;
        bool activelyTearing = false;

        bool busy                    = false;
        bool frameScheduledWhileBusy = false;
    } tearingState;

    // for the special workspace. 0 means not open.
    int                                                        specialWorkspaceID = 0;

    std::array<std::vector<std::unique_ptr<SLayerSurface>>, 4> m_aLayerSurfaceLayers;

    DYNLISTENER(monitorFrame);
    DYNLISTENER(monitorDestroy);
    DYNLISTENER(monitorStateRequest);
    DYNLISTENER(monitorDamage);
    DYNLISTENER(monitorNeedsFrame);
    DYNLISTENER(monitorCommit);
    DYNLISTENER(monitorBind);

    // 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);
    void     setMirror(const std::string&);
    bool     isMirror();
    float    getDefaultScale();
    void     changeWorkspace(CWorkspace* const pWorkspace, bool internal = false, bool noMouseMove = false, bool noFocus = false);
    void     changeWorkspace(const int& id, bool internal = false);
    void     setSpecialWorkspace(CWorkspace* const pWorkspace);
    void     setSpecialWorkspace(const int& id);
    void     moveTo(const Vector2D& pos);
    Vector2D middle();
    void     updateMatrix();

    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&);
    int  findAvailableDefaultWS();
};