6331f32d1fe3049339b8093ecb6dbf1825d25b84

Author
outfoxxed <outfoxxed@outfoxxed.me>
Committer
outfoxxed <outfoxxed@outfoxxed.me>
Date

Message

Allow focusing tab groups via mouse click

Diff

  1diff --git a/README.md b/README.md
  2index 17e2f587df413e04a56a9cc3353117085358d472..18948dfc8911d56b0e8f586b718c5e756fb6c541 100644
  3--- a/README.md
  4+++ b/README.md
  5@@ -98,6 +98,7 @@ plugin {
  6  - `hy3:movewindow, <l | u | d | r | left | down | up | right> [, once]` - move a window left, up, down, or right
  7    - `once` - only move directly to the neighboring group, without moving into any of its subgroups
  8  - `hy3:raisefocus` - raise the active focus one level
  9+ - `hy3:focustab` - focus a tab under the mouse (bind to `mouse:272` for left click)
 10  - `hy3:debugnodes` - print the node tree into the hyprland log
 11 
 12 ## Installing
 13diff --git a/src/Hy3Layout.cpp b/src/Hy3Layout.cpp
 14index 315257fd573f9b1f2fae0d15552c19b57b361445..5abdac295ac39be679252b343af056841ed37589 100644
 15--- a/src/Hy3Layout.cpp
 16+++ b/src/Hy3Layout.cpp
 17@@ -1544,6 +1544,57 @@ void Hy3Layout::raiseFocus(int workspace) {
 18 	}
 19 }
 20 
 21+Hy3Node* Hy3Node::findNodeForTabGroup(Hy3TabGroup& tab_group) {
 22+	if (this->data.type == Hy3NodeData::Group) {
 23+		auto& group = this->data.as_group;
 24+
 25+		if (group.layout == Hy3GroupLayout::Tabbed && group.tab_bar == &tab_group) {
 26+			return this;
 27+		}
 28+
 29+		for (auto& node: group.children) {
 30+			auto* r = node->findNodeForTabGroup(tab_group);
 31+			if (r != nullptr) return r;
 32+		}
 33+	} else return nullptr;
 34+
 35+	return nullptr;
 36+}
 37+
 38+void Hy3Layout::focusTab(int workspace) {
 39+	auto* node = this->getWorkspaceRootGroup(workspace);
 40+	if (node == nullptr) return;
 41+
 42+	auto mouse_pos = g_pInputManager->getMouseCoordsInternal();
 43+
 44+	for (auto& tab_group: this->tab_groups) {
 45+		auto pos = tab_group.pos.vec();
 46+		if (pos.x > mouse_pos.x || pos.y > mouse_pos.y) continue;
 47+		auto size = tab_group.size.vec();
 48+		if (pos.x + size.x < mouse_pos.x || pos.y + size.y < mouse_pos.y) continue;
 49+
 50+		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);
 51+		auto* group = node->findNodeForTabGroup(tab_group);
 52+		if (group == nullptr) continue;
 53+
 54+		auto delta = mouse_pos - pos;
 55+
 56+		auto& node_list = group->data.as_group.children;
 57+		auto node_iter = node_list.begin();
 58+
 59+		for (auto& tab: tab_group.bar.entries) {
 60+			if (node_iter == node_list.end()) break;
 61+
 62+			if (delta.x > tab.offset.fl() * size.x && delta.x < (tab.offset.fl() + tab.width.fl()) * size.x) {
 63+				(*node_iter)->focus();
 64+				break;
 65+			}
 66+
 67+			node_iter = std::next(node_iter);
 68+		}
 69+	}
 70+}
 71+
 72 bool Hy3Layout::shouldRenderSelected(CWindow* window) {
 73 	if (window == nullptr) return false;
 74 	auto* root = this->getWorkspaceRootGroup(window->m_iWorkspaceID);
 75diff --git a/src/Hy3Layout.hpp b/src/Hy3Layout.hpp
 76index 0a75f065713070c6bfc4ea1e85524092b5eb1ad2..112e50c400fd406f94c008dc2b3a13f26779ba4c 100644
 77--- a/src/Hy3Layout.hpp
 78+++ b/src/Hy3Layout.hpp
 79@@ -88,6 +88,7 @@ struct Hy3Node {
 80 	void updateTabBarRecursive();
 81 	bool isUrgent();
 82 	bool isIndirectlyFocused();
 83+	Hy3Node* findNodeForTabGroup(Hy3TabGroup&);
 84 	std::string getTitle();
 85 
 86 	bool operator==(const Hy3Node&) const;
 87@@ -133,6 +134,7 @@ public:
 88 	void shiftWindow(int, ShiftDirection, bool);
 89 	void shiftFocus(int, ShiftDirection);
 90 	void raiseFocus(int);
 91+	void focusTab(int);
 92 
 93 	bool shouldRenderSelected(CWindow*);
 94 
 95diff --git a/src/main.cpp b/src/main.cpp
 96index a572c6c8e69c980baafb558a5fedec4a63550778..8830fef2f2654704d920b16780c253b89784e41e 100644
 97--- a/src/main.cpp
 98+++ b/src/main.cpp
 99@@ -88,6 +88,13 @@ void dispatch_raisefocus(std::string arg) {
100 	g_Hy3Layout->raiseFocus(workspace);
101 }
102 
103+void dispatch_focustab(std::string arg) {
104+	int workspace = workspace_for_action();
105+	if (workspace == -1) return;
106+
107+	g_Hy3Layout->focusTab(workspace);
108+}
109+
110 void dispatch_debug(std::string arg) {
111 	int workspace = workspace_for_action();
112 	if (workspace == -1) return;
113@@ -128,6 +135,7 @@ APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) {
114 	HyprlandAPI::addDispatcher(PHANDLE, "hy3:movefocus", dispatch_movefocus);
115 	HyprlandAPI::addDispatcher(PHANDLE, "hy3:movewindow", dispatch_movewindow);
116 	HyprlandAPI::addDispatcher(PHANDLE, "hy3:raisefocus", dispatch_raisefocus);
117+	HyprlandAPI::addDispatcher(PHANDLE, "hy3:focustab", dispatch_focustab);
118 	HyprlandAPI::addDispatcher(PHANDLE, "hy3:debugnodes", dispatch_debug);
119 
120 	return {"hy3", "i3 like layout for hyprland", "outfoxxed", "0.1"};