mirror of
https://github.com/Trensa-Organization/hy3.git
synced 2025-03-15 18:53:40 +01:00
Keep track of window focus similarly to i3
This commit is contained in:
parent
32cfd86d13
commit
e1fe28f39f
2 changed files with 93 additions and 58 deletions
|
@ -110,7 +110,11 @@ void Hy3Node::recalcSizePosRecursive(bool force) {
|
||||||
auto* group = &this->data.as_group;
|
auto* group = &this->data.as_group;
|
||||||
|
|
||||||
if (group->children.size() == 1 && this->parent != nullptr) {
|
if (group->children.size() == 1 && this->parent != nullptr) {
|
||||||
auto& child = group->children.front();
|
auto child = group->children.front();
|
||||||
|
|
||||||
|
if (child == this) {
|
||||||
|
Debug::log(ERR, "a group (%p) has become its own child", this);
|
||||||
|
}
|
||||||
|
|
||||||
double distortOut;
|
double distortOut;
|
||||||
double distortIn;
|
double distortIn;
|
||||||
|
@ -203,28 +207,6 @@ bool Hy3GroupData::hasChild(Hy3Node* node) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Hy3Node::removeChild(Hy3Node* child, bool childSwallows) {
|
|
||||||
if (this->data.type != Hy3NodeData::Group) return false;
|
|
||||||
Hy3GroupData& group = this->data.as_group;
|
|
||||||
|
|
||||||
if (group.children.remove(child)) {
|
|
||||||
if (group.children.empty()) {
|
|
||||||
Debug::log(LOG, "Group %p is empty, removing", this);
|
|
||||||
this->parent->removeChild(this, childSwallows);
|
|
||||||
this->layout->nodes.remove(*this);
|
|
||||||
} else if (childSwallows && group.children.size() == 1) {
|
|
||||||
auto remaining = group.children.front();
|
|
||||||
Debug::log(LOG, "Group %p has only one child(%p), swallowing", this, remaining);
|
|
||||||
swapNodeData(*this, *remaining);
|
|
||||||
this->layout->nodes.remove(*remaining);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void swapNodeData(Hy3Node& a, Hy3Node& b) {
|
void swapNodeData(Hy3Node& a, Hy3Node& b) {
|
||||||
Hy3NodeData aData = std::move(a.data);
|
Hy3NodeData aData = std::move(a.data);
|
||||||
a.data = b.data;
|
a.data = b.data;
|
||||||
|
@ -435,6 +417,7 @@ void Hy3Layout::onWindowCreatedTiling(CWindow* window) {
|
||||||
Debug::log(LOG, "open new window %p(node: %p:%p) on winodow %p in %p", window, &node, node.data.as_window, opening_after, opening_into);
|
Debug::log(LOG, "open new window %p(node: %p:%p) on winodow %p in %p", window, &node, node.data.as_window, opening_after, opening_into);
|
||||||
|
|
||||||
opening_into->recalcSizePosRecursive();
|
opening_into->recalcSizePosRecursive();
|
||||||
|
Debug::log(LOG, "opening_into (%p) contains new child (%p)? %d", opening_into, &node, opening_into->data.as_group.hasChild(&node));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Hy3Layout::onWindowRemovedTiling(CWindow* window) {
|
void Hy3Layout::onWindowRemovedTiling(CWindow* window) {
|
||||||
|
@ -455,39 +438,46 @@ void Hy3Layout::onWindowRemovedTiling(CWindow* window) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* parent = node->parent;
|
auto* parent = node->parent;
|
||||||
|
auto* group = &parent->data.as_group;
|
||||||
|
|
||||||
parent->data.as_group.children.remove(node);
|
group->children.remove(node);
|
||||||
this->nodes.remove(*node);
|
this->nodes.remove(*node);
|
||||||
|
|
||||||
while (parent != nullptr && parent->data.as_group.children.empty()) {
|
while (parent->parent != nullptr && group->children.empty()) {
|
||||||
auto* child = parent;
|
auto* child = parent;
|
||||||
parent = parent->parent;
|
parent = parent->parent;
|
||||||
|
group = &parent->data.as_group;
|
||||||
|
|
||||||
|
if (group->children.size() > 2) {
|
||||||
|
auto iter = std::find(group->children.begin(), group->children.end(), child);
|
||||||
|
if (iter == group->children.begin()) {
|
||||||
|
group->lastFocusedChild = *std::next(iter);
|
||||||
|
} else {
|
||||||
|
group->lastFocusedChild = *std::prev(iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parent->data.as_group.children.remove(child);
|
||||||
|
|
||||||
|
if (group->children.size() == 1) {
|
||||||
|
group->lastFocusedChild = group->children.front();
|
||||||
|
}
|
||||||
|
|
||||||
if (parent != nullptr) parent->data.as_group.children.remove(child);
|
|
||||||
this->nodes.remove(*child);
|
this->nodes.remove(*child);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parent != nullptr) parent->recalcSizePosRecursive();
|
if (parent != nullptr) {
|
||||||
|
parent->recalcSizePosRecursive();
|
||||||
|
auto* focus = group->lastFocusedChild;
|
||||||
|
while (focus->data.type == Hy3NodeData::Group) focus = focus->data.as_group.lastFocusedChild;
|
||||||
|
g_pCompositor->focusWindow(focus->data.as_window);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Hy3Layout::onWindowFocusChange(CWindow* window) {
|
void Hy3Layout::onWindowFocusChange(CWindow* window) {
|
||||||
Debug::log(LOG, "Switched windows from %p to %p", this->lastActiveWindow, window);
|
Debug::log(LOG, "Switched windows from %p to %p", this->lastActiveWindow, window);
|
||||||
auto* node = this->getNodeFromWindow(this->lastActiveWindow);
|
auto* node = this->getNodeFromWindow(this->lastActiveWindow);
|
||||||
|
if (node != nullptr) Debug::log(LOG, "Switched focused node to %p (parent: %p)", node, node->parent);
|
||||||
while (node != nullptr
|
|
||||||
&& node->parent != nullptr
|
|
||||||
&& node->parent->parent != nullptr
|
|
||||||
&& node->parent->data.as_group.children.size() == 1)
|
|
||||||
{
|
|
||||||
auto parent = node->parent;
|
|
||||||
swapNodeData(*parent, *node);
|
|
||||||
this->nodes.remove(*node);
|
|
||||||
node = parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node != nullptr) {
|
|
||||||
node->recalcSizePosRecursive();
|
|
||||||
}
|
|
||||||
|
|
||||||
this->lastActiveWindow = window;
|
this->lastActiveWindow = window;
|
||||||
}
|
}
|
||||||
|
@ -696,23 +686,32 @@ Hy3Node* shiftOrGetFocus(Hy3Node& node, ShiftDirection direction, bool shift) {
|
||||||
|
|
||||||
if (group_data.children.empty()) return nullptr; // in theory this would never happen
|
if (group_data.children.empty()) return nullptr; // in theory this would never happen
|
||||||
|
|
||||||
bool layout_matches = ((group_data.layout == Hy3GroupLayout::SplitH || group_data.layout == Hy3GroupLayout::Tabbed)
|
bool shift_after = false;
|
||||||
|
|
||||||
|
if (((group_data.layout == Hy3GroupLayout::SplitH || group_data.layout == Hy3GroupLayout::Tabbed)
|
||||||
&& (direction == ShiftDirection::Left || direction == ShiftDirection::Right))
|
&& (direction == ShiftDirection::Left || direction == ShiftDirection::Right))
|
||||||
|| (group_data.layout == Hy3GroupLayout::SplitV
|
|| (group_data.layout == Hy3GroupLayout::SplitV
|
||||||
&& (direction == ShiftDirection::Up || direction == ShiftDirection::Down));
|
&& (direction == ShiftDirection::Up || direction == ShiftDirection::Down)))
|
||||||
|
{
|
||||||
if (layout_matches) {
|
|
||||||
// if the group has the same orientation as movement pick the last/first child based
|
// if the group has the same orientation as movement pick the last/first child based
|
||||||
// on movement direction
|
// on movement direction
|
||||||
if (shiftIsForward(direction)) iter = group_data.children.begin();
|
if (shiftIsForward(direction)) iter = group_data.children.begin();
|
||||||
else iter = std::prev(group_data.children.end());
|
else {
|
||||||
|
iter = std::prev(group_data.children.end());
|
||||||
|
shift_after = true;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
iter = group_data.children.begin();
|
if (group_data.lastFocusedChild != nullptr) {
|
||||||
|
iter = std::find(group_data.children.begin(), group_data.children.end(), group_data.lastFocusedChild);
|
||||||
|
shift_after = true;
|
||||||
|
} else {
|
||||||
|
iter = group_data.children.begin();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((*iter)->data.type == Hy3NodeData::Window) {
|
if ((*iter)->data.type == Hy3NodeData::Window) {
|
||||||
if (shift) {
|
if (shift) {
|
||||||
if (layout_matches && !shiftIsForward(direction)) insert = std::next(iter);
|
if (shift_after) insert = std::next(iter);
|
||||||
else insert = iter;
|
else insert = iter;
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
|
@ -734,12 +733,52 @@ Hy3Node* shiftOrGetFocus(Hy3Node& node, ShiftDirection direction, bool shift) {
|
||||||
target_group->recalcSizePosRecursive();
|
target_group->recalcSizePosRecursive();
|
||||||
} else {
|
} else {
|
||||||
auto* old_parent = node.parent;
|
auto* old_parent = node.parent;
|
||||||
auto* common_parent = findCommonParentNode(*target_group, node);
|
auto* old_group = &old_parent->data.as_group;
|
||||||
|
|
||||||
|
if (old_group->children.size() > 2) {
|
||||||
|
auto iter = std::find(old_group->children.begin(), old_group->children.end(), &node);
|
||||||
|
if (iter == old_group->children.begin()) {
|
||||||
|
old_group->lastFocusedChild = *std::next(iter);
|
||||||
|
} else {
|
||||||
|
old_group->lastFocusedChild = *std::prev(iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
node.parent = target_group;
|
node.parent = target_group;
|
||||||
node.size_ratio = 1.0;
|
node.size_ratio = 1.0;
|
||||||
target_group->data.as_group.children.insert(insert, &node);
|
target_group->data.as_group.children.insert(insert, &node);
|
||||||
old_parent->removeChild(&node, true);
|
|
||||||
common_parent->recalcSizePosRecursive();
|
// must happen AFTER `insert` is used
|
||||||
|
old_group->children.remove(&node);
|
||||||
|
if (old_group->children.empty()) {
|
||||||
|
while (old_parent->parent != nullptr && old_parent->data.as_group.children.empty()) {
|
||||||
|
auto* child = old_parent;
|
||||||
|
old_parent = old_parent->parent;
|
||||||
|
old_group = &old_parent->data.as_group;
|
||||||
|
|
||||||
|
if (old_group->children.size() > 2) {
|
||||||
|
auto iter = std::find(old_group->children.begin(), old_group->children.end(), child);
|
||||||
|
if (iter == old_group->children.begin()) {
|
||||||
|
old_group->lastFocusedChild = *std::next(iter);
|
||||||
|
} else {
|
||||||
|
old_group->lastFocusedChild = *std::prev(iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
old_parent->data.as_group.children.remove(child);
|
||||||
|
|
||||||
|
if (old_group->children.size() == 1) {
|
||||||
|
old_group->lastFocusedChild = old_group->children.front();
|
||||||
|
}
|
||||||
|
|
||||||
|
old_parent->layout->nodes.remove(*child);
|
||||||
|
}
|
||||||
|
} else if (old_group->children.size() == 1) {
|
||||||
|
old_group->lastFocusedChild = old_group->children.front();
|
||||||
|
}
|
||||||
|
|
||||||
|
old_parent->recalcSizePosRecursive();
|
||||||
|
target_group->recalcSizePosRecursive();
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
@ -22,6 +22,7 @@ enum class ShiftDirection {
|
||||||
struct Hy3GroupData {
|
struct Hy3GroupData {
|
||||||
Hy3GroupLayout layout = Hy3GroupLayout::SplitH;
|
Hy3GroupLayout layout = Hy3GroupLayout::SplitH;
|
||||||
std::list<Hy3Node*> children;
|
std::list<Hy3Node*> children;
|
||||||
|
Hy3Node* lastFocusedChild = nullptr;
|
||||||
|
|
||||||
bool hasChild(Hy3Node* child);
|
bool hasChild(Hy3Node* child);
|
||||||
|
|
||||||
|
@ -73,11 +74,6 @@ struct Hy3Node {
|
||||||
Hy3Layout* layout = nullptr;
|
Hy3Layout* layout = nullptr;
|
||||||
|
|
||||||
void recalcSizePosRecursive(bool force = false);
|
void recalcSizePosRecursive(bool force = false);
|
||||||
// remove a child node, returns true on success.
|
|
||||||
// fails if not a group
|
|
||||||
// if only a single child node remains && childSwallows, replace this group with said child.
|
|
||||||
// if no children remain, remove this node from its parent.
|
|
||||||
bool removeChild(Hy3Node* child, bool childSwallows = false);
|
|
||||||
|
|
||||||
bool operator==(const Hy3Node&) const;
|
bool operator==(const Hy3Node&) const;
|
||||||
};
|
};
|
||||||
|
@ -106,8 +102,8 @@ public:
|
||||||
void shiftWindow(CWindow*, ShiftDirection);
|
void shiftWindow(CWindow*, ShiftDirection);
|
||||||
void shiftFocus(CWindow*, ShiftDirection);
|
void shiftFocus(CWindow*, ShiftDirection);
|
||||||
|
|
||||||
private:
|
|
||||||
std::list<Hy3Node> nodes;
|
std::list<Hy3Node> nodes;
|
||||||
|
private:
|
||||||
CWindow* lastActiveWindow = nullptr;
|
CWindow* lastActiveWindow = nullptr;
|
||||||
|
|
||||||
int getWorkspaceNodeCount(const int&);
|
int getWorkspaceNodeCount(const int&);
|
||||||
|
|
Loading…
Add table
Reference in a new issue