From 614451f3a4efc1c68ca2c862904e8459f87ffa60 Mon Sep 17 00:00:00 2001 From: Rafael Caricio Date: Fri, 19 Jun 2020 18:05:17 +0200 Subject: [PATCH 01/14] Release 0.4.0 --- lvgl-codegen/Cargo.toml | 2 +- lvgl-sys/Cargo.toml | 2 +- lvgl/Cargo.toml | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lvgl-codegen/Cargo.toml b/lvgl-codegen/Cargo.toml index 635a7e9..c26278b 100644 --- a/lvgl-codegen/Cargo.toml +++ b/lvgl-codegen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "lvgl-codegen" -version = "0.3.3" +version = "0.4.0" description = "Code generation based on LVGL source code" authors = ["Rafael Caricio "] readme = "README.md" diff --git a/lvgl-sys/Cargo.toml b/lvgl-sys/Cargo.toml index c28513b..a2d9690 100644 --- a/lvgl-sys/Cargo.toml +++ b/lvgl-sys/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "lvgl-sys" description = "Raw bindings to the LittlevGL C library." -version = "0.3.3" +version = "0.4.0" authors = ["Rafael Caricio "] edition = "2018" license = "MIT" diff --git a/lvgl/Cargo.toml b/lvgl/Cargo.toml index 115c754..2af077e 100644 --- a/lvgl/Cargo.toml +++ b/lvgl/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "lvgl" description = "LittlevGL bindings for Rust. A powerful and easy-to-use embedded GUI with many widgets, advanced visual effects (opacity, antialiasing, animations) and low memory requirements (16K RAM, 64K Flash)." -version = "0.3.3" +version = "0.4.0" authors = ["Rafael Caricio "] edition = "2018" repository = "https://github.com/rafaelcaricio/lvgl-rs" @@ -12,7 +12,7 @@ keywords = ["littlevgl", "lvgl", "graphical_interfaces"] build = "build.rs" [dependencies] -lvgl-sys = { version = "0.3.3", path = "../lvgl-sys" } +lvgl-sys = { version = "0.4.0", path = "../lvgl-sys" } cty = "0.2.1" embedded-graphics = "0.6.2" cstr_core = { version = "0.2.0" } @@ -21,6 +21,6 @@ bitflags = "1.2.1" [build-dependencies] quote = "1.0.7" proc-macro2 = "1.0.18" -lvgl-codegen = { version = "0.3.3", path = "../lvgl-codegen" } -lvgl-sys = { version = "0.3.3", path = "../lvgl-sys" } +lvgl-codegen = { version = "0.4.0", path = "../lvgl-codegen" } +lvgl-sys = { version = "0.4.0", path = "../lvgl-sys" } -- 2.34.1 From 266ccdba031006ba0778e877eb0907e1aecfec7c Mon Sep 17 00:00:00 2001 From: Rafael Caricio Date: Fri, 19 Jun 2020 19:43:14 +0200 Subject: [PATCH 02/14] Re-export max resolutions --- examples/Cargo.toml | 4 ++++ examples/arc.rs | 7 ++---- examples/bar.rs | 7 ++---- examples/button_click.rs | 7 ++---- examples/demo.rs | 6 ++--- examples/gauge.rs | 9 +++---- examples/simple.rs | 52 ++++++++++++++++++++++++++++++++++++++++ lvgl/src/lib.rs | 3 +++ 8 files changed, 70 insertions(+), 25 deletions(-) create mode 100644 examples/simple.rs diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 5e116c8..52dd934 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -13,6 +13,10 @@ embedded-graphics-simulator = "0.2.0" heapless = "0.5.5" cstr_core = { version = "0.2.0", features = ["alloc"] } +[[example]] +name = "simple" +path = "simple.rs" + [[example]] name = "demo" path = "demo.rs" diff --git a/examples/arc.rs b/examples/arc.rs index 05523a4..52183ef 100644 --- a/examples/arc.rs +++ b/examples/arc.rs @@ -8,14 +8,11 @@ use lvgl::style::Style; use lvgl::widgets::{Arc, Label, LabelAlign}; use lvgl::{self, Align, Color, Part, State, UI}; use lvgl::{LvError, Widget}; -use lvgl_sys; use std::time::Instant; fn main() -> Result<(), LvError> { - let display: SimulatorDisplay = SimulatorDisplay::new(Size::new( - lvgl_sys::LV_HOR_RES_MAX, - lvgl_sys::LV_VER_RES_MAX, - )); + let display: SimulatorDisplay = + SimulatorDisplay::new(Size::new(lvgl::HOR_RES_MAX, lvgl::VER_RES_MAX)); let output_settings = OutputSettingsBuilder::new().scale(2).build(); let mut window = Window::new("Arc Example", &output_settings); diff --git a/examples/bar.rs b/examples/bar.rs index 6472b74..ea428d5 100644 --- a/examples/bar.rs +++ b/examples/bar.rs @@ -7,14 +7,11 @@ use embedded_graphics_simulator::{ use lvgl::style::Style; use lvgl::widgets::{Bar, Label, LabelAlign}; use lvgl::{self, Align, Animation, Color, Event, LvError, Part, State, Widget, UI}; -use lvgl_sys; use std::time::Instant; fn main() -> Result<(), LvError> { - let display: SimulatorDisplay = SimulatorDisplay::new(Size::new( - lvgl_sys::LV_HOR_RES_MAX, - lvgl_sys::LV_VER_RES_MAX, - )); + let display: SimulatorDisplay = + SimulatorDisplay::new(Size::new(lvgl::HOR_RES_MAX, lvgl::VER_RES_MAX)); let output_settings = OutputSettingsBuilder::new().scale(2).build(); let mut window = Window::new("Bar Example", &output_settings); diff --git a/examples/button_click.rs b/examples/button_click.rs index 58d6980..f6d47ce 100644 --- a/examples/button_click.rs +++ b/examples/button_click.rs @@ -7,14 +7,11 @@ use embedded_graphics_simulator::{ use lvgl::style::Style; use lvgl::widgets::{Btn, Label}; use lvgl::{self, Align, Color, Event, LvError, Part, State, Widget, UI}; -use lvgl_sys; use std::time::Instant; fn main() -> Result<(), LvError> { - let display: SimulatorDisplay = SimulatorDisplay::new(Size::new( - lvgl_sys::LV_HOR_RES_MAX, - lvgl_sys::LV_VER_RES_MAX, - )); + let display: SimulatorDisplay = + SimulatorDisplay::new(Size::new(lvgl::HOR_RES_MAX, lvgl::VER_RES_MAX)); let output_settings = OutputSettingsBuilder::new().scale(2).build(); let mut window = Window::new("Bar Example", &output_settings); diff --git a/examples/demo.rs b/examples/demo.rs index 60a6be5..b236c2b 100644 --- a/examples/demo.rs +++ b/examples/demo.rs @@ -13,10 +13,8 @@ use std::thread::sleep; use std::time::{Duration, Instant}; fn main() -> Result<(), LvError> { - let display: SimulatorDisplay = SimulatorDisplay::new(Size::new( - lvgl_sys::LV_HOR_RES_MAX, - lvgl_sys::LV_VER_RES_MAX, - )); + let display: SimulatorDisplay = + SimulatorDisplay::new(Size::new(lvgl::HOR_RES_MAX, lvgl::VER_RES_MAX)); let output_settings = OutputSettingsBuilder::new().scale(2).build(); let mut window = Window::new("PineTime", &output_settings); diff --git a/examples/gauge.rs b/examples/gauge.rs index 508e58b..ca236d4 100644 --- a/examples/gauge.rs +++ b/examples/gauge.rs @@ -6,14 +6,11 @@ use embedded_graphics_simulator::{ use lvgl::style::{Opacity, Style}; use lvgl::widgets::Gauge; use lvgl::{self, Align, Color, LvError, Part, State, Widget, UI}; -use lvgl_sys; use std::time::Instant; fn main() -> Result<(), LvError> { - let display: SimulatorDisplay = SimulatorDisplay::new(Size::new( - lvgl_sys::LV_HOR_RES_MAX, - lvgl_sys::LV_VER_RES_MAX, - )); + let display: SimulatorDisplay = + SimulatorDisplay::new(Size::new(lvgl::HOR_RES_MAX, lvgl::VER_RES_MAX)); let output_settings = OutputSettingsBuilder::new().scale(2).build(); let mut window = Window::new("Gauge Example", &output_settings); @@ -36,7 +33,7 @@ fn main() -> Result<(), LvError> { gauge_style.set_radius(State::DEFAULT, 5); gauge_style.set_bg_opa(State::DEFAULT, Opacity::OPA_COVER); gauge_style.set_bg_color(State::DEFAULT, Color::from_rgb((192, 192, 192))); - // Set some paddings + // Set some padding's gauge_style.set_pad_inner(State::DEFAULT, 20); gauge_style.set_pad_top(State::DEFAULT, 20); gauge_style.set_pad_left(State::DEFAULT, 5); diff --git a/examples/simple.rs b/examples/simple.rs new file mode 100644 index 0000000..1a05bd0 --- /dev/null +++ b/examples/simple.rs @@ -0,0 +1,52 @@ +use embedded_graphics::pixelcolor::Rgb565; +use embedded_graphics::prelude::*; +use embedded_graphics_simulator::{ + OutputSettingsBuilder, SimulatorDisplay, SimulatorEvent, Window, +}; +use lvgl::widgets::Keyboard; +use lvgl::LvError; +use lvgl::UI; +use std::time::Instant; + +fn main() -> Result<(), LvError> { + let display: SimulatorDisplay = + SimulatorDisplay::new(Size::new(lvgl::HOR_RES_MAX, lvgl::VER_RES_MAX)); + + let output_settings = OutputSettingsBuilder::new().scale(2).build(); + let mut window = Window::new("Simple Example", &output_settings); + + // Initialize LVGL + let mut ui = UI::init()?; + + // Register your display + ui.disp_drv_register(display)?; + + // Get the active screen + let mut screen = ui.scr_act()?; + + // Create a Keyboard widget on the screen + let _ = Keyboard::new(&mut screen)?; + + let mut loop_started = Instant::now(); + 'running: loop { + // Tell LVGL to process UI related tasks + ui.task_handler(); + + // Update your window with the latest display image + window.update(ui.get_display_ref().unwrap()); + + for event in window.events() { + match event { + SimulatorEvent::Quit => break 'running, + _ => {} + } + } + + // Tell LVGL how much time has past since last loop + ui.tick_inc(loop_started.elapsed()); + + loop_started = Instant::now(); + } + + Ok(()) +} diff --git a/lvgl/src/lib.rs b/lvgl/src/lib.rs index 8042594..adb763c 100644 --- a/lvgl/src/lib.rs +++ b/lvgl/src/lib.rs @@ -13,3 +13,6 @@ pub mod widgets; pub use lv_core::*; pub use support::*; pub use ui::*; + +pub const HOR_RES_MAX: u32 = lvgl_sys::LV_HOR_RES_MAX; +pub const VER_RES_MAX: u32 = lvgl_sys::LV_VER_RES_MAX; -- 2.34.1 From 18f4be1c88ca943784db1c39469882f7edb90089 Mon Sep 17 00:00:00 2001 From: Rafael Caricio Date: Fri, 19 Jun 2020 23:56:37 +0200 Subject: [PATCH 03/14] Fist attempt at input devices --- examples/button_click.rs | 23 ++++- lvgl/src/input_device.rs | 185 +++++++++++++++++++++++++++++++++++++++ lvgl/src/lib.rs | 1 + lvgl/src/mem.rs | 21 +++-- lvgl/src/ui.rs | 12 +++ 5 files changed, 232 insertions(+), 10 deletions(-) create mode 100644 lvgl/src/input_device.rs diff --git a/examples/button_click.rs b/examples/button_click.rs index f6d47ce..25f3b76 100644 --- a/examples/button_click.rs +++ b/examples/button_click.rs @@ -4,9 +4,12 @@ use embedded_graphics::prelude::*; use embedded_graphics_simulator::{ OutputSettingsBuilder, SimulatorDisplay, SimulatorEvent, Window, }; +use lvgl::input_device::{InputData, Pointer}; use lvgl::style::Style; use lvgl::widgets::{Btn, Label}; -use lvgl::{self, Align, Color, Event, LvError, Part, State, Widget, UI}; +use lvgl::{self, Align, Color, LvError, Part, State, Widget, UI}; +use std::cell::RefCell; +use std::rc::Rc; use std::time::Instant; fn main() -> Result<(), LvError> { @@ -21,6 +24,22 @@ fn main() -> Result<(), LvError> { // Implement and register your display: ui.disp_drv_register(display)?; + // Register the input mode + let latest_touch_point: Rc>> = Rc::new(RefCell::new(None)); + let internal = Rc::clone(&latest_touch_point); + let mut touch_screen = Pointer::new(move || { + let info = internal.borrow().clone(); + if info.is_some() { + let point = info.unwrap(); + println!("Changed to {:?}", point); + Some(InputData::Touch(point).pressed().once()) + } else { + None + } + }); + + ui.indev_drv_register(&mut touch_screen)?; + // Create screen and widgets let mut screen = ui.scr_act()?; @@ -64,7 +83,7 @@ fn main() -> Result<(), LvError> { } => { println!("Clicked on: {:?}", point); // Send a event to the button directly - ui.event_send(&mut button, Event::Clicked)?; + latest_touch_point.borrow_mut().replace(point); } SimulatorEvent::Quit => break 'running, _ => {} diff --git a/lvgl/src/input_device.rs b/lvgl/src/input_device.rs new file mode 100644 index 0000000..dca2241 --- /dev/null +++ b/lvgl/src/input_device.rs @@ -0,0 +1,185 @@ +use crate::LvResult; +use core::mem::MaybeUninit; +use embedded_graphics::geometry::Point; + +#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)] +pub enum InputData { + Touch(Point), + Key(u32), +} + +impl InputData { + pub fn released(self) -> InputState { + InputState::Released(self) + } + + pub fn pressed(self) -> InputState { + InputState::Pressed(self) + } +} + +#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)] +pub enum InputState { + Released(InputData), + Pressed(InputData), +} + +impl InputState { + pub fn once(self) -> BufferStatus { + BufferStatus::Empty(self) + } + + pub fn and_continued(self) -> BufferStatus { + BufferStatus::Buffered(self) + } +} + +#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)] +pub enum BufferStatus { + Empty(InputState), + Buffered(InputState), +} + +pub struct Pointer +where + F: Fn() -> Option, +{ + pub(crate) driver: lvgl_sys::lv_indev_drv_t, + pub(crate) descriptor: Option, + handler: F, +} + +impl Pointer +where + F: Fn() -> Option, +{ + pub fn new(mut handler: F) -> Self { + let driver = unsafe { + let mut indev_drv = MaybeUninit::uninit(); + lvgl_sys::lv_indev_drv_init(indev_drv.as_mut_ptr()); + let mut indev_drv = indev_drv.assume_init(); + indev_drv.type_ = lvgl_sys::LV_INDEV_TYPE_POINTER as lvgl_sys::lv_indev_type_t; + indev_drv.read_cb = Some(read_input::); + indev_drv.user_data = &mut handler as *mut _ as lvgl_sys::lv_indev_drv_user_data_t; + indev_drv + }; + Self { + handler, + driver, + descriptor: None, + } + } + + pub(crate) unsafe fn set_descriptor( + &mut self, + descriptor: *mut lvgl_sys::lv_indev_t, + ) -> LvResult<()> { + // TODO: check if not null && check if `self.descriptor` is not already set! + self.descriptor = Some(*descriptor); + Ok(()) + } +} + +unsafe extern "C" fn read_input( + indev_drv: *mut lvgl_sys::lv_indev_drv_t, + data: *mut lvgl_sys::lv_indev_data_t, +) -> bool +where + F: Fn() -> Option, +{ + let mut data = *data; + // convert user data to function + let user_closure = &mut *((*indev_drv).user_data as *mut F); + // call user data + let result: Option = user_closure(); + return if let Some(info) = result { + match info { + BufferStatus::Empty(InputState::Pressed(InputData::Touch(point))) => { + data.point.x = point.x as lvgl_sys::lv_coord_t; + data.point.y = point.y as lvgl_sys::lv_coord_t; + data.state = lvgl_sys::LV_INDEV_STATE_PR as lvgl_sys::lv_indev_state_t; + false + } + BufferStatus::Empty(InputState::Released(InputData::Touch(point))) => { + data.point.x = point.x as lvgl_sys::lv_coord_t; + data.point.y = point.y as lvgl_sys::lv_coord_t; + data.state = lvgl_sys::LV_INDEV_STATE_REL as lvgl_sys::lv_indev_state_t; + false + } + BufferStatus::Buffered(InputState::Pressed(InputData::Touch(point))) => { + data.point.x = point.x as lvgl_sys::lv_coord_t; + data.point.y = point.y as lvgl_sys::lv_coord_t; + data.state = lvgl_sys::LV_INDEV_STATE_PR as lvgl_sys::lv_indev_state_t; + true + } + BufferStatus::Buffered(InputState::Released(InputData::Touch(point))) => { + data.point.x = point.x as lvgl_sys::lv_coord_t; + data.point.y = point.y as lvgl_sys::lv_coord_t; + data.state = lvgl_sys::LV_INDEV_STATE_REL as lvgl_sys::lv_indev_state_t; + true + } + BufferStatus::Empty(InputState::Released(InputData::Key(_))) => false, + BufferStatus::Empty(InputState::Pressed(InputData::Key(_))) => false, + BufferStatus::Buffered(InputState::Released(InputData::Key(_))) => true, + BufferStatus::Buffered(InputState::Pressed(InputData::Key(_))) => true, + } + } else { + false + }; +} + +#[cfg(test)] +mod test { + use super::*; + use crate::{Color, UI}; + use core::marker::PhantomData; + use embedded_graphics::drawable::Pixel; + use embedded_graphics::geometry::Size; + use embedded_graphics::pixelcolor::PixelColor; + use embedded_graphics::pixelcolor::Rgb565; + use embedded_graphics::DrawTarget; + + struct FakeDisplay + where + C: PixelColor + From, + { + p: PhantomData, + } + + impl DrawTarget for FakeDisplay + where + C: PixelColor + From, + { + type Error = (); + + fn draw_pixel(&mut self, item: Pixel) -> Result<(), Self::Error> { + Ok(()) + } + + fn size(&self) -> Size { + Size::new(crate::VER_RES_MAX, crate::HOR_RES_MAX) + } + } + + //#[test] + // We cannot test right now by having instances of UI global state... :( + // I need to find a way to test while having global state... + fn pointer_input_device() -> LvResult<()> { + let mut ui = UI::init()?; + + let disp: FakeDisplay = FakeDisplay { p: PhantomData }; + + ui.disp_drv_register(disp); + + fn read_touchpad_device() -> Point { + Point::new(120, 23) + } + + let mut touch_screen = + Pointer::new(|| InputData::Touch(read_touchpad_device()).pressed().once()); + + ui.indev_drv_register(&mut touch_screen)?; + + Ok(()) + } +} diff --git a/lvgl/src/lib.rs b/lvgl/src/lib.rs index adb763c..6ae501f 100644 --- a/lvgl/src/lib.rs +++ b/lvgl/src/lib.rs @@ -3,6 +3,7 @@ #[macro_use] extern crate bitflags; +pub mod input_device; pub(crate) mod mem; mod support; mod ui; diff --git a/lvgl/src/mem.rs b/lvgl/src/mem.rs index 9167858..e041cd4 100644 --- a/lvgl/src/mem.rs +++ b/lvgl/src/mem.rs @@ -70,16 +70,17 @@ impl AsMut for Box { mod test { use super::*; use core::mem::MaybeUninit; - use std::sync::Once; - - static INIT_LVGL: Once = Once::new(); fn init() { - INIT_LVGL.call_once(|| { - unsafe { - lvgl_sys::lv_init(); - }; - }); + unsafe { + lvgl_sys::lv_init(); + }; + } + + fn teardown() { + unsafe { + lvgl_sys::lv_deinit(); + } } #[test] @@ -90,6 +91,8 @@ mod test { drop(v); let v = Box::new(10).unwrap(); drop(v); + + teardown(); } #[test] @@ -129,6 +132,8 @@ mod test { } assert_eq!(point.x, i); } + + teardown(); } fn print_mem_info() { diff --git a/lvgl/src/ui.rs b/lvgl/src/ui.rs index 699741c..5a4f223 100644 --- a/lvgl/src/ui.rs +++ b/lvgl/src/ui.rs @@ -1,3 +1,4 @@ +use crate::input_device::{BufferStatus, Pointer}; use crate::mem::Box; use crate::{Color, Event, LvError, LvResult, Obj, Widget}; use core::marker::PhantomData; @@ -56,6 +57,17 @@ where } } + pub fn indev_drv_register(&mut self, input_device: &mut Pointer) -> LvResult<()> + where + F: Fn() -> Option, + { + unsafe { + let descr = lvgl_sys::lv_indev_drv_register(&mut input_device.driver as *mut _); + input_device.set_descriptor(descr)?; + } + Ok(()) + } + pub fn disp_drv_register(&mut self, display: T) -> LvResult<()> { self.display_data = Some(DisplayUserData { display, -- 2.34.1 From 16b3ee0dc859303f52980734b157ae9bb5058ed7 Mon Sep 17 00:00:00 2001 From: Rafael Caricio Date: Sat, 20 Jun 2020 12:15:10 +0200 Subject: [PATCH 04/14] Input device working, first version --- examples/button_click.rs | 43 +++++++++++++------ lvgl/src/input_device.rs | 92 ++++++++++++++++++---------------------- lvgl/src/support.rs | 2 + lvgl/src/ui.rs | 5 +-- 4 files changed, 74 insertions(+), 68 deletions(-) diff --git a/examples/button_click.rs b/examples/button_click.rs index 25f3b76..8f2ea68 100644 --- a/examples/button_click.rs +++ b/examples/button_click.rs @@ -4,13 +4,14 @@ use embedded_graphics::prelude::*; use embedded_graphics_simulator::{ OutputSettingsBuilder, SimulatorDisplay, SimulatorEvent, Window, }; -use lvgl::input_device::{InputData, Pointer}; +use lvgl::input_device::{BufferStatus, InputData, Pointer}; use lvgl::style::Style; use lvgl::widgets::{Btn, Label}; use lvgl::{self, Align, Color, LvError, Part, State, Widget, UI}; use std::cell::RefCell; use std::rc::Rc; -use std::time::Instant; +use std::thread::sleep; +use std::time::{Duration, Instant}; fn main() -> Result<(), LvError> { let display: SimulatorDisplay = @@ -24,18 +25,17 @@ fn main() -> Result<(), LvError> { // Implement and register your display: ui.disp_drv_register(display)?; + // Initial state of input + let latest_touch_status: Rc> = Rc::new(RefCell::new( + InputData::Touch(Point::new(0, 0)).released().once(), + )); + // Register the input mode - let latest_touch_point: Rc>> = Rc::new(RefCell::new(None)); - let internal = Rc::clone(&latest_touch_point); + let internal = Rc::clone(&latest_touch_status); let mut touch_screen = Pointer::new(move || { - let info = internal.borrow().clone(); - if info.is_some() { - let point = info.unwrap(); - println!("Changed to {:?}", point); - Some(InputData::Touch(point).pressed().once()) - } else { - None - } + let input_status = internal.borrow().clone(); + //println!("input_status = {:?}", input_status); + input_status }); ui.indev_drv_register(&mut touch_screen)?; @@ -56,6 +56,7 @@ fn main() -> Result<(), LvError> { let mut btn_state = false; button.on_event(|mut btn, event| { + println!("Some event! {:?}", event); if let lvgl::Event::Clicked = event { if btn_state { let nt = CString::new("Click me!").unwrap(); @@ -71,11 +72,22 @@ fn main() -> Result<(), LvError> { })?; let mut loop_started = Instant::now(); + let mut latest_touch_point = Point::new(0, 0); 'running: loop { ui.task_handler(); window.update(ui.get_display_ref().unwrap()); - for event in window.events() { + let mut events = window.events().peekable(); + + if events.peek().is_none() { + latest_touch_status.replace( + InputData::Touch(latest_touch_point.clone()) + .released() + .once(), + ); + } + + for event in events { match event { SimulatorEvent::MouseButtonUp { mouse_btn: _, @@ -83,13 +95,16 @@ fn main() -> Result<(), LvError> { } => { println!("Clicked on: {:?}", point); // Send a event to the button directly - latest_touch_point.borrow_mut().replace(point); + latest_touch_point = point.clone(); + latest_touch_status.replace(InputData::Touch(point).pressed().once()); } SimulatorEvent::Quit => break 'running, _ => {} } } + sleep(Duration::from_millis(50)); + ui.tick_inc(loop_started.elapsed()); loop_started = Instant::now(); } diff --git a/lvgl/src/input_device.rs b/lvgl/src/input_device.rs index dca2241..9f1d26b 100644 --- a/lvgl/src/input_device.rs +++ b/lvgl/src/input_device.rs @@ -1,3 +1,4 @@ +use crate::mem::Box; use crate::LvResult; use core::mem::MaybeUninit; use embedded_graphics::geometry::Point; @@ -26,7 +27,7 @@ pub enum InputState { impl InputState { pub fn once(self) -> BufferStatus { - BufferStatus::Empty(self) + BufferStatus::Once(self) } pub fn and_continued(self) -> BufferStatus { @@ -36,35 +37,31 @@ impl InputState { #[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)] pub enum BufferStatus { - Empty(InputState), + Once(InputState), Buffered(InputState), } -pub struct Pointer -where - F: Fn() -> Option, -{ +pub struct Pointer { pub(crate) driver: lvgl_sys::lv_indev_drv_t, pub(crate) descriptor: Option, - handler: F, } -impl Pointer -where - F: Fn() -> Option, -{ - pub fn new(mut handler: F) -> Self { +impl Pointer { + pub fn new(mut handler: F) -> Self + where + F: Fn() -> BufferStatus, + { let driver = unsafe { let mut indev_drv = MaybeUninit::uninit(); lvgl_sys::lv_indev_drv_init(indev_drv.as_mut_ptr()); let mut indev_drv = indev_drv.assume_init(); indev_drv.type_ = lvgl_sys::LV_INDEV_TYPE_POINTER as lvgl_sys::lv_indev_type_t; indev_drv.read_cb = Some(read_input::); - indev_drv.user_data = &mut handler as *mut _ as lvgl_sys::lv_indev_drv_user_data_t; + indev_drv.user_data = Box::into_raw(Box::new(handler).unwrap()) as *mut _ + as lvgl_sys::lv_indev_drv_user_data_t; indev_drv }; Self { - handler, driver, descriptor: None, } @@ -85,47 +82,42 @@ unsafe extern "C" fn read_input( data: *mut lvgl_sys::lv_indev_data_t, ) -> bool where - F: Fn() -> Option, + F: Fn() -> BufferStatus, { - let mut data = *data; // convert user data to function let user_closure = &mut *((*indev_drv).user_data as *mut F); // call user data - let result: Option = user_closure(); - return if let Some(info) = result { - match info { - BufferStatus::Empty(InputState::Pressed(InputData::Touch(point))) => { - data.point.x = point.x as lvgl_sys::lv_coord_t; - data.point.y = point.y as lvgl_sys::lv_coord_t; - data.state = lvgl_sys::LV_INDEV_STATE_PR as lvgl_sys::lv_indev_state_t; - false - } - BufferStatus::Empty(InputState::Released(InputData::Touch(point))) => { - data.point.x = point.x as lvgl_sys::lv_coord_t; - data.point.y = point.y as lvgl_sys::lv_coord_t; - data.state = lvgl_sys::LV_INDEV_STATE_REL as lvgl_sys::lv_indev_state_t; - false - } - BufferStatus::Buffered(InputState::Pressed(InputData::Touch(point))) => { - data.point.x = point.x as lvgl_sys::lv_coord_t; - data.point.y = point.y as lvgl_sys::lv_coord_t; - data.state = lvgl_sys::LV_INDEV_STATE_PR as lvgl_sys::lv_indev_state_t; - true - } - BufferStatus::Buffered(InputState::Released(InputData::Touch(point))) => { - data.point.x = point.x as lvgl_sys::lv_coord_t; - data.point.y = point.y as lvgl_sys::lv_coord_t; - data.state = lvgl_sys::LV_INDEV_STATE_REL as lvgl_sys::lv_indev_state_t; - true - } - BufferStatus::Empty(InputState::Released(InputData::Key(_))) => false, - BufferStatus::Empty(InputState::Pressed(InputData::Key(_))) => false, - BufferStatus::Buffered(InputState::Released(InputData::Key(_))) => true, - BufferStatus::Buffered(InputState::Pressed(InputData::Key(_))) => true, + let info: BufferStatus = user_closure(); + match info { + BufferStatus::Once(InputState::Pressed(InputData::Touch(point))) => { + (*data).point.x = point.x as lvgl_sys::lv_coord_t; + (*data).point.y = point.y as lvgl_sys::lv_coord_t; + (*data).state = lvgl_sys::LV_INDEV_STATE_PR as lvgl_sys::lv_indev_state_t; + false } - } else { - false - }; + BufferStatus::Once(InputState::Released(InputData::Touch(point))) => { + (*data).point.x = point.x as lvgl_sys::lv_coord_t; + (*data).point.y = point.y as lvgl_sys::lv_coord_t; + (*data).state = lvgl_sys::LV_INDEV_STATE_REL as lvgl_sys::lv_indev_state_t; + false + } + BufferStatus::Buffered(InputState::Pressed(InputData::Touch(point))) => { + (*data).point.x = point.x as lvgl_sys::lv_coord_t; + (*data).point.y = point.y as lvgl_sys::lv_coord_t; + (*data).state = lvgl_sys::LV_INDEV_STATE_PR as lvgl_sys::lv_indev_state_t; + true + } + BufferStatus::Buffered(InputState::Released(InputData::Touch(point))) => { + (*data).point.x = point.x as lvgl_sys::lv_coord_t; + (*data).point.y = point.y as lvgl_sys::lv_coord_t; + (*data).state = lvgl_sys::LV_INDEV_STATE_REL as lvgl_sys::lv_indev_state_t; + true + } + BufferStatus::Once(InputState::Released(InputData::Key(_))) => false, + BufferStatus::Once(InputState::Pressed(InputData::Key(_))) => false, + BufferStatus::Buffered(InputState::Released(InputData::Key(_))) => true, + BufferStatus::Buffered(InputState::Pressed(InputData::Key(_))) => true, + } } #[cfg(test)] diff --git a/lvgl/src/support.rs b/lvgl/src/support.rs index e614de0..600742e 100644 --- a/lvgl/src/support.rs +++ b/lvgl/src/support.rs @@ -61,6 +61,7 @@ impl From for Rgb565 { /// /// All objects (such as Buttons/Labels/Sliders etc.) receive these generic events /// regardless of their type. +#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)] pub enum Event { /// The object has been pressed Pressed, @@ -140,6 +141,7 @@ impl From> for lvgl_sys::lv_event_t { } /// These events are sent only by pointer-like input devices (E.g. mouse or touchpad) +#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)] pub enum PointerEvent { DragBegin, DragEnd, diff --git a/lvgl/src/ui.rs b/lvgl/src/ui.rs index 5a4f223..dd08c1b 100644 --- a/lvgl/src/ui.rs +++ b/lvgl/src/ui.rs @@ -57,10 +57,7 @@ where } } - pub fn indev_drv_register(&mut self, input_device: &mut Pointer) -> LvResult<()> - where - F: Fn() -> Option, - { + pub fn indev_drv_register(&mut self, input_device: &mut Pointer) -> LvResult<()> { unsafe { let descr = lvgl_sys::lv_indev_drv_register(&mut input_device.driver as *mut _); input_device.set_descriptor(descr)?; -- 2.34.1 From 8cc4bf8ab8190d9b7731584c970ea38e549f36ce Mon Sep 17 00:00:00 2001 From: Rafael Caricio Date: Sat, 20 Jun 2020 12:19:13 +0200 Subject: [PATCH 05/14] Simplify example --- examples/button_click.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/examples/button_click.rs b/examples/button_click.rs index 8f2ea68..3070c73 100644 --- a/examples/button_click.rs +++ b/examples/button_click.rs @@ -32,11 +32,7 @@ fn main() -> Result<(), LvError> { // Register the input mode let internal = Rc::clone(&latest_touch_status); - let mut touch_screen = Pointer::new(move || { - let input_status = internal.borrow().clone(); - //println!("input_status = {:?}", input_status); - input_status - }); + let mut touch_screen = Pointer::new(move || internal.borrow().clone()); ui.indev_drv_register(&mut touch_screen)?; @@ -103,7 +99,7 @@ fn main() -> Result<(), LvError> { } } - sleep(Duration::from_millis(50)); + sleep(Duration::from_millis(15)); ui.tick_inc(loop_started.elapsed()); loop_started = Instant::now(); -- 2.34.1 From c8c63456bc748471046d21ecee7e1a0500213609 Mon Sep 17 00:00:00 2001 From: Rafael Caricio Date: Sat, 20 Jun 2020 12:27:46 +0200 Subject: [PATCH 06/14] Simplify example --- examples/button_click.rs | 14 +++++--------- lvgl/src/input_device.rs | 2 +- lvgl/src/ui.rs | 2 +- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/examples/button_click.rs b/examples/button_click.rs index 3070c73..75ca15b 100644 --- a/examples/button_click.rs +++ b/examples/button_click.rs @@ -1,3 +1,4 @@ +use core::cell::Cell; use cstr_core::CString; use embedded_graphics::pixelcolor::Rgb565; use embedded_graphics::prelude::*; @@ -8,8 +9,6 @@ use lvgl::input_device::{BufferStatus, InputData, Pointer}; use lvgl::style::Style; use lvgl::widgets::{Btn, Label}; use lvgl::{self, Align, Color, LvError, Part, State, Widget, UI}; -use std::cell::RefCell; -use std::rc::Rc; use std::thread::sleep; use std::time::{Duration, Instant}; @@ -26,13 +25,11 @@ fn main() -> Result<(), LvError> { ui.disp_drv_register(display)?; // Initial state of input - let latest_touch_status: Rc> = Rc::new(RefCell::new( - InputData::Touch(Point::new(0, 0)).released().once(), - )); + let latest_touch_status: Cell = + Cell::new(InputData::Touch(Point::new(0, 0)).released().once()); // Register the input mode - let internal = Rc::clone(&latest_touch_status); - let mut touch_screen = Pointer::new(move || internal.borrow().clone()); + let mut touch_screen = Pointer::new(|| latest_touch_status.get()); ui.indev_drv_register(&mut touch_screen)?; @@ -52,7 +49,7 @@ fn main() -> Result<(), LvError> { let mut btn_state = false; button.on_event(|mut btn, event| { - println!("Some event! {:?}", event); + println!("Button received event: {:?}", event); if let lvgl::Event::Clicked = event { if btn_state { let nt = CString::new("Click me!").unwrap(); @@ -62,7 +59,6 @@ fn main() -> Result<(), LvError> { btn_lbl.set_text(nt.as_c_str()).unwrap(); } btn_state = !btn_state; - println!("Clicked! Inner.."); btn.toggle().unwrap(); } })?; diff --git a/lvgl/src/input_device.rs b/lvgl/src/input_device.rs index 9f1d26b..b813cf2 100644 --- a/lvgl/src/input_device.rs +++ b/lvgl/src/input_device.rs @@ -47,7 +47,7 @@ pub struct Pointer { } impl Pointer { - pub fn new(mut handler: F) -> Self + pub fn new(handler: F) -> Self where F: Fn() -> BufferStatus, { diff --git a/lvgl/src/ui.rs b/lvgl/src/ui.rs index dd08c1b..73bf3a5 100644 --- a/lvgl/src/ui.rs +++ b/lvgl/src/ui.rs @@ -1,4 +1,4 @@ -use crate::input_device::{BufferStatus, Pointer}; +use crate::input_device::Pointer; use crate::mem::Box; use crate::{Color, Event, LvError, LvResult, Obj, Widget}; use core::marker::PhantomData; -- 2.34.1 From dc0e2f947a7fa5e44da0ecd4922dab48a52531be Mon Sep 17 00:00:00 2001 From: Rafael Caricio Date: Sat, 20 Jun 2020 12:31:37 +0200 Subject: [PATCH 07/14] Add some guiding comments to example --- examples/button_click.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/examples/button_click.rs b/examples/button_click.rs index 75ca15b..383f12d 100644 --- a/examples/button_click.rs +++ b/examples/button_click.rs @@ -21,16 +21,15 @@ fn main() -> Result<(), LvError> { let mut ui = UI::init()?; - // Implement and register your display: + // Register your display: ui.disp_drv_register(display)?; - // Initial state of input + // Define the initial state of your input let latest_touch_status: Cell = Cell::new(InputData::Touch(Point::new(0, 0)).released().once()); - // Register the input mode + // Register a new input device that's capable of reading the current state of the input let mut touch_screen = Pointer::new(|| latest_touch_status.get()); - ui.indev_drv_register(&mut touch_screen)?; // Create screen and widgets -- 2.34.1 From 7781c12809a3e788ada0ee2661e99a5b2b8bed4e Mon Sep 17 00:00:00 2001 From: Rafael Caricio Date: Sat, 20 Jun 2020 12:58:26 +0200 Subject: [PATCH 08/14] Fix test --- lvgl/src/input_device.rs | 15 +++++++-------- lvgl/src/ui.rs | 12 ++++++++++++ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/lvgl/src/input_device.rs b/lvgl/src/input_device.rs index b813cf2..5cec36c 100644 --- a/lvgl/src/input_device.rs +++ b/lvgl/src/input_device.rs @@ -123,7 +123,7 @@ where #[cfg(test)] mod test { use super::*; - use crate::{Color, UI}; + use crate::UI; use core::marker::PhantomData; use embedded_graphics::drawable::Pixel; use embedded_graphics::geometry::Size; @@ -133,14 +133,14 @@ mod test { struct FakeDisplay where - C: PixelColor + From, + C: PixelColor, { p: PhantomData, } impl DrawTarget for FakeDisplay where - C: PixelColor + From, + C: PixelColor, { type Error = (); @@ -161,14 +161,13 @@ mod test { let disp: FakeDisplay = FakeDisplay { p: PhantomData }; - ui.disp_drv_register(disp); + ui.disp_drv_register(disp)?; - fn read_touchpad_device() -> Point { - Point::new(120, 23) + fn read_touchpad_device() -> BufferStatus { + InputData::Touch(Point::new(120, 23)).pressed().once() } - let mut touch_screen = - Pointer::new(|| InputData::Touch(read_touchpad_device()).pressed().once()); + let mut touch_screen = Pointer::new(|| read_touchpad_device()); ui.indev_drv_register(&mut touch_screen)?; diff --git a/lvgl/src/ui.rs b/lvgl/src/ui.rs index 73bf3a5..aa4ab3d 100644 --- a/lvgl/src/ui.rs +++ b/lvgl/src/ui.rs @@ -58,6 +58,18 @@ where } pub fn indev_drv_register(&mut self, input_device: &mut Pointer) -> LvResult<()> { + if self.display_data.is_none() { + // TODO: Better yet would be to create a display struct that one register the + // input device in that instance. Represents better the LVGL correct usage. Also it's + // inline with unrepresentable invalid states using Rust type system. + // ```rust + // let disp = ui.disp_drv_register(embed_graph_disp)?; + // disp.indev_drv_register(disp); + // ... + // window.update(&disp) + // ``` + return Err(LvError::Uninitialized); + } unsafe { let descr = lvgl_sys::lv_indev_drv_register(&mut input_device.driver as *mut _); input_device.set_descriptor(descr)?; -- 2.34.1 From 30c5d87bb3ae0d04f2d49a248560681d34cfc91a Mon Sep 17 00:00:00 2001 From: Rafael Caricio Date: Sat, 20 Jun 2020 18:46:36 +0200 Subject: [PATCH 09/14] Simplify example --- examples/button_click.rs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/examples/button_click.rs b/examples/button_click.rs index 383f12d..f16e567 100644 --- a/examples/button_click.rs +++ b/examples/button_click.rs @@ -1,14 +1,15 @@ -use core::cell::Cell; use cstr_core::CString; use embedded_graphics::pixelcolor::Rgb565; use embedded_graphics::prelude::*; use embedded_graphics_simulator::{ OutputSettingsBuilder, SimulatorDisplay, SimulatorEvent, Window, }; + use lvgl::input_device::{BufferStatus, InputData, Pointer}; use lvgl::style::Style; use lvgl::widgets::{Btn, Label}; use lvgl::{self, Align, Color, LvError, Part, State, Widget, UI}; + use std::thread::sleep; use std::time::{Duration, Instant}; @@ -25,11 +26,10 @@ fn main() -> Result<(), LvError> { ui.disp_drv_register(display)?; // Define the initial state of your input - let latest_touch_status: Cell = - Cell::new(InputData::Touch(Point::new(0, 0)).released().once()); + let mut latest_touch_status = InputData::Touch(Point::new(0, 0)).released().once(); // Register a new input device that's capable of reading the current state of the input - let mut touch_screen = Pointer::new(|| latest_touch_status.get()); + let mut touch_screen = Pointer::new(|| latest_touch_status); ui.indev_drv_register(&mut touch_screen)?; // Create screen and widgets @@ -71,11 +71,9 @@ fn main() -> Result<(), LvError> { let mut events = window.events().peekable(); if events.peek().is_none() { - latest_touch_status.replace( - InputData::Touch(latest_touch_point.clone()) - .released() - .once(), - ); + latest_touch_status = InputData::Touch(latest_touch_point.clone()) + .released() + .once(); } for event in events { @@ -87,7 +85,7 @@ fn main() -> Result<(), LvError> { println!("Clicked on: {:?}", point); // Send a event to the button directly latest_touch_point = point.clone(); - latest_touch_status.replace(InputData::Touch(point).pressed().once()); + latest_touch_status = InputData::Touch(point).pressed().once(); } SimulatorEvent::Quit => break 'running, _ => {} -- 2.34.1 From 2edb9f031627ec02c22c9364d6e90aa82c01956d Mon Sep 17 00:00:00 2001 From: Rafael Caricio Date: Sat, 20 Jun 2020 19:00:13 +0200 Subject: [PATCH 10/14] Release 0.5.0 --- lvgl-codegen/Cargo.toml | 2 +- lvgl-sys/Cargo.toml | 2 +- lvgl/Cargo.toml | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lvgl-codegen/Cargo.toml b/lvgl-codegen/Cargo.toml index c26278b..89c6cdc 100644 --- a/lvgl-codegen/Cargo.toml +++ b/lvgl-codegen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "lvgl-codegen" -version = "0.4.0" +version = "0.5.0" description = "Code generation based on LVGL source code" authors = ["Rafael Caricio "] readme = "README.md" diff --git a/lvgl-sys/Cargo.toml b/lvgl-sys/Cargo.toml index a2d9690..37f6af0 100644 --- a/lvgl-sys/Cargo.toml +++ b/lvgl-sys/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "lvgl-sys" description = "Raw bindings to the LittlevGL C library." -version = "0.4.0" +version = "0.5.0" authors = ["Rafael Caricio "] edition = "2018" license = "MIT" diff --git a/lvgl/Cargo.toml b/lvgl/Cargo.toml index 2af077e..8094e9a 100644 --- a/lvgl/Cargo.toml +++ b/lvgl/Cargo.toml @@ -12,7 +12,7 @@ keywords = ["littlevgl", "lvgl", "graphical_interfaces"] build = "build.rs" [dependencies] -lvgl-sys = { version = "0.4.0", path = "../lvgl-sys" } +lvgl-sys = { version = "0.5.0", path = "../lvgl-sys" } cty = "0.2.1" embedded-graphics = "0.6.2" cstr_core = { version = "0.2.0" } @@ -21,6 +21,6 @@ bitflags = "1.2.1" [build-dependencies] quote = "1.0.7" proc-macro2 = "1.0.18" -lvgl-codegen = { version = "0.4.0", path = "../lvgl-codegen" } -lvgl-sys = { version = "0.4.0", path = "../lvgl-sys" } +lvgl-codegen = { version = "0.5.0", path = "../lvgl-codegen" } +lvgl-sys = { version = "0.5.0", path = "../lvgl-sys" } -- 2.34.1 From 42ae30700aa3ae468658cd61f13640968bc9f2be Mon Sep 17 00:00:00 2001 From: Rafael Caricio Date: Thu, 27 Aug 2020 11:37:00 +0200 Subject: [PATCH 11/14] Expose RGB values from Color --- lvgl/src/support.rs | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/lvgl/src/support.rs b/lvgl/src/support.rs index 600742e..bc9b0fb 100644 --- a/lvgl/src/support.rs +++ b/lvgl/src/support.rs @@ -27,6 +27,24 @@ impl Color { pub fn from_raw(raw: lvgl_sys::lv_color_t) -> Self { Self { raw } } + + pub fn r(&self) -> u8 { + unsafe { + lvgl_sys::_LV_COLOR_GET_R(self.raw) as u8 + } + } + + pub fn g(&self) -> u8 { + unsafe { + lvgl_sys::_LV_COLOR_GET_G(self.raw) as u8 + } + } + + pub fn b(&self) -> u8 { + unsafe { + lvgl_sys::_LV_COLOR_GET_B(self.raw) as u8 + } + } } impl From for Rgb888 { @@ -233,3 +251,25 @@ impl From for lvgl_sys::lv_anim_enable_t { } } } + + +#[cfg(test)] +mod test { + use super::*; + use lvgl_sys; + + #[test] + fn color_properties_accessible() { + let color = Color::from_rgb((206, 51, 255)); + + if lvgl_sys::LV_COLOR_DEPTH == 32 { + assert_eq!(color.r(), 206); + assert_eq!(color.g(), 51); + assert_eq!(color.b(), 255); + } else if lvgl_sys::LV_COLOR_DEPTH == 16 { + assert_eq!(color.r(), 25); + assert_eq!(color.g(), 12); + assert_eq!(color.b(), 31); + } + } +} -- 2.34.1 From 054f2ba31f02e93149e0a42ee92e45a9b044a17f Mon Sep 17 00:00:00 2001 From: Rafael Caricio Date: Mon, 21 Sep 2020 20:01:31 +0200 Subject: [PATCH 12/14] Compile to WASM using emscripten --- lvgl-sys/build.rs | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/lvgl-sys/build.rs b/lvgl-sys/build.rs index 19c14ff..9bc0450 100644 --- a/lvgl-sys/build.rs +++ b/lvgl-sys/build.rs @@ -62,25 +62,48 @@ fn main() { .include(&lv_config_dir) .compile("lvgl"); - let cc_args = [ + let mut cc_args = vec![ "-DLV_CONF_INCLUDE_SIMPLE=1", "-I", lv_config_dir.to_str().unwrap(), "-I", vendor.to_str().unwrap(), + "-fvisibility=default", ]; + // Set correct target triple for bindgen when cross-compiling + let target = env::var("TARGET").expect("Cargo build scripts always have TARGET"); + let host = env::var("HOST").expect("Cargo build scripts always have HOST"); + if target != host { + cc_args.push("-target"); + cc_args.push(target.as_str()); + } + + let mut additional_args = Vec::new(); + if target.ends_with("emscripten") { + if let Ok(em_path) = env::var("EMSDK") { + additional_args.push("-I".to_string()); + additional_args.push(format!("{}/upstream/emscripten/system/include/libc", em_path)); + additional_args.push("-I".to_string()); + additional_args.push(format!("{}/upstream/emscripten/system/lib/libc/musl/arch/emscripten", em_path)); + additional_args.push("-I".to_string()); + additional_args.push(format!("{}/upstream/emscripten/system/include/SDL", em_path)); + } + } + let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); - bindgen::Builder::default() + let bindings = bindgen::Builder::default() .header(shims_dir.join("lvgl_sys.h").to_str().unwrap()) .layout_tests(false) .use_core() .rustfmt_bindings(true) .ctypes_prefix("cty") .clang_args(&cc_args) + .clang_args(&additional_args) .generate() - .expect("Unable to generate bindings") - .write_to_file(out_path.join("bindings.rs")) + .expect("Unable to generate bindings"); + + bindings.write_to_file(out_path.join("bindings.rs")) .expect("Can't write bindings!"); } -- 2.34.1 From b395724561109288c84cdb6883a86994bb9d6724 Mon Sep 17 00:00:00 2001 From: Ralf Weinbrecher Date: Tue, 17 Nov 2020 16:17:42 +0100 Subject: [PATCH 13/14] Update README: Added a hint to install sdl2 before running the demos on macOS --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index c6d7f07..c2394ed 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,12 @@ $ DEP_LV_CONFIG_PATH=`pwd` cargo build -Zfeatures=build_dep ## Running the demo +**Hint for macOS users**: Before you run the demos you need to make sure you have [libsdl](https://www.libsdl.org) installed on your machine. To install it, use HomeBrew: + +```shell +$ brew install sdl2 +``` + [This project contains examples that can run in a desktop simulator.](./examples) First, make sure to pull `lvgl-rs` submodules: -- 2.34.1 From 1745f68b7aa536740f2386c783e91604174774ba Mon Sep 17 00:00:00 2001 From: Jai A Date: Fri, 12 Feb 2021 13:58:35 -0700 Subject: [PATCH 14/14] Fix compile error --- lvgl-codegen/src/lib.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lvgl-codegen/src/lib.rs b/lvgl-codegen/src/lib.rs index b6b8132..eaf83bd 100644 --- a/lvgl-codegen/src/lib.rs +++ b/lvgl-codegen/src/lib.rs @@ -1,12 +1,11 @@ use inflector::cases::pascalcase::to_pascal_case; use lazy_static::lazy_static; use proc_macro2::{Ident, TokenStream}; -use quote::format_ident; +use quote::{format_ident, ToTokens}; use quote::quote; use regex::Regex; use std::collections::HashMap; use std::error::Error; -use syn::export::ToTokens; use syn::{FnArg, ForeignItem, ForeignItemFn, Item, ReturnType}; type CGResult = Result>; -- 2.34.1