Add an inward glow bleeding from the border over the window
New plugin:hyprchrome:glow_size (px, 0 = off) and glow_strength (0-1) bleed the border's own gradient inward past the window edge, over the window's own pixels. Off by default, so existing setups are unchanged. Drawn into the hole the ring's even-odd fill already leaves behind, from overlapping layers - one per px of depth - each covering the window edge inward to a progressively greater depth. Overlapping rather than abutting disjoint bands avoids an antialiasing seam at every shared edge; the cost is that a layer composites over every deeper one, so its alpha is solved outermost-inward from the target profile rather than being it. That profile is strength * (1 - d/glow)^2.2: steep off the window edge, easing into a tail that reaches zero tangentially so there's no ring where it stops. Corner handling, in order of how much it mattered: - Each layer's outer edge is the ring's inner boundary verbatim, chamfer vertices and all. Anything else detaches the glow from the frame and opens a sliver of unpainted window at each corner. - Each layer's inner edge - which is what the falloff's contours actually follow - is filleted in proportion to its own depth, so the glow reads as chamfered where it meets the frame and rounder as it fades inward. - Those inner edges also shrink their chamfer by (2-sqrt2) per px of inset. Insetting a chamfered rect while holding the chamfer constant moves the 45-degree face in by d*sqrt(2) rather than d, which had the glow running ~41% deeper at every corner than along the sides. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -44,6 +44,8 @@ std::vector<UP<IPassElement>> ChromePassElement::draw() {
|
||||
? hyprlandBorder
|
||||
: (isActive ? PluginState->config.activeColor->value() : PluginState->config.inactiveColor->value()));
|
||||
const float borderAlpha = gradient.FirstAlpha();
|
||||
const float glowPx = static_cast<float>(PluginState->config.glowSize->value()) * monitor->m_scale;
|
||||
const float glowStrength = static_cast<float>(PluginState->config.glowStrength->value());
|
||||
const float titleBarHeightPx = static_cast<float>(PluginState->config.titlebarHeight->value()) * monitor->m_scale;
|
||||
const float textSizePx = static_cast<float>(PluginState->config.titlebarTextSize->value()) * monitor->m_scale;
|
||||
const std::string fontFamily = PluginState->config.titlebarFont->value();
|
||||
@@ -73,7 +75,7 @@ std::vector<UP<IPassElement>> ChromePassElement::draw() {
|
||||
// with title length - otherwise every title change would needlessly
|
||||
// regenerate an identical border texture.
|
||||
const float borderTitleBarWidthPx = geo.fullSpan ? geo.MaxTitleBarWidth() : geo.titleBarWidth;
|
||||
const auto tex = data.decoration->GetBorderTexture({box.w, box.h}, extentPx, chamferPx, gradient, titleBarHeightPx, borderTitleBarWidthPx);
|
||||
const auto tex = data.decoration->GetBorderTexture({box.w, box.h}, extentPx, chamferPx, gradient, titleBarHeightPx, borderTitleBarWidthPx, glowPx, glowStrength);
|
||||
if (!tex || !tex->ok())
|
||||
return {};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user