mirror of
https://github.com/Trensa-Organization/hy3.git
synced 2025-03-15 18:53:40 +01:00
Move tab create/update/delete to relevant locations
Also tab close animation
This commit is contained in:
parent
8715516d93
commit
910fcc0f25
4 changed files with 118 additions and 71 deletions
|
@ -18,6 +18,20 @@ void errorNotif() {
|
|||
|
||||
Hy3GroupData::Hy3GroupData(Hy3GroupLayout layout): layout(layout) {}
|
||||
|
||||
Hy3GroupData::Hy3GroupData(Hy3GroupData&& from) {
|
||||
this->layout = from.layout;
|
||||
this->children = std::move(from.children);
|
||||
this->group_focused = from.group_focused;
|
||||
this->focused_child = from.focused_child;
|
||||
from.focused_child = nullptr;
|
||||
this->tab_bar = from.tab_bar;
|
||||
from.tab_bar = nullptr;
|
||||
}
|
||||
|
||||
Hy3GroupData::~Hy3GroupData() {
|
||||
if (this->tab_bar != nullptr) this->tab_bar->bar.beginDestroy();
|
||||
}
|
||||
|
||||
Hy3NodeData::Hy3NodeData(): Hy3NodeData((CWindow*)nullptr) {}
|
||||
|
||||
Hy3NodeData::Hy3NodeData(CWindow *window): type(Hy3NodeData::Window) {
|
||||
|
@ -151,6 +165,8 @@ void Hy3Node::recalcSizePosRecursive(bool force) {
|
|||
break;
|
||||
}
|
||||
|
||||
this->updateTabBar();
|
||||
|
||||
child->recalcSizePosRecursive(force);
|
||||
return;
|
||||
}
|
||||
|
@ -200,6 +216,8 @@ void Hy3Node::recalcSizePosRecursive(bool force) {
|
|||
|
||||
child->recalcSizePosRecursive(force);
|
||||
}
|
||||
|
||||
this->updateTabBar();
|
||||
}
|
||||
|
||||
void Hy3Node::setHidden(bool hidden) {
|
||||
|
@ -227,6 +245,17 @@ bool Hy3Node::isUrgent() {
|
|||
}
|
||||
}
|
||||
|
||||
bool Hy3Node::isIndirectlyFocused() {
|
||||
Hy3Node* node = this;
|
||||
|
||||
while (node->parent != nullptr) {
|
||||
if (node->parent->data.as_group.focused_child != node) return false;
|
||||
node = node->parent;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string Hy3Node::getTitle() {
|
||||
switch (this->data.type) {
|
||||
case Hy3NodeData::Window:
|
||||
|
@ -272,14 +301,30 @@ void Hy3Node::markFocused() {
|
|||
this->data.as_group.focused_child = nullptr;
|
||||
}
|
||||
|
||||
auto* node2 = node;
|
||||
while (node2->parent != nullptr) {
|
||||
node2->parent->data.as_group.focused_child = node2;
|
||||
node2->parent->data.as_group.group_focused = false;
|
||||
node2 = node2->parent;
|
||||
}
|
||||
|
||||
while (node->parent != nullptr) {
|
||||
node->parent->data.as_group.focused_child = node;
|
||||
node->parent->data.as_group.group_focused = false;
|
||||
node->parent->updateTabBar();
|
||||
node = node->parent;
|
||||
}
|
||||
while (node2->parent != nullptr) {
|
||||
node2->parent->data.as_group.focused_child = node2;
|
||||
node2->parent->data.as_group.group_focused = false;
|
||||
node2->parent->updateTabBar();
|
||||
node2 = node2->parent;
|
||||
}
|
||||
|
||||
if (oldfocus != nullptr) {
|
||||
oldfocus->updateDecos();
|
||||
while (oldfocus != nullptr) {
|
||||
oldfocus->updateTabBar();
|
||||
oldfocus = oldfocus->parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -462,6 +507,20 @@ void Hy3Node::swapData(Hy3Node& a, Hy3Node& b) {
|
|||
}
|
||||
}
|
||||
|
||||
void Hy3Node::updateTabBar() {
|
||||
if (this->data.type == Hy3NodeData::Group) {
|
||||
auto& group = this->data.as_group;
|
||||
|
||||
if (group.layout == Hy3GroupLayout::Tabbed) {
|
||||
if (group.tab_bar == nullptr) group.tab_bar = &this->layout->tab_groups.emplace_back(*this);
|
||||
group.tab_bar->updateWithGroup(*this);
|
||||
} else if (group.tab_bar != nullptr) {
|
||||
group.tab_bar->bar.beginDestroy();
|
||||
group.tab_bar = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Hy3Node::updateDecos() {
|
||||
switch (this->data.type) {
|
||||
case Hy3NodeData::Window:
|
||||
|
@ -1495,11 +1554,12 @@ void renderTabs(Hy3Node& node);
|
|||
void Hy3Layout::renderHook(void*, std::any data) {
|
||||
auto render_stage = std::any_cast<eRenderStage>(data);
|
||||
if (render_stage == RENDER_POST_WINDOWS) {
|
||||
auto* monitor = g_pHyprOpenGL->m_RenderData.pMonitor;
|
||||
auto workspace = monitor->activeWorkspace;
|
||||
auto* root = g_Hy3Layout->getWorkspaceRootGroup(workspace);
|
||||
|
||||
if (root != nullptr) renderTabsRecursive(*root);
|
||||
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 entry++->renderTabBar();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1522,11 +1582,5 @@ void renderTabsRecursive(Hy3Node& node) {
|
|||
void renderTabs(Hy3Node& node) {
|
||||
auto& group = node.data.as_group;
|
||||
|
||||
if (!group.tab_bar) {
|
||||
group.tab_bar = Hy3TabGroup::new_(node);
|
||||
} else {
|
||||
group.tab_bar->updateWithGroup(node);
|
||||
}
|
||||
|
||||
group.tab_bar->renderTabBar();
|
||||
}
|
||||
|
|
|
@ -27,14 +27,16 @@ struct Hy3GroupData {
|
|||
std::list<Hy3Node*> children;
|
||||
bool group_focused = true;
|
||||
Hy3Node* focused_child = nullptr;
|
||||
std::shared_ptr<Hy3TabGroup> tab_bar;
|
||||
Hy3TabGroup* tab_bar = nullptr;
|
||||
|
||||
bool hasChild(Hy3Node* child);
|
||||
|
||||
Hy3GroupData(Hy3GroupLayout layout);
|
||||
~Hy3GroupData();
|
||||
|
||||
private:
|
||||
Hy3GroupData(Hy3GroupData&&) = default;
|
||||
Hy3GroupData(Hy3GroupData&&);
|
||||
Hy3GroupData(const Hy3GroupData&) = delete;
|
||||
|
||||
friend class Hy3NodeData;
|
||||
};
|
||||
|
@ -81,6 +83,7 @@ struct Hy3Node {
|
|||
void updateDecos();
|
||||
void setHidden(bool hidden);
|
||||
bool isUrgent();
|
||||
bool isIndirectlyFocused();
|
||||
std::string getTitle();
|
||||
|
||||
bool operator==(const Hy3Node&) const;
|
||||
|
@ -95,6 +98,9 @@ struct Hy3Node {
|
|||
Hy3Node* intoGroup(Hy3GroupLayout);
|
||||
|
||||
static void swapData(Hy3Node&, Hy3Node&);
|
||||
|
||||
private:
|
||||
void updateTabBar();
|
||||
};
|
||||
|
||||
class Hy3Layout: public IHyprLayout {
|
||||
|
@ -135,6 +141,7 @@ public:
|
|||
static void renderHook(void*, std::any);
|
||||
|
||||
std::list<Hy3Node> nodes;
|
||||
std::list<Hy3TabGroup> tab_groups;
|
||||
private:
|
||||
struct {
|
||||
bool started = false;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include <hyprland/src/Compositor.hpp>
|
||||
#include <cairo/cairo.h>
|
||||
|
||||
Hy3TabBarEntry::Hy3TabBarEntry(std::shared_ptr<Hy3TabGroup> tab_group, Hy3Node& node): tab_group(tab_group), node(node) {
|
||||
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);
|
||||
this->width.create(AVARTYPE_FLOAT, -1.0f, g_pConfigManager->getAnimationPropertyConfig("windowsMove"), nullptr, AVARDAMAGE_NONE);
|
||||
|
||||
|
@ -24,25 +24,24 @@ bool Hy3TabBarEntry::operator==(const Hy3TabBarEntry& entry) const {
|
|||
return this->node == entry.node;
|
||||
}
|
||||
|
||||
void Hy3TabBarEntry::prepareTexture(float scale, Vector2D size) {
|
||||
void Hy3TabBarEntry::prepareTexture(float scale, wlr_box& box) {
|
||||
static const auto* rounding_setting = &HyprlandAPI::getConfigValue(PHANDLE, "plugin:hy3:tabs:rounding")->intValue;
|
||||
|
||||
auto width = size.x * scale;
|
||||
auto height = size.y * scale;
|
||||
auto width = box.width;
|
||||
auto height = box.height;
|
||||
|
||||
auto rounding = std::min((double) *rounding_setting, std::min(width * 0.5, height * 0.5));
|
||||
|
||||
if (this->needs_redraw
|
||||
|| this->texture.m_iTexID == 0
|
||||
|| this->last_render_rounding == rounding
|
||||
|| this->last_render_scale == scale
|
||||
|| this->last_render_size == size
|
||||
|| true // todo
|
||||
if (this->texture.m_iTexID == 0
|
||||
|| this->last_render_rounding != rounding
|
||||
|| this->last_render_focused != focused
|
||||
|| this->last_render_urgent != urgent
|
||||
|| !wlr_box_equal(&this->last_render_box, &box)
|
||||
) {
|
||||
this->needs_redraw = false;
|
||||
this->last_render_rounding = rounding;
|
||||
this->last_render_scale = scale;
|
||||
this->last_render_size = size;
|
||||
this->last_render_focused = this->focused;
|
||||
this->last_render_urgent = this->urgent;
|
||||
this->last_render_box = box;
|
||||
|
||||
auto cairo_surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
|
||||
auto cairo = cairo_create(cairo_surface);
|
||||
|
@ -95,17 +94,6 @@ void Hy3TabBarEntry::prepareTexture(float scale, Vector2D size) {
|
|||
}
|
||||
}
|
||||
|
||||
void Hy3TabBarEntry::animateRemoval() {
|
||||
if (this->width.goalf() == 0.0) return;
|
||||
this->width = 0.0;
|
||||
|
||||
// not removing the callback is required for soundness, as the animation will
|
||||
// be deleted once the callback ends.
|
||||
this->width.setCallbackOnEnd([this](void*) {
|
||||
this->tab_group->bar.entries.remove(*this);
|
||||
}, false);
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -120,6 +108,12 @@ Hy3TabBar::Hy3TabBar() {
|
|||
this->fade_opacity = 1.0;
|
||||
}
|
||||
|
||||
void Hy3TabBar::beginDestroy() {
|
||||
this->vertical_pos = 1.0;
|
||||
this->fade_opacity = 0.0;
|
||||
this->fade_opacity.setCallbackOnEnd([this](void*) { this->destroy = true; });
|
||||
}
|
||||
|
||||
void Hy3TabBar::focusNode(Hy3Node* node) {
|
||||
this->focused_node = node;
|
||||
|
||||
|
@ -180,7 +174,7 @@ void Hy3TabBar::updateNodeList(std::list<Hy3Node*>& nodes) {
|
|||
entry = *moved;
|
||||
removed_entries.erase(moved);
|
||||
} else {
|
||||
entry = this->entries.emplace(entry, this->group.lock(), **node);
|
||||
entry = this->entries.emplace(entry, *this, **node);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -190,10 +184,7 @@ void Hy3TabBar::updateNodeList(std::list<Hy3Node*>& nodes) {
|
|||
}
|
||||
|
||||
// set stats from node data
|
||||
auto* root = *node;
|
||||
while (root->parent != nullptr) root = root->parent;
|
||||
auto* focused = root->getFocusedNode();
|
||||
entry->focused = focused == *node;
|
||||
entry->focused = (*node)->isIndirectlyFocused();
|
||||
entry->urgent = (*node)->isUrgent();
|
||||
|
||||
node = std::next(node);
|
||||
|
@ -202,7 +193,8 @@ void Hy3TabBar::updateNodeList(std::list<Hy3Node*>& nodes) {
|
|||
|
||||
// initiate remove animations for any removed entries
|
||||
for (auto& entry: removed_entries) {
|
||||
entry->animateRemoval();
|
||||
if (entry->width.goalf() != 0.0) entry->width = 0.0;
|
||||
if (entry->width.fl() == 0.0) this->entries.erase(entry);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -251,27 +243,20 @@ void Hy3TabBar::setSize(Vector2D size) {
|
|||
this->size = size;
|
||||
}
|
||||
|
||||
Hy3TabGroup::Hy3TabGroup() {
|
||||
Hy3TabGroup::Hy3TabGroup(Hy3Node& node) {
|
||||
this->pos.create(AVARTYPE_VECTOR, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), nullptr, AVARDAMAGE_NONE);
|
||||
this->size.create(AVARTYPE_VECTOR, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), nullptr, AVARDAMAGE_NONE);
|
||||
this->pos.registerVar();
|
||||
this->size.registerVar();
|
||||
}
|
||||
|
||||
std::shared_ptr<Hy3TabGroup> Hy3TabGroup::new_(Hy3Node& node) {
|
||||
auto ptr = std::shared_ptr<Hy3TabGroup>(new Hy3TabGroup());
|
||||
ptr->self = ptr;
|
||||
ptr->bar.group = ptr;
|
||||
|
||||
ptr->updateWithGroup(node);
|
||||
ptr->bar.updateAnimations(true);
|
||||
ptr->pos.warp();
|
||||
ptr->size.warp();
|
||||
|
||||
return ptr;
|
||||
this->updateWithGroup(node);
|
||||
this->bar.updateAnimations(true);
|
||||
this->pos.warp();
|
||||
this->size.warp();
|
||||
}
|
||||
|
||||
void Hy3TabGroup::updateWithGroup(Hy3Node& node) {
|
||||
Debug::log(LOG, "updated tab bar for %p", &node);
|
||||
static const auto* gaps_in = &HyprlandAPI::getConfigValue(PHANDLE, "general:gaps_in")->intValue;
|
||||
static const auto* bar_height = &HyprlandAPI::getConfigValue(PHANDLE, "plugin:hy3:tabs:bar_height")->intValue;
|
||||
|
||||
|
@ -340,8 +325,6 @@ void Hy3TabGroup::renderTabBar() {
|
|||
Vector2D entry_size = { (entry.width.fl() * size.x) - *padding, size.y };
|
||||
if (entry_size.x < 0 || entry_size.y < 0) return;
|
||||
|
||||
entry.prepareTexture(scale, entry_size);
|
||||
|
||||
wlr_box box = {
|
||||
(pos.x + (entry.offset.fl() * size.x) + (*padding * 0.5)) * scale,
|
||||
scaled_pos.y,
|
||||
|
@ -349,6 +332,7 @@ void Hy3TabGroup::renderTabBar() {
|
|||
scaled_size.y,
|
||||
};
|
||||
|
||||
entry.prepareTexture(scale, box);
|
||||
g_pHyprOpenGL->renderTexture(entry.texture, &box, this->bar.fade_opacity.fl());
|
||||
};
|
||||
|
||||
|
|
|
@ -16,31 +16,31 @@ struct Hy3TabBarEntry {
|
|||
std::string window_title;
|
||||
bool focused = false;
|
||||
bool urgent = false;
|
||||
bool needs_redraw = false;
|
||||
CTexture texture;
|
||||
CAnimatedVariable offset; // offset 0, 0.0-1.0 of total bar
|
||||
CAnimatedVariable width; // 0.0-1.0 of total bar
|
||||
std::shared_ptr<Hy3TabGroup> tab_group;
|
||||
Hy3TabBar& tab_bar;
|
||||
Hy3Node& node; // only used for comparioson. do not deref.
|
||||
Vector2D last_render_size;
|
||||
float last_render_scale = 0.0;
|
||||
wlr_box last_render_box;
|
||||
float last_render_rounding = 0.0;
|
||||
bool last_render_focused = false;
|
||||
bool last_render_urgent = false;
|
||||
|
||||
Hy3TabBarEntry(std::shared_ptr<Hy3TabGroup>, Hy3Node&);
|
||||
Hy3TabBarEntry(Hy3TabBar&, Hy3Node&);
|
||||
bool operator==(const Hy3Node&) const;
|
||||
bool operator==(const Hy3TabBarEntry&) const;
|
||||
|
||||
void prepareTexture(float, Vector2D);
|
||||
|
||||
void animateRemoval();
|
||||
void prepareTexture(float, wlr_box&);
|
||||
};
|
||||
|
||||
class Hy3TabBar {
|
||||
public:
|
||||
bool destroy = false;
|
||||
CAnimatedVariable vertical_pos;
|
||||
CAnimatedVariable fade_opacity;
|
||||
|
||||
Hy3TabBar();
|
||||
void beginDestroy();
|
||||
|
||||
void focusNode(Hy3Node*);
|
||||
void updateNodeList(std::list<Hy3Node*>& nodes);
|
||||
|
@ -48,7 +48,6 @@ public:
|
|||
void setSize(Vector2D);
|
||||
|
||||
std::list<Hy3TabBarEntry> entries;
|
||||
std::weak_ptr<Hy3TabGroup> group;
|
||||
private:
|
||||
Hy3Node* focused_node = nullptr;
|
||||
CAnimatedVariable focus_opacity;
|
||||
|
@ -56,6 +55,10 @@ private:
|
|||
CAnimatedVariable focus_end;
|
||||
|
||||
Vector2D size;
|
||||
|
||||
// Tab bar entries take a reference to `this`.
|
||||
Hy3TabBar(Hy3TabBar&&) = delete;
|
||||
Hy3TabBar(const Hy3TabBar&) = delete;
|
||||
};
|
||||
|
||||
class Hy3TabGroup {
|
||||
|
@ -65,7 +68,7 @@ public:
|
|||
CAnimatedVariable size;
|
||||
|
||||
// initialize a group with the given node. UB if node is not a group.
|
||||
static std::shared_ptr<Hy3TabGroup> new_(Hy3Node&);
|
||||
Hy3TabGroup(Hy3Node&);
|
||||
|
||||
// update tab bar with node position and data. UB if node is not a group.
|
||||
void updateWithGroup(Hy3Node&);
|
||||
|
@ -73,7 +76,6 @@ public:
|
|||
void renderTabBar();
|
||||
|
||||
private:
|
||||
std::weak_ptr<Hy3TabGroup> self;
|
||||
std::vector<CWindow*> stencil_windows;
|
||||
|
||||
Hy3TabGroup();
|
||||
|
|
Loading…
Add table
Reference in a new issue