Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lifetime tracking for objects and styles #141

Merged
merged 3 commits into from
Jun 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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