f4850625bd
apple / swift (push) Successful in 1m10s
android / android (push) Successful in 4m56s
arch / build-publish (push) Successful in 5m56s
audit / bun-audit (push) Successful in 13s
audit / cargo-audit (push) Successful in 1m34s
ci / web (push) Successful in 1m11s
windows-host / package (push) Successful in 7m57s
ci / docs-site (push) Successful in 1m27s
release / apple (push) Successful in 8m39s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 3m26s
ci / bench (push) Successful in 5m0s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 3m16s
apple / screenshots (push) Successful in 5m35s
ci / rust (push) Successful in 10m32s
decky / build-publish (push) Successful in 13s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 5s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 5s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 7s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 4m47s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 2m36s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 5s
deb / build-publish (push) Successful in 6m38s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 5m39s
flatpak / build-publish (push) Successful in 5m32s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 11m0s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 10m33s
docker / deploy-docs (push) Successful in 18s
UX polish batch 2 (plan workstreams D/E5/E6): - D: a mouse/keyboard game library page over pf-client-core::library (the GTK ui_library.rs counterpart): responsive 2-6 column poster grid (2:3 portraits, store badge, monogram placeholder while art streams in), loading / error+retry / empty / grid states, tap-to-play via a normal spawn carrying --launch id. Poster bytes land in a disk cache (%LOCALAPPDATA%\punktfunk\art-cache) so the Image widget loads file:/// URIs (reactor has no from-bytes source) and revisits render instantly. Reached from a paired host's "Browse library..." menu item behind the new "Show game library (experimental)" Settings toggle (the shared library_enabled field, Apple/GTK parity). A Shared::library_gen generation guard keeps a superseded fetch from publishing (speed-test pattern). - E5: the session window opens at the shell's own top-left (--window-pos, new SessionOpts::window_pos) instead of centered on the primary display - streams land on the monitor the shell is on, and the hide/restore handoff reads as one window changing content. Fullscreen follows that display. - E6: the Help shortcuts add Alt+Enter and the controller escape chord (LB+RB+Start+Back, hold to disconnect). Also: rustfmt normalization of the merged probe helper. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
66 lines
2.5 KiB
Rust
66 lines
2.5 KiB
Rust
//! Hide/restore the shell's top-level window around a spawned session, so exactly ONE
|
|
//! Punktfunk window is visible at a time: the spawned stream/browse window IS the app
|
|
//! while it runs (hidden = no taskbar entry, no Alt-Tab ghost), and the shell reappears
|
|
//! the moment the child exits — every exit path funnels through the spawn reader's
|
|
//! `Exited` event (clean end, error, crash, Disconnect kill), so the shell can never stay
|
|
//! hidden with no child.
|
|
//!
|
|
//! windows-reactor exposes no window handle, so the HWND is resolved by its (unique)
|
|
//! title and cached — the same pattern as `app::apply_window_icon_when_ready` and
|
|
//! `stream::window_dpi`.
|
|
|
|
use std::sync::atomic::{AtomicIsize, Ordering};
|
|
use windows::Win32::Foundation::{HWND, RECT};
|
|
use windows::Win32::UI::WindowsAndMessaging::{
|
|
FindWindowW, GetWindowRect, IsWindow, SetForegroundWindow, ShowWindow, SW_HIDE, SW_SHOW,
|
|
};
|
|
|
|
static SHELL_HWND: AtomicIsize = AtomicIsize::new(0);
|
|
|
|
fn shell_hwnd() -> Option<HWND> {
|
|
unsafe {
|
|
let cached = SHELL_HWND.load(Ordering::Relaxed);
|
|
if cached != 0 {
|
|
let h = HWND(cached as *mut _);
|
|
if IsWindow(Some(h)).as_bool() {
|
|
return Some(h);
|
|
}
|
|
}
|
|
let h = FindWindowW(None, windows::core::w!("Punktfunk")).ok()?;
|
|
SHELL_HWND.store(h.0 as isize, Ordering::Relaxed);
|
|
Some(h)
|
|
}
|
|
}
|
|
|
|
/// Hide the shell while a spawned session window is up. Called on the child's
|
|
/// `{"ready":true}` (its window has presented — never earlier, so a failed connect keeps
|
|
/// the shell in view with its error banner).
|
|
pub(crate) fn hide() {
|
|
if let Some(h) = shell_hwnd() {
|
|
unsafe {
|
|
let _ = ShowWindow(h, SW_HIDE);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Bring the shell back (and to the foreground) when the child exits. Safe to call when
|
|
/// it was never hidden — showing a visible window is a no-op.
|
|
pub(crate) fn restore() {
|
|
if let Some(h) = shell_hwnd() {
|
|
unsafe {
|
|
let _ = ShowWindow(h, SW_SHOW);
|
|
let _ = SetForegroundWindow(h);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// The shell window's top-left in desktop coordinates — passed to the spawned session
|
|
/// (`--window-pos`) so its window opens on the SAME monitor, roughly where the shell is,
|
|
/// and the visibility handoff reads as one window changing content.
|
|
pub(crate) fn position() -> Option<(i32, i32)> {
|
|
let h = shell_hwnd()?;
|
|
let mut r = RECT::default();
|
|
unsafe { GetWindowRect(h, &mut r).ok()? };
|
|
Some((r.left, r.top))
|
|
}
|