mirror of
https://github.com/htrefil/rkvm.git
synced 2025-01-30 20:34:13 +01:00
Handle repeated keys
This commit is contained in:
parent
57039fa93b
commit
16e1e6ce3f
4 changed files with 94 additions and 157 deletions
134
Cargo.lock
generated
134
Cargo.lock
generated
|
@ -228,101 +228,12 @@ version = "0.1.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
||||
|
||||
[[package]]
|
||||
name = "futures"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b3b0c040a1fe6529d30b3c5944b280c7f0dcb2930d2c3062bca967b602583d0"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-executor",
|
||||
"futures-io",
|
||||
"futures-sink",
|
||||
"futures-task",
|
||||
"futures-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-channel"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4b7109687aa4e177ef6fe84553af6280ef2778bdb7783ba44c9dc3399110fe64"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-core"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "847ce131b72ffb13b6109a221da9ad97a64cbe48feb1028356b836b47b8f1748"
|
||||
|
||||
[[package]]
|
||||
name = "futures-executor"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4caa2b2b68b880003057c1dd49f1ed937e38f22fcf6c212188a121f08cf40a65"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-task",
|
||||
"futures-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-io"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "611834ce18aaa1bd13c4b374f5d653e1027cf99b6b502584ff8c9a64413b30bb"
|
||||
|
||||
[[package]]
|
||||
name = "futures-macro"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77408a692f1f97bcc61dc001d752e00643408fbc922e4d634c655df50d595556"
|
||||
dependencies = [
|
||||
"proc-macro-hack",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-sink"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f878195a49cee50e006b02b93cf7e0a95a38ac7b776b4c4d9cc1207cd20fcb3d"
|
||||
|
||||
[[package]]
|
||||
name = "futures-task"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7c554eb5bf48b2426c4771ab68c6b14468b6e76cc90996f528c3338d761a4d0d"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-util"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d304cff4a7b99cfb7986f7d43fbe93d175e72e704a8860787cc95e9ffd85cbd2"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-io",
|
||||
"futures-macro",
|
||||
"futures-sink",
|
||||
"futures-task",
|
||||
"memchr",
|
||||
"pin-project",
|
||||
"pin-utils",
|
||||
"proc-macro-hack",
|
||||
"proc-macro-nested",
|
||||
"slab",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.1.15"
|
||||
|
@ -400,7 +311,6 @@ name = "input"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bindgen",
|
||||
"futures",
|
||||
"inotify",
|
||||
"libc",
|
||||
"serde",
|
||||
|
@ -531,12 +441,6 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0"
|
||||
|
||||
[[package]]
|
||||
name = "openssl"
|
||||
version = "0.10.30"
|
||||
|
@ -576,38 +480,12 @@ version = "0.1.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
|
||||
|
||||
[[package]]
|
||||
name = "pin-project"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee41d838744f60d959d7074e3afb6b35c7456d0f61cad38a24e35e6553f73841"
|
||||
dependencies = [
|
||||
"pin-project-internal",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-internal"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "81a4ffa594b66bff340084d4081df649a7dc049ac8d7fc458d8e628bfbbb2f86"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c917123afa01924fc84bb20c4c03f004d9c38e5127e3c039bbf7f4b9c76a2f6b"
|
||||
|
||||
[[package]]
|
||||
name = "pin-utils"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.19"
|
||||
|
@ -644,18 +522,6 @@ dependencies = [
|
|||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-hack"
|
||||
version = "0.5.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-nested"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eba180dafb9038b050a4c280019bbedf9f2467b61e5d892dcad585bb57aadc5a"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.24"
|
||||
|
|
|
@ -13,10 +13,10 @@ serde = { version = "1.0.117", features = ["derive"] }
|
|||
inotify = "0.9.1"
|
||||
tokio = { version = "0.3.3", features = ["fs", "io-util", "net", "sync", "rt", "time"] }
|
||||
libc = "0.2.77"
|
||||
futures = "0.3.7"
|
||||
|
||||
[target.'cfg(target_os = "windows")'.dependencies]
|
||||
winapi = { version = "0.3.9", features = ["winuser"] }
|
||||
tokio = { version = "0.3.3", features = ["sync"] }
|
||||
|
||||
[build-dependencies]
|
||||
bindgen = "0.55.1"
|
||||
|
|
|
@ -25,7 +25,7 @@ pub enum Direction {
|
|||
Down, // The key is pressed.
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, Hash)]
|
||||
pub enum KeyKind {
|
||||
Key(Key),
|
||||
Button(Button),
|
||||
|
|
|
@ -1,35 +1,106 @@
|
|||
use crate::event::Event;
|
||||
use crate::event::{Direction, Event, Key, KeyKind};
|
||||
use std::io::Error;
|
||||
use std::time::{Duration, Instant};
|
||||
use tokio::sync::mpsc::{self, UnboundedReceiver, UnboundedSender};
|
||||
use tokio::sync::oneshot::{self, Receiver};
|
||||
use tokio::time;
|
||||
use winapi::um::winuser::{self, INPUT};
|
||||
|
||||
pub struct EventWriter(());
|
||||
pub struct EventWriter {
|
||||
event_sender: UnboundedSender<Event>,
|
||||
error_receiver: Receiver<Error>,
|
||||
}
|
||||
|
||||
impl EventWriter {
|
||||
pub async fn new() -> Result<Self, Error> {
|
||||
Ok(Self(()))
|
||||
let (event_sender, event_receiver) = mpsc::unbounded_channel();
|
||||
let (error_sender, error_receiver) = oneshot::channel();
|
||||
|
||||
tokio::spawn(async move {
|
||||
if let Err(err) = handle_events(event_receiver).await {
|
||||
let _ = error_sender.send(err);
|
||||
}
|
||||
});
|
||||
|
||||
Ok(Self {
|
||||
event_sender,
|
||||
error_receiver,
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn write(&mut self, event: Event) -> Result<(), Error> {
|
||||
if let Some(mut events) = event.to_raw() {
|
||||
return self.write_raw(events.as_mut_slice());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_raw(&mut self, events: &mut [INPUT]) -> Result<(), Error> {
|
||||
let written = unsafe {
|
||||
winuser::SendInput(
|
||||
events.len() as _,
|
||||
events.as_mut_ptr(),
|
||||
std::mem::size_of_val(&events[0]) as _,
|
||||
)
|
||||
};
|
||||
|
||||
if written != 1 {
|
||||
return Err(Error::last_os_error());
|
||||
if let Ok(err) = self.error_receiver.try_recv() {
|
||||
return Err(err);
|
||||
}
|
||||
|
||||
self.event_sender.send(event).unwrap();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
const REPEAT_INTERVAL: Duration = Duration::from_millis(20);
|
||||
const REPEAT_AFTER: Duration = Duration::from_millis(500);
|
||||
|
||||
async fn handle_events(mut receiver: UnboundedReceiver<Event>) -> Result<(), Error> {
|
||||
let mut pressed: Option<(Key, Instant)> = None;
|
||||
let mut interval = time::interval(REPEAT_INTERVAL);
|
||||
|
||||
loop {
|
||||
tokio::select! {
|
||||
_ = interval.tick() => {
|
||||
if let Some((key, created)) = pressed {
|
||||
if created.elapsed() < REPEAT_AFTER {
|
||||
continue;
|
||||
}
|
||||
|
||||
write_event(Event::Key { kind: KeyKind::Key(key), direction: Direction::Down })?;
|
||||
}
|
||||
}
|
||||
event = receiver.recv() => {
|
||||
let event = match event {
|
||||
Some(event) => event,
|
||||
None => return Ok(()),
|
||||
};
|
||||
|
||||
if let Event::Key { kind: KeyKind::Key(key), direction } = event {
|
||||
match direction {
|
||||
Direction::Up => {
|
||||
if pressed.map(|(k, _)| k == key).unwrap_or(false) {
|
||||
pressed = None;
|
||||
}
|
||||
}
|
||||
Direction::Down => {
|
||||
pressed = Some((key, Instant::now()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
write_event(event)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn write_event(event: Event) -> Result<(), Error> {
|
||||
if let Some(mut events) = event.to_raw() {
|
||||
return write_raw(events.as_mut_slice());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_raw(events: &mut [INPUT]) -> Result<(), Error> {
|
||||
let written = unsafe {
|
||||
winuser::SendInput(
|
||||
events.len() as _,
|
||||
events.as_mut_ptr(),
|
||||
std::mem::size_of_val(&events[0]) as _,
|
||||
)
|
||||
};
|
||||
|
||||
if written != 1 {
|
||||
return Err(Error::last_os_error());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue