diff --git a/csgo-vulkan-fix/main.cpp b/csgo-vulkan-fix/main.cpp index a1bc25c..910ddb9 100644 --- a/csgo-vulkan-fix/main.cpp +++ b/csgo-vulkan-fix/main.cpp @@ -10,9 +10,16 @@ #include #include #include +#include +#include #include "globals.hpp" +extern "C" { +#include +#include +} + #include using namespace Hyprutils::String; @@ -24,6 +31,10 @@ typedef void (*origMotion)(CSeatManager*, uint32_t, const Vector2D&); typedef void (*origSurfaceSize)(CXWaylandSurface*, const CBox&); typedef CRegion (*origWLSurfaceDamage)(Desktop::View::CWLSurface*); +static struct { + SP fixMouse; +} configValues; + // Do NOT change this function. APICALL EXPORT std::string PLUGIN_API_VERSION() { return HYPRLAND_API_VERSION; @@ -46,8 +57,6 @@ static const SAppConfig* getAppConfig(const std::string& appClass) { } void hkNotifyMotion(CSeatManager* thisptr, uint32_t time_msec, const Vector2D& local) { - static auto* const PFIX = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:csgo-vulkan-fix:fix_mouse")->getDataStaticPtr(); - Vector2D newCoords = local; auto focusState = Desktop::focusState(); auto window = focusState->window(); @@ -55,7 +64,7 @@ void hkNotifyMotion(CSeatManager* thisptr, uint32_t time_msec, const Vector2D& l const auto CONFIG = window && monitor ? getAppConfig(window->m_initialClass) : nullptr; - if (**PFIX && CONFIG) { + if (configValues.fixMouse->value() && CONFIG) { // fix the coords newCoords.x *= (CONFIG->res.x / monitor->m_size.x) / window->m_X11SurfaceScaledBy; newCoords.y *= (CONFIG->res.y / monitor->m_size.y) / window->m_X11SurfaceScaledBy; @@ -109,6 +118,50 @@ CRegion hkWLSurfaceDamage(Desktop::View::CWLSurface* thisptr) { return RG; } +int vkfixAppLua(lua_State* L) { + if (!lua_istable(L, 1)) + return Config::Lua::Bindings::Internal::configError(L, "vkfix_app: expected a table { app, w, h }"); + + SAppConfig config; + + { + Hyprutils::Utils::CScopeGuard x([L] { lua_pop(L, 1); }); + + lua_getfield(L, 1, "app"); + + if (!lua_isstring(L, -1)) + return Config::Lua::Bindings::Internal::configError(L, "vkfix_app: app must be a class string"); + + config.szClass = lua_tostring(L, -1); + } + + { + Hyprutils::Utils::CScopeGuard x([L] { lua_pop(L, 1); }); + + lua_getfield(L, 1, "w"); + + if (!lua_isinteger(L, -1)) + return Config::Lua::Bindings::Internal::configError(L, "vkfix_app: w must be an integer"); + + config.res.x = lua_tointeger(L, -1); + } + + { + Hyprutils::Utils::CScopeGuard x([L] { lua_pop(L, 1); }); + + lua_getfield(L, 1, "h"); + + if (!lua_isinteger(L, -1)) + return Config::Lua::Bindings::Internal::configError(L, "vkfix_app: h must be an integer"); + + config.res.y = lua_tointeger(L, -1); + } + + g_appConfigs.emplace_back(std::move(config)); + + return 0; +} + APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) { PHANDLE = handle; @@ -121,47 +174,45 @@ APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) { throw std::runtime_error("[vkfix] Version mismatch"); } - HyprlandAPI::addConfigValue(PHANDLE, "plugin:csgo-vulkan-fix:res_w", Hyprlang::INT{1680}); - HyprlandAPI::addConfigValue(PHANDLE, "plugin:csgo-vulkan-fix:res_h", Hyprlang::INT{1050}); - HyprlandAPI::addConfigValue(PHANDLE, "plugin:csgo-vulkan-fix:fix_mouse", Hyprlang::INT{1}); - HyprlandAPI::addConfigValue(PHANDLE, "plugin:csgo-vulkan-fix:class", Hyprlang::STRING{"cs2"}); + static auto P = Event::bus()->m_events.config.preReload.listen([&] { g_appConfigs.clear(); }); - static auto P = Event::bus()->m_events.config.preReload.listen([&] { - g_appConfigs.clear(); + if (Config::mgr()->type() == Config::CONFIG_LEGACY) { + HyprlandAPI::addConfigKeyword( + PHANDLE, "vkfix-app", + [](const char* l, const char* r) -> Hyprlang::CParseResult { + const std::string str = r; + CConstVarList data(str, 0, ',', true); - static auto* const RESX = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:csgo-vulkan-fix:res_w")->getDataStaticPtr(); - static auto* const RESY = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:csgo-vulkan-fix:res_h")->getDataStaticPtr(); - static auto* const PCLASS = (Hyprlang::STRING const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:csgo-vulkan-fix:class")->getDataStaticPtr(); + Hyprlang::CParseResult result; - g_appConfigs.emplace_back(SAppConfig{.szClass = *PCLASS, .res = Vector2D{(int)**RESX, (int)**RESY}}); - }); + if (data.size() != 3) { + result.setError("vkfix-app requires 3 params"); + return result; + } - HyprlandAPI::addConfigKeyword( - PHANDLE, "vkfix-app", - [](const char* l, const char* r) -> Hyprlang::CParseResult { - const std::string str = r; - CConstVarList data(str, 0, ',', true); + try { + SAppConfig config; + config.szClass = data[0]; + config.res = Vector2D{std::stoi(std::string{data[1]}), std::stoi(std::string{data[2]})}; + g_appConfigs.emplace_back(std::move(config)); + } catch (std::exception& e) { + result.setError("failed to parse line"); + return result; + } - Hyprlang::CParseResult result; - - if (data.size() != 3) { - result.setError("vkfix-app requires 3 params"); return result; - } + }, + Hyprlang::SHandlerOptions{}); + } else if (Config::mgr()->type() == Config::CONFIG_LUA) { + HyprlandAPI::addLuaFunction(PHANDLE, "csgo_vulkan_fix", "vkfix_app", ::vkfixAppLua); + } else { + HyprlandAPI::addNotification(PHANDLE, "[csgo-vulkan-fix] Failure in initialization: Failed to get a valid config manager", CHyprColor{1.0, 0.2, 0.2, 1.0}, 5000); + throw std::runtime_error("[vkfix] Config manager bad"); + } - try { - SAppConfig config; - config.szClass = data[0]; - config.res = Vector2D{std::stoi(std::string{data[1]}), std::stoi(std::string{data[2]})}; - g_appConfigs.emplace_back(std::move(config)); - } catch (std::exception& e) { - result.setError("failed to parse line"); - return result; - } - - return result; - }, - Hyprlang::SHandlerOptions{}); + configValues.fixMouse = + makeShared("plugin:csgo_vulkan_fix:fix_mouse", "Whether to fix the mouse position. A select few apps might be wonky with this.", true); + HyprlandAPI::addConfigValueV2(PHANDLE, configValues.fixMouse); auto FNS = HyprlandAPI::findFunctionsByName(PHANDLE, "sendPointerMotion"); for (auto& fn : FNS) { @@ -211,5 +262,5 @@ APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) { } APICALL EXPORT void PLUGIN_EXIT() { - ; + configValues = {}; } diff --git a/hyprbars/BarPassElement.cpp b/hyprbars/BarPassElement.cpp index b6b1c61..e714036 100644 --- a/hyprbars/BarPassElement.cpp +++ b/hyprbars/BarPassElement.cpp @@ -1,32 +1,34 @@ #include "BarPassElement.hpp" #include +#include #include "barDeco.hpp" +using namespace Render::GL; + CBarPassElement::CBarPassElement(const CBarPassElement::SBarData& data_) : data(data_) { ; } -void CBarPassElement::draw(const CRegion& damage) { - data.deco->renderPass(g_pHyprOpenGL->m_renderData.pMonitor.lock(), data.a); +std::vector> CBarPassElement::draw() { + data.deco->renderPass(g_pHyprRenderer->m_renderData.pMonitor.lock(), data.a); + return {}; } bool CBarPassElement::needsLiveBlur() { - static auto* const PCOLOR = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprbars:bar_color")->getDataStaticPtr(); - static auto* const PENABLEBLUR = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprbars:bar_blur")->getDataStaticPtr(); static auto* const PENABLEBLURGLOBAL = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "decoration:blur:enabled")->getDataStaticPtr(); - CHyprColor color = data.deco->m_bForcedBarColor.value_or(**PCOLOR); + CHyprColor color = data.deco->m_bForcedBarColor.value_or(CHyprColor{static_cast(g_pGlobalState->config.barColor->value())}); color.a *= data.a; - const bool SHOULDBLUR = **PENABLEBLUR && **PENABLEBLURGLOBAL && color.a < 1.F; + const bool SHOULDBLUR = g_pGlobalState->config.barBlur->value() && **PENABLEBLURGLOBAL && color.a < 1.F; return SHOULDBLUR; } std::optional CBarPassElement::boundingBox() { // Temporary fix: expand the bar bb a bit, otherwise occlusion gets too aggressive. - return data.deco->assignedBoxGlobal().translate(-g_pHyprOpenGL->m_renderData.pMonitor->m_position).expand(10); + return data.deco->assignedBoxGlobal().translate(-g_pHyprRenderer->m_renderData.pMonitor->m_position).expand(10); } bool CBarPassElement::needsPrecomputeBlur() { return false; -} \ No newline at end of file +} diff --git a/hyprbars/BarPassElement.hpp b/hyprbars/BarPassElement.hpp index 7998c3e..630fd9e 100644 --- a/hyprbars/BarPassElement.hpp +++ b/hyprbars/BarPassElement.hpp @@ -13,15 +13,19 @@ class CBarPassElement : public IPassElement { CBarPassElement(const SBarData& data_); virtual ~CBarPassElement() = default; - virtual void draw(const CRegion& damage); - virtual bool needsLiveBlur(); - virtual bool needsPrecomputeBlur(); - virtual std::optional boundingBox(); + virtual std::vector> draw() override; + virtual bool needsLiveBlur() override; + virtual bool needsPrecomputeBlur() override; + virtual std::optional boundingBox() override; - virtual const char* passName() { + virtual const char* passName() override { return "CBarPassElement"; } + virtual ePassElementType type() override { + return EK_CUSTOM; + } + private: SBarData data; }; \ No newline at end of file diff --git a/hyprbars/CMakeLists.txt b/hyprbars/CMakeLists.txt index 9502f21..b99f683 100644 --- a/hyprbars/CMakeLists.txt +++ b/hyprbars/CMakeLists.txt @@ -17,7 +17,6 @@ pkg_check_modules(deps REQUIRED IMPORTED_TARGET libdrm libinput libudev - pangocairo pixman-1 wayland-server xkbcommon diff --git a/hyprbars/Makefile b/hyprbars/Makefile index 609a31f..59c7a93 100644 --- a/hyprbars/Makefile +++ b/hyprbars/Makefile @@ -7,8 +7,8 @@ endif CXXFLAGS ?= -O2 CXXFLAGS += -shared -fPIC -std=c++2b -Wno-c++11-narrowing -INCLUDES = `pkg-config --cflags pixman-1 libdrm hyprland pangocairo libinput libudev wayland-server xkbcommon` -LIBS = `pkg-config --libs pangocairo` +INCLUDES = `pkg-config --cflags pixman-1 libdrm hyprland libinput libudev wayland-server xkbcommon` +LIBS = SRC = main.cpp barDeco.cpp BarPassElement.cpp TARGET = hyprbars.so diff --git a/hyprbars/barDeco.cpp b/hyprbars/barDeco.cpp index e9fbb4f..4f59569 100644 --- a/hyprbars/barDeco.cpp +++ b/hyprbars/barDeco.cpp @@ -8,21 +8,28 @@ #include #include #include +#include +#include +#include #include #include #include #include -#include +#include #include "globals.hpp" #include "BarPassElement.hpp" +using namespace Render::GL; + +static CHyprColor configColor(Config::INTEGER color) { + return CHyprColor{static_cast(color)}; +} + CHyprBar::CHyprBar(PHLWINDOW pWindow) : IHyprWindowDecoration(pWindow) { m_pWindow = pWindow; - static auto* const PCOLOR = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprbars:bar_color")->getDataStaticPtr(); - - const auto PMONITOR = pWindow->m_monitor.lock(); + const auto PMONITOR = pWindow->m_monitor.lock(); PMONITOR->m_scheduledRecalc = true; // button events @@ -34,10 +41,8 @@ CHyprBar::CHyprBar(PHLWINDOW pWindow) : IHyprWindowDecoration(pWindow) { m_pTouchMoveCallback = Event::bus()->m_events.input.touch.motion.listen([&](ITouch::SMotionEvent e, Event::SCallbackInfo& info) { onTouchMove(info, e); }); m_pMouseMoveCallback = Event::bus()->m_events.input.mouse.move.listen([&](Vector2D c, Event::SCallbackInfo& info) { onMouseMove(c); }); - m_pTextTex = makeShared(); - m_pButtonsTex = makeShared(); - - g_pAnimationManager->createAnimation(CHyprColor{**PCOLOR}, m_cRealBarColor, g_pConfigManager->getAnimationPropertyConfig("border"), pWindow, AVARDAMAGE_NONE); + g_pAnimationManager->createAnimation(configColor(g_pGlobalState->config.barColor->value()), m_cRealBarColor, Config::animationTree()->getAnimationPropertyConfig("border"), + pWindow, AVARDAMAGE_NONE); m_cRealBarColor->setUpdateCallback([&](auto) { damageEntire(); }); } @@ -46,16 +51,16 @@ CHyprBar::~CHyprBar() { } SDecorationPositioningInfo CHyprBar::getPositioningInfo() { - static auto* const PHEIGHT = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprbars:bar_height")->getDataStaticPtr(); - static auto* const PENABLED = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprbars:enabled")->getDataStaticPtr(); - static auto* const PPRECEDENCE = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprbars:bar_precedence_over_border")->getDataStaticPtr(); + const auto HEIGHT = g_pGlobalState->config.barHeight->value(); + const auto ENABLED = g_pGlobalState->config.enabled->value(); + const auto PRECEDENCE = g_pGlobalState->config.barPrecedenceOverBorder->value(); SDecorationPositioningInfo info; info.policy = m_hidden ? DECORATION_POSITION_ABSOLUTE : DECORATION_POSITION_STICKY; info.edges = DECORATION_EDGE_TOP; - info.priority = **PPRECEDENCE ? 10005 : 5000; + info.priority = PRECEDENCE ? 10005 : 5000; info.reserved = true; - info.desiredExtents = {{0, m_hidden || !**PENABLED ? 0 : **PHEIGHT}, {0, 0}}; + info.desiredExtents = {{0, m_hidden || !ENABLED ? 0 : HEIGHT}, {0, 0}}; return info; } @@ -71,9 +76,7 @@ std::string CHyprBar::getDisplayName() { } bool CHyprBar::inputIsValid() { - static auto* const PENABLED = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprbars:enabled")->getDataStaticPtr(); - - if (!**PENABLED) + if (!g_pGlobalState->config.enabled->value()) return false; if (!m_pWindow->m_workspace || !m_pWindow->m_workspace->isVisible() || !g_pInputManager->m_exclusiveLSes.empty() || @@ -139,8 +142,7 @@ void CHyprBar::onTouchUp(Event::SCallbackInfo& info, ITouch::SUpEvent e) { void CHyprBar::onMouseMove(Vector2D coords) { // ensure proper redraws of button icons on hover when using hardware cursors - static auto* const PICONONHOVER = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprbars:icon_on_hover")->getDataStaticPtr(); - if (**PICONONHOVER) + if (g_pGlobalState->config.iconOnHover->value()) damageOnButtonHover(); if (!m_bDragPending || m_bTouchEv || !validMapped(m_pWindow) || m_touchId != 0) @@ -184,16 +186,15 @@ void CHyprBar::handleDownEvent(Event::SCallbackInfo& info, std::optionalm_position.x + e.pos.x * PMONITOR->m_size.x, PMONITOR->m_position.y + e.pos.y * PMONITOR->m_size.y) - assignedBoxGlobal().pos(); } - static auto* const PHEIGHT = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprbars:bar_height")->getDataStaticPtr(); - static auto* const PBARBUTTONPADDING = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprbars:bar_button_padding")->getDataStaticPtr(); - static auto* const PBARPADDING = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprbars:bar_padding")->getDataStaticPtr(); - static auto* const PALIGNBUTTONS = (Hyprlang::STRING const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprbars:bar_buttons_alignment")->getDataStaticPtr(); - static auto* const PONDOUBLECLICK = (Hyprlang::STRING const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprbars:on_double_click")->getDataStaticPtr(); + const auto HEIGHT = g_pGlobalState->config.barHeight->value(); + const auto BARBUTTONPADDING = g_pGlobalState->config.barButtonPadding->value(); + const auto BARPADDING = g_pGlobalState->config.barPadding->value(); + const auto ALIGNBUTTONS = g_pGlobalState->config.barButtonsAlignment->value(); + const auto ON_DOUBLE_CLICK = g_pGlobalState->config.onDoubleClick->value(); - const bool BUTTONSRIGHT = std::string{*PALIGNBUTTONS} != "left"; - const std::string ON_DOUBLE_CLICK = *PONDOUBLECLICK; + const bool BUTTONSRIGHT = ALIGNBUTTONS != "left"; - if (!VECINRECT(COORDS, 0, 0, assignedBoxGlobal().w, **PHEIGHT - 1)) { + if (!VECINRECT(COORDS, 0, 0, assignedBoxGlobal().w, HEIGHT - 1)) { if (m_bDraggingThis) { if (m_bTouchEv) @@ -217,12 +218,12 @@ void CHyprBar::handleDownEvent(Event::SCallbackInfo& info, std::optional(Time::steadyNow() - m_lastMouseDown).count() < 400 /* Arbitrary delay I found suitable */) { - g_pKeybindManager->m_dispatchers["exec"](ON_DOUBLE_CLICK); + Config::Supplementary::executor()->spawn(ON_DOUBLE_CLICK); m_bDragPending = false; } else { m_lastMouseDown = Time::steadyNow(); @@ -240,10 +241,10 @@ void CHyprBar::handleUpEvent(Event::SCallbackInfo& info) { m_bCancelledDown = false; if (m_bDraggingThis) { - g_pKeybindManager->m_dispatchers["mouse"]("0movewindow"); + g_pKeybindManager->changeMouseBindMode(MBIND_INVALID); m_bDraggingThis = false; if (m_bTouchEv) - g_pKeybindManager->m_dispatchers["settiled"]("activewindow"); + Config::Actions::floatWindow(Config::Actions::eTogglableAction::TOGGLE_ACTION_DISABLE); Log::logger->log(Log::DEBUG, "[hyprbars] Dragging ended on {:x}", (uintptr_t)m_pWindow.lock().get()); } @@ -254,187 +255,65 @@ void CHyprBar::handleUpEvent(Event::SCallbackInfo& info) { } void CHyprBar::handleMovement() { - g_pKeybindManager->m_dispatchers["mouse"]("1movewindow"); + g_pKeybindManager->changeMouseBindMode(MBIND_MOVE); m_bDraggingThis = true; Log::logger->log(Log::DEBUG, "[hyprbars] Dragging initiated on {:x}", (uintptr_t)m_pWindow.lock().get()); return; } -bool CHyprBar::doButtonPress(Hyprlang::INT* const* PBARPADDING, Hyprlang::INT* const* PBARBUTTONPADDING, Hyprlang::INT* const* PHEIGHT, Vector2D COORDS, const bool BUTTONSRIGHT) { +bool CHyprBar::doButtonPress(Config::INTEGER barPadding, Config::INTEGER barButtonPadding, Config::INTEGER barHeight, Vector2D COORDS, const bool BUTTONSRIGHT) { //check if on a button - float offset = **PBARPADDING; + float offset = barPadding; for (auto& b : g_pGlobalState->buttons) { - const auto BARBUF = Vector2D{(int)assignedBoxGlobal().w, **PHEIGHT}; - Vector2D currentPos = Vector2D{(BUTTONSRIGHT ? BARBUF.x - **PBARBUTTONPADDING - b.size - offset : offset), (BARBUF.y - b.size) / 2.0}.floor(); + const auto BARBUF = Vector2D{(int)assignedBoxGlobal().w, barHeight}; + Vector2D currentPos = Vector2D{(BUTTONSRIGHT ? BARBUF.x - barButtonPadding - b.size - offset : offset), (BARBUF.y - b.size) / 2.0}.floor(); - if (VECINRECT(COORDS, currentPos.x, currentPos.y, currentPos.x + b.size + **PBARBUTTONPADDING, currentPos.y + b.size)) { + if (VECINRECT(COORDS, currentPos.x, currentPos.y, currentPos.x + b.size + barButtonPadding, currentPos.y + b.size)) { // hit on close g_pKeybindManager->m_dispatchers["exec"](b.cmd); return true; } - offset += **PBARBUTTONPADDING + b.size; + offset += barButtonPadding + b.size; } return false; } -void CHyprBar::renderText(SP out, const std::string& text, const CHyprColor& color, const Vector2D& bufferSize, const float scale, const int fontSize) { - const auto CAIROSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, bufferSize.x, bufferSize.y); - const auto CAIRO = cairo_create(CAIROSURFACE); - - // clear the pixmap - cairo_save(CAIRO); - cairo_set_operator(CAIRO, CAIRO_OPERATOR_CLEAR); - cairo_paint(CAIRO); - cairo_restore(CAIRO); - - // draw title using Pango - PangoLayout* layout = pango_cairo_create_layout(CAIRO); - pango_layout_set_text(layout, text.c_str(), -1); - - PangoFontDescription* fontDesc = pango_font_description_from_string("sans"); - pango_font_description_set_size(fontDesc, fontSize * scale * PANGO_SCALE); - pango_layout_set_font_description(layout, fontDesc); - pango_font_description_free(fontDesc); - - const int maxWidth = bufferSize.x; - - pango_layout_set_width(layout, maxWidth * PANGO_SCALE); - pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_NONE); - - cairo_set_source_rgba(CAIRO, color.r, color.g, color.b, color.a); - - PangoRectangle ink_rect, logical_rect; - pango_layout_get_extents(layout, &ink_rect, &logical_rect); - - const int layoutWidth = ink_rect.width; - const int layoutHeight = logical_rect.height; - - const double xOffset = (bufferSize.x / 2.0 - layoutWidth / PANGO_SCALE / 2.0); - const double yOffset = (bufferSize.y / 2.0 - layoutHeight / PANGO_SCALE / 2.0); - - cairo_move_to(CAIRO, xOffset, yOffset); - pango_cairo_show_layout(CAIRO, layout); - - g_object_unref(layout); - - cairo_surface_flush(CAIROSURFACE); - - // copy the data to an OpenGL texture we have - const auto DATA = cairo_image_surface_get_data(CAIROSURFACE); - out->allocate(); - glBindTexture(GL_TEXTURE_2D, out->m_texID); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - -#ifndef GLES2 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED); -#endif - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bufferSize.x, bufferSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA); - - // delete cairo - cairo_destroy(CAIRO); - cairo_surface_destroy(CAIROSURFACE); -} - void CHyprBar::renderBarTitle(const Vector2D& bufferSize, const float scale) { - static auto* const PCOLOR = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprbars:col.text")->getDataStaticPtr(); - static auto* const PSIZE = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprbars:bar_text_size")->getDataStaticPtr(); - static auto* const PFONT = (Hyprlang::STRING const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprbars:bar_text_font")->getDataStaticPtr(); - static auto* const PALIGN = (Hyprlang::STRING const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprbars:bar_text_align")->getDataStaticPtr(); - static auto* const PALIGNBUTTONS = (Hyprlang::STRING const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprbars:bar_buttons_alignment")->getDataStaticPtr(); - static auto* const PBARPADDING = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprbars:bar_padding")->getDataStaticPtr(); - static auto* const PBARBUTTONPADDING = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprbars:bar_button_padding")->getDataStaticPtr(); + const auto COLORVAL = g_pGlobalState->config.textColor->value(); + const auto SIZE = g_pGlobalState->config.barTextSize->value(); + const auto FONT = g_pGlobalState->config.barTextFont->value(); + const auto ALIGN = g_pGlobalState->config.barTextAlign->value(); + const auto BARPADDING = g_pGlobalState->config.barPadding->value(); + const auto BARBUTTONPADDING = g_pGlobalState->config.barButtonPadding->value(); - const bool BUTTONSRIGHT = std::string{*PALIGNBUTTONS} != "left"; - - const auto PWINDOW = m_pWindow.lock(); - - const auto BORDERSIZE = PWINDOW->getRealBorderSize(); - - float buttonSizes = **PBARBUTTONPADDING; + float buttonSizes = BARBUTTONPADDING; for (auto& b : g_pGlobalState->buttons) { - buttonSizes += b.size + **PBARBUTTONPADDING; + buttonSizes += b.size + BARBUTTONPADDING; } - const auto scaledSize = **PSIZE * scale; - const auto scaledBorderSize = BORDERSIZE * scale; - const auto scaledButtonsSize = buttonSizes * scale; - const auto scaledButtonsPad = **PBARBUTTONPADDING * scale; - const auto scaledBarPadding = **PBARPADDING * scale; + const int scaledSize = std::round(SIZE * scale); + const auto scaledButtonsSize = buttonSizes * scale; + const auto scaledBarPadding = BARPADDING * scale; + const int paddingTotal = scaledBarPadding * 2 + scaledButtonsSize + (ALIGN != "left" ? scaledButtonsSize : 0); + const int maxWidth = std::clamp(static_cast(bufferSize.x - paddingTotal), 0, INT_MAX); - const CHyprColor COLOR = m_bForcedTitleColor.value_or(**PCOLOR); + if (m_szLastTitle.empty() || maxWidth < 1) { + m_pTextTex = nullptr; + return; + } - const auto CAIROSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, bufferSize.x, bufferSize.y); - const auto CAIRO = cairo_create(CAIROSURFACE); - - // clear the pixmap - cairo_save(CAIRO); - cairo_set_operator(CAIRO, CAIRO_OPERATOR_CLEAR); - cairo_paint(CAIRO); - cairo_restore(CAIRO); - - // draw title using Pango - PangoLayout* layout = pango_cairo_create_layout(CAIRO); - pango_layout_set_text(layout, m_szLastTitle.c_str(), -1); - - PangoFontDescription* fontDesc = pango_font_description_from_string(*PFONT); - pango_font_description_set_size(fontDesc, scaledSize * PANGO_SCALE); - pango_layout_set_font_description(layout, fontDesc); - pango_font_description_free(fontDesc); - - PangoContext* context = pango_layout_get_context(layout); - pango_context_set_base_dir(context, PANGO_DIRECTION_NEUTRAL); - - const int paddingTotal = scaledBarPadding * 2 + scaledButtonsSize + (std::string{*PALIGN} != "left" ? scaledButtonsSize : 0); - const int maxWidth = std::clamp(static_cast(bufferSize.x - paddingTotal), 0, INT_MAX); - - pango_layout_set_width(layout, maxWidth * PANGO_SCALE); - pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END); - - cairo_set_source_rgba(CAIRO, COLOR.r, COLOR.g, COLOR.b, COLOR.a); - - int layoutWidth, layoutHeight; - pango_layout_get_size(layout, &layoutWidth, &layoutHeight); - const int xOffset = std::string{*PALIGN} == "left" ? std::round(scaledBarPadding + (BUTTONSRIGHT ? 0 : scaledButtonsSize)) : - std::round(((bufferSize.x - scaledBorderSize) / 2.0 - layoutWidth / PANGO_SCALE / 2.0)); - const int yOffset = std::round((bufferSize.y / 2.0 - layoutHeight / PANGO_SCALE / 2.0)); - - cairo_move_to(CAIRO, xOffset, yOffset); - pango_cairo_show_layout(CAIRO, layout); - - g_object_unref(layout); - - cairo_surface_flush(CAIROSURFACE); - - // copy the data to an OpenGL texture we have - const auto DATA = cairo_image_surface_get_data(CAIROSURFACE); - m_pTextTex->allocate(); - glBindTexture(GL_TEXTURE_2D, m_pTextTex->m_texID); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - -#ifndef GLES2 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED); -#endif - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bufferSize.x, bufferSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA); - - // delete cairo - cairo_destroy(CAIRO); - cairo_surface_destroy(CAIROSURFACE); + const CHyprColor COLOR = m_bForcedTitleColor.value_or(configColor(COLORVAL)); + m_pTextTex = g_pHyprRenderer->renderText(m_szLastTitle, COLOR, scaledSize, false, FONT, maxWidth); } -size_t CHyprBar::getVisibleButtonCount(Hyprlang::INT* const* PBARBUTTONPADDING, Hyprlang::INT* const* PBARPADDING, const Vector2D& bufferSize, const float scale) { - float availableSpace = bufferSize.x - **PBARPADDING * scale * 2; +size_t CHyprBar::getVisibleButtonCount(Config::INTEGER barButtonPadding, Config::INTEGER barPadding, const Vector2D& bufferSize, const float scale) { + float availableSpace = bufferSize.x - barPadding * scale * 2; size_t count = 0; for (const auto& button : g_pGlobalState->buttons) { - const float buttonSpace = (button.size + **PBARBUTTONPADDING) * scale; + const float buttonSpace = (button.size + barButtonPadding) * scale; if (availableSpace >= buttonSpace) { count++; availableSpace -= buttonSpace; @@ -445,106 +324,82 @@ size_t CHyprBar::getVisibleButtonCount(Hyprlang::INT* const* PBARBUTTONPADDING, return count; } -void CHyprBar::renderBarButtons(const Vector2D& bufferSize, const float scale) { - static auto* const PBARBUTTONPADDING = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprbars:bar_button_padding")->getDataStaticPtr(); - static auto* const PBARPADDING = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprbars:bar_padding")->getDataStaticPtr(); - static auto* const PALIGNBUTTONS = (Hyprlang::STRING const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprbars:bar_buttons_alignment")->getDataStaticPtr(); - static auto* const PINACTIVECOLOR = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprbars:inactive_button_color")->getDataStaticPtr(); +void CHyprBar::renderBarButtons(CBox* barBox, const float scale, const float a) { + const auto BARBUTTONPADDING = g_pGlobalState->config.barButtonPadding->value(); + const auto BARPADDING = g_pGlobalState->config.barPadding->value(); + const auto ALIGNBUTTONS = g_pGlobalState->config.barButtonsAlignment->value(); + const auto INACTIVECOLOR = g_pGlobalState->config.inactiveButtonColor->value(); - const bool BUTTONSRIGHT = std::string{*PALIGNBUTTONS} != "left"; - const auto visibleCount = getVisibleButtonCount(PBARBUTTONPADDING, PBARPADDING, bufferSize, scale); + const bool BUTTONSRIGHT = ALIGNBUTTONS != "left"; + const auto visibleCount = getVisibleButtonCount(BARBUTTONPADDING, BARPADDING, Vector2D{barBox->w, barBox->h}, scale); + const bool INVALIDATEICONS = m_bButtonsDirty || m_bWindowSizeChanged; - const auto CAIROSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, bufferSize.x, bufferSize.y); - const auto CAIRO = cairo_create(CAIROSURFACE); - - // clear the pixmap - cairo_save(CAIRO); - cairo_set_operator(CAIRO, CAIRO_OPERATOR_CLEAR); - cairo_paint(CAIRO); - cairo_restore(CAIRO); - - // draw buttons - int offset = **PBARPADDING * scale; + int offset = BARPADDING * scale; for (size_t i = 0; i < visibleCount; ++i) { - const auto& button = g_pGlobalState->buttons[i]; - const auto scaledButtonSize = button.size * scale; - const auto scaledButtonsPad = **PBARBUTTONPADDING * scale; + auto& button = g_pGlobalState->buttons[i]; + const auto scaledButtonSize = button.size * scale; + const auto scaledButtonsPad = BARBUTTONPADDING * scale; - const auto pos = Vector2D{BUTTONSRIGHT ? bufferSize.x - offset - scaledButtonSize / 2.0 : offset + scaledButtonSize / 2.0, bufferSize.y / 2.0}.floor(); - auto color = button.bgcol; + auto color = button.bgcol; - if (**PINACTIVECOLOR > 0) { - color = m_bWindowHasFocus ? color : CHyprColor(**PINACTIVECOLOR); - if (button.userfg && button.iconTex->m_texID != 0) - button.iconTex->destroyTexture(); + if (INACTIVECOLOR > 0) { + color = m_bWindowHasFocus ? color : configColor(INACTIVECOLOR); + if (INVALIDATEICONS && button.userfg && button.iconTex) + button.iconTex = nullptr; } - cairo_set_source_rgba(CAIRO, color.r, color.g, color.b, color.a); - cairo_arc(CAIRO, pos.x, pos.y, scaledButtonSize / 2, 0, 2 * M_PI); - cairo_fill(CAIRO); + color.a *= a; + + CBox buttonBox = {barBox->x + (BUTTONSRIGHT ? barBox->w - offset - scaledButtonSize : offset), barBox->y + (barBox->h - scaledButtonSize) / 2.0, scaledButtonSize, + scaledButtonSize}; + buttonBox.round(); + + g_pHyprOpenGL->renderRect(buttonBox, color, {.round = static_cast(std::round(scaledButtonSize / 2.0)), .roundingPower = 2.F}); offset += scaledButtonsPad + scaledButtonSize; } - - // copy the data to an OpenGL texture we have - const auto DATA = cairo_image_surface_get_data(CAIROSURFACE); - m_pButtonsTex->allocate(); - glBindTexture(GL_TEXTURE_2D, m_pButtonsTex->m_texID); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - -#ifndef GLES2 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED); -#endif - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bufferSize.x, bufferSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA); - - // delete cairo - cairo_destroy(CAIRO); - cairo_surface_destroy(CAIROSURFACE); } void CHyprBar::renderBarButtonsText(CBox* barBox, const float scale, const float a) { - static auto* const PHEIGHT = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprbars:bar_height")->getDataStaticPtr(); - static auto* const PBARBUTTONPADDING = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprbars:bar_button_padding")->getDataStaticPtr(); - static auto* const PBARPADDING = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprbars:bar_padding")->getDataStaticPtr(); - static auto* const PALIGNBUTTONS = (Hyprlang::STRING const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprbars:bar_buttons_alignment")->getDataStaticPtr(); - static auto* const PICONONHOVER = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprbars:icon_on_hover")->getDataStaticPtr(); + const auto HEIGHT = g_pGlobalState->config.barHeight->value(); + const auto BARBUTTONPADDING = g_pGlobalState->config.barButtonPadding->value(); + const auto BARPADDING = g_pGlobalState->config.barPadding->value(); + const auto ALIGNBUTTONS = g_pGlobalState->config.barButtonsAlignment->value(); + const auto ICONONHOVER = g_pGlobalState->config.iconOnHover->value(); - const bool BUTTONSRIGHT = std::string{*PALIGNBUTTONS} != "left"; - const auto visibleCount = getVisibleButtonCount(PBARBUTTONPADDING, PBARPADDING, Vector2D{barBox->w, barBox->h}, scale); - const auto COORDS = cursorRelativeToBar(); + const bool BUTTONSRIGHT = ALIGNBUTTONS != "left"; + const auto visibleCount = getVisibleButtonCount(BARBUTTONPADDING, BARPADDING, Vector2D{barBox->w, barBox->h}, scale); + const auto COORDS = cursorRelativeToBar(); - int offset = **PBARPADDING * scale; - float noScaleOffset = **PBARPADDING; + int offset = BARPADDING * scale; + float noScaleOffset = BARPADDING; for (size_t i = 0; i < visibleCount; ++i) { auto& button = g_pGlobalState->buttons[i]; const auto scaledButtonSize = button.size * scale; - const auto scaledButtonsPad = **PBARBUTTONPADDING * scale; + const auto scaledButtonsPad = BARBUTTONPADDING * scale; // check if hovering here - const auto BARBUF = Vector2D{(int)assignedBoxGlobal().w, **PHEIGHT}; - Vector2D currentPos = Vector2D{(BUTTONSRIGHT ? BARBUF.x - **PBARBUTTONPADDING - button.size - noScaleOffset : noScaleOffset), (BARBUF.y - button.size) / 2.0}.floor(); - bool hovering = VECINRECT(COORDS, currentPos.x, currentPos.y, currentPos.x + button.size + **PBARBUTTONPADDING, currentPos.y + button.size); - noScaleOffset += **PBARBUTTONPADDING + button.size; + const auto BARBUF = Vector2D{(int)assignedBoxGlobal().w, HEIGHT}; + Vector2D currentPos = Vector2D{(BUTTONSRIGHT ? BARBUF.x - BARBUTTONPADDING - button.size - noScaleOffset : noScaleOffset), (BARBUF.y - button.size) / 2.0}.floor(); + bool hovering = VECINRECT(COORDS, currentPos.x, currentPos.y, currentPos.x + button.size + BARBUTTONPADDING, currentPos.y + button.size); + noScaleOffset += BARBUTTONPADDING + button.size; - if (button.iconTex->m_texID == 0 /* icon is not rendered */ && !button.icon.empty()) { + if ((!button.iconTex || button.iconTex->m_texID == 0) && !button.icon.empty()) { // render icon - const Vector2D BUFSIZE = {scaledButtonSize, scaledButtonSize}; - auto fgcol = button.userfg ? button.fgcol : (button.bgcol.r + button.bgcol.g + button.bgcol.b < 1) ? CHyprColor(0xFFFFFFFF) : CHyprColor(0xFF000000); + auto fgcol = button.userfg ? button.fgcol : (button.bgcol.r + button.bgcol.g + button.bgcol.b < 1) ? CHyprColor(0xFFFFFFFF) : CHyprColor(0xFF000000); - renderText(button.iconTex, button.icon, fgcol, BUFSIZE, scale, button.size * 0.62); + button.iconTex = g_pHyprRenderer->renderText(button.icon, fgcol, std::round(button.size * 0.62 * scale), false, "sans", scaledButtonSize); } - if (button.iconTex->m_texID == 0) + if (!button.iconTex || button.iconTex->m_texID == 0) continue; - CBox pos = {barBox->x + (BUTTONSRIGHT ? barBox->width - offset - scaledButtonSize : offset), barBox->y + (barBox->height - scaledButtonSize) / 2.0, scaledButtonSize, - scaledButtonSize}; + const auto iconX = barBox->x + (BUTTONSRIGHT ? barBox->width - offset - scaledButtonSize / 2.0 : offset + scaledButtonSize / 2.0) - button.iconTex->m_size.x / 2.0; + const auto iconY = barBox->y + barBox->height / 2.0 - button.iconTex->m_size.y / 2.0; + CBox pos = {iconX, iconY, button.iconTex->m_size.x, button.iconTex->m_size.y}; - if (!**PICONONHOVER || (**PICONONHOVER && m_iButtonHoverState > 0)) + if (!ICONONHOVER || (ICONONHOVER && m_iButtonHoverState > 0)) g_pHyprOpenGL->renderTexture(button.iconTex, pos, {.a = a}); offset += scaledButtonsPad + scaledButtonSize; @@ -558,14 +413,14 @@ void CHyprBar::renderBarButtonsText(CBox* barBox, const float scale, const float } void CHyprBar::draw(PHLMONITOR pMonitor, const float& a) { - static auto* const PENABLED = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprbars:enabled")->getDataStaticPtr(); + const auto ENABLED = g_pGlobalState->config.enabled->value(); - if (m_bLastEnabledState != **PENABLED) { - m_bLastEnabledState = **PENABLED; + if (m_bLastEnabledState != ENABLED) { + m_bLastEnabledState = ENABLED; g_pDecorationPositioner->repositionDeco(this); } - if (m_hidden || !validMapped(m_pWindow) || !**PENABLED) + if (m_hidden || !validMapped(m_pWindow) || !ENABLED) return; const auto PWINDOW = m_pWindow.lock(); @@ -580,16 +435,16 @@ void CHyprBar::draw(PHLMONITOR pMonitor, const float& a) { void CHyprBar::renderPass(PHLMONITOR pMonitor, const float& a) { const auto PWINDOW = m_pWindow.lock(); - static auto* const PCOLOR = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprbars:bar_color")->getDataStaticPtr(); - static auto* const PHEIGHT = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprbars:bar_height")->getDataStaticPtr(); - static auto* const PPRECEDENCE = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprbars:bar_precedence_over_border")->getDataStaticPtr(); - static auto* const PALIGNBUTTONS = (Hyprlang::STRING const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprbars:bar_buttons_alignment")->getDataStaticPtr(); - static auto* const PENABLETITLE = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprbars:bar_title_enabled")->getDataStaticPtr(); - static auto* const PENABLEBLUR = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprbars:bar_blur")->getDataStaticPtr(); static auto* const PENABLEBLURGLOBAL = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "decoration:blur:enabled")->getDataStaticPtr(); - static auto* const PINACTIVECOLOR = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprbars:inactive_button_color")->getDataStaticPtr(); + const auto BARCOLOR = g_pGlobalState->config.barColor->value(); + const auto HEIGHT = g_pGlobalState->config.barHeight->value(); + const auto PRECEDENCE = g_pGlobalState->config.barPrecedenceOverBorder->value(); + const auto ALIGNBUTTONS = g_pGlobalState->config.barButtonsAlignment->value(); + const auto ENABLETITLE = g_pGlobalState->config.barTitleEnabled->value(); + const auto ENABLEBLUR = g_pGlobalState->config.barBlur->value(); + const auto INACTIVECOLOR = g_pGlobalState->config.inactiveButtonColor->value(); - if (**PINACTIVECOLOR > 0) { + if (INACTIVECOLOR > 0) { bool currentWindowFocus = PWINDOW == Desktop::focusState()->window(); if (currentWindowFocus != m_bWindowHasFocus) { m_bWindowHasFocus = currentWindowFocus; @@ -597,29 +452,29 @@ void CHyprBar::renderPass(PHLMONITOR pMonitor, const float& a) { } } - const CHyprColor DEST_COLOR = m_bForcedBarColor.value_or(**PCOLOR); + const CHyprColor DEST_COLOR = m_bForcedBarColor.value_or(configColor(BARCOLOR)); if (DEST_COLOR != m_cRealBarColor->goal()) *m_cRealBarColor = DEST_COLOR; CHyprColor color = m_cRealBarColor->value(); color.a *= a; - const bool BUTTONSRIGHT = std::string{*PALIGNBUTTONS} != "left"; - const bool SHOULDBLUR = **PENABLEBLUR && **PENABLEBLURGLOBAL && color.a < 1.F; + const bool BUTTONSRIGHT = ALIGNBUTTONS != "left"; + const bool SHOULDBLUR = ENABLEBLUR && **PENABLEBLURGLOBAL && color.a < 1.F; - if (**PHEIGHT < 1) { - m_iLastHeight = **PHEIGHT; + if (HEIGHT < 1) { + m_iLastHeight = HEIGHT; return; } const auto PWORKSPACE = PWINDOW->m_workspace; const auto WORKSPACEOFFSET = PWORKSPACE && !PWINDOW->m_pinned ? PWORKSPACE->m_renderOffset->value() : Vector2D(); - const auto ROUNDING = PWINDOW->rounding() + (*PPRECEDENCE ? 0 : PWINDOW->getRealBorderSize()); + const auto ROUNDING = PWINDOW->rounding() + (PRECEDENCE ? 0 : PWINDOW->getRealBorderSize()); const auto scaledRounding = ROUNDING > 0 ? ROUNDING * pMonitor->m_scale - 2 /* idk why but otherwise it looks bad due to the gaps */ : 0; - m_seExtents = {{0, **PHEIGHT}, {}}; + m_seExtents = {{0, HEIGHT}, {}}; const auto DECOBOX = assignedBoxGlobal(); @@ -668,7 +523,7 @@ void CHyprBar::renderPass(PHLMONITOR pMonitor, const float& a) { g_pHyprOpenGL->renderRect(titleBarBox, color, {.round = scaledRounding, .roundingPower = m_pWindow->roundingPower()}); // render title - if (**PENABLETITLE && (m_szLastTitle != PWINDOW->m_title || m_bWindowSizeChanged || m_pTextTex->m_texID == 0 || m_bTitleColorChanged)) { + if (ENABLETITLE && (m_szLastTitle != PWINDOW->m_title || m_bWindowSizeChanged || !m_pTextTex || m_pTextTex->m_texID == 0 || m_bTitleColorChanged)) { m_szLastTitle = PWINDOW->m_title; renderBarTitle(BARBUF, pMonitor->m_scale); } @@ -683,15 +538,29 @@ void CHyprBar::renderPass(PHLMONITOR pMonitor, const float& a) { } CBox textBox = {titleBarBox.x, titleBarBox.y, (int)BARBUF.x, (int)BARBUF.y}; - if (**PENABLETITLE) - g_pHyprOpenGL->renderTexture(m_pTextTex, textBox, {.a = a}); + if (ENABLETITLE && m_pTextTex) { + const auto BARPADDING = g_pGlobalState->config.barPadding->value(); + const auto BARBUTTONPADDING = g_pGlobalState->config.barButtonPadding->value(); + const auto ALIGN = g_pGlobalState->config.barTextAlign->value(); - if (m_bButtonsDirty || m_bWindowSizeChanged) { - renderBarButtons(BARBUF, pMonitor->m_scale); - m_bButtonsDirty = false; + float buttonSizes = BARBUTTONPADDING; + for (auto& b : g_pGlobalState->buttons) { + buttonSizes += b.size + BARBUTTONPADDING; + } + + const auto scaledBorderSize = PWINDOW->getRealBorderSize() * pMonitor->m_scale; + const auto scaledButtonsSize = buttonSizes * pMonitor->m_scale; + const auto scaledBarPadding = BARPADDING * pMonitor->m_scale; + const auto xOffset = ALIGN == "left" ? std::round(scaledBarPadding + (BUTTONSRIGHT ? 0 : scaledButtonsSize)) : + std::round(((BARBUF.x - scaledBorderSize) / 2.0 - m_pTextTex->m_size.x / 2.0)); + const auto yOffset = std::round((BARBUF.y - m_pTextTex->m_size.y) / 2.0); + CBox titleBox = {textBox.x + xOffset, textBox.y + yOffset, m_pTextTex->m_size.x, m_pTextTex->m_size.y}; + + g_pHyprOpenGL->renderTexture(m_pTextTex, titleBox, {.a = a}); } - g_pHyprOpenGL->renderTexture(m_pButtonsTex, textBox, {.a = a}); + renderBarButtons(&textBox, pMonitor->m_scale, a); + m_bButtonsDirty = false; g_pHyprOpenGL->scissor(nullptr); @@ -701,9 +570,9 @@ void CHyprBar::renderPass(PHLMONITOR pMonitor, const float& a) { m_bTitleColorChanged = false; // dynamic updates change the extents - if (m_iLastHeight != **PHEIGHT) { + if (m_iLastHeight != HEIGHT) { PWINDOW->layoutTarget()->recalc(); - m_iLastHeight = **PHEIGHT; + m_iLastHeight = HEIGHT; } } @@ -715,6 +584,15 @@ void CHyprBar::updateWindow(PHLWINDOW pWindow) { damageEntire(); } +void CHyprBar::onConfigReloaded() { + m_bButtonsDirty = true; + m_bTitleColorChanged = true; + m_pTextTex = nullptr; + + g_pDecorationPositioner->repositionDeco(this); + damageEntire(); +} + void CHyprBar::damageEntire() { g_pHyprRenderer->damageBox(assignedBoxGlobal()); } @@ -728,8 +606,7 @@ eDecorationLayer CHyprBar::getDecorationLayer() { } uint64_t CHyprBar::getDecorationFlags() { - static auto* const PPART = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprbars:bar_part_of_window")->getDataStaticPtr(); - return DECORATION_ALLOWS_MOUSE_INPUT | (**PPART ? DECORATION_PART_OF_MAIN_WINDOW : 0); + return DECORATION_ALLOWS_MOUSE_INPUT | (g_pGlobalState->config.barPartOfWindow->value() ? DECORATION_PART_OF_MAIN_WINDOW : 0); } CBox CHyprBar::assignedBoxGlobal() { @@ -772,27 +649,27 @@ void CHyprBar::updateRules() { } void CHyprBar::damageOnButtonHover() { - static auto* const PBARPADDING = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprbars:bar_padding")->getDataStaticPtr(); - static auto* const PBARBUTTONPADDING = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprbars:bar_button_padding")->getDataStaticPtr(); - static auto* const PHEIGHT = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprbars:bar_height")->getDataStaticPtr(); - static auto* const PALIGNBUTTONS = (Hyprlang::STRING const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprbars:bar_buttons_alignment")->getDataStaticPtr(); - const bool BUTTONSRIGHT = std::string{*PALIGNBUTTONS} != "left"; + const auto BARPADDING = g_pGlobalState->config.barPadding->value(); + const auto BARBUTTONPADDING = g_pGlobalState->config.barButtonPadding->value(); + const auto HEIGHT = g_pGlobalState->config.barHeight->value(); + const auto ALIGNBUTTONS = g_pGlobalState->config.barButtonsAlignment->value(); + const bool BUTTONSRIGHT = ALIGNBUTTONS != "left"; - float offset = **PBARPADDING; + float offset = BARPADDING; - const auto COORDS = cursorRelativeToBar(); + const auto COORDS = cursorRelativeToBar(); for (auto& b : g_pGlobalState->buttons) { - const auto BARBUF = Vector2D{(int)assignedBoxGlobal().w, **PHEIGHT}; - Vector2D currentPos = Vector2D{(BUTTONSRIGHT ? BARBUF.x - **PBARBUTTONPADDING - b.size - offset : offset), (BARBUF.y - b.size) / 2.0}.floor(); + const auto BARBUF = Vector2D{(int)assignedBoxGlobal().w, HEIGHT}; + Vector2D currentPos = Vector2D{(BUTTONSRIGHT ? BARBUF.x - BARBUTTONPADDING - b.size - offset : offset), (BARBUF.y - b.size) / 2.0}.floor(); - bool hover = VECINRECT(COORDS, currentPos.x, currentPos.y, currentPos.x + b.size + **PBARBUTTONPADDING, currentPos.y + b.size); + bool hover = VECINRECT(COORDS, currentPos.x, currentPos.y, currentPos.x + b.size + BARBUTTONPADDING, currentPos.y + b.size); if (hover != m_bButtonHovered) { m_bButtonHovered = hover; damageEntire(); } - offset += **PBARBUTTONPADDING + b.size; + offset += BARBUTTONPADDING + b.size; } } diff --git a/hyprbars/barDeco.hpp b/hyprbars/barDeco.hpp index bc4d32d..a3b4e2d 100644 --- a/hyprbars/barDeco.hpp +++ b/hyprbars/barDeco.hpp @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -48,52 +49,51 @@ class CHyprBar : public IHyprWindowDecoration { PHLWINDOW getOwner(); void updateRules(); + void onConfigReloaded(); WP m_self; private: - SBoxExtents m_seExtents; + SBoxExtents m_seExtents; - PHLWINDOWREF m_pWindow; + PHLWINDOWREF m_pWindow; - CBox m_bAssignedBox; + CBox m_bAssignedBox; - SP m_pTextTex; - SP m_pButtonsTex; + SP m_pTextTex; - bool m_bWindowSizeChanged = false; - bool m_hidden = false; - bool m_bTitleColorChanged = false; - bool m_bButtonHovered = false; - bool m_bLastEnabledState = false; - bool m_bWindowHasFocus = false; - std::optional m_bForcedBarColor; - std::optional m_bForcedTitleColor; + bool m_bWindowSizeChanged = false; + bool m_hidden = false; + bool m_bTitleColorChanged = false; + bool m_bButtonHovered = false; + bool m_bLastEnabledState = false; + bool m_bWindowHasFocus = false; + std::optional m_bForcedBarColor; + std::optional m_bForcedTitleColor; - Time::steady_tp m_lastMouseDown = Time::steadyNow(); + Time::steady_tp m_lastMouseDown = Time::steadyNow(); - PHLANIMVAR m_cRealBarColor; + PHLANIMVAR m_cRealBarColor; - Vector2D cursorRelativeToBar(); + Vector2D cursorRelativeToBar(); - void renderPass(PHLMONITOR, float const& a); - void renderBarTitle(const Vector2D& bufferSize, const float scale); - void renderText(SP out, const std::string& text, const CHyprColor& color, const Vector2D& bufferSize, const float scale, const int fontSize); - void renderBarButtons(const Vector2D& bufferSize, const float scale); - void renderBarButtonsText(CBox* barBox, const float scale, const float a); - void damageOnButtonHover(); + void renderPass(PHLMONITOR, float const& a); + void renderBarTitle(const Vector2D& bufferSize, const float scale); + void renderBarButtons(CBox* barBox, const float scale, const float a); + void renderBarButtonsText(CBox* barBox, const float scale, const float a); + void damageOnButtonHover(); - bool inputIsValid(); - void onMouseButton(Event::SCallbackInfo& info, IPointer::SButtonEvent e); - void onTouchDown(Event::SCallbackInfo& info, ITouch::SDownEvent e); - void onTouchUp(Event::SCallbackInfo& info, ITouch::SUpEvent e); - void onMouseMove(Vector2D coords); - void onTouchMove(Event::SCallbackInfo& info, ITouch::SMotionEvent e); + bool inputIsValid(); + void onMouseButton(Event::SCallbackInfo& info, IPointer::SButtonEvent e); + void onTouchDown(Event::SCallbackInfo& info, ITouch::SDownEvent e); + void onTouchUp(Event::SCallbackInfo& info, ITouch::SUpEvent e); + void onMouseMove(Vector2D coords); + void onTouchMove(Event::SCallbackInfo& info, ITouch::SMotionEvent e); - void handleDownEvent(Event::SCallbackInfo& info, std::optional touchEvent); - void handleUpEvent(Event::SCallbackInfo& info); - void handleMovement(); - bool doButtonPress(Hyprlang::INT* const* PBARPADDING, Hyprlang::INT* const* PBARBUTTONPADDING, Hyprlang::INT* const* PHEIGHT, Vector2D COORDS, bool BUTTONSRIGHT); + void handleDownEvent(Event::SCallbackInfo& info, std::optional touchEvent); + void handleUpEvent(Event::SCallbackInfo& info); + void handleMovement(); + bool doButtonPress(Config::INTEGER barPadding, Config::INTEGER barButtonPadding, Config::INTEGER barHeight, Vector2D COORDS, bool BUTTONSRIGHT); CBox assignedBoxGlobal(); @@ -118,7 +118,7 @@ class CHyprBar : public IHyprWindowDecoration { // for dynamic updates int m_iLastHeight = 0; - size_t getVisibleButtonCount(Hyprlang::INT* const* PBARBUTTONPADDING, Hyprlang::INT* const* PBARPADDING, const Vector2D& bufferSize, const float scale); + size_t getVisibleButtonCount(Config::INTEGER barButtonPadding, Config::INTEGER barPadding, const Vector2D& bufferSize, const float scale); friend class CBarPassElement; }; diff --git a/hyprbars/globals.hpp b/hyprbars/globals.hpp index 79bf4dc..9a44e9f 100644 --- a/hyprbars/globals.hpp +++ b/hyprbars/globals.hpp @@ -2,17 +2,21 @@ #include #include +#include +#include +#include +#include inline HANDLE PHANDLE = nullptr; struct SHyprButton { - std::string cmd = ""; - bool userfg = false; - CHyprColor fgcol = CHyprColor(0, 0, 0, 0); - CHyprColor bgcol = CHyprColor(0, 0, 0, 0); - float size = 10; - std::string icon = ""; - SP iconTex = makeShared(); + std::string cmd = ""; + bool userfg = false; + CHyprColor fgcol = CHyprColor(0, 0, 0, 0); + CHyprColor bgcol = CHyprColor(0, 0, 0, 0); + float size = 10; + std::string icon = ""; + SP iconTex; }; class CHyprBar; @@ -20,9 +24,19 @@ class CHyprBar; struct SGlobalState { std::vector buttons; std::vector> bars; - uint32_t nobarRuleIdx = 0; - uint32_t barColorRuleIdx = 0; + uint32_t nobarRuleIdx = 0; + uint32_t barColorRuleIdx = 0; uint32_t titleColorRuleIdx = 0; + + struct { + SP barColor, textColor, inactiveButtonColor; + SP barHeight; + SP barTextSize; + SP barPadding; + SP barButtonPadding; + SP barBlur, barTitleEnabled, barPartOfWindow, barPrecedenceOverBorder, enabled, iconOnHover; + SP barTextFont, barTextAlign, barButtonsAlignment, onDoubleClick; + } config; }; inline UP g_pGlobalState; diff --git a/hyprbars/main.cpp b/hyprbars/main.cpp index 7c3dd9b..72a4491 100644 --- a/hyprbars/main.cpp +++ b/hyprbars/main.cpp @@ -9,12 +9,21 @@ #include #include #include +#include +#include + +#include #include #include "barDeco.hpp" #include "globals.hpp" +extern "C" { +#include +#include +} + // Do NOT change this function. APICALL EXPORT std::string PLUGIN_API_VERSION() { return HYPRLAND_API_VERSION; @@ -36,6 +45,15 @@ static void onPreConfigReload() { g_pGlobalState->buttons.clear(); } +static void onConfigReloaded() { + for (auto& b : g_pGlobalState->bars) { + if (!b) + continue; + + b->onConfigReloaded(); + } +} + static void onUpdateWindowRules(PHLWINDOW window) { const auto BARIT = std::find_if(g_pGlobalState->bars.begin(), g_pGlobalState->bars.end(), [window](const auto& bar) { return bar->getOwner() == window; }); @@ -47,10 +65,10 @@ static void onUpdateWindowRules(PHLWINDOW window) { } Hyprlang::CParseResult onNewButton(const char* K, const char* V) { - std::string v = V; - CVarList vars(v); + std::string v = V; + Hyprutils::String::CVarList vars(v); - Hyprlang::CParseResult result; + Hyprlang::CParseResult result; // hyprbars-button = bgcolor, size, icon, action, fgcolor @@ -95,6 +113,80 @@ Hyprlang::CParseResult onNewButton(const char* K, const char* V) { return result; } +int newLuaButton(lua_State* L) { + if (!lua_istable(L, 1)) + return Config::Lua::Bindings::Internal::configError(L, "add_button: expected a table { bg_color, fg_color, size, icon, action }"); + + SHyprButton button; + + { + Hyprutils::Utils::CScopeGuard x([L] { lua_pop(L, 1); }); + + lua_getfield(L, 1, "bg_color"); + + Config::Lua::CLuaConfigColor parser(0); + auto err = parser.parse(L); + if (err.errorCode != Config::Lua::PARSE_ERROR_OK) + return Config::Lua::Bindings::Internal::configError(L, "add_button: failed to parse bg_color"); + + button.bgcol = parser.parsed(); + } + + { + Hyprutils::Utils::CScopeGuard x([L] { lua_pop(L, 1); }); + + lua_getfield(L, 1, "fg_color"); + + Config::Lua::CLuaConfigColor parser(0); + auto err = parser.parse(L); + if (err.errorCode != Config::Lua::PARSE_ERROR_OK) + return Config::Lua::Bindings::Internal::configError(L, "add_button: failed to parse fg_color"); + + button.fgcol = parser.parsed(); + } + + { + Hyprutils::Utils::CScopeGuard x([L] { lua_pop(L, 1); }); + + lua_getfield(L, 1, "size"); + + if (!lua_isnumber(L, -1)) + return Config::Lua::Bindings::Internal::configError(L, "add_button: size must be an integer"); + + button.size = lua_tointeger(L, -1); + } + + { + Hyprutils::Utils::CScopeGuard x([L] { lua_pop(L, 1); }); + + lua_getfield(L, 1, "icon"); + + if (!lua_isstring(L, -1)) + return Config::Lua::Bindings::Internal::configError(L, "add_button: icon must be a string"); + + button.icon = lua_tostring(L, -1); + } + + { + Hyprutils::Utils::CScopeGuard x([L] { lua_pop(L, 1); }); + + lua_getfield(L, 1, "action"); + + if (!lua_isstring(L, -1)) + return Config::Lua::Bindings::Internal::configError(L, "add_button: action must be a string"); + + button.cmd = lua_tostring(L, -1); + } + + g_pGlobalState->buttons.push_back(std::move(button)); + + for (auto& b : g_pGlobalState->bars) { + b->m_bButtonsDirty = true; + } + + return 0; +} + APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) { PHANDLE = handle; @@ -112,29 +204,54 @@ APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) { g_pGlobalState->barColorRuleIdx = Desktop::Rule::windowEffects()->registerEffect("hyprbars:bar_color"); g_pGlobalState->titleColorRuleIdx = Desktop::Rule::windowEffects()->registerEffect("hyprbars:title_color"); - static auto P = Event::bus()->m_events.window.open.listen([&](PHLWINDOW w) { onNewWindow(w); }); + static auto P = Event::bus()->m_events.window.open.listen([&](PHLWINDOW w) { onNewWindow(w); }); static auto P3 = Event::bus()->m_events.window.updateRules.listen([&](PHLWINDOW w) { onUpdateWindowRules(w); }); - HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprbars:bar_color", Hyprlang::INT{*configStringToInt("rgba(33333388)")}); - HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprbars:bar_height", Hyprlang::INT{15}); - HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprbars:col.text", Hyprlang::INT{*configStringToInt("rgba(ffffffff)")}); - HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprbars:bar_text_size", Hyprlang::INT{10}); - HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprbars:bar_title_enabled", Hyprlang::INT{1}); - HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprbars:bar_blur", Hyprlang::INT{0}); - HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprbars:bar_text_font", Hyprlang::STRING{"Sans"}); - HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprbars:bar_text_align", Hyprlang::STRING{"center"}); - HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprbars:bar_part_of_window", Hyprlang::INT{1}); - HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprbars:bar_precedence_over_border", Hyprlang::INT{0}); - HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprbars:bar_buttons_alignment", Hyprlang::STRING{"right"}); - HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprbars:bar_padding", Hyprlang::INT{7}); - HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprbars:bar_button_padding", Hyprlang::INT{5}); - HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprbars:enabled", Hyprlang::INT{1}); - HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprbars:icon_on_hover", Hyprlang::INT{0}); - HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprbars:inactive_button_color", Hyprlang::INT{0}); // unset - HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprbars:on_double_click", Hyprlang::STRING{""}); + g_pGlobalState->config.barColor = makeShared("plugin:hyprbars:bar_color", "Change the bar color", *configStringToInt("rgba(33333388)")); + g_pGlobalState->config.textColor = makeShared("plugin:hyprbars:col.text", "Change the text color", *configStringToInt("rgba(ffffffff)")); + g_pGlobalState->config.inactiveButtonColor = makeShared( + "plugin:hyprbars:inactive_button_color", "Change the inactive button's color. 0x00000000 means unset", *configStringToInt("rgba(00000000)")); + g_pGlobalState->config.barHeight = makeShared("plugin:hyprbars:bar_height", "Change the bar's height", 15); + g_pGlobalState->config.barTextSize = makeShared("plugin:hyprbars:bar_text_size", "Change the bar's text size", 10); + g_pGlobalState->config.barTitleEnabled = makeShared("plugin:hyprbars:bar_title_enabled", "Whether to enable titles in the bar", true); + g_pGlobalState->config.barBlur = makeShared("plugin:hyprbars:bar_blur", "Whether to enable blur of the bar", false); + g_pGlobalState->config.barTextFont = makeShared("plugin:hyprbars:bar_text_font", "Bar's text font", "Sans"); + g_pGlobalState->config.barTextAlign = makeShared("plugin:hyprbars:bar_text_align", "Bar's text alignment", "center"); + g_pGlobalState->config.barPartOfWindow = + makeShared("plugin:hyprbars:bar_part_of_window", "Whether the bar is a part of the window (reserves space)", true); + g_pGlobalState->config.barPrecedenceOverBorder = + makeShared("plugin:hyprbars:bar_precedence_over_border", "Whether the bar is before, or after the border", false); + g_pGlobalState->config.barButtonsAlignment = makeShared("plugin:hyprbars:bar_buttons_alignment", "Alignment of the bar buttons", "right"); + g_pGlobalState->config.barPadding = makeShared("plugin:hyprbars:bar_padding", "Padding of the bar", 7); + g_pGlobalState->config.barButtonPadding = makeShared("plugin:hyprbars:bar_button_padding", "Padding of the bar buttons", 5); + g_pGlobalState->config.enabled = makeShared("plugin:hyprbars:enabled", "Whether bars are enabled", true); + g_pGlobalState->config.iconOnHover = makeShared("plugin:hyprbars:icon_on_hover", "Whether to use an icon on hover of the buttons", false); + g_pGlobalState->config.onDoubleClick = makeShared("plugin:hyprbars:on_double_click", "Action to execute on double click of the bar", ""); - HyprlandAPI::addConfigKeyword(PHANDLE, "plugin:hyprbars:hyprbars-button", onNewButton, Hyprlang::SHandlerOptions{}); + HyprlandAPI::addConfigValueV2(PHANDLE, g_pGlobalState->config.barColor); + HyprlandAPI::addConfigValueV2(PHANDLE, g_pGlobalState->config.textColor); + HyprlandAPI::addConfigValueV2(PHANDLE, g_pGlobalState->config.inactiveButtonColor); + HyprlandAPI::addConfigValueV2(PHANDLE, g_pGlobalState->config.barHeight); + HyprlandAPI::addConfigValueV2(PHANDLE, g_pGlobalState->config.barTextSize); + HyprlandAPI::addConfigValueV2(PHANDLE, g_pGlobalState->config.barTitleEnabled); + HyprlandAPI::addConfigValueV2(PHANDLE, g_pGlobalState->config.barBlur); + HyprlandAPI::addConfigValueV2(PHANDLE, g_pGlobalState->config.barTextFont); + HyprlandAPI::addConfigValueV2(PHANDLE, g_pGlobalState->config.barTextAlign); + HyprlandAPI::addConfigValueV2(PHANDLE, g_pGlobalState->config.barPartOfWindow); + HyprlandAPI::addConfigValueV2(PHANDLE, g_pGlobalState->config.barPrecedenceOverBorder); + HyprlandAPI::addConfigValueV2(PHANDLE, g_pGlobalState->config.barButtonsAlignment); + HyprlandAPI::addConfigValueV2(PHANDLE, g_pGlobalState->config.barPadding); + HyprlandAPI::addConfigValueV2(PHANDLE, g_pGlobalState->config.barButtonPadding); + HyprlandAPI::addConfigValueV2(PHANDLE, g_pGlobalState->config.enabled); + HyprlandAPI::addConfigValueV2(PHANDLE, g_pGlobalState->config.iconOnHover); + HyprlandAPI::addConfigValueV2(PHANDLE, g_pGlobalState->config.onDoubleClick); + + if (Config::mgr()->type() == Config::CONFIG_LEGACY) + HyprlandAPI::addConfigKeyword(PHANDLE, "plugin:hyprbars:hyprbars-button", onNewButton, Hyprlang::SHandlerOptions{}); + else + HyprlandAPI::addLuaFunction(PHANDLE, "hyprbars", "add_button", ::newLuaButton); static auto P4 = Event::bus()->m_events.config.preReload.listen([&] { onPreConfigReload(); }); + static auto P5 = Event::bus()->m_events.config.reloaded.listen([&] { onConfigReloaded(); }); // add deco to existing windows for (auto& w : g_pCompositor->m_windows) { diff --git a/hyprbars/meson.build b/hyprbars/meson.build index 6a6238f..7002ba4 100644 --- a/hyprbars/meson.build +++ b/hyprbars/meson.build @@ -28,7 +28,6 @@ shared_module(meson.project_name(), src, dependency('hyprland'), dependency('pixman-1'), dependency('libdrm'), - dependency('pangocairo'), dependency('libinput'), dependency('libudev'), dependency('wayland-server'), diff --git a/hyprfocus/main.cpp b/hyprfocus/main.cpp index 1e6330a..3950aa9 100644 --- a/hyprfocus/main.cpp +++ b/hyprfocus/main.cpp @@ -10,11 +10,15 @@ #define private public #include #include +#include #include #include #include #include #include +#include +#include +#include #include #undef private @@ -25,6 +29,12 @@ using namespace Hyprutils::String; using namespace Hyprutils::Animation; +static struct { + SP onlyOnMonitorChange; + SP fadeOpacity, slideHeight, bounceStrength; + SP mode; +} configValues; + // Do NOT change this function. APICALL EXPORT std::string PLUGIN_API_VERSION() { return HYPRLAND_API_VERSION; @@ -39,23 +49,17 @@ static void onFocusChange(PHLWINDOW window) { if (lastWindow == window) return; - static const auto PONLY_ON_MONITOR_CHANGE = CConfigValue("plugin:hyprfocus:only_on_monitor_change"); - if (*PONLY_ON_MONITOR_CHANGE && lastWindow && lastWindow->m_monitor == window->m_monitor) + if (configValues.onlyOnMonitorChange->value() && lastWindow && lastWindow->m_monitor == window->m_monitor) return; lastWindow = window; + const auto PIN = Config::animationTree()->getAnimationPropertyConfig("hyprfocusIn"); + const auto POUT = Config::animationTree()->getAnimationPropertyConfig("hyprfocusOut"); - static const auto POPACITY = CConfigValue("plugin:hyprfocus:fade_opacity"); - static const auto PBOUNCE = CConfigValue("plugin:hyprfocus:bounce_strength"); - static const auto PSLIDE = CConfigValue("plugin:hyprfocus:slide_height"); - static const auto PMODE = CConfigValue("plugin:hyprfocus:mode"); - const auto PIN = g_pConfigManager->getAnimationPropertyConfig("hyprfocusIn"); - const auto POUT = g_pConfigManager->getAnimationPropertyConfig("hyprfocusOut"); - - if (*PMODE == "flash") { + if (configValues.mode->value() == "flash") { const auto ORIGINAL = window->m_activeInactiveAlpha->goal(); window->m_activeInactiveAlpha->setConfig(PIN); - *window->m_activeInactiveAlpha = std::clamp(*POPACITY, 0.F, 1.F); + *window->m_activeInactiveAlpha = configValues.fadeOpacity->value(); window->m_activeInactiveAlpha->setCallbackOnEnd([w = PHLWINDOWREF{window}, POUT, ORIGINAL](WP pav) { if (!w) @@ -65,13 +69,13 @@ static void onFocusChange(PHLWINDOW window) { w->m_activeInactiveAlpha->setCallbackOnEnd(nullptr); }); - } else if (*PMODE == "bounce") { + } else if (configValues.mode->value() == "bounce") { const auto ORIGINAL = CBox{window->m_realPosition->goal(), window->m_realSize->goal()}; window->m_realPosition->setConfig(PIN); window->m_realSize->setConfig(PIN); - auto box = ORIGINAL.copy().scaleFromCenter(std::clamp(*PBOUNCE, 0.1F, 1.F)); + auto box = ORIGINAL.copy().scaleFromCenter(configValues.bounceStrength->value()); *window->m_realPosition = box.pos(); *window->m_realSize = box.size(); @@ -90,12 +94,12 @@ static void onFocusChange(PHLWINDOW window) { w->m_realSize->setCallbackOnEnd(nullptr); }); - } else if (*PMODE == "slide") { + } else if (configValues.mode->value() == "slide") { const auto ORIGINAL = window->m_realPosition->goal(); window->m_realPosition->setConfig(PIN); - *window->m_realPosition = ORIGINAL - Vector2D{0.F, std::clamp(*PSLIDE, 0.F, 150.F)}; + *window->m_realPosition = ORIGINAL - Vector2D{0.F, configValues.slideHeight->value()}; window->m_realPosition->setCallbackOnEnd([w = PHLWINDOWREF{window}, POUT, ORIGINAL](WP pav) { if (!w) @@ -126,16 +130,22 @@ APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) { static auto P = Event::bus()->m_events.window.active.listen([&](PHLWINDOW w, Desktop::eFocusReason r) { onFocusChange(w); }); - HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprfocus:mode", Hyprlang::STRING{"flash"}); - HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprfocus:only_on_monitor_change", Hyprlang::INT{0}); - HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprfocus:fade_opacity", Hyprlang::FLOAT{0.8F}); - HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprfocus:slide_height", Hyprlang::FLOAT{20.F}); - HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprfocus:bounce_strength", Hyprlang::FLOAT{0.95F}); + configValues.mode = makeShared("plugin:hyprfocus:mode", "mode to use", "flash"); + configValues.onlyOnMonitorChange = makeShared("plugin:hyprfocus:only_on_monitor_change", "whether to fire the animation only on monitor change", false); + configValues.fadeOpacity = makeShared("plugin:hyprfocus:fade_opacity", "fade opacity", 0.8F, Config::Values::SFloatValueOptions{.min = 0.F, .max = 1.F} ); + configValues.slideHeight = makeShared("plugin:hyprfocus:slide_height", "slide height", 20.F, Config::Values::SFloatValueOptions{.min = 0.F, .max = 150.F} ); + configValues.bounceStrength = makeShared("plugin:hyprfocus:bounce_strength", "bounce strength", 0.95F, Config::Values::SFloatValueOptions{.min = 0.F, .max = 1.F} ); + + HyprlandAPI::addConfigValueV2(PHANDLE, configValues.mode); + HyprlandAPI::addConfigValueV2(PHANDLE, configValues.onlyOnMonitorChange); + HyprlandAPI::addConfigValueV2(PHANDLE, configValues.fadeOpacity); + HyprlandAPI::addConfigValueV2(PHANDLE, configValues.slideHeight); + HyprlandAPI::addConfigValueV2(PHANDLE, configValues.bounceStrength); // this will not be cleaned up after we are unloaded but it doesn't really matter, // as if we create this again it will just overwrite the old one. - g_pConfigManager->m_animationTree.createNode("hyprfocusIn", "windowsIn"); - g_pConfigManager->m_animationTree.createNode("hyprfocusOut", "windowsOut"); + Config::animationTree()->m_animationTree.createNode("hyprfocusIn", "windowsIn"); + Config::animationTree()->m_animationTree.createNode("hyprfocusOut", "windowsOut"); return {"hyprfocus", "Flashfocus for Hyprland", "Vaxry", "1.0"}; }