diff --git a/executables/file_manager/src/file_manager.rs b/executables/file_manager/src/file_manager.rs index 705418ba..930c4c21 100644 --- a/executables/file_manager/src/file_manager.rs +++ b/executables/file_manager/src/file_manager.rs @@ -96,6 +96,8 @@ impl FileManager { } }); + self.window.yield_now().await; + self.running } diff --git a/executables/file_manager/src/lib.rs b/executables/file_manager/src/lib.rs index 86f23a4f..732fdeb5 100644 --- a/executables/file_manager/src/lib.rs +++ b/executables/file_manager/src/lib.rs @@ -8,9 +8,7 @@ mod file_manager; use alloc::boxed::Box; use alloc::string::{String, ToString}; use core::num::NonZeroUsize; -use core::time::Duration; use xila::executable::{self, ExecutableTrait, Standard}; -use xila::task; use xila::task::TaskIdentifier; use xila::virtual_file_system::{File, VirtualFileSystem}; @@ -62,9 +60,7 @@ pub async fn main(_: Standard, _: Vec) -> core::result::Result<(), NonZe .await .map_err(|_| NonZeroUsize::new(1).unwrap())?; - while file_manager.handle_events().await { - task::sleep(Duration::from_millis(50)).await; - } + while file_manager.handle_events().await {} Ok(()) } diff --git a/executables/settings/src/lib.rs b/executables/settings/src/lib.rs index 4b1869c5..4fb1e994 100644 --- a/executables/settings/src/lib.rs +++ b/executables/settings/src/lib.rs @@ -13,9 +13,7 @@ pub use settings::*; use alloc::string::{String, ToString}; use alloc::vec::Vec; use core::num::NonZeroUsize; -use core::time::Duration; use xila::executable::{self, ExecutableTrait, Standard}; -use xila::task; use xila::task::TaskIdentifier; use xila::virtual_file_system::{File, VirtualFileSystem}; @@ -70,9 +68,7 @@ pub async fn main(_: Standard, _: Vec) -> core::result::Result<(), NonZe .map_err(|_| NonZeroUsize::new(1).unwrap())?; // Run the main loop - while settings.handle_events().await { - task::sleep(Duration::from_millis(50)).await; - } + while settings.handle_events().await {} Ok(()) } diff --git a/executables/settings/src/settings.rs b/executables/settings/src/settings.rs index 85215f53..52448417 100644 --- a/executables/settings/src/settings.rs +++ b/executables/settings/src/settings.rs @@ -56,25 +56,25 @@ impl Settings { } pub async fn handle_events(&mut self) -> bool { - let mut running = true; - graphics::lock!({ while let Some(event) = self.window.pop_event() { + // Logique de filtrage spécifique à Settings if (event.code == EventKind::Delete || event.code == EventKind::CloseRequested) && event.target == self.window.get_object() { - running = false; - } else { - // Let each tab handle the event - for tab in &mut self.tabs { - if tab.handle_event(&event).await { - break; // Event was handled, no need to check other tabs - } + return false; + } + + for tab in &mut self.tabs { + if tab.handle_event(&event).await { + break; } } } }); - running + self.window.yield_now().await; + + true } } diff --git a/modules/graphics/src/window.rs b/modules/graphics/src/window.rs index 30db6bd4..51cb9c61 100644 --- a/modules/graphics/src/window.rs +++ b/modules/graphics/src/window.rs @@ -2,14 +2,17 @@ use super::lvgl; use crate::{Color, Error, EventKind, Result, event::Event}; use alloc::boxed::Box; use alloc::collections::VecDeque; -use core::{mem::forget, str}; +use core::{future::poll_fn, mem::forget, str, task::Poll}; +use synchronization::waitqueue::AtomicWaker; struct UserData { pub queue: VecDeque, pub icon_text: [u8; 2], pub icon_color: Color, + pub waker_registration: AtomicWaker, } +#[derive(Clone)] pub struct Window { window: *mut lvgl::lv_obj_t, } @@ -34,7 +37,7 @@ unsafe extern "C" fn event_callback(event: *mut lvgl::lv_event_t) { unsafe { let code = lvgl::lv_event_get_code(event); - let queue = lvgl::lv_event_get_user_data(event) as *mut VecDeque; + let user_data = lvgl::lv_event_get_user_data(event) as *mut UserData; let target = lvgl::lv_event_get_target(event) as *mut lvgl::lv_obj_t; @@ -42,7 +45,10 @@ unsafe extern "C" fn event_callback(event: *mut lvgl::lv_event_t) { lvgl::lv_event_code_t_LV_EVENT_CHILD_CREATED => { lvgl::lv_obj_add_flag(target, lvgl::lv_obj_flag_t_LV_OBJ_FLAG_EVENT_BUBBLE); - (*queue).push_back(Event::new(EventKind::ChildCreated, target, None)); + (*user_data) + .queue + .push_back(Event::new(EventKind::ChildCreated, target, None)); + (*user_data).waker_registration.wake(); } lvgl::lv_event_code_t_LV_EVENT_DRAW_MAIN | lvgl::lv_event_code_t_LV_EVENT_DRAW_MAIN_BEGIN @@ -51,16 +57,25 @@ unsafe extern "C" fn event_callback(event: *mut lvgl::lv_event_t) { | lvgl::lv_event_code_t_LV_EVENT_DRAW_POST_BEGIN | lvgl::lv_event_code_t_LV_EVENT_DRAW_POST_END | lvgl::lv_event_code_t_LV_EVENT_GET_SELF_SIZE - | lvgl::lv_event_code_t_LV_EVENT_COVER_CHECK => { + | lvgl::lv_event_code_t_LV_EVENT_COVER_CHECK + | lvgl::lv_event_code_t_LV_EVENT_LAYOUT_CHANGED => { // Ignore draw events } lvgl::lv_event_code_t_LV_EVENT_KEY => { let key = lvgl::lv_indev_get_key(lvgl::lv_indev_active()); - (*queue).push_back(Event::new(EventKind::Key, target, Some(key.into()))); + (*user_data) + .queue + .push_back(Event::new(EventKind::Key, target, Some(key.into()))); + (*user_data).waker_registration.wake(); } _ => { - (*queue).push_back(Event::new(EventKind::from_lvgl_code(code), target, None)); + (*user_data).queue.push_back(Event::new( + EventKind::from_lvgl_code(code), + target, + None, + )); + (*user_data).waker_registration.wake(); } } } @@ -96,6 +111,7 @@ impl Window { queue: VecDeque::with_capacity(10), icon_text: [b'I', b'c'], icon_color: Color::BLACK, + waker_registration: AtomicWaker::new(), }; let mut user_data = Box::new(user_data); @@ -192,6 +208,14 @@ impl Window { user_data.icon_color = icon_color; } + pub fn register_waker(&mut self, waker: &core::task::Waker) { + let user_data = unsafe { lvgl::lv_obj_get_user_data(self.window) as *mut UserData }; + + let user_data = unsafe { &mut *user_data }; + + user_data.waker_registration.register(waker); + } + /// Convert a raw pointer to a window object. /// /// # Returns @@ -206,6 +230,19 @@ impl Window { Self { window } } + pub fn yield_now(&mut self) -> impl core::future::Future + '_ { + let mut yielded = false; + poll_fn(move |cx| { + if yielded { + Poll::Ready(()) + } else { + self.register_waker(cx.waker()); + yielded = true; + Poll::Pending + } + }) + } + pub fn into_raw(self) -> *mut lvgl::lv_obj_t { let window = self.window;