mirror of
https://github.com/Trensa-Organization/hy3.git
synced 2025-03-15 18:53:40 +01:00
Add text in tab bars
This commit is contained in:
parent
7061981a1e
commit
1a490734ba
5 changed files with 140 additions and 19 deletions
|
@ -496,6 +496,7 @@ Hy3Node* Hy3Node::intoGroup(Hy3GroupLayout layout) {
|
|||
this->data.as_group.group_focused = false;
|
||||
this->data.as_group.focused_child = node;
|
||||
this->recalcSizePosRecursive();
|
||||
this->updateTabBarRecursive();
|
||||
|
||||
return node;
|
||||
}
|
||||
|
@ -583,6 +584,15 @@ void Hy3Node::updateTabBar() {
|
|||
}
|
||||
}
|
||||
|
||||
void Hy3Node::updateTabBarRecursive() {
|
||||
auto* node = this;
|
||||
|
||||
while (node != nullptr) {
|
||||
node->updateTabBar();
|
||||
node = node->parent;
|
||||
}
|
||||
}
|
||||
|
||||
void Hy3Node::updateDecos() {
|
||||
switch (this->data.type) {
|
||||
case Hy3NodeData::Window:
|
||||
|
@ -1243,6 +1253,7 @@ void Hy3Layout::replaceWindowDataWith(CWindow* from, CWindow* to) {
|
|||
}
|
||||
|
||||
std::unique_ptr<HOOK_CALLBACK_FN> renderHookPtr = std::make_unique<HOOK_CALLBACK_FN>(Hy3Layout::renderHook);
|
||||
std::unique_ptr<HOOK_CALLBACK_FN> windowTitleHookPtr = std::make_unique<HOOK_CALLBACK_FN>(Hy3Layout::windowTitleHook);
|
||||
std::unique_ptr<HOOK_CALLBACK_FN> tickHookPtr = std::make_unique<HOOK_CALLBACK_FN>(Hy3Layout::tickHook);
|
||||
|
||||
void Hy3Layout::onEnable() {
|
||||
|
@ -1257,12 +1268,14 @@ void Hy3Layout::onEnable() {
|
|||
}
|
||||
|
||||
HyprlandAPI::registerCallbackStatic(PHANDLE, "render", renderHookPtr.get());
|
||||
HyprlandAPI::registerCallbackStatic(PHANDLE, "windowTitle", windowTitleHookPtr.get());
|
||||
HyprlandAPI::registerCallbackStatic(PHANDLE, "tick", tickHookPtr.get());
|
||||
selection_hook::enable();
|
||||
}
|
||||
|
||||
void Hy3Layout::onDisable() {
|
||||
HyprlandAPI::unregisterCallback(PHANDLE, renderHookPtr.get());
|
||||
HyprlandAPI::unregisterCallback(PHANDLE, windowTitleHookPtr.get());
|
||||
HyprlandAPI::unregisterCallback(PHANDLE, tickHookPtr.get());
|
||||
selection_hook::disable();
|
||||
this->nodes.clear();
|
||||
|
@ -1594,6 +1607,14 @@ void Hy3Layout::renderHook(void*, std::any data) {
|
|||
}
|
||||
}
|
||||
|
||||
void Hy3Layout::windowTitleHook(void*, std::any data) {
|
||||
CWindow* window = std::any_cast<CWindow*>(data);
|
||||
if (window == nullptr) return;
|
||||
auto* node = g_Hy3Layout->getNodeFromWindow(window);
|
||||
|
||||
node->updateTabBarRecursive();
|
||||
}
|
||||
|
||||
void Hy3Layout::tickHook(void*, std::any) {
|
||||
auto& tab_groups = g_Hy3Layout->tab_groups;
|
||||
auto entry = tab_groups.begin();
|
||||
|
|
|
@ -84,6 +84,8 @@ struct Hy3Node {
|
|||
Hy3Node* getFocusedNode();
|
||||
void updateDecos();
|
||||
void setHidden(bool hidden);
|
||||
void updateTabBar();
|
||||
void updateTabBarRecursive();
|
||||
bool isUrgent();
|
||||
bool isIndirectlyFocused();
|
||||
std::string getTitle();
|
||||
|
@ -100,9 +102,6 @@ struct Hy3Node {
|
|||
Hy3Node* intoGroup(Hy3GroupLayout);
|
||||
|
||||
static void swapData(Hy3Node&, Hy3Node&);
|
||||
|
||||
private:
|
||||
void updateTabBar();
|
||||
};
|
||||
|
||||
class Hy3Layout: public IHyprLayout {
|
||||
|
@ -141,6 +140,7 @@ public:
|
|||
Hy3Node* getWorkspaceFocusedNode(const int&);
|
||||
|
||||
static void renderHook(void*, std::any);
|
||||
static void windowTitleHook(void*, std::any);
|
||||
static void tickHook(void*, std::any);
|
||||
|
||||
std::list<Hy3Node> nodes;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include <hyprland/src/Compositor.hpp>
|
||||
#include <cairo/cairo.h>
|
||||
#include <pango/pangocairo.h>
|
||||
#include <hyprland/src/helpers/Color.hpp>
|
||||
#include <hyprland/src/plugins/PluginAPI.hpp>
|
||||
#include <hyprland/src/render/OpenGL.hpp>
|
||||
|
@ -47,27 +48,63 @@ void Hy3TabBarEntry::setUrgent(bool urgent) {
|
|||
}
|
||||
}
|
||||
|
||||
void Hy3TabBarEntry::setWindowTitle(std::string title) {
|
||||
if (this->window_title != title) {
|
||||
this->window_title = title;
|
||||
this->tab_bar.dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Hy3TabBarEntry::prepareTexture(float scale, wlr_box& box) {
|
||||
static const auto* rounding_setting = &HyprlandAPI::getConfigValue(PHANDLE, "plugin:hy3:tabs:rounding")->intValue;
|
||||
static const auto* s_rounding = &HyprlandAPI::getConfigValue(PHANDLE, "plugin:hy3:tabs:rounding")->intValue;
|
||||
static const auto* render_text = &HyprlandAPI::getConfigValue(PHANDLE, "plugin:hy3:tabs:render_text")->intValue;
|
||||
static const auto* text_font = &HyprlandAPI::getConfigValue(PHANDLE, "plugin:hy3:tabs:text_font")->strValue;
|
||||
static const auto* text_height = &HyprlandAPI::getConfigValue(PHANDLE, "plugin:hy3:tabs:text_height")->intValue;
|
||||
static const auto* text_padding = &HyprlandAPI::getConfigValue(PHANDLE, "plugin:hy3:tabs:text_padding")->intValue;
|
||||
static const auto* col_active = &HyprlandAPI::getConfigValue(PHANDLE, "plugin:hy3:tabs:col.active")->intValue;
|
||||
static const auto* col_urgent = &HyprlandAPI::getConfigValue(PHANDLE, "plugin:hy3:tabs:col.urgent")->intValue;
|
||||
static const auto* col_inactive = &HyprlandAPI::getConfigValue(PHANDLE, "plugin:hy3:tabs:col.inactive")->intValue;
|
||||
static const auto* col_text_active = &HyprlandAPI::getConfigValue(PHANDLE, "plugin:hy3:tabs:col.text.active")->intValue;
|
||||
static const auto* col_text_urgent = &HyprlandAPI::getConfigValue(PHANDLE, "plugin:hy3:tabs:col.text.urgent")->intValue;
|
||||
static const auto* col_text_inactive = &HyprlandAPI::getConfigValue(PHANDLE, "plugin:hy3:tabs:col.text.inactive")->intValue;
|
||||
|
||||
auto width = box.width;
|
||||
auto height = box.height;
|
||||
|
||||
auto rounding = std::min((double) *rounding_setting, std::min(width * 0.5, height * 0.5));
|
||||
auto rounding = std::min((double) *s_rounding, std::min(width * 0.5, height * 0.5));
|
||||
|
||||
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->last_render.x != box.x
|
||||
|| this->last_render.y != box.y
|
||||
|| this->last_render.focused != this->focused
|
||||
|| this->last_render.urgent != this->urgent
|
||||
|| this->last_render.window_title != this->window_title
|
||||
|| this->last_render.rounding != rounding
|
||||
|| this->last_render.text_font != *text_font
|
||||
|| this->last_render.text_height != *text_height
|
||||
|| this->last_render.text_padding != *text_padding
|
||||
|| this->last_render.col_active != *col_active
|
||||
|| this->last_render.col_urgent != *col_urgent
|
||||
|| this->last_render.col_inactive != *col_inactive
|
||||
|| this->last_render.col_text_active != *col_text_active
|
||||
|| this->last_render.col_text_urgent != *col_text_urgent
|
||||
|| this->last_render.col_text_inactive != *col_text_inactive
|
||||
) {
|
||||
this->last_render_rounding = rounding;
|
||||
this->last_render_focused = this->focused;
|
||||
this->last_render_urgent = this->urgent;
|
||||
this->last_render_box = box;
|
||||
this->last_render.x = box.x;
|
||||
this->last_render.y = box.y;
|
||||
this->last_render.focused = this->focused;
|
||||
this->last_render.urgent = this->urgent;
|
||||
this->last_render.window_title = this->window_title;
|
||||
this->last_render.rounding = rounding;
|
||||
this->last_render.text_font = *text_font;
|
||||
this->last_render.text_height = *text_height;
|
||||
this->last_render.text_padding = *text_padding;
|
||||
this->last_render.col_active = *col_active;
|
||||
this->last_render.col_urgent = *col_urgent;
|
||||
this->last_render.col_inactive = *col_inactive;
|
||||
this->last_render.col_text_active = *col_text_active;
|
||||
this->last_render.col_text_urgent = *col_text_urgent;
|
||||
this->last_render.col_text_inactive = *col_text_inactive;
|
||||
|
||||
auto cairo_surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
|
||||
auto cairo = cairo_create(cairo_surface);
|
||||
|
@ -104,6 +141,45 @@ void Hy3TabBarEntry::prepareTexture(float scale, wlr_box& box) {
|
|||
// draw
|
||||
cairo_fill(cairo);
|
||||
|
||||
// render window title
|
||||
if (*render_text) {
|
||||
PangoLayout* layout = pango_cairo_create_layout(cairo);
|
||||
pango_layout_set_text(layout, this->window_title.c_str(), -1);
|
||||
|
||||
PangoFontDescription* font_desc = pango_font_description_from_string(text_font->c_str());
|
||||
pango_font_description_set_size(font_desc, *text_height * scale * PANGO_SCALE);
|
||||
pango_layout_set_font_description(layout, font_desc);
|
||||
pango_font_description_free(font_desc);
|
||||
|
||||
int padding = *text_padding * scale;
|
||||
int width = box.width - padding * 2;
|
||||
|
||||
pango_layout_set_width(layout, width * PANGO_SCALE);
|
||||
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END);
|
||||
|
||||
CColor c;
|
||||
if (this->focused) {
|
||||
c = CColor(*col_text_active);
|
||||
} else if (this->urgent) {
|
||||
c = CColor(*col_text_urgent);
|
||||
} else {
|
||||
c = CColor(*col_text_inactive);
|
||||
}
|
||||
|
||||
cairo_set_source_rgba(cairo, c.r, c.g, c.b, c.a);
|
||||
|
||||
int layout_width, layout_height;
|
||||
pango_layout_get_size(layout, &layout_width, &layout_height);
|
||||
|
||||
auto y_offset = (height / 2.0) - (((double)layout_height / PANGO_SCALE) / 2.0);
|
||||
cairo_move_to(cairo, padding, y_offset);
|
||||
pango_cairo_show_layout(cairo, layout);
|
||||
g_object_unref(layout);
|
||||
}
|
||||
|
||||
// flush cairo
|
||||
cairo_surface_flush(cairo_surface);
|
||||
|
||||
auto data = cairo_image_surface_get_data(cairo_surface);
|
||||
this->texture.allocate();
|
||||
|
||||
|
@ -205,6 +281,7 @@ void Hy3TabBar::updateNodeList(std::list<Hy3Node*>& nodes) {
|
|||
auto& parent_group = parent->data.as_group;
|
||||
entry->setFocused(parent_group.focused_child == *node || (parent_group.group_focused && parent->isIndirectlyFocused()));
|
||||
entry->setUrgent((*node)->isUrgent());
|
||||
entry->setWindowTitle((*node)->getTitle());
|
||||
|
||||
node = std::next(node);
|
||||
if (entry != this->entries.end()) entry = std::next(entry);
|
||||
|
|
|
@ -21,10 +21,25 @@ struct Hy3TabBarEntry {
|
|||
CAnimatedVariable width; // 0.0-1.0 of total bar
|
||||
Hy3TabBar& tab_bar;
|
||||
Hy3Node& node; // only used for comparioson. do not deref.
|
||||
wlr_box last_render_box;
|
||||
float last_render_rounding = 0.0;
|
||||
bool last_render_focused = false;
|
||||
bool last_render_urgent = false;
|
||||
|
||||
struct {
|
||||
int x, y;
|
||||
float rounding = 0.0;
|
||||
float scale = 0.0;
|
||||
bool focused = false;
|
||||
bool urgent = false;
|
||||
std::string window_title;
|
||||
|
||||
std::string text_font;
|
||||
int text_height = 0;
|
||||
int text_padding = 0;
|
||||
int col_active = 0;
|
||||
int col_urgent = 0;
|
||||
int col_inactive = 0;
|
||||
int col_text_active = 0;
|
||||
int col_text_urgent = 0;
|
||||
int col_text_inactive = 0;
|
||||
} last_render;
|
||||
|
||||
Hy3TabBarEntry(Hy3TabBar&, Hy3Node&);
|
||||
bool operator==(const Hy3Node&) const;
|
||||
|
@ -32,6 +47,7 @@ struct Hy3TabBarEntry {
|
|||
|
||||
void setFocused(bool);
|
||||
void setUrgent(bool);
|
||||
void setWindowTitle(std::string);
|
||||
void prepareTexture(float, wlr_box&);
|
||||
};
|
||||
|
||||
|
|
11
src/main.cpp
11
src/main.cpp
|
@ -108,11 +108,18 @@ APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) {
|
|||
HyprlandAPI::addConfigValue(PHANDLE, "plugin:hy3:no_gaps_when_only", SConfigValue{.intValue = 0});
|
||||
HyprlandAPI::addConfigValue(PHANDLE, "plugin:hy3:tabs:height", SConfigValue{.intValue = 15});
|
||||
HyprlandAPI::addConfigValue(PHANDLE, "plugin:hy3:tabs:padding", SConfigValue{.intValue = 5});
|
||||
HyprlandAPI::addConfigValue(PHANDLE, "plugin:hy3:tabs:from_top", SConfigValue{.intValue = 0});
|
||||
HyprlandAPI::addConfigValue(PHANDLE, "plugin:hy3:tabs:rounding", SConfigValue{.intValue = 3});
|
||||
HyprlandAPI::addConfigValue(PHANDLE, "plugin:hy3:tabs:render_text", SConfigValue{.intValue = 1});
|
||||
HyprlandAPI::addConfigValue(PHANDLE, "plugin:hy3:tabs:text_font", SConfigValue{.strValue = "Sans"});
|
||||
HyprlandAPI::addConfigValue(PHANDLE, "plugin:hy3:tabs:text_height", SConfigValue{.intValue = 8});
|
||||
HyprlandAPI::addConfigValue(PHANDLE, "plugin:hy3:tabs:text_padding", SConfigValue{.intValue = 3});
|
||||
HyprlandAPI::addConfigValue(PHANDLE, "plugin:hy3:tabs:col.active", SConfigValue{.intValue = 0xff32b4ff});
|
||||
HyprlandAPI::addConfigValue(PHANDLE, "plugin:hy3:tabs:col.urgent", SConfigValue{.intValue = 0xffff4f4f});
|
||||
HyprlandAPI::addConfigValue(PHANDLE, "plugin:hy3:tabs:col.inactive", SConfigValue{.intValue = 0x80808080});
|
||||
HyprlandAPI::addConfigValue(PHANDLE, "plugin:hy3:tabs:from_top", SConfigValue{.intValue = 0});
|
||||
HyprlandAPI::addConfigValue(PHANDLE, "plugin:hy3:tabs:rounding", SConfigValue{.intValue = 3});
|
||||
HyprlandAPI::addConfigValue(PHANDLE, "plugin:hy3:tabs:col.text.active", SConfigValue{.intValue = 0xff000000});
|
||||
HyprlandAPI::addConfigValue(PHANDLE, "plugin:hy3:tabs:col.text.urgent", SConfigValue{.intValue = 0xff000000});
|
||||
HyprlandAPI::addConfigValue(PHANDLE, "plugin:hy3:tabs:col.text.inactive", SConfigValue{.intValue = 0xff000000});
|
||||
|
||||
g_Hy3Layout = std::make_unique<Hy3Layout>();
|
||||
HyprlandAPI::addLayout(PHANDLE, "hy3", g_Hy3Layout.get());
|
||||
|
|
Loading…
Add table
Reference in a new issue