From 41c6f43a3cf4725c83a542102814a43a2b7840a8 Mon Sep 17 00:00:00 2001 From: Aleksander Date: Sat, 21 Feb 2026 20:03:50 +0100 Subject: [PATCH 1/9] dash-frontend: Monado runtime: Tabs, add stub DebugTimings tab --- dash-frontend/assets/dashboard/not_a_bug.svg | 3 + dash-frontend/assets/gui/t_group_box.xml | 4 +- dash-frontend/assets/gui/tab/monado.xml | 41 +-- .../gui/tab/monado_tab_debug_timings.xml | 9 + .../gui/tab/monado_tab_general_settings.xml | 12 + .../gui/tab/monado_tab_process_list.xml | 35 +++ dash-frontend/assets/gui/tab/settings.xml | 4 +- dash-frontend/assets/lang/de.json | 3 +- dash-frontend/assets/lang/en.json | 1 + dash-frontend/assets/lang/es.json | 3 +- dash-frontend/assets/lang/it.json | 3 +- dash-frontend/assets/lang/ja.json | 3 +- dash-frontend/assets/lang/pl.json | 3 +- dash-frontend/assets/lang/zh_CN.json | 3 +- dash-frontend/src/frontend.rs | 2 +- dash-frontend/src/tab/monado.rs | 270 ++++++++++++++---- 16 files changed, 304 insertions(+), 95 deletions(-) create mode 100644 dash-frontend/assets/dashboard/not_a_bug.svg create mode 100644 dash-frontend/assets/gui/tab/monado_tab_debug_timings.xml create mode 100644 dash-frontend/assets/gui/tab/monado_tab_general_settings.xml create mode 100644 dash-frontend/assets/gui/tab/monado_tab_process_list.xml diff --git a/dash-frontend/assets/dashboard/not_a_bug.svg b/dash-frontend/assets/dashboard/not_a_bug.svg new file mode 100644 index 00000000..a7fdd8e6 --- /dev/null +++ b/dash-frontend/assets/dashboard/not_a_bug.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dash-frontend/assets/gui/t_group_box.xml b/dash-frontend/assets/gui/t_group_box.xml index 799bb124..8292d2c6 100644 --- a/dash-frontend/assets/gui/t_group_box.xml +++ b/dash-frontend/assets/gui/t_group_box.xml @@ -11,10 +11,10 @@ gap="8" round="8" /> - + + + + - + + +
+
+
\ No newline at end of file diff --git a/dash-frontend/src/tab/monado.rs b/dash-frontend/src/tab/monado.rs index 4235464f..5215e784 100644 --- a/dash-frontend/src/tab/monado.rs +++ b/dash-frontend/src/tab/monado.rs @@ -4,6 +4,7 @@ use wgui::{ assets::AssetPath, components::{ bar_graph::{ComponentBarGraph, ValueCell}, + button::ComponentButton, checkbox::ComponentCheckbox, slider::ComponentSlider, tabs::ComponentTabs, @@ -46,6 +47,10 @@ enum Task { // `ProcessList` tab ProcessListRefresh, ProcessListFocusClient(String), + + // `DebugTimings` tab + DebugTimingsRefreshSessionList, + DebugTimingsSetSessionId(i64), } struct SubtabProcessList { @@ -65,7 +70,14 @@ struct DebugGraph { data: ParserData, } +struct DebugSessionList { + buttons: Vec>, + #[allow(dead_code)] + data_vec: Vec, +} + struct TimingsSession { + resolved_name: Option, last_frame: MonadoDumpSessionFrame, } @@ -83,13 +95,20 @@ struct Graphs { when_gpu_done: DebugGraph, } +type SessionsMap = HashMap; + struct SubtabDebugTimings { #[allow(dead_code)] state: ParserState, - graphs: Graphs, + graphs: Option, + session_list: DebugSessionList, + selected_session_id: Option, - sessions: HashMap, + id_sessions_list_parent: WidgetID, + id_timings_parent: WidgetID, + + sessions: SessionsMap, } #[allow(dead_code)] @@ -131,6 +150,16 @@ impl Tab for TabMonado { process_list.focus_client(frontend, data, client_name, &self.tasks)?; } } + Task::DebugTimingsRefreshSessionList => { + if let Subtab::DebugTimings(tab) = &mut self.subtab { + tab.refresh_session_list(&mut frontend.layout, &self.tasks)?; + } + } + Task::DebugTimingsSetSessionId(session_id) => { + if let Subtab::DebugTimings(tab) = &mut self.subtab { + tab.set_session_id(&mut frontend.layout, session_id)?; + } + } Task::SetBrightness(brightness) => self.set_brightness(frontend, data, brightness), Task::SetTab(tab) => { frontend.layout.remove_children(self.id_content); @@ -148,7 +177,7 @@ impl Tab for TabMonado { self.subtab = Subtab::ProcessList(SubtabProcessList::new(self.id_content, frontend)?) } TabNameEnum::DebugTimings => { - self.subtab = Subtab::DebugTimings(SubtabDebugTimings::new(self.id_content, frontend)?) + self.subtab = Subtab::DebugTimings(SubtabDebugTimings::new(self.id_content, frontend, &self.tasks)?) } } } @@ -167,7 +196,7 @@ impl Tab for TabMonado { } } Subtab::DebugTimings(timings) => { - timings.update(data, frontend); + timings.update(&self.tasks, data, frontend); } } @@ -249,21 +278,71 @@ impl SubtabGeneralSettings { } } +fn mount_sessions_list( + state: &mut ParserState, + layout: &mut Layout, + tasks: &Tasks, + id_parent: WidgetID, + sessions: &SessionsMap, +) -> anyhow::Result { + let mut buttons = Vec::new(); + let mut data_vec = Vec::new(); + let globals = layout.state.globals.clone(); + layout.remove_children(id_parent); + + for (session_id, session) in sessions { + let mut params = HashMap::new(); + + params.insert( + Rc::from("text"), + Rc::from(format!( + "{} (ID {})", + session.resolved_name.as_ref().map_or("Unknown", |s| s.as_str()), + session_id, + )), + ); + + let data = state.parse_template( + &doc_params_tab_debug_timings(&globals), + "SessionButton", + layout, + id_parent, + params, + )?; + + let button = data.fetch_component_as::("button")?; + + button.on_click({ + let tasks = tasks.clone(); + let session_id = *session_id; + Rc::new(move |_, _| { + tasks.push(Task::DebugTimingsSetSessionId(session_id)); + Ok(()) + }) + }); + + buttons.push(button); + data_vec.push(data); + } + + Ok(DebugSessionList { buttons, data_vec }) +} + fn mount_graph( state: &mut ParserState, - globals: &WguiGlobals, layout: &mut Layout, id_parent: WidgetID, name: &'static str, limits: (f32, f32), ) -> anyhow::Result { + let globals = layout.state.globals.clone(); let mut params = HashMap::new(); params.insert(Rc::from("name"), Rc::from(name)); params.insert(Rc::from("limit_min"), Rc::from(limits.0.to_string())); params.insert(Rc::from("limit_max"), Rc::from(limits.1.to_string())); let data = state.parse_template( - &doc_params_tab_debug_timings(globals), + &doc_params_tab_debug_timings(&globals), "DebugGraph", layout, id_parent, @@ -279,28 +358,46 @@ fn ns_to_ms(ns: i64) -> f32 { } impl SubtabDebugTimings { - fn new(parent_id: WidgetID, frontend: &mut Frontend) -> anyhow::Result { + fn new(parent_id: WidgetID, frontend: &mut Frontend, tasks: &Tasks) -> anyhow::Result { let mut state = wgui::parser::parse_from_assets( &doc_params_tab_debug_timings(&frontend.globals), &mut frontend.layout, parent_id, )?; - let id_parent = state.get_widget_id("parent")?; + let id_timings_parent = state.get_widget_id("timings_parent")?; + let id_sessions_list_parent = state.get_widget_id("session_list_parent")?; + + let sessions = Default::default(); + + let session_list = mount_sessions_list( + &mut state, + &mut frontend.layout, + tasks, + id_sessions_list_parent, + &sessions, + )?; + + Ok(Self { + state, + graphs: None, + session_list, + id_sessions_list_parent, + id_timings_parent, + sessions, + selected_session_id: None, + }) + } + + fn set_session_id(&mut self, layout: &mut Layout, session_id: i64) -> anyhow::Result<()> { + layout.remove_children(self.id_timings_parent); let mut graph = |name: &'static str, limits: (f32, f32)| -> anyhow::Result { - mount_graph( - &mut state, - &frontend.globals, - &mut frontend.layout, - id_parent, - name, - limits, - ) + mount_graph(&mut self.state, layout, self.id_timings_parent, name, limits) }; // populate graphs - let graphs = Graphs { + self.graphs = Some(Graphs { predicted_display_time: graph("Predicted display time", (0.0, 30.0))?, predicted_frame_time: graph("Predicted frame time", (0.0, 30.0))?, predicted_wake_up_time: graph("Predicted wake-up time", (0.0, 30.0))?, @@ -311,17 +408,26 @@ impl SubtabDebugTimings { when_wait_woke: graph("When wait woke", (0.0, 30.0))?, when_begin: graph("When begin", (0.0, 30.0))?, when_delivered: graph("When delivered", (0.0, 30.0))?, - when_gpu_done: graph("When gpu done", (0.0, 30.0))?, - }; + when_gpu_done: graph("When GPU done", (0.0, 30.0))?, + }); - Ok(Self { - state, - graphs, - sessions: Default::default(), - }) + self.selected_session_id = Some(session_id); + + Ok(()) } - fn update(&mut self, data: &mut T, frontend: &mut Frontend) { + fn refresh_session_list(&mut self, layout: &mut Layout, tasks: &Tasks) -> anyhow::Result<()> { + self.session_list = mount_sessions_list( + &mut self.state, + layout, + tasks, + self.id_sessions_list_parent, + &self.sessions, + )?; + Ok(()) + } + + fn update(&mut self, tasks: &Tasks, data: &mut T, frontend: &mut Frontend) { if !frontend.interface.monado_metrics_set_enabled(data, true) { return; } @@ -334,85 +440,95 @@ impl SubtabDebugTimings { let col_green = Color::new(0.0, 1.0, 0.0, 1.0); for frame in frames { - log::info!("{:?}", frame); + //log::info!("{:?}", frame); match self.sessions.get_mut(&frame.session_id) { Some(session) => { - let predicted_display_time = ns_to_ms(session.last_frame.predicted_display_time_ns as i64); - let predicted_frame_time = ns_to_ms(frame.predicted_frame_time_ns as i64); - let predicted_wake_up_time = - ns_to_ms(frame.predicted_wake_up_time_ns as i64 - session.last_frame.predicted_wake_up_time_ns as i64); - let predicted_gpu_done_time = - ns_to_ms(frame.predicted_gpu_done_time_ns as i64 - session.last_frame.predicted_gpu_done_time_ns as i64); - let predicted_display_period = ns_to_ms(session.last_frame.predicted_display_period_ns as i64); // 6.944 ms for 144Hz - let display_time = ns_to_ms(frame.display_time_ns as i64 - session.last_frame.display_time_ns as i64); - let when_predicted = ns_to_ms(frame.when_predicted_ns as i64 - session.last_frame.when_predicted_ns as i64); - let when_wait_woke = ns_to_ms(frame.when_wait_woke_ns as i64 - session.last_frame.when_wait_woke_ns as i64); - let when_begin = ns_to_ms(frame.when_begin_ns as i64 - session.last_frame.when_begin_ns as i64); - let when_delivered = ns_to_ms(frame.when_delivered_ns as i64 - session.last_frame.when_delivered_ns as i64); - let when_gpu_done = ns_to_ms(frame.when_gpu_done_ns as i64 - session.last_frame.when_gpu_done_ns as i64); + if let Some(graphs) = &mut self.graphs + && let Some(selected_session_id) = self.selected_session_id + && selected_session_id == frame.session_id + { + let predicted_display_time = ns_to_ms(session.last_frame.predicted_display_time_ns as i64); + let predicted_frame_time = ns_to_ms(frame.predicted_frame_time_ns as i64); + let predicted_wake_up_time = + ns_to_ms(frame.predicted_wake_up_time_ns as i64 - session.last_frame.predicted_wake_up_time_ns as i64); + let predicted_gpu_done_time = + ns_to_ms(frame.predicted_gpu_done_time_ns as i64 - session.last_frame.predicted_gpu_done_time_ns as i64); + let predicted_display_period = ns_to_ms(session.last_frame.predicted_display_period_ns as i64); // 6.944 ms for 144Hz + let display_time = ns_to_ms(frame.display_time_ns as i64 - session.last_frame.display_time_ns as i64); + let when_predicted = ns_to_ms(frame.when_predicted_ns as i64 - session.last_frame.when_predicted_ns as i64); + let when_wait_woke = ns_to_ms(frame.when_wait_woke_ns as i64 - session.last_frame.when_wait_woke_ns as i64); + let when_begin = ns_to_ms(frame.when_begin_ns as i64 - session.last_frame.when_begin_ns as i64); + let when_delivered = ns_to_ms(frame.when_delivered_ns as i64 - session.last_frame.when_delivered_ns as i64); + let when_gpu_done = ns_to_ms(frame.when_gpu_done_ns as i64 - session.last_frame.when_gpu_done_ns as i64); - self.graphs.predicted_display_time.graph.push_value(ValueCell { - value: predicted_display_time, - color: col_green, - }); + graphs.predicted_display_time.graph.push_value(ValueCell { + value: predicted_display_time, + color: col_green, + }); - self.graphs.predicted_frame_time.graph.push_value(ValueCell { - value: predicted_frame_time, - color: col_green, - }); + graphs.predicted_frame_time.graph.push_value(ValueCell { + value: predicted_frame_time, + color: col_green, + }); - self.graphs.predicted_wake_up_time.graph.push_value(ValueCell { - value: predicted_wake_up_time, - color: col_green, - }); + graphs.predicted_wake_up_time.graph.push_value(ValueCell { + value: predicted_wake_up_time, + color: col_green, + }); - self.graphs.predicted_gpu_done_time.graph.push_value(ValueCell { - value: predicted_gpu_done_time, - color: col_green, - }); + graphs.predicted_gpu_done_time.graph.push_value(ValueCell { + value: predicted_gpu_done_time, + color: col_green, + }); - self.graphs.predicted_display_period.graph.push_value(ValueCell { - value: predicted_display_period, - color: col_green, - }); + graphs.predicted_display_period.graph.push_value(ValueCell { + value: predicted_display_period, + color: col_green, + }); - self.graphs.display_time.graph.push_value(ValueCell { - value: display_time, - color: col_green, - }); + graphs.display_time.graph.push_value(ValueCell { + value: display_time, + color: col_green, + }); - self.graphs.when_predicted.graph.push_value(ValueCell { - value: when_predicted, - color: col_green, - }); + graphs.when_predicted.graph.push_value(ValueCell { + value: when_predicted, + color: col_green, + }); - self.graphs.when_wait_woke.graph.push_value(ValueCell { - value: when_wait_woke, - color: col_green, - }); + graphs.when_wait_woke.graph.push_value(ValueCell { + value: when_wait_woke, + color: col_green, + }); - self.graphs.when_begin.graph.push_value(ValueCell { - value: when_begin, - color: col_green, - }); + graphs.when_begin.graph.push_value(ValueCell { + value: when_begin, + color: col_green, + }); - self.graphs.when_delivered.graph.push_value(ValueCell { - value: when_delivered, - color: col_green, - }); + graphs.when_delivered.graph.push_value(ValueCell { + value: when_delivered, + color: col_green, + }); - self.graphs.when_gpu_done.graph.push_value(ValueCell { - value: when_gpu_done, - color: col_green, - }); + graphs.when_gpu_done.graph.push_value(ValueCell { + value: when_gpu_done, + color: col_green, + }); + } session.last_frame = frame; } None => { - self - .sessions - .insert(frame.session_id, TimingsSession { last_frame: frame }); + self.sessions.insert( + frame.session_id, + TimingsSession { + last_frame: frame, + resolved_name: None, + }, + ); + tasks.push(Task::DebugTimingsRefreshSessionList); } } } diff --git a/wayvr/src/overlays/dashboard.rs b/wayvr/src/overlays/dashboard.rs index 8f6b0a34..1db82735 100644 --- a/wayvr/src/overlays/dashboard.rs +++ b/wayvr/src/overlays/dashboard.rs @@ -609,8 +609,9 @@ impl DashInterface for DashInterfaceLive { } #[cfg(not(feature = "openxr"))] - fn monado_metrics_set_enabled(&mut self, _: &mut AppState, _enabled: bool) { + fn monado_metrics_set_enabled(&mut self, _: &mut AppState, _enabled: bool) -> bool { // not supported in this build + false } #[cfg(not(feature = "openxr"))] From 0a4fc34face66836d93277a8f602f2e1df44d1a4 Mon Sep 17 00:00:00 2001 From: Aleksander Date: Thu, 26 Mar 2026 22:15:05 +0100 Subject: [PATCH 7/9] dash-interface: fetch client IDs, toggle filter --- Cargo.lock | 6 ------ dash-frontend/src/tab/monado.rs | 21 ++++++++++++++------- wayvr/src/overlays/dashboard.rs | 10 +++++++++- wlx-common/src/dash_interface.rs | 3 ++- wlx-common/src/dash_interface_emulated.rs | 9 ++++++++- 5 files changed, 33 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4372aafe..18302e7a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2795,12 +2795,6 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - [[package]] name = "lebe" version = "0.5.3" diff --git a/dash-frontend/src/tab/monado.rs b/dash-frontend/src/tab/monado.rs index 5215e784..c65861b9 100644 --- a/dash-frontend/src/tab/monado.rs +++ b/dash-frontend/src/tab/monado.rs @@ -71,6 +71,7 @@ struct DebugGraph { } struct DebugSessionList { + #[allow(dead_code)] buttons: Vec>, #[allow(dead_code)] data_vec: Vec, @@ -112,6 +113,7 @@ struct SubtabDebugTimings { } #[allow(dead_code)] +#[allow(clippy::large_enum_variant)] enum Subtab { Empty, GeneralSettings(SubtabGeneralSettings), @@ -196,7 +198,7 @@ impl Tab for TabMonado { } } Subtab::DebugTimings(timings) => { - timings.update(&self.tasks, data, frontend); + timings.update(&self.tasks, data, frontend)?; } } @@ -427,14 +429,14 @@ impl SubtabDebugTimings { Ok(()) } - fn update(&mut self, tasks: &Tasks, data: &mut T, frontend: &mut Frontend) { + fn update(&mut self, tasks: &Tasks, data: &mut T, frontend: &mut Frontend) -> anyhow::Result<()> { if !frontend.interface.monado_metrics_set_enabled(data, true) { - return; + return Ok(()); } let frames = frontend.interface.monado_metrics_dump_session_frames(data); if frames.is_empty() { - return; + return Ok(()); } let col_green = Color::new(0.0, 1.0, 0.0, 1.0); @@ -525,7 +527,7 @@ impl SubtabDebugTimings { frame.session_id, TimingsSession { last_frame: frame, - resolved_name: None, + resolved_name: None, /* TODO! find client ID from session ID */ }, ); tasks.push(Task::DebugTimingsRefreshSessionList); @@ -534,6 +536,8 @@ impl SubtabDebugTimings { } frontend.layout.mark_redraw(); + + Ok(()) } } @@ -568,7 +572,10 @@ impl SubtabProcessList { Rc::from("0") }, ); - par.insert("name".into(), client.name.clone().into()); + par.insert( + "name".into(), + format!("{} (Client ID: {})", client.name, client.id).into(), + ); par.insert("flag_active".into(), yesno(client.is_active).into()); par.insert("flag_focused".into(), yesno(client.is_focused).into()); par.insert("flag_io_active".into(), yesno(client.is_io_active).into()); @@ -618,7 +625,7 @@ impl SubtabProcessList { fn refresh(&mut self, frontend: &mut Frontend, data: &mut T, tasks: &Tasks) -> anyhow::Result<()> { log::debug!("refreshing monado client list"); - let clients = frontend.interface.monado_client_list(data)?; + let clients = frontend.interface.monado_client_list(data, true)?; frontend.layout.remove_children(self.id_list_parent); self.cells.clear(); diff --git a/wayvr/src/overlays/dashboard.rs b/wayvr/src/overlays/dashboard.rs index 1db82735..f36e0558 100644 --- a/wayvr/src/overlays/dashboard.rs +++ b/wayvr/src/overlays/dashboard.rs @@ -470,20 +470,27 @@ impl DashInterface for DashInterfaceLive { fn monado_client_list( &mut self, app: &mut AppState, + filtered: bool, ) -> anyhow::Result> { let Some(monado) = &mut app.monado_state else { return Ok(Vec::new()); // no monado available }; - let clients = monado_list_clients_filtered(&mut monado.ipc)?; + let clients = if filtered { + monado_list_clients_filtered(&mut monado.ipc)? + } else { + monado.ipc.clients()?.into_iter().collect() + }; let mut res = Vec::::new(); for mut client in clients { + let client_id = client.id(); let name = client.name()?; let state = client.state()?; res.push(dash_interface::MonadoClient { + id: client_id as i64, name, is_primary: state.contains(libmonado::ClientState::ClientPrimaryApp), is_active: state.contains(libmonado::ClientState::ClientSessionActive), @@ -592,6 +599,7 @@ impl DashInterface for DashInterfaceLive { fn monado_client_list( &mut self, _: &mut AppState, + _filtered: bool, ) -> anyhow::Result> { anyhow::bail!("Not supported in this build.") } diff --git a/wlx-common/src/dash_interface.rs b/wlx-common/src/dash_interface.rs index 424ed2b2..7f80d557 100644 --- a/wlx-common/src/dash_interface.rs +++ b/wlx-common/src/dash_interface.rs @@ -7,6 +7,7 @@ use crate::{config::GeneralConfig, desktop_finder::DesktopFinder}; #[derive(Clone)] pub struct MonadoClient { + pub id: i64, pub name: String, pub is_primary: bool, pub is_active: bool, @@ -55,7 +56,7 @@ pub trait DashInterface { ) -> anyhow::Result; fn process_list(&mut self, data: &mut T) -> anyhow::Result>; fn process_terminate(&mut self, data: &mut T, handle: WvrProcessHandle) -> anyhow::Result<()>; - fn monado_client_list(&mut self, data: &mut T) -> anyhow::Result>; + fn monado_client_list(&mut self, data: &mut T, filtered: bool) -> anyhow::Result>; fn monado_client_focus(&mut self, data: &mut T, name: &str) -> anyhow::Result<()>; fn monado_brightness_get(&mut self, data: &mut T) -> Option; fn monado_brightness_set(&mut self, data: &mut T, brightness: f32) -> Option<()>; diff --git a/wlx-common/src/dash_interface_emulated.rs b/wlx-common/src/dash_interface_emulated.rs index 49b0dd7e..3526de94 100644 --- a/wlx-common/src/dash_interface_emulated.rs +++ b/wlx-common/src/dash_interface_emulated.rs @@ -88,6 +88,7 @@ impl DashInterfaceEmulated { let monado_clients = vec![ dash_interface::MonadoClient { + id: 1, name: String::from("The Best VR Game 3000"), is_active: true, is_focused: true, @@ -97,6 +98,7 @@ impl DashInterfaceEmulated { is_visible: true, }, dash_interface::MonadoClient { + id: 2, name: String::from("Second app"), is_active: true, is_focused: false, @@ -106,6 +108,7 @@ impl DashInterfaceEmulated { is_visible: true, }, dash_interface::MonadoClient { + id: 3, name: String::from("Third app"), is_active: true, is_focused: false, @@ -233,7 +236,11 @@ impl DashInterface<()> for DashInterfaceEmulated { fn toggle_dashboard(&mut self, _data: &mut ()) {} - fn monado_client_list(&mut self, _data: &mut ()) -> anyhow::Result> { + fn monado_client_list( + &mut self, + _data: &mut (), + _filtered: bool, + ) -> anyhow::Result> { Ok(self.monado_clients.clone()) } From 80277e0c12d0904d1d68da955920cc419b1db975 Mon Sep 17 00:00:00 2001 From: Aleksander Date: Fri, 27 Mar 2026 22:11:23 +0100 Subject: [PATCH 8/9] ParserState: add `realize_template`, fix sliders not being updated --- .../assets/gui/view/audio_settings.xml | 10 ++--- dash-frontend/src/tab/apps.rs | 4 +- dash-frontend/src/tab/monado.rs | 18 +++----- dash-frontend/src/views/audio_settings.rs | 7 ++- dash-frontend/src/views/running_games_list.rs | 2 +- wgui/src/layout.rs | 2 +- wgui/src/parser/mod.rs | 43 ++++++++++++++++--- wgui/src/windowing/context_menu.rs | 4 +- 8 files changed, 56 insertions(+), 34 deletions(-) diff --git a/dash-frontend/assets/gui/view/audio_settings.xml b/dash-frontend/assets/gui/view/audio_settings.xml index a6a4b887..e1dbabc2 100644 --- a/dash-frontend/assets/gui/view/audio_settings.xml +++ b/dash-frontend/assets/gui/view/audio_settings.xml @@ -1,16 +1,16 @@ - + @@ -67,4 +67,4 @@
- \ No newline at end of file + diff --git a/dash-frontend/src/tab/apps.rs b/dash-frontend/src/tab/apps.rs index cd2a5150..7e17ff39 100644 --- a/dash-frontend/src/tab/apps.rs +++ b/dash-frontend/src/tab/apps.rs @@ -286,7 +286,7 @@ impl AppList { let mut params = HashMap::, Rc>::new(); params.insert("text".into(), category_name.into()); - parser_state.parse_template( + parser_state.realize_template( doc_params, "CategoryText", &mut frontend.layout, @@ -318,7 +318,7 @@ impl AppList { ); params.insert("name".into(), entry.app_name.clone()); - let data = parser_state.parse_template( + let data = parser_state.realize_template( doc_params, "AppEntry", &mut frontend.layout, diff --git a/dash-frontend/src/tab/monado.rs b/dash-frontend/src/tab/monado.rs index c65861b9..0f714306 100644 --- a/dash-frontend/src/tab/monado.rs +++ b/dash-frontend/src/tab/monado.rs @@ -12,7 +12,7 @@ use wgui::{ drawing::Color, globals::WguiGlobals, layout::{Layout, WidgetID}, - parser::{self, Fetchable, ParseDocumentParams, ParserData, ParserState}, + parser::{self, Fetchable, ParseDocumentParams, ParserState}, task::Tasks, }; use wlx_common::dash_interface::{self, MonadoDumpSessionFrame}; @@ -66,15 +66,11 @@ struct SubtabGeneralSettings { struct DebugGraph { graph: Rc, - #[allow(dead_code)] - data: ParserData, } struct DebugSessionList { #[allow(dead_code)] buttons: Vec>, - #[allow(dead_code)] - data_vec: Vec, } struct TimingsSession { @@ -288,7 +284,6 @@ fn mount_sessions_list( sessions: &SessionsMap, ) -> anyhow::Result { let mut buttons = Vec::new(); - let mut data_vec = Vec::new(); let globals = layout.state.globals.clone(); layout.remove_children(id_parent); @@ -304,7 +299,7 @@ fn mount_sessions_list( )), ); - let data = state.parse_template( + let data = state.realize_template( &doc_params_tab_debug_timings(&globals), "SessionButton", layout, @@ -324,10 +319,9 @@ fn mount_sessions_list( }); buttons.push(button); - data_vec.push(data); } - Ok(DebugSessionList { buttons, data_vec }) + Ok(DebugSessionList { buttons }) } fn mount_graph( @@ -343,7 +337,7 @@ fn mount_graph( params.insert(Rc::from("limit_min"), Rc::from(limits.0.to_string())); params.insert(Rc::from("limit_max"), Rc::from(limits.1.to_string())); - let data = state.parse_template( + let data = state.realize_template( &doc_params_tab_debug_timings(&globals), "DebugGraph", layout, @@ -352,7 +346,7 @@ fn mount_graph( )?; let graph = data.fetch_component_as::("graph")?; - Ok(DebugGraph { graph, data }) + Ok(DebugGraph { graph }) } fn ns_to_ms(ns: i64) -> f32 { @@ -585,7 +579,7 @@ impl SubtabProcessList { let globals = layout.state.globals.clone(); - let state_cell = self.state.parse_template( + let state_cell = self.state.realize_template( &doc_params_tab_process_list(&globals), "Cell", layout, diff --git a/dash-frontend/src/views/audio_settings.rs b/dash-frontend/src/views/audio_settings.rs index f2c43f45..61061d33 100644 --- a/dash-frontend/src/views/audio_settings.rs +++ b/dash-frontend/src/views/audio_settings.rs @@ -750,7 +750,7 @@ impl View { let data = self .state - .parse_template(&doc_params(&self.globals), "Card", params.layout, self.id_devices, par)?; + .realize_template(&doc_params(&self.globals), "Card", params.layout, self.id_devices, par)?; let btn_card = data.fetch_component_as::("btn_card")?; btn_card.on_click({ @@ -764,7 +764,6 @@ impl View { }) }); - log::info!("mount card TODO: {}", params.card.name); Ok(()) } @@ -794,7 +793,7 @@ impl View { }, ); - let data = self.state.parse_template( + let data = self.state.realize_template( &doc_params(&self.globals), "DeviceSlider", params.layout, @@ -941,7 +940,7 @@ impl View { layout.remove_children(self.id_devices); { - let data = self.state.parse_template( + let data = self.state.realize_template( &doc_params(&self.globals), "SelectAudioProfileText", layout, diff --git a/dash-frontend/src/views/running_games_list.rs b/dash-frontend/src/views/running_games_list.rs index 19f96911..6428f5d1 100644 --- a/dash-frontend/src/views/running_games_list.rs +++ b/dash-frontend/src/views/running_games_list.rs @@ -127,7 +127,7 @@ impl View { for game in games { let game_name = View::extract_name_from_appid(&game.app_id, &self.installed_games); - let t = self.state.parse_template( + let t = self.state.realize_template( &doc_params(layout.state.globals.clone()), "RunningGameCell", layout, diff --git a/wgui/src/layout.rs b/wgui/src/layout.rs index 9c9a786b..2569f8b7 100644 --- a/wgui/src/layout.rs +++ b/wgui/src/layout.rs @@ -377,7 +377,7 @@ impl Layout { self.registered_components_to_refresh.insert(*node_id, component.weak()); } - /// Convenience function to avoid repeated `WidgetID` → `WidgetState` lookups. + /// Convenience function to avoid repeated `WidgetID` → `WidgetState` look-ups. pub fn add_event_listener( &self, widget_id: WidgetID, diff --git a/wgui/src/parser/mod.rs b/wgui/src/parser/mod.rs index bd716e7e..a715b4df 100644 --- a/wgui/src/parser/mod.rs +++ b/wgui/src/parser/mod.rs @@ -203,7 +203,6 @@ impl Fetchable for ParserData { let casted = widget .get_as::() .ok_or_else(|| anyhow::anyhow!("fetch_widget_as({id}): failed to cast"))?; - Ok(casted) } } @@ -219,16 +218,40 @@ pub struct ParserState { } impl ParserState { - /// This function is suitable in cases if you don't want to pollute main parser state with dynamic IDs - /// Use `instantiate_template` instead unless you want to handle `components` results yourself. - /// Make sure not to drop them if you want to have your listener handles valid - pub fn parse_template( + /// Parse named