From 66bf25f7ddb0854120628b6aa41f5b57f6009594 Mon Sep 17 00:00:00 2001 From: server2 Date: Thu, 8 Oct 2026 11:38:16 +0200 Subject: [PATCH] fix workspace clicks and the island stuck after a hidden start - workspace pill: clicks did nothing. amane's Workspaces::focus sends 'dispatch workspace N', which hyprland 0.56 with a lua config turns into hl.dispatch(workspace N) and rejects. dispatch the lua form the user's keybinds use, hl.dsp.focus({ workspace = N }), through hyprctl on its own thread (named workspaces with negative ids are left out) - island: 'magic-island has no child to draw' at startup without a player, and the island then never appeared. hyprland 0.56 configures a layer surface before its first commit (seen with WAYLAND_DEBUG), so a window that starts visible(false) gets a size, amane runs the empty view, logs, and waits for frame callbacks an undrawn surface never gets. with no player the island is now an empty click-through window instead - verified on the desktop: 0 'no child' lines, island draws at startup and shows on all 4 monitors when a player starts --- src/island.rs | 9 ++++++++- src/workspaces.rs | 24 ++++++++++++++++++++++-- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/island.rs b/src/island.rs index 43a8576..0e7972f 100644 --- a/src/island.rs +++ b/src/island.rs @@ -267,8 +267,15 @@ pub fn view(monitor: &Monitor) -> LayerWindow { .space(Zone::Ignore) .namespace("magic-island"); + /* + * no player: an empty window that lets every click through, never visible(false). + * hyprland 0.56 configures a layer surface before its first commit, so a window + * that starts hidden gets a size anyway: amane then logs "no child to draw" and, + * with nothing ever drawn, waits for frame callbacks that never come, and the + * island never showed up once a player started + */ let Some(player) = shown(&media, island.selected.as_deref()) else { - return window.visible(false); + return window.click_through().child(Rectangle::new().width(0.0).height(0.0)); }; let (grow, pill, reveal) = phases(if opened_here { island.open.value() } else { 0.0 }); diff --git a/src/workspaces.rs b/src/workspaces.rs index 157516e..913a8f8 100644 --- a/src/workspaces.rs +++ b/src/workspaces.rs @@ -1,4 +1,6 @@ use std::collections::HashMap; +use std::process::Command; +use std::thread; use std::time::Duration; use amane::{ @@ -59,8 +61,9 @@ pub fn view(monitor: &Monitor) -> LayerWindow { .space(Zone::Ignore) .namespace("magic-workspaces"); + // empty and click-through rather than hidden: see the island's view for why if here.is_empty() { - return window.visible(false); + return window.click_through().child(Rectangle::new().width(0.0).height(0.0)); } let mut slots: Vec> = Vec::new(); @@ -95,7 +98,7 @@ pub fn view(monitor: &Monitor) -> LayerWindow { .scale(1.0 + 0.08 * lit) .cursor(Pointer) .on_hover(move |inside| hovering(id, inside)) - .on_click(move |_| Workspaces::focus(id)) + .on_click(move |_| focus(id)) .child(Text::new(label).size(12.0).weight(weight).color(color)), )); } @@ -131,6 +134,23 @@ pub fn view(monitor: &Monitor) -> LayerWindow { ) } +/* + * switches to a workspace. amane's Workspaces::focus sends `dispatch workspace N`, + * which hyprland 0.56 with a lua config turns into hl.dispatch(workspace N) and + * rejects; this is the lua form the user's own keybinds use. on its own thread, + * so hyprctl never holds up drawing. named workspaces (negative ids) aren't + * switched: their lua form is unverified + */ +fn focus(id: i64) { + if id < 0 { + return; + } + + thread::spawn(move || { + let _ = Command::new("hyprctl").arg("dispatch").arg(format!("hl.dsp.focus({{ workspace = {id} }})")).output(); + }); +} + /* * one workspace lit at a time: amane matches hover targets by their place in the frame, * so a workspace that closes under the pointer never hears it leave