From 311939d4439033cfdeb77dbc1dba0d689cef750b Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Sun, 5 May 2024 17:47:55 -0700 Subject: [PATCH] feat: add cursor warping support to `hy3:movefocus` --- CHANGELOG.md | 4 ++++ README.md | 4 +++- src/Hy3Layout.cpp | 47 ++++++++++++++++++++++++++++++++++----------- src/Hy3Layout.hpp | 3 ++- src/Hy3Node.cpp | 17 +++++++++++----- src/Hy3Node.hpp | 2 +- src/dispatchers.cpp | 17 +++++++++++++--- 7 files changed, 72 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ec064b4..655cedf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## Upcoming + +- Added cursor warping options for `hy3:movefocus`. + ## hl0.37.1 and before - Added `no_gaps_when_only = 2` diff --git a/README.md b/README.md index ef2dda8..4b73234 100644 --- a/README.md +++ b/README.md @@ -317,8 +317,10 @@ plugin { - `toggletab` will untab if group is tabbed, and tab if group is untabbed - `opposite` will toggle between horizontal and vertical layouts if the group is not tabbed. - `hy3:setephemeral, ` - change the ephemerality of the group the node belongs to - - `hy3:movefocus, , [visible]` - move the focus left, up, down, or right + - `hy3:movefocus, , [visible], [warp | nowarp]` - move the focus left, up, down, or right - `visible` - only move between visible nodes, not hidden tabs + - `warp` - warp the mouse to the selected window, even if `general:no_cursor_warps` is true. + - `nowarp` - does not warp the mouse to the selected window, even if `general:no_cursor_warps` is false. - `hy3:movewindow, , [once], [visible]` - move a window left, up, down, or right - `once` - only move directly to the neighboring group, without moving into any of its subgroups - `visible` - only move between visible nodes, not hidden tabs diff --git a/src/Hy3Layout.cpp b/src/Hy3Layout.cpp index 348e1fc..bc5dc5d 100644 --- a/src/Hy3Layout.cpp +++ b/src/Hy3Layout.cpp @@ -8,6 +8,7 @@ #include #include "Hy3Layout.hpp" +#include "Hy3Node.hpp" #include "SelectionHook.hpp" #include "globals.hpp" @@ -878,7 +879,12 @@ void Hy3Layout::shiftWindow( this->shiftNode(*node, direction, once, visible); } -void Hy3Layout::shiftFocus(const PHLWORKSPACE& workspace, ShiftDirection direction, bool visible) { +void Hy3Layout::shiftFocus( + const PHLWORKSPACE& workspace, + ShiftDirection direction, + bool visible, + bool warp +) { auto current_window = g_pCompositor->m_pLastWindow.lock(); if (current_window != nullptr) { @@ -893,7 +899,10 @@ void Hy3Layout::shiftFocus(const PHLWORKSPACE& workspace, ShiftDirection directi : 'r' ); - if (next_window != nullptr) g_pCompositor->focusWindow(next_window); + if (next_window != nullptr) { + g_pCompositor->focusWindow(next_window); + if (warp) Hy3Layout::warpCursorToBox(next_window->m_vPosition, next_window->m_vSize); + } return; } } @@ -904,7 +913,13 @@ void Hy3Layout::shiftFocus(const PHLWORKSPACE& workspace, ShiftDirection directi auto* target = this->shiftOrGetFocus(*node, direction, false, false, visible); if (target != nullptr) { - target->focus(); + if (warp) { + // don't warp for nodes in the same tab + warp = node->parent == nullptr || target->parent == nullptr || node->parent != target->parent + || node->parent->data.as_group().layout != Hy3GroupLayout::Tabbed; + } + + target->focus(warp); while (target->parent != nullptr) target = target->parent; target->recalcSizePosRecursive(); } @@ -1007,24 +1022,24 @@ void Hy3Layout::changeFocus(const PHLWORKSPACE& workspace, FocusShift shift) { node = node->parent; } - node->focus(); + node->focus(false); return; case FocusShift::Raise: if (node->parent == nullptr) goto bottom; else { - node->parent->focus(); + node->parent->focus(false); } return; case FocusShift::Lower: if (node->data.is_group() && node->data.as_group().focused_child != nullptr) - node->data.as_group().focused_child->focus(); + node->data.as_group().focused_child->focus(false); return; case FocusShift::Tab: // make sure we go up at least one level if (node->parent != nullptr) node = node->parent; while (node->parent != nullptr) { if (node->data.as_group().layout == Hy3GroupLayout::Tabbed) { - node->focus(); + node->focus(false); return; } @@ -1036,7 +1051,7 @@ void Hy3Layout::changeFocus(const PHLWORKSPACE& workspace, FocusShift shift) { if (node->parent != nullptr) node = node->parent; while (node->parent != nullptr) { if (node->parent->data.as_group().layout == Hy3GroupLayout::Tabbed) { - node->focus(); + node->focus(false); return; } @@ -1050,7 +1065,7 @@ bottom: node = node->data.as_group().focused_child; } - node->focus(); + node->focus(false); return; } @@ -1202,7 +1217,7 @@ hastab: && focus->data.as_group().focused_child != nullptr) focus = focus->data.as_group().focused_child; - focus->focus(); + focus->focus(false); tab_node->recalcSizePosRecursive(); } @@ -1324,6 +1339,16 @@ fsupdate: this->recalculateMonitor(monitor->ID); } +void Hy3Layout::warpCursorToBox(const Vector2D& pos, const Vector2D& size) { + auto cursorpos = Vector2D(g_pCompositor->m_sWLRCursor->x, g_pCompositor->m_sWLRCursor->y); + + if (cursorpos.x < pos.x || cursorpos.x >= pos.x + size.x || cursorpos.y < pos.y + || cursorpos.y >= pos.y + size.y) + { + g_pCompositor->warpCursorTo(pos + size / 2, true); + } +} + bool Hy3Layout::shouldRenderSelected(const PHLWINDOW& window) { if (window == nullptr) return false; auto* root = this->getWorkspaceRootGroup(window->m_pWorkspace); @@ -1791,7 +1816,7 @@ Hy3Node* Hy3Layout::shiftOrGetFocus( } node.updateTabBarRecursive(); - node.focus(); + node.focus(false); if (target_parent != target_group && target_parent != nullptr) target_parent->recalcSizePosRecursive(); diff --git a/src/Hy3Layout.hpp b/src/Hy3Layout.hpp index 7916261..d6b118b 100644 --- a/src/Hy3Layout.hpp +++ b/src/Hy3Layout.hpp @@ -112,7 +112,7 @@ public: void changeGroupEphemeralityOn(Hy3Node&, bool ephemeral); void shiftNode(Hy3Node&, ShiftDirection, bool once, bool visible); void shiftWindow(const PHLWORKSPACE& workspace, ShiftDirection, bool once, bool visible); - void shiftFocus(const PHLWORKSPACE& workspace, ShiftDirection, bool visible); + void shiftFocus(const PHLWORKSPACE& workspace, ShiftDirection, bool visible, bool warp); void moveNodeToWorkspace(const PHLWORKSPACE& origin, std::string wsname, bool follow); void changeFocus(const PHLWORKSPACE& workspace, FocusShift); void focusTab( @@ -125,6 +125,7 @@ public: void setNodeSwallow(const PHLWORKSPACE& workspace, SetSwallowOption); void killFocusedNode(const PHLWORKSPACE& workspace); void expand(const PHLWORKSPACE& workspace, ExpandOption, ExpandFullscreenOption); + static void warpCursorToBox(const Vector2D& pos, const Vector2D& size); bool shouldRenderSelected(const PHLWINDOW&); diff --git a/src/Hy3Node.cpp b/src/Hy3Node.cpp index 04ef6f5..5a9dd3d 100644 --- a/src/Hy3Node.cpp +++ b/src/Hy3Node.cpp @@ -8,6 +8,7 @@ #include #include +#include "Hy3Layout.hpp" #include "Hy3Node.hpp" #include "globals.hpp" @@ -163,19 +164,25 @@ PHLWINDOW Hy3NodeData::as_window() { bool Hy3Node::operator==(const Hy3Node& rhs) const { return this->data == rhs.data; } -void Hy3Node::focus() { +void Hy3Node::focus(bool warp) { this->markFocused(); switch (this->data.type()) { - case Hy3NodeType::Window: - this->data.as_window()->setHidden(false); - g_pCompositor->focusWindow(this->data.as_window()); + case Hy3NodeType::Window: { + auto window = this->data.as_window(); + window->setHidden(false); + g_pCompositor->focusWindow(window); + if (warp) Hy3Layout::warpCursorToBox(window->m_vPosition, window->m_vSize); break; - case Hy3NodeType::Group: + } + case Hy3NodeType::Group: { g_pCompositor->focusWindow(nullptr); this->raiseToTop(); + + if (warp) Hy3Layout::warpCursorToBox(this->position, this->size); break; } + } } PHLWINDOW Hy3Node::bringToTop() { diff --git a/src/Hy3Node.hpp b/src/Hy3Node.hpp index 7a52f3c..2d3969e 100644 --- a/src/Hy3Node.hpp +++ b/src/Hy3Node.hpp @@ -95,7 +95,7 @@ struct Hy3Node { bool operator==(const Hy3Node&) const; - void focus(); + void focus(bool warp); void focusWindow(); PHLWINDOW bringToTop(); void markFocused(); diff --git a/src/dispatchers.cpp b/src/dispatchers.cpp index 843b17a..aae34e8 100644 --- a/src/dispatchers.cpp +++ b/src/dispatchers.cpp @@ -113,9 +113,20 @@ void dispatch_movefocus(std::string value) { auto args = CVarList(value); - if (auto shift = parseShiftArg(args[0])) { - g_Hy3Layout->shiftFocus(workspace, shift.value(), args[1] == "visible"); - } + static const auto no_cursor_warps = ConfigValue("general:no_cursor_warps"); + auto warp_cursor = !*no_cursor_warps; + + int argi = 0; + auto shift = parseShiftArg(args[argi++]); + if (!shift) return; + + auto visible = args[argi] == "visible"; + if (visible) argi++; + + if (args[argi] == "nowarp") warp_cursor = false; + else if (args[argi] == "warp") warp_cursor = true; + + g_Hy3Layout->shiftFocus(workspace, shift.value(), visible, warp_cursor); } void dispatch_move_to_workspace(std::string value) {