Touch input device #27

Open
rafaelcaricio wants to merge 15 commits from indev into master
4 changed files with 74 additions and 68 deletions
Showing only changes of commit 16b3ee0dc8 - Show all commits

View file

@ -4,13 +4,14 @@ use embedded_graphics::prelude::*;
use embedded_graphics_simulator::{ use embedded_graphics_simulator::{
OutputSettingsBuilder, SimulatorDisplay, SimulatorEvent, Window, OutputSettingsBuilder, SimulatorDisplay, SimulatorEvent, Window,
}; };
use lvgl::input_device::{InputData, Pointer}; use lvgl::input_device::{BufferStatus, InputData, Pointer};
use lvgl::style::Style; use lvgl::style::Style;
use lvgl::widgets::{Btn, Label}; use lvgl::widgets::{Btn, Label};
use lvgl::{self, Align, Color, LvError, Part, State, Widget, UI}; use lvgl::{self, Align, Color, LvError, Part, State, Widget, UI};
use std::cell::RefCell; use std::cell::RefCell;
use std::rc::Rc; use std::rc::Rc;
use std::time::Instant; use std::thread::sleep;
use std::time::{Duration, Instant};
fn main() -> Result<(), LvError> { fn main() -> Result<(), LvError> {
let display: SimulatorDisplay<Rgb565> = let display: SimulatorDisplay<Rgb565> =
@ -24,18 +25,17 @@ fn main() -> Result<(), LvError> {
// Implement and register your display: // Implement and register your display:
ui.disp_drv_register(display)?; ui.disp_drv_register(display)?;
// Initial state of input
let latest_touch_status: Rc<RefCell<BufferStatus>> = Rc::new(RefCell::new(
InputData::Touch(Point::new(0, 0)).released().once(),
));
// Register the input mode // Register the input mode
let latest_touch_point: Rc<RefCell<Option<Point>>> = Rc::new(RefCell::new(None)); let internal = Rc::clone(&latest_touch_status);
let internal = Rc::clone(&latest_touch_point);
let mut touch_screen = Pointer::new(move || { let mut touch_screen = Pointer::new(move || {
let info = internal.borrow().clone(); let input_status = internal.borrow().clone();
if info.is_some() { //println!("input_status = {:?}", input_status);
let point = info.unwrap(); input_status
println!("Changed to {:?}", point);
Some(InputData::Touch(point).pressed().once())
} else {
None
}
}); });
ui.indev_drv_register(&mut touch_screen)?; ui.indev_drv_register(&mut touch_screen)?;
@ -56,6 +56,7 @@ fn main() -> Result<(), LvError> {
let mut btn_state = false; let mut btn_state = false;
button.on_event(|mut btn, event| { button.on_event(|mut btn, event| {
println!("Some event! {:?}", event);
if let lvgl::Event::Clicked = event { if let lvgl::Event::Clicked = event {
if btn_state { if btn_state {
let nt = CString::new("Click me!").unwrap(); let nt = CString::new("Click me!").unwrap();
@ -71,11 +72,22 @@ fn main() -> Result<(), LvError> {
})?; })?;
let mut loop_started = Instant::now(); let mut loop_started = Instant::now();
let mut latest_touch_point = Point::new(0, 0);
'running: loop { 'running: loop {
ui.task_handler(); ui.task_handler();
window.update(ui.get_display_ref().unwrap()); 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 { match event {
SimulatorEvent::MouseButtonUp { SimulatorEvent::MouseButtonUp {
mouse_btn: _, mouse_btn: _,
@ -83,13 +95,16 @@ fn main() -> Result<(), LvError> {
} => { } => {
println!("Clicked on: {:?}", point); println!("Clicked on: {:?}", point);
// Send a event to the button directly // 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, SimulatorEvent::Quit => break 'running,
_ => {} _ => {}
} }
} }
sleep(Duration::from_millis(50));
ui.tick_inc(loop_started.elapsed()); ui.tick_inc(loop_started.elapsed());
loop_started = Instant::now(); loop_started = Instant::now();
} }

View file

@ -1,3 +1,4 @@
use crate::mem::Box;
use crate::LvResult; use crate::LvResult;
use core::mem::MaybeUninit; use core::mem::MaybeUninit;
use embedded_graphics::geometry::Point; use embedded_graphics::geometry::Point;
@ -26,7 +27,7 @@ pub enum InputState {
impl InputState { impl InputState {
pub fn once(self) -> BufferStatus { pub fn once(self) -> BufferStatus {
BufferStatus::Empty(self) BufferStatus::Once(self)
} }
pub fn and_continued(self) -> BufferStatus { pub fn and_continued(self) -> BufferStatus {
@ -36,35 +37,31 @@ impl InputState {
#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)] #[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
pub enum BufferStatus { pub enum BufferStatus {
Empty(InputState), Once(InputState),
Buffered(InputState), Buffered(InputState),
} }
pub struct Pointer<F> pub struct Pointer {
where
F: Fn() -> Option<BufferStatus>,
{
pub(crate) driver: lvgl_sys::lv_indev_drv_t, pub(crate) driver: lvgl_sys::lv_indev_drv_t,
pub(crate) descriptor: Option<lvgl_sys::lv_indev_t>, pub(crate) descriptor: Option<lvgl_sys::lv_indev_t>,
handler: F,
} }
impl<F> Pointer<F> impl Pointer {
pub fn new<F>(mut handler: F) -> Self
where where
F: Fn() -> Option<BufferStatus>, F: Fn() -> BufferStatus,
{ {
pub fn new(mut handler: F) -> Self {
let driver = unsafe { let driver = unsafe {
let mut indev_drv = MaybeUninit::uninit(); let mut indev_drv = MaybeUninit::uninit();
lvgl_sys::lv_indev_drv_init(indev_drv.as_mut_ptr()); lvgl_sys::lv_indev_drv_init(indev_drv.as_mut_ptr());
let mut indev_drv = indev_drv.assume_init(); 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.type_ = lvgl_sys::LV_INDEV_TYPE_POINTER as lvgl_sys::lv_indev_type_t;
indev_drv.read_cb = Some(read_input::<F>); indev_drv.read_cb = Some(read_input::<F>);
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 indev_drv
}; };
Self { Self {
handler,
driver, driver,
descriptor: None, descriptor: None,
} }
@ -85,47 +82,42 @@ unsafe extern "C" fn read_input<F>(
data: *mut lvgl_sys::lv_indev_data_t, data: *mut lvgl_sys::lv_indev_data_t,
) -> bool ) -> bool
where where
F: Fn() -> Option<BufferStatus>, F: Fn() -> BufferStatus,
{ {
let mut data = *data;
// convert user data to function // convert user data to function
let user_closure = &mut *((*indev_drv).user_data as *mut F); let user_closure = &mut *((*indev_drv).user_data as *mut F);
// call user data // call user data
let result: Option<BufferStatus> = user_closure(); let info: BufferStatus = user_closure();
return if let Some(info) = result {
match info { match info {
BufferStatus::Empty(InputState::Pressed(InputData::Touch(point))) => { BufferStatus::Once(InputState::Pressed(InputData::Touch(point))) => {
data.point.x = point.x as lvgl_sys::lv_coord_t; (*data).point.x = point.x as lvgl_sys::lv_coord_t;
data.point.y = point.y 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; (*data).state = lvgl_sys::LV_INDEV_STATE_PR as lvgl_sys::lv_indev_state_t;
false false
} }
BufferStatus::Empty(InputState::Released(InputData::Touch(point))) => { BufferStatus::Once(InputState::Released(InputData::Touch(point))) => {
data.point.x = point.x as lvgl_sys::lv_coord_t; (*data).point.x = point.x as lvgl_sys::lv_coord_t;
data.point.y = point.y 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; (*data).state = lvgl_sys::LV_INDEV_STATE_REL as lvgl_sys::lv_indev_state_t;
false false
} }
BufferStatus::Buffered(InputState::Pressed(InputData::Touch(point))) => { BufferStatus::Buffered(InputState::Pressed(InputData::Touch(point))) => {
data.point.x = point.x as lvgl_sys::lv_coord_t; (*data).point.x = point.x as lvgl_sys::lv_coord_t;
data.point.y = point.y 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; (*data).state = lvgl_sys::LV_INDEV_STATE_PR as lvgl_sys::lv_indev_state_t;
true true
} }
BufferStatus::Buffered(InputState::Released(InputData::Touch(point))) => { BufferStatus::Buffered(InputState::Released(InputData::Touch(point))) => {
data.point.x = point.x as lvgl_sys::lv_coord_t; (*data).point.x = point.x as lvgl_sys::lv_coord_t;
data.point.y = point.y 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; (*data).state = lvgl_sys::LV_INDEV_STATE_REL as lvgl_sys::lv_indev_state_t;
true true
} }
BufferStatus::Empty(InputState::Released(InputData::Key(_))) => false, BufferStatus::Once(InputState::Released(InputData::Key(_))) => false,
BufferStatus::Empty(InputState::Pressed(InputData::Key(_))) => false, BufferStatus::Once(InputState::Pressed(InputData::Key(_))) => false,
BufferStatus::Buffered(InputState::Released(InputData::Key(_))) => true, BufferStatus::Buffered(InputState::Released(InputData::Key(_))) => true,
BufferStatus::Buffered(InputState::Pressed(InputData::Key(_))) => true, BufferStatus::Buffered(InputState::Pressed(InputData::Key(_))) => true,
} }
} else {
false
};
} }
#[cfg(test)] #[cfg(test)]

View file

@ -61,6 +61,7 @@ impl From<Color> for Rgb565 {
/// ///
/// All objects (such as Buttons/Labels/Sliders etc.) receive these generic events /// All objects (such as Buttons/Labels/Sliders etc.) receive these generic events
/// regardless of their type. /// regardless of their type.
#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
pub enum Event<T> { pub enum Event<T> {
/// The object has been pressed /// The object has been pressed
Pressed, Pressed,
@ -140,6 +141,7 @@ impl<S> From<Event<S>> for lvgl_sys::lv_event_t {
} }
/// These events are sent only by pointer-like input devices (E.g. mouse or touchpad) /// 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 { pub enum PointerEvent {
DragBegin, DragBegin,
DragEnd, DragEnd,

View file

@ -57,10 +57,7 @@ where
} }
} }
pub fn indev_drv_register<F>(&mut self, input_device: &mut Pointer<F>) -> LvResult<()> pub fn indev_drv_register(&mut self, input_device: &mut Pointer) -> LvResult<()> {
where
F: Fn() -> Option<BufferStatus>,
{
unsafe { unsafe {
let descr = lvgl_sys::lv_indev_drv_register(&mut input_device.driver as *mut _); let descr = lvgl_sys::lv_indev_drv_register(&mut input_device.driver as *mut _);
input_device.set_descriptor(descr)?; input_device.set_descriptor(descr)?;