mirror of
https://github.com/Trensa-Organization/hy3.git
synced 2025-03-15 18:53:40 +01:00
Fix and document focustab
This commit is contained in:
parent
6643cbb6d4
commit
5763c8fe62
5 changed files with 145 additions and 38 deletions
14
README.md
14
README.md
|
@ -91,9 +91,9 @@ plugin {
|
||||||
|
|
||||||
### Dispatcher list
|
### Dispatcher list
|
||||||
- `hy3:makegroup, <h | v | opposite | tab>` - make a vertical / horizontal split or tab group
|
- `hy3:makegroup, <h | v | opposite | tab>` - make a vertical / horizontal split or tab group
|
||||||
- `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]` - 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
|
||||||
- `hy3:movewindow, <l | u | d | r | left | down | up | right> [, once]` - 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
|
- `once` - only move directly to the neighboring group, without moving into any of its subgroups
|
||||||
- `hy3:changefocus, <top | bottom | raise | lower | tab | tabnode>`
|
- `hy3:changefocus, <top | bottom | raise | lower | tab | tabnode>`
|
||||||
- `top` - focus all nodes in the workspace
|
- `top` - focus all nodes in the workspace
|
||||||
|
@ -102,6 +102,16 @@ plugin {
|
||||||
- `lower` - lower focus one level
|
- `lower` - lower focus one level
|
||||||
- `tab` - raise focus to the nearest tab
|
- `tab` - raise focus to the nearest tab
|
||||||
- `tabnode` - raise focus to the nearest node under the tab
|
- `tabnode` - raise focus to the nearest node under the tab
|
||||||
|
- `hy3:focustab <mouse | [l | r | left | right], [prioritize_hovered | require_hovered], [wrap]>`
|
||||||
|
- `mouse` - focus the tab under the mouse, works well with a non consuming bind, e.g.
|
||||||
|
```conf
|
||||||
|
# binds hy3:focustab to lmb and still allows windows to receive clicks
|
||||||
|
bindn = , mouse:272, hy3:focustab, mouse
|
||||||
|
```
|
||||||
|
- `l | r | left | right` - direction to change tabs in
|
||||||
|
- `prioritize_hovered` - prioritize the tab group under the mouse when multiple are stacked. use the lowest group if none is under the mouse.
|
||||||
|
- `require_hovered` - affect the tab group under the mouse. do nothing if none are hovered.
|
||||||
|
- `wrap` - wrap to the opposite size of the tab bar if moving off the end
|
||||||
- `hy3:debugnodes` - print the node tree into the hyprland log
|
- `hy3:debugnodes` - print the node tree into the hyprland log
|
||||||
|
|
||||||
## Installing
|
## Installing
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
name = "hy3";
|
name = "hy3";
|
||||||
|
|
||||||
nativeBuildInputs = with pkgs; [
|
nativeBuildInputs = with pkgs; [
|
||||||
clang-tools
|
clang-tools_16
|
||||||
bear
|
bear
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -196,10 +196,12 @@ void Hy3Node::recalcSizePosRecursive(bool force) {
|
||||||
|
|
||||||
double offset = 0;
|
double offset = 0;
|
||||||
|
|
||||||
if (group->layout == Hy3GroupLayout::Tabbed && group->focused_child != nullptr && !group->focused_child->hidden) {
|
if (group->layout == Hy3GroupLayout::Tabbed && group->focused_child != nullptr
|
||||||
|
&& !group->focused_child->hidden)
|
||||||
|
{
|
||||||
group->focused_child->setHidden(false);
|
group->focused_child->setHidden(false);
|
||||||
|
|
||||||
auto box = wlr_box { tpos.x, tpos.y, tsize.x, tsize.y };
|
auto box = wlr_box {tpos.x, tpos.y, tsize.x, tsize.y};
|
||||||
g_pHyprRenderer->damageBox(&box);
|
g_pHyprRenderer->damageBox(&box);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1684,6 +1686,8 @@ bottom:
|
||||||
|
|
||||||
Hy3Node* Hy3Node::findNodeForTabGroup(Hy3TabGroup& tab_group) {
|
Hy3Node* Hy3Node::findNodeForTabGroup(Hy3TabGroup& tab_group) {
|
||||||
if (this->data.type == Hy3NodeData::Group) {
|
if (this->data.type == Hy3NodeData::Group) {
|
||||||
|
if (this->hidden) return nullptr;
|
||||||
|
|
||||||
auto& group = this->data.as_group;
|
auto& group = this->data.as_group;
|
||||||
|
|
||||||
if (group.layout == Hy3GroupLayout::Tabbed && group.tab_bar == &tab_group) {
|
if (group.layout == Hy3GroupLayout::Tabbed && group.tab_bar == &tab_group) {
|
||||||
|
@ -1699,50 +1703,105 @@ Hy3Node* Hy3Node::findNodeForTabGroup(Hy3TabGroup& tab_group) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Hy3Layout::focusTab(int workspace) {
|
void Hy3Layout::focusTab(
|
||||||
|
int workspace,
|
||||||
|
TabFocus target,
|
||||||
|
TabFocusMousePriority mouse,
|
||||||
|
bool wrap_scroll
|
||||||
|
) {
|
||||||
|
static const auto* tab_bar_padding
|
||||||
|
= &HyprlandAPI::getConfigValue(PHANDLE, "plugin:hy3:tabs:padding")->intValue;
|
||||||
|
|
||||||
auto* node = this->getWorkspaceRootGroup(workspace);
|
auto* node = this->getWorkspaceRootGroup(workspace);
|
||||||
if (node == nullptr) return;
|
if (node == nullptr) return;
|
||||||
|
|
||||||
auto mouse_pos = g_pInputManager->getMouseCoordsInternal();
|
Hy3Node* tab_node = nullptr;
|
||||||
|
Hy3Node* tab_focused_node;
|
||||||
|
|
||||||
for (auto& tab_group: this->tab_groups) {
|
if (target == TabFocus::MouseLocation || mouse != TabFocusMousePriority::Ignore) {
|
||||||
auto pos = tab_group.pos.vec();
|
auto mouse_pos = g_pInputManager->getMouseCoordsInternal();
|
||||||
if (pos.x > mouse_pos.x || pos.y > mouse_pos.y) continue;
|
|
||||||
auto size = tab_group.size.vec();
|
|
||||||
if (pos.x + size.x < mouse_pos.x || pos.y + size.y < mouse_pos.y) continue;
|
|
||||||
|
|
||||||
Debug::log(
|
for (auto& tab_group: this->tab_groups) {
|
||||||
LOG,
|
auto pos = tab_group.pos.vec();
|
||||||
"!!! tab group clicked: %f %f, %f %f [%f %f]",
|
if (pos.x > mouse_pos.x || pos.y > mouse_pos.y) continue;
|
||||||
pos.x,
|
auto size = tab_group.size.vec();
|
||||||
pos.y,
|
if (pos.x + size.x < mouse_pos.x || pos.y + size.y + *tab_bar_padding < mouse_pos.y) continue;
|
||||||
size.x,
|
|
||||||
size.y,
|
|
||||||
mouse_pos.x,
|
|
||||||
mouse_pos.y
|
|
||||||
);
|
|
||||||
|
|
||||||
auto* group = node->findNodeForTabGroup(tab_group);
|
tab_node = node->findNodeForTabGroup(tab_group);
|
||||||
if (group == nullptr) continue;
|
if (tab_node == nullptr) continue;
|
||||||
|
if (target != TabFocus::MouseLocation) goto hastab;
|
||||||
|
|
||||||
auto delta = mouse_pos - pos;
|
auto delta = mouse_pos - pos;
|
||||||
|
|
||||||
auto& node_list = group->data.as_group.children;
|
auto& node_list = tab_node->data.as_group.children;
|
||||||
auto node_iter = node_list.begin();
|
auto node_iter = node_list.begin();
|
||||||
|
|
||||||
for (auto& tab: tab_group.bar.entries) {
|
for (auto& tab: tab_group.bar.entries) {
|
||||||
if (node_iter == node_list.end()) break;
|
if (node_iter == node_list.end()) break;
|
||||||
|
|
||||||
if (delta.x > tab.offset.fl() * size.x
|
if (delta.x > tab.offset.fl() * size.x
|
||||||
&& delta.x < (tab.offset.fl() + tab.width.fl()) * size.x)
|
&& delta.x < (tab.offset.fl() + tab.width.fl()) * size.x)
|
||||||
{
|
{
|
||||||
(*node_iter)->focus();
|
tab_focused_node = *node_iter;
|
||||||
break;
|
goto hastab;
|
||||||
|
}
|
||||||
|
|
||||||
|
node_iter = std::next(node_iter);
|
||||||
}
|
}
|
||||||
|
|
||||||
node_iter = std::next(node_iter);
|
node->recalcSizePosRecursive();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target == TabFocus::MouseLocation || mouse == TabFocusMousePriority::Require) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tab_node == nullptr) {
|
||||||
|
tab_node = this->getWorkspaceFocusedNode(workspace);
|
||||||
|
if (tab_node == nullptr) return;
|
||||||
|
|
||||||
|
while (tab_node != nullptr && tab_node->data.as_group.layout != Hy3GroupLayout::Tabbed
|
||||||
|
&& tab_node->parent != nullptr)
|
||||||
|
tab_node = tab_node->parent;
|
||||||
|
|
||||||
|
if (tab_node == nullptr || tab_node->data.type != Hy3NodeData::Group
|
||||||
|
|| tab_node->data.as_group.layout != Hy3GroupLayout::Tabbed)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
hastab:
|
||||||
|
if (target != TabFocus::MouseLocation) {
|
||||||
|
if (tab_node->data.as_group.focused_child == nullptr
|
||||||
|
|| tab_node->data.as_group.children.size() < 2)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto& children = tab_node->data.as_group.children;
|
||||||
|
auto node_iter
|
||||||
|
= std::find(children.begin(), children.end(), tab_node->data.as_group.focused_child);
|
||||||
|
if (node_iter == children.end()) return;
|
||||||
|
if (target == TabFocus::Left) {
|
||||||
|
if (node_iter == children.begin()) {
|
||||||
|
if (wrap_scroll) node_iter = std::prev(children.end());
|
||||||
|
else return;
|
||||||
|
} else node_iter = std::prev(node_iter);
|
||||||
|
|
||||||
|
tab_focused_node = *node_iter;
|
||||||
|
} else {
|
||||||
|
if (node_iter == std::prev(children.end())) {
|
||||||
|
if (wrap_scroll) node_iter = children.begin();
|
||||||
|
else return;
|
||||||
|
} else node_iter = std::next(node_iter);
|
||||||
|
|
||||||
|
tab_focused_node = *node_iter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto* focus = tab_focused_node;
|
||||||
|
while (focus->data.type == Hy3NodeData::Group && !focus->data.as_group.group_focused
|
||||||
|
&& focus->data.as_group.focused_child != nullptr)
|
||||||
|
focus = focus->data.as_group.focused_child;
|
||||||
|
|
||||||
|
focus->focus();
|
||||||
|
tab_node->recalcSizePosRecursive();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Hy3Layout::shouldRenderSelected(CWindow* window) {
|
bool Hy3Layout::shouldRenderSelected(CWindow* window) {
|
||||||
|
|
|
@ -31,6 +31,18 @@ enum class FocusShift {
|
||||||
TabNode,
|
TabNode,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class TabFocus {
|
||||||
|
MouseLocation,
|
||||||
|
Left,
|
||||||
|
Right,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class TabFocusMousePriority {
|
||||||
|
Ignore,
|
||||||
|
Prioritize,
|
||||||
|
Require,
|
||||||
|
};
|
||||||
|
|
||||||
struct Hy3GroupData {
|
struct Hy3GroupData {
|
||||||
Hy3GroupLayout layout = Hy3GroupLayout::SplitH;
|
Hy3GroupLayout layout = Hy3GroupLayout::SplitH;
|
||||||
std::list<Hy3Node*> children;
|
std::list<Hy3Node*> children;
|
||||||
|
@ -146,7 +158,7 @@ public:
|
||||||
void shiftWindow(int, ShiftDirection, bool);
|
void shiftWindow(int, ShiftDirection, bool);
|
||||||
void shiftFocus(int, ShiftDirection, bool);
|
void shiftFocus(int, ShiftDirection, bool);
|
||||||
void changeFocus(int, FocusShift);
|
void changeFocus(int, FocusShift);
|
||||||
void focusTab(int);
|
void focusTab(int, TabFocus, TabFocusMousePriority, bool);
|
||||||
|
|
||||||
bool shouldRenderSelected(CWindow*);
|
bool shouldRenderSelected(CWindow*);
|
||||||
|
|
||||||
|
|
30
src/main.cpp
30
src/main.cpp
|
@ -93,11 +93,37 @@ void dispatch_changefocus(std::string arg) {
|
||||||
else if (arg == "tabnode") g_Hy3Layout->changeFocus(workspace, FocusShift::TabNode);
|
else if (arg == "tabnode") g_Hy3Layout->changeFocus(workspace, FocusShift::TabNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dispatch_focustab(std::string arg) {
|
void dispatch_focustab(std::string value) {
|
||||||
int workspace = workspace_for_action();
|
int workspace = workspace_for_action();
|
||||||
if (workspace == -1) return;
|
if (workspace == -1) return;
|
||||||
|
|
||||||
g_Hy3Layout->focusTab(workspace);
|
auto i = 0;
|
||||||
|
auto args = CVarList(value);
|
||||||
|
|
||||||
|
TabFocus focus;
|
||||||
|
auto mouse = TabFocusMousePriority::Ignore;
|
||||||
|
bool wrap_scroll = false;
|
||||||
|
|
||||||
|
if (args[i] == "l" || args[i] == "left") focus = TabFocus::Left;
|
||||||
|
else if (args[i] == "r" || args[i] == "right") focus = TabFocus::Right;
|
||||||
|
else if (args[i] == "mouse") {
|
||||||
|
g_Hy3Layout->focusTab(workspace, TabFocus::MouseLocation, mouse, false);
|
||||||
|
return;
|
||||||
|
} else return;
|
||||||
|
|
||||||
|
i++;
|
||||||
|
|
||||||
|
if (args[i] == "prioritize_hovered") {
|
||||||
|
mouse = TabFocusMousePriority::Prioritize;
|
||||||
|
i++;
|
||||||
|
} else if (args[i] == "require_hovered") {
|
||||||
|
mouse = TabFocusMousePriority::Require;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args[i++] == "wrap") wrap_scroll = true;
|
||||||
|
|
||||||
|
g_Hy3Layout->focusTab(workspace, focus, mouse, wrap_scroll);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dispatch_debug(std::string arg) {
|
void dispatch_debug(std::string arg) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue