diff --git a/src/Hy3Layout.cpp b/src/Hy3Layout.cpp index 831f02c..7371b89 100644 --- a/src/Hy3Layout.cpp +++ b/src/Hy3Layout.cpp @@ -1229,6 +1229,7 @@ void Hy3Layout::replaceWindowDataWith(CWindow* from, CWindow* to) { } std::unique_ptr renderHookPtr = std::make_unique(Hy3Layout::renderHook); +std::unique_ptr tickHookPtr = std::make_unique(Hy3Layout::tickHook); void Hy3Layout::onEnable() { for (auto &window : g_pCompositor->m_vWindows) { @@ -1242,11 +1243,13 @@ void Hy3Layout::onEnable() { } HyprlandAPI::registerCallbackStatic(PHANDLE, "render", renderHookPtr.get()); + HyprlandAPI::registerCallbackStatic(PHANDLE, "tick", tickHookPtr.get()); selection_hook::enable(); } void Hy3Layout::onDisable() { HyprlandAPI::unregisterCallback(PHANDLE, renderHookPtr.get()); + HyprlandAPI::unregisterCallback(PHANDLE, tickHookPtr.get()); selection_hook::disable(); this->nodes.clear(); } @@ -1531,6 +1534,57 @@ bool Hy3Layout::shouldRenderSelected(CWindow* window) { } } +void Hy3Layout::renderHook(void*, std::any data) { + static bool rendering_normally = false; + static std::vector rendered_groups; + + auto render_stage = std::any_cast(data); + + switch (render_stage) { + case RENDER_PRE_WINDOWS: + rendering_normally = true; + rendered_groups.clear(); + break; + case RENDER_POST_WINDOW: + if (!rendering_normally) break; + + for (auto& entry: g_Hy3Layout->tab_groups) { + if (entry.target_window == g_pHyprOpenGL->m_pCurrentWindow + && std::find(rendered_groups.begin(), rendered_groups.end(), &entry) == rendered_groups.end() + ) { + entry.renderTabBar(); + rendered_groups.push_back(&entry); + } + } + + break; + case RENDER_POST_WINDOWS: + rendering_normally = false; + + for (auto& entry: g_Hy3Layout->tab_groups) { + if (entry.target_window->m_iMonitorID == g_pHyprOpenGL->m_RenderData.pMonitor->ID + && std::find(rendered_groups.begin(), rendered_groups.end(), &entry) == rendered_groups.end() + ) { + entry.renderTabBar(); + } + } + + break; + default: + break; + } +} + +void Hy3Layout::tickHook(void*, std::any) { + auto& tab_groups = g_Hy3Layout->tab_groups; + auto entry = tab_groups.begin(); + while (entry != tab_groups.end()) { + entry->damageIfRequired(); + if (entry->bar.destroy) tab_groups.erase(entry++); + else entry = std::next(entry); + } +} + std::string Hy3Node::debugNode() { std::stringstream buf; std::string addr = "0x" + std::to_string((size_t)this); @@ -1580,55 +1634,3 @@ std::string Hy3Node::debugNode() { return buf.str(); } - -// Recursively render tabs on all tab groups. -void renderTabsRecursive(Hy3Node& node); - -// Render tabs for the provided node, blindly assuming it is a tab group. -void renderTabs(Hy3Node& node); - -void Hy3Layout::renderHook(void*, std::any data) { - static bool rendering_normally = false; - static std::vector rendered_groups; - - auto render_stage = std::any_cast(data); - - switch (render_stage) { - case RENDER_PRE_WINDOWS: - rendering_normally = true; - rendered_groups.clear(); - break; - case RENDER_POST_WINDOW: { - if (!rendering_normally) break; - - auto& tab_groups = g_Hy3Layout->tab_groups; - auto entry = tab_groups.begin(); - while (entry != tab_groups.end()) { - if (entry->target_window == g_pHyprOpenGL->m_pCurrentWindow && std::find(rendered_groups.begin(), rendered_groups.end(), &*entry) == rendered_groups.end()) { - entry->renderTabBar(); - rendered_groups.push_back(&*entry); - } - - entry = std::next(entry); - } - } break; - case RENDER_POST_WINDOWS: { - rendering_normally = false; - - auto& tab_groups = g_Hy3Layout->tab_groups; - auto entry = tab_groups.begin(); - while (entry != tab_groups.end()) { - if (entry->target_window->m_iMonitorID == g_pHyprOpenGL->m_RenderData.pMonitor->ID - && std::find(rendered_groups.begin(), rendered_groups.end(), &*entry) == rendered_groups.end() - ) { - entry->renderTabBar(); - if (entry->bar.destroy) tab_groups.erase(entry++); - } - - entry = std::next(entry); - } - } break; - default: - break; - } -} diff --git a/src/Hy3Layout.hpp b/src/Hy3Layout.hpp index 1196471..d065d06 100644 --- a/src/Hy3Layout.hpp +++ b/src/Hy3Layout.hpp @@ -139,6 +139,7 @@ public: Hy3Node* getWorkspaceFocusedNode(const int&); static void renderHook(void*, std::any); + static void tickHook(void*, std::any); std::list nodes; std::list tab_groups; diff --git a/src/TabGroup.cpp b/src/TabGroup.cpp index b9eb99e..32ddfb6 100644 --- a/src/TabGroup.cpp +++ b/src/TabGroup.cpp @@ -14,7 +14,7 @@ Hy3TabBarEntry::Hy3TabBarEntry(Hy3TabBar& tab_bar, Hy3Node& node): tab_bar(tab_b this->offset.registerVar(); this->width.registerVar(); - auto update_callback = [this](void*) { this->tab_bar.needs_redraw = true; }; + auto update_callback = [this](void*) { this->tab_bar.dirty = true; }; this->offset.setUpdateCallback(update_callback); this->width.setUpdateCallback(update_callback); @@ -34,14 +34,14 @@ bool Hy3TabBarEntry::operator==(const Hy3TabBarEntry& entry) const { void Hy3TabBarEntry::setFocused(bool focused) { if (this->focused != focused) { this->focused = focused; - this->tab_bar.needs_redraw = true; + this->tab_bar.dirty = true; } } void Hy3TabBarEntry::setUrgent(bool urgent) { if (this->urgent != urgent) { this->urgent = urgent; - this->tab_bar.needs_redraw = true; + this->tab_bar.dirty = true; } } @@ -121,7 +121,7 @@ Hy3TabBar::Hy3TabBar() { this->vertical_pos.registerVar(); this->fade_opacity.registerVar(); - auto update_callback = [this](void*) { this->needs_redraw = true; }; + auto update_callback = [this](void*) { this->dirty = true; }; this->vertical_pos.setUpdateCallback(update_callback); this->fade_opacity.setUpdateCallback(update_callback); @@ -280,6 +280,31 @@ void Hy3TabGroup::updateWithGroup(Hy3Node& node) { } } +void Hy3TabGroup::damageIfRequired() { + static const auto* enter_from_top = &HyprlandAPI::getConfigValue(PHANDLE, "plugin:hy3:tabs:from_top")->intValue; + + auto pos = this->pos.vec(); + auto size = this->size.vec(); + pos.y += (this->bar.vertical_pos.fl() * size.y) * (*enter_from_top ? -1 : 1); + + if (this->last_pos != pos || this->last_size != size) { + wlr_box damage_box = { this->last_pos.x, this->last_pos.y, this->last_size.x, this->last_size.y }; + g_pHyprRenderer->damageBox(&damage_box); + + this->bar.damaged = true; + this->last_pos = pos; + this->last_size = size; + } + + if (this->bar.destroy || this->bar.dirty) { + wlr_box damage_box = { pos.x, pos.y, size.x, size.y }; + g_pHyprRenderer->damageBox(&damage_box); + + this->bar.damaged = true; + this->bar.dirty = false; + } +} + void Hy3TabGroup::renderTabBar() { static const auto* window_rounding = &HyprlandAPI::getConfigValue(PHANDLE, "decoration:rounding")->intValue; static const auto* enter_from_top = &HyprlandAPI::getConfigValue(PHANDLE, "plugin:hy3:tabs:from_top")->intValue; @@ -296,25 +321,16 @@ void Hy3TabGroup::renderTabBar() { auto scaled_size = Vector2D(std::round(size.x * scale), std::round(size.y * scale)); wlr_box box = { scaled_pos.x, scaled_pos.y, scaled_size.x, scaled_size.y }; - this->bar.needs_redraw = true; - /*if (!this->bar.needs_redraw) { + if (!this->bar.damaged) { pixman_region32 damage; pixman_region32_init(&damage); pixman_region32_intersect_rect(&damage, g_pHyprOpenGL->m_RenderData.pDamage, box.x, box.y, box.width, box.height); - this->bar.needs_redraw = pixman_region32_not_empty(&damage); + this->bar.damaged = pixman_region32_not_empty(&damage); pixman_region32_fini(&damage); - }*/ - - if (this->bar.destroy || this->last_pos != scaled_pos || this->last_size != scaled_size) { - wlr_box damage_box = { this->last_pos.x, this->last_pos.y, this->last_size.x, this->last_size.y }; - monitor->addDamage(&damage_box); - this->last_pos = scaled_pos; - this->last_size = scaled_size; - this->bar.needs_redraw = true; } - if (!this->bar.needs_redraw || this->bar.destroy) return; - this->bar.needs_redraw = false; + if (!this->bar.damaged || this->bar.destroy) return; + this->bar.damaged = false; this->bar.setSize(scaled_size); @@ -379,8 +395,6 @@ void Hy3TabGroup::renderTabBar() { glStencilMask(0xff); glStencilFunc(GL_ALWAYS, 1, 0xff); } - - monitor->addDamage(&box); } void findOverlappingWindows(Hy3Node& node, float height, std::vector& windows) { diff --git a/src/TabGroup.hpp b/src/TabGroup.hpp index e01daa2..2834a3c 100644 --- a/src/TabGroup.hpp +++ b/src/TabGroup.hpp @@ -38,7 +38,8 @@ struct Hy3TabBarEntry { class Hy3TabBar { public: bool destroy = false; - bool needs_redraw = true; + bool dirty = true; + bool damaged = true; CAnimatedVariable vertical_pos; CAnimatedVariable fade_opacity; @@ -71,6 +72,7 @@ public: // update tab bar with node position and data. UB if node is not a group. void updateWithGroup(Hy3Node&); + void damageIfRequired(); // render the scaled tab bar on the current monitor. void renderTabBar();