style: cargo fmt --all (rustfmt 1.96.0 drift across the re-arch branch)

`cargo fmt --all --check` (ci.yml) was red on main: the client re-architecture
commits and origin's windows-shortcut commit landed with rustfmt violations
(e.g. a 104-char .with_context line in hyprland.rs, an unsorted mod block in
vdisplay.rs, the input.rs `{`-placement CI flagged). Reformat the tree so the
fmt gate passes; no functional changes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-07 23:33:40 +02:00
parent 966758e757
commit 062a54e3a5
17 changed files with 382 additions and 224 deletions
+29 -6
View File
@@ -172,10 +172,22 @@ fn mat_mul(a: &[f64; 16], b: &[f64; 16]) -> [f64; 16] {
/// `meshColors`: dark-violet corners sink the frame, the edges carry mid-tone violets, and
/// the four interior points hold the bright brand family (warm pools left, cool right).
pub const MESH_COLORS: [(f64, f64, f64); 16] = [
(0.075, 0.060, 0.160), (0.34, 0.27, 0.72), (0.30, 0.26, 0.74), (0.075, 0.060, 0.160),
(0.42, 0.20, 0.54), (0.49, 0.39, 0.95), (0.28, 0.31, 0.84), (0.16, 0.26, 0.64),
(0.45, 0.23, 0.60), (0.53, 0.31, 0.75), (0.35, 0.35, 0.91), (0.19, 0.28, 0.70),
(0.075, 0.060, 0.160), (0.22, 0.18, 0.54), (0.24, 0.20, 0.58), (0.075, 0.060, 0.160),
(0.075, 0.060, 0.160),
(0.34, 0.27, 0.72),
(0.30, 0.26, 0.74),
(0.075, 0.060, 0.160),
(0.42, 0.20, 0.54),
(0.49, 0.39, 0.95),
(0.28, 0.31, 0.84),
(0.16, 0.26, 0.64),
(0.45, 0.23, 0.60),
(0.53, 0.31, 0.75),
(0.35, 0.35, 0.91),
(0.19, 0.28, 0.70),
(0.075, 0.060, 0.160),
(0.22, 0.18, 0.54),
(0.24, 0.20, 0.58),
(0.075, 0.060, 0.160),
];
/// The four interior control points that wander; the 12 boundary points stay pinned to the
@@ -414,7 +426,10 @@ mod tests {
}
assert!((pos - 3.0).abs() < 0.01, "{pos}");
let (p, v) = spring_advance(0.0, 0.0, 1.0, BUMP_K, BUMP_C, 0.05);
assert!(p.is_finite() && v.is_finite() && p > 0.0 && p < 2.0, "{p}/{v}");
assert!(
p.is_finite() && v.is_finite() && p > 0.0 && p < 2.0,
"{p}/{v}"
);
}
/// The focused card (angle 0, scale 1) maps its center to (cx, cy) exactly.
@@ -435,7 +450,15 @@ mod tests {
#[test]
fn side_card_inner_edge_recedes() {
let flat = card_matrix(900.0, 400.0, 0.0, 1.0, POSTER_W, POSTER_H, PERSPECTIVE);
let tilted = card_matrix(900.0, 400.0, -ROTATE_DEG, 1.0, POSTER_W, POSTER_H, PERSPECTIVE);
let tilted = card_matrix(
900.0,
400.0,
-ROTATE_DEG,
1.0,
POSTER_W,
POSTER_H,
PERSPECTIVE,
);
let project = |m: &[f32; 16], x: f32, y: f32| {
let px = m[0] * x + m[1] * y + m[3];
let pw = m[12] * x + m[13] * y + m[15];
+103 -31
View File
@@ -5,15 +5,17 @@
//! restack hack is gone), and every state renders in-scene (gamescope maps no dialogs).
use crate::library::{
card_matrix, initials, mesh_sksl, spring_advance, step_cursor, store_label,
LibraryGame, LibraryPhase, LibraryShared, StepResult, BUMP_C, BUMP_K, BUMP_PX, FOCUS_GAP,
JUMP, PERSPECTIVE, POSTER_H, POSTER_W, RECEDE_DIM, RECEDE_SCALE, ROTATE_DEG, SIDE_SPACING,
SPRING_C, SPRING_K, VISIBLE_RANGE,
card_matrix, initials, mesh_sksl, spring_advance, step_cursor, store_label, LibraryGame,
LibraryPhase, LibraryShared, StepResult, BUMP_C, BUMP_K, BUMP_PX, FOCUS_GAP, JUMP, PERSPECTIVE,
POSTER_H, POSTER_W, RECEDE_DIM, RECEDE_SCALE, ROTATE_DEG, SIDE_SPACING, SPRING_C, SPRING_K,
VISIBLE_RANGE,
};
use anyhow::{anyhow, Result};
use pf_client_core::gamepad::{MenuDir, MenuEvent, MenuPulse};
use pf_presenter::overlay::OverlayAction;
use skia_safe::textlayout::{FontCollection, ParagraphBuilder, ParagraphStyle, TextAlign, TextStyle};
use skia_safe::textlayout::{
FontCollection, ParagraphBuilder, ParagraphStyle, TextAlign, TextStyle,
};
use skia_safe::{
Canvas, Color4f, Data, Font, FontStyle, Image, Paint, Point, RRect, Rect, RuntimeEffect,
Typeface, M44,
@@ -80,11 +82,7 @@ impl LibraryUi {
if self.shared.generation() != self.generation {
let (phase, games, generation) = self.shared.snapshot();
let fresh_games = self.games.len() != games.len()
|| self
.games
.iter()
.zip(&games)
.any(|(a, b)| a.id != b.id);
|| self.games.iter().zip(&games).any(|(a, b)| a.id != b.id);
self.phase = phase;
self.games = games;
self.generation = generation;
@@ -233,14 +231,8 @@ impl LibraryUi {
.map_or(1.0 / 60.0, |t| (now - t).as_secs_f64().clamp(0.0, 0.05));
if self.phase == LibraryPhase::Ready {
let target = f64::from(self.cursor);
(self.anim_pos, self.anim_vel) = spring_advance(
self.anim_pos,
self.anim_vel,
target,
SPRING_K,
SPRING_C,
dt,
);
(self.anim_pos, self.anim_vel) =
spring_advance(self.anim_pos, self.anim_vel, target, SPRING_K, SPRING_C, dt);
if (target - self.anim_pos).abs() < 0.001 && self.anim_vel.abs() < 0.01 {
self.anim_pos = target;
self.anim_vel = 0.0;
@@ -259,19 +251,75 @@ impl LibraryUi {
LibraryPhase::Ready => self.draw_carousel(canvas, wf, hf, k, fonts),
LibraryPhase::Loading => {
self.draw_spinner(canvas, wf / 2.0, hf / 2.0 - 24.0 * k, 16.0 * k);
fonts.centered(canvas, "Loading library…", 14.0 * k, DIM_TEXT, wf / 2.0, hf / 2.0 + 16.0 * k, wf * 0.8);
fonts.centered(
canvas,
"Loading library…",
14.0 * k,
DIM_TEXT,
wf / 2.0,
hf / 2.0 + 16.0 * k,
wf * 0.8,
);
}
LibraryPhase::PairFirst => {
fonts.centered_bold(canvas, "Not paired with this host", 22.0 * k, WHITE, wf / 2.0, hf / 2.0 - 20.0 * k, wf * 0.8);
fonts.centered(canvas, "Pair from the Punktfunk plugin first.", 14.0 * k, DIM_TEXT, wf / 2.0, hf / 2.0 + 12.0 * k, wf * 0.8);
fonts.centered_bold(
canvas,
"Not paired with this host",
22.0 * k,
WHITE,
wf / 2.0,
hf / 2.0 - 20.0 * k,
wf * 0.8,
);
fonts.centered(
canvas,
"Pair from the Punktfunk plugin first.",
14.0 * k,
DIM_TEXT,
wf / 2.0,
hf / 2.0 + 12.0 * k,
wf * 0.8,
);
}
LibraryPhase::Empty => {
fonts.centered_bold(canvas, "No games found", 22.0 * k, WHITE, wf / 2.0, hf / 2.0 - 20.0 * k, wf * 0.8);
fonts.centered(canvas, "Install Steam titles or add custom entries in the host's web console.", 14.0 * k, DIM_TEXT, wf / 2.0, hf / 2.0 + 12.0 * k, wf * 0.8);
fonts.centered_bold(
canvas,
"No games found",
22.0 * k,
WHITE,
wf / 2.0,
hf / 2.0 - 20.0 * k,
wf * 0.8,
);
fonts.centered(
canvas,
"Install Steam titles or add custom entries in the host's web console.",
14.0 * k,
DIM_TEXT,
wf / 2.0,
hf / 2.0 + 12.0 * k,
wf * 0.8,
);
}
LibraryPhase::Error { title, body, .. } => {
fonts.centered_bold(canvas, &title, 22.0 * k, WHITE, wf / 2.0, hf / 2.0 - 32.0 * k, wf * 0.8);
fonts.centered(canvas, &body, 14.0 * k, DIM_TEXT, wf / 2.0, hf / 2.0 + 4.0 * k, (600.0 * k).min(wf * 0.85));
fonts.centered_bold(
canvas,
&title,
22.0 * k,
WHITE,
wf / 2.0,
hf / 2.0 - 32.0 * k,
wf * 0.8,
);
fonts.centered(
canvas,
&body,
14.0 * k,
DIM_TEXT,
wf / 2.0,
hf / 2.0 + 4.0 * k,
(600.0 * k).min(wf * 0.85),
);
}
}
@@ -346,17 +394,28 @@ impl LibraryUi {
let sh = iw / card_aspect;
Rect::from_xywh(0.0, (ih - sh) / 2.0, iw, sh)
};
canvas.draw_image_rect(img, Some((&src, skia_safe::canvas::SrcRectConstraint::Fast)), rect, &Paint::default());
canvas.draw_image_rect(
img,
Some((&src, skia_safe::canvas::SrcRectConstraint::Fast)),
rect,
&Paint::default(),
);
}
None => {
// Solid face, not glass: the side cards OVERLAP (GTK CSS note).
canvas.draw_rect(rect, &Paint::new(Color4f::new(0.118, 0.118, 0.145, 1.0), None));
canvas.draw_rect(
rect,
&Paint::new(Color4f::new(0.118, 0.118, 0.145, 1.0), None),
);
let mono = initials(&game.title);
let font = fonts.sans_bold(38.0 * k);
let tw = font.measure_str(&mono, None).0;
canvas.draw_str(
&mono,
Point::new((card_w as f32 - tw) / 2.0, card_h as f32 / 2.0 + 13.0 * k as f32),
Point::new(
(card_w as f32 - tw) / 2.0,
card_h as f32 / 2.0 + 13.0 * k as f32,
),
&font,
&Paint::new(Color4f::new(1.0, 1.0, 1.0, 0.45), None),
);
@@ -384,7 +443,10 @@ impl LibraryUi {
if prox > 0.0 {
canvas.draw_rect(
rect,
&Paint::new(Color4f::new(0.0, 0.0, 0.0, (prox * RECEDE_DIM) as f32), None),
&Paint::new(
Color4f::new(0.0, 0.0, 0.0, (prox * RECEDE_DIM) as f32),
None,
),
);
}
canvas.restore();
@@ -392,7 +454,15 @@ impl LibraryUi {
// Detail block: focused title + store, centered between strip and hints.
if let Some(g) = self.games.get(self.cursor as usize) {
fonts.centered_bold(canvas, &g.title, 27.0 * k, WHITE, w / 2.0, h - 96.0 * k, w * 0.8);
fonts.centered_bold(
canvas,
&g.title,
27.0 * k,
WHITE,
w / 2.0,
h - 96.0 * k,
w * 0.8,
);
fonts.centered(
canvas,
&store_label(&g.store).to_uppercase(),
@@ -451,7 +521,9 @@ impl LibraryUi {
} else {
match &self.phase {
LibraryPhase::Ready => "A Play B Quit L1 / R1 Jump".to_string(),
LibraryPhase::Error { can_retry: true, .. } => "A Retry B Quit".to_string(),
LibraryPhase::Error {
can_retry: true, ..
} => "A Retry B Quit".to_string(),
_ => "B Quit".to_string(),
}
};
+27 -38
View File
@@ -120,11 +120,13 @@ impl Overlay for SkiaOverlay {
skvk::GetProcOf::Instance(raw_instance, name) => entry
.get_instance_proc_addr(avk::Instance::from_raw(raw_instance as _), name)
.map_or(std::ptr::null(), |f| f as *const std::ffi::c_void),
skvk::GetProcOf::Device(raw_device, name) => (instance.fp_v1_0()
.get_device_proc_addr)(
avk::Device::from_raw(raw_device as _), name
)
.map_or(std::ptr::null(), |f| f as *const std::ffi::c_void),
skvk::GetProcOf::Device(raw_device, name) => {
(instance.fp_v1_0().get_device_proc_addr)(
avk::Device::from_raw(raw_device as _),
name,
)
.map_or(std::ptr::null(), |f| f as *const std::ffi::c_void)
}
}
}
};
@@ -173,12 +175,8 @@ impl Overlay for SkiaOverlay {
} = event
{
use sdl3::keyboard::Mod;
if !keymod.intersects(Mod::LCTRLMOD | Mod::RCTRLMOD | Mod::LALTMOD | Mod::RALTMOD)
{
return self
.library
.as_mut()
.is_some_and(|l| l.key(*sc, *repeat));
if !keymod.intersects(Mod::LCTRLMOD | Mod::RCTRLMOD | Mod::LALTMOD | Mod::RALTMOD) {
return self.library.as_mut().is_some_and(|l| l.key(*sc, *repeat));
}
}
}
@@ -231,10 +229,10 @@ impl Overlay for SkiaOverlay {
let slot = slots[next].as_mut().expect("just ensured");
let lib = library.as_mut().expect("library_visible");
let fonts = fonts.as_mut().expect("init ran");
fonts.chip_text = Some(
ctx.pad
.map_or("No controller — keyboard works too".to_string(), str::to_owned),
);
fonts.chip_text = Some(ctx.pad.map_or(
"No controller — keyboard works too".to_string(),
str::to_owned,
));
lib.sync();
lib.render(slot.surface.canvas(), ctx.width, ctx.height, fonts);
gpu.context.flush_surface_with_texture_state(
@@ -269,15 +267,12 @@ impl Overlay for SkiaOverlay {
};
if want == self.drawn {
// Unchanged — hand the presenter the already-rendered image.
return Ok(self
.slots[self.current]
.as_ref()
.map(|s| OverlayFrame {
image: s.image,
view: s.view,
width: s.width,
height: s.height,
}));
return Ok(self.slots[self.current].as_ref().map(|s| OverlayFrame {
image: s.image,
view: s.view,
width: s.width,
height: s.height,
}));
}
// Render into the OTHER slot — the presenter may still be sampling the current
@@ -335,10 +330,8 @@ impl SkiaOverlay {
// alternates and the presenter waits its fence before each record).
unsafe { gpu.device.destroy_image_view(old.view, None) };
}
let info = skia_safe::ImageInfo::new_n32_premul(
(width.max(1) as i32, height.max(1) as i32),
None,
);
let info =
skia_safe::ImageInfo::new_n32_premul((width.max(1) as i32, height.max(1) as i32), None);
let mut surface = gpu::surfaces::render_target(
&mut gpu.context,
gpu::Budgeted::Yes,
@@ -350,12 +343,11 @@ impl SkiaOverlay {
None,
)
.context("Skia render-target surface")?;
let texture =
gpu::surfaces::get_backend_texture(
&mut surface,
skia_safe::surface::BackendHandleAccess::FlushRead,
)
.context("surface backend texture")?;
let texture = gpu::surfaces::get_backend_texture(
&mut surface,
skia_safe::surface::BackendHandleAccess::FlushRead,
)
.context("surface backend texture")?;
let image_info = texture
.vulkan_image_info()
.context("backend texture is not Vulkan")?;
@@ -412,10 +404,7 @@ fn draw_osd_panel(canvas: &Canvas, font: &Font, text: &str, x: f32, y: f32) {
for (i, line) in lines.iter().enumerate() {
canvas.draw_str(
line,
Point::new(
x + pad_x,
y + pad_y - metrics.ascent + line_h * i as f32,
),
Point::new(x + pad_x, y + pad_y - metrics.ascent + line_h * i as f32),
font,
&text_paint,
);