From 6331f32d1fe3049339b8093ecb6dbf1825d25b84 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Sun, 4 Jun 2023 20:26:22 -0700 Subject: [PATCH] Allow focusing tab groups via mouse click --- README.md | 1 + src/Hy3Layout.cpp | 51 +++++++++++++++++++++++++++++++++++++++++++++++ src/Hy3Layout.hpp | 2 ++ src/main.cpp | 8 ++++++++ 4 files changed, 62 insertions(+) diff --git a/README.md b/README.md index 17e2f58..18948df 100644 --- a/README.md +++ b/README.md @@ -98,6 +98,7 @@ plugin { - `hy3:movewindow, [, 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:raisefocus` - raise the active focus one level + - `hy3:focustab` - focus a tab under the mouse (bind to `mouse:272` for left click) - `hy3:debugnodes` - print the node tree into the hyprland log ## Installing diff --git a/src/Hy3Layout.cpp b/src/Hy3Layout.cpp index 315257f..5abdac2 100644 --- a/src/Hy3Layout.cpp +++ b/src/Hy3Layout.cpp @@ -1544,6 +1544,57 @@ void Hy3Layout::raiseFocus(int workspace) { } } +Hy3Node* Hy3Node::findNodeForTabGroup(Hy3TabGroup& tab_group) { + if (this->data.type == Hy3NodeData::Group) { + auto& group = this->data.as_group; + + if (group.layout == Hy3GroupLayout::Tabbed && group.tab_bar == &tab_group) { + return this; + } + + for (auto& node: group.children) { + auto* r = node->findNodeForTabGroup(tab_group); + if (r != nullptr) return r; + } + } else return nullptr; + + return nullptr; +} + +void Hy3Layout::focusTab(int workspace) { + auto* node = this->getWorkspaceRootGroup(workspace); + if (node == nullptr) return; + + 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; + + 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; + + auto delta = mouse_pos - pos; + + auto& node_list = group->data.as_group.children; + auto node_iter = node_list.begin(); + + for (auto& tab: tab_group.bar.entries) { + if (node_iter == node_list.end()) break; + + if (delta.x > tab.offset.fl() * size.x && delta.x < (tab.offset.fl() + tab.width.fl()) * size.x) { + (*node_iter)->focus(); + break; + } + + node_iter = std::next(node_iter); + } + } +} + bool Hy3Layout::shouldRenderSelected(CWindow* window) { if (window == nullptr) return false; auto* root = this->getWorkspaceRootGroup(window->m_iWorkspaceID); diff --git a/src/Hy3Layout.hpp b/src/Hy3Layout.hpp index 0a75f06..112e50c 100644 --- a/src/Hy3Layout.hpp +++ b/src/Hy3Layout.hpp @@ -88,6 +88,7 @@ struct Hy3Node { void updateTabBarRecursive(); bool isUrgent(); bool isIndirectlyFocused(); + Hy3Node* findNodeForTabGroup(Hy3TabGroup&); std::string getTitle(); bool operator==(const Hy3Node&) const; @@ -133,6 +134,7 @@ public: void shiftWindow(int, ShiftDirection, bool); void shiftFocus(int, ShiftDirection); void raiseFocus(int); + void focusTab(int); bool shouldRenderSelected(CWindow*); diff --git a/src/main.cpp b/src/main.cpp index a572c6c..8830fef 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -88,6 +88,13 @@ void dispatch_raisefocus(std::string arg) { g_Hy3Layout->raiseFocus(workspace); } +void dispatch_focustab(std::string arg) { + int workspace = workspace_for_action(); + if (workspace == -1) return; + + g_Hy3Layout->focusTab(workspace); +} + void dispatch_debug(std::string arg) { int workspace = workspace_for_action(); if (workspace == -1) return; @@ -128,6 +135,7 @@ APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) { HyprlandAPI::addDispatcher(PHANDLE, "hy3:movefocus", dispatch_movefocus); HyprlandAPI::addDispatcher(PHANDLE, "hy3:movewindow", dispatch_movewindow); HyprlandAPI::addDispatcher(PHANDLE, "hy3:raisefocus", dispatch_raisefocus); + HyprlandAPI::addDispatcher(PHANDLE, "hy3:focustab", dispatch_focustab); HyprlandAPI::addDispatcher(PHANDLE, "hy3:debugnodes", dispatch_debug); return {"hy3", "i3 like layout for hyprland", "outfoxxed", "0.1"};