use std::any::Any;
use std::io;
use std::sync::mpsc::Sender;
pub mod devicequery;
#[cfg(target_os = "linux")]
pub mod evdev_backend;
pub use device_query::Keycode;
#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Button {
Left,
Middle,
Right,
Other(u16),
}
impl Button {
pub fn label(self, lang: crate::i18n::Lang) -> String {
use crate::i18n::Lang::{En, Fr};
match (lang, self) {
(Fr, Button::Left) => "gauche".into(),
(Fr, Button::Middle) => "milieu".into(),
(Fr, Button::Right) => "droit".into(),
(Fr, Button::Other(n)) => format!("bouton {n}"),
(En, Button::Left) => "left".into(),
(En, Button::Middle) => "middle".into(),
(En, Button::Right) => "right".into(),
(En, Button::Other(n)) => format!("button {n}"),
}
}
}
#[derive(Clone, Debug)]
pub enum InputEvent {
MouseUp {
button: Button,
pos: Option<(i32, i32)>,
},
KeyDown(Keycode),
KeyUp(Keycode),
}
pub struct InputHandle {
_inner: Box<dyn Any + Send>,
}
impl InputHandle {
pub(crate) fn new(inner: impl Any + Send) -> Self {
Self {
_inner: Box::new(inner),
}
}
}
pub trait InputBackend: Send {
fn name(&self) -> &'static str;
fn start(&self, tx: Sender<InputEvent>) -> io::Result<InputHandle>;
}
pub fn select() -> Box<dyn InputBackend> {
#[cfg(target_os = "linux")]
{
if is_wayland() {
return Box::new(evdev_backend::EvdevBackend);
}
}
Box::new(devicequery::DeviceQueryBackend)
}
#[cfg(target_os = "linux")]
pub fn is_wayland() -> bool {
std::env::var("XDG_SESSION_TYPE")
.map(|v| v.eq_ignore_ascii_case("wayland"))
.unwrap_or(false)
|| std::env::var_os("WAYLAND_DISPLAY").is_some()
}