mirror of
https://github.com/feschber/lan-mouse.git
synced 2026-04-02 16:31:30 +03:00
Add a dummy backend
This commit is contained in:
committed by
Ferdinand Schober
parent
eca367cdb4
commit
f5a0ff4f3a
@@ -15,3 +15,6 @@ pub mod libei;
|
|||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
pub mod macos;
|
pub mod macos;
|
||||||
|
|
||||||
|
/// fallback consumer
|
||||||
|
pub mod dummy;
|
||||||
|
|||||||
21
src/backend/consumer/dummy.rs
Normal file
21
src/backend/consumer/dummy.rs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
use async_trait::async_trait;
|
||||||
|
use crate::{consumer::EventConsumer, event::Event, client::{ClientHandle, ClientEvent}};
|
||||||
|
|
||||||
|
pub struct DummyConsumer;
|
||||||
|
|
||||||
|
impl DummyConsumer {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl EventConsumer for DummyConsumer {
|
||||||
|
async fn consume(&mut self, event: Event, client_handle: ClientHandle) {
|
||||||
|
log::info!("received event: ({client_handle}) {event}");
|
||||||
|
}
|
||||||
|
async fn notify(&mut self, client_event: ClientEvent) {
|
||||||
|
log::info!("{client_event:?}");
|
||||||
|
}
|
||||||
|
async fn destroy(&mut self) {}
|
||||||
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use anyhow::{anyhow, Result};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use x11::{xlib::{self, XCloseDisplay}, xtest};
|
use x11::{xlib::{self, XCloseDisplay}, xtest};
|
||||||
@@ -11,15 +12,16 @@ pub struct X11Consumer {
|
|||||||
unsafe impl Send for X11Consumer {}
|
unsafe impl Send for X11Consumer {}
|
||||||
|
|
||||||
impl X11Consumer {
|
impl X11Consumer {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Result<Self> {
|
||||||
let display = unsafe {
|
let display = unsafe {
|
||||||
match xlib::XOpenDisplay(ptr::null()) {
|
match xlib::XOpenDisplay(ptr::null()) {
|
||||||
d if d == ptr::null::<xlib::Display>() as *mut xlib::Display => None,
|
d if d == ptr::null::<xlib::Display>() as *mut xlib::Display => {
|
||||||
display => Some(display),
|
Err(anyhow!("could not open display"))
|
||||||
|
}
|
||||||
|
display => Ok(display),
|
||||||
}
|
}
|
||||||
};
|
}?;
|
||||||
let display = display.expect("could not open display");
|
Ok(Self { display })
|
||||||
Self { display }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn relative_motion(&self, dx: i32, dy: i32) {
|
fn relative_motion(&self, dx: i32, dy: i32) {
|
||||||
@@ -68,12 +70,6 @@ impl X11Consumer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for X11Consumer {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for X11Consumer {
|
impl Drop for X11Consumer {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|||||||
@@ -1,10 +1,17 @@
|
|||||||
#[cfg(all(unix, feature = "libei", not(target_os = "macos")))]
|
#[cfg(all(unix, feature = "libei", not(target_os = "macos")))]
|
||||||
pub mod libei;
|
pub mod libei;
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
pub mod macos;
|
pub mod macos;
|
||||||
|
|
||||||
#[cfg(all(unix, feature = "wayland", not(target_os = "macos")))]
|
#[cfg(all(unix, feature = "wayland", not(target_os = "macos")))]
|
||||||
pub mod wayland;
|
pub mod wayland;
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
pub mod windows;
|
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
|
||||||
|
pub mod dummy;
|
||||||
|
|||||||
41
src/backend/producer/dummy.rs
Normal file
41
src/backend/producer/dummy.rs
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
use std::io;
|
||||||
|
use std::pin::Pin;
|
||||||
|
use std::task::{Poll, Context};
|
||||||
|
|
||||||
|
use futures_core::Stream;
|
||||||
|
|
||||||
|
use crate::event::Event;
|
||||||
|
use crate::producer::EventProducer;
|
||||||
|
|
||||||
|
use crate::client::{ClientEvent, ClientHandle};
|
||||||
|
|
||||||
|
pub struct DummyProducer {}
|
||||||
|
|
||||||
|
impl DummyProducer {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for DummyProducer {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EventProducer for DummyProducer {
|
||||||
|
fn notify(&mut self, _: ClientEvent) {}
|
||||||
|
|
||||||
|
fn release(&mut self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Stream for DummyProducer {
|
||||||
|
type Item = io::Result<(ClientHandle, Event)>;
|
||||||
|
|
||||||
|
fn poll_next(
|
||||||
|
self: Pin<&mut Self>,
|
||||||
|
_cx: &mut Context<'_>,
|
||||||
|
) -> Poll<Option<Self::Item>> {
|
||||||
|
Poll::Pending
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
use anyhow::Result;
|
use anyhow::{anyhow, Result};
|
||||||
use std::{io, task::Poll};
|
use std::{io, task::Poll};
|
||||||
|
|
||||||
use futures_core::Stream;
|
use futures_core::Stream;
|
||||||
@@ -9,7 +9,7 @@ pub struct LibeiProducer {}
|
|||||||
|
|
||||||
impl LibeiProducer {
|
impl LibeiProducer {
|
||||||
pub fn new() -> Result<Self> {
|
pub fn new() -> Result<Self> {
|
||||||
Ok(Self {})
|
Err(anyhow!("not implemented"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use anyhow::{anyhow, Result};
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::task::Poll;
|
use std::task::Poll;
|
||||||
|
|
||||||
@@ -11,14 +12,8 @@ use crate::client::{ClientEvent, ClientHandle};
|
|||||||
pub struct X11Producer {}
|
pub struct X11Producer {}
|
||||||
|
|
||||||
impl X11Producer {
|
impl X11Producer {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Result<Self> {
|
||||||
Self {}
|
return Err(anyhow!("not implemented"));
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for X11Producer {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::new()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ pub struct Client {
|
|||||||
pub pos: Position,
|
pub pos: Position,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum ClientEvent {
|
pub enum ClientEvent {
|
||||||
Create(ClientHandle, Position),
|
Create(ClientHandle, Position),
|
||||||
Destroy(ClientHandle),
|
Destroy(ClientHandle),
|
||||||
|
|||||||
139
src/consumer.rs
139
src/consumer.rs
@@ -1,9 +1,6 @@
|
|||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use std::future;
|
use std::future;
|
||||||
|
|
||||||
#[cfg(all(unix, not(target_os = "macos")))]
|
|
||||||
use std::env;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::consumer,
|
backend::consumer,
|
||||||
client::{ClientEvent, ClientHandle},
|
client::{ClientEvent, ClientHandle},
|
||||||
@@ -11,15 +8,6 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
#[cfg(all(unix, not(target_os = "macos")))]
|
|
||||||
#[derive(Debug)]
|
|
||||||
enum Backend {
|
|
||||||
Wlroots,
|
|
||||||
X11,
|
|
||||||
RemoteDesktopPortal,
|
|
||||||
Libei,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
pub trait EventConsumer: Send {
|
pub trait EventConsumer: Send {
|
||||||
async fn consume(&mut self, event: Event, client_handle: ClientHandle);
|
async fn consume(&mut self, event: Event, client_handle: ClientHandle);
|
||||||
@@ -33,90 +21,55 @@ pub trait EventConsumer: Send {
|
|||||||
async fn destroy(&mut self);
|
async fn destroy(&mut self);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn create() -> Result<Box<dyn EventConsumer>> {
|
pub async fn create() -> Box<dyn EventConsumer> {
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
return Ok(Box::new(consumer::windows::WindowsConsumer::new()));
|
return Box::new(consumer::windows::WindowsConsumer::new());
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
return Ok(Box::new(consumer::macos::MacOSConsumer::new()?));
|
match consumer::macos::MacOSConsumer::new() {
|
||||||
|
Ok(c) => {
|
||||||
#[cfg(all(unix, not(target_os = "macos")))]
|
log::info!("using macos event consumer");
|
||||||
let backend = match env::var("XDG_SESSION_TYPE") {
|
return Box::new(c);
|
||||||
Ok(session_type) => match session_type.as_str() {
|
|
||||||
"x11" => {
|
|
||||||
log::info!("XDG_SESSION_TYPE = x11 -> using x11 event consumer");
|
|
||||||
Backend::X11
|
|
||||||
}
|
|
||||||
"wayland" => {
|
|
||||||
log::info!("XDG_SESSION_TYPE = wayland -> using wayland event consumer");
|
|
||||||
match env::var("XDG_CURRENT_DESKTOP") {
|
|
||||||
Ok(current_desktop) => match current_desktop.as_str() {
|
|
||||||
"GNOME" => {
|
|
||||||
log::info!("XDG_CURRENT_DESKTOP = GNOME -> using libei backend");
|
|
||||||
Backend::Libei
|
|
||||||
}
|
|
||||||
"KDE" => {
|
|
||||||
log::info!(
|
|
||||||
"XDG_CURRENT_DESKTOP = KDE -> using xdg_desktop_portal backend"
|
|
||||||
);
|
|
||||||
Backend::RemoteDesktopPortal
|
|
||||||
}
|
|
||||||
"sway" => {
|
|
||||||
log::info!("XDG_CURRENT_DESKTOP = sway -> using wlroots backend");
|
|
||||||
Backend::Wlroots
|
|
||||||
}
|
|
||||||
"Hyprland" => {
|
|
||||||
log::info!("XDG_CURRENT_DESKTOP = Hyprland -> using wlroots backend");
|
|
||||||
Backend::Wlroots
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
log::warn!(
|
|
||||||
"unknown XDG_CURRENT_DESKTOP -> defaulting to wlroots backend"
|
|
||||||
);
|
|
||||||
Backend::Wlroots
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// default to wlroots backend for now
|
|
||||||
_ => {
|
|
||||||
log::warn!("unknown XDG_CURRENT_DESKTOP -> defaulting to wlroots backend");
|
|
||||||
Backend::Wlroots
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => panic!("unknown XDG_SESSION_TYPE"),
|
|
||||||
},
|
|
||||||
Err(_) => {
|
|
||||||
panic!("could not detect session type: XDG_SESSION_TYPE environment variable not set!")
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#[cfg(all(unix, not(target_os = "macos")))]
|
|
||||||
match backend {
|
|
||||||
Backend::Libei => {
|
|
||||||
#[cfg(not(feature = "libei"))]
|
|
||||||
panic!("feature libei not enabled");
|
|
||||||
#[cfg(feature = "libei")]
|
|
||||||
Ok(Box::new(consumer::libei::LibeiConsumer::new().await?))
|
|
||||||
}
|
|
||||||
Backend::RemoteDesktopPortal => {
|
|
||||||
#[cfg(not(feature = "xdg_desktop_portal"))]
|
|
||||||
panic!("feature xdg_desktop_portal not enabled");
|
|
||||||
#[cfg(feature = "xdg_desktop_portal")]
|
|
||||||
Ok(Box::new(
|
|
||||||
consumer::xdg_desktop_portal::DesktopPortalConsumer::new().await?,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
Backend::Wlroots => {
|
|
||||||
#[cfg(not(feature = "wayland"))]
|
|
||||||
panic!("feature wayland not enabled");
|
|
||||||
#[cfg(feature = "wayland")]
|
|
||||||
Ok(Box::new(consumer::wlroots::WlrootsConsumer::new()?))
|
|
||||||
}
|
|
||||||
Backend::X11 => {
|
|
||||||
#[cfg(not(feature = "x11"))]
|
|
||||||
panic!("feature x11 not enabled");
|
|
||||||
#[cfg(feature = "x11")]
|
|
||||||
Ok(Box::new(consumer::x11::X11Consumer::new()))
|
|
||||||
}
|
}
|
||||||
|
Err(e) => log::error!("macos consumer not available: {e}"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(all(unix, feature = "wayland", not(target_os = "macos")))]
|
||||||
|
match consumer::wlroots::WlrootsConsumer::new() {
|
||||||
|
Ok(c) => {
|
||||||
|
log::info!("using wlroots event consumer");
|
||||||
|
return Box::new(c);
|
||||||
|
}
|
||||||
|
Err(e) => log::info!("wayland backend not available: {e}"),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(unix, feature = "libei", not(target_os = "macos")))]
|
||||||
|
match consumer::libei::LibeiConsumer::new().await {
|
||||||
|
Ok(c) => {
|
||||||
|
log::info!("using libei event consumer");
|
||||||
|
return Box::new(c);
|
||||||
|
}
|
||||||
|
Err(e) => log::info!("libei not available: {e}"),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(unix, feature = "xdg_desktop_portal", not(target_os = "macos")))]
|
||||||
|
match consumer::xdg_desktop_portal::DesktopPortalConsumer::new().await {
|
||||||
|
Ok(c) => {
|
||||||
|
log::info!("using xdg-remote-desktop-portal event consumer");
|
||||||
|
return Box::new(c);
|
||||||
|
}
|
||||||
|
Err(e) => log::info!("remote desktop portal not available: {e}"),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(unix, feature = "x11", not(target_os = "macos")))]
|
||||||
|
match consumer::x11::X11Consumer::new() {
|
||||||
|
Ok(c) => {
|
||||||
|
log::info!("using x11 event consumer");
|
||||||
|
return Box::new(c);
|
||||||
|
}
|
||||||
|
Err(e) => log::info!("x11 consumer not available: {e}"),
|
||||||
|
}
|
||||||
|
|
||||||
|
log::error!("falling back to dummy event consumer");
|
||||||
|
Box::new(consumer::dummy::DummyConsumer::new())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,8 +70,7 @@ fn run_service(config: &Config) -> Result<()> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// create event producer and consumer
|
// create event producer and consumer
|
||||||
let (producer, consumer) = join!(producer::create(), consumer::create(),);
|
let (producer, consumer) = join!(producer::create(), consumer::create());
|
||||||
let (producer, consumer) = (producer?, consumer?);
|
|
||||||
|
|
||||||
// create server
|
// create server
|
||||||
let mut event_server = Server::new(config, frontend_adapter, consumer, producer).await?;
|
let mut event_server = Server::new(config, frontend_adapter, consumer, producer).await?;
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
use anyhow::Result;
|
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
use futures_core::Stream;
|
use futures_core::Stream;
|
||||||
@@ -9,77 +8,42 @@ use crate::{
|
|||||||
event::Event,
|
event::Event,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(all(unix, not(target_os = "macos")))]
|
pub async fn create() -> Box<dyn EventProducer> {
|
||||||
use std::env;
|
|
||||||
|
|
||||||
#[cfg(all(unix, not(target_os = "macos")))]
|
|
||||||
enum Backend {
|
|
||||||
LayerShell,
|
|
||||||
Libei,
|
|
||||||
X11,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn create() -> Result<Box<dyn EventProducer>> {
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
return Ok(Box::new(producer::macos::MacOSProducer::new()));
|
return Box::new(producer::macos::MacOSProducer::new());
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
return Ok(Box::new(producer::windows::WindowsProducer::new()));
|
return Box::new(producer::windows::WindowsProducer::new());
|
||||||
|
|
||||||
#[cfg(all(unix, not(target_os = "macos")))]
|
#[cfg(all(unix, feature = "libei", not(target_os = "macos")))]
|
||||||
let backend = match env::var("XDG_SESSION_TYPE") {
|
match producer::libei::LibeiProducer::new() {
|
||||||
Ok(session_type) => match session_type.as_str() {
|
Ok(p) => {
|
||||||
"x11" => {
|
log::info!("using libei event producer");
|
||||||
log::info!("XDG_SESSION_TYPE = x11 -> using X11 event producer");
|
return Box::new(p);
|
||||||
Backend::X11
|
|
||||||
}
|
|
||||||
"wayland" => {
|
|
||||||
log::info!("XDG_SESSION_TYPE = wayland -> using wayland event producer");
|
|
||||||
match env::var("XDG_CURRENT_DESKTOP") {
|
|
||||||
Ok(desktop) => match desktop.as_str() {
|
|
||||||
"GNOME" => {
|
|
||||||
log::info!("XDG_CURRENT_DESKTOP = GNOME -> using libei backend");
|
|
||||||
Backend::Libei
|
|
||||||
}
|
|
||||||
d => {
|
|
||||||
log::info!("XDG_CURRENT_DESKTOP = {d} -> using layer_shell backend");
|
|
||||||
Backend::LayerShell
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Err(_) => {
|
|
||||||
log::warn!("XDG_CURRENT_DESKTOP not set! Assuming layer_shell support -> using layer_shell backend");
|
|
||||||
Backend::LayerShell
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => panic!("unknown XDG_SESSION_TYPE"),
|
|
||||||
},
|
|
||||||
Err(_) => {
|
|
||||||
panic!("could not detect session type: XDG_SESSION_TYPE environment variable not set!")
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#[cfg(all(unix, not(target_os = "macos")))]
|
|
||||||
match backend {
|
|
||||||
Backend::X11 => {
|
|
||||||
#[cfg(not(feature = "x11"))]
|
|
||||||
panic!("feature x11 not enabled");
|
|
||||||
#[cfg(feature = "x11")]
|
|
||||||
Ok(Box::new(producer::x11::X11Producer::new()))
|
|
||||||
}
|
|
||||||
Backend::LayerShell => {
|
|
||||||
#[cfg(not(feature = "wayland"))]
|
|
||||||
panic!("feature wayland not enabled");
|
|
||||||
#[cfg(feature = "wayland")]
|
|
||||||
Ok(Box::new(producer::wayland::WaylandEventProducer::new()?))
|
|
||||||
}
|
|
||||||
Backend::Libei => {
|
|
||||||
#[cfg(not(feature = "libei"))]
|
|
||||||
panic!("feature libei not enabled");
|
|
||||||
#[cfg(feature = "libei")]
|
|
||||||
Ok(Box::new(producer::libei::LibeiProducer::new()?))
|
|
||||||
}
|
}
|
||||||
|
Err(e) => log::info!("libei event producer not available: {e}"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(all(unix, feature = "wayland", not(target_os = "macos")))]
|
||||||
|
match producer::wayland::WaylandEventProducer::new() {
|
||||||
|
Ok(p) => {
|
||||||
|
log::info!("using layer-shell event producer");
|
||||||
|
return Box::new(p);
|
||||||
|
}
|
||||||
|
Err(e) => log::info!("layer_shell event producer not available: {e}"),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(unix, feature = "x11", not(target_os = "macos")))]
|
||||||
|
match producer::x11::X11Producer::new() {
|
||||||
|
Ok(p) => {
|
||||||
|
log::info!("using x11 event producer");
|
||||||
|
return Box::new(p);
|
||||||
|
}
|
||||||
|
Err(e) => log::info!("x11 event producer not available: {e}"),
|
||||||
|
}
|
||||||
|
|
||||||
|
log::error!("falling back to dummy event producer");
|
||||||
|
Box::new(producer::dummy::DummyProducer::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait EventProducer: Stream<Item = io::Result<(ClientHandle, Event)>> + Unpin {
|
pub trait EventProducer: Stream<Item = io::Result<(ClientHandle, Event)>> + Unpin {
|
||||||
|
|||||||
Reference in New Issue
Block a user