mirror of
https://github.com/feschber/lan-mouse.git
synced 2026-04-22 12:33:19 +03:00
committed by
GitHub
parent
daf8818a9f
commit
9e56c546cd
@@ -8,6 +8,8 @@ use std::{error::Error, fs};
|
|||||||
use toml;
|
use toml;
|
||||||
|
|
||||||
use crate::client::Position;
|
use crate::client::Position;
|
||||||
|
use crate::scancode;
|
||||||
|
use crate::scancode::Linux::{KeyLeftAlt, KeyLeftCtrl, KeyLeftMeta, KeyLeftShift};
|
||||||
|
|
||||||
pub const DEFAULT_PORT: u16 = 4242;
|
pub const DEFAULT_PORT: u16 = 4242;
|
||||||
|
|
||||||
@@ -15,6 +17,7 @@ pub const DEFAULT_PORT: u16 = 4242;
|
|||||||
pub struct ConfigToml {
|
pub struct ConfigToml {
|
||||||
pub port: Option<u16>,
|
pub port: Option<u16>,
|
||||||
pub frontend: Option<String>,
|
pub frontend: Option<String>,
|
||||||
|
pub release_bind: Option<Vec<scancode::Linux>>,
|
||||||
pub left: Option<TomlClient>,
|
pub left: Option<TomlClient>,
|
||||||
pub right: Option<TomlClient>,
|
pub right: Option<TomlClient>,
|
||||||
pub top: Option<TomlClient>,
|
pub top: Option<TomlClient>,
|
||||||
@@ -70,6 +73,7 @@ pub struct Config {
|
|||||||
pub port: u16,
|
pub port: u16,
|
||||||
pub clients: Vec<(TomlClient, Position)>,
|
pub clients: Vec<(TomlClient, Position)>,
|
||||||
pub daemon: bool,
|
pub daemon: bool,
|
||||||
|
pub release_bind: Vec<scancode::Linux>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ConfigClient {
|
pub struct ConfigClient {
|
||||||
@@ -80,6 +84,9 @@ pub struct ConfigClient {
|
|||||||
pub active: bool,
|
pub active: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const DEFAULT_RELEASE_KEYS: [scancode::Linux; 4] =
|
||||||
|
[KeyLeftCtrl, KeyLeftShift, KeyLeftMeta, KeyLeftAlt];
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
pub fn new() -> Result<Self> {
|
pub fn new() -> Result<Self> {
|
||||||
let args = CliArgs::parse();
|
let args = CliArgs::parse();
|
||||||
@@ -138,6 +145,12 @@ impl Config {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
log::debug!("{config_toml:?}");
|
||||||
|
let release_bind = config_toml
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|c| c.release_bind.clone())
|
||||||
|
.unwrap_or(Vec::from_iter(DEFAULT_RELEASE_KEYS.iter().cloned()));
|
||||||
|
|
||||||
let mut clients: Vec<(TomlClient, Position)> = vec![];
|
let mut clients: Vec<(TomlClient, Position)> = vec![];
|
||||||
|
|
||||||
if let Some(config_toml) = config_toml {
|
if let Some(config_toml) = config_toml {
|
||||||
@@ -162,6 +175,7 @@ impl Config {
|
|||||||
frontend,
|
frontend,
|
||||||
clients,
|
clients,
|
||||||
port,
|
port,
|
||||||
|
release_bind,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ pub fn run() -> Result<()> {
|
|||||||
// parse config file + cli args
|
// parse config file + cli args
|
||||||
let config = Config::new()?;
|
let config = Config::new()?;
|
||||||
log::debug!("{config:?}");
|
log::debug!("{config:?}");
|
||||||
|
log::info!("release bind: {:?}", config.release_bind);
|
||||||
|
|
||||||
if config.daemon {
|
if config.daemon {
|
||||||
// if daemon is specified we run the service
|
// if daemon is specified we run the service
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* https://learn.microsoft.com/en-us/windows/win32/inputdev/about-keyboard-input
|
* https://learn.microsoft.com/en-us/windows/win32/inputdev/about-keyboard-input
|
||||||
*/
|
*/
|
||||||
@@ -165,7 +167,7 @@ pub enum Windows {
|
|||||||
* https://github.com/torvalds/linux/blob/master/include/uapi/linux/input-event-codes.h
|
* https://github.com/torvalds/linux/blob/master/include/uapi/linux/input-event-codes.h
|
||||||
*/
|
*/
|
||||||
#[repr(u32)]
|
#[repr(u32)]
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Serialize, Deserialize, Debug, Clone, Copy, Eq, Hash, PartialEq)]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub enum Linux {
|
pub enum Linux {
|
||||||
KeyReserved = 0,
|
KeyReserved = 0,
|
||||||
@@ -210,7 +212,7 @@ pub enum Linux {
|
|||||||
KeySemicolon = 39,
|
KeySemicolon = 39,
|
||||||
KeyApostrophe = 40,
|
KeyApostrophe = 40,
|
||||||
KeyGrave = 41,
|
KeyGrave = 41,
|
||||||
KeyLeftshift = 42,
|
KeyLeftShift = 42,
|
||||||
KeyBackslash = 43,
|
KeyBackslash = 43,
|
||||||
KeyZ = 44,
|
KeyZ = 44,
|
||||||
KeyX = 45,
|
KeyX = 45,
|
||||||
@@ -224,7 +226,7 @@ pub enum Linux {
|
|||||||
KeySlash = 53,
|
KeySlash = 53,
|
||||||
KeyRightShift = 54,
|
KeyRightShift = 54,
|
||||||
KeyKpAsterisk = 55,
|
KeyKpAsterisk = 55,
|
||||||
KeyLeftalt = 56,
|
KeyLeftAlt = 56,
|
||||||
KeySpace = 57,
|
KeySpace = 57,
|
||||||
KeyCapsLock = 58,
|
KeyCapsLock = 58,
|
||||||
KeyF1 = 59,
|
KeyF1 = 59,
|
||||||
@@ -294,7 +296,7 @@ pub enum Linux {
|
|||||||
// KEY_HANGUEL = KeyHangeul,
|
// KEY_HANGUEL = KeyHangeul,
|
||||||
KeyHanja = 123,
|
KeyHanja = 123,
|
||||||
KeyYen = 124,
|
KeyYen = 124,
|
||||||
KeyLeftmeta = 125,
|
KeyLeftMeta = 125,
|
||||||
KeyRightmeta = 126,
|
KeyRightmeta = 126,
|
||||||
KeyCompose = 127,
|
KeyCompose = 127,
|
||||||
KeyStop = 128, /* AC Stop */
|
KeyStop = 128, /* AC Stop */
|
||||||
@@ -485,7 +487,7 @@ impl TryFrom<Linux> for Windows {
|
|||||||
Linux::KeySemicolon => Ok(Self::KeySemiColon),
|
Linux::KeySemicolon => Ok(Self::KeySemiColon),
|
||||||
Linux::KeyApostrophe => Ok(Self::KeyApostrophe),
|
Linux::KeyApostrophe => Ok(Self::KeyApostrophe),
|
||||||
Linux::KeyGrave => Ok(Self::KeyGrave),
|
Linux::KeyGrave => Ok(Self::KeyGrave),
|
||||||
Linux::KeyLeftshift => Ok(Self::KeyLeftShift),
|
Linux::KeyLeftShift => Ok(Self::KeyLeftShift),
|
||||||
Linux::KeyBackslash => Ok(Self::KeyBackslash),
|
Linux::KeyBackslash => Ok(Self::KeyBackslash),
|
||||||
Linux::KeyZ => Ok(Self::KeyZ),
|
Linux::KeyZ => Ok(Self::KeyZ),
|
||||||
Linux::KeyX => Ok(Self::KeyX),
|
Linux::KeyX => Ok(Self::KeyX),
|
||||||
@@ -499,7 +501,7 @@ impl TryFrom<Linux> for Windows {
|
|||||||
Linux::KeySlash => Ok(Self::KeySlash),
|
Linux::KeySlash => Ok(Self::KeySlash),
|
||||||
Linux::KeyRightShift => Ok(Self::KeyRightShift),
|
Linux::KeyRightShift => Ok(Self::KeyRightShift),
|
||||||
Linux::KeyKpAsterisk => Ok(Self::KeypadStar),
|
Linux::KeyKpAsterisk => Ok(Self::KeypadStar),
|
||||||
Linux::KeyLeftalt => Ok(Self::KeyLeftAlt),
|
Linux::KeyLeftAlt => Ok(Self::KeyLeftAlt),
|
||||||
Linux::KeySpace => Ok(Self::KeySpace),
|
Linux::KeySpace => Ok(Self::KeySpace),
|
||||||
Linux::KeyCapsLock => Ok(Self::KeyCapsLock),
|
Linux::KeyCapsLock => Ok(Self::KeyCapsLock),
|
||||||
Linux::KeyF1 => Ok(Self::KeyF1),
|
Linux::KeyF1 => Ok(Self::KeyF1),
|
||||||
@@ -567,7 +569,7 @@ impl TryFrom<Linux> for Windows {
|
|||||||
Linux::KeyHangeul => Ok(Self::KeyInternational1), // TODO unsure
|
Linux::KeyHangeul => Ok(Self::KeyInternational1), // TODO unsure
|
||||||
Linux::KeyHanja => Ok(Self::KeyInternational2), // TODO unsure
|
Linux::KeyHanja => Ok(Self::KeyInternational2), // TODO unsure
|
||||||
Linux::KeyYen => Ok(Self::KeyInternational3), // TODO unsure
|
Linux::KeyYen => Ok(Self::KeyInternational3), // TODO unsure
|
||||||
Linux::KeyLeftmeta => Ok(Self::KeyLeftGUI),
|
Linux::KeyLeftMeta => Ok(Self::KeyLeftGUI),
|
||||||
Linux::KeyRightmeta => Ok(Self::KeyRightGUI),
|
Linux::KeyRightmeta => Ok(Self::KeyRightGUI),
|
||||||
Linux::KeyCompose => Ok(Self::KeyApplication),
|
Linux::KeyCompose => Ok(Self::KeyApplication),
|
||||||
Linux::KeyStop => Ok(Self::ACStop),
|
Linux::KeyStop => Ok(Self::ACStop),
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ pub struct Server {
|
|||||||
client_manager: Rc<RefCell<ClientManager>>,
|
client_manager: Rc<RefCell<ClientManager>>,
|
||||||
port: Rc<Cell<u16>>,
|
port: Rc<Cell<u16>>,
|
||||||
state: Rc<Cell<State>>,
|
state: Rc<Cell<State>>,
|
||||||
|
release_bind: Vec<crate::scancode::Linux>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Server {
|
impl Server {
|
||||||
@@ -57,11 +58,13 @@ impl Server {
|
|||||||
config_client.active,
|
config_client.active,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
let release_bind = config.release_bind.clone();
|
||||||
Self {
|
Self {
|
||||||
active_client,
|
active_client,
|
||||||
client_manager,
|
client_manager,
|
||||||
port,
|
port,
|
||||||
state,
|
state,
|
||||||
|
release_bind,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,8 +88,13 @@ impl Server {
|
|||||||
network_task::new(self.clone(), frontend_notify_tx).await?;
|
network_task::new(self.clone(), frontend_notify_tx).await?;
|
||||||
|
|
||||||
// event producer
|
// event producer
|
||||||
let (mut producer_task, producer_channel) =
|
let (mut producer_task, producer_channel) = producer_task::new(
|
||||||
producer_task::new(producer, self.clone(), sender_tx.clone(), timer_tx.clone());
|
producer,
|
||||||
|
self.clone(),
|
||||||
|
sender_tx.clone(),
|
||||||
|
timer_tx.clone(),
|
||||||
|
self.release_bind.clone(),
|
||||||
|
);
|
||||||
|
|
||||||
// event consumer
|
// event consumer
|
||||||
let (mut consumer_task, consumer_channel) = consumer_task::new(
|
let (mut consumer_task, consumer_channel) = consumer_task::new(
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
use std::net::SocketAddr;
|
use std::{collections::HashSet, net::SocketAddr};
|
||||||
|
|
||||||
use tokio::{sync::mpsc::Sender, task::JoinHandle};
|
use tokio::{sync::mpsc::Sender, task::JoinHandle};
|
||||||
|
|
||||||
@@ -8,6 +8,7 @@ use crate::{
|
|||||||
client::{ClientEvent, ClientHandle},
|
client::{ClientEvent, ClientHandle},
|
||||||
event::{Event, KeyboardEvent},
|
event::{Event, KeyboardEvent},
|
||||||
producer::EventProducer,
|
producer::EventProducer,
|
||||||
|
scancode,
|
||||||
server::State,
|
server::State,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -28,14 +29,16 @@ pub fn new(
|
|||||||
server: Server,
|
server: Server,
|
||||||
sender_tx: Sender<(Event, SocketAddr)>,
|
sender_tx: Sender<(Event, SocketAddr)>,
|
||||||
timer_tx: Sender<()>,
|
timer_tx: Sender<()>,
|
||||||
|
release_bind: Vec<scancode::Linux>,
|
||||||
) -> (JoinHandle<Result<()>>, Sender<ProducerEvent>) {
|
) -> (JoinHandle<Result<()>>, Sender<ProducerEvent>) {
|
||||||
let (tx, mut rx) = tokio::sync::mpsc::channel(32);
|
let (tx, mut rx) = tokio::sync::mpsc::channel(32);
|
||||||
let task = tokio::task::spawn_local(async move {
|
let task = tokio::task::spawn_local(async move {
|
||||||
|
let mut pressed_keys = HashSet::new();
|
||||||
loop {
|
loop {
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
event = producer.next() => {
|
event = producer.next() => {
|
||||||
let event = event.ok_or(anyhow!("event producer closed"))??;
|
let event = event.ok_or(anyhow!("event producer closed"))??;
|
||||||
handle_producer_event(&server, &mut producer, &sender_tx, &timer_tx, event).await?;
|
handle_producer_event(&server, &mut producer, &sender_tx, &timer_tx, event, &mut pressed_keys, &release_bind).await?;
|
||||||
}
|
}
|
||||||
e = rx.recv() => {
|
e = rx.recv() => {
|
||||||
log::debug!("producer notify rx: {e:?}");
|
log::debug!("producer notify rx: {e:?}");
|
||||||
@@ -59,7 +62,15 @@ pub fn new(
|
|||||||
(task, tx)
|
(task, tx)
|
||||||
}
|
}
|
||||||
|
|
||||||
const RELEASE_MODIFIERDS: u32 = 77; // ctrl+shift+super+alt
|
fn update_pressed_keys(pressed_keys: &mut HashSet<scancode::Linux>, key: u32, state: u8) {
|
||||||
|
if let Ok(scancode) = scancode::Linux::try_from(key) {
|
||||||
|
log::debug!("key: {key}, state: {state}, scancode: {scancode:?}");
|
||||||
|
match state {
|
||||||
|
1 => pressed_keys.insert(scancode),
|
||||||
|
_ => pressed_keys.remove(&scancode),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async fn handle_producer_event(
|
async fn handle_producer_event(
|
||||||
server: &Server,
|
server: &Server,
|
||||||
@@ -67,12 +78,18 @@ async fn handle_producer_event(
|
|||||||
sender_tx: &Sender<(Event, SocketAddr)>,
|
sender_tx: &Sender<(Event, SocketAddr)>,
|
||||||
timer_tx: &Sender<()>,
|
timer_tx: &Sender<()>,
|
||||||
event: (ClientHandle, Event),
|
event: (ClientHandle, Event),
|
||||||
|
pressed_keys: &mut HashSet<scancode::Linux>,
|
||||||
|
release_bind: &[scancode::Linux],
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let (c, mut e) = event;
|
let (c, mut e) = event;
|
||||||
log::trace!("({c}) {e:?}");
|
log::trace!("({c}) {e:?}");
|
||||||
|
|
||||||
if let Event::Keyboard(KeyboardEvent::Modifiers { mods_depressed, .. }) = e {
|
if let Event::Keyboard(KeyboardEvent::Key { key, state, .. }) = e {
|
||||||
if mods_depressed == RELEASE_MODIFIERDS {
|
update_pressed_keys(pressed_keys, key, state);
|
||||||
|
log::debug!("{pressed_keys:?}");
|
||||||
|
if release_bind.iter().all(|k| pressed_keys.contains(k)) {
|
||||||
|
pressed_keys.clear();
|
||||||
|
log::info!("releasing pointer");
|
||||||
producer.release()?;
|
producer.release()?;
|
||||||
server.state.replace(State::Receiving);
|
server.state.replace(State::Receiving);
|
||||||
log::trace!("STATE ===> Receiving");
|
log::trace!("STATE ===> Receiving");
|
||||||
|
|||||||
Reference in New Issue
Block a user