add evfb (evdev + fbdev) backend
Outside of a terminal emulator or web browser, this typing experience can be useful outside the DE, such as in the TTY or when entering a password for full-disk encryption. Add a target that uses the bare hardware to allow the keyboard to be deployed in more flexible environments.
This commit is contained in:
parent
9b893e474d
commit
7b38edb656
12 changed files with 866 additions and 0 deletions
80
src/ufkbd_evfb.rs
Normal file
80
src/ufkbd_evfb.rs
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
/*
|
||||
* Copyright (c) 2025, Richard Acayan. All rights reserved.
|
||||
*/
|
||||
|
||||
mod core;
|
||||
mod evdev;
|
||||
mod fbdev;
|
||||
mod linux;
|
||||
|
||||
use crate::core::Button;
|
||||
use crate::core::Configuration;
|
||||
use crate::core::Display;
|
||||
use crate::core::Graphics;
|
||||
use crate::core::Layout;
|
||||
use crate::evdev::Touchscreen;
|
||||
use crate::evdev::VirtualKeyboard;
|
||||
use crate::fbdev::Framebuffer;
|
||||
use crate::linux::Teletype;
|
||||
use polling::Event;
|
||||
use polling::Events;
|
||||
use polling::Poller;
|
||||
use signal_hook::consts::signal;
|
||||
use signal_hook::iterator::Signals;
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
use std::time::Instant;
|
||||
|
||||
fn main()
|
||||
{
|
||||
let cfg = Configuration::load().unwrap();
|
||||
let disp = Framebuffer::new(&cfg).unwrap();
|
||||
|
||||
let gfx = Graphics::new(disp, &cfg);
|
||||
let gfx = Mutex::new(gfx);
|
||||
let gfx = Arc::new(gfx);
|
||||
|
||||
let tty = Teletype::new(&cfg).unwrap();
|
||||
let kbd = VirtualKeyboard::new(tty).unwrap();
|
||||
let layout = Layout::load(&cfg).unwrap();
|
||||
let mut btn = Button::new(&cfg, layout, kbd, gfx.clone());
|
||||
btn.set_text_supported(true);
|
||||
|
||||
{
|
||||
let mut gfx = gfx.lock().unwrap();
|
||||
let (width, height) = gfx.display().size();
|
||||
gfx.resize(btn.layout(), btn.mod_state(), width, height);
|
||||
}
|
||||
|
||||
let mut touchscreen = Touchscreen::new(btn, &cfg).unwrap();
|
||||
|
||||
let mut events = Events::new();
|
||||
let poller = Poller::new().unwrap();
|
||||
let ts_evt = Event::readable(0);
|
||||
|
||||
let mut sigs = Signals::new([
|
||||
signal::SIGHUP,
|
||||
signal::SIGINT,
|
||||
signal::SIGPIPE,
|
||||
signal::SIGTERM,
|
||||
]).unwrap();
|
||||
|
||||
while sigs.pending().next().is_none() {
|
||||
let timer = touchscreen.button().next_time().map(|t| t - Instant::now());
|
||||
|
||||
unsafe {
|
||||
poller.add(&touchscreen, ts_evt).unwrap();
|
||||
}
|
||||
|
||||
events.clear();
|
||||
poller.wait(&mut events, timer).unwrap();
|
||||
poller.delete(&touchscreen).unwrap();
|
||||
|
||||
if !events.is_empty() {
|
||||
touchscreen.handle_events();
|
||||
}
|
||||
|
||||
touchscreen.dispatch_timers();
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue