e3bb15bc13d1d1cb74ac5240cd7826aaddb7a99b

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

Message

Tab entry animation

Diff

This diff is truncated to protect this page.

  1diff --git a/src/TabGroup.cpp b/src/TabGroup.cpp
  2index 979444a39e9001b8633c70538fabb983350fa560..b04ce91cc38adebfa069ee8d9328b5f0ad5aafe6 100644
  3--- a/src/TabGroup.cpp
  4+++ b/src/TabGroup.cpp
  5@@ -21,8 +21,8 @@ bool Hy3TabBarEntry::operator==(const Hy3Node& node) const {
  6 }
  7 
  8 Hy3TabBar::Hy3TabBar() {
  9-	this->vertical_pos.create(AVARTYPE_FLOAT, 20.0f, g_pConfigManager->getAnimationPropertyConfig("windowsMove"), nullptr, AVARDAMAGE_NONE);
 10-	this->fade_opacity.create(AVARTYPE_FLOAT, 0.0f, g_pConfigManager->getAnimationPropertyConfig("windowsMove"), nullptr, AVARDAMAGE_NONE);
 11+	this->vertical_pos.create(AVARTYPE_FLOAT, 1.0f, g_pConfigManager->getAnimationPropertyConfig("windowsMove"), nullptr, AVARDAMAGE_NONE);
 12+	this->fade_opacity.create(AVARTYPE_FLOAT, 1.0f, g_pConfigManager->getAnimationPropertyConfig("windowsMove"), nullptr, AVARDAMAGE_NONE);
 13 	this->focus_start.create(AVARTYPE_FLOAT, 0.0f, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), nullptr, AVARDAMAGE_NONE);
 14 	this->focus_end.create(AVARTYPE_FLOAT, 1.0f, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), nullptr, AVARDAMAGE_NONE);
 15 	this->vertical_pos.registerVar();
 16@@ -221,16 +221,22 @@ void Hy3TabGroup::updateWithGroup(Hy3Node& node) {
 17 	if (this->size.goalv() != tsize) this->size = tsize;
 18 
 19 	this->bar.updateNodeList(node.data.as_group.children);
 20+
 21+	if (node.data.as_group.lastFocusedChild != nullptr) {
 22+		this->updateStencilWindows(*node.data.as_group.lastFocusedChild);
 23+	}
 24 }
 25 
 26 void Hy3TabGroup::renderTabBar() {
 27+	static auto* const window_rounding = &HyprlandAPI::getConfigValue(PHANDLE, "decoration:rounding")->intValue;
 28+	static auto* const enter_from_top = &HyprlandAPI::getConfigValue(PHANDLE, "plugin:hy3:tabs:from_top")->intValue;
 29 
 30 	auto* monitor = g_pHyprOpenGL->m_RenderData.pMonitor;
 31 	auto scale = monitor->scale;
 32 
 33 	auto pos = this->pos.vec();
 34-	pos.y += this->bar.vertical_pos.fl();
 35 	auto size = this->size.vec();
 36+	pos.y += (this->bar.vertical_pos.fl() * size.y) * (*enter_from_top ? -1 : 1);
 37 
 38 	auto scaled_pos = Vector2D(std::round(pos.x * scale), std::round(pos.y * scale));
 39 	auto scaled_size = Vector2D(std::round(size.x * scale), std::round(size.y * scale));
 40@@ -238,7 +244,76 @@ void Hy3TabGroup::renderTabBar() {
 41 
 42 	this->bar.setSize(scaled_size);
 43 
 44+	{
 45+		glClearStencil(0);
 46+		glClear(GL_STENCIL_BUFFER_BIT);
 47+		glEnable(GL_STENCIL_TEST);
 48+		glStencilMask(0xff);
 49+		glStencilFunc(GL_ALWAYS, 1, 0xff);
 50+		glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
 51+
 52+		glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
 53+
 54+		for (auto* window: this->stencil_windows) {
 55+			if (!g_pCompositor->windowExists(window)) continue;
 56+
 57+			auto wpos = window->m_vRealPosition.vec();
 58+			auto wsize = window->m_vRealPosition.vec();
 59+
 60+			wlr_box window_box = { wpos.x, wpos.y, wsize.x, wsize.y };
 61+			g_pHyprOpenGL->renderRect(&window_box, CColor(0, 0, 0, 0), *window_rounding);
 62+		}
 63+
 64+
 65+		glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
 66+
 67+		glStencilMask(0x00);
 68+		glStencilFunc(GL_NOTEQUAL, 1, 0xff);
 69+	}
 70+
 71 	this->bar.prepareMask();
 72 	g_pHyprOpenGL->renderTexture(this->bar.mask_texture, &box, this->bar.fade_opacity.fl());
 73+
 74+	{
 75+		glClearStencil(0);
 76+		glClear(GL_STENCIL_BUFFER_BIT);
 77+		glDisable(GL_STENCIL_TEST);
 78+		glStencilMask(0xff);
 79+		glStencilFunc(GL_ALWAYS, 1, 0xff);
 80+	}
 81+
 82 	g_pHyprRenderer->damageBox(&box);
 83 }
 84+
 85+void findOverlappingWindows(Hy3Node& node, float height, std::vector<CWindow*>& windows) {
 86+	switch (node.data.type) {
 87+	case Hy3NodeData::Window:
 88+		windows.push_back(node.data.as_window);
 89+		break;
 90+	case Hy3NodeData::Group:
 91+		auto& group = node.data.as_group;
 92+
 93+		switch (group.layout) {
 94+		case Hy3GroupLayout::SplitH:
 95+			for (auto* node: group.children) {
 96+				findOverlappingWindows(*node, height, windows);
 97+			}
 98+			break;
 99+		case Hy3GroupLayout::SplitV:
100+			for (auto* node: group.children) {
101+				findOverlappingWindows(*node, height, windows);
102+				height -= node->size.y;
103+				if (height <= 0) break;
104+			}
105diff --git a/src/TabGroup.hpp b/src/TabGroup.hpp
106index eb373c4f6d6d0bca500a7828a021b8e79e3e1cd0..399e2156e21364806a8444db75cd34bd27642735 100644
107--- a/src/TabGroup.hpp
108+++ b/src/TabGroup.hpp
109@@ -3,6 +3,7 @@
110 #include <hyprland/src/helpers/AnimatedVariable.hpp>
111 #include <hyprland/src/helpers/Vector2D.hpp>
112 #include <list>
113+#include <vector>
114 
115 class Hy3TabGroup;
116 class Hy3TabBar;
117@@ -66,6 +67,11 @@ public:
118 	void renderTabBar();
119 
120 private:
121+	std::vector<CWindow*> stencil_windows;
122+
123 	// moving a Hy3TabGroup will unregister any active animations
124 	Hy3TabGroup(Hy3TabGroup&&) = delete;
125+
126+	// UB if node is not a group.
127+	void updateStencilWindows(Hy3Node&);
128 };
129diff --git a/src/main.cpp b/src/main.cpp
130index 309303b838f6221f7bdccb287417e507dc2df6ca..3ffa2dcf281ee31425d2cdf86a38be1af5f23594 100644
131--- a/src/main.cpp
132+++ b/src/main.cpp
133@@ -107,6 +107,7 @@ APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) {
134 
135 	HyprlandAPI::addConfigValue(PHANDLE, "plugin:hy3:no_gaps_when_only", SConfigValue{.intValue = 0});
136 	HyprlandAPI::addConfigValue(PHANDLE, "plugin:hy3:tabs:bar_height", SConfigValue{.intValue = 15});
137+	HyprlandAPI::addConfigValue(PHANDLE, "plugin:hy3:tabs:from_top", SConfigValue{.intValue = 0});
138 	HyprlandAPI::addConfigValue(PHANDLE, "plugin:hy3:tabs:rounding", SConfigValue{.intValue = 3});
139 
140 	g_Hy3Layout = std::make_unique<Hy3Layout>();