system settings
git clone https://git.lucas.co/cce-system-interface.git
Introduce last_write_mtime tracking to eliminate background thread config reload race conditions
src/main.rs | 45 +++++++++++++++++++++++++++++++++------------
src/watchers.rs | 18 ++++++++++++------
2 files changed, 45 insertions(+), 18 deletions(-)
diff --git a/src/main.rs b/src/main.rs
index 39fd9d5..16288fc 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -172,15 +172,15 @@ struct SystemInterface {
rx_display: std::sync::mpsc::Receiver<pages::display::DisplayState>,
rx_network: std::sync::mpsc::Receiver<pages::network::NetworkState>,
rx_layout: std::sync::mpsc::Receiver<pages::interface::WindowsState>,
- rx_input: std::sync::mpsc::Receiver<pages::input::InputState>,
+ rx_input: std::sync::mpsc::Receiver<(pages::input::InputState, std::time::SystemTime)>,
rx_fingers: std::sync::mpsc::Receiver<Vec<Finger>>,
- rx_processes: std::sync::mpsc::Receiver<pages::processes::ProcessesState>,
+ pub rx_processes: std::sync::mpsc::Receiver<pages::processes::ProcessesState>, // wait, keep it as in original
rx_system: std::sync::mpsc::Receiver<pages::system_info::SystemState>,
rx_storage: std::sync::mpsc::Receiver<pages::storage::StorageState>,
rx_notifications: std::sync::mpsc::Receiver<pages::system_info::NotificationsConfig>,
rx_typeface: std::sync::mpsc::Receiver<pages::interface::InterfaceState>,
rx_services: std::sync::mpsc::Receiver<Vec<pages::processes::ServiceInfo>>,
- rx_interface: std::sync::mpsc::Receiver<pages::interface::InterfaceState>,
+ rx_interface: std::sync::mpsc::Receiver<(pages::interface::InterfaceState, std::time::SystemTime)>,
rx_accounts: std::sync::mpsc::Receiver<Vec<pages::accounts::AccountInfo>>,
tx_backup: std::sync::mpsc::Sender<pages::storage::StorageMessage>,
rx_backup: std::sync::mpsc::Receiver<pages::storage::StorageMessage>,
@@ -214,6 +214,7 @@ struct SystemInterface {
search_open: bool,
search_query: String,
search_box: cce_ui::widget::input::TextBox,
+ last_write_mtime: std::time::SystemTime,
}
impl cce_ui::engine::Application for SystemInterface {
@@ -288,6 +289,9 @@ impl cce_ui::engine::Application for SystemInterface {
rx_packages: watchers.rx_packages,
tx_update,
rx_update,
+ last_write_mtime: std::fs::metadata("/home/lsgalante/.config/cce/config.json")
+ .and_then(|m| m.modified())
+ .unwrap_or_else(|_| std::time::SystemTime::now()),
scale_factor: 1.0,
width: 820,
@@ -351,11 +355,16 @@ impl cce_ui::engine::Application for SystemInterface {
}
fn update(&mut self, msg: Self::Message, needs_rebuild: &mut bool, exit: &mut bool) {
- if matches!(msg, AppAction::Exit) {
+ if let AppAction::Exit = msg {
*exit = true;
return;
}
self.handle_action(&msg);
+ if let Ok(metadata) = std::fs::metadata("/home/lsgalante/.config/cce/config.json") {
+ if let Ok(mtime) = metadata.modified() {
+ self.last_write_mtime = mtime;
+ }
+ }
*needs_rebuild = true;
self.needs_rebuild = true;
}
@@ -370,9 +379,17 @@ impl cce_ui::engine::Application for SystemInterface {
}
let mut actions = Vec::new();
self.propagate_widget_changes(&mut actions);
+ let has_actions = !actions.is_empty();
for action in actions {
self.handle_action(&action);
}
+ if has_actions {
+ if let Ok(metadata) = std::fs::metadata("/home/lsgalante/.config/cce/config.json") {
+ if let Ok(mtime) = metadata.modified() {
+ self.last_write_mtime = mtime;
+ }
+ }
+ }
if self.needs_rebuild || self.ui_context.is_dirty() {
*needs_rebuild = true;
self.needs_rebuild = true;
@@ -658,10 +675,12 @@ fn collect_popover_rects(w: &dyn cce_ui::widget::Element, popovers: &mut Vec<(f3
}
}
- while let Ok(s) = self.rx_input.try_recv() {
- input::update(&mut self.app.input, input::InputMessage::Refreshed(s));
- if self.app.current_page == Page::Input {
- self.needs_rebuild = true;
+ while let Ok((s, mtime)) = self.rx_input.try_recv() {
+ if mtime > self.last_write_mtime {
+ input::update(&mut self.app.input, input::InputMessage::Refreshed(s));
+ if self.app.current_page == Page::Input {
+ self.needs_rebuild = true;
+ }
}
}
let mut got_fingers = None;
@@ -713,10 +732,12 @@ fn collect_popover_rects(w: &dyn cce_ui::widget::Element, popovers: &mut Vec<(f3
self.needs_rebuild = true;
}
}
- while let Ok(s) = self.rx_interface.try_recv() {
- interface::update(&mut self.app.interface, pages::interface::InterfaceMessage::Refreshed(s));
- if self.app.current_page == Page::Interface {
- self.needs_rebuild = true;
+ while let Ok((s, mtime)) = self.rx_interface.try_recv() {
+ if mtime > self.last_write_mtime {
+ interface::update(&mut self.app.interface, pages::interface::InterfaceMessage::Refreshed(s));
+ if self.app.current_page == Page::Interface {
+ self.needs_rebuild = true;
+ }
}
}
diff --git a/src/watchers.rs b/src/watchers.rs
index 3f02252..c4c3adf 100644
--- a/src/watchers.rs
+++ b/src/watchers.rs
@@ -9,7 +9,7 @@ pub struct Watchers {
pub rx_display: Receiver<display::DisplayState>,
pub rx_network: Receiver<network::NetworkState>,
pub rx_layout: Receiver<interface::WindowsState>,
- pub rx_input: Receiver<input::InputState>,
+ pub rx_input: Receiver<(input::InputState, std::time::SystemTime)>,
pub rx_fingers: Receiver<Vec<Finger>>,
pub rx_processes: Receiver<processes::ProcessesState>,
pub rx_system: Receiver<system_info::SystemState>,
@@ -17,7 +17,7 @@ pub struct Watchers {
pub rx_notifications: Receiver<system_info::NotificationsConfig>,
pub rx_typeface: Receiver<interface::InterfaceState>,
pub rx_services: Receiver<Vec<processes::ServiceInfo>>,
- pub rx_interface: Receiver<interface::InterfaceState>,
+ pub rx_interface: Receiver<(interface::InterfaceState, std::time::SystemTime)>,
pub rx_accounts: Receiver<Vec<accounts::AccountInfo>>,
pub rx_packages: Receiver<packages::PackagesState>,
}
@@ -95,7 +95,7 @@ pub fn spawn_all(
let rx_input = {
- let (tx, rx) = channel::<input::InputState>();
+ let (tx, rx) = channel::<(input::InputState, std::time::SystemTime)>();
let current_page_shared = current_page_shared.clone();
tokio::spawn(async move {
let mut last_fetch: Option<std::time::Instant> = None;
@@ -107,9 +107,12 @@ pub fn spawn_all(
Some(t) => t.elapsed() >= std::time::Duration::from_secs(30),
};
if should_fetch {
+ let mtime = std::fs::metadata("/home/lsgalante/.config/cce/config.json")
+ .and_then(|m| m.modified())
+ .unwrap_or_else(|_| std::time::SystemTime::now());
let val = tokio::task::spawn_blocking(|| input::read_input_config()).await;
if let Ok(val) = val {
- if tx.send(val).is_err() { break; }
+ if tx.send((val, mtime)).is_err() { break; }
}
last_fetch = Some(std::time::Instant::now());
}
@@ -188,7 +191,7 @@ pub fn spawn_all(
let rx_accounts = spawn_bg_active(current_page_shared.clone(), Page::Accounts.index() as u8, 3, || accounts::fetch_accounts());
let rx_interface = {
- let (tx, rx) = channel::<interface::InterfaceState>();
+ let (tx, rx) = channel::<(interface::InterfaceState, std::time::SystemTime)>();
let current_page_shared = current_page_shared.clone();
tokio::spawn(async move {
let mut last_fetch: Option<std::time::Instant> = None;
@@ -200,9 +203,12 @@ pub fn spawn_all(
Some(t) => t.elapsed() >= std::time::Duration::from_secs(30),
};
if should_fetch {
+ let mtime = std::fs::metadata("/home/lsgalante/.config/cce/config.json")
+ .and_then(|m| m.modified())
+ .unwrap_or_else(|_| std::time::SystemTime::now());
let val = tokio::task::spawn_blocking(|| interface::read_interface_config()).await;
if let Ok(val) = val {
- if tx.send(val).is_err() { break; }
+ if tx.send((val, mtime)).is_err() { break; }
}
last_fetch = Some(std::time::Instant::now());
}