From dfe386752914481a3e25259b6fb496ed67059a05 Mon Sep 17 00:00:00 2001 From: server2 Date: Thu, 15 Oct 2026 01:14:55 +0200 Subject: [PATCH] Peeks start where the part is: no dip when the bar hides Switching from a workspace with the bar shown to a fullscreen one slid the bar away while the workspace peek slid in from hidden, so the pill dipped and came back. A peek now starts from the part's current position, so a shown pill stays still for the peek and then leaves. The tray, which peeks don't show, slides away on its own. Tested on DP-2 (2 -> 3 and back), frame by frame. --- AGENTS.md | 2 +- src/edge.rs | 9 ++++++++- src/workspaces.rs | 13 +++++++------ 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 7b06ab2..00e4f33 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -30,7 +30,7 @@ Handoff for agents continuing work on the Magic Island shell (Hermes, Claude Cod - **Control centre** (top right): a status pill (Wi-Fi or hotspot, VPN, Bluetooth, Ethernet, battery; icons of stopped services hidden) that opens a panel: tiles for Wi-Fi, Bluetooth, VPN, Hotspot, Ethernet; volume with the output, brightness, keyboard light, performance mode, external-GPU programs. The panel morphs into its menus as one shape: Wi-Fi and Bluetooth maps (devices floating round this computer, click to join/pair, right-click a saved network for its password, click the centre to search again), VPN list, sound outputs, Ethernet details with copyable addresses. The maps reach from the right edge to the island's pill, less 16 px. Popups (`magic-prompt`) ask for passwords, PINs and passkeys and say why something failed. - **System tray** right of the workspace pill. -- **Bar hiding:** only on monitors showing a fullscreen window; the pointer resting on the top edge brings it back. Events bring one part in for a moment (a peek): the workspace pill alone on a workspace change, the island on a song change or a new player. +- **Bar hiding:** only on monitors showing a fullscreen window; the pointer resting on the top edge brings it back. Events bring one part in for a moment (a peek): the workspace pill alone on a workspace change, the island on a song change or a new player. A peek starts from where the part is, so switching from a shown bar to a fullscreen workspace keeps the workspace pill still (no dip) while the tray leaves on its own. - **Reserved space:** windows that aren't fullscreen stay below the bar (44 px at the top of every monitor). On 2026-10-13 the user was asked to try the mouse-only parts (tray clicks, top-edge hover reveal, Copy buttons, PIN pairing) and answered "All works"; the agent itself only drove them over IPC. diff --git a/src/edge.rs b/src/edge.rs index 0bd0272..6bea89a 100644 --- a/src/edge.rs +++ b/src/edge.rs @@ -238,7 +238,14 @@ fn peek(edge: &mut Edge, part: Part, monitor: &str) { let key = (part, monitor.to_string()); let began = Instant::now(); - let entry = edge.peeks.entry(key.clone()).or_insert_with(|| (sliding(0.0), began)); + // from wherever the part is now: one already showing (the bar on its way out after a switch to a fullscreen workspace) stays put instead of dipping + let now = edge.part(part, monitor); + + let entry = edge.peeks.entry(key.clone()).or_insert_with(|| (sliding(now), began)); + + if entry.0.value() < now { + entry.0 = sliding(now); + } entry.0.to(1.0); entry.1 = began; diff --git a/src/workspaces.rs b/src/workspaces.rs index d5171ac..01da9f3 100644 --- a/src/workspaces.rs +++ b/src/workspaces.rs @@ -46,11 +46,12 @@ pub fn view(monitor: &Monitor) -> LayerWindow { let workspaces = Workspaces::read(); let hover = Hover::read(); - // hidden on a fullscreen monitor until wanted, or for a moment on a workspace change (edge.rs) - let (slide, switched, peeking) = { + // hidden on a fullscreen monitor until wanted, or for a moment on a workspace change (edge.rs); the tray only goes with the whole bar + let (slide, tray_slide, switched, peeking) = { let edge = Edge::read(); + let shown = edge.shown(&monitor.name); - (edge::hidden_by(edge.part(Part::Workspaces, &monitor.name), 0.0, HIDE_H), edge.switched(&monitor.name), edge.shown(&monitor.name) == 0.0) + (edge::hidden_by(edge.part(Part::Workspaces, &monitor.name), 0.0, HIDE_H), edge::hidden_by(shown, 0.0, HIDE_H), edge.switched(&monitor.name), shown == 0.0) }; // special workspaces (scratchpads) aren't places to switch to @@ -180,11 +181,12 @@ pub fn view(monitor: &Monitor) -> LayerWindow { // clicks next to the pills reach the windows underneath let mut regions = vec![InputArea { x: LEFT as i32, y: TOP_GAP as i32, width: width.ceil() as i32, height: COMPACT_H as i32 }]; - let mut pills: Vec> = vec![Box::new(pill)]; + let mut pills: Vec> = vec![Box::new(pill.translate(0.0, slide))]; + // a peek keeps the workspaces in while the bar leaves: the tray slides away on its own if let Some((tray, tray_pill_w)) = tray { regions.push(InputArea { x: (LEFT + width + TRAY_GAP) as i32, y: TOP_GAP as i32, width: tray_pill_w.ceil() as i32, height: COMPACT_H as i32 }); - pills.push(Box::new(tray)); + pills.push(Box::new(tray.translate(0.0, tray_slide))); } window.input_region(regions).child( @@ -193,7 +195,6 @@ pub fn view(monitor: &Monitor) -> LayerWindow { .height(Parent) .padding(Padding { top: TOP_GAP, right: 0.0, bottom: 0.0, left: LEFT }) .align_child(Start, Start) - .translate(0.0, slide) .child(Row::new(pills).gap(TRAY_GAP).align(Start)), ) }