From 74fc9aefaf01e42d84b466ab7b3e4758a847eb9c Mon Sep 17 00:00:00 2001 From: The_miro Date: Sun, 19 Jul 2026 17:36:04 +0200 Subject: [PATCH] feat(hyprdrive/beacon): draw the divider as a Cairo magenta sine path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaces the ∿-glyph label divider with a Gtk.DrawingArea that strokes a sampled sine wave (soft-glow + bright-core passes), colour per urgency (magenta / accent), phase-advanced each tick so it travels like a live signal. Background stays transparent — a class-specific rule overrides the CyberQueer theme's universal `background-color`, so no dark pill shows behind it. Co-Authored-By: Claude Opus 4.8 --- desktopenvs/hyprdrive/beacon/notification.py | 45 ++++++++++++++++++-- desktopenvs/hyprdrive/beacon/style/style.css | 15 ++++--- 2 files changed, 50 insertions(+), 10 deletions(-) diff --git a/desktopenvs/hyprdrive/beacon/notification.py b/desktopenvs/hyprdrive/beacon/notification.py index 4cfd7aa..3ee6ef4 100644 --- a/desktopenvs/hyprdrive/beacon/notification.py +++ b/desktopenvs/hyprdrive/beacon/notification.py @@ -12,6 +12,7 @@ from __future__ import annotations import math from typing import Callable, Optional +import cairo import gi gi.require_version("Gtk", "4.0") @@ -21,9 +22,17 @@ from gi.repository import Gdk, GdkPixbuf, GLib, Gtk # noqa: E402 from lib.hologram import HologramOverlay -_SQUIGGLE = "∿" * 16 # ∿ sine-wave "tuned signal" divider _CARD_RADIUS = 16.0 +# Divider "radio wave" colour (Cairo, not CSS): a magenta wave line on a +# transparent background. Critical keeps an accent wave to match its frame. +_MAGENTA = (0xEB / 255, 0x00 / 255, 0xA6 / 255) # foreground wave (normal) +_ACCENT = (0xE4 / 255, 0x00 / 255, 0x46 / 255) # foreground wave (critical) +_SQUIGGLE_H = 14 # divider row height +_SQUIGGLE_AMP = 3.0 # wave amplitude (px) +_SQUIGGLE_CYCLES = 0.045 # cycles per px of width +_SQUIGGLE_SPEED = 2.4 # phase advance (rad/s) — a slowly travelling signal + def _rounded_path(cr, w: float, h: float, r: float = _CARD_RADIUS) -> None: r = min(r, w / 2, h / 2) @@ -66,9 +75,14 @@ class NotificationCard: lbl.set_max_width_chars(30) textcol.append(lbl) - squig = Gtk.Label(label=_SQUIGGLE, xalign=0.0) - squig.add_css_class("beacon-squiggle") - textcol.append(squig) + self._squiggle_color = _ACCENT if critical else _MAGENTA + self._squiggle_phase = 0.0 + self._squiggle = Gtk.DrawingArea() + self._squiggle.add_css_class("beacon-squiggle") + self._squiggle.set_content_height(_SQUIGGLE_H) + self._squiggle.set_hexpand(True) + self._squiggle.set_draw_func(self._draw_squiggle) + textcol.append(self._squiggle) if body: blbl = Gtk.Label(xalign=0.0) @@ -123,6 +137,29 @@ class NotificationCard: # -- public --------------------------------------------------------------- def tick(self, dt: float) -> None: self._holo.tick(dt) + self._squiggle_phase += dt * _SQUIGGLE_SPEED + self._squiggle.queue_draw() # travel the wave along like a live signal + + def _draw_squiggle(self, _area, cr, width: int, height: int) -> None: + if width <= 0: + return + # transparent background — just the magenta (accent for critical) radio wave + mid = height / 2.0 + amp = min(_SQUIGGLE_AMP, mid - 2.0) + k = _SQUIGGLE_CYCLES * 2.0 * math.pi # angular freq per px + steps = max(2, int(width)) + cr.set_line_cap(cairo.LINE_CAP_ROUND) + cr.set_line_join(cairo.LINE_JOIN_ROUND) + # two passes: a soft wide glow, then a bright thin core — reads as emitted + # light over the purple bar, matching the card's holographic frame. + for line_w, alpha in ((3.0, 0.30), (1.4, 1.0)): + cr.set_line_width(line_w) + cr.set_source_rgba(*self._squiggle_color, alpha) + for i in range(steps + 1): + x = width * i / steps + y = mid + amp * math.sin(x * k + self._squiggle_phase) + cr.line_to(x, y) if i else cr.move_to(x, y) + cr.stroke() def dismiss(self) -> None: """Play the dissolve, then hand the id back to the window for removal.""" diff --git a/desktopenvs/hyprdrive/beacon/style/style.css b/desktopenvs/hyprdrive/beacon/style/style.css index 7d95bd9..0ca352d 100644 --- a/desktopenvs/hyprdrive/beacon/style/style.css +++ b/desktopenvs/hyprdrive/beacon/style/style.css @@ -54,14 +54,17 @@ drawingarea { } .beacon-card.critical .beacon-summary { color: @accent; } -/* radio-squiggle divider (the tuned-signal line) */ +/* radio-wave divider — a Cairo sine path drawn in notification.py (colour handled + * there, per urgency); this only spaces it from the title/body. The explicit + * transparent bg beats the CyberQueer theme's `* { background-color:#1a1a1a }` + * (a class selector out-specifies its universal one), so no dark pill shows. */ .beacon-squiggle { - color: #8A5CFF; - font-size: 9pt; - margin: 1px 0; - opacity: 0.9; + margin: 2px 0; + background: none; + background-color: transparent; + border: none; + box-shadow: none; } -.beacon-card.critical .beacon-squiggle { color: @accent; } .beacon-body { color: @text;