track pressed keys in input-capture (#170)

move pressed key tracking to input capture
This commit is contained in:
Ferdinand Schober
2024-08-09 13:18:23 +02:00
committed by GitHub
parent 096567640c
commit 266ad28c6b
9 changed files with 125 additions and 77 deletions

View File

@@ -8,7 +8,7 @@ use input_event::Event;
use crate::CaptureError;
use super::{CaptureHandle, InputCapture, Position};
use super::{Capture, CaptureHandle, Position};
pub struct DummyInputCapture {}
@@ -25,7 +25,7 @@ impl Default for DummyInputCapture {
}
#[async_trait]
impl InputCapture for DummyInputCapture {
impl Capture for DummyInputCapture {
async fn create(&mut self, _handle: CaptureHandle, _pos: Position) -> Result<(), CaptureError> {
Ok(())
}

View File

@@ -1,31 +1,32 @@
use std::fmt::Display;
use std::{collections::HashSet, fmt::Display, task::Poll};
use async_trait::async_trait;
use futures::StreamExt;
use futures_core::Stream;
use input_event::Event;
use input_event::{scancode, Event, KeyboardEvent};
pub use error::{CaptureCreationError, CaptureError, InputCaptureError};
pub mod error;
#[cfg(all(unix, feature = "libei", not(target_os = "macos")))]
pub mod libei;
mod libei;
#[cfg(target_os = "macos")]
pub mod macos;
mod macos;
#[cfg(all(unix, feature = "wayland", not(target_os = "macos")))]
pub mod wayland;
mod wayland;
#[cfg(windows)]
pub mod windows;
mod windows;
#[cfg(all(unix, feature = "x11", not(target_os = "macos")))]
pub mod x11;
mod x11;
/// fallback input capture (does not produce events)
pub mod dummy;
mod dummy;
pub type CaptureHandle = u64;
@@ -93,10 +94,79 @@ impl Display for Backend {
}
}
pub struct InputCapture {
capture: Box<dyn Capture>,
pressed_keys: HashSet<scancode::Linux>,
}
impl InputCapture {
/// create a new client with the given id
pub async fn create(&mut self, id: CaptureHandle, pos: Position) -> Result<(), CaptureError> {
self.capture.create(id, pos).await
}
/// destroy the client with the given id, if it exists
pub async fn destroy(&mut self, id: CaptureHandle) -> Result<(), CaptureError> {
self.capture.destroy(id).await
}
/// release mouse
pub async fn release(&mut self) -> Result<(), CaptureError> {
self.pressed_keys.clear();
self.capture.release().await
}
/// destroy the input capture
pub async fn terminate(&mut self) -> Result<(), CaptureError> {
self.capture.terminate().await
}
/// creates a new [`InputCapture`]
pub async fn new(backend: Option<Backend>) -> Result<Self, CaptureCreationError> {
let capture = create(backend).await?;
Ok(Self {
capture,
pressed_keys: HashSet::new(),
})
}
/// check whether the given keys are pressed
pub fn keys_pressed(&self, keys: &[scancode::Linux]) -> bool {
keys.iter().all(|k| self.pressed_keys.contains(k))
}
fn update_pressed_keys(&mut self, key: u32, state: u8) {
if let Ok(scancode) = scancode::Linux::try_from(key) {
log::debug!("key: {key}, state: {state}, scancode: {scancode:?}");
match state {
1 => self.pressed_keys.insert(scancode),
_ => self.pressed_keys.remove(&scancode),
};
}
}
}
impl Stream for InputCapture {
type Item = Result<(CaptureHandle, Event), CaptureError>;
fn poll_next(
mut self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> Poll<Option<Self::Item>> {
match self.capture.poll_next_unpin(cx) {
Poll::Ready(e) => {
if let Some(Ok((_, Event::Keyboard(KeyboardEvent::Key { key, state, .. })))) = e {
self.update_pressed_keys(key, state);
}
Poll::Ready(e)
}
Poll::Pending => Poll::Pending,
}
}
}
#[async_trait]
pub trait InputCapture:
Stream<Item = Result<(CaptureHandle, Event), CaptureError>> + Unpin
{
trait Capture: Stream<Item = Result<(CaptureHandle, Event), CaptureError>> + Unpin {
/// create a new client with the given id
async fn create(&mut self, id: CaptureHandle, pos: Position) -> Result<(), CaptureError>;
@@ -110,10 +180,10 @@ pub trait InputCapture:
async fn terminate(&mut self) -> Result<(), CaptureError>;
}
pub async fn create_backend(
async fn create_backend(
backend: Backend,
) -> Result<
Box<dyn InputCapture<Item = Result<(CaptureHandle, Event), CaptureError>>>,
Box<dyn Capture<Item = Result<(CaptureHandle, Event), CaptureError>>>,
CaptureCreationError,
> {
match backend {
@@ -131,10 +201,10 @@ pub async fn create_backend(
}
}
pub async fn create(
async fn create(
backend: Option<Backend>,
) -> Result<
Box<dyn InputCapture<Item = Result<(CaptureHandle, Event), CaptureError>>>,
Box<dyn Capture<Item = Result<(CaptureHandle, Event), CaptureError>>>,
CaptureCreationError,
> {
if let Some(backend) = backend {

View File

@@ -38,7 +38,7 @@ use input_event::Event;
use super::{
error::{CaptureError, LibeiCaptureCreationError, ReisConvertEventStreamError},
CaptureHandle, InputCapture as LanMouseInputCapture, Position,
Capture as LanMouseInputCapture, CaptureHandle, Position,
};
/* there is a bug in xdg-remote-desktop-portal-gnome / mutter that

View File

@@ -1,5 +1,5 @@
use crate::{
error::MacOSInputCaptureCreationError, CaptureError, CaptureHandle, InputCapture, Position,
error::MacOSInputCaptureCreationError, Capture, CaptureError, CaptureHandle, Position,
};
use async_trait::async_trait;
use futures_core::Stream;
@@ -24,7 +24,7 @@ impl Stream for MacOSInputCapture {
}
#[async_trait]
impl InputCapture for MacOSInputCapture {
impl Capture for MacOSInputCapture {
async fn create(&mut self, _id: CaptureHandle, _pos: Position) -> Result<(), CaptureError> {
Ok(())
}

View File

@@ -58,15 +58,13 @@ use wayland_client::{
Connection, Dispatch, DispatchError, EventQueue, QueueHandle, WEnum,
};
use tempfile;
use input_event::{Event, KeyboardEvent, PointerEvent};
use crate::CaptureError;
use super::{
error::{LayerShellCaptureCreationError, WaylandBindError},
CaptureHandle, InputCapture, Position,
Capture, CaptureHandle, Position,
};
struct Globals {
@@ -561,7 +559,7 @@ impl Inner {
}
#[async_trait]
impl InputCapture for WaylandInputCapture {
impl Capture for WaylandInputCapture {
async fn create(&mut self, handle: CaptureHandle, pos: Position) -> Result<(), CaptureError> {
self.add_client(handle, pos);
let inner = self.0.get_mut();

View File

@@ -37,7 +37,7 @@ use input_event::{
Event, KeyboardEvent, PointerEvent, BTN_BACK, BTN_FORWARD, BTN_LEFT, BTN_MIDDLE, BTN_RIGHT,
};
use super::{CaptureError, CaptureHandle, InputCapture, Position};
use super::{Capture, CaptureError, CaptureHandle, Position};
enum Request {
Create(CaptureHandle, Position),
@@ -64,7 +64,7 @@ unsafe fn signal_message_thread(event_type: EventType) {
}
#[async_trait]
impl InputCapture for WindowsInputCapture {
impl Capture for WindowsInputCapture {
async fn create(&mut self, handle: CaptureHandle, pos: Position) -> Result<(), CaptureError> {
unsafe {
{

View File

@@ -5,7 +5,7 @@ use futures_core::Stream;
use crate::CaptureError;
use super::InputCapture;
use super::Capture;
use input_event::Event;
use super::error::X11InputCaptureCreationError;
@@ -20,7 +20,7 @@ impl X11InputCapture {
}
#[async_trait]
impl InputCapture for X11InputCapture {
impl Capture for X11InputCapture {
async fn create(&mut self, _id: CaptureHandle, _pos: Position) -> Result<(), CaptureError> {
Ok(())
}