Skip to content

Commit

Permalink
Merge pull request #141 from lvgl/obj-style-lifetimes
Browse files Browse the repository at this point in the history
Lifetime tracking for objects and styles
  • Loading branch information
nia-e authored Jun 20, 2023
2 parents 216d7ab + 8d6ca84 commit a5dde98
Show file tree
Hide file tree
Showing 17 changed files with 132 additions and 119 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ members = [
"lvgl-codegen",
"lvgl-sys",
]

resolver = "2"
10 changes: 5 additions & 5 deletions lvgl-codegen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ impl Rusty for LvWidget {
Ok(quote! {
define_object!(#widget_name);

impl #widget_name {
impl<'a> #widget_name<'a> {
#(#methods)*
}
})
Expand Down Expand Up @@ -122,7 +122,7 @@ impl Rusty for LvFunc {
}

pub fn new() -> crate::LvResult<Self> {
let mut parent = crate::display::DefaultDisplay::get_scr_act()?;
let mut parent = crate::display::get_scr_act()?;
Self::create(&mut parent)
}

Expand Down Expand Up @@ -613,7 +613,7 @@ mod test {
let expected_code = quote! {
define_object!(Arc);

impl Arc {
impl<'a> Arc<'a> {

}
};
Expand Down Expand Up @@ -645,7 +645,7 @@ mod test {
let expected_code = quote! {
define_object!(Arc);

impl Arc {
impl<'a> Arc<'a> {
pub fn create(parent: &mut impl crate::NativeObject) -> crate::LvResult<Self> {
unsafe {
let ptr = lvgl_sys::lv_arc_create(
Expand All @@ -661,7 +661,7 @@ mod test {
}

pub fn new() -> crate::LvResult<Self> {
let mut parent = crate::display::DefaultDisplay::get_scr_act()?;
let mut parent = crate::display::get_scr_act()?;
Self::create(&mut parent)
}
}
Expand Down
4 changes: 2 additions & 2 deletions lvgl-sys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ mod tests {
lv_init();

let horizontal_resolution = lv_disp_get_hor_res(core::ptr::null_mut());
assert_eq!(horizontal_resolution, 0 as i16);
assert_eq!(horizontal_resolution, 0);

let vertical_resolution = lv_disp_get_ver_res(core::ptr::null_mut());
assert_eq!(vertical_resolution, 0 as i16);
assert_eq!(vertical_resolution, 0);
}
}
}
41 changes: 19 additions & 22 deletions lvgl/src/display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ use crate::Screen;
use crate::{disp_drv_register, disp_get_default, get_str_act, LvResult, NativeObject};
use crate::{Box, Color};
use core::convert::TryInto;
#[cfg(feature = "nightly")]
use core::error::Error;
use core::fmt;
use core::mem::{ManuallyDrop, MaybeUninit};
use core::pin::Pin;
use core::ptr::NonNull;
use core::{ptr, result};
use core::fmt;
#[cfg(feature = "nightly")]
use core::error::Error;

/// Error in interacting with a `Display`.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
Expand All @@ -21,11 +21,15 @@ pub enum DisplayError {

impl fmt::Display for DisplayError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Display {}", match self {
DisplayError::NotAvailable => "not available",
DisplayError::FailedToRegister => "failed to register",
DisplayError::NotRegistered => "not registered",
})
write!(
f,
"Display {}",
match self {
DisplayError::NotAvailable => "not available",
DisplayError::FailedToRegister => "failed to register",
DisplayError::NotRegistered => "not registered",
}
)
}
}

Expand Down Expand Up @@ -63,18 +67,17 @@ impl<'a> Display {
let disp_p = &mut display_diver.disp_drv;
disp_p.hor_res = hor_res.try_into().unwrap_or(240);
disp_p.ver_res = ver_res.try_into().unwrap_or(240);
let ret = Ok(disp_drv_register(&mut display_diver, None)?);
Ok(disp_drv_register(&mut display_diver, None)?)
//display_diver.disp_drv.leak();
ret
}

/// Returns the current active screen.
pub fn get_scr_act(&self) -> Result<Screen> {
pub fn get_scr_act(&'a self) -> Result<Screen<'a>> {
Ok(get_str_act(Some(self))?.try_into()?)
}

/// Sets a `Screen` as currently active.
pub fn set_scr_act(&mut self, screen: &mut Screen) -> LvResult<()> {
pub fn set_scr_act(&'a self, screen: &'a mut Screen) -> LvResult<()> {
let scr_ptr = unsafe { screen.raw()?.as_mut() };
unsafe { lvgl_sys::lv_disp_load_scr(scr_ptr) }
Ok(())
Expand Down Expand Up @@ -152,14 +155,9 @@ impl Drop for Display {
}
}

#[derive(Copy, Clone)]
pub(crate) struct DefaultDisplay {}

impl DefaultDisplay {
/// Gets the active screen of the default display.
pub(crate) fn get_scr_act() -> Result<Screen> {
Ok(get_str_act(None)?.try_into()?)
}
/// Gets the active screen of the default display.
pub(crate) fn get_scr_act() -> Result<Screen<'static>> {
Ok(get_str_act(None)?.try_into()?)
}

/// A buffer of size `N` representing `N` pixels. `N` can be smaller than the
Expand Down Expand Up @@ -401,8 +399,7 @@ mod tests {
let _screen_direct = display
.get_scr_act()
.expect("Return screen directly from the display instance");
let _screen_default =
DefaultDisplay::get_scr_act().expect("Return screen from the default display");
let _screen_default = get_scr_act().expect("Return screen from the default display");
}

#[test]
Expand Down
5 changes: 4 additions & 1 deletion lvgl/src/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,10 @@ pub fn task_handler() {

/// Directly send an event to a specific widget.
#[inline]
pub fn event_send<W: Widget>(obj: &mut W, event: Event<W::SpecialEvent>) -> LvResult<()> {
pub fn event_send<W: for<'a> Widget<'a>>(
obj: &mut W,
event: Event<<W as Widget<'_>>::SpecialEvent>,
) -> LvResult<()> {
unsafe {
lvgl_sys::lv_event_send(obj.raw()?.as_mut(), event.into(), ptr::null_mut());
};
Expand Down
12 changes: 10 additions & 2 deletions lvgl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,12 @@ fn once_init() {
}
}

/// Initializes LVGL. Unless `unsafe_no_autoinit` is enabled, do not call
/// without first calling `deinit()` and dropping all old values.
/// Initializes LVGL.
///
/// # Safety
///
/// Unless `unsafe_no_autoinit` is enabled, do not call this function without
/// first calling `deinit()` and dropping all old values.
#[cfg(not(feature = "unsafe_no_autoinit"))]
pub unsafe fn init() {
unsafe {
Expand All @@ -119,6 +123,10 @@ pub unsafe fn init() {
}

/// Uninitializes LVGL. Make sure to reinitialize it before reusing it.
///
/// # Safety
///
/// This function should not be called if LVGL is already uninitialized.
pub unsafe fn deinit() {
unsafe { lvgl_sys::lv_deinit() }
}
Expand Down
50 changes: 31 additions & 19 deletions lvgl/src/lv_core/obj.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use crate::lv_core::style::Style;
use crate::{Align, LvError, LvResult};
use core::fmt::{self, Debug};
use core::marker::PhantomData;
use core::ptr;

/// Represents a native LVGL object.
Expand All @@ -19,13 +20,15 @@ pub trait NativeObject {
/// Generic LVGL object.
///
/// This is the parent object of all widget types. It stores the native LVGL raw pointer.
pub struct Obj {
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: *mut lvgl_sys::lv_obj_t,
// This is to ensure safety for style memory; it has no runtime impact
styles_used: PhantomData<&'a lvgl_sys::lv_style_t>,
}

impl Debug for Obj {
impl Debug for Obj<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("NativeObject")
.field("raw", &"!! LVGL lv_obj_t ptr !!")
Expand All @@ -35,26 +38,29 @@ impl Debug for Obj {

// We need to manually impl methods on Obj since widget codegen is defined in
// terms of Obj
impl Obj {
impl Obj<'_> {
pub fn create(parent: &mut impl NativeObject) -> LvResult<Self> {
unsafe {
let ptr = lvgl_sys::lv_obj_create(parent.raw()?.as_mut());
if ptr::NonNull::new(ptr).is_some() {
//(*ptr).user_data = Box::new(UserDataObj::empty()).into_raw() as *mut _;
Ok(Self { raw: ptr })
Ok(Self {
raw: ptr,
styles_used: PhantomData,
})
} else {
Err(LvError::InvalidReference)
}
}
}

pub fn new() -> crate::LvResult<Self> {
let mut parent = crate::display::DefaultDisplay::get_scr_act()?;
let mut parent = crate::display::get_scr_act()?;
Self::create(&mut parent)
}
}

impl NativeObject for Obj {
impl NativeObject for Obj<'_> {
fn raw(&self) -> LvResult<ptr::NonNull<lvgl_sys::lv_obj_t>> {
if let Some(non_null_ptr) = ptr::NonNull::new(self.raw) {
Ok(non_null_ptr)
Expand All @@ -65,7 +71,7 @@ impl NativeObject for Obj {
}

/// A wrapper for all LVGL common operations on generic objects.
pub trait Widget: NativeObject + Sized {
pub trait Widget<'a>: NativeObject + Sized + 'a {
type SpecialEvent;
type Part: Into<lvgl_sys::lv_part_t>;

Expand All @@ -79,7 +85,7 @@ pub trait Widget: NativeObject + Sized {
unsafe fn from_raw(raw_pointer: ptr::NonNull<lvgl_sys::lv_obj_t>) -> Option<Self>;

/// Adds a `Style` to a given widget.
fn add_style(&mut self, part: Self::Part, style: &mut Style) -> LvResult<()> {
fn add_style(&mut self, part: Self::Part, style: &'a mut Style) -> LvResult<()> {
unsafe {
lvgl_sys::lv_obj_add_style(
self.raw()?.as_mut(),
Expand Down Expand Up @@ -144,19 +150,23 @@ pub trait Widget: NativeObject + Sized {
}
}

impl Widget for Obj {
impl<'a> Widget<'a> for Obj<'a> {
type SpecialEvent = u32;
type Part = Part;

unsafe fn from_raw(raw: ptr::NonNull<lvgl_sys::lv_obj_t>) -> Option<Self> {
Some(Self { raw: raw.as_ptr() })
Some(Self {
raw: raw.as_ptr(),
styles_used: PhantomData,
})
}
}

impl Default for Obj {
impl Default for Obj<'_> {
fn default() -> Self {
Self {
raw: unsafe { lvgl_sys::lv_obj_create(ptr::null_mut()) },
styles_used: PhantomData,
}
}
}
Expand All @@ -176,22 +186,24 @@ macro_rules! define_object {
};
($item:ident, event = $event_type:ty, part = $part_type:ty) => {
#[derive(Debug)]
pub struct $item {
core: $crate::Obj,
pub struct $item<'a> {
core: $crate::Obj<'a>,
}

impl $item {
impl<'a> $item<'a> {
pub fn on_event<F>(&mut self, f: F) -> $crate::LvResult<()>
where
F: FnMut(Self, $crate::support::Event<<Self as $crate::Widget>::SpecialEvent>),
F: FnMut(Self, $crate::support::Event<<Self as $crate::Widget<'a>>::SpecialEvent>),
{
use $crate::NativeObject;
unsafe {
let obj = self.raw()?.as_mut();
obj.user_data = $crate::Box::into_raw($crate::Box::new(f)) as *mut _;
lvgl_sys::lv_obj_add_event_cb(
obj,
lvgl_sys::lv_event_cb_t::Some($crate::support::event_callback::<Self, F>),
lvgl_sys::lv_event_cb_t::Some(
$crate::support::event_callback::<'a, Self, F>,
),
lvgl_sys::lv_event_code_t_LV_EVENT_ALL,
obj.user_data,
);
Expand All @@ -200,13 +212,13 @@ macro_rules! define_object {
}
}

impl $crate::NativeObject for $item {
impl $crate::NativeObject for $item<'_> {
fn raw(&self) -> $crate::LvResult<core::ptr::NonNull<lvgl_sys::lv_obj_t>> {
self.core.raw()
}
}

impl $crate::Widget for $item {
impl<'a> $crate::Widget<'a> for $item<'a> {
type SpecialEvent = $event_type;
type Part = $part_type;

Expand Down Expand Up @@ -248,7 +260,7 @@ macro_rules! define_object {
// }
//
// pub fn new() -> crate::LvResult<Self> {
// let mut parent = crate::display::DefaultDisplay::get_scr_act()?;
// let mut parent = crate::display::get_scr_act()?;
// Ok(Self::create_at(&mut parent)?)
// }
// }
Expand Down
Loading

0 comments on commit a5dde98

Please sign in to comment.