diff --git a/src/Hy3Layout.cpp b/src/Hy3Layout.cpp index d80cf1c..176fd8a 100644 --- a/src/Hy3Layout.cpp +++ b/src/Hy3Layout.cpp @@ -1588,36 +1588,46 @@ void renderTabsRecursive(Hy3Node& node); 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); - if (render_stage == RENDER_POST_WINDOW) { + + 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->bar.destroy) tab_groups.erase(entry++); - else if (entry->target_window == g_pHyprOpenGL->m_pCurrentWindow) entry++->renderTabBar(); - else entry++; - } - } -} - -void renderTabsRecursive(Hy3Node& node) { - if (node.data.type == Hy3NodeData::Group) { - for (auto* child: node.data.as_group.children) { - if (node.data.as_group.layout != Hy3GroupLayout::Tabbed - || node.data.as_group.focused_child == child) - { - renderTabsRecursive(*child); + 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 (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); } - if (node.data.as_group.layout == Hy3GroupLayout::Tabbed) { - renderTabs(node); - } + } break; + default: + break; } } - -void renderTabs(Hy3Node& node) { - auto& group = node.data.as_group; - - group.tab_bar->renderTabBar(); -} diff --git a/src/TabGroup.cpp b/src/TabGroup.cpp index a85f5e4..a2403d0 100644 --- a/src/TabGroup.cpp +++ b/src/TabGroup.cpp @@ -4,6 +4,8 @@ #include #include +#include +#include Hy3TabBarEntry::Hy3TabBarEntry(Hy3TabBar& tab_bar, Hy3Node& node): tab_bar(tab_bar), node(node) { this->offset.create(AVARTYPE_FLOAT, -1.0f, g_pConfigManager->getAnimationPropertyConfig("windowsMove"), nullptr, AVARDAMAGE_NONE); @@ -12,6 +14,11 @@ 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; }; + + this->offset.setUpdateCallback(update_callback); + this->width.setUpdateCallback(update_callback); + this->window_title = node.getTitle(); this->urgent = node.isUrgent(); } @@ -24,6 +31,20 @@ bool Hy3TabBarEntry::operator==(const Hy3TabBarEntry& entry) const { return this->node == entry.node; } +void Hy3TabBarEntry::setFocused(bool focused) { + if (this->focused != focused) { + this->focused = focused; + this->tab_bar.needs_redraw = true; + } +} + +void Hy3TabBarEntry::setUrgent(bool urgent) { + if (this->urgent != urgent) { + this->urgent = urgent; + this->tab_bar.needs_redraw = true; + } +} + void Hy3TabBarEntry::prepareTexture(float scale, wlr_box& box) { static const auto* rounding_setting = &HyprlandAPI::getConfigValue(PHANDLE, "plugin:hy3:tabs:rounding")->intValue; @@ -96,13 +117,14 @@ void Hy3TabBarEntry::prepareTexture(float scale, wlr_box& box) { Hy3TabBar::Hy3TabBar() { this->vertical_pos.create(AVARTYPE_FLOAT, 1.0f, g_pConfigManager->getAnimationPropertyConfig("windowsMove"), nullptr, AVARDAMAGE_NONE); - this->fade_opacity.create(AVARTYPE_FLOAT, 1.0f, g_pConfigManager->getAnimationPropertyConfig("windowsMove"), nullptr, AVARDAMAGE_NONE); - this->focus_start.create(AVARTYPE_FLOAT, 0.0f, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), nullptr, AVARDAMAGE_NONE); - this->focus_end.create(AVARTYPE_FLOAT, 1.0f, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), nullptr, AVARDAMAGE_NONE); + this->fade_opacity.create(AVARTYPE_FLOAT, 0.0f, g_pConfigManager->getAnimationPropertyConfig("windowsMove"), nullptr, AVARDAMAGE_NONE); this->vertical_pos.registerVar(); this->fade_opacity.registerVar(); - this->focus_start.registerVar(); - this->focus_end.registerVar(); + + auto update_callback = [this](void*) { this->needs_redraw = true; }; + + this->vertical_pos.setUpdateCallback(update_callback); + this->fade_opacity.setUpdateCallback(update_callback); this->vertical_pos = 0.0; this->fade_opacity = 1.0; @@ -114,22 +136,6 @@ void Hy3TabBar::beginDestroy() { this->fade_opacity.setCallbackOnEnd([this](void*) { this->destroy = true; }); } -void Hy3TabBar::focusNode(Hy3Node* node) { - this->focused_node = node; - - if (this->focused_node == nullptr) { - this->focus_start = 0.0; - this->focus_end = 1.0; - } else { - auto entry = std::find(this->entries.begin(), this->entries.end(), *node); - - if (entry != this->entries.end()) { - this->focus_start = entry->offset.goalf(); - this->focus_end = entry->offset.goalf() + entry->width.goalf(); - } - } -} - void Hy3TabBar::updateNodeList(std::list& nodes) { std::list::iterator> removed_entries; @@ -184,8 +190,8 @@ void Hy3TabBar::updateNodeList(std::list& nodes) { } // set stats from node data - entry->focused = (*node)->isIndirectlyFocused(); - entry->urgent = (*node)->isUrgent(); + entry->setFocused((*node)->isIndirectlyFocused()); + entry->setUrgent((*node)->isUrgent()); node = std::next(node); if (entry != this->entries.end()) entry = std::next(entry); @@ -288,7 +294,27 @@ void Hy3TabGroup::renderTabBar() { auto scaled_pos = Vector2D(std::round(pos.x * scale), std::round(pos.y * scale)); auto scaled_size = Vector2D(std::round(size.x * scale), std::round(size.y * scale)); - auto box = wlr_box { scaled_pos.x, scaled_pos.y, scaled_size.x, scaled_size.y }; + 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) { + 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); + 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; this->bar.setSize(scaled_size); @@ -354,7 +380,7 @@ void Hy3TabGroup::renderTabBar() { glStencilFunc(GL_ALWAYS, 1, 0xff); } - g_pHyprRenderer->damageBox(&box); + monitor->addDamage(&box); } void findOverlappingWindows(Hy3Node& node, float height, std::vector& windows) { diff --git a/src/TabGroup.hpp b/src/TabGroup.hpp index 7daf1ec..e01daa2 100644 --- a/src/TabGroup.hpp +++ b/src/TabGroup.hpp @@ -30,19 +30,21 @@ struct Hy3TabBarEntry { bool operator==(const Hy3Node&) const; bool operator==(const Hy3TabBarEntry&) const; + void setFocused(bool); + void setUrgent(bool); void prepareTexture(float, wlr_box&); }; class Hy3TabBar { public: bool destroy = false; + bool needs_redraw = true; CAnimatedVariable vertical_pos; CAnimatedVariable fade_opacity; Hy3TabBar(); void beginDestroy(); - void focusNode(Hy3Node*); void updateNodeList(std::list& nodes); void updateAnimations(bool warp = false); void setSize(Vector2D); @@ -50,10 +52,6 @@ public: std::list entries; private: Hy3Node* focused_node = nullptr; - CAnimatedVariable focus_opacity; - CAnimatedVariable focus_start; - CAnimatedVariable focus_end; - Vector2D size; // Tab bar entries take a reference to `this`. @@ -78,6 +76,8 @@ public: private: std::vector stencil_windows; + Vector2D last_pos; + Vector2D last_size; Hy3TabGroup();