Add once option to movewindow

This commit is contained in:
outfoxxed 2023-05-10 00:42:53 -07:00
parent f12993ecf0
commit f72c5d0b48
No known key found for this signature in database
GPG key ID: 4C88A185FB89301E
4 changed files with 41 additions and 28 deletions

View file

@ -33,8 +33,9 @@ You can use `hy3:makegroup` to create a new split.
### Dispatcher list ### Dispatcher list
- `hy3:makegroup, <h | v | opposite>` - make a vertical or horizontal split - `hy3:makegroup, <h | v | opposite>` - make a vertical or horizontal split
- `hy3:movefocus, <l | u | d | r>` - move the focus left, up, down, or right - `hy3:movefocus, <l | u | d | r | left | down | up | right>` - move the focus left, up, down, or right
- `hy3:movewindow, <l | u | d | r>` - move a window left, up, down, or right - `hy3:movewindow, <l | u | d | r | left | down | up | right> [, 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:raisefocus` - raise the active focus one level
- `hy3:debugnodes` - print the node tree into the hyprland log - `hy3:debugnodes` - print the node tree into the hyprland log

View file

@ -1127,26 +1127,24 @@ void Hy3Layout::makeOppositeGroupOn(Hy3Node* node) {
} }
} }
Hy3Node* shiftOrGetFocus(Hy3Node& node, ShiftDirection direction, bool shift);
void Hy3Layout::shiftFocus(int workspace, ShiftDirection direction) { void Hy3Layout::shiftFocus(int workspace, ShiftDirection direction) {
auto* node = this->getWorkspaceFocusedNode(workspace); auto* node = this->getWorkspaceFocusedNode(workspace);
Debug::log(LOG, "ShiftFocus %p %d", node, direction); Debug::log(LOG, "ShiftFocus %p %d", node, direction);
if (node == nullptr) return; if (node == nullptr) return;
Hy3Node* target; Hy3Node* target;
if ((target = this->shiftOrGetFocus(*node, direction, false))) { if ((target = this->shiftOrGetFocus(*node, direction, false, false))) {
g_pCompositor->focusWindow(target->data.as_window); 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); auto* node = this->getWorkspaceFocusedNode(workspace);
Debug::log(LOG, "ShiftWindow %p %d", node, direction); Debug::log(LOG, "ShiftWindow %p %d", node, direction);
if (node == nullptr) return; if (node == nullptr) return;
this->shiftOrGetFocus(*node, direction, true); this->shiftOrGetFocus(*node, direction, true, once);
} }
bool shiftIsForward(ShiftDirection direction) { bool shiftIsForward(ShiftDirection direction) {
@ -1162,16 +1160,20 @@ bool shiftMatchesLayout(Hy3GroupLayout layout, ShiftDirection direction) {
|| (layout != Hy3GroupLayout::SplitV && !shiftIsVertical(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_origin = &node;
auto* break_parent = break_origin->parent; 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 // break parents until we hit a container oriented the same way as the shift direction
while (true) { while (true) {
if (break_parent == nullptr) return nullptr; if (break_parent == nullptr) return nullptr;
auto& group = break_parent->data.as_group; // must be a group in order to be a parent 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)) { if (shiftMatchesLayout(group.layout, direction)) {
// group has the correct orientation // group has the correct orientation
@ -1182,6 +1184,8 @@ Hy3Node* Hy3Layout::shiftOrGetFocus(Hy3Node& node, ShiftDirection direction, boo
break; break;
} }
has_broken_once = true;
if (break_parent->parent == nullptr) { if (break_parent->parent == nullptr) {
if (!shift) return nullptr; if (!shift) return nullptr;
@ -1233,7 +1237,7 @@ Hy3Node* Hy3Layout::shiftOrGetFocus(Hy3Node& node, ShiftDirection direction, boo
if (shiftIsForward(direction)) iter = std::next(iter); if (shiftIsForward(direction)) iter = std::next(iter);
else iter = std::prev(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 (shift) {
if (target_group == node.parent) { if (target_group == node.parent) {
if (shiftIsForward(direction)) insert = std::next(iter); 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 ((*iter)->data.type == Hy3NodeData::Window) {
if (shift) { if (shift) {
if (shift_after) insert = std::next(iter); if (shift_after) insert = std::next(iter);

View file

@ -117,7 +117,7 @@ public:
void makeOppositeGroupOnWorkspace(int); void makeOppositeGroupOnWorkspace(int);
void makeGroupOn(Hy3Node*, Hy3GroupLayout); void makeGroupOn(Hy3Node*, Hy3GroupLayout);
void makeOppositeGroupOn(Hy3Node*); void makeOppositeGroupOn(Hy3Node*);
void shiftWindow(int, ShiftDirection); void shiftWindow(int, ShiftDirection, bool);
void shiftFocus(int, ShiftDirection); void shiftFocus(int, ShiftDirection);
void raiseFocus(int); void raiseFocus(int);
@ -140,7 +140,8 @@ private:
// if shift is true, shift the window in the given direction, returning nullptr, // 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. // 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; friend struct Hy3Node;
}; };

View file

@ -1,3 +1,5 @@
#include <optional>
#include <hyprland/src/plugins/PluginAPI.hpp> #include <hyprland/src/plugins/PluginAPI.hpp>
#include <hyprland/src/Compositor.hpp> #include <hyprland/src/Compositor.hpp>
@ -48,18 +50,23 @@ void dispatch_makegroup(std::string arg) {
} }
} }
void dispatch_movewindow(std::string arg) { std::optional<ShiftDirection> 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(); int workspace = workspace_for_action();
if (workspace < 0) return; if (workspace < 0) return;
if (arg == "l") { auto args = CVarList(value);
g_Hy3Layout->shiftWindow(workspace, ShiftDirection::Left);
} else if (arg == "u") { if (auto shift = parseShiftArg(args[0])) {
g_Hy3Layout->shiftWindow(workspace, ShiftDirection::Up); auto once = args[1] == "once";
} else if (arg == "d") { g_Hy3Layout->shiftWindow(workspace, shift.value(), once);
g_Hy3Layout->shiftWindow(workspace, ShiftDirection::Down);
} else if (arg == "r") {
g_Hy3Layout->shiftWindow(workspace, ShiftDirection::Right);
} }
} }
@ -67,14 +74,8 @@ void dispatch_movefocus(std::string arg) {
int workspace = workspace_for_action(); int workspace = workspace_for_action();
if (workspace < 0) return; if (workspace < 0) return;
if (arg == "l") { if (auto shift = parseShiftArg(arg)) {
g_Hy3Layout->shiftFocus(workspace, ShiftDirection::Left); g_Hy3Layout->shiftFocus(workspace, shift.value());
} 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);
} }
} }