-
Notifications
You must be signed in to change notification settings - Fork 60
/
Compositor.h
154 lines (119 loc) · 4.72 KB
/
Compositor.h
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
#pragma once
#include <Lemon/Graphics/Surface.h>
#include <Lemon/Graphics/Types.h>
#include <atomic>
#include <ctime>
#include <list>
#include <thread>
template <typename T, class... D> std::list<T> SplitModify(Rect& victim, const Rect& cut, D... extraData) {
std::list<T> clips;
if (cut.left() > victim.left() && cut.left() <= victim.right()) { // Clip left edge
Rect clip;
clip.top(victim.top());
clip.left(victim.left());
clip.bottom(victim.bottom());
clip.right(cut.left() - 1); // Left of cutting rect's left edge
victim.left(cut.left());
if (clip.width > 0) {
clips.push_back(T{clip, extraData...});
}
}
if (cut.top() > victim.top() && cut.top() <= victim.bottom()) { // Clip top edge
Rect clip;
clip.top(victim.top());
clip.left(victim.left());
clip.bottom(cut.top() - 1); // Above cutting rect's top edge
clip.right(victim.right());
victim.top(cut.top());
if (clip.height > 0) {
clips.push_back(T{clip, extraData...});
}
}
if (cut.right() >= victim.left() && cut.right() < victim.right()) { // Clip right edge
Rect clip;
clip.top(victim.top());
clip.left(cut.right() + 1);
clip.bottom(victim.bottom());
clip.right(victim.right());
victim.right(cut.right());
if (clip.width > 0) {
clips.push_back(T{clip, extraData...});
}
}
if (cut.bottom() >= victim.top() && cut.bottom() < victim.bottom()) { // Clip bottom edge
Rect clip;
clip.top(cut.bottom() + 1);
clip.left(victim.left());
clip.bottom(victim.bottom());
clip.right(victim.right());
victim.bottom(cut.bottom());
if (clip.height > 0) {
clips.push_back(T{clip, extraData...});
}
}
return clips;
}
template <typename T, class... D> inline std::list<T> Split(Rect victim, const Rect& cut, D... extraData){
return SplitModify<T, D...>(victim, cut, extraData...);
}
struct WindowClipRect {
Rect rect;
class WMWindow* win;
enum {
TypeWindow,
TypeWindowDecoration,
} type = TypeWindow;
bool invalid = true;
bool occluded = false;
std::list<WindowClipRect> SplitModify(const Rect& cut) { return ::SplitModify<WindowClipRect>(rect, cut, win, type, true, occluded); }
std::list<WindowClipRect> Split(const Rect& cut) { return ::Split<WindowClipRect>(rect, cut, win, type, true, occluded); }
};
struct BackgroundClipRect {
Rect rect;
bool invalid = true;
std::list<BackgroundClipRect> SplitModify(const Rect& cut) { return ::SplitModify<BackgroundClipRect, bool>(rect, cut, true); }
std::list<BackgroundClipRect> Split(const Rect& cut) { return ::Split<BackgroundClipRect, bool>(rect, cut, true); }
};
class Compositor {
public:
Compositor(const Surface& displaySurface);
void Render();
inline Vector2i GetScreenBounds() const { return {m_renderSurface.width, m_renderSurface.height}; }
void InvalidateAll();
void Invalidate(const Rect& rect);
void InvalidateWindow(class WMWindow* window);
void SetWallpaper(const std::string& path);
void SetShouldDisplayFramerate(bool value) { m_displayFramerate = value; }
inline void SetNormalCursor() { m_cursorCurrent = &m_cursorNormal; }
inline void SetResizeCursor() { m_cursorCurrent = &m_cursorResize; }
private:
void RecalculateWindowClipping();
void RecalculateBackgroundClipping();
void RecalculateRenderClipping();
void InvalidateBackgroundRect(BackgroundClipRect& bgRect);
void InvalidateWindowRect(WindowClipRect& wRect);
void InvalidateDecorationRect(WindowClipRect& dRect);
bool m_invalidateAll = true;
bool m_displayFramerate = false;
Vector2i m_lastMousePos = {0, 0};
Surface m_cursorNormal; // Normal mouse cursor
Surface m_cursorResize; // Window resize mouse cursor
Surface* m_cursorCurrent = &m_cursorNormal; // Current mouse cursor
// Used for framerate counter
timespec m_lastRender;
long m_avgFrametime = 0;
long m_fCount = 0;
int m_fRate = 0;
Surface m_renderSurface; // Backbuffer to render to
Surface m_displaySurface; // Display mapped surface
Surface m_wallpaper = {}; // Wallpaper surface
std::thread m_wallpaperThread;
std::atomic<int> m_wallpaperStatus = 0;
std::mutex m_renderMutex; // Currently only used for the wallpaper for invalidation
std::mutex m_wallpaperMutex;
std::list<BackgroundClipRect> m_backgroundRects;
std::list<WindowClipRect> m_windowClipRects;
// Clip rects used when determining which parts of the screen
// to copy to the framebuffer
std::list<BackgroundClipRect> m_renderClipRects;
};