mirror of
https://github.com/Trensa-Organization/hy3.git
synced 2025-03-15 18:53:40 +01:00
feat: add cursor warping support to hy3:movefocus
This commit is contained in:
parent
bc25b2a87f
commit
311939d443
7 changed files with 72 additions and 22 deletions
|
@ -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`
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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&);
|
||||||
|
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue