tawasuyu/llimphi
Sovereign retained-mode GPU UI framework in Rust (wgpu+vello+taffy+parley), Elm loop, 40+ widgets.
chore: refresco desde el monorepo (pin tawasuyu.git v0.3.0)
1//! `diag_iconos` — ¿qué ícono le toca a cada `app_id`?
2//!
3//! El instrumento del índice `app_id → Icon= → archivo`. Se le pasan los
4//! `app_id` de Wayland por argumento (los de las ventanas abiertas salen de
5//! `mirada-ctl windows`) y por cada uno imprime la vía por la que resolvió y el
6//! archivo que se va a pintar — o `LETRA`, que es lo que hoy ve el usuario.
7//!
8//! Sin argumentos barre todos los `.desktop` del sistema y da el conteo: cuántas
9//! entradas declaran `StartupWMClass` (las que el `app_id` a pelo NO alcanzaba).
10
11fn main() {
12 let ids: Vec<String> = std::env::args().skip(1).collect();
13 if ids.is_empty() {
14 eprintln!("uso: diag_iconos <app_id> [app_id...]");
15 return;
16 }
17 // Lo que cuesta armar el índice: se arma UNA vez, pero se arma dentro de un
18 // cuadro de UI (el primer ícono que alguien pide), así que el número
19 // importa — un barrido caro ahí es un tirón visible.
20 // `precargar_indice` es la vía SÍNCRONA (la que mide el barrido de verdad);
21 // el camino normal de una app lo arma en un hilo y no bloquea el cuadro.
22 let t0 = std::time::Instant::now();
23 llimphi_widget_app_icon::precargar_indice();
24 let armado = t0.elapsed();
25 let t1 = std::time::Instant::now();
26 let _ = llimphi_widget_app_icon::icon_name_for_app_id("segunda-llamada-ya-cacheada");
27 let cacheado = t1.elapsed();
28 println!("indice: armado {armado:?} · lookup posterior {cacheado:?}\n");
29
30 let (mut por_indice, mut por_directo, mut letra) = (0, 0, 0);
31 // El camino VIEJO, para contrastar: el `app_id` probado como nombre de
32 // ícono a pelo, que es lo único que tenía el dock (y la taskbar ni eso).
33 let mut antes = 0;
34 for id in &ids {
35 let via_indice = llimphi_widget_app_icon::icon_name_for_app_id(id);
36 let nombre = via_indice.clone().unwrap_or_else(|| id.clone());
37 // Un `Icon=` puede ser un **path absoluto** (`/opt/pycharm/bin/x.svg`),
38 // que no se busca en ningún tema. `get_or_load` ya lo contempla; si el
39 // diag no, reporta LETRA sobre un ícono que en realidad se pinta.
40 let ruta = if nombre.starts_with('/') {
41 let p = std::path::PathBuf::from(&nombre);
42 p.is_file().then_some(p)
43 } else {
44 llimphi_widget_app_icon::resolve_icon_path(&nombre)
45 };
46 let via = match (&via_indice, &ruta) {
47 (_, None) => {
48 letra += 1;
49 "LETRA".to_string()
50 }
51 (Some(_), Some(_)) => {
52 por_indice += 1;
53 "indice".to_string()
54 }
55 (None, Some(_)) => {
56 por_directo += 1;
57 "directo".to_string()
58 }
59 };
60 let resolvia_antes = llimphi_widget_app_icon::resolve_icon_path(id).is_some();
61 if resolvia_antes {
62 antes += 1;
63 }
64 println!(
65 "{:<30} {:<7} {:<8} {:<28} {}",
66 id,
67 if resolvia_antes { "antes✓" } else { "antes·" },
68 via,
69 via_indice.as_deref().unwrap_or("—"),
70 ruta.map(|p| p.display().to_string()).unwrap_or_else(|| "—".into())
71 );
72 }
73 println!(
74 "\n{} ids · ANTES resolvia {} · AHORA indice={} directo={} LETRA={}",
75 ids.len(),
76 antes,
77 por_indice,
78 por_directo,
79 letra
80 );
81}