Skip to content

Commit

Permalink
Add a dummy backend
Browse files Browse the repository at this point in the history
  • Loading branch information
feschber committed Dec 17, 2023
1 parent eca367c commit f5a0ff4
Show file tree
Hide file tree
Showing 11 changed files with 155 additions and 175 deletions.
3 changes: 3 additions & 0 deletions src/backend/consumer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,6 @@ pub mod libei;

#[cfg(target_os = "macos")]
pub mod macos;

/// fallback consumer
pub mod dummy;
21 changes: 21 additions & 0 deletions src/backend/consumer/dummy.rs
Original file line number Diff line number Diff line change
@@ -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) {}
}
20 changes: 8 additions & 12 deletions src/backend/consumer/x11.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use anyhow::{anyhow, Result};
use async_trait::async_trait;
use std::ptr;
use x11::{xlib::{self, XCloseDisplay}, xtest};
Expand All @@ -11,15 +12,16 @@ pub struct X11Consumer {
unsafe impl Send for X11Consumer {}

impl X11Consumer {
pub fn new() -> Self {
pub fn new() -> Result<Self> {
let display = unsafe {
match xlib::XOpenDisplay(ptr::null()) {
d if d == ptr::null::<xlib::Display>() as *mut xlib::Display => None,
display => Some(display),
d if d == ptr::null::<xlib::Display>() as *mut xlib::Display => {
Err(anyhow!("could not open display"))
}
display => Ok(display),
}
};
let display = display.expect("could not open display");
Self { display }
}?;
Ok(Self { display })
}

fn relative_motion(&self, dx: i32, dy: i32) {
Expand Down Expand Up @@ -68,12 +70,6 @@ impl X11Consumer {
}
}

impl Default for X11Consumer {
fn default() -> Self {
Self::new()
}
}

impl Drop for X11Consumer {
fn drop(&mut self) {
unsafe {
Expand Down
7 changes: 7 additions & 0 deletions src/backend/producer.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
#[cfg(all(unix, feature = "libei", not(target_os = "macos")))]
pub mod libei;

#[cfg(target_os = "macos")]
pub mod macos;

#[cfg(all(unix, feature = "wayland", not(target_os = "macos")))]
pub mod wayland;

#[cfg(windows)]
pub mod windows;

#[cfg(all(unix, feature = "x11", not(target_os = "macos")))]
pub mod x11;

/// fallback event producer
pub mod dummy;
41 changes: 41 additions & 0 deletions src/backend/producer/dummy.rs
Original file line number Diff line number Diff line change
@@ -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
}
}
4 changes: 2 additions & 2 deletions src/backend/producer/libei.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use anyhow::Result;
use anyhow::{anyhow, Result};
use std::{io, task::Poll};

use futures_core::Stream;
Expand All @@ -9,7 +9,7 @@ pub struct LibeiProducer {}

impl LibeiProducer {
pub fn new() -> Result<Self> {
Ok(Self {})
Err(anyhow!("not implemented"))
}
}

Expand Down
11 changes: 3 additions & 8 deletions src/backend/producer/x11.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use anyhow::{anyhow, Result};
use std::io;
use std::task::Poll;

Expand All @@ -11,14 +12,8 @@ use crate::client::{ClientEvent, ClientHandle};
pub struct X11Producer {}

impl X11Producer {
pub fn new() -> Self {
Self {}
}
}

impl Default for X11Producer {
fn default() -> Self {
Self::new()
pub fn new() -> Result<Self> {
return Err(anyhow!("not implemented"));
}
}

Expand Down
1 change: 1 addition & 0 deletions src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ pub struct Client {
pub pos: Position,
}

#[derive(Debug)]
pub enum ClientEvent {
Create(ClientHandle, Position),
Destroy(ClientHandle),
Expand Down
129 changes: 41 additions & 88 deletions src/consumer.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,13 @@
use async_trait::async_trait;
use std::future;

#[cfg(all(unix, not(target_os = "macos")))]
use std::env;

use crate::{
backend::consumer,
client::{ClientEvent, ClientHandle},
event::Event,
};
use anyhow::Result;

#[cfg(all(unix, not(target_os = "macos")))]
#[derive(Debug)]
enum Backend {
Wlroots,
X11,
RemoteDesktopPortal,
Libei,
}

#[async_trait]
pub trait EventConsumer: Send {
async fn consume(&mut self, event: Event, client_handle: ClientHandle);
Expand All @@ -33,90 +21,55 @@ pub trait EventConsumer: Send {
async fn destroy(&mut self);
}

pub async fn create() -> Result<Box<dyn EventConsumer>> {
pub async fn create() -> Box<dyn EventConsumer> {
#[cfg(windows)]
return Ok(Box::new(consumer::windows::WindowsConsumer::new()));
return Box::new(consumer::windows::WindowsConsumer::new());

#[cfg(target_os = "macos")]
return Ok(Box::new(consumer::macos::MacOSConsumer::new()?));

#[cfg(all(unix, not(target_os = "macos")))]
let backend = match env::var("XDG_SESSION_TYPE") {
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!")
match consumer::macos::MacOSConsumer::new() {
Ok(c) => {
log::info!("using macos event consumer");
return Box::new(c);
}
};
Err(e) => log::error!("macos consumer not available: {e}"),
}

#[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?))
#[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);
}
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?,
))
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);
}
Backend::Wlroots => {
#[cfg(not(feature = "wayland"))]
panic!("feature wayland not enabled");
#[cfg(feature = "wayland")]
Ok(Box::new(consumer::wlroots::WlrootsConsumer::new()?))
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);
}
Backend::X11 => {
#[cfg(not(feature = "x11"))]
panic!("feature x11 not enabled");
#[cfg(feature = "x11")]
Ok(Box::new(consumer::x11::X11Consumer::new()))
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())
}
3 changes: 1 addition & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,7 @@ fn run_service(config: &Config) -> Result<()> {
};

// create event producer and consumer
let (producer, consumer) = join!(producer::create(), consumer::create(),);
let (producer, consumer) = (producer?, consumer?);
let (producer, consumer) = join!(producer::create(), consumer::create());

// create server
let mut event_server = Server::new(config, frontend_adapter, consumer, producer).await?;
Expand Down
Loading

0 comments on commit f5a0ff4

Please sign in to comment.