Diff
1diff --git a/src/Hy3Layout.cpp b/src/Hy3Layout.cpp
2index faaa283c29ca30d95277856ba6d221a0c38360e5..9e286fc79ed3793436a12d7d0568e0f84f0f069a 100644
3--- a/src/Hy3Layout.cpp
4+++ b/src/Hy3Layout.cpp
5@@ -199,13 +199,15 @@ void Hy3Node::recalcSizePosRecursive(bool force) {
6
7 bool Hy3Node::swallowGroups(Hy3Node* into) {
8 if (into == nullptr
9- || into->parent == nullptr
10 || into->data.type != Hy3NodeData::Group
11 || into->data.as_group.children.size() != 1)
12 return false;
13
14 auto* child = into->data.as_group.children.front();
15
16+ // a lot of segfaulting happens once the assumption that the root node is a group is wrong.
17+ if (into->parent == nullptr && child->data.type != Hy3NodeData::Group) return false;
18+
19 Debug::log(LOG, "Swallowing %p into %p", child, into);
20 Hy3Node::swapData(*into, *child);
21 into->layout->nodes.remove(*child);
22@@ -961,7 +963,7 @@ void Hy3Layout::shiftFocus(CWindow* window, ShiftDirection direction) {
23 if (node == nullptr) return;
24
25 Hy3Node* target;
26- if ((target = Hy3Layout::shiftOrGetFocus(*node, direction, false))) {
27+ if ((target = this->shiftOrGetFocus(*node, direction, false))) {
28 g_pCompositor->focusWindow(target->data.as_window);
29 }
30 }
31@@ -972,7 +974,7 @@ void Hy3Layout::shiftWindow(CWindow* window, ShiftDirection direction) {
32 if (node == nullptr) return;
33
34
35- Hy3Layout::shiftOrGetFocus(*node, direction, true);
36+ this->shiftOrGetFocus(*node, direction, true);
37 }
38
39 bool shiftIsForward(ShiftDirection direction) {
40@@ -1009,7 +1011,28 @@ Hy3Node* Hy3Layout::shiftOrGetFocus(Hy3Node& node, ShiftDirection direction, boo
41 }
42
43 if (break_parent->parent == nullptr) {
44- return nullptr;
45+ if (!shift) return nullptr;
46+
47+ // if we haven't gone up any levels and the group is in the same direction
48+ // there's no reason to wrap the root group.
49+ if (shiftMatchesLayout(group.layout, direction)) break;
50+
51+ // wrap the root group in another group
52+ this->nodes.push_back({
53+ .parent = break_parent,
54+ .data = shiftIsVertical(direction) ? Hy3GroupLayout::SplitV : Hy3GroupLayout::SplitH,
55+ .position = break_parent->position,
56+ .size = break_parent->size,
57+ .workspace_id = break_parent->workspace_id,
58+ .layout = this,
59+ });
60+
61+ auto* newChild = &this->nodes.back();
62+ Hy3Node::swapData(*break_parent, *newChild);
63+ break_parent->data.as_group.children.push_back(newChild);
64+ break_parent->data.as_group.lastFocusedChild = newChild;
65+ break_origin = newChild;
66+ break;
67 } else {
68 break_origin = break_parent;
69 break_parent = break_origin->parent;
70diff --git a/src/Hy3Layout.hpp b/src/Hy3Layout.hpp
71index 7eb2cf00c9b59291fd9cf6afb6c171d52944527e..a4d33843556e36629e2b5ebd0d1cac5393f6d520 100644
72--- a/src/Hy3Layout.hpp
73+++ b/src/Hy3Layout.hpp
74@@ -125,7 +125,7 @@ private:
75
76 // if shift is true, shift the window in the given direction, returning nullptr,
77 // if shift is false, return the window in the given direction or nullptr.
78- static Hy3Node* shiftOrGetFocus(Hy3Node&, ShiftDirection, bool);
79+ Hy3Node* shiftOrGetFocus(Hy3Node&, ShiftDirection, bool);
80
81 friend struct Hy3Node;
82 };