910fcc0f257e260120dac0197293b0ecfa6e11cf
- Author
- outfoxxed <outfoxxed@outfoxxed.me>
- Committer
- outfoxxed <outfoxxed@outfoxxed.me>
- Date
Message
Diff
This diff is truncated to protect this page.
1diff --git a/src/Hy3Layout.cpp b/src/Hy3Layout.cpp
2index e97898e6688d8c7309228267787748a1bb7ec36c..efe6b27bf23dd7530d1fb022464ef82ce34e604a 100644
3--- a/src/Hy3Layout.cpp
4+++ b/src/Hy3Layout.cpp
5@@ -18,6 +18,20 @@ void errorNotif() {
6
7 Hy3GroupData::Hy3GroupData(Hy3GroupLayout layout): layout(layout) {}
8
9+Hy3GroupData::Hy3GroupData(Hy3GroupData&& from) {
10+ this->layout = from.layout;
11+ this->children = std::move(from.children);
12+ this->group_focused = from.group_focused;
13+ this->focused_child = from.focused_child;
14+ from.focused_child = nullptr;
15+ this->tab_bar = from.tab_bar;
16+ from.tab_bar = nullptr;
17+}
18+
19+Hy3GroupData::~Hy3GroupData() {
20+ if (this->tab_bar != nullptr) this->tab_bar->bar.beginDestroy();
21+}
22+
23 Hy3NodeData::Hy3NodeData(): Hy3NodeData((CWindow*)nullptr) {}
24
25 Hy3NodeData::Hy3NodeData(CWindow *window): type(Hy3NodeData::Window) {
26@@ -151,6 +165,8 @@ void Hy3Node::recalcSizePosRecursive(bool force) {
27 break;
28 }
29
30+ this->updateTabBar();
31+
32 child->recalcSizePosRecursive(force);
33 return;
34 }
35@@ -200,6 +216,8 @@ void Hy3Node::recalcSizePosRecursive(bool force) {
36
37 child->recalcSizePosRecursive(force);
38 }
39+
40+ this->updateTabBar();
41 }
42
43 void Hy3Node::setHidden(bool hidden) {
44@@ -227,6 +245,17 @@ bool Hy3Node::isUrgent() {
45 }
46 }
47
48+bool Hy3Node::isIndirectlyFocused() {
49+ Hy3Node* node = this;
50+
51+ while (node->parent != nullptr) {
52+ if (node->parent->data.as_group.focused_child != node) return false;
53+ node = node->parent;
54+ }
55+
56+ return true;
57+}
58+
59 std::string Hy3Node::getTitle() {
60 switch (this->data.type) {
61 case Hy3NodeData::Window:
62@@ -272,14 +301,30 @@ void Hy3Node::markFocused() {
63 this->data.as_group.focused_child = nullptr;
64 }
65
66+ auto* node2 = node;
67+ while (node2->parent != nullptr) {
68+ node2->parent->data.as_group.focused_child = node2;
69+ node2->parent->data.as_group.group_focused = false;
70+ node2 = node2->parent;
71+ }
72+
73 while (node->parent != nullptr) {
74- node->parent->data.as_group.focused_child = node;
75- node->parent->data.as_group.group_focused = false;
76+ node->parent->updateTabBar();
77 node = node->parent;
78 }
79+ while (node2->parent != nullptr) {
80+ node2->parent->data.as_group.focused_child = node2;
81+ node2->parent->data.as_group.group_focused = false;
82+ node2->parent->updateTabBar();
83+ node2 = node2->parent;
84+ }
85
86 if (oldfocus != nullptr) {
87 oldfocus->updateDecos();
88+ while (oldfocus != nullptr) {
89+ oldfocus->updateTabBar();
90+ oldfocus = oldfocus->parent;
91+ }
92 }
93 }
94
95@@ -462,6 +507,20 @@ void Hy3Node::swapData(Hy3Node& a, Hy3Node& b) {
96 }
97 }
98
99+void Hy3Node::updateTabBar() {
100+ if (this->data.type == Hy3NodeData::Group) {
101+ auto& group = this->data.as_group;
102+
103+ if (group.layout == Hy3GroupLayout::Tabbed) {
104+ if (group.tab_bar == nullptr) group.tab_bar = &this->layout->tab_groups.emplace_back(*this);
105diff --git a/src/Hy3Layout.hpp b/src/Hy3Layout.hpp
106index 1dc286c5d9d582ba6a38827a70351f6116093994..1196471413edd4b9ae550e370eb16de9abfe8387 100644
107--- a/src/Hy3Layout.hpp
108+++ b/src/Hy3Layout.hpp
109@@ -27,14 +27,16 @@ struct Hy3GroupData {
110 std::list<Hy3Node*> children;
111 bool group_focused = true;
112 Hy3Node* focused_child = nullptr;
113- std::shared_ptr<Hy3TabGroup> tab_bar;
114+ Hy3TabGroup* tab_bar = nullptr;
115
116 bool hasChild(Hy3Node* child);
117
118 Hy3GroupData(Hy3GroupLayout layout);
119+ ~Hy3GroupData();
120
121 private:
122- Hy3GroupData(Hy3GroupData&&) = default;
123+ Hy3GroupData(Hy3GroupData&&);
124+ Hy3GroupData(const Hy3GroupData&) = delete;
125
126 friend class Hy3NodeData;
127 };
128@@ -81,6 +83,7 @@ struct Hy3Node {
129 void updateDecos();
130 void setHidden(bool hidden);
131 bool isUrgent();
132+ bool isIndirectlyFocused();
133 std::string getTitle();
134
135 bool operator==(const Hy3Node&) const;
136@@ -95,6 +98,9 @@ struct Hy3Node {
137 Hy3Node* intoGroup(Hy3GroupLayout);
138
139 static void swapData(Hy3Node&, Hy3Node&);
140+
141+private:
142+ void updateTabBar();
143 };
144
145 class Hy3Layout: public IHyprLayout {
146@@ -135,6 +141,7 @@ public:
147 static void renderHook(void*, std::any);
148
149 std::list<Hy3Node> nodes;
150+ std::list<Hy3TabGroup> tab_groups;
151 private:
152 struct {
153 bool started = false;
154diff --git a/src/TabGroup.cpp b/src/TabGroup.cpp
155index ce664f471055b88b3743825fc99f6d632bd20d25..5b3681b557965943889cfd29f1c1e9804e2c2c9b 100644
156--- a/src/TabGroup.cpp
157+++ b/src/TabGroup.cpp
158@@ -5,7 +5,7 @@
159 #include <hyprland/src/Compositor.hpp>
160 #include <cairo/cairo.h>
161
162-Hy3TabBarEntry::Hy3TabBarEntry(std::shared_ptr<Hy3TabGroup> tab_group, Hy3Node& node): tab_group(tab_group), node(node) {
163+Hy3TabBarEntry::Hy3TabBarEntry(Hy3TabBar& tab_bar, Hy3Node& node): tab_bar(tab_bar), node(node) {
164 this->offset.create(AVARTYPE_FLOAT, -1.0f, g_pConfigManager->getAnimationPropertyConfig("windowsMove"), nullptr, AVARDAMAGE_NONE);
165 this->width.create(AVARTYPE_FLOAT, -1.0f, g_pConfigManager->getAnimationPropertyConfig("windowsMove"), nullptr, AVARDAMAGE_NONE);
166
167@@ -24,25 +24,24 @@ bool Hy3TabBarEntry::operator==(const Hy3TabBarEntry& entry) const {
168 return this->node == entry.node;
169 }
170
171-void Hy3TabBarEntry::prepareTexture(float scale, Vector2D size) {
172+void Hy3TabBarEntry::prepareTexture(float scale, wlr_box& box) {
173 static const auto* rounding_setting = &HyprlandAPI::getConfigValue(PHANDLE, "plugin:hy3:tabs:rounding")->intValue;
174
175- auto width = size.x * scale;
176- auto height = size.y * scale;
177+ auto width = box.width;
178+ auto height = box.height;
179
180 auto rounding = std::min((double) *rounding_setting, std::min(width * 0.5, height * 0.5));
181
182- if (this->needs_redraw
183- || this->texture.m_iTexID == 0
184- || this->last_render_rounding == rounding
185- || this->last_render_scale == scale
186- || this->last_render_size == size
187- || true // todo
188+ if (this->texture.m_iTexID == 0
189+ || this->last_render_rounding != rounding
190+ || this->last_render_focused != focused
191+ || this->last_render_urgent != urgent
192+ || !wlr_box_equal(&this->last_render_box, &box)
193 ) {
194- this->needs_redraw = false;
195 this->last_render_rounding = rounding;
196- this->last_render_scale = scale;
197- this->last_render_size = size;
198+ this->last_render_focused = this->focused;
199+ this->last_render_urgent = this->urgent;
200+ this->last_render_box = box;
201
202 auto cairo_surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
203 auto cairo = cairo_create(cairo_surface);
204@@ -95,17 +94,6 @@ void Hy3TabBarEntry::prepareTexture(float scale, Vector2D size) {
205 }
206 }
207
208-void Hy3TabBarEntry::animateRemoval() {
209- if (this->width.goalf() == 0.0) return;
210- this->width = 0.0;
211-
212- // not removing the callback is required for soundness, as the animation will
213- // be deleted once the callback ends.
214- this->width.setCallbackOnEnd([this](void*) {
215- this->tab_group->bar.entries.remove(*this);
216- }, false);
217-}
218-
219 Hy3TabBar::Hy3TabBar() {
220 this->vertical_pos.create(AVARTYPE_FLOAT, 1.0f, g_pConfigManager->getAnimationPropertyConfig("windowsMove"), nullptr, AVARDAMAGE_NONE);
221 this->fade_opacity.create(AVARTYPE_FLOAT, 1.0f, g_pConfigManager->getAnimationPropertyConfig("windowsMove"), nullptr, AVARDAMAGE_NONE);
222@@ -120,6 +108,12 @@ Hy3TabBar::Hy3TabBar() {
223 this->fade_opacity = 1.0;
224 }
225
226+void Hy3TabBar::beginDestroy() {
227+ this->vertical_pos = 1.0;
228+ this->fade_opacity = 0.0;
229+ this->fade_opacity.setCallbackOnEnd([this](void*) { this->destroy = true; });
230+}
231+
232 void Hy3TabBar::focusNode(Hy3Node* node) {
233 this->focused_node = node;
234
235@@ -180,7 +174,7 @@ void Hy3TabBar::updateNodeList(std::list<Hy3Node*>& nodes) {
236 entry = *moved;
237 removed_entries.erase(moved);
238 } else {
239- entry = this->entries.emplace(entry, this->group.lock(), **node);
240+ entry = this->entries.emplace(entry, *this, **node);
241 }
242 }
243
244@@ -190,10 +184,7 @@ void Hy3TabBar::updateNodeList(std::list<Hy3Node*>& nodes) {
245 }
246
247 // set stats from node data
248- auto* root = *node;
249- while (root->parent != nullptr) root = root->parent;
250- auto* focused = root->getFocusedNode();
251- entry->focused = focused == *node;
252+ entry->focused = (*node)->isIndirectlyFocused();
253 entry->urgent = (*node)->isUrgent();
254
255 node = std::next(node);
256@@ -202,7 +193,8 @@ void Hy3TabBar::updateNodeList(std::list<Hy3Node*>& nodes) {
257
258diff --git a/src/TabGroup.hpp b/src/TabGroup.hpp
259index 7fa4ebd01b10efc445d74aa6ffc7c1df17b65e6c..e52667d031089a1728b54a6fa02cdd802c5203f1 100644
260--- a/src/TabGroup.hpp
261+++ b/src/TabGroup.hpp
262@@ -16,31 +16,31 @@ struct Hy3TabBarEntry {
263 std::string window_title;
264 bool focused = false;
265 bool urgent = false;
266- bool needs_redraw = false;
267 CTexture texture;
268 CAnimatedVariable offset; // offset 0, 0.0-1.0 of total bar
269 CAnimatedVariable width; // 0.0-1.0 of total bar
270- std::shared_ptr<Hy3TabGroup> tab_group;
271+ Hy3TabBar& tab_bar;
272 Hy3Node& node; // only used for comparioson. do not deref.
273- Vector2D last_render_size;
274- float last_render_scale = 0.0;
275+ wlr_box last_render_box;
276 float last_render_rounding = 0.0;
277+ bool last_render_focused = false;
278+ bool last_render_urgent = false;
279
280- Hy3TabBarEntry(std::shared_ptr<Hy3TabGroup>, Hy3Node&);
281+ Hy3TabBarEntry(Hy3TabBar&, Hy3Node&);
282 bool operator==(const Hy3Node&) const;
283 bool operator==(const Hy3TabBarEntry&) const;
284
285- void prepareTexture(float, Vector2D);
286-
287- void animateRemoval();
288+ void prepareTexture(float, wlr_box&);
289 };
290
291 class Hy3TabBar {
292 public:
293+ bool destroy = false;
294 CAnimatedVariable vertical_pos;
295 CAnimatedVariable fade_opacity;
296
297 Hy3TabBar();
298+ void beginDestroy();
299
300 void focusNode(Hy3Node*);
301 void updateNodeList(std::list<Hy3Node*>& nodes);
302@@ -48,7 +48,6 @@ public:
303 void setSize(Vector2D);
304
305 std::list<Hy3TabBarEntry> entries;
306- std::weak_ptr<Hy3TabGroup> group;
307 private:
308 Hy3Node* focused_node = nullptr;
309 CAnimatedVariable focus_opacity;
310@@ -56,6 +55,10 @@ private:
311 CAnimatedVariable focus_end;
312
313 Vector2D size;
314+
315+ // Tab bar entries take a reference to `this`.
316+ Hy3TabBar(Hy3TabBar&&) = delete;
317+ Hy3TabBar(const Hy3TabBar&) = delete;
318 };
319
320 class Hy3TabGroup {
321@@ -65,7 +68,7 @@ public:
322 CAnimatedVariable size;
323
324 // initialize a group with the given node. UB if node is not a group.
325- static std::shared_ptr<Hy3TabGroup> new_(Hy3Node&);
326+ Hy3TabGroup(Hy3Node&);
327
328 // update tab bar with node position and data. UB if node is not a group.
329 void updateWithGroup(Hy3Node&);
330@@ -73,7 +76,6 @@ public:
331 void renderTabBar();
332
333 private:
334- std::weak_ptr<Hy3TabGroup> self;
335 std::vector<CWindow*> stencil_windows;
336
337 Hy3TabGroup();