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)?;