From f72c5d0b480bf0ac77b0bf7e637d44be46045d63 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Wed, 10 May 2023 00:42:53 -0700 Subject: [PATCH] Add `once` option to movewindow --- README.md | 5 +++-- src/Hy3Layout.cpp | 24 +++++++++++++++++------- src/Hy3Layout.hpp | 5 +++-- src/main.cpp | 35 ++++++++++++++++++----------------- 4 files changed, 41 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index a89f069..66a1146 100644 --- a/README.md +++ b/README.md @@ -33,8 +33,9 @@ You can use `hy3:makegroup` to create a new split. ### Dispatcher list - `hy3:makegroup, ` - make a vertical or horizontal split - - `hy3:movefocus, ` - move the focus left, up, down, or right - - `hy3:movewindow, ` - move a window left, up, down, or right + - `hy3:movefocus, ` - move the focus left, up, down, or right + - `hy3:movewindow, [, once]` - move a window left, up, down, or right + - `once` - only move directly to the neighboring group, without moving into any of its subgroups - `hy3:raisefocus` - raise the active focus one level - `hy3:debugnodes` - print the node tree into the hyprland log diff --git a/src/Hy3Layout.cpp b/src/Hy3Layout.cpp index 1237db3..9d8b4bd 100644 --- a/src/Hy3Layout.cpp +++ b/src/Hy3Layout.cpp @@ -1127,26 +1127,24 @@ void Hy3Layout::makeOppositeGroupOn(Hy3Node* node) { } } -Hy3Node* shiftOrGetFocus(Hy3Node& node, ShiftDirection direction, bool shift); - void Hy3Layout::shiftFocus(int workspace, ShiftDirection direction) { auto* node = this->getWorkspaceFocusedNode(workspace); Debug::log(LOG, "ShiftFocus %p %d", node, direction); if (node == nullptr) return; Hy3Node* target; - if ((target = this->shiftOrGetFocus(*node, direction, false))) { + if ((target = this->shiftOrGetFocus(*node, direction, false, false))) { g_pCompositor->focusWindow(target->data.as_window); } } -void Hy3Layout::shiftWindow(int workspace, ShiftDirection direction) { +void Hy3Layout::shiftWindow(int workspace, ShiftDirection direction, bool once) { auto* node = this->getWorkspaceFocusedNode(workspace); Debug::log(LOG, "ShiftWindow %p %d", node, direction); if (node == nullptr) return; - this->shiftOrGetFocus(*node, direction, true); + this->shiftOrGetFocus(*node, direction, true, once); } bool shiftIsForward(ShiftDirection direction) { @@ -1162,16 +1160,20 @@ bool shiftMatchesLayout(Hy3GroupLayout layout, ShiftDirection direction) { || (layout != Hy3GroupLayout::SplitV && !shiftIsVertical(direction)); } -Hy3Node* Hy3Layout::shiftOrGetFocus(Hy3Node& node, ShiftDirection direction, bool shift) { +Hy3Node* Hy3Layout::shiftOrGetFocus(Hy3Node& node, ShiftDirection direction, bool shift, bool once) { auto* break_origin = &node; auto* break_parent = break_origin->parent; + auto has_broken_once = false; + // break parents until we hit a container oriented the same way as the shift direction while (true) { if (break_parent == nullptr) return nullptr; auto& group = break_parent->data.as_group; // must be a group in order to be a parent + if (has_broken_once) break; + if (shiftMatchesLayout(group.layout, direction)) { // group has the correct orientation @@ -1182,6 +1184,8 @@ Hy3Node* Hy3Layout::shiftOrGetFocus(Hy3Node& node, ShiftDirection direction, boo break; } + has_broken_once = true; + if (break_parent->parent == nullptr) { if (!shift) return nullptr; @@ -1233,7 +1237,7 @@ Hy3Node* Hy3Layout::shiftOrGetFocus(Hy3Node& node, ShiftDirection direction, boo if (shiftIsForward(direction)) iter = std::next(iter); else iter = std::prev(iter); - if ((*iter)->data.type == Hy3NodeData::Window) { + if ((*iter)->data.type == Hy3NodeData::Window || (shift && once && has_broken_once)) { if (shift) { if (target_group == node.parent) { if (shiftIsForward(direction)) insert = std::next(iter); @@ -1270,6 +1274,12 @@ Hy3Node* Hy3Layout::shiftOrGetFocus(Hy3Node& node, ShiftDirection direction, boo } } + if (shift && once) { + if (shift_after) insert = std::next(iter); + else insert = iter; + break; + } + if ((*iter)->data.type == Hy3NodeData::Window) { if (shift) { if (shift_after) insert = std::next(iter); diff --git a/src/Hy3Layout.hpp b/src/Hy3Layout.hpp index 02637af..7b34ae6 100644 --- a/src/Hy3Layout.hpp +++ b/src/Hy3Layout.hpp @@ -117,7 +117,7 @@ public: void makeOppositeGroupOnWorkspace(int); void makeGroupOn(Hy3Node*, Hy3GroupLayout); void makeOppositeGroupOn(Hy3Node*); - void shiftWindow(int, ShiftDirection); + void shiftWindow(int, ShiftDirection, bool); void shiftFocus(int, ShiftDirection); void raiseFocus(int); @@ -140,7 +140,8 @@ private: // if shift is true, shift the window in the given direction, returning nullptr, // if shift is false, return the window in the given direction or nullptr. - Hy3Node* shiftOrGetFocus(Hy3Node&, ShiftDirection, bool); + // if once is true, only one group will be broken out of / into + Hy3Node* shiftOrGetFocus(Hy3Node&, ShiftDirection, bool, bool); friend struct Hy3Node; }; diff --git a/src/main.cpp b/src/main.cpp index 6c6c476..f299fe9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,3 +1,5 @@ +#include + #include #include @@ -48,18 +50,23 @@ void dispatch_makegroup(std::string arg) { } } -void dispatch_movewindow(std::string arg) { +std::optional parseShiftArg(std::string arg) { + if (arg == "l" || arg == "left") return ShiftDirection::Left; + else if (arg == "r" || arg == "right") return ShiftDirection::Right; + else if (arg == "u" || arg == "up") return ShiftDirection::Up; + else if (arg == "d" || arg == "down") return ShiftDirection::Down; + else return {}; +} + +void dispatch_movewindow(std::string value) { int workspace = workspace_for_action(); if (workspace < 0) return; - if (arg == "l") { - g_Hy3Layout->shiftWindow(workspace, ShiftDirection::Left); - } else if (arg == "u") { - g_Hy3Layout->shiftWindow(workspace, ShiftDirection::Up); - } else if (arg == "d") { - g_Hy3Layout->shiftWindow(workspace, ShiftDirection::Down); - } else if (arg == "r") { - g_Hy3Layout->shiftWindow(workspace, ShiftDirection::Right); + auto args = CVarList(value); + + if (auto shift = parseShiftArg(args[0])) { + auto once = args[1] == "once"; + g_Hy3Layout->shiftWindow(workspace, shift.value(), once); } } @@ -67,14 +74,8 @@ void dispatch_movefocus(std::string arg) { int workspace = workspace_for_action(); if (workspace < 0) return; - if (arg == "l") { - g_Hy3Layout->shiftFocus(workspace, ShiftDirection::Left); - } else if (arg == "u") { - g_Hy3Layout->shiftFocus(workspace, ShiftDirection::Up); - } else if (arg == "d") { - g_Hy3Layout->shiftFocus(workspace, ShiftDirection::Down); - } else if (arg == "r") { - g_Hy3Layout->shiftFocus(workspace, ShiftDirection::Right); + if (auto shift = parseShiftArg(arg)) { + g_Hy3Layout->shiftFocus(workspace, shift.value()); } }