aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/render/decorations/DecorationPositioner.hpp
blob: c2d69881e56f4b398377f724d071e0893e4b21ca (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
#pragma once

#include <cstdint>
#include <vector>
#include <map>
#include "../../helpers/math/Math.hpp"
#include "../../desktop/DesktopTypes.hpp"

class CWindow;
class IHyprWindowDecoration;

enum eDecorationPositioningPolicy : uint8_t {
    DECORATION_POSITION_ABSOLUTE = 0, /* Decoration wants absolute positioning */
    DECORATION_POSITION_STICKY,       /* Decoration is stuck to some edge of a window */
};

enum eDecorationEdges : uint8_t {
    DECORATION_EDGE_TOP    = 1 << 0,
    DECORATION_EDGE_BOTTOM = 1 << 1,
    DECORATION_EDGE_LEFT   = 1 << 2,
    DECORATION_EDGE_RIGHT  = 1 << 3
};

/*
Request the positioner to position a decoration

DECORATION_POSITION_ABSOLUTE:
    - desiredExtents has to contain the extents. Edges has to have the edges used.
    - reserved allowed
DECORATION_POSITION_STICKY:
    - one edge allowed
    - priority allowed
    - desiredExtents contains the desired extents. Any other edge than the one selected is ignored.
    - reserved is allowed
*/
struct SDecorationPositioningInfo {
    eDecorationPositioningPolicy policy   = DECORATION_POSITION_ABSOLUTE;
    uint32_t                     edges    = 0;  // enum eDecorationEdges
    uint32_t                     priority = 10; // priority, decos will be evaluated high -> low
    SBoxExtents                  desiredExtents;
    bool                         reserved = false; // if true, geometry will use reserved area
};

/*
A reply from the positioner. This may be sent multiple times, if anything changes.

DECORATION_POSITION_ABSOLUTE:
    - assignedGeometry is empty
DECORATION_POSITION_STICKY:
    - assignedGeometry is relative to the edge's center point
    - ephemeral is sent
*/
struct SDecorationPositioningReply {
    CBox assignedGeometry;
    bool ephemeral = false; // if true, means it's a result of an animation and will change soon.
};

class CDecorationPositioner {
  public:
    CDecorationPositioner();

    Vector2D getEdgeDefinedPoint(uint32_t edges, PHLWINDOW pWindow);

    // called on resize, or insert/removal of a new deco
    void        onWindowUpdate(PHLWINDOW pWindow);
    void        uncacheDecoration(IHyprWindowDecoration* deco);
    SBoxExtents getWindowDecorationReserved(PHLWINDOW pWindow);
    SBoxExtents getWindowDecorationExtents(PHLWINDOW pWindow, bool inputOnly = false);
    CBox        getBoxWithIncludedDecos(PHLWINDOW pWindow);
    void        repositionDeco(IHyprWindowDecoration* deco);
    CBox        getWindowDecorationBox(IHyprWindowDecoration* deco);
    void        forceRecalcFor(PHLWINDOW pWindow);

  private:
    struct SWindowPositioningData {
        PHLWINDOWREF                pWindow;
        IHyprWindowDecoration*      pDecoration = nullptr;
        SDecorationPositioningInfo  positioningInfo;
        SDecorationPositioningReply lastReply;
        bool                        needsReposition = true;
    };

    struct SWindowData {
        Vector2D    lastWindowSize = {};
        SBoxExtents reserved       = {};
        SBoxExtents extents        = {};
        bool        needsRecalc    = false;
    };

    std::map<PHLWINDOWREF, SWindowData>                  m_mWindowDatas;
    std::vector<std::unique_ptr<SWindowPositioningData>> m_vWindowPositioningDatas;

    SWindowPositioningData*                              getDataFor(IHyprWindowDecoration* pDecoration, PHLWINDOW pWindow);
    void                                                 onWindowUnmap(PHLWINDOW pWindow);
    void                                                 onWindowMap(PHLWINDOW pWindow);
    void                                                 sanitizeDatas();
};

inline std::unique_ptr<CDecorationPositioner> g_pDecorationPositioner;