use std::rc::Rc; use std::thread::sleep; use std::time::{Duration, Instant}; use evdev::KeyCode; use slint::LogicalPosition; use slint::platform::software_renderer::{MinimalSoftwareWindow, RepaintBufferType}; use slint::platform::{Platform, WindowEvent}; use self::input::InputState; use self::screen::Screen; type UpdateFn = fn(&mut Context, &mut S) -> bool; mod input; mod screen; pub struct Context { pub screen: Screen, pub input: InputState, } pub struct Trekstor { state: S, ctx: Context, window: Rc, last_time: Instant, current_time: Instant, update_timestep: Duration, } impl Trekstor { pub fn new(update_fps: i32, state: S) -> Self { let screen = Screen::new(); let input = InputState::new(&screen); let window = MinimalSoftwareWindow::new(RepaintBufferType::ReusedBuffer); Self { state, ctx: Context { screen, input }, window, current_time: Instant::now(), last_time: Instant::now(), update_timestep: Duration::from_nanos( (1_000_000_000f64 / update_fps as f64).round() as u64 ), } } pub fn update(&mut self) { loop { self.current_time = Instant::now(); let dt = self.current_time - self.last_time; self.last_time = self.current_time; if dt < self.update_timestep { sleep(self.update_timestep - dt); } self.ctx.input.handle_event(); slint::platform::update_timers_and_animations(); if self.ctx.input.is_just_pressed(KeyCode::BTN_TOUCH) { self.window.try_dispatch_event(WindowEvent::PointerPressed { position: LogicalPosition::new( self.ctx.input.x as f32, self.ctx.input.y as f32, ), button: slint::platform::PointerEventButton::Left, }); } if self.ctx.input.is_just_released(KeyCode::BTN_TOUCH) { self.window .try_dispatch_event(WindowEvent::PointerReleased { position: LogicalPosition::new( self.ctx.input.x as f32, self.ctx.input.y as f32, ), button: slint::platform::PointerEventButton::Left, }); } self.ctx.screen.flush(); self.ctx.input.finish(); } } } impl Platform for Trekstor { fn create_window_adapter( &self, ) -> Result, slint::PlatformError> { Ok(self.window.clone()) } // .. }