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
|
||||
- `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
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
name = "hy3";
|
||||
|
||||
nativeBuildInputs = with pkgs; [
|
||||
clang-tools
|
||||
clang-tools_16
|
||||
bear
|
||||
];
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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*);
|
||||
|
||||
|
|
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);
|
||||
}
|
||||
|
||||
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) {
|
||||
|
|
Loading…
Add table
Reference in a new issue