mirror of
https://github.com/feschber/lan-mouse.git
synced 2026-04-15 23:41:28 +03:00
wire frontend
This commit is contained in:
@@ -1,4 +1,3 @@
|
|||||||
use std::io;
|
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::task::{Context, Poll};
|
use std::task::{Context, Poll};
|
||||||
|
|
||||||
@@ -27,15 +26,15 @@ impl Default for DummyInputCapture {
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl InputCapture for DummyInputCapture {
|
impl InputCapture for DummyInputCapture {
|
||||||
async fn create(&mut self, _handle: CaptureHandle, _pos: Position) -> io::Result<()> {
|
async fn create(&mut self, _handle: CaptureHandle, _pos: Position) -> Result<(), CaptureError> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn destroy(&mut self, _handle: CaptureHandle) -> io::Result<()> {
|
async fn destroy(&mut self, _handle: CaptureHandle) -> Result<(), CaptureError> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn release(&mut self) -> io::Result<()> {
|
async fn release(&mut self) -> Result<(), CaptureError> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use std::{fmt::Display, io};
|
use std::fmt::Display;
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use futures_core::Stream;
|
use futures_core::Stream;
|
||||||
@@ -98,13 +98,13 @@ pub trait InputCapture:
|
|||||||
Stream<Item = Result<(CaptureHandle, Event), CaptureError>> + Unpin
|
Stream<Item = Result<(CaptureHandle, Event), CaptureError>> + Unpin
|
||||||
{
|
{
|
||||||
/// create a new client with the given id
|
/// create a new client with the given id
|
||||||
async fn create(&mut self, id: CaptureHandle, pos: Position) -> io::Result<()>;
|
async fn create(&mut self, id: CaptureHandle, pos: Position) -> Result<(), CaptureError>;
|
||||||
|
|
||||||
/// destroy the client with the given id, if it exists
|
/// destroy the client with the given id, if it exists
|
||||||
async fn destroy(&mut self, id: CaptureHandle) -> io::Result<()>;
|
async fn destroy(&mut self, id: CaptureHandle) -> Result<(), CaptureError>;
|
||||||
|
|
||||||
/// release mouse
|
/// release mouse
|
||||||
async fn release(&mut self) -> io::Result<()>;
|
async fn release(&mut self) -> Result<(), CaptureError>;
|
||||||
|
|
||||||
/// destroy the input acpture
|
/// destroy the input acpture
|
||||||
async fn terminate(&mut self) -> Result<(), CaptureError>;
|
async fn terminate(&mut self) -> Result<(), CaptureError>;
|
||||||
|
|||||||
@@ -37,10 +37,9 @@ use once_cell::sync::Lazy;
|
|||||||
|
|
||||||
use input_event::{Event, KeyboardEvent, PointerEvent};
|
use input_event::{Event, KeyboardEvent, PointerEvent};
|
||||||
|
|
||||||
use crate::error::{CaptureError, ReisConvertEventStreamError};
|
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
error::LibeiCaptureCreationError, CaptureHandle, InputCapture as LanMouseInputCapture, Position,
|
error::{CaptureError, LibeiCaptureCreationError, ReisConvertEventStreamError},
|
||||||
|
CaptureHandle, InputCapture as LanMouseInputCapture, Position,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* there is a bug in xdg-remote-desktop-portal-gnome / mutter that
|
/* there is a bug in xdg-remote-desktop-portal-gnome / mutter that
|
||||||
@@ -648,7 +647,7 @@ fn to_input_events(ei_event: EiEvent) -> Events {
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl<'a> LanMouseInputCapture for LibeiInputCapture<'a> {
|
impl<'a> LanMouseInputCapture for LibeiInputCapture<'a> {
|
||||||
async fn create(&mut self, handle: CaptureHandle, pos: Position) -> io::Result<()> {
|
async fn create(&mut self, handle: CaptureHandle, pos: Position) -> Result<(), CaptureError> {
|
||||||
let _ = self
|
let _ = self
|
||||||
.notify_capture
|
.notify_capture
|
||||||
.send(CaptureEvent::Create(handle, pos))
|
.send(CaptureEvent::Create(handle, pos))
|
||||||
@@ -656,7 +655,7 @@ impl<'a> LanMouseInputCapture for LibeiInputCapture<'a> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn destroy(&mut self, handle: CaptureHandle) -> io::Result<()> {
|
async fn destroy(&mut self, handle: CaptureHandle) -> Result<(), CaptureError> {
|
||||||
let _ = self
|
let _ = self
|
||||||
.notify_capture
|
.notify_capture
|
||||||
.send(CaptureEvent::Destroy(handle))
|
.send(CaptureEvent::Destroy(handle))
|
||||||
@@ -664,7 +663,7 @@ impl<'a> LanMouseInputCapture for LibeiInputCapture<'a> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn release(&mut self) -> io::Result<()> {
|
async fn release(&mut self) -> Result<(), CaptureError> {
|
||||||
let _ = self.notify_capture_session.send(ReleaseCaptureEvent).await;
|
let _ = self.notify_capture_session.send(ReleaseCaptureEvent).await;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,15 +25,15 @@ impl Stream for MacOSInputCapture {
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl InputCapture for MacOSInputCapture {
|
impl InputCapture for MacOSInputCapture {
|
||||||
async fn create(&mut self, _id: CaptureHandle, _pos: Position) -> io::Result<()> {
|
async fn create(&mut self, _id: CaptureHandle, _pos: Position) -> Result<(), CaptureError> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn destroy(&mut self, _id: CaptureHandle) -> io::Result<()> {
|
async fn destroy(&mut self, _id: CaptureHandle) -> Result<(), CaptureError> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn release(&mut self) -> io::Result<()> {
|
async fn release(&mut self) -> Result<(), CaptureError> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -566,23 +566,23 @@ impl Inner {
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl InputCapture for WaylandInputCapture {
|
impl InputCapture for WaylandInputCapture {
|
||||||
async fn create(&mut self, handle: CaptureHandle, pos: Position) -> io::Result<()> {
|
async fn create(&mut self, handle: CaptureHandle, pos: Position) -> Result<(), CaptureError> {
|
||||||
self.add_client(handle, pos);
|
self.add_client(handle, pos);
|
||||||
let inner = self.0.get_mut();
|
let inner = self.0.get_mut();
|
||||||
inner.flush_events()
|
Ok(inner.flush_events()?)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn destroy(&mut self, handle: CaptureHandle) -> io::Result<()> {
|
async fn destroy(&mut self, handle: CaptureHandle) -> Result<(), CaptureError> {
|
||||||
self.delete_client(handle);
|
self.delete_client(handle);
|
||||||
let inner = self.0.get_mut();
|
let inner = self.0.get_mut();
|
||||||
inner.flush_events()
|
Ok(inner.flush_events()?)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn release(&mut self) -> io::Result<()> {
|
async fn release(&mut self) -> Result<(), CaptureError> {
|
||||||
log::debug!("releasing pointer");
|
log::debug!("releasing pointer");
|
||||||
let inner = self.0.get_mut();
|
let inner = self.0.get_mut();
|
||||||
inner.state.ungrab();
|
inner.state.ungrab();
|
||||||
inner.flush_events()
|
Ok(inner.flush_events()?)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn terminate(&mut self) -> Result<(), CaptureError> {
|
async fn terminate(&mut self) -> Result<(), CaptureError> {
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ unsafe fn signal_message_thread(event_type: EventType) {
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl InputCapture for WindowsInputCapture {
|
impl InputCapture for WindowsInputCapture {
|
||||||
async fn create(&mut self, handle: CaptureHandle, pos: Position) -> io::Result<()> {
|
async fn create(&mut self, handle: CaptureHandle, pos: Position) -> Result<(), CaptureError> {
|
||||||
unsafe {
|
unsafe {
|
||||||
{
|
{
|
||||||
let mut requests = REQUEST_BUFFER.lock().unwrap();
|
let mut requests = REQUEST_BUFFER.lock().unwrap();
|
||||||
@@ -76,7 +76,7 @@ impl InputCapture for WindowsInputCapture {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn destroy(&mut self, handle: CaptureHandle) -> io::Result<()> {
|
async fn destroy(&mut self, handle: CaptureHandle) -> Result<(), CaptureError> {
|
||||||
unsafe {
|
unsafe {
|
||||||
{
|
{
|
||||||
let mut requests = REQUEST_BUFFER.lock().unwrap();
|
let mut requests = REQUEST_BUFFER.lock().unwrap();
|
||||||
@@ -87,7 +87,7 @@ impl InputCapture for WindowsInputCapture {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn release(&mut self) -> io::Result<()> {
|
async fn release(&mut self) -> Result<(), CaptureError> {
|
||||||
unsafe { signal_message_thread(EventType::Release) };
|
unsafe { signal_message_thread(EventType::Release) };
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
use std::io;
|
|
||||||
use std::task::Poll;
|
use std::task::Poll;
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
@@ -22,15 +21,15 @@ impl X11InputCapture {
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl InputCapture for X11InputCapture {
|
impl InputCapture for X11InputCapture {
|
||||||
async fn create(&mut self, _id: CaptureHandle, _pos: Position) -> io::Result<()> {
|
async fn create(&mut self, _id: CaptureHandle, _pos: Position) -> Result<(), CaptureError> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn destroy(&mut self, _id: CaptureHandle) -> io::Result<()> {
|
async fn destroy(&mut self, _id: CaptureHandle) -> Result<(), CaptureError> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn release(&mut self) -> io::Result<()> {
|
async fn release(&mut self) -> Result<(), CaptureError> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,11 +45,12 @@
|
|||||||
<property name="orientation">vertical</property>
|
<property name="orientation">vertical</property>
|
||||||
<property name="spacing">12</property>
|
<property name="spacing">12</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="AdwPreferencesGroup">
|
<object class="AdwPreferencesGroup" id="capture_emulation_group">
|
||||||
<property name="title" translatable="yes">Capture / Emulation Status</property>
|
<property name="title" translatable="yes">Capture / Emulation Status</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="AdwActionRow">
|
<object class="AdwActionRow" id="capture_status_row">
|
||||||
<property name="title">input capture is disabled</property>
|
<property name="title">input capture is disabled</property>
|
||||||
|
<property name="subtitle">required for outgoing and incoming connections</property>
|
||||||
<property name="icon-name">dialog-warning-symbolic</property>
|
<property name="icon-name">dialog-warning-symbolic</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkButton" id="input_capture_button">
|
<object class="GtkButton" id="input_capture_button">
|
||||||
@@ -73,8 +74,9 @@
|
|||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="AdwActionRow">
|
<object class="AdwActionRow" id="emulation_status_row">
|
||||||
<property name="title">input emulation is disabled</property>
|
<property name="title">input emulation is disabled</property>
|
||||||
|
<property name="subtitle">required for incoming connections</property>
|
||||||
<property name="icon-name">dialog-warning-symbolic</property>
|
<property name="icon-name">dialog-warning-symbolic</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkButton" id="input_emulation_button">
|
<object class="GtkButton" id="input_emulation_button">
|
||||||
|
|||||||
@@ -115,6 +115,21 @@ pub enum FrontendRequest {
|
|||||||
EnableEmulation,
|
EnableEmulation,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
||||||
|
pub enum Status {
|
||||||
|
Enabled,
|
||||||
|
Disabled,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Status> for bool {
|
||||||
|
fn from(status: Status) -> Self {
|
||||||
|
match status {
|
||||||
|
Status::Enabled => true,
|
||||||
|
Status::Disabled => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub enum FrontendEvent {
|
pub enum FrontendEvent {
|
||||||
/// a client was created
|
/// a client was created
|
||||||
@@ -131,6 +146,10 @@ pub enum FrontendEvent {
|
|||||||
Enumerate(Vec<(ClientHandle, ClientConfig, ClientState)>),
|
Enumerate(Vec<(ClientHandle, ClientConfig, ClientState)>),
|
||||||
/// an error occured
|
/// an error occured
|
||||||
Error(String),
|
Error(String),
|
||||||
|
/// capture status
|
||||||
|
CaptureStatus(Status),
|
||||||
|
/// emulation status
|
||||||
|
EmulationStatus(Status),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct FrontendListener {
|
pub struct FrontendListener {
|
||||||
|
|||||||
@@ -273,6 +273,12 @@ impl<'a> Cli<'a> {
|
|||||||
FrontendEvent::Error(e) => {
|
FrontendEvent::Error(e) => {
|
||||||
eprintln!("ERROR: {e}");
|
eprintln!("ERROR: {e}");
|
||||||
}
|
}
|
||||||
|
FrontendEvent::CaptureStatus(s) => {
|
||||||
|
eprintln!("capture status: {s:?}")
|
||||||
|
}
|
||||||
|
FrontendEvent::EmulationStatus(s) => {
|
||||||
|
eprintln!("emulation status: {s:?}")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -150,6 +150,12 @@ fn build_ui(app: &Application) {
|
|||||||
}
|
}
|
||||||
window.imp().set_port(port);
|
window.imp().set_port(port);
|
||||||
}
|
}
|
||||||
|
FrontendEvent::CaptureStatus(s) => {
|
||||||
|
window.set_capture(s.into());
|
||||||
|
}
|
||||||
|
FrontendEvent::EmulationStatus(s) => {
|
||||||
|
window.set_emulation(s.into());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -222,6 +222,7 @@ impl Window {
|
|||||||
pub fn request_emulation(&self) {
|
pub fn request_emulation(&self) {
|
||||||
self.request(FrontendRequest::EnableEmulation);
|
self.request(FrontendRequest::EnableEmulation);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn request_client_state(&self, client: &ClientObject) {
|
pub fn request_client_state(&self, client: &ClientObject) {
|
||||||
let handle = client.handle();
|
let handle = client.handle();
|
||||||
let event = FrontendRequest::GetState(handle);
|
let event = FrontendRequest::GetState(handle);
|
||||||
@@ -286,4 +287,24 @@ impl Window {
|
|||||||
let toast_overlay = &self.imp().toast_overlay;
|
let toast_overlay = &self.imp().toast_overlay;
|
||||||
toast_overlay.add_toast(toast);
|
toast_overlay.add_toast(toast);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_capture(&self, active: bool) {
|
||||||
|
self.imp().capture_active.replace(active);
|
||||||
|
self.update_capture_emulation_status();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_emulation(&self, active: bool) {
|
||||||
|
self.imp().emulation_active.replace(active);
|
||||||
|
self.update_capture_emulation_status();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_capture_emulation_status(&self) {
|
||||||
|
let capture = self.imp().capture_active.get();
|
||||||
|
let emulation = self.imp().emulation_active.get();
|
||||||
|
self.imp().capture_status_row.set_visible(!capture);
|
||||||
|
self.imp().emulation_status_row.set_visible(!emulation);
|
||||||
|
self.imp()
|
||||||
|
.capture_emulation_group
|
||||||
|
.set_visible(!capture || !emulation);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use std::net::TcpStream;
|
|||||||
use std::os::unix::net::UnixStream;
|
use std::os::unix::net::UnixStream;
|
||||||
|
|
||||||
use adw::subclass::prelude::*;
|
use adw::subclass::prelude::*;
|
||||||
use adw::{prelude::*, ActionRow, ToastOverlay};
|
use adw::{prelude::*, ActionRow, PreferencesGroup, ToastOverlay};
|
||||||
use glib::subclass::InitializingObject;
|
use glib::subclass::InitializingObject;
|
||||||
use gtk::glib::clone;
|
use gtk::glib::clone;
|
||||||
use gtk::{gdk, gio, glib, Button, CompositeTemplate, Entry, Label, ListBox};
|
use gtk::{gdk, gio, glib, Button, CompositeTemplate, Entry, Label, ListBox};
|
||||||
@@ -31,6 +31,12 @@ pub struct Window {
|
|||||||
#[template_child]
|
#[template_child]
|
||||||
pub toast_overlay: TemplateChild<ToastOverlay>,
|
pub toast_overlay: TemplateChild<ToastOverlay>,
|
||||||
#[template_child]
|
#[template_child]
|
||||||
|
pub capture_emulation_group: TemplateChild<PreferencesGroup>,
|
||||||
|
#[template_child]
|
||||||
|
pub capture_status_row: TemplateChild<ActionRow>,
|
||||||
|
#[template_child]
|
||||||
|
pub emulation_status_row: TemplateChild<ActionRow>,
|
||||||
|
#[template_child]
|
||||||
pub input_emulation_button: TemplateChild<Button>,
|
pub input_emulation_button: TemplateChild<Button>,
|
||||||
#[template_child]
|
#[template_child]
|
||||||
pub input_capture_button: TemplateChild<Button>,
|
pub input_capture_button: TemplateChild<Button>,
|
||||||
@@ -40,6 +46,8 @@ pub struct Window {
|
|||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
pub stream: RefCell<Option<TcpStream>>,
|
pub stream: RefCell<Option<TcpStream>>,
|
||||||
pub port: Cell<u16>,
|
pub port: Cell<u16>,
|
||||||
|
pub capture_active: Cell<bool>,
|
||||||
|
pub emulation_active: Cell<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[glib::object_subclass]
|
#[glib::object_subclass]
|
||||||
@@ -111,7 +119,6 @@ impl Window {
|
|||||||
|
|
||||||
#[template_callback]
|
#[template_callback]
|
||||||
fn handle_capture(&self) {
|
fn handle_capture(&self) {
|
||||||
log::info!("requesting capture");
|
|
||||||
self.obj().request_capture();
|
self.obj().request_capture();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -102,15 +102,21 @@ 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.clone()).await?;
|
network_task::new(self.clone(), frontend_notify_tx.clone()).await?;
|
||||||
|
|
||||||
|
// restart notify tokens
|
||||||
|
let notify_capture = Arc::new(Notify::new());
|
||||||
|
let notify_emulation = Arc::new(Notify::new());
|
||||||
|
|
||||||
// input capture
|
// input capture
|
||||||
let (mut capture_task, capture_channel) = capture_task::new(
|
let (mut capture_task, capture_channel) = capture_task::new(
|
||||||
capture_backend,
|
capture_backend,
|
||||||
self.clone(),
|
self.clone(),
|
||||||
sender_tx.clone(),
|
sender_tx.clone(),
|
||||||
|
frontend_notify_tx.clone(),
|
||||||
timer_notify.clone(),
|
timer_notify.clone(),
|
||||||
self.release_bind.clone(),
|
self.release_bind.clone(),
|
||||||
cancellation_token.clone(),
|
cancellation_token.clone(),
|
||||||
)?;
|
notify_capture.clone(),
|
||||||
|
);
|
||||||
|
|
||||||
// input emulation
|
// input emulation
|
||||||
let (mut emulation_task, emulate_channel) = emulation_task::new(
|
let (mut emulation_task, emulate_channel) = emulation_task::new(
|
||||||
@@ -119,8 +125,10 @@ impl Server {
|
|||||||
receiver_rx,
|
receiver_rx,
|
||||||
sender_tx.clone(),
|
sender_tx.clone(),
|
||||||
capture_channel.clone(),
|
capture_channel.clone(),
|
||||||
|
frontend_notify_tx.clone(),
|
||||||
timer_notify.clone(),
|
timer_notify.clone(),
|
||||||
cancellation_token.clone(),
|
cancellation_token.clone(),
|
||||||
|
notify_emulation.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// create dns resolver
|
// create dns resolver
|
||||||
@@ -133,6 +141,8 @@ impl Server {
|
|||||||
frontend,
|
frontend,
|
||||||
frontend_notify_rx,
|
frontend_notify_rx,
|
||||||
self.clone(),
|
self.clone(),
|
||||||
|
notify_emulation,
|
||||||
|
notify_capture,
|
||||||
capture_channel.clone(),
|
capture_channel.clone(),
|
||||||
emulate_channel.clone(),
|
emulate_channel.clone(),
|
||||||
resolve_tx.clone(),
|
resolve_tx.clone(),
|
||||||
@@ -175,16 +185,8 @@ impl Server {
|
|||||||
_ = signal::ctrl_c() => {
|
_ = signal::ctrl_c() => {
|
||||||
log::info!("terminating service");
|
log::info!("terminating service");
|
||||||
}
|
}
|
||||||
e = &mut capture_task => {
|
_ = &mut capture_task => { }
|
||||||
if let Ok(Err(e)) = e {
|
_ = &mut emulation_task => { }
|
||||||
log::error!("error in input capture task: {e}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
e = &mut emulation_task => {
|
|
||||||
if let Ok(Err(e)) = e {
|
|
||||||
log::error!("error in input emulation task: {e}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
e = &mut frontend_task => {
|
e = &mut frontend_task => {
|
||||||
if let Ok(Err(e)) = e {
|
if let Ok(Err(e)) = e {
|
||||||
log::error!("error in frontend listener: {e}");
|
log::error!("error in frontend listener: {e}");
|
||||||
@@ -198,20 +200,13 @@ impl Server {
|
|||||||
cancellation_token.cancel();
|
cancellation_token.cancel();
|
||||||
|
|
||||||
if !capture_task.is_finished() {
|
if !capture_task.is_finished() {
|
||||||
if let Err(e) = capture_task.await {
|
let _ = capture_task.await;
|
||||||
log::error!("error in input capture task: {e}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if !emulation_task.is_finished() {
|
if !emulation_task.is_finished() {
|
||||||
if let Err(e) = emulation_task.await {
|
let _ = emulation_task.await;
|
||||||
log::error!("error in input emulation task: {e}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !frontend_task.is_finished() {
|
if !frontend_task.is_finished() {
|
||||||
if let Err(e) = frontend_task.await {
|
let _ = frontend_task.await;
|
||||||
log::error!("error in frontend listener: {e}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
resolver_task.abort();
|
resolver_task.abort();
|
||||||
|
|||||||
@@ -1,22 +1,40 @@
|
|||||||
use anyhow::{anyhow, Result};
|
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
use std::{collections::HashSet, net::SocketAddr, sync::Arc};
|
use std::{collections::HashSet, net::SocketAddr, sync::Arc};
|
||||||
|
use thiserror::Error;
|
||||||
use tokio_util::sync::CancellationToken;
|
use tokio_util::sync::CancellationToken;
|
||||||
|
|
||||||
use tokio::{
|
use tokio::{
|
||||||
process::Command,
|
process::Command,
|
||||||
sync::{mpsc::Sender, Notify},
|
sync::{
|
||||||
|
mpsc::{Receiver, Sender},
|
||||||
|
Notify,
|
||||||
|
},
|
||||||
task::JoinHandle,
|
task::JoinHandle,
|
||||||
};
|
};
|
||||||
|
|
||||||
use input_capture::{self, error::CaptureCreationError, CaptureHandle, InputCapture, Position};
|
use input_capture::{
|
||||||
|
self, error::CaptureCreationError, CaptureError, CaptureHandle, InputCapture, Position,
|
||||||
|
};
|
||||||
|
|
||||||
use input_event::{scancode, Event, KeyboardEvent};
|
use input_event::{scancode, Event, KeyboardEvent};
|
||||||
|
|
||||||
use crate::{client::ClientHandle, config::CaptureBackend, server::State};
|
use crate::{
|
||||||
|
client::ClientHandle,
|
||||||
|
config::CaptureBackend,
|
||||||
|
frontend::{FrontendEvent, Status},
|
||||||
|
server::State,
|
||||||
|
};
|
||||||
|
|
||||||
use super::Server;
|
use super::Server;
|
||||||
|
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
pub enum LanMouseCaptureError {
|
||||||
|
#[error("error creating input-capture: `{0}`")]
|
||||||
|
Create(#[from] CaptureCreationError),
|
||||||
|
#[error("error while capturing input: `{0}`")]
|
||||||
|
Capture(#[from] CaptureError),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub enum CaptureEvent {
|
pub enum CaptureEvent {
|
||||||
/// capture must release the mouse
|
/// capture must release the mouse
|
||||||
@@ -25,60 +43,125 @@ pub enum CaptureEvent {
|
|||||||
Create(CaptureHandle, Position),
|
Create(CaptureHandle, Position),
|
||||||
/// destory a capture client
|
/// destory a capture client
|
||||||
Destroy(CaptureHandle),
|
Destroy(CaptureHandle),
|
||||||
/// restart input capture
|
|
||||||
Restart,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(
|
pub fn new(
|
||||||
backend: Option<CaptureBackend>,
|
backend: Option<CaptureBackend>,
|
||||||
server: Server,
|
server: Server,
|
||||||
sender_tx: Sender<(Event, SocketAddr)>,
|
sender_tx: Sender<(Event, SocketAddr)>,
|
||||||
|
frontend_tx: Sender<FrontendEvent>,
|
||||||
timer_notify: Arc<Notify>,
|
timer_notify: Arc<Notify>,
|
||||||
release_bind: Vec<scancode::Linux>,
|
release_bind: Vec<scancode::Linux>,
|
||||||
cancellation_token: CancellationToken,
|
cancellation_token: CancellationToken,
|
||||||
) -> Result<(JoinHandle<Result<()>>, Sender<CaptureEvent>), CaptureCreationError> {
|
notify_capture: Arc<Notify>,
|
||||||
let (tx, mut rx) = tokio::sync::mpsc::channel(32);
|
) -> (JoinHandle<()>, Sender<CaptureEvent>) {
|
||||||
|
let (tx, rx) = tokio::sync::mpsc::channel(32);
|
||||||
let backend = backend.map(|b| b.into());
|
let backend = backend.map(|b| b.into());
|
||||||
let task = tokio::task::spawn_local(async move {
|
let task = tokio::task::spawn_local(capture_task(
|
||||||
let mut capture = input_capture::create(backend).await?;
|
backend,
|
||||||
let mut pressed_keys = HashSet::new();
|
server,
|
||||||
loop {
|
sender_tx,
|
||||||
tokio::select! {
|
rx,
|
||||||
event = capture.next() => {
|
frontend_tx,
|
||||||
match event {
|
timer_notify,
|
||||||
Some(Ok(event)) => handle_capture_event(&server, &mut capture, &sender_tx, &timer_notify, event, &mut pressed_keys, &release_bind).await?,
|
release_bind,
|
||||||
Some(Err(e)) => return Err(anyhow!("input capture: {e:?}")),
|
cancellation_token,
|
||||||
None => return Err(anyhow!("input capture terminated")),
|
notify_capture,
|
||||||
}
|
));
|
||||||
}
|
(task, tx)
|
||||||
e = rx.recv() => {
|
}
|
||||||
log::debug!("input capture notify rx: {e:?}");
|
|
||||||
match e {
|
async fn capture_task(
|
||||||
Some(e) => match e {
|
backend: Option<input_capture::Backend>,
|
||||||
CaptureEvent::Release => {
|
server: Server,
|
||||||
capture.release().await?;
|
sender_tx: Sender<(Event, SocketAddr)>,
|
||||||
server.state.replace(State::Receiving);
|
mut notify_rx: Receiver<CaptureEvent>,
|
||||||
}
|
frontend_tx: Sender<FrontendEvent>,
|
||||||
CaptureEvent::Create(h, p) => capture.create(h, p).await?,
|
timer_notify: Arc<Notify>,
|
||||||
CaptureEvent::Destroy(h) => capture.destroy(h).await?,
|
release_bind: Vec<scancode::Linux>,
|
||||||
CaptureEvent::Restart => {
|
cancellation_token: CancellationToken,
|
||||||
let clients = server.client_manager.borrow().get_client_states().map(|(h, (c,_))| (h, c.pos)).collect::<Vec<_>>();
|
notify_capture: Arc<Notify>,
|
||||||
capture.terminate().await?;
|
) {
|
||||||
capture = input_capture::create(backend).await?;
|
loop {
|
||||||
for (handle, pos) in clients {
|
if let Err(e) = do_capture(
|
||||||
capture.create(handle, pos.into()).await?;
|
backend,
|
||||||
}
|
&server,
|
||||||
}
|
&sender_tx,
|
||||||
},
|
&mut notify_rx,
|
||||||
None => break,
|
&frontend_tx,
|
||||||
}
|
&timer_notify,
|
||||||
}
|
&release_bind,
|
||||||
_ = cancellation_token.cancelled() => break,
|
&cancellation_token,
|
||||||
}
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
log::warn!("input emulation exited: {e}");
|
||||||
}
|
}
|
||||||
anyhow::Ok(())
|
let _ = frontend_tx
|
||||||
});
|
.send(FrontendEvent::CaptureStatus(Status::Disabled))
|
||||||
Ok((task, tx))
|
.await;
|
||||||
|
if cancellation_token.is_cancelled() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
notify_capture.notified().await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn do_capture(
|
||||||
|
backend: Option<input_capture::Backend>,
|
||||||
|
server: &Server,
|
||||||
|
sender_tx: &Sender<(Event, SocketAddr)>,
|
||||||
|
notify_rx: &mut Receiver<CaptureEvent>,
|
||||||
|
frontend_tx: &Sender<FrontendEvent>,
|
||||||
|
timer_notify: &Notify,
|
||||||
|
release_bind: &[scancode::Linux],
|
||||||
|
cancellation_token: &CancellationToken,
|
||||||
|
) -> Result<(), LanMouseCaptureError> {
|
||||||
|
let mut capture = input_capture::create(backend).await?;
|
||||||
|
let _ = frontend_tx
|
||||||
|
.send(FrontendEvent::CaptureStatus(Status::Enabled))
|
||||||
|
.await;
|
||||||
|
|
||||||
|
// FIXME DUPLICATES
|
||||||
|
let clients = server
|
||||||
|
.client_manager
|
||||||
|
.borrow()
|
||||||
|
.get_client_states()
|
||||||
|
.map(|(h, (c, _))| (h, c.pos))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
for (handle, pos) in clients {
|
||||||
|
capture.create(handle, pos.into()).await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut pressed_keys = HashSet::new();
|
||||||
|
loop {
|
||||||
|
tokio::select! {
|
||||||
|
event = capture.next() => {
|
||||||
|
match event {
|
||||||
|
Some(Ok(event)) => handle_capture_event(server, &mut capture, sender_tx, timer_notify, event, &mut pressed_keys, release_bind).await?,
|
||||||
|
Some(Err(e)) => return Err(e.into()),
|
||||||
|
None => return Ok(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
e = notify_rx.recv() => {
|
||||||
|
log::debug!("input capture notify rx: {e:?}");
|
||||||
|
match e {
|
||||||
|
Some(e) => match e {
|
||||||
|
CaptureEvent::Release => {
|
||||||
|
capture.release().await?;
|
||||||
|
server.state.replace(State::Receiving);
|
||||||
|
}
|
||||||
|
CaptureEvent::Create(h, p) => capture.create(h, p).await?,
|
||||||
|
CaptureEvent::Destroy(h) => capture.destroy(h).await?,
|
||||||
|
},
|
||||||
|
None => break,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ = cancellation_token.cancelled() => break,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
capture.terminate().await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_pressed_keys(pressed_keys: &mut HashSet<scancode::Linux>, key: u32, state: u8) {
|
fn update_pressed_keys(pressed_keys: &mut HashSet<scancode::Linux>, key: u32, state: u8) {
|
||||||
@@ -99,7 +182,7 @@ async fn handle_capture_event(
|
|||||||
event: (CaptureHandle, Event),
|
event: (CaptureHandle, Event),
|
||||||
pressed_keys: &mut HashSet<scancode::Linux>,
|
pressed_keys: &mut HashSet<scancode::Linux>,
|
||||||
release_bind: &[scancode::Linux],
|
release_bind: &[scancode::Linux],
|
||||||
) -> Result<()> {
|
) -> Result<(), CaptureError> {
|
||||||
let (handle, mut e) = event;
|
let (handle, mut e) = event;
|
||||||
log::trace!("({handle}) {e:?}");
|
log::trace!("({handle}) {e:?}");
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ use tokio_util::sync::CancellationToken;
|
|||||||
use crate::{
|
use crate::{
|
||||||
client::{ClientHandle, ClientManager},
|
client::{ClientHandle, ClientManager},
|
||||||
config::EmulationBackend,
|
config::EmulationBackend,
|
||||||
|
frontend::{FrontendEvent, Status},
|
||||||
server::State,
|
server::State,
|
||||||
};
|
};
|
||||||
use input_emulation::{
|
use input_emulation::{
|
||||||
@@ -32,8 +33,6 @@ pub enum EmulationEvent {
|
|||||||
Destroy(EmulationHandle),
|
Destroy(EmulationHandle),
|
||||||
/// input emulation must release keys for client
|
/// input emulation must release keys for client
|
||||||
ReleaseKeys(ClientHandle),
|
ReleaseKeys(ClientHandle),
|
||||||
/// restart input emulation
|
|
||||||
Restart,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(
|
pub fn new(
|
||||||
@@ -42,12 +41,11 @@ pub fn new(
|
|||||||
udp_rx: Receiver<Result<(Event, SocketAddr), NetworkError>>,
|
udp_rx: Receiver<Result<(Event, SocketAddr), NetworkError>>,
|
||||||
sender_tx: Sender<(Event, SocketAddr)>,
|
sender_tx: Sender<(Event, SocketAddr)>,
|
||||||
capture_tx: Sender<CaptureEvent>,
|
capture_tx: Sender<CaptureEvent>,
|
||||||
|
frontend_tx: Sender<FrontendEvent>,
|
||||||
timer_notify: Arc<Notify>,
|
timer_notify: Arc<Notify>,
|
||||||
cancellation_token: CancellationToken,
|
cancellation_token: CancellationToken,
|
||||||
) -> (
|
notify_emulation: Arc<Notify>,
|
||||||
JoinHandle<Result<(), LanMouseEmulationError>>,
|
) -> (JoinHandle<()>, Sender<EmulationEvent>) {
|
||||||
Sender<EmulationEvent>,
|
|
||||||
) {
|
|
||||||
let (tx, rx) = tokio::sync::mpsc::channel(32);
|
let (tx, rx) = tokio::sync::mpsc::channel(32);
|
||||||
let emulation_task = emulation_task(
|
let emulation_task = emulation_task(
|
||||||
backend,
|
backend,
|
||||||
@@ -56,8 +54,10 @@ pub fn new(
|
|||||||
udp_rx,
|
udp_rx,
|
||||||
sender_tx,
|
sender_tx,
|
||||||
capture_tx,
|
capture_tx,
|
||||||
|
frontend_tx,
|
||||||
timer_notify,
|
timer_notify,
|
||||||
cancellation_token,
|
cancellation_token,
|
||||||
|
notify_emulation,
|
||||||
);
|
);
|
||||||
let emulate_task = tokio::task::spawn_local(emulation_task);
|
let emulate_task = tokio::task::spawn_local(emulation_task);
|
||||||
(emulate_task, tx)
|
(emulate_task, tx)
|
||||||
@@ -78,11 +78,68 @@ async fn emulation_task(
|
|||||||
mut udp_rx: Receiver<Result<(Event, SocketAddr), NetworkError>>,
|
mut udp_rx: Receiver<Result<(Event, SocketAddr), NetworkError>>,
|
||||||
sender_tx: Sender<(Event, SocketAddr)>,
|
sender_tx: Sender<(Event, SocketAddr)>,
|
||||||
capture_tx: Sender<CaptureEvent>,
|
capture_tx: Sender<CaptureEvent>,
|
||||||
|
frontend_tx: Sender<FrontendEvent>,
|
||||||
timer_notify: Arc<Notify>,
|
timer_notify: Arc<Notify>,
|
||||||
cancellation_token: CancellationToken,
|
cancellation_token: CancellationToken,
|
||||||
|
notify_emulation: Arc<Notify>,
|
||||||
|
) {
|
||||||
|
loop {
|
||||||
|
match do_emulation(
|
||||||
|
backend,
|
||||||
|
&mut rx,
|
||||||
|
&server,
|
||||||
|
&mut udp_rx,
|
||||||
|
&sender_tx,
|
||||||
|
&capture_tx,
|
||||||
|
&frontend_tx,
|
||||||
|
&timer_notify,
|
||||||
|
&cancellation_token,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(()) => {}
|
||||||
|
Err(e) => {
|
||||||
|
log::warn!("input emulation exited: {e}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let _ = frontend_tx
|
||||||
|
.send(FrontendEvent::EmulationStatus(Status::Disabled))
|
||||||
|
.await;
|
||||||
|
if cancellation_token.is_cancelled() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
notify_emulation.notified().await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn do_emulation(
|
||||||
|
backend: Option<EmulationBackend>,
|
||||||
|
rx: &mut Receiver<EmulationEvent>,
|
||||||
|
server: &Server,
|
||||||
|
udp_rx: &mut Receiver<Result<(Event, SocketAddr), NetworkError>>,
|
||||||
|
sender_tx: &Sender<(Event, SocketAddr)>,
|
||||||
|
capture_tx: &Sender<CaptureEvent>,
|
||||||
|
frontend_tx: &Sender<FrontendEvent>,
|
||||||
|
timer_notify: &Notify,
|
||||||
|
cancellation_token: &CancellationToken,
|
||||||
) -> Result<(), LanMouseEmulationError> {
|
) -> Result<(), LanMouseEmulationError> {
|
||||||
let backend = backend.map(|b| b.into());
|
let backend = backend.map(|b| b.into());
|
||||||
let mut emulation = input_emulation::create(backend).await?;
|
let mut emulation = input_emulation::create(backend).await?;
|
||||||
|
let _ = frontend_tx
|
||||||
|
.send(FrontendEvent::EmulationStatus(Status::Enabled))
|
||||||
|
.await;
|
||||||
|
|
||||||
|
// FIMXE DUPLICATES
|
||||||
|
// add clients
|
||||||
|
let clients = server
|
||||||
|
.client_manager
|
||||||
|
.borrow()
|
||||||
|
.get_client_states()
|
||||||
|
.map(|(h, _)| h)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
for handle in clients {
|
||||||
|
emulation.create(handle).await;
|
||||||
|
}
|
||||||
|
|
||||||
let mut last_ignored = None;
|
let mut last_ignored = None;
|
||||||
loop {
|
loop {
|
||||||
@@ -104,13 +161,6 @@ async fn emulation_task(
|
|||||||
EmulationEvent::Create(h) => emulation.create(h).await,
|
EmulationEvent::Create(h) => emulation.create(h).await,
|
||||||
EmulationEvent::Destroy(h) => emulation.destroy(h).await,
|
EmulationEvent::Destroy(h) => emulation.destroy(h).await,
|
||||||
EmulationEvent::ReleaseKeys(c) => release_keys(&server, &mut emulation, c).await?,
|
EmulationEvent::ReleaseKeys(c) => release_keys(&server, &mut emulation, c).await?,
|
||||||
EmulationEvent::Restart => {
|
|
||||||
let clients = server.client_manager.borrow().get_client_states().map(|(h, _)| h).collect::<Vec<_>>();
|
|
||||||
emulation = input_emulation::create(backend).await?;
|
|
||||||
for handle in clients {
|
|
||||||
emulation.create(handle).await;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
None => break,
|
None => break,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ use std::{
|
|||||||
collections::HashSet,
|
collections::HashSet,
|
||||||
io::ErrorKind,
|
io::ErrorKind,
|
||||||
net::{IpAddr, SocketAddr},
|
net::{IpAddr, SocketAddr},
|
||||||
|
sync::Arc,
|
||||||
};
|
};
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
use tokio::net::UnixStream;
|
use tokio::net::UnixStream;
|
||||||
@@ -12,7 +13,10 @@ use tokio::net::TcpStream;
|
|||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use tokio::{
|
use tokio::{
|
||||||
io::ReadHalf,
|
io::ReadHalf,
|
||||||
sync::mpsc::{Receiver, Sender},
|
sync::{
|
||||||
|
mpsc::{Receiver, Sender},
|
||||||
|
Notify,
|
||||||
|
},
|
||||||
task::JoinHandle,
|
task::JoinHandle,
|
||||||
};
|
};
|
||||||
use tokio_util::sync::CancellationToken;
|
use tokio_util::sync::CancellationToken;
|
||||||
@@ -30,6 +34,8 @@ pub(crate) fn new(
|
|||||||
mut frontend: FrontendListener,
|
mut frontend: FrontendListener,
|
||||||
mut notify_rx: Receiver<FrontendEvent>,
|
mut notify_rx: Receiver<FrontendEvent>,
|
||||||
server: Server,
|
server: Server,
|
||||||
|
notify_capture: Arc<Notify>,
|
||||||
|
notify_emulation: Arc<Notify>,
|
||||||
capture: Sender<CaptureEvent>,
|
capture: Sender<CaptureEvent>,
|
||||||
emulate: Sender<EmulationEvent>,
|
emulate: Sender<EmulationEvent>,
|
||||||
resolve_ch: Sender<DnsRequest>,
|
resolve_ch: Sender<DnsRequest>,
|
||||||
@@ -54,7 +60,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, &capture, &emulate, &resolve_ch, &mut frontend, &port_tx, frontend_event).await {
|
if handle_frontend_event(&server, ¬ify_capture, ¬ify_emulation, &capture, &emulate, &resolve_ch, &mut frontend, &port_tx, frontend_event).await {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -115,6 +121,8 @@ async fn listen_frontend(
|
|||||||
|
|
||||||
async fn handle_frontend_event(
|
async fn handle_frontend_event(
|
||||||
server: &Server,
|
server: &Server,
|
||||||
|
notify_capture: &Notify,
|
||||||
|
notify_emulation: &Notify,
|
||||||
capture: &Sender<CaptureEvent>,
|
capture: &Sender<CaptureEvent>,
|
||||||
emulate: &Sender<EmulationEvent>,
|
emulate: &Sender<EmulationEvent>,
|
||||||
resolve_tx: &Sender<DnsRequest>,
|
resolve_tx: &Sender<DnsRequest>,
|
||||||
@@ -125,10 +133,10 @@ async fn handle_frontend_event(
|
|||||||
log::debug!("frontend: {event:?}");
|
log::debug!("frontend: {event:?}");
|
||||||
match event {
|
match event {
|
||||||
FrontendRequest::EnableCapture => {
|
FrontendRequest::EnableCapture => {
|
||||||
let _ = capture.send(CaptureEvent::Restart).await;
|
notify_capture.notify_waiters();
|
||||||
}
|
}
|
||||||
FrontendRequest::EnableEmulation => {
|
FrontendRequest::EnableEmulation => {
|
||||||
let _ = emulate.send(EmulationEvent::Restart).await;
|
notify_emulation.notify_waiters();
|
||||||
}
|
}
|
||||||
FrontendRequest::Create => {
|
FrontendRequest::Create => {
|
||||||
let handle = add_client(server, frontend).await;
|
let handle = add_client(server, frontend).await;
|
||||||
|
|||||||
Reference in New Issue
Block a user