feat(clients/windows): WinUI UX batch - tile hover, Settings NavigationView, modal slide-up
audit / cargo-audit (push) Successful in 1m13s
apple / swift (push) Successful in 1m14s
release / apple (push) Successful in 8m2s
android / android (push) Successful in 10m42s
ci / web (push) Successful in 48s
ci / docs-site (push) Successful in 58s
ci / rust (push) Successful in 12m23s
apple / screenshots (push) Successful in 5m27s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 1m43s
windows-msix / package (x64, C:\Users\Public\ffmpeg, x86_64-pc-windows-msvc, C:\t) (push) Successful in 1m21s
ci / bench (push) Successful in 4m49s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 1m10s
deb / build-publish (push) Successful in 4m0s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 6s
decky / build-publish (push) Successful in 26s
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 4s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 5s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 4s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 1m20s
windows-host / package (push) Failing after 23s
flatpak / build-publish (push) Successful in 4m39s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 9m42s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 9m16s
docker / deploy-docs (push) Successful in 34s
audit / cargo-audit (push) Successful in 1m13s
apple / swift (push) Successful in 1m14s
release / apple (push) Successful in 8m2s
android / android (push) Successful in 10m42s
ci / web (push) Successful in 48s
ci / docs-site (push) Successful in 58s
ci / rust (push) Successful in 12m23s
apple / screenshots (push) Successful in 5m27s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 1m43s
windows-msix / package (x64, C:\Users\Public\ffmpeg, x86_64-pc-windows-msvc, C:\t) (push) Successful in 1m21s
ci / bench (push) Successful in 4m49s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 1m10s
deb / build-publish (push) Successful in 4m0s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 6s
decky / build-publish (push) Successful in 26s
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 4s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 5s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 4s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 1m20s
windows-host / package (push) Failing after 23s
flatpak / build-publish (push) Successful in 4m39s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 9m42s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 9m16s
docker / deploy-docs (push) Successful in 34s
Bump windows-reactor + windows to a4f7b2cb (from b4129fcc) for the new PointerEntered/PointerExited events; migration is mechanical renames only (SymbolGlyph->Symbol, placeholder->placeholder_text, on_changed-> on_text_changed/on_toggled, on_menu_item_clicked->on_item_clicked, on_ready->on_mounted). New runtime model: reactor lost its build.rs, so the client build.rs stages the WinAppSDK bootstrap via windows-reactor-setup::as_framework_dependent() and main calls windows_reactor::bootstrap() (missing either = 0x80040154 at launch); staged filenames unchanged, so pack-msix and the MSIX manifest are untouched. - Host tiles: WinUI pointer-over fill (ControlFillSecondary) via the new pointer enter/exit events, hover id in root state (backend-wired handlers bypass the reconciler flush, like the flyout clicks). - Settings: stock NavigationView sidebar (Windows-Settings pattern) with Display/Video/Input/Audio/About panes, built-in back arrow, wide content column, and a per-section content slide-up tween. The section card is KEYED by section: an in-place diff across sections re-sets a reused ComboBox's items (clearing WinUI's selection) but skips selected_index when the values compare equal, rendering a blank selection - the key forces a remount. Card titles/descriptions dropped; per-control guidance moved to hover tooltips (ToolTipService). - New "Show the stats overlay (HUD)" setting (show_hud, default on), honored mid-stream via the 400 ms HUD re-render. - Add-host modal: entrance fade + slide-up tween (scrim fades with it). - Self-initiated disconnect (Ctrl+Alt+Shift+D -> Ended(None)) returns to the host list silently instead of raising the error banner. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -41,8 +41,8 @@ impl PartialEq for StreamProps {
|
||||
}
|
||||
|
||||
thread_local! {
|
||||
/// Frames + host clock offset, stashed by the mount effect for `on_ready` (which fires later,
|
||||
/// once the native panel exists).
|
||||
/// Frames + host clock offset, stashed by the mount effect for `on_mounted` (which fires
|
||||
/// later, once the native panel exists).
|
||||
static PENDING: RefCell<Option<(crate::session::FrameRx, i64)>> = const { RefCell::new(None) };
|
||||
/// The live render thread; stopped + joined by the unmount cleanup (before panel teardown).
|
||||
static RENDER: RefCell<Option<RenderThread>> = const { RefCell::new(None) };
|
||||
@@ -65,7 +65,7 @@ fn window_dpi() -> u32 {
|
||||
pub(crate) fn stream_page(props: &StreamProps, cx: &mut RenderCx) -> Element {
|
||||
let ctx = &props.svc.ctx;
|
||||
// Take the connector + frames handoff once on mount; keep the connector alive (and for input)
|
||||
// in a use_ref, stash frames for `on_ready`, install the input hooks. The cleanup stops the
|
||||
// in a use_ref, stash frames for `on_mounted`, install the input hooks. The cleanup stops the
|
||||
// render thread FIRST (it must not present into a panel that's tearing down), then removes
|
||||
// the input hooks.
|
||||
let connector_ref = cx.use_ref::<Option<Arc<NativeClient>>>(None);
|
||||
@@ -95,46 +95,48 @@ pub(crate) fn stream_page(props: &StreamProps, cx: &mut RenderCx) -> Element {
|
||||
|
||||
let mode = connector_ref.borrow().as_ref().map(|c| c.mode());
|
||||
let host = ctx.shared.target.lock().unwrap().name.clone();
|
||||
grid((
|
||||
swap_chain_panel()
|
||||
.on_ready(|panel| {
|
||||
// Placeholder size — the first `on_resize` (fired after the first layout pass)
|
||||
// resizes to the panel's real pixel size.
|
||||
let dpi = window_dpi();
|
||||
match Presenter::new(1280, 720, dpi) {
|
||||
Ok(p) => {
|
||||
if let Err(e) = panel.set_swap_chain(p.swap_chain()) {
|
||||
tracing::error!(error = %e, "set_swap_chain");
|
||||
return;
|
||||
}
|
||||
if let Some((frames, clock_offset)) =
|
||||
PENDING.with(|c| c.borrow_mut().take())
|
||||
{
|
||||
let shared = render::RenderShared::new(1280, 720, dpi);
|
||||
RENDER.with(|cell| {
|
||||
*cell.borrow_mut() =
|
||||
Some(render::spawn(p, frames, shared, clock_offset));
|
||||
});
|
||||
tracing::info!(dpi, "stream presenter bound — render thread started");
|
||||
}
|
||||
// Read per render: this page re-renders on every HUD sample (~400 ms), so toggling the
|
||||
// overlay in Settings takes effect mid-stream.
|
||||
let show_hud = ctx.settings.lock().unwrap().show_hud;
|
||||
let mut layers: Vec<Element> = vec![swap_chain_panel()
|
||||
.on_mounted(|panel| {
|
||||
// Placeholder size — the first `on_resize` (fired after the first layout pass)
|
||||
// resizes to the panel's real pixel size.
|
||||
let dpi = window_dpi();
|
||||
match Presenter::new(1280, 720, dpi) {
|
||||
Ok(p) => {
|
||||
if let Err(e) = panel.set_swap_chain(p.swap_chain()) {
|
||||
tracing::error!(error = %e, "set_swap_chain");
|
||||
return;
|
||||
}
|
||||
if let Some((frames, clock_offset)) = PENDING.with(|c| c.borrow_mut().take()) {
|
||||
let shared = render::RenderShared::new(1280, 720, dpi);
|
||||
RENDER.with(|cell| {
|
||||
*cell.borrow_mut() =
|
||||
Some(render::spawn(p, frames, shared, clock_offset));
|
||||
});
|
||||
tracing::info!(dpi, "stream presenter bound — render thread started");
|
||||
}
|
||||
Err(e) => tracing::error!(error = %e, "create presenter"),
|
||||
}
|
||||
})
|
||||
.on_resize(|w, h| {
|
||||
// DIPs → physical pixels; the presenter maps back via SetMatrixTransform.
|
||||
let dpi = window_dpi();
|
||||
let px = |v: f64| (v * f64::from(dpi) / 96.0).round() as u32;
|
||||
RENDER.with(|cell| {
|
||||
if let Some(rt) = cell.borrow().as_ref() {
|
||||
rt.shared().set_dpi(dpi);
|
||||
rt.shared().set_size(px(w), px(h));
|
||||
}
|
||||
});
|
||||
}),
|
||||
hud_overlay(&props.hud, mode, &host),
|
||||
))
|
||||
.into()
|
||||
Err(e) => tracing::error!(error = %e, "create presenter"),
|
||||
}
|
||||
})
|
||||
.on_resize(|w, h| {
|
||||
// DIPs → physical pixels; the presenter maps back via SetMatrixTransform.
|
||||
let dpi = window_dpi();
|
||||
let px = |v: f64| (v * f64::from(dpi) / 96.0).round() as u32;
|
||||
RENDER.with(|cell| {
|
||||
if let Some(rt) = cell.borrow().as_ref() {
|
||||
rt.shared().set_dpi(dpi);
|
||||
rt.shared().set_size(px(w), px(h));
|
||||
}
|
||||
});
|
||||
})
|
||||
.into()];
|
||||
if show_hud {
|
||||
layers.push(hud_overlay(&props.hud, mode, &host));
|
||||
}
|
||||
grid(layers).into()
|
||||
}
|
||||
|
||||
/// A small chip for the dark HUD: coloured text on a translucent dark fill.
|
||||
|
||||
Reference in New Issue
Block a user