feat: add cursor warping support to hy3:movefocus

This commit is contained in:
outfoxxed 2024-05-05 17:47:55 -07:00
parent bc25b2a87f
commit 311939d443
No known key found for this signature in database
GPG key ID: 4C88A185FB89301E
7 changed files with 72 additions and 22 deletions

View file

@ -1,5 +1,9 @@
# Changelog # Changelog
## Upcoming
- Added cursor warping options for `hy3:movefocus`.
## hl0.37.1 and before ## hl0.37.1 and before
- Added `no_gaps_when_only = 2` - Added `no_gaps_when_only = 2`

View file

@ -317,8 +317,10 @@ plugin {
- `toggletab` will untab if group is tabbed, and tab if group is untabbed - `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. - `opposite` will toggle between horizontal and vertical layouts if the group is not tabbed.
- `hy3:setephemeral, <true | false>` - change the ephemerality of the group the node belongs to - `hy3:setephemeral, <true | false>` - change the ephemerality of the group the node belongs to
- `hy3:movefocus, <l | u | d | r | left | down | up | right>, [visible]` - move the focus left, up, down, or right - `hy3:movefocus, <l | u | d | r | left | down | up | right>, [visible], [warp | nowarp]` - move the focus left, up, down, or right
- `visible` - only move between visible nodes, not hidden tabs - `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, <l | u | d | r | left | down | up | right>, [once], [visible]` - move a window left, up, down, or right - `hy3:movewindow, <l | u | d | r | left | down | up | right>, [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 - `once` - only move directly to the neighboring group, without moving into any of its subgroups
- `visible` - only move between visible nodes, not hidden tabs - `visible` - only move between visible nodes, not hidden tabs

View file

@ -8,6 +8,7 @@
#include <ranges> #include <ranges>
#include "Hy3Layout.hpp" #include "Hy3Layout.hpp"
#include "Hy3Node.hpp"
#include "SelectionHook.hpp" #include "SelectionHook.hpp"
#include "globals.hpp" #include "globals.hpp"
@ -878,7 +879,12 @@ void Hy3Layout::shiftWindow(
this->shiftNode(*node, direction, once, visible); 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(); auto current_window = g_pCompositor->m_pLastWindow.lock();
if (current_window != nullptr) { if (current_window != nullptr) {
@ -893,7 +899,10 @@ void Hy3Layout::shiftFocus(const PHLWORKSPACE& workspace, ShiftDirection directi
: 'r' : '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; return;
} }
} }
@ -904,7 +913,13 @@ void Hy3Layout::shiftFocus(const PHLWORKSPACE& workspace, ShiftDirection directi
auto* target = this->shiftOrGetFocus(*node, direction, false, false, visible); auto* target = this->shiftOrGetFocus(*node, direction, false, false, visible);
if (target != nullptr) { 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; while (target->parent != nullptr) target = target->parent;
target->recalcSizePosRecursive(); target->recalcSizePosRecursive();
} }
@ -1007,24 +1022,24 @@ void Hy3Layout::changeFocus(const PHLWORKSPACE& workspace, FocusShift shift) {
node = node->parent; node = node->parent;
} }
node->focus(); node->focus(false);
return; return;
case FocusShift::Raise: case FocusShift::Raise:
if (node->parent == nullptr) goto bottom; if (node->parent == nullptr) goto bottom;
else { else {
node->parent->focus(); node->parent->focus(false);
} }
return; return;
case FocusShift::Lower: case FocusShift::Lower:
if (node->data.is_group() && node->data.as_group().focused_child != nullptr) 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; return;
case FocusShift::Tab: case FocusShift::Tab:
// make sure we go up at least one level // make sure we go up at least one level
if (node->parent != nullptr) node = node->parent; if (node->parent != nullptr) node = node->parent;
while (node->parent != nullptr) { while (node->parent != nullptr) {
if (node->data.as_group().layout == Hy3GroupLayout::Tabbed) { if (node->data.as_group().layout == Hy3GroupLayout::Tabbed) {
node->focus(); node->focus(false);
return; return;
} }
@ -1036,7 +1051,7 @@ void Hy3Layout::changeFocus(const PHLWORKSPACE& workspace, FocusShift shift) {
if (node->parent != nullptr) node = node->parent; if (node->parent != nullptr) node = node->parent;
while (node->parent != nullptr) { while (node->parent != nullptr) {
if (node->parent->data.as_group().layout == Hy3GroupLayout::Tabbed) { if (node->parent->data.as_group().layout == Hy3GroupLayout::Tabbed) {
node->focus(); node->focus(false);
return; return;
} }
@ -1050,7 +1065,7 @@ bottom:
node = node->data.as_group().focused_child; node = node->data.as_group().focused_child;
} }
node->focus(); node->focus(false);
return; return;
} }
@ -1202,7 +1217,7 @@ hastab:
&& focus->data.as_group().focused_child != nullptr) && focus->data.as_group().focused_child != nullptr)
focus = focus->data.as_group().focused_child; focus = focus->data.as_group().focused_child;
focus->focus(); focus->focus(false);
tab_node->recalcSizePosRecursive(); tab_node->recalcSizePosRecursive();
} }
@ -1324,6 +1339,16 @@ fsupdate:
this->recalculateMonitor(monitor->ID); 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) { bool Hy3Layout::shouldRenderSelected(const PHLWINDOW& window) {
if (window == nullptr) return false; if (window == nullptr) return false;
auto* root = this->getWorkspaceRootGroup(window->m_pWorkspace); auto* root = this->getWorkspaceRootGroup(window->m_pWorkspace);
@ -1791,7 +1816,7 @@ Hy3Node* Hy3Layout::shiftOrGetFocus(
} }
node.updateTabBarRecursive(); node.updateTabBarRecursive();
node.focus(); node.focus(false);
if (target_parent != target_group && target_parent != nullptr) if (target_parent != target_group && target_parent != nullptr)
target_parent->recalcSizePosRecursive(); target_parent->recalcSizePosRecursive();

View file

@ -112,7 +112,7 @@ public:
void changeGroupEphemeralityOn(Hy3Node&, bool ephemeral); void changeGroupEphemeralityOn(Hy3Node&, bool ephemeral);
void shiftNode(Hy3Node&, ShiftDirection, bool once, bool visible); void shiftNode(Hy3Node&, ShiftDirection, bool once, bool visible);
void shiftWindow(const PHLWORKSPACE& workspace, 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 moveNodeToWorkspace(const PHLWORKSPACE& origin, std::string wsname, bool follow);
void changeFocus(const PHLWORKSPACE& workspace, FocusShift); void changeFocus(const PHLWORKSPACE& workspace, FocusShift);
void focusTab( void focusTab(
@ -125,6 +125,7 @@ public:
void setNodeSwallow(const PHLWORKSPACE& workspace, SetSwallowOption); void setNodeSwallow(const PHLWORKSPACE& workspace, SetSwallowOption);
void killFocusedNode(const PHLWORKSPACE& workspace); void killFocusedNode(const PHLWORKSPACE& workspace);
void expand(const PHLWORKSPACE& workspace, ExpandOption, ExpandFullscreenOption); void expand(const PHLWORKSPACE& workspace, ExpandOption, ExpandFullscreenOption);
static void warpCursorToBox(const Vector2D& pos, const Vector2D& size);
bool shouldRenderSelected(const PHLWINDOW&); bool shouldRenderSelected(const PHLWINDOW&);

View file

@ -8,6 +8,7 @@
#include <hyprland/src/helpers/Box.hpp> #include <hyprland/src/helpers/Box.hpp>
#include <hyprland/src/plugins/PluginAPI.hpp> #include <hyprland/src/plugins/PluginAPI.hpp>
#include "Hy3Layout.hpp"
#include "Hy3Node.hpp" #include "Hy3Node.hpp"
#include "globals.hpp" #include "globals.hpp"
@ -163,19 +164,25 @@ PHLWINDOW Hy3NodeData::as_window() {
bool Hy3Node::operator==(const Hy3Node& rhs) const { return this->data == rhs.data; } bool Hy3Node::operator==(const Hy3Node& rhs) const { return this->data == rhs.data; }
void Hy3Node::focus() { void Hy3Node::focus(bool warp) {
this->markFocused(); this->markFocused();
switch (this->data.type()) { switch (this->data.type()) {
case Hy3NodeType::Window: case Hy3NodeType::Window: {
this->data.as_window()->setHidden(false); auto window = this->data.as_window();
g_pCompositor->focusWindow(this->data.as_window()); window->setHidden(false);
g_pCompositor->focusWindow(window);
if (warp) Hy3Layout::warpCursorToBox(window->m_vPosition, window->m_vSize);
break; break;
case Hy3NodeType::Group: }
case Hy3NodeType::Group: {
g_pCompositor->focusWindow(nullptr); g_pCompositor->focusWindow(nullptr);
this->raiseToTop(); this->raiseToTop();
if (warp) Hy3Layout::warpCursorToBox(this->position, this->size);
break; break;
} }
}
} }
PHLWINDOW Hy3Node::bringToTop() { PHLWINDOW Hy3Node::bringToTop() {

View file

@ -95,7 +95,7 @@ struct Hy3Node {
bool operator==(const Hy3Node&) const; bool operator==(const Hy3Node&) const;
void focus(); void focus(bool warp);
void focusWindow(); void focusWindow();
PHLWINDOW bringToTop(); PHLWINDOW bringToTop();
void markFocused(); void markFocused();

View file

@ -113,9 +113,20 @@ void dispatch_movefocus(std::string value) {
auto args = CVarList(value); auto args = CVarList(value);
if (auto shift = parseShiftArg(args[0])) { static const auto no_cursor_warps = ConfigValue<Hyprlang::INT>("general:no_cursor_warps");
g_Hy3Layout->shiftFocus(workspace, shift.value(), args[1] == "visible"); 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) { void dispatch_move_to_workspace(std::string value) {