From 507f41914d8db997a0ceb7a814ba462459fa28fe Mon Sep 17 00:00:00 2001 From: Alix ANNERAUD Date: Wed, 27 May 2026 22:52:31 +0200 Subject: [PATCH 01/18] Refactor split_host_port function for improved readability and efficiency --- drivers/shared/src/devices/http_common.rs | 31 +++++++++++------------ 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/drivers/shared/src/devices/http_common.rs b/drivers/shared/src/devices/http_common.rs index 627e39ef..c77d5b03 100644 --- a/drivers/shared/src/devices/http_common.rs +++ b/drivers/shared/src/devices/http_common.rs @@ -22,25 +22,24 @@ pub fn map_network_error(error: network::Error) -> Error { } pub fn split_host_port(host_value: &str, default_port: u16) -> (&str, u16) { - if let Some(stripped) = host_value.strip_prefix('[') { - if let Some(end) = stripped.find(']') { - let host = &stripped[..end]; - let remainder = &stripped[end + 1..]; - if let Some(port_string) = remainder.strip_prefix(':') { - if let Ok(port) = port_string.parse::() { - return (host, port); - } - } - return (host, default_port); + if let Some(stripped) = host_value.strip_prefix('[') + && let Some(end) = stripped.find(']') + { + let host = &stripped[..end]; + let remainder = &stripped[end + 1..]; + if let Some(port_string) = remainder.strip_prefix(':') + && let Ok(port) = port_string.parse::() + { + return (host, port); } + return (host, default_port); } - if let Some((host, port_string)) = host_value.rsplit_once(':') { - if !host.contains(':') { - if let Ok(port) = port_string.parse::() { - return (host, port); - } - } + if let Some((host, port_string)) = host_value.rsplit_once(':') + && !host.contains(':') + && let Ok(port) = port_string.parse::() + { + return (host, port); } (host_value, default_port) From ba76ac174412a785b5ac854c42e56f461374d328 Mon Sep 17 00:00:00 2001 From: Alix ANNERAUD Date: Wed, 27 May 2026 22:52:37 +0200 Subject: [PATCH 02/18] Refactor render_cpuinfo_text function for improved readability --- drivers/std/src/devices/cpu.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/std/src/devices/cpu.rs b/drivers/std/src/devices/cpu.rs index 462337f5..51ee118e 100644 --- a/drivers/std/src/devices/cpu.rs +++ b/drivers/std/src/devices/cpu.rs @@ -99,10 +99,10 @@ fn render_cpuinfo_text() -> String { let architecture = std::env::consts::ARCH; let cores = std::thread::available_parallelism().ok().map(usize::from); - if cfg!(target_os = "linux") { - if let Ok(content) = std::fs::read_to_string("/proc/cpuinfo") { - return build_cpuinfo_text_from_proc(&content, architecture, cores); - } + if cfg!(target_os = "linux") + && let Ok(content) = std::fs::read_to_string("/proc/cpuinfo") + { + return build_cpuinfo_text_from_proc(&content, architecture, cores); } build_cpuinfo_text_from_proc("", architecture, cores) From f565e1149c126275c4b45e25db0b046f8a98ee71 Mon Sep 17 00:00:00 2001 From: Alix ANNERAUD Date: Wed, 27 May 2026 22:52:47 +0200 Subject: [PATCH 03/18] Enable private API usage in lv_conf.h --- modules/graphics/include/lv_conf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/graphics/include/lv_conf.h b/modules/graphics/include/lv_conf.h index 84ff7622..4430f465 100644 --- a/modules/graphics/include/lv_conf.h +++ b/modules/graphics/include/lv_conf.h @@ -485,7 +485,7 @@ #define LV_USE_MATRIX 0 /** Include `lvgl_private.h` in `lvgl.h` to access internal data and functions by default */ -#define LV_USE_PRIVATE_API 0 +#define LV_USE_PRIVATE_API 1 /*================== * FONT USAGE From 9616e4b7488ec6dfec62d46b4c560176134bc7ed Mon Sep 17 00:00:00 2001 From: Alix ANNERAUD Date: Wed, 27 May 2026 22:53:01 +0200 Subject: [PATCH 04/18] Refactor Window structure and event handling for improved clarity and performance --- modules/graphics/src/window.rs | 364 ++++++++++++++++++++------------- 1 file changed, 225 insertions(+), 139 deletions(-) diff --git a/modules/graphics/src/window.rs b/modules/graphics/src/window.rs index 51cb9c61..a8ba2f56 100644 --- a/modules/graphics/src/window.rs +++ b/modules/graphics/src/window.rs @@ -1,91 +1,144 @@ use super::lvgl; -use crate::{Color, Error, EventKind, Result, event::Event}; -use alloc::boxed::Box; +use crate::{Color, Error, EventKind, Key, Result, event::Event, synchronous_lock}; use alloc::collections::VecDeque; -use core::{future::poll_fn, mem::forget, str, task::Poll}; -use synchronization::waitqueue::AtomicWaker; +use core::{ + future::poll_fn, + mem::{ManuallyDrop, forget}, + ops::{Deref, DerefMut}, + ptr::{self, NonNull}, + str, + task::Poll, +}; +use synchronization::{once_lock::OnceLock, waitqueue::AtomicWaker}; + +const WINDOW_QUEUE_DEFAULT_CAPACITY: usize = 10; + +#[repr(transparent)] +pub struct ClassWrapper(lvgl::lv_obj_class_t); + +unsafe impl Send for ClassWrapper {} +unsafe impl Sync for ClassWrapper {} + +static WINDOW_CLASS: OnceLock = OnceLock::new(); + +pub fn get_window_class() -> &'static lvgl::lv_obj_class_t { + let class_ref = WINDOW_CLASS.get_or_init(|| { + let mut cls = lvgl::lv_obj_class_t { + base_class: unsafe { &lvgl::lv_obj_class }, + constructor_cb: Some(window_constructor), + destructor_cb: Some(window_destructor), + event_cb: Some(window_event_callback), + width_def: unsafe { lvgl::lv_pct(100) }, + height_def: unsafe { lvgl::lv_pct(100) }, + name: c"window".as_ptr(), + ..Default::default() + }; + + cls.set_instance_size(size_of::() as _); + cls.set_group_def(lvgl::lv_obj_class_group_def_t_LV_OBJ_CLASS_GROUP_DEF_INHERIT as _); + cls.set_theme_inheritable( + lvgl::lv_obj_class_theme_inheritable_t_LV_OBJ_CLASS_THEME_INHERITABLE_TRUE as _, + ); + cls.set_editable(lvgl::lv_obj_class_editable_t_LV_OBJ_CLASS_EDITABLE_INHERIT as _); -struct UserData { - pub queue: VecDeque, - pub icon_text: [u8; 2], - pub icon_color: Color, - pub waker_registration: AtomicWaker, + ClassWrapper(cls) + }); + + &class_ref.0 } -#[derive(Clone)] +#[repr(C)] pub struct Window { - window: *mut lvgl::lv_obj_t, + object: lvgl::lv_obj_t, + event_queue: VecDeque, + icon_text: [u8; 2], + icon_color: Color, + waker_registration: AtomicWaker, } -impl Drop for Window { - fn drop(&mut self) { - if !self.is_valid() { - return; - } - - unsafe { - let user_data = lvgl::lv_obj_get_user_data(self.window) as *mut UserData; - - let _user_data = Box::from_raw(user_data); +unsafe extern "C" fn window_constructor( + _class_p: *const lvgl::lv_obj_class_t, + object: *mut lvgl::lv_obj_t, +) { + unsafe { + let window = object as *mut Window; + + ptr::write( + &mut (*window).event_queue, + VecDeque::with_capacity(WINDOW_QUEUE_DEFAULT_CAPACITY), + ); + ptr::write(&mut (*window).icon_text, [b'W', b'i']); + ptr::write(&mut (*window).icon_color, Color::BLACK); + ptr::write(&mut (*window).waker_registration, AtomicWaker::new()); + + lvgl::lv_obj_add_flag( + &mut (*window).object, + lvgl::lv_obj_flag_t_LV_OBJ_FLAG_EVENT_BUBBLE, + ); + lvgl::lv_obj_set_style_border_width(&mut (*window).object, 0, lvgl::LV_STATE_DEFAULT); + lvgl::lv_obj_set_style_radius(&mut (*window).object, 0, lvgl::LV_STATE_DEFAULT); + } +} - lvgl::lv_obj_delete(self.window); - } +unsafe extern "C" fn window_destructor( + _class_p: *const lvgl::lv_obj_class_t, + obj: *mut lvgl::lv_obj_t, +) { + unsafe { + let window = obj as *mut Window; + // Appelle explicitement Drop sur l'ensemble des champs Rust de Window + core::ptr::drop_in_place(window); } } -unsafe extern "C" fn event_callback(event: *mut lvgl::lv_event_t) { +unsafe extern "C" fn window_event_callback( + _class_p: *const lvgl::lv_obj_class_t, + event: *mut lvgl::lv_event_t, +) { unsafe { - let code = lvgl::lv_event_get_code(event); + let res = lvgl::lv_obj_event_base(get_window_class(), event); + + if res != lvgl::lv_result_t_LV_RESULT_OK { + return; // Not our event, ignore it + } - let user_data = lvgl::lv_event_get_user_data(event) as *mut UserData; + let code = lvgl::lv_event_get_code(event); + let window = lvgl::lv_event_get_current_target(event) as *mut Window; let target = lvgl::lv_event_get_target(event) as *mut lvgl::lv_obj_t; - match code { + let (code, key) = match code { 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); - - (*user_data) - .queue - .push_back(Event::new(EventKind::ChildCreated, target, None)); - (*user_data).waker_registration.wake(); + (code, None) + } + lvgl::lv_event_code_t_LV_EVENT_KEY => { + let key = lvgl::lv_indev_get_key(lvgl::lv_indev_active()); + let key = Key::from(key); + (code, Some(key)) } lvgl::lv_event_code_t_LV_EVENT_DRAW_MAIN | lvgl::lv_event_code_t_LV_EVENT_DRAW_MAIN_BEGIN | lvgl::lv_event_code_t_LV_EVENT_DRAW_MAIN_END | lvgl::lv_event_code_t_LV_EVENT_DRAW_POST | 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_LAYOUT_CHANGED => { + return; // Ignore draw events } - lvgl::lv_event_code_t_LV_EVENT_KEY => { - let key = lvgl::lv_indev_get_key(lvgl::lv_indev_active()); + _ => (code, None), + }; - (*user_data) - .queue - .push_back(Event::new(EventKind::Key, target, Some(key.into()))); - (*user_data).waker_registration.wake(); - } - _ => { - (*user_data).queue.push_back(Event::new( - EventKind::from_lvgl_code(code), - target, - None, - )); - (*user_data).waker_registration.wake(); - } - } + (*window) + .event_queue + .push_back(Event::new(EventKind::from_lvgl_code(code), target, key)); + (*window).waker_registration.wake(); } } impl Window { - fn is_valid(&self) -> bool { - unsafe { lvgl::lv_obj_is_valid(self.window) } - } - /// Create a new window. /// /// # Arguments @@ -100,120 +153,67 @@ impl Window { /// /// This function is unsafe because it may dereference raw pointers (e.g. `Parent_object`). /// - pub unsafe fn new(parent_object: *mut lvgl::lv_obj_t) -> Result { - let window = unsafe { lvgl::lv_obj_create(parent_object) }; - - if window.is_null() { - return Err(Error::FailedToCreateObject); - } - - let user_data = UserData { - 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); + pub unsafe fn new(parent: *mut lvgl::lv_obj_t) -> Result> { + let obj = unsafe { lvgl::lv_obj_class_create_obj(get_window_class(), parent) }; unsafe { - // Set the event callback for the window. - lvgl::lv_obj_add_event_cb( - window, - Some(event_callback), - lvgl::lv_event_code_t_LV_EVENT_ALL, - &mut user_data.queue as *mut _ as *mut core::ffi::c_void, - ); - lvgl::lv_obj_add_flag(window, lvgl::lv_obj_flag_t_LV_OBJ_FLAG_EVENT_BUBBLE); - lvgl::lv_obj_set_user_data(window, Box::into_raw(user_data) as *mut core::ffi::c_void); - // Set the size of the window to 100% of the parent object. - lvgl::lv_obj_set_size(window, lvgl::lv_pct(100), lvgl::lv_pct(100)); - lvgl::lv_obj_set_style_border_width(window, 0, lvgl::LV_STATE_DEFAULT); - lvgl::lv_obj_set_style_radius(window, 0, lvgl::LV_STATE_DEFAULT); + lvgl::lv_obj_class_init_obj(obj); } - Ok(Self { window }) + match NonNull::new(obj as *mut Self) { + Some(window) => Ok(window), + None => Err(Error::FailedToCreateObject), + } } pub fn get_identifier(&self) -> usize { - self.window as usize + self as *const Self as usize } pub fn peek_event(&self) -> Option { - if !self.is_valid() { - return None; - } - - let user_data = unsafe { lvgl::lv_obj_get_user_data(self.window) as *mut UserData }; - - let user_data = unsafe { Box::from_raw(user_data) }; - - let event = user_data.queue.front().cloned(); - - forget(user_data); - - event + self.event_queue.front().cloned() } pub fn pop_event(&mut self) -> Option { - if !self.is_valid() { - return None; - } - - let user_data = unsafe { lvgl::lv_obj_get_user_data(self.window) as *mut UserData }; - - let mut user_data = unsafe { Box::from_raw(user_data) }; - - let event = user_data.queue.pop_front(); - - forget(user_data); + self.event_queue.pop_front() + } - event + pub fn as_object(&self) -> &lvgl::lv_obj_t { + &self.object } - pub fn get_object(&self) -> *mut lvgl::lv_obj_t { - self.window + pub fn as_object_mutable(&mut self) -> &mut lvgl::lv_obj_t { + &mut self.object } pub fn get_icon(&self) -> (&str, Color) { - let user_data = unsafe { - let user_data = lvgl::lv_obj_get_user_data(self.window) as *mut UserData; - - &*user_data - }; + let icon_string = str::from_utf8(&self.icon_text) + .unwrap_or("??") + .trim_matches(char::from(0)); - unsafe { - ( - str::from_utf8_unchecked(&user_data.icon_text), - user_data.icon_color, - ) - } + (icon_string, self.icon_color) } pub fn set_icon(&mut self, icon_string: &str, icon_color: Color) { - let user_data = unsafe { lvgl::lv_obj_get_user_data(self.window) as *mut UserData }; - - let user_data = unsafe { &mut *user_data }; - let mut iterator = icon_string.chars(); if let Some(character) = iterator.next() { - user_data.icon_text[0] = character as u8; + self.icon_text[0] = character as u8; } if let Some(character) = iterator.next() { - user_data.icon_text[1] = character as u8; + self.icon_text[1] = character as u8; } - user_data.icon_color = icon_color; + self.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 }; + pub fn wake_up(&mut self) { + self.waker_registration.wake(); + } - user_data.waker_registration.register(waker); + pub fn register_waker(&mut self, waker: &core::task::Waker) { + self.waker_registration.register(waker); } /// Convert a raw pointer to a window object. @@ -226,8 +226,18 @@ impl Window { /// /// This function is unsafe because it may dereference raw pointers (e.g. `Window`). /// - pub unsafe fn from_raw(window: *mut lvgl::lv_obj_t) -> Self { - Self { window } + pub unsafe fn from_raw(window: *mut lvgl::lv_obj_t) -> Option> { + if !unsafe { lvgl::lv_obj_is_valid(window) } { + return None; + } + + let class = unsafe { lvgl::lv_obj_get_class(window) }; + + if class != get_window_class() { + return None; + } + + NonNull::new(window as *mut Self) } pub fn yield_now(&mut self) -> impl core::future::Future + '_ { @@ -243,11 +253,87 @@ impl Window { }) } - pub fn into_raw(self) -> *mut lvgl::lv_obj_t { - let window = self.window; + pub fn delete(&mut self) { + unsafe { + lvgl::lv_obj_delete(&mut self.object); + } + } +} + +impl AsRef for Window { + #[inline] + fn as_ref(&self) -> &lvgl::lv_obj_t { + &self.object + } +} + +impl AsMut for Window { + #[inline] + fn as_mut(&mut self) -> &mut lvgl::lv_obj_t { + &mut self.object + } +} + +impl Deref for Window { + type Target = lvgl::lv_obj_t; + + #[inline] + fn deref(&self) -> &Self::Target { + &self.object + } +} + +impl DerefMut for Window { + #[inline] + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.object + } +} - forget(self); +/// A wrapper around Window that automatically deletes the window when dropped. +pub struct OwnedWindow(NonNull); + +impl OwnedWindow { + pub fn new(window: NonNull) -> Self { + Self(window) + } +} + +impl From> for OwnedWindow { + fn from(window: NonNull) -> Self { + Self::new(window) + } +} + +impl Into> for OwnedWindow { + fn into(self) -> NonNull { + let this = ManuallyDrop::new(self); + this.0 + } +} + +impl Drop for OwnedWindow { + fn drop(&mut self) { + synchronous_lock!({ + unsafe { + self.0.as_mut().delete(); + } + }); + } +} + +impl Deref for OwnedWindow { + type Target = Window; + + #[inline] + fn deref(&self) -> &Self::Target { + unsafe { self.0.as_ref() } + } +} - window +impl DerefMut for OwnedWindow { + #[inline] + fn deref_mut(&mut self) -> &mut Self::Target { + unsafe { self.0.as_mut() } } } From b078583cbb1060915b08c6136a4199c2506f7670 Mon Sep 17 00:00:00 2001 From: Alix ANNERAUD Date: Wed, 27 May 2026 22:53:08 +0200 Subject: [PATCH 05/18] Refactor Manager to use OwnedWindow and improve window handling --- modules/graphics/src/manager.rs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/modules/graphics/src/manager.rs b/modules/graphics/src/manager.rs index c9c13e92..670ff1a6 100644 --- a/modules/graphics/src/manager.rs +++ b/modules/graphics/src/manager.rs @@ -9,17 +9,17 @@ use synchronization::mutex::{Mutex, MutexGuard}; use synchronization::{once_lock::OnceLock, rwlock::RwLock}; use task::block_on; -use core::{future::Future, mem::forget}; +use core::future::Future; use core::time::Duration; use super::lvgl; -use crate::Display; use crate::Input; use crate::InputKind; use crate::window::Window; use crate::{Color, theme}; +use crate::{Display, OwnedWindow}; use crate::{Error, Result}; static MANAGER_INSTANCE: OnceLock = OnceLock::new(); @@ -163,12 +163,12 @@ impl Manager { Ok(()) } - pub async fn create_window(&self) -> Result { + pub async fn create_window(&self) -> Result { let parent_object = self.inner.write().await.window_parent; let window = unsafe { Window::new(parent_object)? }; - Ok(window) + Ok(OwnedWindow::new(window)) } pub async fn add_input_device( @@ -209,15 +209,13 @@ impl Manager { let window = unsafe { let child = lvgl::lv_obj_get_child(window_parent, index as i32); - Window::from_raw(child) + Window::from_raw(child).ok_or(Error::InvalidWindowIdentifier)? }; - let icon = window.get_icon(); + let icon = unsafe { window.as_ref().get_icon() }; let icon = (icon.0.to_string(), icon.1); - forget(window); - Ok(icon) } From e1d0494aa0e3e28400d59e2519fdfa56ec97fd0f Mon Sep 17 00:00:00 2001 From: Alix ANNERAUD Date: Wed, 27 May 2026 22:54:20 +0200 Subject: [PATCH 06/18] Refactor graphics window handling to use OwnedWindow for improved consistency and performance --- executables/file_manager/src/file_manager.rs | 24 +++--- executables/settings/src/settings.rs | 9 +- executables/shell/graphical/src/desk.rs | 89 +++++++++----------- executables/shell/graphical/src/layout.rs | 24 +++--- executables/shell/graphical/src/login.rs | 23 +++-- executables/terminal/src/terminal.rs | 19 +++-- 6 files changed, 88 insertions(+), 100 deletions(-) diff --git a/executables/file_manager/src/file_manager.rs b/executables/file_manager/src/file_manager.rs index 930c4c21..fa3630ed 100644 --- a/executables/file_manager/src/file_manager.rs +++ b/executables/file_manager/src/file_manager.rs @@ -6,20 +6,20 @@ pub(crate) use alloc::{ vec::Vec, }; use core::ptr::null_mut; -use xila::internationalization::translate; use xila::log; use xila::task; use xila::virtual_file_system::{Directory, get_instance}; use xila::{ file_system::{Kind, Path, PathOwned}, graphics::{ - self, EventKind, Window, lvgl, + self, EventKind, lvgl, palette::{self, Hue}, }, }; +use xila::{graphics::OwnedWindow, internationalization::translate}; pub struct FileManager { - window: Window, + window: OwnedWindow, toolbar: *mut lvgl::lv_obj_t, up_button: *mut lvgl::lv_obj_t, home_button: *mut lvgl::lv_obj_t, @@ -63,15 +63,15 @@ impl FileManager { // Set up window layout for flex unsafe { lvgl::lv_obj_set_layout( - manager.window.get_object(), + manager.window.as_object_mutable(), lvgl::lv_layout_t_LV_LAYOUT_FLEX, ); lvgl::lv_obj_set_flex_flow( - manager.window.get_object(), + manager.window.as_object_mutable(), lvgl::lv_flex_flow_t_LV_FLEX_FLOW_COLUMN, ); lvgl::lv_obj_set_style_pad_all( - manager.window.get_object(), + manager.window.as_object_mutable(), 0, lvgl::LV_STATE_DEFAULT, ); @@ -103,10 +103,10 @@ impl FileManager { pub async fn handle_event(&mut self, event: graphics::Event) -> Result<()> { match event.code { - EventKind::Delete | EventKind::CloseRequested => { - if event.target == self.window.get_object() { - self.running = false; - } + EventKind::Delete | EventKind::CloseRequested + if event.target == self.window.as_object_mutable() => + { + self.running = false; } EventKind::Clicked => { let target = event.target; @@ -133,7 +133,7 @@ impl FileManager { async fn create_toolbar(&mut self) -> Result<()> { unsafe { - self.toolbar = lvgl::lv_obj_create(self.window.get_object()); + self.toolbar = lvgl::lv_obj_create(self.window.as_object_mutable()); if self.toolbar.is_null() { return Err(Error::FailedToCreateObject); } @@ -223,7 +223,7 @@ impl FileManager { async fn create_file_list(&mut self) -> Result<()> { unsafe { - self.file_list = lvgl::lv_list_create(self.window.get_object()); + self.file_list = lvgl::lv_list_create(self.window.as_object_mutable()); if self.file_list.is_null() { return Err(Error::FailedToCreateObject); } diff --git a/executables/settings/src/settings.rs b/executables/settings/src/settings.rs index 52448417..74dcb82c 100644 --- a/executables/settings/src/settings.rs +++ b/executables/settings/src/settings.rs @@ -1,7 +1,8 @@ use alloc::string::String; use xila::file_system::Kind; +use xila::graphics::OwnedWindow; use xila::graphics::{ - self, EventKind, Window, lvgl, + self, EventKind, lvgl, palette::{self, Hue}, }; @@ -9,7 +10,7 @@ use crate::error::Result; use crate::tabs::{AboutTab, GeneralTab, NetworkTab, PasswordTab, Tab}; pub struct Settings { - window: Window, + window: OwnedWindow, tabs: [Tab; 4], } @@ -30,7 +31,7 @@ impl Settings { // Create tabview let tabview = unsafe { - let tabview = lvgl::lv_tabview_create(window.get_object()); + let tabview = lvgl::lv_tabview_create(window.as_object_mutable()); if tabview.is_null() { return Err(crate::error::Error::FailedToCreateUiElement); @@ -60,7 +61,7 @@ impl Settings { 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() + && event.target == self.window.as_object_mutable() { return false; } diff --git a/executables/shell/graphical/src/desk.rs b/executables/shell/graphical/src/desk.rs index 69dc6a9c..0fc3a146 100644 --- a/executables/shell/graphical/src/desk.rs +++ b/executables/shell/graphical/src/desk.rs @@ -12,7 +12,7 @@ use alloc::{ vec, vec::Vec, }; -use xila::graphics::{self, Color, EventKind, Logo, Point, Window, lvgl}; +use xila::graphics::{self, Color, EventKind, Logo, OwnedWindow, Point, lvgl}; use xila::log::{self, error, warning}; use xila::task; use xila::virtual_file_system::{self, Directory}; @@ -26,7 +26,7 @@ use xila::{file_system::Kind, graphics::symbol}; pub const WINDOWS_PARENT_CHILD_CHANGED: graphics::EventKind = graphics::EventKind::Custom2; pub struct Desk { - window: Window, + window: OwnedWindow, tile_view: *mut lvgl::lv_obj_t, drawer_tile: *mut lvgl::lv_obj_t, desk_tile: *mut lvgl::lv_obj_t, @@ -72,8 +72,8 @@ impl Desk { pub const HOME_EVENT: EventKind = EventKind::Custom1; - pub fn get_window_object(&self) -> *mut lvgl::lv_obj_t { - self.window.get_object() + pub fn get_window_object(&mut self) -> *mut lvgl::lv_obj_t { + self.window.as_object_mutable() } pub fn is_hidden(&self) -> bool { @@ -89,20 +89,20 @@ impl Desk { window.set_icon("De", Color::BLACK); unsafe { - lvgl::lv_obj_set_style_pad_all(window.get_object(), 0, lvgl::LV_STATE_DEFAULT); + lvgl::lv_obj_set_style_pad_all(window.as_mut(), 0, lvgl::LV_STATE_DEFAULT); lvgl::lv_obj_add_event_cb( windows_parent, Some(event_handler), EventKind::All as u32, - window.get_object() as *mut core::ffi::c_void, + window.as_object_mutable() as *mut _ as *mut _, ); } // - Create the logo unsafe { // Create the logo in the background of the window - let logo = Logo::new(window.get_object(), 4, Color::BLACK)?; + let logo = Logo::new(window.as_mut(), 4, Color::BLACK)?; let logo_inner_object = logo.get_inner_object(); forget(logo); // Prevent the logo from being dropped @@ -133,7 +133,7 @@ impl Desk { // - Create a tile view let tile_view = unsafe { - let tile_view = lvgl::lv_tileview_create(window.get_object()); + let tile_view = lvgl::lv_tileview_create(window.as_mut()); if tile_view.is_null() { return Err(Error::FailedToCreateObject); @@ -353,7 +353,7 @@ impl Desk { unsafe { self.close_dock_menu(); - let menu = lvgl::lv_list_create(self.window.get_object()); + let menu = lvgl::lv_list_create(self.window.as_object_mutable()); if menu.is_null() { return Err(Error::FailedToCreateObject); @@ -560,17 +560,13 @@ impl Desk { Self::HOME_EVENT => unsafe { lvgl::lv_tileview_set_tile_by_index(self.tile_view, 0, 0, true); }, - EventKind::ValueChanged => { - if event.target == self.tile_view { - unsafe { - if lvgl::lv_tileview_get_tile_active(self.tile_view) == self.desk_tile { - lvgl::lv_obj_clean(self.drawer_tile); - } else if lvgl::lv_obj_get_child_count(self.drawer_tile) == 0 { - let _ = self.create_drawer_interface(self.drawer_tile).await; - } - } + EventKind::ValueChanged if event.target == self.tile_view => unsafe { + if lvgl::lv_tileview_get_tile_active(self.tile_view) == self.desk_tile { + lvgl::lv_obj_clean(self.drawer_tile); + } else if lvgl::lv_obj_get_child_count(self.drawer_tile) == 0 { + let _ = self.create_drawer_interface(self.drawer_tile).await; } - } + }, EventKind::Clicked => { if self .dock_menu_maximize_button @@ -668,43 +664,38 @@ impl Desk { } } } - EventKind::LongPressed => { + EventKind::LongPressed if unsafe { lvgl::lv_obj_get_parent(event.target) == self.dock } - && event.target != self.main_button - { - let window_identifier = - unsafe { lvgl::lv_obj_get_user_data(event.target) as usize }; + && event.target != self.main_button => + { + let window_identifier = + unsafe { lvgl::lv_obj_get_user_data(event.target) as usize }; - unsafe { - self.open_dock_menu(event.target, window_identifier)?; - } + unsafe { + self.open_dock_menu(event.target, window_identifier)?; } } - EventKind::Pressed => { - if event.target == self.main_button - || unsafe { lvgl::lv_obj_get_parent(event.target) == self.main_button } - { - unsafe { - lvgl::lv_obj_add_state(self.main_button, lvgl::LV_STATE_PRESSED as u16); - for i in 0..4 { - let part = lvgl::lv_obj_get_child(self.main_button, i); + EventKind::Pressed + if (event.target == self.main_button + || unsafe { lvgl::lv_obj_get_parent(event.target) == self.main_button }) => + unsafe { + lvgl::lv_obj_add_state(self.main_button, lvgl::LV_STATE_PRESSED as u16); + for i in 0..4 { + let part = lvgl::lv_obj_get_child(self.main_button, i); - lvgl::lv_obj_add_state(part, lvgl::LV_STATE_PRESSED as u16); - } - } + lvgl::lv_obj_add_state(part, lvgl::LV_STATE_PRESSED as u16); + } + }, + EventKind::Released + if (event.target == self.main_button + || unsafe { lvgl::lv_obj_get_parent(event.target) == self.main_button }) => + { + unsafe { + self.clear_main_button_pressed_state(); } - } - EventKind::Released => { - if event.target == self.main_button - || unsafe { lvgl::lv_obj_get_parent(event.target) == self.main_button } - { - unsafe { - self.clear_main_button_pressed_state(); - } - unsafe { - lvgl::lv_tileview_set_tile_by_index(self.tile_view, 0, 1, true); - } + unsafe { + lvgl::lv_tileview_set_tile_by_index(self.tile_view, 0, 1, true); } } EventKind::PressLost => unsafe { diff --git a/executables/shell/graphical/src/layout.rs b/executables/shell/graphical/src/layout.rs index d6710e2e..9eaee220 100644 --- a/executables/shell/graphical/src/layout.rs +++ b/executables/shell/graphical/src/layout.rs @@ -88,21 +88,17 @@ pub unsafe extern "C" fn screen_event_handler(event: *mut lvgl::lv_event_t) { } match code { - EventKind::Focused => { - if lvgl::lv_obj_has_class(target, &lvgl::lv_textarea_class) { - lvgl::lv_keyboard_set_textarea(keyboard, target); - lvgl::lv_obj_remove_flag(keyboard, lvgl::lv_obj_flag_t_LV_OBJ_FLAG_HIDDEN); - lvgl::lv_obj_move_foreground(keyboard); - - let width = lvgl::lv_obj_get_width(keyboard); - lvgl::lv_obj_set_height(keyboard, (width as f64 / KEYBOARD_SIZE_RATIO) as i32); - } + EventKind::Focused if lvgl::lv_obj_has_class(target, &lvgl::lv_textarea_class) => { + lvgl::lv_keyboard_set_textarea(keyboard, target); + lvgl::lv_obj_remove_flag(keyboard, lvgl::lv_obj_flag_t_LV_OBJ_FLAG_HIDDEN); + lvgl::lv_obj_move_foreground(keyboard); + + let width = lvgl::lv_obj_get_width(keyboard); + lvgl::lv_obj_set_height(keyboard, (width as f64 / KEYBOARD_SIZE_RATIO) as i32); } - EventKind::Defocused => { - if lvgl::lv_obj_has_class(target, &lvgl::lv_textarea_class) { - lvgl::lv_keyboard_set_textarea(keyboard, null_mut()); - lvgl::lv_obj_add_flag(keyboard, lvgl::lv_obj_flag_t_LV_OBJ_FLAG_HIDDEN); - } + EventKind::Defocused if lvgl::lv_obj_has_class(target, &lvgl::lv_textarea_class) => { + lvgl::lv_keyboard_set_textarea(keyboard, null_mut()); + lvgl::lv_obj_add_flag(keyboard, lvgl::lv_obj_flag_t_LV_OBJ_FLAG_HIDDEN); } _ => {} } diff --git a/executables/shell/graphical/src/login.rs b/executables/shell/graphical/src/login.rs index 2ccf876f..e9a09abe 100644 --- a/executables/shell/graphical/src/login.rs +++ b/executables/shell/graphical/src/login.rs @@ -1,8 +1,7 @@ -pub(crate) use core::ffi::CStr; - use alloc::string::ToString; +pub(crate) use core::ffi::CStr; use xila::authentication; -use xila::graphics::{self, EventKind, Window, lvgl}; +use xila::graphics::{self, EventKind, OwnedWindow, lvgl}; use xila::internationalization::translate; use xila::task; use xila::users::UserIdentifier; @@ -11,7 +10,7 @@ use xila::virtual_file_system; use crate::error::{Error, Result}; pub struct Login { - window: Window, + window: OwnedWindow, user_name_text_area: *mut lvgl::lv_obj_t, password_text_area: *mut lvgl::lv_obj_t, button: *mut lvgl::lv_obj_t, @@ -24,12 +23,12 @@ impl Login { // - Lock the graphics graphics::lock!({ // - Create a window - let window = graphics::get_instance().create_window().await?; + let mut window = graphics::get_instance().create_window().await?; unsafe { - lvgl::lv_obj_set_flex_flow(window.get_object(), lvgl::LV_FLEX_COLUMN); + lvgl::lv_obj_set_flex_flow(window.as_object_mutable(), lvgl::LV_FLEX_COLUMN); lvgl::lv_obj_set_flex_align( - window.get_object(), + window.as_object_mutable(), lvgl::lv_flex_align_t_LV_FLEX_ALIGN_CENTER, lvgl::lv_flex_align_t_LV_FLEX_ALIGN_CENTER, lvgl::lv_flex_align_t_LV_FLEX_ALIGN_CENTER, @@ -38,7 +37,7 @@ impl Login { let user_name_text_area = unsafe { // - Create a text area for the user name - let user_name_text_area = lvgl::lv_textarea_create(window.get_object()); + let user_name_text_area = lvgl::lv_textarea_create(window.as_object_mutable()); lvgl::lv_textarea_set_placeholder_text( user_name_text_area, @@ -51,7 +50,7 @@ impl Login { let password_text_area = unsafe { // - Create a text area for the password - let password_text_area = lvgl::lv_textarea_create(window.get_object()); + let password_text_area = lvgl::lv_textarea_create(window.as_mut()); lvgl::lv_textarea_set_placeholder_text( password_text_area, @@ -65,7 +64,7 @@ impl Login { let error_label = unsafe { // - Create a label for the error - let error_label = lvgl::lv_label_create(window.get_object()); + let error_label = lvgl::lv_label_create(window.as_mut()); lvgl::lv_label_set_text(error_label, c"".as_ptr()); @@ -74,7 +73,7 @@ impl Login { let button = unsafe { // - Create a button - let button = lvgl::lv_button_create(window.get_object()); + let button = lvgl::lv_button_create(window.as_mut()); let label = lvgl::lv_label_create(button); @@ -151,7 +150,7 @@ impl Login { pub async fn event_handler(&mut self) { graphics::lock! {{ - while let Some(event) = self.window.pop_event() { + while let Some(event) = self.window.pop_event() { // If we are typing the user name or the password if event.code == EventKind::ValueChanged && (event.target == self.user_name_text_area diff --git a/executables/terminal/src/terminal.rs b/executables/terminal/src/terminal.rs index be2bba1b..227c371d 100644 --- a/executables/terminal/src/terminal.rs +++ b/executables/terminal/src/terminal.rs @@ -1,15 +1,16 @@ use crate::error::{Error, Result}; use alloc::{collections::vec_deque::VecDeque, string::String}; use core::ffi::CStr; +use xila::graphics::OwnedWindow; use xila::graphics::fonts::get_font_monospace_medium; use xila::graphics::{ - self, Color, EventKind, Key, Window, + self, Color, EventKind, Key, lvgl::{self, lv_obj_t}, }; use xila::synchronization::{blocking_mutex::raw::CriticalSectionRawMutex, rwlock::RwLock}; pub(crate) struct Inner { - window: Window, + window: OwnedWindow, buffer: String, display: *mut lvgl::lv_obj_t, input: *mut lvgl::lv_obj_t, @@ -34,13 +35,13 @@ impl Terminal { window.set_icon(">_", Color::BLACK); lvgl::lv_obj_set_flex_flow( - window.get_object(), + window.as_object_mutable(), lvgl::lv_flex_flow_t_LV_FLEX_FLOW_COLUMN, ); } let container = unsafe { - let container = lvgl::lv_obj_create(window.get_object()); + let container = lvgl::lv_obj_create(window.as_object_mutable()); lvgl::lv_obj_set_width(container, lvgl::lv_pct(100)); lvgl::lv_obj_set_flex_grow(container, 1); @@ -74,7 +75,7 @@ impl Terminal { }; let input = unsafe { - let input = lvgl::lv_textarea_create(window.get_object()); + let input = lvgl::lv_textarea_create(window.as_object_mutable()); if input.is_null() { return Err(crate::error::Error::FailedToCreateObject); @@ -191,10 +192,10 @@ impl Terminal { while let Some(event) = inner.window.pop_event() { match event.code { - EventKind::Delete | EventKind::CloseRequested => { - if event.target == inner.window.get_object() { - running = false; - } + EventKind::Delete | EventKind::CloseRequested + if event.target == inner.window.as_object_mutable() => + { + running = false; } EventKind::Key => { if let Some(Key::Enter) = event.key { From 1e36f48abd95b95a3dba3acc1574c10409809c6e Mon Sep 17 00:00:00 2001 From: Alix ANNERAUD Date: Wed, 27 May 2026 22:54:27 +0200 Subject: [PATCH 07/18] Refactor command resolution logic for improved readability and consistency --- executables/shell/command_line/src/lib.rs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/executables/shell/command_line/src/lib.rs b/executables/shell/command_line/src/lib.rs index 7f9a6e17..14a9c492 100644 --- a/executables/shell/command_line/src/lib.rs +++ b/executables/shell/command_line/src/lib.rs @@ -125,14 +125,12 @@ impl Shell { None => return Ok(()), }; - let result = match next_positional { - command => match resolve_user_command(command) { - Some(user_command) => { - let mut context = ShellCommandContext::new(self); - dispatch_user_command(user_command, &mut context, &mut options, paths).await - } - None => self.execute(input, paths).await, - }, + let result = match resolve_user_command(next_positional) { + Some(user_command) => { + let mut context = ShellCommandContext::new(self); + dispatch_user_command(user_command, &mut context, &mut options, paths).await + } + None => self.execute(input, paths).await, }; if let Err(error) = result { From 15a181def29269c6e2e12ac32e5c72d6b9fa7c77 Mon Sep 17 00:00:00 2001 From: Alix ANNERAUD Date: Wed, 27 May 2026 22:54:36 +0200 Subject: [PATCH 08/18] Refactor graphics window handling to use NonNull for improved safety and clarity --- executables/wasm/build/utilities/context.rs | 1 + .../src/host/bindings/graphics/additionnal.rs | 59 ++++++++++--------- 2 files changed, 33 insertions(+), 27 deletions(-) diff --git a/executables/wasm/build/utilities/context.rs b/executables/wasm/build/utilities/context.rs index 8d956ea8..93b386a3 100644 --- a/executables/wasm/build/utilities/context.rs +++ b/executables/wasm/build/utilities/context.rs @@ -80,6 +80,7 @@ impl LvglContext { "lv_obj_null_on_delete", "lv_buttonmatrix_get_map", "lv_textarea_get_text", + "lv_obj_get_layer_type", ]; let signature_ident_str = signature.ident.to_string(); diff --git a/executables/wasm/src/host/bindings/graphics/additionnal.rs b/executables/wasm/src/host/bindings/graphics/additionnal.rs index 3b7ea6e3..d223feb4 100644 --- a/executables/wasm/src/host/bindings/graphics/additionnal.rs +++ b/executables/wasm/src/host/bindings/graphics/additionnal.rs @@ -1,4 +1,4 @@ -use core::ffi::CStr; +use core::{ffi::CStr, ptr::NonNull}; use xila::{ graphics::{self, Color, Window, lvgl}, @@ -16,9 +16,11 @@ pub unsafe fn object_delete(__translator: &mut Translator, object: WasmPointer) } pub unsafe fn window_create() -> *mut lvgl::lv_obj_t { - task::block_on(graphics::get_instance().create_window()) - .unwrap() - .into_raw() + let window = task::block_on(graphics::get_instance().create_window()).unwrap(); + + let window: NonNull = window.into(); + + window.as_ptr() as *mut lvgl::lv_obj_t } pub unsafe fn window_pop_event( @@ -27,9 +29,12 @@ pub unsafe fn window_pop_event( code: *mut u32, target: *mut WasmPointer, ) { - let mut window = unsafe { graphics::Window::from_raw(window) }; + let mut window = match unsafe { Window::from_raw(window) } { + Some(window) => window, + None => return, + }; - if let Some(event) = window.pop_event() { + if let Some(event) = unsafe { window.as_mut().pop_event() } { unsafe { *code = event.code as u32; @@ -38,48 +43,47 @@ pub unsafe fn window_pop_event( .unwrap_or(0); } } - - core::mem::forget(window); } pub unsafe fn window_get_event_code(window: *mut lvgl::lv_obj_t) -> u32 { - let window = unsafe { graphics::Window::from_raw(window) }; + let mut window = match unsafe { Window::from_raw(window) } { + Some(window) => window, + None => return graphics::EventKind::All as u32, + }; - let code = if let Some(event) = window.peek_event() { + if let Some(event) = unsafe { window.as_mut().peek_event() } { event.code as u32 } else { graphics::EventKind::All as u32 - }; - - core::mem::forget(window); - - code + } } pub unsafe fn window_get_event_target( __translator: &mut Translator, window: *mut lvgl::lv_obj_t, ) -> WasmPointer { - let window = unsafe { graphics::Window::from_raw(window) }; + let mut window = match unsafe { Window::from_raw(window) } { + Some(window) => window, + None => return 0, + }; - let target = if let Some(event) = window.peek_event() { + let target = if let Some(event) = unsafe { window.as_mut().peek_event() } { event.target } else { log::warning!("No event available for the window"); core::ptr::null_mut() }; - core::mem::forget(window); - unsafe { __translator.translate_to_guest(target, false).unwrap() } } pub unsafe fn window_next_event(window: *mut lvgl::lv_obj_t) { - let mut window = unsafe { Window::from_raw(window) }; - - window.pop_event(); + let mut window = match unsafe { Window::from_raw(window) } { + Some(window) => window, + None => return, + }; - core::mem::forget(window); + unsafe { window.as_mut().pop_event() }; } pub unsafe fn window_set_icon( @@ -87,14 +91,15 @@ pub unsafe fn window_set_icon( icon_string: *const core::ffi::c_char, icon_color: lvgl::lv_color_t, ) { - let mut window = unsafe { Window::from_raw(window) }; + let mut window = match unsafe { Window::from_raw(window) } { + Some(window) => window, + None => return, + }; let icon_string = unsafe { CStr::from_ptr(icon_string).to_str().unwrap() }; let icon_color = Color::from_lvgl_color(icon_color); - window.set_icon(icon_string, icon_color); - - core::mem::forget(window); + unsafe { window.as_mut().set_icon(icon_string, icon_color) }; } pub unsafe fn percentage(value: i32) -> i32 { From 136892ead3a3341031335401185dc67834bda7ab Mon Sep 17 00:00:00 2001 From: Alix ANNERAUD Date: Wed, 27 May 2026 22:54:41 +0200 Subject: [PATCH 09/18] Refactor format functions to simplify data handling and improve readability --- executables/weather/src/format.rs | 54 +++++++++---------------------- 1 file changed, 15 insertions(+), 39 deletions(-) diff --git a/executables/weather/src/format.rs b/executables/weather/src/format.rs index a8447d6b..4f586081 100644 --- a/executables/weather/src/format.rs +++ b/executables/weather/src/format.rs @@ -26,33 +26,21 @@ pub fn format_hourly_tab(hourly: Option<&HourlyWeather>) -> String { return String::from("No hourly data."); }; - let times = h.time.as_ref().map(|v| v.as_slice()).unwrap_or(&[]); - let temps = h - .temperature_2m - .as_ref() - .map(|v| v.as_slice()) - .unwrap_or(&[]); - let probs = h - .precipitation_probability - .as_ref() - .map(|v| v.as_slice()) - .unwrap_or(&[]); - let winds = h - .wind_speed_10m - .as_ref() - .map(|v| v.as_slice()) - .unwrap_or(&[]); + let times = h.time.as_deref().unwrap_or(&[]); + let temps = h.temperature_2m.as_deref().unwrap_or(&[]); + let probs = h.precipitation_probability.as_deref().unwrap_or(&[]); + let winds = h.wind_speed_10m.as_deref().unwrap_or(&[]); let mut out = String::from("Next 24h\n"); let count = core::cmp::min(times.len(), 24); - for i in 0..count { + for (i, time) in times.iter().enumerate().take(count) { let temp = temps.get(i).copied().unwrap_or_default(); let prob = probs.get(i).copied().unwrap_or_default(); let wind = winds.get(i).copied().unwrap_or_default(); out.push_str(&format!( "{} | {:.1} C | {}% rain | {:.1} km/h\n", - times[i], temp, prob, wind + time, temp, prob, wind )); } @@ -64,31 +52,19 @@ pub fn format_daily_tab(daily: Option<&DailyWeather>) -> String { return String::from("No daily data."); }; - let times = d.time.as_ref().map(|v| v.as_slice()).unwrap_or(&[]); - let maxs = d - .temperature_2m_max - .as_ref() - .map(|v| v.as_slice()) - .unwrap_or(&[]); - let mins = d - .temperature_2m_min - .as_ref() - .map(|v| v.as_slice()) - .unwrap_or(&[]); - let weather = d.weather_code.as_ref().map(|v| v.as_slice()).unwrap_or(&[]); - let precip = d - .precipitation_probability_max - .as_ref() - .map(|v| v.as_slice()) - .unwrap_or(&[]); - let sunrise = d.sunrise.as_ref().map(|v| v.as_slice()).unwrap_or(&[]); - let sunset = d.sunset.as_ref().map(|v| v.as_slice()).unwrap_or(&[]); + let times = d.time.as_deref().unwrap_or(&[]); + let maxs = d.temperature_2m_max.as_deref().unwrap_or(&[]); + let mins = d.temperature_2m_min.as_deref().unwrap_or(&[]); + let weather = d.weather_code.as_deref().unwrap_or(&[]); + let precip = d.precipitation_probability_max.as_deref().unwrap_or(&[]); + let sunrise = d.sunrise.as_deref().unwrap_or(&[]); + let sunset = d.sunset.as_deref().unwrap_or(&[]); let mut out = String::from("Next days\n"); - for i in 0..times.len().min(10) { + for (i, time) in times.iter().enumerate().take(10) { out.push_str(&format!( "{} | min {:.1} / max {:.1} C | code {} | rain {}%\n sunrise {} sunset {}\n", - times[i], + time, mins.get(i).copied().unwrap_or_default(), maxs.get(i).copied().unwrap_or_default(), weather.get(i).copied().unwrap_or_default(), From 0f9a06971ec2dc637a9aaa24183bfc01d4e008fe Mon Sep 17 00:00:00 2001 From: Alix ANNERAUD Date: Wed, 27 May 2026 23:02:27 +0200 Subject: [PATCH 10/18] Refactor clipboard event handling in KeyboardDevice for improved readability and efficiency --- drivers/wasm/src/devices/graphics/keyboard.rs | 5 ++--- drivers/wasm/src/devices/http_client.rs | 4 ++-- drivers/wasm/src/devices/time.rs | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/wasm/src/devices/graphics/keyboard.rs b/drivers/wasm/src/devices/graphics/keyboard.rs index 81b820ea..293142fb 100644 --- a/drivers/wasm/src/devices/graphics/keyboard.rs +++ b/drivers/wasm/src/devices/graphics/keyboard.rs @@ -79,14 +79,13 @@ impl KeyboardDevice { let sender = inner.0.sender(); let paste_closure = Closure::wrap(Box::new(move |event: ClipboardEvent| { - if let Some(clipboard_data) = event.clipboard_data() { - if let Ok(text) = clipboard_data.get_data("text") { + if let Some(clipboard_data) = event.clipboard_data() + && let Ok(text) = clipboard_data.get_data("text") { for char in text.chars() { Self::handle_key_press_char(sender, char, true); Self::handle_key_press_char(sender, char, false); } } - } }) as Box); window diff --git a/drivers/wasm/src/devices/http_client.rs b/drivers/wasm/src/devices/http_client.rs index 1a8ff830..939c080f 100644 --- a/drivers/wasm/src/devices/http_client.rs +++ b/drivers/wasm/src/devices/http_client.rs @@ -69,7 +69,7 @@ fn build_request<'a>(scheme: &str, request: HttpRequestParser<'a>) -> Option Result { @@ -78,7 +78,7 @@ fn build_headers_response(response: &web_sys::Response, buffer: &mut [u8]) -> Re // Status code let status = response.status(); builder - .add_status_code(status as u16) + .add_status_code(status) .ok_or(Error::InternalError)?; // Headers diff --git a/drivers/wasm/src/devices/time.rs b/drivers/wasm/src/devices/time.rs index 59212559..b159c3eb 100644 --- a/drivers/wasm/src/devices/time.rs +++ b/drivers/wasm/src/devices/time.rs @@ -69,7 +69,7 @@ impl DirectBaseOperations for TimeDevice { buffer[..duration_bytes.len()].copy_from_slice(duration_bytes); - Ok(duration_bytes.len().into()) + Ok(duration_bytes.len()) } fn write(&self, _: &[u8], _: Size) -> Result { From 2df3ff19ead251e8f18fe64d94a2d43a4a3444a7 Mon Sep 17 00:00:00 2001 From: Alix ANNERAUD Date: Wed, 27 May 2026 23:02:35 +0200 Subject: [PATCH 11/18] Refactor clipboard event handling in KeyboardDevice for improved clarity and safety --- drivers/wasm/src/devices/graphics/keyboard.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/wasm/src/devices/graphics/keyboard.rs b/drivers/wasm/src/devices/graphics/keyboard.rs index 293142fb..68b7756d 100644 --- a/drivers/wasm/src/devices/graphics/keyboard.rs +++ b/drivers/wasm/src/devices/graphics/keyboard.rs @@ -80,12 +80,13 @@ impl KeyboardDevice { let paste_closure = Closure::wrap(Box::new(move |event: ClipboardEvent| { if let Some(clipboard_data) = event.clipboard_data() - && let Ok(text) = clipboard_data.get_data("text") { - for char in text.chars() { - Self::handle_key_press_char(sender, char, true); - Self::handle_key_press_char(sender, char, false); - } + && let Ok(text) = clipboard_data.get_data("text") + { + for char in text.chars() { + Self::handle_key_press_char(sender, char, true); + Self::handle_key_press_char(sender, char, false); } + } }) as Box); window From 27e8f9394417762add82bf92bd47cb5a9a4998cc Mon Sep 17 00:00:00 2001 From: Alix ANNERAUD Date: Wed, 27 May 2026 23:02:44 +0200 Subject: [PATCH 12/18] Refactor window module to improve memory handling and simplify icon text initialization --- modules/graphics/src/window.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/graphics/src/window.rs b/modules/graphics/src/window.rs index a8ba2f56..dc5c28b8 100644 --- a/modules/graphics/src/window.rs +++ b/modules/graphics/src/window.rs @@ -3,7 +3,7 @@ use crate::{Color, Error, EventKind, Key, Result, event::Event, synchronous_lock use alloc::collections::VecDeque; use core::{ future::poll_fn, - mem::{ManuallyDrop, forget}, + mem::ManuallyDrop, ops::{Deref, DerefMut}, ptr::{self, NonNull}, str, @@ -67,7 +67,7 @@ unsafe extern "C" fn window_constructor( &mut (*window).event_queue, VecDeque::with_capacity(WINDOW_QUEUE_DEFAULT_CAPACITY), ); - ptr::write(&mut (*window).icon_text, [b'W', b'i']); + ptr::write(&mut (*window).icon_text, *b"Wi"); ptr::write(&mut (*window).icon_color, Color::BLACK); ptr::write(&mut (*window).waker_registration, AtomicWaker::new()); @@ -305,9 +305,9 @@ impl From> for OwnedWindow { } } -impl Into> for OwnedWindow { - fn into(self) -> NonNull { - let this = ManuallyDrop::new(self); +impl From for NonNull { + fn from(val: OwnedWindow) -> Self { + let this = ManuallyDrop::new(val); this.0 } } From 45508e7c23a5813ec8401d4738c3fd1dcaa7bdf1 Mon Sep 17 00:00:00 2001 From: Alix ANNERAUD Date: Wed, 27 May 2026 23:02:56 +0200 Subject: [PATCH 13/18] Refactor find_first_available_identifier to simplify range handling and improve readability --- modules/task/src/manager/utilities.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/modules/task/src/manager/utilities.rs b/modules/task/src/manager/utilities.rs index 7315d4de..9a56e969 100644 --- a/modules/task/src/manager/utilities.rs +++ b/modules/task/src/manager/utilities.rs @@ -16,14 +16,11 @@ impl Manager { RawIdentifier: Debug, { for key in map.keys() { - match range.next() { - Some(test_key) => { - if *key != test_key { - return Some(test_key.into()); - } + { + let test_key = range.next()?; + if *key != test_key { + return Some(test_key.into()); } - - None => return None, // No more identifiers to check } } From 558ab55fa7c23a20295996acf7cd1c5b78a31d1b Mon Sep 17 00:00:00 2001 From: Alix ANNERAUD Date: Wed, 27 May 2026 23:03:12 +0200 Subject: [PATCH 14/18] Refactor unmount logic in VirtualFileSystem to improve clarity and efficiency --- modules/virtual_file_system/src/file_system/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/virtual_file_system/src/file_system/mod.rs b/modules/virtual_file_system/src/file_system/mod.rs index 3c3d1164..3b305c15 100644 --- a/modules/virtual_file_system/src/file_system/mod.rs +++ b/modules/virtual_file_system/src/file_system/mod.rs @@ -175,14 +175,14 @@ impl VirtualFileSystem { unsafe { Box::from_raw(file_system.file_system as *const _ as *mut _) }; } - for (_, block_device) in block_devices.iter_mut() { + for block_device in block_devices.values_mut() { block_device.device.unmount()?; let _: Box = unsafe { Box::from_raw(block_device.device as *const _ as *mut _) }; } block_devices.clear(); - for (_, character_device) in character_devices.iter_mut() { + for character_device in character_devices.values_mut() { character_device.device.unmount()?; let _: Box = unsafe { Box::from_raw(character_device.device as *const _ as *mut _) }; From 0c45847747587abbe8c6223106e431d0446b5203 Mon Sep 17 00:00:00 2001 From: Alix ANNERAUD Date: Wed, 27 May 2026 23:03:18 +0200 Subject: [PATCH 15/18] Refactor error handling and improve readability in https_get function --- executables/weather/src/net.rs | 36 +++++++++++++++------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/executables/weather/src/net.rs b/executables/weather/src/net.rs index 54a5c23d..2cdc6b2b 100644 --- a/executables/weather/src/net.rs +++ b/executables/weather/src/net.rs @@ -8,8 +8,6 @@ use std::fs::OpenOptions; #[cfg(target_arch = "wasm32")] use std::io::{ErrorKind, Read, Write}; #[cfg(target_arch = "wasm32")] -use std::println; -#[cfg(target_arch = "wasm32")] use std::thread::{sleep, yield_now}; #[cfg(target_arch = "wasm32")] @@ -40,7 +38,7 @@ fn read_with_retry( sleep(std::time::Duration::from_millis(1)); } } - Err(error) => { + Err(_error) => { return Err(String::from(error_label)); } } @@ -167,7 +165,7 @@ pub fn https_get(url: &str) -> Result, String> { .read(true) .write(true) .open("/devices/https_client") - .map_err(|e| String::from("failed to open https device"))?; + .map_err(|_e| String::from("failed to open https device"))?; file.write_all(&request_buffer[..request_length]) .map_err(|_| String::from("failed to write request"))?; @@ -197,24 +195,24 @@ pub fn https_get(url: &str) -> Result, String> { let mut chunk = [0u8; 4096]; let mut retry_count = 0usize; loop { - if let Some(expected_length) = expected_body_length { - if body.len() >= expected_length { - break; - } + if let Some(expected_length) = expected_body_length + && body.len() >= expected_length + { + break; } let count = read_with_retry(&mut file, &mut chunk, "failed to read body")?; if count == 0 { - if let Some(expected_length) = expected_body_length { - if body.len() < expected_length { - retry_count += 1; - if retry_count >= HTTPS_READ_MAX_RETRIES { - return Err(String::from("timed out waiting for https response body")); - } - - yield_now(); - continue; + if let Some(expected_length) = expected_body_length + && body.len() < expected_length + { + retry_count += 1; + if retry_count >= HTTPS_READ_MAX_RETRIES { + return Err(String::from("timed out waiting for https response body")); } + + yield_now(); + continue; } break; @@ -225,9 +223,7 @@ pub fn https_get(url: &str) -> Result, String> { // Decode chunked transfer encoding if present let final_body = if has_chunked_encoding(&headers_buffer[..headers_len]) { - let decoded = decode_chunked_body(&body)?; - - decoded + decode_chunked_body(&body)? } else { body }; From 1f3f62f9b91d20bd526127c7fd7feb47ecb21d75 Mon Sep 17 00:00:00 2001 From: Alix ANNERAUD Date: Wed, 27 May 2026 23:03:26 +0200 Subject: [PATCH 16/18] Refactor MBR reading logic to simplify device reference handling --- examples/wasm/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/wasm/src/main.rs b/examples/wasm/src/main.rs index 856440a8..d00b89e9 100644 --- a/examples/wasm/src/main.rs +++ b/examples/wasm/src/main.rs @@ -86,7 +86,7 @@ async fn main() { let partition = Box::leak(Box::new(partition)); // Print MBR information - let mbr = Mbr::read_from_device(&*drive).unwrap(); + let mbr = Mbr::read_from_device(drive).unwrap(); log::information!("MBR Information: {mbr}"); // Mount the file system From ac514992ae2200342473f7a296c1bdaa10efb7df Mon Sep 17 00:00:00 2001 From: Alix ANNERAUD Date: Wed, 27 May 2026 23:09:05 +0200 Subject: [PATCH 17/18] Refactor generate_code function to simplify function call handling --- executables/wasm/build/host.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/executables/wasm/build/host.rs b/executables/wasm/build/host.rs index cb3622c2..a2bf5854 100644 --- a/executables/wasm/build/host.rs +++ b/executables/wasm/build/host.rs @@ -155,7 +155,7 @@ pub fn generate_code( }; unsafe { - let result = match __function { + match __function { #( #functions_call )* From 2f268bfcf744be6fe0c477dc10602f55d34e2c9e Mon Sep 17 00:00:00 2001 From: Alix ANNERAUD Date: Wed, 27 May 2026 23:23:44 +0200 Subject: [PATCH 18/18] Refactor window creation in graphics test to use mutable object reference --- modules/graphics/tests/graphics.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/graphics/tests/graphics.rs b/modules/graphics/tests/graphics.rs index 2daaf313..176a849b 100644 --- a/modules/graphics/tests/graphics.rs +++ b/modules/graphics/tests/graphics.rs @@ -54,9 +54,9 @@ async fn main() { .await .unwrap(); - let window = graphics.create_window().await.unwrap(); + let mut window = graphics.create_window().await.unwrap(); - let window = window.into_raw(); + let window = window.as_object_mutable(); let _calendar = unsafe { lvgl::lv_calendar_create(window) };