hyprbars: Add icon_on_hover option (#305)

This commit is contained in:
Khalid 2025-04-06 17:43:42 +03:00 committed by GitHub
parent cef1854a54
commit be6b9875dd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 62 additions and 3 deletions

View File

@ -48,6 +48,8 @@ plugin {
`bar_button_padding` -> (int) padding between the buttons (default `5`)
`icon_on_hover` -> (bool) whether the icons show on mouse hovering over the buttons (default `false`)
## Buttons Config
Use the `hyprbars-button` keyword.

View File

@ -113,6 +113,11 @@ void CHyprBar::onTouchDown(SCallbackInfo& info, ITouch::SDownEvent 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)
damageOnButtonHover();
if (!m_bDragPending || m_bTouchEv || !validMapped(m_pWindow))
return;
@ -160,7 +165,8 @@ void CHyprBar::handleDownEvent(SCallbackInfo& info, std::optional<ITouch::SDownE
return;
}
g_pCompositor->focusWindow(PWINDOW);
if (g_pCompositor->m_pLastWindow.lock() != PWINDOW)
g_pCompositor->focusWindow(PWINDOW);
if (PWINDOW->m_bIsFloating)
g_pCompositor->changeWindowZOrder(PWINDOW, true);
@ -437,19 +443,30 @@ void CHyprBar::renderBarButtons(const Vector2D& bufferSize, const float scale) {
}
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 bool BUTTONSRIGHT = std::string{*PALIGNBUTTONS} != "left";
const auto visibleCount = getVisibleButtonCount(PBARBUTTONPADDING, PBARPADDING, Vector2D{barBox->w, barBox->h}, scale);
const auto COORDS = cursorRelativeToBar();
int offset = **PBARPADDING * scale;
float noScaleOffset = **PBARPADDING;
int offset = **PBARPADDING * scale;
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;
// 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;
if (button.iconTex->m_iTexID == 0 /* icon is not rendered */ && !button.icon.empty()) {
// render icon
const Vector2D BUFSIZE = {scaledButtonSize, scaledButtonSize};
@ -464,8 +481,16 @@ void CHyprBar::renderBarButtonsText(CBox* barBox, const float scale, const float
CBox pos = {barBox->x + (BUTTONSRIGHT ? barBox->width - offset - scaledButtonSize : offset), barBox->y + (barBox->height - scaledButtonSize) / 2.0, scaledButtonSize,
scaledButtonSize};
g_pHyprOpenGL->renderTexture(button.iconTex, pos, a);
if (!**PICONONHOVER || (**PICONONHOVER && m_iButtonHoverState > 0))
g_pHyprOpenGL->renderTexture(button.iconTex, pos, a);
offset += scaledButtonsPad + scaledButtonSize;
bool currentBit = (m_iButtonHoverState & (1 << i)) != 0;
if (hovering != currentBit) {
m_iButtonHoverState ^= (1 << i);
// damage to get rid of some artifacts when icons are "hidden"
damageEntire();
}
}
}
@ -675,3 +700,29 @@ void CHyprBar::applyRule(const SP<CWindowRule>& r) {
else if (r->szRule.starts_with("plugin:hyprbars:title_color"))
m_bForcedTitleColor = CHyprColor(configStringToInt(arg).value_or(0));
}
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";
float offset = **PBARPADDING;
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();
bool hover = VECINRECT(COORDS, currentPos.x, currentPos.y, currentPos.x + b.size + **PBARBUTTONPADDING, currentPos.y + b.size);
if (hover != m_bButtonHovered) {
m_bButtonHovered = hover;
damageEntire();
}
offset += **PBARBUTTONPADDING + b.size;
}
}

View File

@ -59,6 +59,7 @@ class CHyprBar : public IHyprWindowDecoration {
bool m_bWindowSizeChanged = false;
bool m_bHidden = false;
bool m_bTitleColorChanged = false;
bool m_bButtonHovered = false;
std::optional<CHyprColor> m_bForcedBarColor;
std::optional<CHyprColor> m_bForcedTitleColor;
@ -71,6 +72,7 @@ class CHyprBar : public IHyprWindowDecoration {
void renderText(SP<CTexture> 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();
bool inputIsValid();
void onMouseButton(SCallbackInfo& info, IPointer::SButtonEvent e);
@ -99,6 +101,9 @@ class CHyprBar : public IHyprWindowDecoration {
bool m_bDragPending = false;
bool m_bCancelledDown = false;
// store hover state for buttons as a bitfield
unsigned int m_iButtonHoverState = 0;
// for dynamic updates
int m_iLastHeight = 0;

View File

@ -140,6 +140,7 @@ APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) {
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:icon_on_hover", Hyprlang::INT{0});
HyprlandAPI::addConfigKeyword(PHANDLE, "hyprbars-button", onNewButton, Hyprlang::SHandlerOptions{});
static auto P4 = HyprlandAPI::registerCallbackDynamic(PHANDLE, "preConfigReload", [&](void* self, SCallbackInfo& info, std::any data) { onPreConfigReload(); });