From 606166fca5ee928c8f27eafa1158c7f54a77d68a Mon Sep 17 00:00:00 2001 From: Nia Espera Date: Wed, 21 Jun 2023 14:05:31 +0200 Subject: [PATCH 1/8] auto drop objects, still wip --- lvgl-codegen/src/lib.rs | 8 +++--- lvgl/src/display.rs | 40 ++++++++++++++++-------------- lvgl/src/drivers/lv_drv_display.rs | 2 +- lvgl/src/drivers/lv_drv_input.rs | 6 +++-- lvgl/src/functions.rs | 15 +---------- lvgl/src/input_device/encoder.rs | 8 +++--- lvgl/src/input_device/pointer.rs | 8 +++--- lvgl/src/lib.rs | 9 +------ lvgl/src/lv_core/group.rs | 8 +++--- lvgl/src/lv_core/obj.rs | 22 ++++++++++------ lvgl/src/lv_core/screen.rs | 2 +- lvgl/src/mem.rs | 6 ++--- lvgl/src/misc/anim.rs | 8 +++--- 13 files changed, 71 insertions(+), 71 deletions(-) diff --git a/lvgl-codegen/src/lib.rs b/lvgl-codegen/src/lib.rs index ca97a8c6..967d9098 100644 --- a/lvgl-codegen/src/lib.rs +++ b/lvgl-codegen/src/lib.rs @@ -121,10 +121,10 @@ impl Rusty for LvFunc { } } - pub fn new() -> crate::LvResult { - let mut parent = crate::display::get_scr_act()?; - Self::create(&mut parent) - } + //pub fn new() -> crate::LvResult { + // let mut parent = crate::display::get_scr_act()?; + // Self::create(&mut parent) + //} }); } diff --git a/lvgl/src/display.rs b/lvgl/src/display.rs index 8284d944..e521ac86 100644 --- a/lvgl/src/display.rs +++ b/lvgl/src/display.rs @@ -1,6 +1,6 @@ use crate::functions::CoreError; -use crate::Screen; -use crate::{disp_drv_register, disp_get_default, get_str_act, NativeObject}; +use crate::{Screen, Widget}; +use crate::{disp_drv_register, disp_get_default, NativeObject}; use crate::{Box, Color}; use core::convert::TryInto; #[cfg(feature = "nightly")] @@ -40,7 +40,7 @@ type Result = result::Result; /// An LVGL-registered display. Equivalent to an `lv_disp_t`. pub struct Display { - pub(crate) disp: NonNull, + _disp: NonNull, drop: Option, } @@ -49,7 +49,7 @@ impl<'a> Display { disp: NonNull, drop: Option, ) -> Self { - Self { disp, drop } + Self { _disp: disp, drop } } /// Registers a given `DrawBuffer` with an associated update function to @@ -72,8 +72,11 @@ impl<'a> Display { } /// Returns the current active screen. - pub fn get_scr_act(&'a self) -> Result> { - Ok(get_str_act(Some(self))?.try_into()?) + pub fn get_scr_act(&'a self) -> Option> { + unsafe { + let ret = lvgl_sys::lv_disp_get_scr_act(&self as *const _ as *mut _); + Screen::from_raw(NonNull::new(ret)?) + } } /// Sets a `Screen` as currently active. @@ -155,11 +158,6 @@ impl Drop for Display { } } -/// Gets the active screen of the default display. -pub(crate) fn get_scr_act() -> Result> { - Ok(get_str_act(None)?.try_into()?) -} - /// A buffer of size `N` representing `N` pixels. `N` can be smaller than the /// entire number of pixels on the screen, in which case the screen will be /// drawn to multiple times per frame. @@ -389,24 +387,30 @@ mod tests { #[test] fn get_scr_act_return_display() { - tests::initialize_test(true); - let _screen = get_str_act(None).expect("We can get the active screen"); + tests::initialize_test(); + const REFRESH_BUFFER_SIZE: usize = 240 * 240 / 10; + let buffer = DrawBuffer::::default(); + let display = Display::register(buffer, 240, 240, |_| {}).unwrap(); + let _screen = display.get_scr_act(); } #[test] fn get_default_display() { - tests::initialize_test(true); - let display = Display::default(); + tests::initialize_test(); + const REFRESH_BUFFER_SIZE: usize = 240 * 240 / 10; + let buffer = DrawBuffer::::default(); + let display = Display::register(buffer, 240, 240, |_| {}).unwrap(); let _screen_direct = display .get_scr_act() .expect("Return screen directly from the display instance"); - let _screen_default = get_scr_act().expect("Return screen from the default display"); } #[test] fn register_display_directly() -> Result<()> { - crate::tests::initialize_test(true); - let display = Display::default(); + crate::tests::initialize_test(); + const REFRESH_BUFFER_SIZE: usize = 240 * 240 / 10; + let buffer = DrawBuffer::::default(); + let display = Display::register(buffer, 240, 240, |_| {}).unwrap(); let _screen = display .get_scr_act() .expect("Return screen directly from the display instance"); diff --git a/lvgl/src/drivers/lv_drv_display.rs b/lvgl/src/drivers/lv_drv_display.rs index b8803c6d..03282ba0 100644 --- a/lvgl/src/drivers/lv_drv_display.rs +++ b/lvgl/src/drivers/lv_drv_display.rs @@ -274,7 +274,7 @@ mod tests { fn gtk_test() { const HOR_RES: u32 = 240; const VER_RES: u32 = 240; - tests::initialize_test(false); + tests::initialize_test(); let buffer = DrawBuffer::<{ (HOR_RES * VER_RES) as usize }>::default(); let _disp = lv_drv_disp_sdl!(buffer, HOR_RES, VER_RES).unwrap(); } diff --git a/lvgl/src/drivers/lv_drv_input.rs b/lvgl/src/drivers/lv_drv_input.rs index f3fd41c4..85d6c56b 100644 --- a/lvgl/src/drivers/lv_drv_input.rs +++ b/lvgl/src/drivers/lv_drv_input.rs @@ -88,8 +88,10 @@ mod tests { #[test] fn gtk_test() { - tests::initialize_test(true); - let disp = Display::default(); + tests::initialize_test(); + const REFRESH_BUFFER_SIZE: usize = 240 * 240 / 10; + let buffer = DrawBuffer::::default(); + let disp = Display::register(buffer, 240, 240, |_| {}).unwrap(); let _input = lv_drv_input_pointer_sdl!(disp); } } diff --git a/lvgl/src/functions.rs b/lvgl/src/functions.rs index ca19e2c2..06d693d6 100644 --- a/lvgl/src/functions.rs +++ b/lvgl/src/functions.rs @@ -1,6 +1,6 @@ use crate::display::{Display, DisplayDriver}; use crate::input_device::InputDriver; -use crate::{Event, LvError, LvResult, Obj, Widget}; +use crate::{Event, LvError, LvResult, Widget}; use core::ptr::NonNull; #[cfg(not(feature = "rust_timer"))] use core::time::Duration; @@ -38,19 +38,6 @@ pub(crate) fn disp_get_default() -> Result { )) } -pub(crate) fn get_str_act(disp: Option<&Display>) -> Result { - let scr_ptr = unsafe { - lvgl_sys::lv_disp_get_scr_act( - disp.map(|d| d.disp.as_ptr()) - .unwrap_or(ptr::null_mut() as *mut lvgl_sys::lv_disp_t), - ) - }; - match unsafe { Obj::from_raw(NonNull::new(scr_ptr).ok_or(CoreError::ResourceNotAvailable)?) } { - Some(o) => Ok(o), - None => Err(CoreError::OperationFailed), - } -} - /// Runs an LVGL tick lasting a given `core::time::Duration`. This function /// should be called periodically. #[inline] diff --git a/lvgl/src/input_device/encoder.rs b/lvgl/src/input_device/encoder.rs index 97700f14..37920a69 100644 --- a/lvgl/src/input_device/encoder.rs +++ b/lvgl/src/input_device/encoder.rs @@ -173,7 +173,7 @@ unsafe extern "C" fn feedback(_indev_drv: *mut lvgl_sys::lv_indev_drv_t, _code: #[cfg(test)] mod test { use super::*; - use crate::Display; + use crate::{Display, DrawBuffer}; use core::marker::PhantomData; use embedded_graphics::draw_target::DrawTarget; use embedded_graphics::geometry::Size; @@ -214,8 +214,10 @@ mod test { #[test] fn encoder_input_device() { - crate::tests::initialize_test(true); - let display = Display::default(); + crate::tests::initialize_test(); + const REFRESH_BUFFER_SIZE: usize = 240 * 240 / 10; + let buffer = DrawBuffer::::default(); + let display = Display::register(buffer, 240, 240, |_| {}).unwrap(); fn read_encoder_device() -> BufferStatus { EncoderInputData::Press.pressed().once() diff --git a/lvgl/src/input_device/pointer.rs b/lvgl/src/input_device/pointer.rs index 97905ea3..3665d899 100644 --- a/lvgl/src/input_device/pointer.rs +++ b/lvgl/src/input_device/pointer.rs @@ -178,7 +178,7 @@ unsafe extern "C" fn feedback(_indev_drv: *mut lvgl_sys::lv_indev_drv_t, _code: #[cfg(test)] mod test { use super::*; - use crate::Display; + use crate::{Display, DrawBuffer}; use core::marker::PhantomData; use embedded_graphics::draw_target::DrawTarget; use embedded_graphics::geometry::Size; @@ -219,8 +219,10 @@ mod test { #[test] fn pointer_input_device() { - crate::tests::initialize_test(true); - let display = Display::default(); + crate::tests::initialize_test(); + const REFRESH_BUFFER_SIZE: usize = 240 * 240 / 10; + let buffer = DrawBuffer::::default(); + let display = Display::register(buffer, 240, 240, |_| {}).unwrap(); fn read_touchpad_device() -> BufferStatus { PointerInputData::Touch(Point::new(120, 23)) diff --git a/lvgl/src/lib.rs b/lvgl/src/lib.rs index 8a0638fe..3b8cf15c 100644 --- a/lvgl/src/lib.rs +++ b/lvgl/src/lib.rs @@ -114,15 +114,8 @@ fn once_init() { #[cfg(test)] pub(crate) mod tests { - use crate::display::{Display, DrawBuffer}; - - pub(crate) fn initialize_test(buf: bool) { + pub(crate) fn initialize_test() { unsafe { crate::deinit() }; crate::init(); - if buf { - const REFRESH_BUFFER_SIZE: usize = 240 * 240 / 10; - let buffer = DrawBuffer::::default(); - let _ = Display::register(buffer, 240, 240, |_| {}).unwrap(); - } } } diff --git a/lvgl/src/lv_core/group.rs b/lvgl/src/lv_core/group.rs index 53053def..a1a46771 100644 --- a/lvgl/src/lv_core/group.rs +++ b/lvgl/src/lv_core/group.rs @@ -26,7 +26,7 @@ impl Group { } /// Adds an object to the group. - pub fn add_obj(&mut self, obj: &impl NativeObject) -> LvResult<()> { + pub fn add_obj(&mut self, obj: &mut impl NativeObject) -> LvResult<()> { unsafe { lvgl_sys::lv_group_add_obj(self.raw()?.as_mut(), obj.raw().as_mut()) } Ok(()) } @@ -64,12 +64,12 @@ mod test { fn group_test() { const HOR_RES: u32 = 240; const VER_RES: u32 = 240; - crate::tests::initialize_test(false); + crate::tests::initialize_test(); let buffer = DrawBuffer::<{ (HOR_RES * VER_RES) as usize }>::default(); let display = Display::register(buffer, HOR_RES, VER_RES, |_| {}).unwrap(); let mut screen = display.get_scr_act().unwrap(); let mut group = Group::default(); - let btn = Btn::create(&mut screen).unwrap(); - group.add_obj(&btn).unwrap(); + let mut btn = Btn::create(&mut screen).unwrap(); + group.add_obj(&mut btn).unwrap(); } } diff --git a/lvgl/src/lv_core/obj.rs b/lvgl/src/lv_core/obj.rs index 433ca537..fba744bf 100644 --- a/lvgl/src/lv_core/obj.rs +++ b/lvgl/src/lv_core/obj.rs @@ -29,6 +29,14 @@ pub struct Obj<'a> { dependents: PhantomData<&'a isize>, } +impl Drop for Obj<'_> { + fn drop(&mut self) { + unsafe { + lvgl_sys::lv_obj_del(self.raw().as_mut()) + } + } +} + impl Debug for Obj<'_> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("NativeObject") @@ -43,7 +51,7 @@ impl<'a> Obj<'a> { pub fn create(parent: &'a mut impl NativeObject) -> LvResult { unsafe { let ptr = lvgl_sys::lv_obj_create(parent.raw().as_mut()); - if let Some(nn_ptr) = ptr::NonNull::new(ptr) { + if let Some(nn_ptr) = NonNull::new(ptr) { //(*ptr).user_data = Box::new(UserDataObj::empty()).into_raw() as *mut _; Ok(Self { raw: nn_ptr, @@ -55,10 +63,10 @@ impl<'a> Obj<'a> { } } - pub fn new() -> crate::LvResult { - let mut parent = crate::display::get_scr_act()?; - Self::create(unsafe { &mut *(&mut parent as *mut _) }) - } + //pub fn new() -> crate::LvResult { + // let mut parent = crate::display::get_scr_act()?; + // Self::create(unsafe { &mut *(&mut parent as *mut _) }) + //} pub fn blank() -> LvResult { match NonNull::new(unsafe { lvgl_sys::lv_obj_create(ptr::null_mut()) }) { @@ -72,7 +80,7 @@ impl<'a> Obj<'a> { } impl NativeObject for Obj<'_> { - fn raw(&self) -> ptr::NonNull { + fn raw(&self) -> NonNull { self.raw } } @@ -89,7 +97,7 @@ pub trait Widget<'a>: NativeObject + Sized + 'a { /// If the pointer is derived from a Rust-instantiated `obj` such as via /// calling `.raw()`, only the `obj` that survives longest may be dropped /// and the caller is responsible for ensuring data races do not occur. - unsafe fn from_raw(raw_pointer: ptr::NonNull) -> Option; + unsafe fn from_raw(raw_pointer: NonNull) -> Option; /// Adds a `Style` to a given widget. fn add_style(&mut self, part: Self::Part, style: &'a mut Style) { diff --git a/lvgl/src/lv_core/screen.rs b/lvgl/src/lv_core/screen.rs index ef87065b..279f68cf 100644 --- a/lvgl/src/lv_core/screen.rs +++ b/lvgl/src/lv_core/screen.rs @@ -69,7 +69,7 @@ mod test { fn screen_test() { const HOR_RES: u32 = 240; const VER_RES: u32 = 240; - crate::tests::initialize_test(false); + crate::tests::initialize_test(); let buffer = DrawBuffer::<{ (HOR_RES * VER_RES) as usize }>::default(); let display = Display::register(buffer, HOR_RES, VER_RES, |_| {}).unwrap(); let mut screen_old = display.get_scr_act().unwrap(); diff --git a/lvgl/src/mem.rs b/lvgl/src/mem.rs index 176185b6..e724d4a1 100644 --- a/lvgl/src/mem.rs +++ b/lvgl/src/mem.rs @@ -127,7 +127,7 @@ mod test { #[test] fn place_value_in_lv_mem() { - tests::initialize_test(false); + tests::initialize_test(); let v = Box::new(5); drop(v); @@ -137,7 +137,7 @@ mod test { #[test] fn place_complex_value_in_lv_mem() { - tests::initialize_test(false); + tests::initialize_test(); #[repr(C)] #[derive(Debug)] @@ -189,7 +189,7 @@ mod test { #[test] fn clone_object_in_lv_mem() { - crate::tests::initialize_test(false); + crate::tests::initialize_test(); let v1 = Box::new(5); let v2 = v1.clone(); diff --git a/lvgl/src/misc/anim.rs b/lvgl/src/misc/anim.rs index 206e9a93..550ca19a 100644 --- a/lvgl/src/misc/anim.rs +++ b/lvgl/src/misc/anim.rs @@ -127,12 +127,14 @@ where mod test { use super::*; use crate::widgets::Btn; - use crate::Display; + use crate::{Display, DrawBuffer}; #[test] fn anim_test() { - crate::tests::initialize_test(true); - let display = Display::default(); + crate::tests::initialize_test(); + const REFRESH_BUFFER_SIZE: usize = 240 * 240 / 10; + let buffer = DrawBuffer::::default(); + let display = Display::register(buffer, 240, 240, |_| {}).unwrap(); let mut screen = display.get_scr_act().unwrap(); let mut btn = Btn::create(&mut screen).unwrap(); let mut anim = From 08f0be563eecf34014e6c4115228330c02806cac Mon Sep 17 00:00:00 2001 From: Nia Espera Date: Wed, 21 Jun 2023 14:14:42 +0200 Subject: [PATCH 2/8] fmt --- lvgl/src/display.rs | 2 +- lvgl/src/lv_core/obj.rs | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/lvgl/src/display.rs b/lvgl/src/display.rs index e521ac86..418cd268 100644 --- a/lvgl/src/display.rs +++ b/lvgl/src/display.rs @@ -1,7 +1,7 @@ use crate::functions::CoreError; -use crate::{Screen, Widget}; use crate::{disp_drv_register, disp_get_default, NativeObject}; use crate::{Box, Color}; +use crate::{Screen, Widget}; use core::convert::TryInto; #[cfg(feature = "nightly")] use core::error::Error; diff --git a/lvgl/src/lv_core/obj.rs b/lvgl/src/lv_core/obj.rs index fba744bf..552da15d 100644 --- a/lvgl/src/lv_core/obj.rs +++ b/lvgl/src/lv_core/obj.rs @@ -31,9 +31,7 @@ pub struct Obj<'a> { impl Drop for Obj<'_> { fn drop(&mut self) { - unsafe { - lvgl_sys::lv_obj_del(self.raw().as_mut()) - } + unsafe { lvgl_sys::lv_obj_del(self.raw().as_mut()) } } } From 1ada590af51fa1eaac0b43616cc3b6f589de08f3 Mon Sep 17 00:00:00 2001 From: Nia Espera Date: Wed, 21 Jun 2023 15:02:38 +0200 Subject: [PATCH 3/8] lifetime on display --- lvgl/src/display.rs | 40 ++++++++++++++++++++++++++-------------- lvgl/src/functions.rs | 14 +++++++------- 2 files changed, 33 insertions(+), 21 deletions(-) diff --git a/lvgl/src/display.rs b/lvgl/src/display.rs index 418cd268..8da000fa 100644 --- a/lvgl/src/display.rs +++ b/lvgl/src/display.rs @@ -1,11 +1,12 @@ use crate::functions::CoreError; -use crate::{disp_drv_register, disp_get_default, NativeObject}; +use crate::{disp_drv_register, NativeObject}; use crate::{Box, Color}; use crate::{Screen, Widget}; use core::convert::TryInto; #[cfg(feature = "nightly")] use core::error::Error; use core::fmt; +use core::marker::PhantomData; use core::mem::{ManuallyDrop, MaybeUninit}; use core::pin::Pin; use core::ptr::NonNull; @@ -39,17 +40,22 @@ impl Error for DisplayError {} type Result = result::Result; /// An LVGL-registered display. Equivalent to an `lv_disp_t`. -pub struct Display { +pub struct Display<'a> { _disp: NonNull, drop: Option, + _screens: PhantomData<&'a Screen<'a>>, } -impl<'a> Display { +impl<'a> Display<'a> { pub(crate) fn from_raw( disp: NonNull, drop: Option, ) -> Self { - Self { _disp: disp, drop } + Self { + _disp: disp, + drop, + _screens: PhantomData, + } } /// Registers a given `DrawBuffer` with an associated update function to @@ -63,11 +69,14 @@ impl<'a> Display { where F: FnMut(&DisplayRefresh) + 'a, { - let mut display_diver = DisplayDriver::new(draw_buffer, display_update)?; - let disp_p = &mut display_diver.disp_drv; + let mut display_driver = DisplayDriver::new(draw_buffer, display_update)?; + let disp_p = &mut display_driver.disp_drv; disp_p.hor_res = hor_res.try_into().unwrap_or(240); disp_p.ver_res = ver_res.try_into().unwrap_or(240); - Ok(disp_drv_register(&mut display_diver, None)?) + Ok(disp_drv_register::( + unsafe { &mut *(&mut display_driver as *mut _ as *mut _) }, + None, + )?) //display_diver.disp_drv.leak(); } @@ -140,17 +149,20 @@ impl<'a> Display { let disp_p = &mut display_driver.disp_drv; disp_p.hor_res = hor_res.try_into().unwrap_or(240); disp_p.ver_res = ver_res.try_into().unwrap_or(240); - Ok(disp_drv_register(&mut display_driver, drop)?) + Ok(disp_drv_register::( + unsafe { &mut *(&mut display_driver as *mut _ as *mut _) }, + drop, + )?) } } -impl Default for Display { - fn default() -> Self { - disp_get_default().expect("LVGL must be INITIALIZED") - } -} +//impl Default for Display<'_> { +// fn default() -> Self { +// disp_get_default().expect("LVGL must be INITIALIZED") +// } +//} -impl Drop for Display { +impl Drop for Display<'_> { fn drop(&mut self) { if let Some(drop) = self.drop { unsafe { drop() } diff --git a/lvgl/src/functions.rs b/lvgl/src/functions.rs index 06d693d6..0b8e68a6 100644 --- a/lvgl/src/functions.rs +++ b/lvgl/src/functions.rs @@ -30,13 +30,13 @@ pub(crate) fn disp_drv_register( )) } -pub(crate) fn disp_get_default() -> Result { - let disp_ptr = unsafe { lvgl_sys::lv_disp_get_default() }; - Ok(Display::from_raw( - NonNull::new(disp_ptr).ok_or(CoreError::OperationFailed)?, - None, - )) -} +//pub(crate) fn disp_get_default() -> Result { +// let disp_ptr = unsafe { lvgl_sys::lv_disp_get_default() }; +// Ok(Display::from_raw( +// NonNull::new(disp_ptr).ok_or(CoreError::OperationFailed)?, +// None, +// )) +//} /// Runs an LVGL tick lasting a given `core::time::Duration`. This function /// should be called periodically. From dfb8b218e2ed0adf85385e94f713e7f0b06fd96e Mon Sep 17 00:00:00 2001 From: Nia Espera Date: Wed, 21 Jun 2023 15:51:11 +0200 Subject: [PATCH 4/8] still broken as hell --- examples/sdl.rs | 10 +-- lvgl/src/display.rs | 117 +++++++++++++++++++++-------- lvgl/src/drivers/lv_drv_display.rs | 22 +++--- lvgl/src/drivers/lv_drv_input.rs | 2 +- lvgl/src/input_device/encoder.rs | 2 +- lvgl/src/input_device/pointer.rs | 2 +- lvgl/src/lv_core/group.rs | 3 +- lvgl/src/lv_core/obj.rs | 2 +- lvgl/src/lv_core/screen.rs | 3 +- lvgl/src/misc/anim.rs | 4 +- lvgl/src/widgets/label.rs | 40 +++------- 11 files changed, 118 insertions(+), 89 deletions(-) diff --git a/examples/sdl.rs b/examples/sdl.rs index 1c14f1a6..6dd9d818 100644 --- a/examples/sdl.rs +++ b/examples/sdl.rs @@ -19,15 +19,13 @@ fn main() -> LvResult<()> { const HOR_RES: u32 = 240; const VER_RES: u32 = 240; + let mut screen_style = Style::default(); + screen_style.set_bg_color(Color::from_rgb((0, 0, 0))); + let buffer = DrawBuffer::<{ (HOR_RES * VER_RES) as usize }>::default(); - let display = lv_drv_disp_sdl!(buffer, HOR_RES, VER_RES)?; + let (display, mut screen) = lv_drv_disp_sdl!(buffer, HOR_RES, VER_RES)?; let _input = lv_drv_input_pointer_sdl!(display)?; - // Create screen and widgets - let mut screen = display.get_scr_act()?; - - let mut screen_style = Style::default(); - screen_style.set_bg_color(Color::from_rgb((0, 0, 0))); screen.add_style(Part::Main, &mut screen_style); // Create the button let mut button = Btn::create(&mut screen)?; diff --git a/lvgl/src/display.rs b/lvgl/src/display.rs index 8da000fa..84355977 100644 --- a/lvgl/src/display.rs +++ b/lvgl/src/display.rs @@ -41,7 +41,7 @@ type Result = result::Result; /// An LVGL-registered display. Equivalent to an `lv_disp_t`. pub struct Display<'a> { - _disp: NonNull, + disp: NonNull, drop: Option, _screens: PhantomData<&'a Screen<'a>>, } @@ -52,7 +52,7 @@ impl<'a> Display<'a> { drop: Option, ) -> Self { Self { - _disp: disp, + disp, drop, _screens: PhantomData, } @@ -65,7 +65,7 @@ impl<'a> Display<'a> { hor_res: u32, ver_res: u32, display_update: F, - ) -> Result + ) -> Result<(Self, Screen<'a>)> where F: FnMut(&DisplayRefresh) + 'a, { @@ -73,15 +73,30 @@ impl<'a> Display<'a> { let disp_p = &mut display_driver.disp_drv; disp_p.hor_res = hor_res.try_into().unwrap_or(240); disp_p.ver_res = ver_res.try_into().unwrap_or(240); - Ok(disp_drv_register::( + let disp = disp_drv_register::( unsafe { &mut *(&mut display_driver as *mut _ as *mut _) }, None, - )?) + )?; + let scr = unsafe { + Screen::from_raw( + NonNull::new(lvgl_sys::lv_disp_get_scr_act(disp.disp.as_ptr())) + .ok_or(DisplayError::FailedToRegister)?, + ) + .ok_or(DisplayError::FailedToRegister)? + }; + Ok((disp, scr)) //display_diver.disp_drv.leak(); } /// Returns the current active screen. - pub fn get_scr_act(&'a self) -> Option> { + /// + /// # Safety + /// + /// This function should only be called if the resulting `Screen` was not + /// previously instantiated (i.e. the display was registered with + /// `register_raw()`) or the resulting screen is never in conflict with the + /// other screen which holds the same underlying value. + pub unsafe fn get_scr_act(&'a self) -> Option> { unsafe { let ret = lvgl_sys::lv_disp_get_scr_act(&self as *const _ as *mut _); Screen::from_raw(NonNull::new(ret)?) @@ -94,6 +109,65 @@ impl<'a> Display<'a> { unsafe { lvgl_sys::lv_disp_load_scr(scr_ptr) } } + pub fn is_scr_act(&self, screen: &Screen) -> bool { + unsafe { + let act = self.get_scr_act().map(|s| { + s.raw().as_ptr() as usize + }).unwrap_or(0); + let given = screen.raw().as_ptr() as usize; + act == given + } + } + + /// Same as `register_raw`, but also returns the original screen. Intended + /// for use within display-initializing macros. + /// + /// # Safety + /// + /// See `register_raw()`. + pub unsafe fn register_raw_macro(draw_buffer: DrawBuffer, + hor_res: u32, + ver_res: u32, + flush_cb: Option< + unsafe extern "C" fn( + *mut lvgl_sys::lv_disp_drv_t, + *const lvgl_sys::lv_area_t, + *mut lvgl_sys::lv_color_t, + ), + >, + rounder_cb: Option< + unsafe extern "C" fn(*mut lvgl_sys::lv_disp_drv_t, *mut lvgl_sys::lv_area_t), + >, + set_px_cb: Option< + unsafe extern "C" fn( + *mut lvgl_sys::lv_disp_drv_t, + *mut u8, + lvgl_sys::lv_coord_t, + lvgl_sys::lv_coord_t, + lvgl_sys::lv_coord_t, + lvgl_sys::lv_color_t, + lvgl_sys::lv_opa_t, + ), + >, + clear_cb: Option, + monitor_cb: Option, + wait_cb: Option, + clean_dcache_cb: Option, + drv_update_cb: Option, + render_start_cb: Option, + drop: Option, + ) -> Result<(Self, Screen<'a>)> { + let disp = unsafe { + Display::register_raw(draw_buffer, hor_res, ver_res, flush_cb, rounder_cb, set_px_cb, clear_cb, monitor_cb, wait_cb, clean_dcache_cb, drv_update_cb, render_start_cb, drop)? + }; + let scr = Screen::from_raw( + NonNull::new(lvgl_sys::lv_disp_get_scr_act(disp.disp.as_ptr())) + .ok_or(DisplayError::FailedToRegister)?, + ) + .ok_or(DisplayError::FailedToRegister)?; + Ok((disp, scr)) + } + /// Registers a display from raw functions and values. /// /// # Safety @@ -398,34 +472,13 @@ mod tests { use crate::tests; #[test] - fn get_scr_act_return_display() { + fn register_display_and_screen() { tests::initialize_test(); const REFRESH_BUFFER_SIZE: usize = 240 * 240 / 10; let buffer = DrawBuffer::::default(); - let display = Display::register(buffer, 240, 240, |_| {}).unwrap(); - let _screen = display.get_scr_act(); - } - - #[test] - fn get_default_display() { - tests::initialize_test(); - const REFRESH_BUFFER_SIZE: usize = 240 * 240 / 10; - let buffer = DrawBuffer::::default(); - let display = Display::register(buffer, 240, 240, |_| {}).unwrap(); - let _screen_direct = display - .get_scr_act() - .expect("Return screen directly from the display instance"); - } - - #[test] - fn register_display_directly() -> Result<()> { - crate::tests::initialize_test(); - const REFRESH_BUFFER_SIZE: usize = 240 * 240 / 10; - let buffer = DrawBuffer::::default(); - let display = Display::register(buffer, 240, 240, |_| {}).unwrap(); - let _screen = display - .get_scr_act() - .expect("Return screen directly from the display instance"); - Ok(()) + let (_display, _screen) = Display::register(buffer, 240, 240, |_| {}).unwrap(); + //let _screen_direct = display + // .get_scr_act() + // .expect("Return screen directly from the display instance"); } } diff --git a/lvgl/src/drivers/lv_drv_display.rs b/lvgl/src/drivers/lv_drv_display.rs index 03282ba0..cc1e1e08 100644 --- a/lvgl/src/drivers/lv_drv_display.rs +++ b/lvgl/src/drivers/lv_drv_display.rs @@ -3,7 +3,7 @@ macro_rules! lv_drv_disp_fbdev { ($draw_buffer:ident, $hor_res:ident, $ver_res:ident) => { unsafe { lvgl_sys::fbdev_init(); - $crate::Display::register_raw( + $crate::Display::register_raw_macro( $draw_buffer, $hor_res, $ver_res, @@ -27,7 +27,7 @@ macro_rules! lv_drv_disp_drm { ($draw_buffer:ident, $hor_res:ident, $ver_res:ident) => { unsafe { lvgl_sys::drm_init(); - $crate::Display::register_raw( + $crate::Display::register_raw_macro( $draw_buffer, $hor_res, $ver_res, @@ -51,7 +51,7 @@ macro_rules! lv_drv_disp_gtk { ($draw_buffer:ident, $hor_res:ident, $ver_res:ident) => { unsafe { lvgl_sys::gtkdrv_init(); - $crate::Display::register_raw( + $crate::Display::register_raw_macro( $draw_buffer, $hor_res, $ver_res, @@ -75,7 +75,7 @@ macro_rules! lv_drv_disp_sdl { ($draw_buffer:ident, $hor_res:ident, $ver_res:ident) => { unsafe { lvgl_sys::sdl_init(); - $crate::Display::register_raw( + $crate::Display::register_raw_macro( $draw_buffer, $hor_res, $ver_res, @@ -102,7 +102,7 @@ macro_rules! lv_drv_disp_gc9a01 { 0 => (), c = panic!("GC9A01_init() returned error code {c}") }; - $crate::Display::register_raw( + $crate::Display::register_raw_macro( $draw_buffer, $hor_res, $ver_res, @@ -126,7 +126,7 @@ macro_rules! lv_drv_disp_ili9341 { ($draw_buffer:ident, $hor_res:ident, $ver_res:ident) => { unsafe { lvgl_sys::ili9341_init(); - $crate::Display::register_raw( + $crate::Display::register_raw_macro( $draw_buffer, $hor_res, $ver_res, @@ -150,7 +150,7 @@ macro_rules! lv_drv_disp_r61581 { ($draw_buffer:ident, $hor_res:ident, $ver_res:ident) => { unsafe { lvgl_sys::r61581_init(); - $crate::Display::register_raw( + $crate::Display::register_raw_macro( $draw_buffer, $hor_res, $ver_res, @@ -174,7 +174,7 @@ macro_rules! lv_drv_disp_sharp_mip { ($draw_buffer:ident, $hor_res:ident, $ver_res:ident) => { unsafe { lvgl_sys::sharp_mip_init(); - $crate::Display::register_raw( + $crate::Display::register_raw_macro( $draw_buffer, $hor_res, $ver_res, @@ -198,7 +198,7 @@ macro_rules! lv_drv_disp_ssd1963 { ($draw_buffer:ident, $hor_res:ident, $ver_res:ident) => { unsafe { lvgl_sys::ssd1963_init(); - $crate::Display::register_raw( + $crate::Display::register_raw_macro( $draw_buffer, $hor_res, $ver_res, @@ -222,7 +222,7 @@ macro_rules! lv_drv_disp_st7565 { ($draw_buffer:ident, $hor_res:ident, $ver_res:ident) => { unsafe { lvgl_sys::st7565_init(); - $crate::Display::register_raw( + $crate::Display::register_raw_macro( $draw_buffer, $hor_res, $ver_res, @@ -246,7 +246,7 @@ macro_rules! lv_drv_disp_uc1610 { ($draw_buffer:ident, $hor_res:ident, $ver_res:ident) => { unsafe { lvgl_sys::uc1610_init(); - $crate::Display::register_raw( + $crate::Display::register_raw_macro( $draw_buffer, $hor_res, $ver_res, diff --git a/lvgl/src/drivers/lv_drv_input.rs b/lvgl/src/drivers/lv_drv_input.rs index 85d6c56b..eaa606e0 100644 --- a/lvgl/src/drivers/lv_drv_input.rs +++ b/lvgl/src/drivers/lv_drv_input.rs @@ -91,7 +91,7 @@ mod tests { tests::initialize_test(); const REFRESH_BUFFER_SIZE: usize = 240 * 240 / 10; let buffer = DrawBuffer::::default(); - let disp = Display::register(buffer, 240, 240, |_| {}).unwrap(); + let (disp, _) = Display::register(buffer, 240, 240, |_| {}).unwrap(); let _input = lv_drv_input_pointer_sdl!(disp); } } diff --git a/lvgl/src/input_device/encoder.rs b/lvgl/src/input_device/encoder.rs index 37920a69..87e3c70f 100644 --- a/lvgl/src/input_device/encoder.rs +++ b/lvgl/src/input_device/encoder.rs @@ -217,7 +217,7 @@ mod test { crate::tests::initialize_test(); const REFRESH_BUFFER_SIZE: usize = 240 * 240 / 10; let buffer = DrawBuffer::::default(); - let display = Display::register(buffer, 240, 240, |_| {}).unwrap(); + let (display, _) = Display::register(buffer, 240, 240, |_| {}).unwrap(); fn read_encoder_device() -> BufferStatus { EncoderInputData::Press.pressed().once() diff --git a/lvgl/src/input_device/pointer.rs b/lvgl/src/input_device/pointer.rs index 3665d899..e68154f4 100644 --- a/lvgl/src/input_device/pointer.rs +++ b/lvgl/src/input_device/pointer.rs @@ -222,7 +222,7 @@ mod test { crate::tests::initialize_test(); const REFRESH_BUFFER_SIZE: usize = 240 * 240 / 10; let buffer = DrawBuffer::::default(); - let display = Display::register(buffer, 240, 240, |_| {}).unwrap(); + let (display, _) = Display::register(buffer, 240, 240, |_| {}).unwrap(); fn read_touchpad_device() -> BufferStatus { PointerInputData::Touch(Point::new(120, 23)) diff --git a/lvgl/src/lv_core/group.rs b/lvgl/src/lv_core/group.rs index a1a46771..aa672830 100644 --- a/lvgl/src/lv_core/group.rs +++ b/lvgl/src/lv_core/group.rs @@ -66,8 +66,7 @@ mod test { const VER_RES: u32 = 240; crate::tests::initialize_test(); let buffer = DrawBuffer::<{ (HOR_RES * VER_RES) as usize }>::default(); - let display = Display::register(buffer, HOR_RES, VER_RES, |_| {}).unwrap(); - let mut screen = display.get_scr_act().unwrap(); + let (_display, mut screen) = Display::register(buffer, HOR_RES, VER_RES, |_| {}).unwrap(); let mut group = Group::default(); let mut btn = Btn::create(&mut screen).unwrap(); group.add_obj(&mut btn).unwrap(); diff --git a/lvgl/src/lv_core/obj.rs b/lvgl/src/lv_core/obj.rs index 552da15d..f33ea165 100644 --- a/lvgl/src/lv_core/obj.rs +++ b/lvgl/src/lv_core/obj.rs @@ -31,7 +31,7 @@ pub struct Obj<'a> { impl Drop for Obj<'_> { fn drop(&mut self) { - unsafe { lvgl_sys::lv_obj_del(self.raw().as_mut()) } + unsafe { lvgl_sys::lv_obj_del_async(self.raw().as_mut()) } } } diff --git a/lvgl/src/lv_core/screen.rs b/lvgl/src/lv_core/screen.rs index 279f68cf..4fdd6ff0 100644 --- a/lvgl/src/lv_core/screen.rs +++ b/lvgl/src/lv_core/screen.rs @@ -71,8 +71,7 @@ mod test { const VER_RES: u32 = 240; crate::tests::initialize_test(); let buffer = DrawBuffer::<{ (HOR_RES * VER_RES) as usize }>::default(); - let display = Display::register(buffer, HOR_RES, VER_RES, |_| {}).unwrap(); - let mut screen_old = display.get_scr_act().unwrap(); + let (display, mut screen_old) = Display::register(buffer, HOR_RES, VER_RES, |_| {}).unwrap(); let mut screen_new = Screen::blank().unwrap(); display.set_scr_act(&mut screen_new); display.set_scr_act(&mut screen_old); diff --git a/lvgl/src/misc/anim.rs b/lvgl/src/misc/anim.rs index 550ca19a..33807e76 100644 --- a/lvgl/src/misc/anim.rs +++ b/lvgl/src/misc/anim.rs @@ -134,8 +134,8 @@ mod test { crate::tests::initialize_test(); const REFRESH_BUFFER_SIZE: usize = 240 * 240 / 10; let buffer = DrawBuffer::::default(); - let display = Display::register(buffer, 240, 240, |_| {}).unwrap(); - let mut screen = display.get_scr_act().unwrap(); + let (_display, mut screen) = Display::register(buffer, 240, 240, |_| {}).unwrap(); + //let mut screen = display.get_scr_act().unwrap(); let mut btn = Btn::create(&mut screen).unwrap(); let mut anim = Animation::new(&mut btn, Duration::from_millis(10), 0, 100, |_, _| {}).unwrap(); diff --git a/lvgl/src/widgets/label.rs b/lvgl/src/widgets/label.rs index 691ffb8d..1b2e1f6e 100644 --- a/lvgl/src/widgets/label.rs +++ b/lvgl/src/widgets/label.rs @@ -1,36 +1,6 @@ use crate::widgets::Label; use crate::{LabelLongMode, NativeObject}; -#[cfg(feature = "alloc")] -mod alloc_imp { - use crate::widgets::Label; - //use crate::LvError; - use cstr_core::CString; - //use core::convert::TryFrom; - - impl> From for Label<'_> { - fn from(text: S) -> Self { - // text.try_into().unwrap() - let text_cstr = CString::new(text.as_ref()).unwrap(); - let mut label = Label::new().unwrap(); - label.set_text(text_cstr.as_c_str()).unwrap(); - label - } - } - - // Issue link: https://github.com/rust-lang/rust/issues/50133 - // - // impl> TryFrom for Label { - // type Error = LvError; - // fn try_from(text: S) -> Result { - // let text_cstr = CString::new(text.as_ref())?; - // let mut label = Label::new()?; - // label.set_text(text_cstr.as_c_str())?; - // Ok(label) - // } - // } -} - impl Label<'_> { pub fn set_long_mode(&mut self, long_mode: LabelLongMode) { unsafe { @@ -41,4 +11,14 @@ impl Label<'_> { pub fn get_long_mode(&self) -> u8 { unsafe { lvgl_sys::lv_label_get_long_mode(self.raw().as_ref()) } } + + #[cfg(feature = "alloc")] + pub fn from_str>(text: S, parent: &mut impl NativeObject) -> Self { + use cstr_core::CString; + // text.try_into().unwrap() + let text_cstr = CString::new(text.as_ref()).unwrap(); + let mut label = Label::create(parent).unwrap(); + label.set_text(text_cstr.as_c_str()).unwrap(); + label + } } From f5b2b25f27e26e4374fc09738b80bc95f30d9484 Mon Sep 17 00:00:00 2001 From: Nia Espera Date: Wed, 21 Jun 2023 16:00:41 +0200 Subject: [PATCH 5/8] update codegen test --- lvgl-codegen/src/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lvgl-codegen/src/lib.rs b/lvgl-codegen/src/lib.rs index 967d9098..092d0a49 100644 --- a/lvgl-codegen/src/lib.rs +++ b/lvgl-codegen/src/lib.rs @@ -660,10 +660,10 @@ mod test { } } - pub fn new() -> crate::LvResult { - let mut parent = crate::display::get_scr_act()?; - Self::create(&mut parent) - } + //pub fn new() -> crate::LvResult { + // let mut parent = crate::display::get_scr_act()?; + // Self::create(&mut parent) + //} } }; From 81246d19d66aba97dfd3df2122a06c75c7ed39e1 Mon Sep 17 00:00:00 2001 From: Nia Espera Date: Fri, 1 Mar 2024 12:55:40 +0100 Subject: [PATCH 6/8] broken; multiple mut --- lvgl-codegen/src/lib.rs | 2 +- lvgl-sys/Cargo.toml | 1 + lvgl-sys/build.rs | 1 + lvgl/Cargo.toml | 2 +- lvgl/src/display.rs | 2 +- lvgl/src/lv_core/obj.rs | 31 +++++++++++++++++-------------- lvgl/src/widgets/label.rs | 4 ++-- 7 files changed, 24 insertions(+), 19 deletions(-) diff --git a/lvgl-codegen/src/lib.rs b/lvgl-codegen/src/lib.rs index 092d0a49..c625a079 100644 --- a/lvgl-codegen/src/lib.rs +++ b/lvgl-codegen/src/lib.rs @@ -107,7 +107,7 @@ impl Rusty for LvFunc { if new_name.as_str().eq("create") { return Ok(quote! { - pub fn create(parent: &mut impl crate::NativeObject) -> crate::LvResult { + pub fn create(parent: &'a mut impl crate::NativeObject) -> crate::LvResult { unsafe { let ptr = lvgl_sys::#original_func_name( parent.raw().as_mut(), diff --git a/lvgl-sys/Cargo.toml b/lvgl-sys/Cargo.toml index b42c74be..63fbb4f6 100644 --- a/lvgl-sys/Cargo.toml +++ b/lvgl-sys/Cargo.toml @@ -35,3 +35,4 @@ bindgen = "0.65.1" use-vendored-config = [] drivers = [] rust_timer = [] +no_compile = [] diff --git a/lvgl-sys/build.rs b/lvgl-sys/build.rs index fbf0ac53..cbd63bf2 100644 --- a/lvgl-sys/build.rs +++ b/lvgl-sys/build.rs @@ -154,6 +154,7 @@ fn main() { #[cfg(feature = "drivers")] cfg.includes(incl_extra.split(',')); + //#[cfg(not(feature = "no_compile"))] cfg.compile("lvgl"); let mut cc_args = vec![ diff --git a/lvgl/Cargo.toml b/lvgl/Cargo.toml index 15069d1c..b9848357 100644 --- a/lvgl/Cargo.toml +++ b/lvgl/Cargo.toml @@ -21,7 +21,7 @@ paste = "1.0.12" ctor = "0.2.2" [features] -default = ["embedded_graphics", "drivers"] +default = ["embedded_graphics", "drivers", "lvgl-sys/no_compile"] # Enable the embedded_graphics crate as a backend for graphics and input # devices. This is the 'legacy' method (supported in LVGL 0.5.2 and below) and diff --git a/lvgl/src/display.rs b/lvgl/src/display.rs index 84355977..3d2153ee 100644 --- a/lvgl/src/display.rs +++ b/lvgl/src/display.rs @@ -109,7 +109,7 @@ impl<'a> Display<'a> { unsafe { lvgl_sys::lv_disp_load_scr(scr_ptr) } } - pub fn is_scr_act(&self, screen: &Screen) -> bool { + pub fn is_scr_act(&'a self, screen: &Screen) -> bool { unsafe { let act = self.get_scr_act().map(|s| { s.raw().as_ptr() as usize diff --git a/lvgl/src/lv_core/obj.rs b/lvgl/src/lv_core/obj.rs index f33ea165..6aa4aaa6 100644 --- a/lvgl/src/lv_core/obj.rs +++ b/lvgl/src/lv_core/obj.rs @@ -7,8 +7,10 @@ use crate::lv_core::style::Style; use crate::{Align, LvError, LvResult}; +use core::cell::UnsafeCell; use core::fmt::{self, Debug}; use core::marker::PhantomData; +use core::mem::transmute; use core::ptr::{self, NonNull}; /// Represents a native LVGL object. @@ -22,11 +24,11 @@ pub trait NativeObject { /// This is the parent object of all widget types. It stores the native LVGL /// raw pointer. pub struct Obj<'a> { - // We use a raw pointer here because we do not control this memory address, - // it is controlled by LVGL's global state. - raw: NonNull, - // This is to ensure safety for children memory; it has no runtime impact - dependents: PhantomData<&'a isize>, + // We do not control this memory address, it is controlled by LVGL's + // global state. + raw: NonNull>, + // This is to ensure parent doesn't get dropped; it has no runtime impact + dependents: PhantomData<&'a Obj<'a>>, } impl Drop for Obj<'_> { @@ -46,13 +48,14 @@ impl Debug for Obj<'_> { // We need to manually impl methods on Obj since widget codegen is defined in // terms of Obj impl<'a> Obj<'a> { - pub fn create(parent: &'a mut impl NativeObject) -> LvResult { + pub fn create(parent: &'a impl NativeObject) -> LvResult { unsafe { let ptr = lvgl_sys::lv_obj_create(parent.raw().as_mut()); if let Some(nn_ptr) = NonNull::new(ptr) { //(*ptr).user_data = Box::new(UserDataObj::empty()).into_raw() as *mut _; Ok(Self { - raw: nn_ptr, + // Gross, but fast. UnsafeCell has the same layout as T + raw: transmute(nn_ptr), dependents: PhantomData::<&'a _>, }) } else { @@ -69,8 +72,8 @@ impl<'a> Obj<'a> { pub fn blank() -> LvResult { match NonNull::new(unsafe { lvgl_sys::lv_obj_create(ptr::null_mut()) }) { Some(raw) => Ok(Self { - raw, - dependents: PhantomData, + raw: unsafe { transmute(raw) }, + dependents: PhantomData::<&'a _>, }), None => Err(LvError::LvOOMemory), } @@ -79,7 +82,7 @@ impl<'a> Obj<'a> { impl NativeObject for Obj<'_> { fn raw(&self) -> NonNull { - self.raw + unsafe { NonNull::new_unchecked((*(self.raw.as_ptr())).get()) } } } @@ -98,7 +101,7 @@ pub trait Widget<'a>: NativeObject + Sized + 'a { unsafe fn from_raw(raw_pointer: NonNull) -> Option; /// Adds a `Style` to a given widget. - fn add_style(&mut self, part: Self::Part, style: &'a mut Style) { + fn add_style(&self, part: Self::Part, style: &'a mut Style) { unsafe { lvgl_sys::lv_obj_add_style( self.raw().as_mut(), @@ -163,8 +166,8 @@ impl<'a> Widget<'a> for Obj<'a> { unsafe fn from_raw(raw: NonNull) -> Option { Some(Self { - raw, - dependents: PhantomData, + raw: transmute(raw), + dependents: PhantomData::<&'a _>, }) } } @@ -189,7 +192,7 @@ macro_rules! define_object { } impl<'a> $item<'a> { - pub fn on_event(&mut self, f: F) -> $crate::LvResult<()> + pub fn on_event(&self, f: F) -> $crate::LvResult<()> where F: FnMut(Self, $crate::support::Event<>::SpecialEvent>), { diff --git a/lvgl/src/widgets/label.rs b/lvgl/src/widgets/label.rs index 1b2e1f6e..5689ad62 100644 --- a/lvgl/src/widgets/label.rs +++ b/lvgl/src/widgets/label.rs @@ -1,7 +1,7 @@ use crate::widgets::Label; use crate::{LabelLongMode, NativeObject}; -impl Label<'_> { +impl<'a> Label<'a> { pub fn set_long_mode(&mut self, long_mode: LabelLongMode) { unsafe { lvgl_sys::lv_label_set_long_mode(self.raw().as_mut(), long_mode.into()); @@ -13,7 +13,7 @@ impl Label<'_> { } #[cfg(feature = "alloc")] - pub fn from_str>(text: S, parent: &mut impl NativeObject) -> Self { + pub fn from_str>(text: S, parent: &'a mut impl NativeObject) -> Self { use cstr_core::CString; // text.try_into().unwrap() let text_cstr = CString::new(text.as_ref()).unwrap(); From be0f4b88cc4f332346cfe36ae0b92d3adf916e3e Mon Sep 17 00:00:00 2001 From: Nia Espera Date: Wed, 6 Mar 2024 15:20:58 +0100 Subject: [PATCH 7/8] return objects from closures, works! --- examples/sdl.rs | 5 +++-- lvgl-codegen/src/lib.rs | 2 +- lvgl/src/lv_core/obj.rs | 10 +++++----- lvgl/src/support.rs | 7 ++++--- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/examples/sdl.rs b/examples/sdl.rs index 6dd9d818..35233d13 100644 --- a/examples/sdl.rs +++ b/examples/sdl.rs @@ -31,11 +31,11 @@ fn main() -> LvResult<()> { let mut button = Btn::create(&mut screen)?; button.set_align(Align::LeftMid, 30, 0); button.set_size(180, 80); - let mut btn_lbl = Label::create(&mut button)?; + let mut btn_lbl = Label::create(&button)?; btn_lbl.set_text(CString::new("Click me!").unwrap().as_c_str())?; let mut btn_state = false; - button.on_event(|_btn, event| { + button.on_event(|btn, event| { println!("Button received event: {:?}", event); if let lvgl::Event::Clicked = event { if btn_state { @@ -47,6 +47,7 @@ fn main() -> LvResult<()> { } btn_state = !btn_state; } + btn })?; loop { diff --git a/lvgl-codegen/src/lib.rs b/lvgl-codegen/src/lib.rs index c625a079..5e0671ac 100644 --- a/lvgl-codegen/src/lib.rs +++ b/lvgl-codegen/src/lib.rs @@ -107,7 +107,7 @@ impl Rusty for LvFunc { if new_name.as_str().eq("create") { return Ok(quote! { - pub fn create(parent: &'a mut impl crate::NativeObject) -> crate::LvResult { + pub fn create(parent: &'a impl crate::NativeObject) -> crate::LvResult { unsafe { let ptr = lvgl_sys::#original_func_name( parent.raw().as_mut(), diff --git a/lvgl/src/lv_core/obj.rs b/lvgl/src/lv_core/obj.rs index 6aa4aaa6..5f013ec5 100644 --- a/lvgl/src/lv_core/obj.rs +++ b/lvgl/src/lv_core/obj.rs @@ -28,7 +28,7 @@ pub struct Obj<'a> { // global state. raw: NonNull>, // This is to ensure parent doesn't get dropped; it has no runtime impact - dependents: PhantomData<&'a Obj<'a>>, + parent: PhantomData<&'a Obj<'a>>, } impl Drop for Obj<'_> { @@ -56,7 +56,7 @@ impl<'a> Obj<'a> { Ok(Self { // Gross, but fast. UnsafeCell has the same layout as T raw: transmute(nn_ptr), - dependents: PhantomData::<&'a _>, + parent: PhantomData::<&'a _>, }) } else { Err(LvError::InvalidReference) @@ -73,7 +73,7 @@ impl<'a> Obj<'a> { match NonNull::new(unsafe { lvgl_sys::lv_obj_create(ptr::null_mut()) }) { Some(raw) => Ok(Self { raw: unsafe { transmute(raw) }, - dependents: PhantomData::<&'a _>, + parent: PhantomData::<&'a _>, }), None => Err(LvError::LvOOMemory), } @@ -167,7 +167,7 @@ impl<'a> Widget<'a> for Obj<'a> { unsafe fn from_raw(raw: NonNull) -> Option { Some(Self { raw: transmute(raw), - dependents: PhantomData::<&'a _>, + parent: PhantomData::<&'a _>, }) } } @@ -194,7 +194,7 @@ macro_rules! define_object { impl<'a> $item<'a> { pub fn on_event(&self, f: F) -> $crate::LvResult<()> where - F: FnMut(Self, $crate::support::Event<>::SpecialEvent>), + F: FnMut(Self, $crate::support::Event<>::SpecialEvent>) -> Self, { use $crate::NativeObject; unsafe { diff --git a/lvgl/src/support.rs b/lvgl/src/support.rs index a85cba6a..2dc3a8d4 100644 --- a/lvgl/src/support.rs +++ b/lvgl/src/support.rs @@ -5,6 +5,7 @@ use core::convert::{TryFrom, TryInto}; use core::error::Error; use core::fmt; use core::ptr::NonNull; +use core::mem::ManuallyDrop; #[cfg(feature = "embedded_graphics")] use embedded_graphics::pixelcolor::{Rgb565, Rgb888}; @@ -280,7 +281,7 @@ pub enum PointerEvent { pub(crate) unsafe extern "C" fn event_callback<'a, T, F>(event: *mut lvgl_sys::lv_event_t) where T: Widget<'a> + Sized, - F: FnMut(T, Event<>::SpecialEvent>), + F: FnMut(T, Event<>::SpecialEvent>) -> T, { let code = (*event).code; let obj = (*event).target; @@ -290,8 +291,8 @@ where let object = T::from_raw(obj_ptr).unwrap(); // get the pointer from the Rust callback closure FnMut provided by users let user_closure = &mut *((*obj).user_data as *mut F); - // call user callback closure - user_closure(object, code); + // call user callback closure and do *not* drop the widget + let _never_drop = ManuallyDrop::new(user_closure(object, code)); } } } From 655ad0c2cd832f79bbb064cd01fbefb5202025da Mon Sep 17 00:00:00 2001 From: Nia Espera Date: Wed, 6 Mar 2024 15:27:38 +0100 Subject: [PATCH 8/8] fix tests --- lvgl-codegen/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lvgl-codegen/src/lib.rs b/lvgl-codegen/src/lib.rs index 5e0671ac..dea403fa 100644 --- a/lvgl-codegen/src/lib.rs +++ b/lvgl-codegen/src/lib.rs @@ -646,7 +646,7 @@ mod test { define_object!(Arc); impl<'a> Arc<'a> { - pub fn create(parent: &mut impl crate::NativeObject) -> crate::LvResult { + pub fn create(parent: &'a impl crate::NativeObject) -> crate::LvResult { unsafe { let ptr = lvgl_sys::lv_arc_create( parent.raw().as_mut(),