rename producer, consumer to emulation and capture (#98)

input emulation / input capture is clearer than event consumer and producer
This commit is contained in:
Ferdinand Schober
2024-03-21 20:26:57 +01:00
committed by GitHub
parent 78c9de45c7
commit 742b1585d7
23 changed files with 237 additions and 237 deletions

View File

@@ -22,55 +22,55 @@ pub mod windows;
#[cfg(all(unix, feature = "x11", not(target_os = "macos")))] #[cfg(all(unix, feature = "x11", not(target_os = "macos")))]
pub mod x11; pub mod x11;
/// fallback event producer /// fallback input capture (does not produce events)
pub mod dummy; pub mod dummy;
pub async fn create() -> Box<dyn EventProducer> { pub async fn create() -> Box<dyn InputCapture> {
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
match macos::MacOSProducer::new() { match macos::MacOSInputCapture::new() {
Ok(p) => return Box::new(p), Ok(p) => return Box::new(p),
Err(e) => log::info!("macos event producer not available: {e}"), Err(e) => log::info!("macos input capture not available: {e}"),
} }
#[cfg(windows)] #[cfg(windows)]
match windows::WindowsProducer::new() { match windows::WindowsInputCapture::new() {
Ok(p) => return Box::new(p), Ok(p) => return Box::new(p),
Err(e) => log::info!("windows event producer not available: {e}"), Err(e) => log::info!("windows input capture not available: {e}"),
} }
#[cfg(all(unix, feature = "libei", not(target_os = "macos")))] #[cfg(all(unix, feature = "libei", not(target_os = "macos")))]
match libei::LibeiProducer::new().await { match libei::LibeiInputCapture::new().await {
Ok(p) => { Ok(p) => {
log::info!("using libei event producer"); log::info!("using libei input capture");
return Box::new(p); return Box::new(p);
} }
Err(e) => log::info!("libei event producer not available: {e}"), Err(e) => log::info!("libei input capture not available: {e}"),
} }
#[cfg(all(unix, feature = "wayland", not(target_os = "macos")))] #[cfg(all(unix, feature = "wayland", not(target_os = "macos")))]
match wayland::WaylandEventProducer::new() { match wayland::WaylandInputCapture::new() {
Ok(p) => { Ok(p) => {
log::info!("using layer-shell event producer"); log::info!("using layer-shell input capture");
return Box::new(p); return Box::new(p);
} }
Err(e) => log::info!("layer_shell event producer not available: {e}"), Err(e) => log::info!("layer_shell input capture not available: {e}"),
} }
#[cfg(all(unix, feature = "x11", not(target_os = "macos")))] #[cfg(all(unix, feature = "x11", not(target_os = "macos")))]
match x11::X11Producer::new() { match x11::X11InputCapture::new() {
Ok(p) => { Ok(p) => {
log::info!("using x11 event producer"); log::info!("using x11 input capture");
return Box::new(p); return Box::new(p);
} }
Err(e) => log::info!("x11 event producer not available: {e}"), Err(e) => log::info!("x11 input capture not available: {e}"),
} }
log::error!("falling back to dummy event producer"); log::error!("falling back to dummy input capture");
Box::new(dummy::DummyProducer::new()) Box::new(dummy::DummyInputCapture::new())
} }
pub trait EventProducer: Stream<Item = io::Result<(ClientHandle, Event)>> + Unpin { pub trait InputCapture: Stream<Item = io::Result<(ClientHandle, Event)>> + Unpin {
/// notify event producer of configuration changes /// notify input capture of configuration changes
fn notify(&mut self, event: ClientEvent) -> io::Result<()>; fn notify(&mut self, event: ClientEvent) -> io::Result<()>;
/// release mouse /// release mouse

View File

@@ -4,26 +4,26 @@ use std::task::{Context, Poll};
use futures_core::Stream; use futures_core::Stream;
use crate::capture::InputCapture;
use crate::event::Event; use crate::event::Event;
use crate::producer::EventProducer;
use crate::client::{ClientEvent, ClientHandle}; use crate::client::{ClientEvent, ClientHandle};
pub struct DummyProducer {} pub struct DummyInputCapture {}
impl DummyProducer { impl DummyInputCapture {
pub fn new() -> Self { pub fn new() -> Self {
Self {} Self {}
} }
} }
impl Default for DummyProducer { impl Default for DummyInputCapture {
fn default() -> Self { fn default() -> Self {
Self::new() Self::new()
} }
} }
impl EventProducer for DummyProducer { impl InputCapture for DummyInputCapture {
fn notify(&mut self, _event: ClientEvent) -> io::Result<()> { fn notify(&mut self, _event: ClientEvent) -> io::Result<()> {
Ok(()) Ok(())
} }
@@ -33,7 +33,7 @@ impl EventProducer for DummyProducer {
} }
} }
impl Stream for DummyProducer { impl Stream for DummyInputCapture {
type Item = io::Result<(ClientHandle, Event)>; type Item = io::Result<(ClientHandle, Event)>;
fn poll_next(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Option<Self::Item>> { fn poll_next(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {

View File

@@ -31,9 +31,9 @@ use futures_core::Stream;
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use crate::{ use crate::{
capture::InputCapture as LanMouseInputCapture,
client::{ClientEvent, ClientHandle, Position}, client::{ClientEvent, ClientHandle, Position},
event::{Event, KeyboardEvent, PointerEvent}, event::{Event, KeyboardEvent, PointerEvent},
producer::EventProducer,
}; };
#[derive(Debug)] #[derive(Debug)]
@@ -43,7 +43,7 @@ enum ProducerEvent {
} }
#[allow(dead_code)] #[allow(dead_code)]
pub struct LibeiProducer<'a> { pub struct LibeiInputCapture<'a> {
input_capture: Pin<Box<InputCapture<'a>>>, input_capture: Pin<Box<InputCapture<'a>>>,
libei_task: JoinHandle<Result<()>>, libei_task: JoinHandle<Result<()>>,
event_rx: tokio::sync::mpsc::Receiver<(u32, Event)>, event_rx: tokio::sync::mpsc::Receiver<(u32, Event)>,
@@ -123,7 +123,7 @@ async fn update_barriers(
Ok(id_map) Ok(id_map)
} }
impl<'a> Drop for LibeiProducer<'a> { impl<'a> Drop for LibeiInputCapture<'a> {
fn drop(&mut self) { fn drop(&mut self) {
self.libei_task.abort(); self.libei_task.abort();
} }
@@ -212,7 +212,7 @@ async fn wait_for_active_client(
Ok(()) Ok(())
} }
impl<'a> LibeiProducer<'a> { impl<'a> LibeiInputCapture<'a> {
pub async fn new() -> Result<Self> { pub async fn new() -> Result<Self> {
let input_capture = Box::pin(InputCapture::new().await?); let input_capture = Box::pin(InputCapture::new().await?);
let input_capture_ptr = input_capture.as_ref().get_ref() as *const InputCapture<'static>; let input_capture_ptr = input_capture.as_ref().get_ref() as *const InputCapture<'static>;
@@ -522,7 +522,7 @@ async fn handle_ei_event(
} }
} }
impl<'a> EventProducer for LibeiProducer<'a> { impl<'a> LanMouseInputCapture for LibeiInputCapture<'a> {
fn notify(&mut self, event: ClientEvent) -> io::Result<()> { fn notify(&mut self, event: ClientEvent) -> io::Result<()> {
let notify_tx = self.notify_tx.clone(); let notify_tx = self.notify_tx.clone();
tokio::task::spawn_local(async move { tokio::task::spawn_local(async move {
@@ -543,7 +543,7 @@ impl<'a> EventProducer for LibeiProducer<'a> {
} }
} }
impl<'a> Stream for LibeiProducer<'a> { impl<'a> Stream for LibeiInputCapture<'a> {
type Item = io::Result<(ClientHandle, Event)>; type Item = io::Result<(ClientHandle, Event)>;
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> { fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {

View File

@@ -1,20 +1,20 @@
use crate::capture::InputCapture;
use crate::client::{ClientEvent, ClientHandle}; use crate::client::{ClientEvent, ClientHandle};
use crate::event::Event; use crate::event::Event;
use crate::producer::EventProducer;
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use futures_core::Stream; use futures_core::Stream;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
use std::{io, pin::Pin}; use std::{io, pin::Pin};
pub struct MacOSProducer; pub struct MacOSInputCapture;
impl MacOSProducer { impl MacOSInputCapture {
pub fn new() -> Result<Self> { pub fn new() -> Result<Self> {
Err(anyhow!("not yet implemented")) Err(anyhow!("not yet implemented"))
} }
} }
impl Stream for MacOSProducer { impl Stream for MacOSInputCapture {
type Item = io::Result<(ClientHandle, Event)>; type Item = io::Result<(ClientHandle, Event)>;
fn poll_next(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Option<Self::Item>> { fn poll_next(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
@@ -22,7 +22,7 @@ impl Stream for MacOSProducer {
} }
} }
impl EventProducer for MacOSProducer { impl InputCapture for MacOSInputCapture {
fn notify(&mut self, _event: ClientEvent) -> io::Result<()> { fn notify(&mut self, _event: ClientEvent) -> io::Result<()> {
Ok(()) Ok(())
} }

View File

@@ -1,6 +1,6 @@
use crate::{ use crate::{
capture::InputCapture,
client::{ClientEvent, ClientHandle, Position}, client::{ClientEvent, ClientHandle, Position},
producer::EventProducer,
}; };
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
@@ -124,7 +124,7 @@ impl AsRawFd for Inner {
} }
} }
pub struct WaylandEventProducer(AsyncFd<Inner>); pub struct WaylandInputCapture(AsyncFd<Inner>);
struct Window { struct Window {
buffer: wl_buffer::WlBuffer, buffer: wl_buffer::WlBuffer,
@@ -256,7 +256,7 @@ fn draw(f: &mut File, (width, height): (u32, u32)) {
} }
} }
impl WaylandEventProducer { impl WaylandInputCapture {
pub fn new() -> Result<Self> { pub fn new() -> Result<Self> {
let conn = match Connection::connect_to_env() { let conn = match Connection::connect_to_env() {
Ok(c) => c, Ok(c) => c,
@@ -390,7 +390,7 @@ impl WaylandEventProducer {
let inner = AsyncFd::new(Inner { queue, state })?; let inner = AsyncFd::new(Inner { queue, state })?;
Ok(WaylandEventProducer(inner)) Ok(WaylandInputCapture(inner))
} }
fn add_client(&mut self, handle: ClientHandle, pos: Position) { fn add_client(&mut self, handle: ClientHandle, pos: Position) {
@@ -587,7 +587,7 @@ impl Inner {
} }
} }
impl EventProducer for WaylandEventProducer { impl InputCapture for WaylandInputCapture {
fn notify(&mut self, client_event: ClientEvent) -> io::Result<()> { fn notify(&mut self, client_event: ClientEvent) -> io::Result<()> {
match client_event { match client_event {
ClientEvent::Create(handle, pos) => { ClientEvent::Create(handle, pos) => {
@@ -609,7 +609,7 @@ impl EventProducer for WaylandEventProducer {
} }
} }
impl Stream for WaylandEventProducer { impl Stream for WaylandInputCapture {
type Item = io::Result<(ClientHandle, Event)>; type Item = io::Result<(ClientHandle, Event)>;
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> { fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {

View File

@@ -4,14 +4,14 @@ use futures::Stream;
use std::{io, pin::Pin}; use std::{io, pin::Pin};
use crate::{ use crate::{
capture::InputCapture,
client::{ClientEvent, ClientHandle}, client::{ClientEvent, ClientHandle},
event::Event, event::Event,
producer::EventProducer,
}; };
pub struct WindowsProducer {} pub struct WindowsInputCapture {}
impl EventProducer for WindowsProducer { impl InputCapture for WindowsInputCapture {
fn notify(&mut self, _event: ClientEvent) -> io::Result<()> { fn notify(&mut self, _event: ClientEvent) -> io::Result<()> {
Ok(()) Ok(())
} }
@@ -21,13 +21,13 @@ impl EventProducer for WindowsProducer {
} }
} }
impl WindowsProducer { impl WindowsInputCapture {
pub(crate) fn new() -> Result<Self> { pub(crate) fn new() -> Result<Self> {
Err(anyhow!("not implemented")) Err(anyhow!("not implemented"))
} }
} }
impl Stream for WindowsProducer { impl Stream for WindowsInputCapture {
type Item = io::Result<(ClientHandle, Event)>; type Item = io::Result<(ClientHandle, Event)>;
fn poll_next(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Option<Self::Item>> { fn poll_next(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
Poll::Pending Poll::Pending

View File

@@ -4,20 +4,20 @@ use std::task::Poll;
use futures_core::Stream; use futures_core::Stream;
use crate::capture::InputCapture;
use crate::event::Event; use crate::event::Event;
use crate::producer::EventProducer;
use crate::client::{ClientEvent, ClientHandle}; use crate::client::{ClientEvent, ClientHandle};
pub struct X11Producer {} pub struct X11InputCapture {}
impl X11Producer { impl X11InputCapture {
pub fn new() -> Result<Self> { pub fn new() -> Result<Self> {
Err(anyhow!("not implemented")) Err(anyhow!("not implemented"))
} }
} }
impl EventProducer for X11Producer { impl InputCapture for X11InputCapture {
fn notify(&mut self, _event: ClientEvent) -> io::Result<()> { fn notify(&mut self, _event: ClientEvent) -> io::Result<()> {
Ok(()) Ok(())
} }
@@ -27,7 +27,7 @@ impl EventProducer for X11Producer {
} }
} }
impl Stream for X11Producer { impl Stream for X11InputCapture {
type Item = io::Result<(ClientHandle, Event)>; type Item = io::Result<(ClientHandle, Event)>;
fn poll_next( fn poll_next(

View File

@@ -67,7 +67,7 @@ pub struct Client {
/// fix ips, determined by the user /// fix ips, determined by the user
pub fix_ips: Vec<IpAddr>, pub fix_ips: Vec<IpAddr>,
/// unique handle to refer to the client. /// unique handle to refer to the client.
/// This way any event consumer / producer backend does not /// This way any emulation / capture backend does not
/// need to know anything about a client other than its handle. /// need to know anything about a client other than its handle.
pub handle: ClientHandle, pub handle: ClientHandle,
/// all ip addresses associated with a particular client /// all ip addresses associated with a particular client

View File

@@ -25,11 +25,11 @@ pub mod libei;
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
pub mod macos; pub mod macos;
/// fallback consumer /// fallback input emulation (logs events)
pub mod dummy; pub mod dummy;
#[async_trait] #[async_trait]
pub trait EventConsumer: Send { pub trait InputEmulation: Send {
async fn consume(&mut self, event: Event, client_handle: ClientHandle); async fn consume(&mut self, event: Event, client_handle: ClientHandle);
async fn notify(&mut self, client_event: ClientEvent); async fn notify(&mut self, client_event: ClientEvent);
/// this function is waited on continuously and can be used to handle events /// this function is waited on continuously and can be used to handle events
@@ -41,58 +41,58 @@ pub trait EventConsumer: Send {
async fn destroy(&mut self); async fn destroy(&mut self);
} }
pub async fn create() -> Box<dyn EventConsumer> { pub async fn create() -> Box<dyn InputEmulation> {
#[cfg(windows)] #[cfg(windows)]
match windows::WindowsConsumer::new() { match windows::WindowsEmulation::new() {
Ok(c) => return Box::new(c), Ok(c) => return Box::new(c),
Err(e) => log::warn!("windows event consumer unavailable: {e}"), Err(e) => log::warn!("windows input emulation unavailable: {e}"),
} }
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
match macos::MacOSConsumer::new() { match macos::MacOSEmulation::new() {
Ok(c) => { Ok(c) => {
log::info!("using macos event consumer"); log::info!("using macos input emulation");
return Box::new(c); return Box::new(c);
} }
Err(e) => log::error!("macos consumer not available: {e}"), Err(e) => log::error!("macos input emulatino not available: {e}"),
} }
#[cfg(all(unix, feature = "wayland", not(target_os = "macos")))] #[cfg(all(unix, feature = "wayland", not(target_os = "macos")))]
match wlroots::WlrootsConsumer::new() { match wlroots::WlrootsEmulation::new() {
Ok(c) => { Ok(c) => {
log::info!("using wlroots event consumer"); log::info!("using wlroots input emulation");
return Box::new(c); return Box::new(c);
} }
Err(e) => log::info!("wayland backend not available: {e}"), Err(e) => log::info!("wayland backend not available: {e}"),
} }
#[cfg(all(unix, feature = "libei", not(target_os = "macos")))] #[cfg(all(unix, feature = "libei", not(target_os = "macos")))]
match libei::LibeiConsumer::new().await { match libei::LibeiEmulation::new().await {
Ok(c) => { Ok(c) => {
log::info!("using libei event consumer"); log::info!("using libei input emulation");
return Box::new(c); return Box::new(c);
} }
Err(e) => log::info!("libei not available: {e}"), Err(e) => log::info!("libei not available: {e}"),
} }
#[cfg(all(unix, feature = "xdg_desktop_portal", not(target_os = "macos")))] #[cfg(all(unix, feature = "xdg_desktop_portal", not(target_os = "macos")))]
match xdg_desktop_portal::DesktopPortalConsumer::new().await { match xdg_desktop_portal::DesktopPortalEmulation::new().await {
Ok(c) => { Ok(c) => {
log::info!("using xdg-remote-desktop-portal event consumer"); log::info!("using xdg-remote-desktop-portal input emulation");
return Box::new(c); return Box::new(c);
} }
Err(e) => log::info!("remote desktop portal not available: {e}"), Err(e) => log::info!("remote desktop portal not available: {e}"),
} }
#[cfg(all(unix, feature = "x11", not(target_os = "macos")))] #[cfg(all(unix, feature = "x11", not(target_os = "macos")))]
match x11::X11Consumer::new() { match x11::X11Emulation::new() {
Ok(c) => { Ok(c) => {
log::info!("using x11 event consumer"); log::info!("using x11 input emulation");
return Box::new(c); return Box::new(c);
} }
Err(e) => log::info!("x11 consumer not available: {e}"), Err(e) => log::info!("x11 input emulation not available: {e}"),
} }
log::error!("falling back to dummy event consumer"); log::error!("falling back to dummy input emulation");
Box::new(dummy::DummyConsumer::new()) Box::new(dummy::DummyEmulation::new())
} }

View File

@@ -1,21 +1,21 @@
use crate::{ use crate::{
client::{ClientEvent, ClientHandle}, client::{ClientEvent, ClientHandle},
consumer::EventConsumer, emulate::InputEmulation,
event::Event, event::Event,
}; };
use async_trait::async_trait; use async_trait::async_trait;
#[derive(Default)] #[derive(Default)]
pub struct DummyConsumer; pub struct DummyEmulation;
impl DummyConsumer { impl DummyEmulation {
pub fn new() -> Self { pub fn new() -> Self {
Self {} Self {}
} }
} }
#[async_trait] #[async_trait]
impl EventConsumer for DummyConsumer { impl InputEmulation for DummyEmulation {
async fn consume(&mut self, event: Event, client_handle: ClientHandle) { async fn consume(&mut self, event: Event, client_handle: ClientHandle) {
log::info!("received event: ({client_handle}) {event}"); log::info!("received event: ({client_handle}) {event}");
} }

View File

@@ -23,11 +23,11 @@ use reis::{
use crate::{ use crate::{
client::{ClientEvent, ClientHandle}, client::{ClientEvent, ClientHandle},
consumer::EventConsumer, emulate::InputEmulation,
event::Event, event::Event,
}; };
pub struct LibeiConsumer { pub struct LibeiEmulation {
handshake: bool, handshake: bool,
context: ei::Context, context: ei::Context,
events: EiEventStream, events: EiEventStream,
@@ -76,7 +76,7 @@ async fn get_ei_fd() -> Result<OwnedFd, ashpd::Error> {
proxy.connect_to_eis(&session).await proxy.connect_to_eis(&session).await
} }
impl LibeiConsumer { impl LibeiEmulation {
pub async fn new() -> Result<Self> { pub async fn new() -> Result<Self> {
// fd is owned by the message, so we need to dup it // fd is owned by the message, so we need to dup it
let eifd = get_ei_fd().await?; let eifd = get_ei_fd().await?;
@@ -107,7 +107,7 @@ impl LibeiConsumer {
} }
#[async_trait] #[async_trait]
impl EventConsumer for LibeiConsumer { impl InputEmulation for LibeiEmulation {
async fn consume(&mut self, event: Event, _client_handle: ClientHandle) { async fn consume(&mut self, event: Event, _client_handle: ClientHandle) {
let now = SystemTime::now() let now = SystemTime::now()
.duration_since(UNIX_EPOCH) .duration_since(UNIX_EPOCH)

View File

@@ -1,5 +1,5 @@
use crate::client::{ClientEvent, ClientHandle}; use crate::client::{ClientEvent, ClientHandle};
use crate::consumer::EventConsumer; use crate::emulate::InputEmulation;
use crate::event::{Event, KeyboardEvent, PointerEvent}; use crate::event::{Event, KeyboardEvent, PointerEvent};
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use async_trait::async_trait; use async_trait::async_trait;
@@ -16,7 +16,7 @@ use tokio::task::AbortHandle;
const DEFAULT_REPEAT_DELAY: Duration = Duration::from_millis(500); const DEFAULT_REPEAT_DELAY: Duration = Duration::from_millis(500);
const DEFAULT_REPEAT_INTERVAL: Duration = Duration::from_millis(32); const DEFAULT_REPEAT_INTERVAL: Duration = Duration::from_millis(32);
pub struct MacOSConsumer { pub struct MacOSEmulation {
pub event_source: CGEventSource, pub event_source: CGEventSource,
repeat_task: Option<AbortHandle>, repeat_task: Option<AbortHandle>,
button_state: ButtonState, button_state: ButtonState,
@@ -50,9 +50,9 @@ impl IndexMut<CGMouseButton> for ButtonState {
} }
} }
unsafe impl Send for MacOSConsumer {} unsafe impl Send for MacOSEmulation {}
impl MacOSConsumer { impl MacOSEmulation {
pub fn new() -> Result<Self> { pub fn new() -> Result<Self> {
let event_source = match CGEventSource::new(CGEventSourceStateID::CombinedSessionState) { let event_source = match CGEventSource::new(CGEventSourceStateID::CombinedSessionState) {
Ok(e) => e, Ok(e) => e,
@@ -108,7 +108,7 @@ fn key_event(event_source: CGEventSource, key: u16, state: u8) {
} }
#[async_trait] #[async_trait]
impl EventConsumer for MacOSConsumer { impl InputEmulation for MacOSEmulation {
async fn consume(&mut self, event: Event, _client_handle: ClientHandle) { async fn consume(&mut self, event: Event, _client_handle: ClientHandle) {
match event { match event {
Event::Pointer(pointer_event) => match pointer_event { Event::Pointer(pointer_event) => match pointer_event {

View File

@@ -1,5 +1,5 @@
use crate::{ use crate::{
consumer::EventConsumer, emulate::InputEmulation,
event::{KeyboardEvent, PointerEvent}, event::{KeyboardEvent, PointerEvent},
scancode, scancode,
}; };
@@ -26,18 +26,18 @@ use crate::{
const DEFAULT_REPEAT_DELAY: Duration = Duration::from_millis(500); const DEFAULT_REPEAT_DELAY: Duration = Duration::from_millis(500);
const DEFAULT_REPEAT_INTERVAL: Duration = Duration::from_millis(32); const DEFAULT_REPEAT_INTERVAL: Duration = Duration::from_millis(32);
pub struct WindowsConsumer { pub struct WindowsEmulation {
repeat_task: Option<AbortHandle>, repeat_task: Option<AbortHandle>,
} }
impl WindowsConsumer { impl WindowsEmulation {
pub fn new() -> Result<Self> { pub fn new() -> Result<Self> {
Ok(Self { repeat_task: None }) Ok(Self { repeat_task: None })
} }
} }
#[async_trait] #[async_trait]
impl EventConsumer for WindowsConsumer { impl InputEmulation for WindowsEmulation {
async fn consume(&mut self, event: Event, _: ClientHandle) { async fn consume(&mut self, event: Event, _: ClientHandle) {
match event { match event {
Event::Pointer(pointer_event) => match pointer_event { Event::Pointer(pointer_event) => match pointer_event {
@@ -87,7 +87,7 @@ impl EventConsumer for WindowsConsumer {
async fn destroy(&mut self) {} async fn destroy(&mut self) {}
} }
impl WindowsConsumer { impl WindowsEmulation {
async fn spawn_repeat_task(&mut self, key: u32) { async fn spawn_repeat_task(&mut self, key: u32) {
// there can only be one repeating key and it's // there can only be one repeating key and it's
// always the last to be pressed // always the last to be pressed

View File

@@ -1,5 +1,5 @@
use crate::client::{ClientEvent, ClientHandle}; use crate::client::{ClientEvent, ClientHandle};
use crate::consumer::EventConsumer; use crate::emulate::InputEmulation;
use async_trait::async_trait; use async_trait::async_trait;
use std::collections::HashMap; use std::collections::HashMap;
use std::io; use std::io;
@@ -40,13 +40,13 @@ struct State {
} }
// App State, implements Dispatch event handlers // App State, implements Dispatch event handlers
pub(crate) struct WlrootsConsumer { pub(crate) struct WlrootsEmulation {
last_flush_failed: bool, last_flush_failed: bool,
state: State, state: State,
queue: EventQueue<State>, queue: EventQueue<State>,
} }
impl WlrootsConsumer { impl WlrootsEmulation {
pub fn new() -> Result<Self> { pub fn new() -> Result<Self> {
let conn = Connection::connect_to_env()?; let conn = Connection::connect_to_env()?;
let (globals, queue) = registry_queue_init::<State>(&conn)?; let (globals, queue) = registry_queue_init::<State>(&conn)?;
@@ -62,7 +62,7 @@ impl WlrootsConsumer {
let input_for_client: HashMap<ClientHandle, VirtualInput> = HashMap::new(); let input_for_client: HashMap<ClientHandle, VirtualInput> = HashMap::new();
let mut consumer = WlrootsConsumer { let mut emulate = WlrootsEmulation {
last_flush_failed: false, last_flush_failed: false,
state: State { state: State {
keymap: None, keymap: None,
@@ -74,16 +74,13 @@ impl WlrootsConsumer {
}, },
queue, queue,
}; };
while consumer.state.keymap.is_none() { while emulate.state.keymap.is_none() {
consumer emulate.queue.blocking_dispatch(&mut emulate.state).unwrap();
.queue
.blocking_dispatch(&mut consumer.state)
.unwrap();
} }
// let fd = unsafe { &File::from_raw_fd(consumer.state.keymap.unwrap().1.as_raw_fd()) }; // let fd = unsafe { &File::from_raw_fd(emulate.state.keymap.unwrap().1.as_raw_fd()) };
// let mmap = unsafe { MmapOptions::new().map_copy(fd).unwrap() }; // let mmap = unsafe { MmapOptions::new().map_copy(fd).unwrap() };
// log::debug!("{:?}", &mmap[..100]); // log::debug!("{:?}", &mmap[..100]);
Ok(consumer) Ok(emulate)
} }
} }
@@ -106,7 +103,7 @@ impl State {
} }
#[async_trait] #[async_trait]
impl EventConsumer for WlrootsConsumer { impl InputEmulation for WlrootsEmulation {
async fn consume(&mut self, event: Event, client_handle: ClientHandle) { async fn consume(&mut self, event: Event, client_handle: ClientHandle) {
if let Some(virtual_input) = self.state.input_for_client.get(&client_handle) { if let Some(virtual_input) = self.state.input_for_client.get(&client_handle) {
if self.last_flush_failed { if self.last_flush_failed {

View File

@@ -8,19 +8,19 @@ use x11::{
use crate::{ use crate::{
client::ClientHandle, client::ClientHandle,
consumer::EventConsumer, emulate::InputEmulation,
event::{ event::{
Event, KeyboardEvent, PointerEvent, BTN_BACK, BTN_FORWARD, BTN_LEFT, BTN_MIDDLE, BTN_RIGHT, Event, KeyboardEvent, PointerEvent, BTN_BACK, BTN_FORWARD, BTN_LEFT, BTN_MIDDLE, BTN_RIGHT,
}, },
}; };
pub struct X11Consumer { pub struct X11Emulation {
display: *mut xlib::Display, display: *mut xlib::Display,
} }
unsafe impl Send for X11Consumer {} unsafe impl Send for X11Emulation {}
impl X11Consumer { impl X11Emulation {
pub fn new() -> Result<Self> { pub fn new() -> Result<Self> {
let display = unsafe { let display = unsafe {
match xlib::XOpenDisplay(ptr::null()) { match xlib::XOpenDisplay(ptr::null()) {
@@ -91,7 +91,7 @@ impl X11Consumer {
} }
} }
impl Drop for X11Consumer { impl Drop for X11Emulation {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
XCloseDisplay(self.display); XCloseDisplay(self.display);
@@ -100,7 +100,7 @@ impl Drop for X11Consumer {
} }
#[async_trait] #[async_trait]
impl EventConsumer for X11Consumer { impl InputEmulation for X11Emulation {
async fn consume(&mut self, event: Event, _: ClientHandle) { async fn consume(&mut self, event: Event, _: ClientHandle) {
match event { match event {
Event::Pointer(pointer_event) => match pointer_event { Event::Pointer(pointer_event) => match pointer_event {

View File

@@ -10,20 +10,20 @@ use async_trait::async_trait;
use crate::{ use crate::{
client::ClientEvent, client::ClientEvent,
consumer::EventConsumer, emulate::InputEmulation,
event::{ event::{
Event::{Keyboard, Pointer}, Event::{Keyboard, Pointer},
KeyboardEvent, PointerEvent, KeyboardEvent, PointerEvent,
}, },
}; };
pub struct DesktopPortalConsumer<'a> { pub struct DesktopPortalEmulation<'a> {
proxy: RemoteDesktop<'a>, proxy: RemoteDesktop<'a>,
session: Session<'a>, session: Session<'a>,
} }
impl<'a> DesktopPortalConsumer<'a> { impl<'a> DesktopPortalEmulation<'a> {
pub async fn new() -> Result<DesktopPortalConsumer<'a>> { pub async fn new() -> Result<DesktopPortalEmulation<'a>> {
log::debug!("connecting to org.freedesktop.portal.RemoteDesktop portal ..."); log::debug!("connecting to org.freedesktop.portal.RemoteDesktop portal ...");
let proxy = RemoteDesktop::new().await?; let proxy = RemoteDesktop::new().await?;
@@ -59,7 +59,7 @@ impl<'a> DesktopPortalConsumer<'a> {
} }
#[async_trait] #[async_trait]
impl<'a> EventConsumer for DesktopPortalConsumer<'a> { impl<'a> InputEmulation for DesktopPortalEmulation<'a> {
async fn consume(&mut self, event: crate::event::Event, _client: crate::client::ClientHandle) { async fn consume(&mut self, event: crate::event::Event, _client: crate::client::ClientHandle) {
match event { match event {
Pointer(p) => { Pointer(p) => {

View File

@@ -4,8 +4,8 @@ pub mod dns;
pub mod event; pub mod event;
pub mod server; pub mod server;
pub mod consumer; pub mod capture;
pub mod producer; pub mod emulate;
pub mod frontend; pub mod frontend;
pub mod scancode; pub mod scancode;

View File

@@ -5,22 +5,22 @@ use std::{
}; };
use tokio::signal; use tokio::signal;
use crate::{capture, emulate};
use crate::{ use crate::{
client::{ClientHandle, ClientManager}, client::{ClientHandle, ClientManager},
config::Config, config::Config,
dns, dns,
frontend::{FrontendEvent, FrontendListener}, frontend::{FrontendEvent, FrontendListener},
server::producer_task::ProducerEvent, server::capture_task::CaptureEvent,
}; };
use crate::{consumer, producer};
use self::{consumer_task::ConsumerEvent, resolver_task::DnsRequest}; use self::{emulation_task::EmulationEvent, resolver_task::DnsRequest};
mod consumer_task; mod capture_task;
mod emulation_task;
mod frontend_task; mod frontend_task;
mod network_task; mod network_task;
mod ping_task; mod ping_task;
mod producer_task;
mod resolver_task; mod resolver_task;
#[derive(Clone, Copy, Debug, Eq, PartialEq)] #[derive(Clone, Copy, Debug, Eq, PartialEq)]
@@ -78,7 +78,7 @@ impl Server {
return anyhow::Ok(()); return anyhow::Ok(());
} }
}; };
let (consumer, producer) = tokio::join!(consumer::create(), producer::create()); let (emulate, capture) = tokio::join!(emulate::create(), capture::create());
let (timer_tx, timer_rx) = tokio::sync::mpsc::channel(1); let (timer_tx, timer_rx) = tokio::sync::mpsc::channel(1);
let (frontend_notify_tx, frontend_notify_rx) = tokio::sync::mpsc::channel(1); let (frontend_notify_tx, frontend_notify_rx) = tokio::sync::mpsc::channel(1);
@@ -87,22 +87,22 @@ impl Server {
let (mut udp_task, sender_tx, receiver_rx, port_tx) = let (mut udp_task, sender_tx, receiver_rx, port_tx) =
network_task::new(self.clone(), frontend_notify_tx).await?; network_task::new(self.clone(), frontend_notify_tx).await?;
// event producer // input capture
let (mut producer_task, producer_channel) = producer_task::new( let (mut capture_task, capture_channel) = capture_task::new(
producer, capture,
self.clone(), self.clone(),
sender_tx.clone(), sender_tx.clone(),
timer_tx.clone(), timer_tx.clone(),
self.release_bind.clone(), self.release_bind.clone(),
); );
// event consumer // input emulation
let (mut consumer_task, consumer_channel) = consumer_task::new( let (mut emulation_task, emulate_channel) = emulation_task::new(
consumer, emulate,
self.clone(), self.clone(),
receiver_rx, receiver_rx,
sender_tx.clone(), sender_tx.clone(),
producer_channel.clone(), capture_channel.clone(),
timer_tx, timer_tx,
); );
@@ -115,8 +115,8 @@ impl Server {
frontend, frontend,
frontend_notify_rx, frontend_notify_rx,
self.clone(), self.clone(),
producer_channel.clone(), capture_channel.clone(),
consumer_channel.clone(), emulate_channel.clone(),
resolve_tx.clone(), resolve_tx.clone(),
port_tx, port_tx,
); );
@@ -125,8 +125,8 @@ impl Server {
let mut ping_task = ping_task::new( let mut ping_task = ping_task::new(
self.clone(), self.clone(),
sender_tx.clone(), sender_tx.clone(),
consumer_channel.clone(), emulate_channel.clone(),
producer_channel.clone(), capture_channel.clone(),
timer_rx, timer_rx,
); );
@@ -156,14 +156,14 @@ impl Server {
_ = signal::ctrl_c() => { _ = signal::ctrl_c() => {
log::info!("terminating service"); log::info!("terminating service");
} }
e = &mut producer_task => { e = &mut capture_task => {
if let Ok(Err(e)) = e { if let Ok(Err(e)) = e {
log::error!("error in event producer: {e}"); log::error!("error in input capture task: {e}");
} }
} }
e = &mut consumer_task => { e = &mut emulation_task => {
if let Ok(Err(e)) = e { if let Ok(Err(e)) = e {
log::error!("error in event consumer: {e}"); log::error!("error in input emulation task: {e}");
} }
} }
e = &mut frontend_task => { e = &mut frontend_task => {
@@ -176,18 +176,18 @@ impl Server {
_ = &mut ping_task => { } _ = &mut ping_task => { }
} }
let _ = consumer_channel.send(ConsumerEvent::Terminate).await; let _ = emulate_channel.send(EmulationEvent::Terminate).await;
let _ = producer_channel.send(ProducerEvent::Terminate).await; let _ = capture_channel.send(CaptureEvent::Terminate).await;
let _ = frontend_tx.send(FrontendEvent::Shutdown()).await; let _ = frontend_tx.send(FrontendEvent::Shutdown()).await;
if !producer_task.is_finished() { if !capture_task.is_finished() {
if let Err(e) = producer_task.await { if let Err(e) = capture_task.await {
log::error!("error in event producer: {e}"); log::error!("error in input capture task: {e}");
} }
} }
if !consumer_task.is_finished() { if !emulation_task.is_finished() {
if let Err(e) = consumer_task.await { if let Err(e) = emulation_task.await {
log::error!("error in event consumer: {e}"); log::error!("error in input emulation task: {e}");
} }
} }

View File

@@ -5,9 +5,9 @@ use std::{collections::HashSet, net::SocketAddr};
use tokio::{sync::mpsc::Sender, task::JoinHandle}; use tokio::{sync::mpsc::Sender, task::JoinHandle};
use crate::{ use crate::{
capture::InputCapture,
client::{ClientEvent, ClientHandle}, client::{ClientEvent, ClientHandle},
event::{Event, KeyboardEvent}, event::{Event, KeyboardEvent},
producer::EventProducer,
scancode, scancode,
server::State, server::State,
}; };
@@ -15,45 +15,45 @@ use crate::{
use super::Server; use super::Server;
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
pub enum ProducerEvent { pub enum CaptureEvent {
/// producer must release the mouse /// capture must release the mouse
Release, Release,
/// producer is notified of a change in client states /// capture is notified of a change in client states
ClientEvent(ClientEvent), ClientEvent(ClientEvent),
/// termination signal /// termination signal
Terminate, Terminate,
} }
pub fn new( pub fn new(
mut producer: Box<dyn EventProducer>, mut capture: Box<dyn InputCapture>,
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>, release_bind: Vec<scancode::Linux>,
) -> (JoinHandle<Result<()>>, Sender<ProducerEvent>) { ) -> (JoinHandle<Result<()>>, Sender<CaptureEvent>) {
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(); let mut pressed_keys = HashSet::new();
loop { loop {
tokio::select! { tokio::select! {
event = producer.next() => { event = capture.next() => {
match event { match event {
Some(Ok(event)) => handle_producer_event(&server, &mut producer, &sender_tx, &timer_tx, event, &mut pressed_keys, &release_bind).await?, Some(Ok(event)) => handle_capture_event(&server, &mut capture, &sender_tx, &timer_tx, event, &mut pressed_keys, &release_bind).await?,
Some(Err(e)) => return Err(anyhow!("event producer: {e:?}")), Some(Err(e)) => return Err(anyhow!("input capture: {e:?}")),
None => return Err(anyhow!("event producer closed")), None => return Err(anyhow!("input capture terminated")),
} }
} }
e = rx.recv() => { e = rx.recv() => {
log::debug!("producer notify rx: {e:?}"); log::debug!("input capture notify rx: {e:?}");
match e { match e {
Some(e) => match e { Some(e) => match e {
ProducerEvent::Release => { CaptureEvent::Release => {
producer.release()?; capture.release()?;
server.state.replace(State::Receiving); server.state.replace(State::Receiving);
} }
ProducerEvent::ClientEvent(e) => producer.notify(e)?, CaptureEvent::ClientEvent(e) => capture.notify(e)?,
ProducerEvent::Terminate => break, CaptureEvent::Terminate => break,
}, },
None => break, None => break,
} }
@@ -75,9 +75,9 @@ fn update_pressed_keys(pressed_keys: &mut HashSet<scancode::Linux>, key: u32, st
} }
} }
async fn handle_producer_event( async fn handle_capture_event(
server: &Server, server: &Server,
producer: &mut Box<dyn EventProducer>, capture: &mut Box<dyn InputCapture>,
sender_tx: &Sender<(Event, SocketAddr)>, sender_tx: &Sender<(Event, SocketAddr)>,
timer_tx: &Sender<()>, timer_tx: &Sender<()>,
event: (ClientHandle, Event), event: (ClientHandle, Event),
@@ -93,7 +93,7 @@ async fn handle_producer_event(
if release_bind.iter().all(|k| pressed_keys.contains(k)) { if release_bind.iter().all(|k| pressed_keys.contains(k)) {
pressed_keys.clear(); pressed_keys.clear();
log::info!("releasing pointer"); log::info!("releasing pointer");
producer.release()?; capture.release()?;
server.state.replace(State::Receiving); server.state.replace(State::Receiving);
log::trace!("STATE ===> Receiving"); log::trace!("STATE ===> Receiving");
// send an event to release all the modifiers // send an event to release all the modifiers
@@ -112,7 +112,7 @@ async fn handle_producer_event(
None => { None => {
// should not happen // should not happen
log::warn!("unknown client!"); log::warn!("unknown client!");
producer.release()?; capture.release()?;
server.state.replace(State::Receiving); server.state.replace(State::Receiving);
log::trace!("STATE ===> Receiving"); log::trace!("STATE ===> Receiving");
return Ok(()); return Ok(());

View File

@@ -8,53 +8,53 @@ use tokio::{
use crate::{ use crate::{
client::{ClientEvent, ClientHandle}, client::{ClientEvent, ClientHandle},
consumer::EventConsumer, emulate::InputEmulation,
event::{Event, KeyboardEvent}, event::{Event, KeyboardEvent},
scancode, scancode,
server::State, server::State,
}; };
use super::{ProducerEvent, Server}; use super::{CaptureEvent, Server};
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum ConsumerEvent { pub enum EmulationEvent {
/// consumer is notified of a change in client states /// input emulation is notified of a change in client states
ClientEvent(ClientEvent), ClientEvent(ClientEvent),
/// consumer must release keys for client /// input emulation must release keys for client
ReleaseKeys(ClientHandle), ReleaseKeys(ClientHandle),
/// termination signal /// termination signal
Terminate, Terminate,
} }
pub fn new( pub fn new(
mut consumer: Box<dyn EventConsumer>, mut emulate: Box<dyn InputEmulation>,
server: Server, server: Server,
mut udp_rx: Receiver<Result<(Event, SocketAddr)>>, mut udp_rx: Receiver<Result<(Event, SocketAddr)>>,
sender_tx: Sender<(Event, SocketAddr)>, sender_tx: Sender<(Event, SocketAddr)>,
producer_tx: Sender<ProducerEvent>, capture_tx: Sender<CaptureEvent>,
timer_tx: Sender<()>, timer_tx: Sender<()>,
) -> (JoinHandle<Result<()>>, Sender<ConsumerEvent>) { ) -> (JoinHandle<Result<()>>, Sender<EmulationEvent>) {
let (tx, mut rx) = tokio::sync::mpsc::channel(32); let (tx, mut rx) = tokio::sync::mpsc::channel(32);
let consumer_task = tokio::task::spawn_local(async move { let emulate_task = tokio::task::spawn_local(async move {
let mut last_ignored = None; let mut last_ignored = None;
loop { loop {
tokio::select! { tokio::select! {
udp_event = udp_rx.recv() => { udp_event = udp_rx.recv() => {
let udp_event = udp_event.ok_or(anyhow!("receiver closed"))??; let udp_event = udp_event.ok_or(anyhow!("receiver closed"))??;
handle_udp_rx(&server, &producer_tx, &mut consumer, &sender_tx, &mut last_ignored, udp_event, &timer_tx).await; handle_udp_rx(&server, &capture_tx, &mut emulate, &sender_tx, &mut last_ignored, udp_event, &timer_tx).await;
} }
consumer_event = rx.recv() => { emulate_event = rx.recv() => {
match consumer_event { match emulate_event {
Some(e) => match e { Some(e) => match e {
ConsumerEvent::ClientEvent(e) => consumer.notify(e).await, EmulationEvent::ClientEvent(e) => emulate.notify(e).await,
ConsumerEvent::ReleaseKeys(c) => release_keys(&server, &mut consumer, c).await, EmulationEvent::ReleaseKeys(c) => release_keys(&server, &mut emulate, c).await,
ConsumerEvent::Terminate => break, EmulationEvent::Terminate => break,
}, },
None => break, None => break,
} }
} }
res = consumer.dispatch() => { res = emulate.dispatch() => {
res?; res?;
} }
} }
@@ -68,20 +68,20 @@ pub fn new(
.map(|s| s.client.handle) .map(|s| s.client.handle)
.collect::<Vec<_>>(); .collect::<Vec<_>>();
for client in clients { for client in clients {
release_keys(&server, &mut consumer, client).await; release_keys(&server, &mut emulate, client).await;
} }
// destroy consumer // destroy emulator
consumer.destroy().await; emulate.destroy().await;
anyhow::Ok(()) anyhow::Ok(())
}); });
(consumer_task, tx) (emulate_task, tx)
} }
async fn handle_udp_rx( async fn handle_udp_rx(
server: &Server, server: &Server,
producer_notify_tx: &Sender<ProducerEvent>, capture_tx: &Sender<CaptureEvent>,
consumer: &mut Box<dyn EventConsumer>, emulate: &mut Box<dyn InputEmulation>,
sender_tx: &Sender<(Event, SocketAddr)>, sender_tx: &Sender<(Event, SocketAddr)>,
last_ignored: &mut Option<SocketAddr>, last_ignored: &mut Option<SocketAddr>,
event: (Event, SocketAddr), event: (Event, SocketAddr),
@@ -127,7 +127,7 @@ async fn handle_udp_rx(
let _ = sender_tx.send((Event::Pong(), addr)).await; let _ = sender_tx.send((Event::Pong(), addr)).await;
} }
(Event::Disconnect(), _) => { (Event::Disconnect(), _) => {
release_keys(server, consumer, handle).await; release_keys(server, emulate, handle).await;
} }
(event, addr) => { (event, addr) => {
// tell clients that we are ready to receive events // tell clients that we are ready to receive events
@@ -143,7 +143,7 @@ async fn handle_udp_rx(
} else { } else {
// upon receiving any event, we go back to receiving mode // upon receiving any event, we go back to receiving mode
server.state.replace(State::Receiving); server.state.replace(State::Receiving);
let _ = producer_notify_tx.send(ProducerEvent::Release).await; let _ = capture_tx.send(CaptureEvent::Release).await;
log::trace!("STATE ===> Receiving"); log::trace!("STATE ===> Receiving");
} }
} }
@@ -176,8 +176,8 @@ async fn handle_udp_rx(
// workaround buggy rdp backend. // workaround buggy rdp backend.
if !ignore_event { if !ignore_event {
// consume event // consume event
consumer.consume(event, handle).await; emulate.consume(event, handle).await;
log::trace!("{event:?} => consumer"); log::trace!("{event:?} => emulate");
} }
} }
State::AwaitingLeave => { State::AwaitingLeave => {
@@ -194,7 +194,7 @@ async fn handle_udp_rx(
// event should still be possible // event should still be possible
if let Event::Enter() = event { if let Event::Enter() = event {
server.state.replace(State::Receiving); server.state.replace(State::Receiving);
let _ = producer_notify_tx.send(ProducerEvent::Release).await; let _ = capture_tx.send(CaptureEvent::Release).await;
log::trace!("STATE ===> Receiving"); log::trace!("STATE ===> Receiving");
} }
} }
@@ -205,7 +205,7 @@ async fn handle_udp_rx(
async fn release_keys( async fn release_keys(
server: &Server, server: &Server,
consumer: &mut Box<dyn EventConsumer>, emulate: &mut Box<dyn InputEmulation>,
client: ClientHandle, client: ClientHandle,
) { ) {
let keys = server let keys = server
@@ -222,7 +222,7 @@ async fn release_keys(
key, key,
state: 0, state: 0,
}); });
consumer.consume(event, client).await; emulate.consume(event, client).await;
if let Ok(key) = scancode::Linux::try_from(key) { if let Ok(key) = scancode::Linux::try_from(key) {
log::warn!("releasing stuck key: {key:?}"); log::warn!("releasing stuck key: {key:?}");
} }
@@ -234,7 +234,7 @@ async fn release_keys(
mods_locked: 0, mods_locked: 0,
group: 0, group: 0,
}; };
consumer emulate
.consume(Event::Keyboard(modifiers_event), client) .consume(Event::Keyboard(modifiers_event), client)
.await; .await;
} }

View File

@@ -22,15 +22,15 @@ use crate::{
}; };
use super::{ use super::{
consumer_task::ConsumerEvent, producer_task::ProducerEvent, resolver_task::DnsRequest, Server, capture_task::CaptureEvent, emulation_task::EmulationEvent, resolver_task::DnsRequest, Server,
}; };
pub(crate) fn new( pub(crate) fn new(
mut frontend: FrontendListener, mut frontend: FrontendListener,
mut notify_rx: Receiver<FrontendNotify>, mut notify_rx: Receiver<FrontendNotify>,
server: Server, server: Server,
producer_notify: Sender<ProducerEvent>, capture_notify: Sender<CaptureEvent>,
consumer_notify: Sender<ConsumerEvent>, emulate_notify: Sender<EmulationEvent>,
resolve_ch: Sender<DnsRequest>, resolve_ch: Sender<DnsRequest>,
port_tx: Sender<u16>, port_tx: Sender<u16>,
) -> (JoinHandle<Result<()>>, Sender<FrontendEvent>) { ) -> (JoinHandle<Result<()>>, Sender<FrontendEvent>) {
@@ -51,7 +51,7 @@ pub(crate) fn new(
} }
event = event_rx.recv() => { event = event_rx.recv() => {
let frontend_event = event.ok_or(anyhow!("frontend channel closed"))?; let frontend_event = event.ok_or(anyhow!("frontend channel closed"))?;
if handle_frontend_event(&server, &producer_notify, &consumer_notify, &resolve_ch, &mut frontend, &port_tx, frontend_event).await { if handle_frontend_event(&server, &capture_notify, &emulate_notify, &resolve_ch, &mut frontend, &port_tx, frontend_event).await {
break; break;
} }
} }
@@ -98,8 +98,8 @@ async fn handle_frontend_stream(
async fn handle_frontend_event( async fn handle_frontend_event(
server: &Server, server: &Server,
producer_tx: &Sender<ProducerEvent>, capture_tx: &Sender<CaptureEvent>,
consumer_tx: &Sender<ConsumerEvent>, emulate_tx: &Sender<EmulationEvent>,
resolve_tx: &Sender<DnsRequest>, resolve_tx: &Sender<DnsRequest>,
frontend: &mut FrontendListener, frontend: &mut FrontendListener,
port_tx: &Sender<u16>, port_tx: &Sender<u16>,
@@ -120,7 +120,7 @@ async fn handle_frontend_event(
Some(FrontendNotify::NotifyClientCreate(client)) Some(FrontendNotify::NotifyClientCreate(client))
} }
FrontendEvent::ActivateClient(handle, active) => { FrontendEvent::ActivateClient(handle, active) => {
activate_client(server, producer_tx, consumer_tx, handle, active).await; activate_client(server, capture_tx, emulate_tx, handle, active).await;
Some(FrontendNotify::NotifyClientActivate(handle, active)) Some(FrontendNotify::NotifyClientActivate(handle, active))
} }
FrontendEvent::ChangePort(port) => { FrontendEvent::ChangePort(port) => {
@@ -128,7 +128,7 @@ async fn handle_frontend_event(
None None
} }
FrontendEvent::DelClient(handle) => { FrontendEvent::DelClient(handle) => {
remove_client(server, producer_tx, consumer_tx, frontend, handle).await; remove_client(server, capture_tx, emulate_tx, frontend, handle).await;
Some(FrontendNotify::NotifyClientDelete(handle)) Some(FrontendNotify::NotifyClientDelete(handle))
} }
FrontendEvent::Enumerate() => { FrontendEvent::Enumerate() => {
@@ -147,8 +147,8 @@ async fn handle_frontend_event(
FrontendEvent::UpdateClient(handle, hostname, port, pos) => { FrontendEvent::UpdateClient(handle, hostname, port, pos) => {
update_client( update_client(
server, server,
producer_tx, capture_tx,
consumer_tx, emulate_tx,
resolve_tx, resolve_tx,
(handle, hostname, port, pos), (handle, hostname, port, pos),
) )
@@ -204,8 +204,8 @@ pub async fn add_client(
pub async fn activate_client( pub async fn activate_client(
server: &Server, server: &Server,
producer_notify_tx: &Sender<ProducerEvent>, capture_notify_tx: &Sender<CaptureEvent>,
consumer_notify_tx: &Sender<ConsumerEvent>, emulate_notify_tx: &Sender<EmulationEvent>,
client: ClientHandle, client: ClientHandle,
active: bool, active: bool,
) { ) {
@@ -217,26 +217,28 @@ pub async fn activate_client(
None => return, None => return,
}; };
if active { if active {
let _ = producer_notify_tx let _ = capture_notify_tx
.send(ProducerEvent::ClientEvent(ClientEvent::Create(client, pos))) .send(CaptureEvent::ClientEvent(ClientEvent::Create(client, pos)))
.await; .await;
let _ = consumer_notify_tx let _ = emulate_notify_tx
.send(ConsumerEvent::ClientEvent(ClientEvent::Create(client, pos))) .send(EmulationEvent::ClientEvent(ClientEvent::Create(
client, pos,
)))
.await; .await;
} else { } else {
let _ = producer_notify_tx let _ = capture_notify_tx
.send(ProducerEvent::ClientEvent(ClientEvent::Destroy(client))) .send(CaptureEvent::ClientEvent(ClientEvent::Destroy(client)))
.await; .await;
let _ = consumer_notify_tx let _ = emulate_notify_tx
.send(ConsumerEvent::ClientEvent(ClientEvent::Destroy(client))) .send(EmulationEvent::ClientEvent(ClientEvent::Destroy(client)))
.await; .await;
} }
} }
pub async fn remove_client( pub async fn remove_client(
server: &Server, server: &Server,
producer_notify_tx: &Sender<ProducerEvent>, capture_notify_tx: &Sender<CaptureEvent>,
consumer_notify_tx: &Sender<ConsumerEvent>, emulate_notify_tx: &Sender<EmulationEvent>,
frontend: &mut FrontendListener, frontend: &mut FrontendListener,
client: ClientHandle, client: ClientHandle,
) -> Option<ClientHandle> { ) -> Option<ClientHandle> {
@@ -250,11 +252,11 @@ pub async fn remove_client(
}; };
if active { if active {
let _ = producer_notify_tx let _ = capture_notify_tx
.send(ProducerEvent::ClientEvent(ClientEvent::Destroy(client))) .send(CaptureEvent::ClientEvent(ClientEvent::Destroy(client)))
.await; .await;
let _ = consumer_notify_tx let _ = emulate_notify_tx
.send(ConsumerEvent::ClientEvent(ClientEvent::Destroy(client))) .send(EmulationEvent::ClientEvent(ClientEvent::Destroy(client)))
.await; .await;
} }
@@ -268,8 +270,8 @@ pub async fn remove_client(
async fn update_client( async fn update_client(
server: &Server, server: &Server,
producer_notify_tx: &Sender<ProducerEvent>, capture_notify_tx: &Sender<CaptureEvent>,
consumer_notify_tx: &Sender<ConsumerEvent>, emulate_notify_tx: &Sender<EmulationEvent>,
resolve_tx: &Sender<DnsRequest>, resolve_tx: &Sender<DnsRequest>,
client_update: (ClientHandle, Option<String>, u16, Position), client_update: (ClientHandle, Option<String>, u16, Position),
) { ) {
@@ -311,7 +313,7 @@ async fn update_client(
) )
}; };
// update state in event consumer & producer // update state in event input emulator & input capture
if changed && active { if changed && active {
// resolve dns // resolve dns
if let Some(hostname) = hostname { if let Some(hostname) = hostname {
@@ -319,17 +321,19 @@ async fn update_client(
} }
// update state // update state
let _ = producer_notify_tx let _ = capture_notify_tx
.send(ProducerEvent::ClientEvent(ClientEvent::Destroy(handle))) .send(CaptureEvent::ClientEvent(ClientEvent::Destroy(handle)))
.await; .await;
let _ = consumer_notify_tx let _ = emulate_notify_tx
.send(ConsumerEvent::ClientEvent(ClientEvent::Destroy(handle))) .send(EmulationEvent::ClientEvent(ClientEvent::Destroy(handle)))
.await; .await;
let _ = producer_notify_tx let _ = capture_notify_tx
.send(ProducerEvent::ClientEvent(ClientEvent::Create(handle, pos))) .send(CaptureEvent::ClientEvent(ClientEvent::Create(handle, pos)))
.await; .await;
let _ = consumer_notify_tx let _ = emulate_notify_tx
.send(ConsumerEvent::ClientEvent(ClientEvent::Create(handle, pos))) .send(EmulationEvent::ClientEvent(ClientEvent::Create(
handle, pos,
)))
.await; .await;
} }
} }

View File

@@ -84,7 +84,6 @@ fn send_event(sock: &UdpSocket, e: Event, addr: SocketAddr) -> Result<usize> {
log::trace!("{:20} ------>->->-> {addr}", e.to_string()); log::trace!("{:20} ------>->->-> {addr}", e.to_string());
let data: Vec<u8> = (&e).into(); let data: Vec<u8> = (&e).into();
// When udp blocks, we dont want to block the event loop. // When udp blocks, we dont want to block the event loop.
// Dropping events is better than potentially crashing the event // Dropping events is better than potentially crashing the input capture.
// producer.
Ok(sock.try_send_to(&data, addr)?) Ok(sock.try_send_to(&data, addr)?)
} }

View File

@@ -7,15 +7,15 @@ use tokio::{
use crate::{client::ClientHandle, event::Event}; use crate::{client::ClientHandle, event::Event};
use super::{consumer_task::ConsumerEvent, producer_task::ProducerEvent, Server, State}; use super::{capture_task::CaptureEvent, emulation_task::EmulationEvent, Server, State};
const MAX_RESPONSE_TIME: Duration = Duration::from_millis(500); const MAX_RESPONSE_TIME: Duration = Duration::from_millis(500);
pub fn new( pub fn new(
server: Server, server: Server,
sender_ch: Sender<(Event, SocketAddr)>, sender_ch: Sender<(Event, SocketAddr)>,
consumer_notify: Sender<ConsumerEvent>, emulate_notify: Sender<EmulationEvent>,
producer_notify: Sender<ProducerEvent>, capture_notify: Sender<CaptureEvent>,
mut timer_rx: Receiver<()>, mut timer_rx: Receiver<()>,
) -> JoinHandle<()> { ) -> JoinHandle<()> {
// timer task // timer task
@@ -114,14 +114,14 @@ pub fn new(
if receiving { if receiving {
for c in unresponsive_clients { for c in unresponsive_clients {
log::warn!("device not responding, releasing keys!"); log::warn!("device not responding, releasing keys!");
let _ = consumer_notify.send(ConsumerEvent::ReleaseKeys(c)).await; let _ = emulate_notify.send(EmulationEvent::ReleaseKeys(c)).await;
} }
} else { } else {
// release pointer if the active client has not responded // release pointer if the active client has not responded
if !unresponsive_clients.is_empty() { if !unresponsive_clients.is_empty() {
log::warn!("client not responding, releasing pointer!"); log::warn!("client not responding, releasing pointer!");
server.state.replace(State::Receiving); server.state.replace(State::Receiving);
let _ = producer_notify.send(ProducerEvent::Release).await; let _ = capture_notify.send(CaptureEvent::Release).await;
} }
} }
} }