mirror of
https://github.com/hyprwm/hyprland-plugins.git
synced 2025-10-29 11:48:42 +00:00
hyprbars: Add icon_on_hover option (#305)
This commit is contained in:
parent
cef1854a54
commit
be6b9875dd
@ -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.
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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(); });
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user