Fix and document focustab

This commit is contained in:
outfoxxed 2023-06-15 00:27:02 -07:00
parent 6643cbb6d4
commit 5763c8fe62
No known key found for this signature in database
GPG key ID: 4C88A185FB89301E
5 changed files with 145 additions and 38 deletions

View file

@ -91,9 +91,9 @@ plugin {
### Dispatcher list
- `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
- `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
- `hy3:changefocus, <top | bottom | raise | lower | tab | tabnode>`
- `top` - focus all nodes in the workspace
@ -102,6 +102,16 @@ plugin {
- `lower` - lower focus one level
- `tab` - raise focus to the nearest 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
## Installing

View file

@ -41,7 +41,7 @@
name = "hy3";
nativeBuildInputs = with pkgs; [
clang-tools
clang-tools_16
bear
];

View file

@ -196,7 +196,9 @@ void Hy3Node::recalcSizePosRecursive(bool force) {
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);
auto box = wlr_box {tpos.x, tpos.y, tsize.x, tsize.y};
@ -1684,6 +1686,8 @@ bottom:
Hy3Node* Hy3Node::findNodeForTabGroup(Hy3TabGroup& tab_group) {
if (this->data.type == Hy3NodeData::Group) {
if (this->hidden) return nullptr;
auto& group = this->data.as_group;
if (group.layout == Hy3GroupLayout::Tabbed && group.tab_bar == &tab_group) {
@ -1699,35 +1703,37 @@ Hy3Node* Hy3Node::findNodeForTabGroup(Hy3TabGroup& tab_group) {
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);
if (node == nullptr) return;
Hy3Node* tab_node = nullptr;
Hy3Node* tab_focused_node;
if (target == TabFocus::MouseLocation || mouse != TabFocusMousePriority::Ignore) {
auto mouse_pos = g_pInputManager->getMouseCoordsInternal();
for (auto& tab_group: this->tab_groups) {
auto pos = tab_group.pos.vec();
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;
if (pos.x + size.x < mouse_pos.x || pos.y + size.y + *tab_bar_padding < mouse_pos.y) continue;
Debug::log(
LOG,
"!!! tab group clicked: %f %f, %f %f [%f %f]",
pos.x,
pos.y,
size.x,
size.y,
mouse_pos.x,
mouse_pos.y
);
auto* group = node->findNodeForTabGroup(tab_group);
if (group == nullptr) continue;
tab_node = node->findNodeForTabGroup(tab_group);
if (tab_node == nullptr) continue;
if (target != TabFocus::MouseLocation) goto hastab;
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();
for (auto& tab: tab_group.bar.entries) {
@ -1736,13 +1742,66 @@ void Hy3Layout::focusTab(int workspace) {
if (delta.x > tab.offset.fl() * size.x
&& delta.x < (tab.offset.fl() + tab.width.fl()) * size.x)
{
(*node_iter)->focus();
break;
tab_focused_node = *node_iter;
goto hastab;
}
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) {

View file

@ -31,6 +31,18 @@ enum class FocusShift {
TabNode,
};
enum class TabFocus {
MouseLocation,
Left,
Right,
};
enum class TabFocusMousePriority {
Ignore,
Prioritize,
Require,
};
struct Hy3GroupData {
Hy3GroupLayout layout = Hy3GroupLayout::SplitH;
std::list<Hy3Node*> children;
@ -146,7 +158,7 @@ public:
void shiftWindow(int, ShiftDirection, bool);
void shiftFocus(int, ShiftDirection, bool);
void changeFocus(int, FocusShift);
void focusTab(int);
void focusTab(int, TabFocus, TabFocusMousePriority, bool);
bool shouldRenderSelected(CWindow*);

View file

@ -93,11 +93,37 @@ void dispatch_changefocus(std::string arg) {
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();
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) {