fix(shell): concentric hover-highlight radius on host cards

The FlowBoxChild draws the hover/selection highlight AROUND the card
(it wraps it with its own padding ring), so its default corner radius
ran visibly tighter than the card's 12px inside it. The host grids now
scope a 15px radius onto their children — card radius + the ring — so
the highlight's corners run concentric with the card's.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-07 22:37:09 +02:00
parent 4543a3f529
commit 8926d82a80
3 changed files with 21 additions and 3 deletions
+4
View File
@@ -23,6 +23,10 @@ pub const APP_ID: &str = "io.unom.Punktfunk";
/// named palette so dark mode just works. /// named palette so dark mode just works.
const CSS: &str = " const CSS: &str = "
.pf-host-card { padding: 16px; } .pf-host-card { padding: 16px; }
/* The FlowBoxChild draws the hover/selection highlight AROUND the card (it wraps it
with its own padding), so its corners must run concentric with the card's 12px —
radius = card radius + the child's padding ring. */
.pf-host-grid > flowboxchild { border-radius: 15px; }
.pf-pill { font-size: 0.72em; font-weight: bold; padding: 2px 10px; border-radius: 999px; .pf-pill { font-size: 0.72em; font-weight: bold; padding: 2px 10px; border-radius: 999px;
color: alpha(currentColor, 0.8); background: alpha(currentColor, 0.1); } color: alpha(currentColor, 0.8); background: alpha(currentColor, 0.1); }
.pf-pill.pf-green { color: @success_color; background: alpha(@success_color, 0.15); } .pf-pill.pf-green { color: @success_color; background: alpha(@success_color, 0.15); }
+5 -2
View File
@@ -386,7 +386,7 @@ impl SimpleComponent for HostsPage {
sender: ComponentSender<Self>, sender: ComponentSender<Self>,
) -> ComponentParts<Self> { ) -> ComponentParts<Self> {
let make_flow = || { let make_flow = || {
gtk::FlowBox::builder() let f = gtk::FlowBox::builder()
.selection_mode(gtk::SelectionMode::None) .selection_mode(gtk::SelectionMode::None)
.activate_on_single_click(true) .activate_on_single_click(true)
.homogeneous(true) .homogeneous(true)
@@ -394,7 +394,10 @@ impl SimpleComponent for HostsPage {
.max_children_per_line(4) .max_children_per_line(4)
.column_spacing(12) .column_spacing(12)
.row_spacing(12) .row_spacing(12)
.build() .build();
// Scopes the concentric hover-highlight radius (see app.rs CSS).
f.add_css_class("pf-host-grid");
f
}; };
let heading = |text: &str| { let heading = |text: &str| {
let l = gtk::Label::new(Some(text)); let l = gtk::Label::new(Some(text));
+12 -1
View File
@@ -50,12 +50,23 @@ For how long the virtual output lives, and extend-vs-exclusive topology, see
## Requirements ## Requirements
- A running Hyprland session (any recent release; validate on both a ≤ 0.54 and a ≥ 0.55 install). - A running Hyprland session (the `hyprctl`/xdph contracts are verified on **0.55.4**; older
releases share the same `hyprctl` surface).
- **xdg-desktop-portal-hyprland (xdph)** installed and running — the host captures through its - **xdg-desktop-portal-hyprland (xdph)** installed and running — the host captures through its
ScreenCast portal, and steers its custom picker. Without it there is no video. ScreenCast portal, and steers its custom picker. Without it there is no video.
- The ScreenCast interface routed to xdph — see `scripts/headless/portals.conf` (a `[Hyprland]` - The ScreenCast interface routed to xdph — see `scripts/headless/portals.conf` (a `[Hyprland]`
section pins `org.freedesktop.impl.portal.ScreenCast=hyprland`). section pins `org.freedesktop.impl.portal.ScreenCast=hyprland`).
## Troubleshooting: black / no video (headless output at 0×0)
A headless output only gets a framebuffer once the compositor can allocate one. On some GPU/driver
combinations (notably NVIDIA, and in nested test setups) that GBM/dmabuf allocation fails and the
output stays `0×0` — you'll see `GBM: Failed to allocate a GBM buffer: bo null` in the Hyprland log
(cf. [Sunshine #4197](https://github.com/LizardByte/Sunshine/issues/4197)). The host detects this
and fails the session with a clear error rather than streaming a blank surface. If you hit it,
capture the Hyprland log (`hyprctl` instance dir → `hyprland.log`) and check your GPU's GBM support;
running Hyprland as a real session (not nested) is the supported configuration.
## Permission system ## Permission system
Hyprland's permission system (`ecosystem.enforce_permissions`, 0.49+, **off by default**) can deny Hyprland's permission system (`ecosystem.enforce_permissions`, 0.49+, **off by default**) can deny