use super::*;
use anyhow::Result;
use log::*;
use crate::kanata::CalculatedMouseMove;
use kanata_parser::custom_action::*;
use std::io;
#[cfg(not(any(target_os = "windows", target_os = "macos")))]
use std::fmt;
use std::sync::Arc;
use std::sync::OnceLock;
type CbOutEvFn = dyn Fn(i64, i64, i64) -> i64 + Send + Sync + 'static; pub struct FnOutEvWrapper {
pub cb: Arc<CbOutEvFn>,
} pub static OUTEVWRAP: OnceLock<FnOutEvWrapper> = OnceLock::new();
use std::sync::mpsc::{SendError, Sender as ASender};
pub struct KbdOut {
pub tx_kout: Option<ASender<InputEvent>>,
}
use std::io::{Error as IoErr, ErrorKind::NotConnected};
impl KbdOut {
#[cfg(not(any(target_os = "linux", target_os = "android")))]
pub fn new() -> Result<Self, io::Error> {
Ok(Self { tx_kout: None })
}
#[cfg(any(target_os = "linux", target_os = "android"))]
pub fn new(
_s: &Option<String>,
_tp: bool,
_name: &str,
_bustype: evdev::BusType,
) -> Result<Self, io::Error> {
Ok(Self { tx_kout: None })
}
#[cfg(any(target_os = "linux", target_os = "android"))]
pub fn write_raw(&mut self, event: InputEvent) -> Result<(), io::Error> {
trace!("out-raw:{event:?}");
Ok(())
}
pub fn write(&mut self, event: InputEvent) -> Result<(), io::Error> {
trace!("out:{event}");
if let Some(tx_kout) = &self.tx_kout {
match tx_kout.send(event) {
Ok(res) => {
debug!(
"✓ tx_kout → rx_kout@key_out(dll) ‘{event}’ from send_out_ev_msg@sim_passthru(oskbd)"
);
return Ok(res);
}
Err(SendError(event)) => {
error!(
"✗ tx_kout → rx_kout@key_out(dll) ‘{event}’ from send_out_ev_msg@sim_passthru(oskbd)"
);
return Err(IoErr::new(
NotConnected,
format!("Failed sending sending {event}"),
));
}
}
} else {
debug!("✗ tx_kout doesn't exist");
}
Ok(())
}
pub fn write_key(&mut self, key: OsCode, value: KeyValue) -> Result<(), io::Error> {
let key_ev = KeyEvent::new(key, value);
let event = {
#[cfg(target_os = "macos")]
{
key_ev.try_into().unwrap()
}
#[cfg(not(target_os = "macos"))]
{
key_ev.into()
}
};
self.write(event)
}
pub fn write_code(&mut self, code: u32, value: KeyValue) -> Result<(), io::Error> {
trace!("out-code:{code};{value:?}");
Ok(())
}
pub fn press_key(&mut self, key: OsCode) -> Result<(), io::Error> {
self.write_key(key, KeyValue::Press)
}
pub fn release_key(&mut self, key: OsCode) -> Result<(), io::Error> {
self.write_key(key, KeyValue::Release)
}
pub fn send_unicode(&mut self, c: char) -> Result<(), io::Error> {
trace!("outU:{c}");
Ok(())
}
pub fn click_btn(&mut self, btn: Btn) -> Result<(), io::Error> {
trace!("out🖰:↓{btn:?}");
Ok(())
}
pub fn release_btn(&mut self, btn: Btn) -> Result<(), io::Error> {
trace!("out🖰:↑{btn:?}");
Ok(())
}
pub fn scroll(&mut self, direction: MWheelDirection, distance: u16) -> Result<(), io::Error> {
trace!("scroll:{direction:?},{distance:?}");
Ok(())
}
pub fn move_mouse(&mut self, mv: CalculatedMouseMove) -> Result<(), io::Error> {
let (direction, distance) = (mv.direction, mv.distance);
trace!("out🖰:move {direction:?},{distance:?}");
Ok(())
}
pub fn move_mouse_many(&mut self, moves: &[CalculatedMouseMove]) -> Result<(), io::Error> {
for mv in moves {
let (direction, distance) = (&mv.direction, &mv.distance);
trace!("out🖰:move {direction:?},{distance:?}");
}
Ok(())
}
pub fn set_mouse(&mut self, x: u16, y: u16) -> Result<(), io::Error> {
log::info!("out🖰:@{x},{y}");
Ok(())
}
pub fn tick(&mut self) {}
}
#[cfg(not(any(target_os = "windows", target_os = "macos")))]
#[derive(Debug, Clone, Copy)]
pub struct InputEvent {
pub code: u32,
pub up: bool,
}
#[cfg(not(any(target_os = "windows", target_os = "macos")))]
impl fmt::Display for InputEvent {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use kanata_keyberon::key_code::KeyCode;
let direction = if self.up { "↑" } else { "↓" };
let key_name = KeyCode::from(OsCode::from(self.code));
write!(f, "{}{:?}", direction, key_name)
}
}
#[cfg(not(any(target_os = "windows", target_os = "macos")))]
impl InputEvent {
pub fn from_oscode(code: OsCode, val: KeyValue) -> Self {
Self {
code: code.into(),
up: val.into(),
}
}
}
#[cfg(not(any(target_os = "windows", target_os = "macos")))]
impl TryFrom<InputEvent> for KeyEvent {
type Error = ();
fn try_from(item: InputEvent) -> Result<Self, Self::Error> {
Ok(Self {
code: OsCode::from_u16(item.code as u16).ok_or(())?,
value: match item.up {
true => KeyValue::Release,
false => KeyValue::Press,
},
})
}
}
#[cfg(not(any(target_os = "windows", target_os = "macos")))]
impl From<KeyEvent> for InputEvent {
fn from(item: KeyEvent) -> Self {
Self {
code: item.code.into(),
up: item.value.into(),
}
}
}