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

Automatically delete Obj and related on drop #144

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from
Draft
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
15 changes: 7 additions & 8 deletions examples/sdl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,23 @@ 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)?;
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 {
Expand All @@ -49,6 +47,7 @@ fn main() -> LvResult<()> {
}
btn_state = !btn_state;
}
btn
})?;

loop {
Expand Down
20 changes: 10 additions & 10 deletions lvgl-codegen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Self> {
pub fn create(parent: &'a impl crate::NativeObject) -> crate::LvResult<Self> {
unsafe {
let ptr = lvgl_sys::#original_func_name(
parent.raw().as_mut(),
Expand All @@ -121,10 +121,10 @@ impl Rusty for LvFunc {
}
}

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

});
}
Expand Down Expand Up @@ -646,7 +646,7 @@ mod test {
define_object!(Arc);

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

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

Expand Down
1 change: 1 addition & 0 deletions lvgl-sys/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,4 @@ bindgen = "0.65.1"
use-vendored-config = []
drivers = []
rust_timer = []
no_compile = []
1 change: 1 addition & 0 deletions lvgl-sys/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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![
Expand Down
2 changes: 1 addition & 1 deletion lvgl/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
163 changes: 116 additions & 47 deletions lvgl/src/display.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use crate::functions::CoreError;
use crate::Screen;
use crate::{disp_drv_register, disp_get_default, get_str_act, 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;
Expand Down Expand Up @@ -39,17 +40,22 @@ impl Error for DisplayError {}
type Result<T> = result::Result<T, DisplayError>;

/// An LVGL-registered display. Equivalent to an `lv_disp_t`.
pub struct Display {
pub(crate) disp: NonNull<lvgl_sys::lv_disp_t>,
pub struct Display<'a> {
disp: NonNull<lvgl_sys::lv_disp_t>,
drop: Option<unsafe extern "C" fn()>,
_screens: PhantomData<&'a Screen<'a>>,
}

impl<'a> Display {
impl<'a> Display<'a> {
pub(crate) fn from_raw(
disp: NonNull<lvgl_sys::lv_disp_t>,
drop: Option<unsafe extern "C" fn()>,
) -> Self {
Self { disp, drop }
Self {
disp,
drop,
_screens: PhantomData,
}
}

/// Registers a given `DrawBuffer` with an associated update function to
Expand All @@ -59,21 +65,42 @@ impl<'a> Display {
hor_res: u32,
ver_res: u32,
display_update: F,
) -> Result<Self>
) -> Result<(Self, Screen<'a>)>
where
F: FnMut(&DisplayRefresh<N>) + '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)?)
let disp = disp_drv_register::<N>(
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) -> Result<Screen<'a>> {
Ok(get_str_act(Some(self))?.try_into()?)
///
/// # 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<Screen<'a>> {
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.
Expand All @@ -82,6 +109,65 @@ impl<'a> Display {
unsafe { lvgl_sys::lv_disp_load_scr(scr_ptr) }
}

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
}).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<const N: usize>(draw_buffer: DrawBuffer<N>,
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<unsafe extern "C" fn(*mut lvgl_sys::lv_disp_drv_t, *mut u8, u32)>,
monitor_cb: Option<unsafe extern "C" fn(*mut lvgl_sys::lv_disp_drv_t, u32, u32)>,
wait_cb: Option<unsafe extern "C" fn(*mut lvgl_sys::lv_disp_drv_t)>,
clean_dcache_cb: Option<unsafe extern "C" fn(*mut lvgl_sys::lv_disp_drv_t)>,
drv_update_cb: Option<unsafe extern "C" fn(*mut lvgl_sys::lv_disp_drv_t)>,
render_start_cb: Option<unsafe extern "C" fn(*mut lvgl_sys::lv_disp_drv_t)>,
drop: Option<unsafe extern "C" fn()>,
) -> 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
Expand Down Expand Up @@ -137,29 +223,27 @@ 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::<N>(
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() }
}
}
}

/// 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
/// entire number of pixels on the screen, in which case the screen will be
/// drawn to multiple times per frame.
Expand Down Expand Up @@ -388,28 +472,13 @@ mod tests {
use crate::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");
}

#[test]
fn get_default_display() {
tests::initialize_test(true);
let display = Display::default();
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();
let _screen = display
.get_scr_act()
.expect("Return screen directly from the display instance");
Ok(())
fn register_display_and_screen() {
tests::initialize_test();
const REFRESH_BUFFER_SIZE: usize = 240 * 240 / 10;
let buffer = DrawBuffer::<REFRESH_BUFFER_SIZE>::default();
let (_display, _screen) = Display::register(buffer, 240, 240, |_| {}).unwrap();
//let _screen_direct = display
// .get_scr_act()
// .expect("Return screen directly from the display instance");
}
}
Loading
Loading