0bdf28f3bc70b099ee61bd151531f179b6e40413
- 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 c0217fcea010ad0b49b7d83884378da398d47ce4..6782798eeedf33e4d97c42c84ff0aee9a6accbfe 100644
3--- a/src/Hy3Layout.cpp
4+++ b/src/Hy3Layout.cpp
5@@ -1,14 +1,5 @@
6 #include "Hy3Layout.hpp"
7-#include "src/Window.hpp"
8-#include "src/debug/Log.hpp"
9-#include "src/helpers/Vector2D.hpp"
10-#include "src/helpers/Workspace.hpp"
11-#include "src/managers/XWaylandManager.hpp"
12-#include "src/managers/input/InputManager.hpp"
13-#include "src/render/Renderer.hpp"
14-#include <cairo/cairo.h>
15-#include <ctime>
16-#include <memory>
17+
18 #include <src/Compositor.hpp>
19
20 Hy3GroupData::Hy3GroupData(Hy3GroupLayout layout): layout(layout) {}
21@@ -23,6 +14,8 @@ Hy3NodeData::Hy3NodeData(Hy3GroupData group): type(Hy3NodeData::Group) {
22 new(&this->as_group) Hy3GroupData(std::move(group));
23 }
24
25+Hy3NodeData::Hy3NodeData(Hy3GroupLayout layout): Hy3NodeData(Hy3GroupData(layout)) {}
26+
27 Hy3NodeData::~Hy3NodeData() {
28 switch (this->type) {
29 case Hy3NodeData::Window:
30@@ -80,6 +73,18 @@ Hy3NodeData& Hy3NodeData::operator=(const Hy3NodeData& from) {
31 return *this;
32 }
33
34+Hy3NodeData& Hy3NodeData::operator=(CWindow* window) {
35+ *this = Hy3NodeData(window);
36+
37+ return *this;
38+}
39+
40+Hy3NodeData& Hy3NodeData::operator=(Hy3GroupLayout layout) {
41+ *this = Hy3NodeData(layout);
42+
43+ return *this;
44+}
45+
46 bool Hy3NodeData::operator==(const Hy3NodeData& rhs) const {
47 if (this->type != rhs.type) return false;
48 switch (this->type) {
49@@ -185,6 +190,59 @@ void Hy3Node::recalcSizePosRecursive(bool force) {
50 }
51 }
52
53+bool Hy3GroupData::hasChild(Hy3Node* node) {
54+ Debug::log(LOG, "Searching for child %p of %p", this, node);
55+ for (auto child: this->children) {
56+ if (child == node) return true;
57+
58+ if (child->data.type == Hy3NodeData::Group) {
59+ if (child->data.as_group.hasChild(node)) return true;
60+ }
61+ }
62+
63+ return false;
64+}
65+
66+bool Hy3Node::removeChild(Hy3Node* child, bool childSwallows) {
67+ if (this->data.type != Hy3NodeData::Group) return false;
68+ Hy3GroupData& group = this->data.as_group;
69+
70+ if (group.children.remove(child)) {
71+ if (group.children.empty()) {
72+ Debug::log(LOG, "Group %p is empty, removing", this);
73+ this->parent->removeChild(this, childSwallows);
74+ this->layout->nodes.remove(*this);
75+ } else if (childSwallows && group.children.size() == 1) {
76+ auto remaining = group.children.front();
77+ Debug::log(LOG, "Group %p has only one child(%p), swallowing", this, remaining);
78+ swapNodeData(*this, *remaining);
79+ this->layout->nodes.remove(*remaining);
80+ }
81+
82+ return true;
83+ }
84+
85+ return false;
86+}
87+
88+void swapNodeData(Hy3Node& a, Hy3Node& b) {
89+ Hy3NodeData aData = std::move(a.data);
90+ a.data = b.data;
91+ b.data = aData;
92+
93+ if (a.data.type == Hy3NodeData::Group) {
94+ for (auto child: a.data.as_group.children) {
95+ child->parent = &a;
96+ }
97+ }
98+
99+ if (b.data.type == Hy3NodeData::Group) {
100+ for (auto child: b.data.as_group.children) {
101+ child->parent = &b;
102+ }
103+ }
104+}
105diff --git a/src/Hy3Layout.hpp b/src/Hy3Layout.hpp
106index c6907cb45544d0fcc6e6d99b8103a336d5ea1f18..37aab20603be1236c3d7e2e54d5d67c78d9a1acf 100644
107--- a/src/Hy3Layout.hpp
108+++ b/src/Hy3Layout.hpp
109@@ -12,14 +12,32 @@ enum class Hy3GroupLayout {
110 Tabbed,
111 };
112
113+enum class ShiftDirection {
114+ Left,
115+ Up,
116+ Down,
117+ Right,
118+};
119+
120 struct Hy3GroupData {
121 Hy3GroupLayout layout = Hy3GroupLayout::SplitH;
122 std::list<Hy3Node*> children;
123
124+ bool hasChild(Hy3Node* child);
125+
126 Hy3GroupData(Hy3GroupLayout layout);
127+
128+private:
129+ Hy3GroupData(Hy3GroupData&&) = default;
130+ Hy3GroupData(const Hy3GroupData&) = default;
131+
132+ friend class Hy3NodeData;
133 };
134
135-struct Hy3NodeData {
136+void swapNodeData(Hy3Node& a, Hy3Node& b);
137+
138+class Hy3NodeData {
139+public:
140 enum { Group, Window } type;
141 union {
142 Hy3GroupData as_group;
143@@ -29,12 +47,19 @@ struct Hy3NodeData {
144 bool operator==(const Hy3NodeData&) const;
145
146 Hy3NodeData();
147- Hy3NodeData(CWindow* window);
148- Hy3NodeData(Hy3GroupData group);
149+ ~Hy3NodeData();
150+ Hy3NodeData(CWindow*);
151+ Hy3NodeData(Hy3GroupLayout);
152+ Hy3NodeData& operator=(CWindow*);
153+ Hy3NodeData& operator=(Hy3GroupLayout);
154+
155+ //private: - I give up, C++ wins
156+ Hy3NodeData(Hy3GroupData);
157 Hy3NodeData(const Hy3NodeData&);
158 Hy3NodeData(Hy3NodeData&&);
159 Hy3NodeData& operator=(const Hy3NodeData&);
160- ~Hy3NodeData();
161+
162+ friend void swapNodeData(Hy3Node&, Hy3Node&);
163 };
164
165 struct Hy3Node {
166@@ -48,6 +73,11 @@ struct Hy3Node {
167 Hy3Layout* layout = nullptr;
168
169 void recalcSizePosRecursive(bool force = false);
170+ // remove a child node, returns true on success.
171+ // fails if not a group
172+ // if only a single child node remains && childSwallows, replace this group with said child.
173+ // if no children remain, remove this node from its parent.
174+ bool removeChild(Hy3Node* child, bool childSwallows = false);
175
176 bool operator==(const Hy3Node&) const;
177 };
178@@ -72,9 +102,12 @@ public:
179 virtual void onEnable();
180 virtual void onDisable();
181
182+ void makeGroupOn(CWindow*, Hy3GroupLayout);
183+ void shiftWindow(CWindow*, ShiftDirection);
184+
185+ Hy3Node* findCommonParentNode(Hy3Node&, Hy3Node&);
186+
187 private:
188- // std::list is used over std::vector because it does not invalidate references
189- // when mutated.
190 std::list<Hy3Node> nodes;
191 CWindow* lastActiveWindow = nullptr;
192
193diff --git a/src/main.cpp b/src/main.cpp
194index 350e61ca9c8999d0fc9d305a1b87ad2fb1ba13ab..2bda5ec22e9ae90bee7707f2948537a4c190c38d 100644
195--- a/src/main.cpp
196+++ b/src/main.cpp
197@@ -10,28 +10,44 @@ APICALL EXPORT std::string PLUGIN_API_VERSION() {
198 return HYPRLAND_API_VERSION;
199 }
200
201-void splith(std::string) {
202- SLayoutMessageHeader header;
203- header.pWindow = g_pCompositor->m_pLastWindow;
204+// return a window if a window action makes sense now
205+CWindow* window_for_action() {
206+ if (g_pLayoutManager->getCurrentLayout() != g_Hy3Layout.get()) return nullptr;
207
208- if (!header.pWindow) return;
209+ auto* window = g_pCompositor->m_pLastWindow;
210
211- const auto workspace = g_pCompositor->getWorkspaceByID(header.pWindow->m_iWorkspaceID);
212- if (workspace->m_bHasFullscreenWindow) return;
213+ if (!window) return nullptr;
214
215- g_pLayoutManager->getCurrentLayout()->layoutMessage(header, "splith");
216-}
217+ const auto workspace = g_pCompositor->getWorkspaceByID(window->m_iWorkspaceID);
218+ if (workspace->m_bHasFullscreenWindow) return nullptr;
219
220-void splitv(std::string) {
221- SLayoutMessageHeader header;
222- header.pWindow = g_pCompositor->m_pLastWindow;
223+ return window;
224+}
225
226- if (!header.pWindow) return;
227+void dispatch_makegroup(std::string arg) {
228+ CWindow* window = window_for_action();
229+ if (window == nullptr) return;
230
231- const auto workspace = g_pCompositor->getWorkspaceByID(header.pWindow->m_iWorkspaceID);
232- if (workspace->m_bHasFullscreenWindow) return;
233+ if (arg == "h") {
234+ g_Hy3Layout->makeGroupOn(window, Hy3GroupLayout::SplitH);
235+ } else if (arg == "v") {
236+ g_Hy3Layout->makeGroupOn(window, Hy3GroupLayout::SplitV);
237+ }
238+}
239
240- g_pLayoutManager->getCurrentLayout()->layoutMessage(header, "splitv");
241+void dispatch_movewindow(std::string arg) {
242+ CWindow* window = window_for_action();
243+ if (window == nullptr) return;
244+
245+ if (arg == "l") {
246+ g_Hy3Layout->shiftWindow(window, ShiftDirection::Left);
247+ } else if (arg == "u") {
248+ g_Hy3Layout->shiftWindow(window, ShiftDirection::Up);
249+ } else if (arg == "d") {
250+ g_Hy3Layout->shiftWindow(window, ShiftDirection::Down);
251+ } else if (arg == "r") {
252+ g_Hy3Layout->shiftWindow(window, ShiftDirection::Right);
253+ }
254 }
255
256 APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) {
257@@ -40,8 +56,8 @@ APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) {
258 g_Hy3Layout = std::make_unique<Hy3Layout>();
259 HyprlandAPI::addLayout(PHANDLE, "hy3", g_Hy3Layout.get());
260
261- HyprlandAPI::addDispatcher(PHANDLE, "splith", splith);
262- HyprlandAPI::addDispatcher(PHANDLE, "splitv", splitv);
263+ HyprlandAPI::addDispatcher(PHANDLE, "hy3_makegroup", dispatch_makegroup);
264+ HyprlandAPI::addDispatcher(PHANDLE, "hy3_movewindow", dispatch_movewindow);
265
266 return {"hy3", "i3 like layout for hyprland", "outfoxxed", "0.1"};
267 }