5763c8fe624e6d54653764cb476aa9e10d4030b0
- Author
- outfoxxed <outfoxxed@outfoxxed.me>
- Committer
- outfoxxed <outfoxxed@outfoxxed.me>
- Date
Message
Diff
This diff is truncated to protect this page.
1diff --git a/README.md b/README.md
2index f698cb07eb0331b9a2f7703a72223bb44941ea9e..d53e4e2c8b44d8cb4166e39bf00d43b80109bbae 100644
3--- a/README.md
4+++ b/README.md
5@@ -91,9 +91,9 @@ plugin {
6
7 ### Dispatcher list
8 - `hy3:makegroup, <h | v | opposite | tab>` - make a vertical / horizontal split or tab group
9- - `hy3:movefocus, <l | u | d | r | left | down | up | right> [, visible]` - move the focus left, up, down, or right
10+ - `hy3:movefocus, <l | u | d | r | left | down | up | right>, [visible]` - move the focus left, up, down, or right
11 - `visible` - only move between visible nodes, not hidden tabs
12- - `hy3:movewindow, <l | u | d | r | left | down | up | right> [, once]` - move a window left, up, down, or right
13+ - `hy3:movewindow, <l | u | d | r | left | down | up | right>, [once]` - move a window left, up, down, or right
14 - `once` - only move directly to the neighboring group, without moving into any of its subgroups
15 - `hy3:changefocus, <top | bottom | raise | lower | tab | tabnode>`
16 - `top` - focus all nodes in the workspace
17@@ -102,6 +102,16 @@ plugin {
18 - `lower` - lower focus one level
19 - `tab` - raise focus to the nearest tab
20 - `tabnode` - raise focus to the nearest node under the tab
21+ - `hy3:focustab <mouse | [l | r | left | right], [prioritize_hovered | require_hovered], [wrap]>`
22+ - `mouse` - focus the tab under the mouse, works well with a non consuming bind, e.g.
23+ ```conf
24+ # binds hy3:focustab to lmb and still allows windows to receive clicks
25+ bindn = , mouse:272, hy3:focustab, mouse
26+ ```
27+ - `l | r | left | right` - direction to change tabs in
28+ - `prioritize_hovered` - prioritize the tab group under the mouse when multiple are stacked. use the lowest group if none is under the mouse.
29+ - `require_hovered` - affect the tab group under the mouse. do nothing if none are hovered.
30+ - `wrap` - wrap to the opposite size of the tab bar if moving off the end
31 - `hy3:debugnodes` - print the node tree into the hyprland log
32
33 ## Installing
34diff --git a/flake.nix b/flake.nix
35index 4eac23c38d13bc99fd9fea1c42bad31a0b911c01..34c543b4901f7712e763ac8783e25739884b6b46 100644
36--- a/flake.nix
37+++ b/flake.nix
38@@ -41,7 +41,7 @@
39 name = "hy3";
40
41 nativeBuildInputs = with pkgs; [
42- clang-tools
43+ clang-tools_16
44 bear
45 ];
46
47diff --git a/src/Hy3Layout.cpp b/src/Hy3Layout.cpp
48index 6d2bcf288cde74664c4ffbad692a2b9d166590e3..4490844d6365ce65cc819495c326842b56951c7f 100644
49--- a/src/Hy3Layout.cpp
50+++ b/src/Hy3Layout.cpp
51@@ -196,10 +196,12 @@ void Hy3Node::recalcSizePosRecursive(bool force) {
52
53 double offset = 0;
54
55- if (group->layout == Hy3GroupLayout::Tabbed && group->focused_child != nullptr && !group->focused_child->hidden) {
56+ if (group->layout == Hy3GroupLayout::Tabbed && group->focused_child != nullptr
57+ && !group->focused_child->hidden)
58+ {
59 group->focused_child->setHidden(false);
60
61- auto box = wlr_box { tpos.x, tpos.y, tsize.x, tsize.y };
62+ auto box = wlr_box {tpos.x, tpos.y, tsize.x, tsize.y};
63 g_pHyprRenderer->damageBox(&box);
64 }
65
66@@ -1684,6 +1686,8 @@ bottom:
67
68 Hy3Node* Hy3Node::findNodeForTabGroup(Hy3TabGroup& tab_group) {
69 if (this->data.type == Hy3NodeData::Group) {
70+ if (this->hidden) return nullptr;
71+
72 auto& group = this->data.as_group;
73
74 if (group.layout == Hy3GroupLayout::Tabbed && group.tab_bar == &tab_group) {
75@@ -1699,50 +1703,105 @@ Hy3Node* Hy3Node::findNodeForTabGroup(Hy3TabGroup& tab_group) {
76 return nullptr;
77 }
78
79-void Hy3Layout::focusTab(int workspace) {
80+void Hy3Layout::focusTab(
81+ int workspace,
82+ TabFocus target,
83+ TabFocusMousePriority mouse,
84+ bool wrap_scroll
85+) {
86+ static const auto* tab_bar_padding
87+ = &HyprlandAPI::getConfigValue(PHANDLE, "plugin:hy3:tabs:padding")->intValue;
88+
89 auto* node = this->getWorkspaceRootGroup(workspace);
90 if (node == nullptr) return;
91
92- auto mouse_pos = g_pInputManager->getMouseCoordsInternal();
93+ Hy3Node* tab_node = nullptr;
94+ Hy3Node* tab_focused_node;
95
96- for (auto& tab_group: this->tab_groups) {
97- auto pos = tab_group.pos.vec();
98- if (pos.x > mouse_pos.x || pos.y > mouse_pos.y) continue;
99- auto size = tab_group.size.vec();
100- if (pos.x + size.x < mouse_pos.x || pos.y + size.y < mouse_pos.y) continue;
101+ if (target == TabFocus::MouseLocation || mouse != TabFocusMousePriority::Ignore) {
102+ auto mouse_pos = g_pInputManager->getMouseCoordsInternal();
103
104- Debug::log(
105- LOG,
106- "!!! tab group clicked: %f %f, %f %f [%f %f]",
107- pos.x,
108- pos.y,
109- size.x,
110- size.y,
111- mouse_pos.x,
112- mouse_pos.y
113- );
114+ for (auto& tab_group: this->tab_groups) {
115+ auto pos = tab_group.pos.vec();
116+ if (pos.x > mouse_pos.x || pos.y > mouse_pos.y) continue;
117+ auto size = tab_group.size.vec();
118+ if (pos.x + size.x < mouse_pos.x || pos.y + size.y + *tab_bar_padding < mouse_pos.y) continue;
119
120- auto* group = node->findNodeForTabGroup(tab_group);
121- if (group == nullptr) continue;
122+ tab_node = node->findNodeForTabGroup(tab_group);
123+ if (tab_node == nullptr) continue;
124+ if (target != TabFocus::MouseLocation) goto hastab;
125
126- auto delta = mouse_pos - pos;
127+ auto delta = mouse_pos - pos;
128
129- auto& node_list = group->data.as_group.children;
130- auto node_iter = node_list.begin();
131+ auto& node_list = tab_node->data.as_group.children;
132+ auto node_iter = node_list.begin();
133
134- for (auto& tab: tab_group.bar.entries) {
135- if (node_iter == node_list.end()) break;
136+ for (auto& tab: tab_group.bar.entries) {
137+ if (node_iter == node_list.end()) break;
138
139- if (delta.x > tab.offset.fl() * size.x
140- && delta.x < (tab.offset.fl() + tab.width.fl()) * size.x)
141- {
142- (*node_iter)->focus();
143- break;
144+ if (delta.x > tab.offset.fl() * size.x
145+ && delta.x < (tab.offset.fl() + tab.width.fl()) * size.x)
146+ {
147+ tab_focused_node = *node_iter;
148+ goto hastab;
149+ }
150+
151diff --git a/src/Hy3Layout.hpp b/src/Hy3Layout.hpp
152index c534e5adb6aee33152e139355033b4fbfff96229..39f6b6ff5a28021153a4aef3ce9795ed0dae06ac 100644
153--- a/src/Hy3Layout.hpp
154+++ b/src/Hy3Layout.hpp
155@@ -31,6 +31,18 @@ enum class FocusShift {
156 TabNode,
157 };
158
159+enum class TabFocus {
160+ MouseLocation,
161+ Left,
162+ Right,
163+};
164+
165+enum class TabFocusMousePriority {
166+ Ignore,
167+ Prioritize,
168+ Require,
169+};
170+
171 struct Hy3GroupData {
172 Hy3GroupLayout layout = Hy3GroupLayout::SplitH;
173 std::list<Hy3Node*> children;
174@@ -146,7 +158,7 @@ public:
175 void shiftWindow(int, ShiftDirection, bool);
176 void shiftFocus(int, ShiftDirection, bool);
177 void changeFocus(int, FocusShift);
178- void focusTab(int);
179+ void focusTab(int, TabFocus, TabFocusMousePriority, bool);
180
181 bool shouldRenderSelected(CWindow*);
182
183diff --git a/src/main.cpp b/src/main.cpp
184index 05daae311d93066b22256118d3fb539001b47c9c..efc00403e8e932910c33b9eaa7aad13dea0a4e01 100644
185--- a/src/main.cpp
186+++ b/src/main.cpp
187@@ -93,11 +93,37 @@ void dispatch_changefocus(std::string arg) {
188 else if (arg == "tabnode") g_Hy3Layout->changeFocus(workspace, FocusShift::TabNode);
189 }
190
191-void dispatch_focustab(std::string arg) {
192+void dispatch_focustab(std::string value) {
193 int workspace = workspace_for_action();
194 if (workspace == -1) return;
195
196- g_Hy3Layout->focusTab(workspace);
197+ auto i = 0;
198+ auto args = CVarList(value);
199+
200+ TabFocus focus;
201+ auto mouse = TabFocusMousePriority::Ignore;
202+ bool wrap_scroll = false;
203+
204+ if (args[i] == "l" || args[i] == "left") focus = TabFocus::Left;
205+ else if (args[i] == "r" || args[i] == "right") focus = TabFocus::Right;
206+ else if (args[i] == "mouse") {
207+ g_Hy3Layout->focusTab(workspace, TabFocus::MouseLocation, mouse, false);
208+ return;
209+ } else return;
210+
211+ i++;
212+
213+ if (args[i] == "prioritize_hovered") {
214+ mouse = TabFocusMousePriority::Prioritize;
215+ i++;
216+ } else if (args[i] == "require_hovered") {
217+ mouse = TabFocusMousePriority::Require;
218+ i++;
219+ }
220+
221+ if (args[i++] == "wrap") wrap_scroll = true;
222+
223+ g_Hy3Layout->focusTab(workspace, focus, mouse, wrap_scroll);
224 }
225
226 void dispatch_debug(std::string arg) {