Support event consumer on KDE! (portal backend) (#31)

* Support event consumer on KDE! (portal backend)

Support for KDE event emulation using the remote-desktop xdg-desktop-portal

* fix scrolling (TODO: smooth / kinetic scrolling)

* windows: fix compilation errors

* Update README.md
This commit is contained in:
Ferdinand Schober
2023-10-13 13:57:33 +02:00
committed by GitHub
parent 4cdc5ea49c
commit be0fe9f2d9
11 changed files with 807 additions and 151 deletions

View File

@@ -1,4 +1,4 @@
use crate::consumer::EventConsumer;
use crate::consumer::SyncConsumer;
pub struct LibeiConsumer {}
@@ -6,7 +6,7 @@ impl LibeiConsumer {
pub fn new() -> Self { Self { } }
}
impl EventConsumer for LibeiConsumer {
impl SyncConsumer for LibeiConsumer {
fn consume(&mut self, _: crate::event::Event, _: crate::client::ClientHandle) {
log::error!("libei backend not yet implemented!");
todo!()

View File

@@ -1,4 +1,4 @@
use crate::{event::{KeyboardEvent, PointerEvent}, consumer::EventConsumer};
use crate::{event::{KeyboardEvent, PointerEvent}, consumer::SyncConsumer};
use winapi::{
self,
um::winuser::{INPUT, INPUT_MOUSE, LPINPUT, MOUSEEVENTF_MOVE, MOUSEINPUT,
@@ -25,7 +25,7 @@ impl WindowsConsumer {
pub fn new() -> Self { Self { } }
}
impl EventConsumer for WindowsConsumer {
impl SyncConsumer for WindowsConsumer {
fn consume(&mut self, event: Event, _: ClientHandle) {
match event {
Event::Pointer(pointer_event) => match pointer_event {

View File

@@ -1,7 +1,7 @@
use wayland_client::WEnum;
use wayland_client::backend::WaylandError;
use crate::client::{ClientHandle, ClientEvent};
use crate::consumer::EventConsumer;
use crate::consumer::SyncConsumer;
use std::collections::HashMap;
use std::io;
use std::os::fd::OwnedFd;
@@ -140,7 +140,7 @@ impl State {
}
}
impl EventConsumer for WlrootsConsumer {
impl SyncConsumer for WlrootsConsumer {
fn consume(&mut self, event: Event, client_handle: ClientHandle) {
if let Some(virtual_input) = self.state.input_for_client.get(&client_handle) {
if self.last_flush_failed {

View File

@@ -3,7 +3,7 @@ use x11::{xlib, xtest};
use crate::{
client::ClientHandle,
event::Event, consumer::EventConsumer,
event::Event, consumer::SyncConsumer,
};
pub struct X11Consumer {
@@ -30,7 +30,7 @@ impl X11Consumer {
}
}
impl EventConsumer for X11Consumer {
impl SyncConsumer for X11Consumer {
fn consume(&mut self, event: Event, _: ClientHandle) {
match event {
Event::Pointer(pointer_event) => match pointer_event {

View File

@@ -1,15 +1,91 @@
use crate::consumer::EventConsumer;
use async_trait::async_trait;
use anyhow::Result;
use ashpd::{desktop::{remote_desktop::{RemoteDesktop, DeviceType, KeyState, Axis}, Session}, WindowIdentifier};
pub struct DesktopPortalConsumer {}
use crate::consumer::AsyncConsumer;
impl DesktopPortalConsumer {
pub fn new() -> Self { Self { } }
pub struct DesktopPortalConsumer<'a> {
proxy: RemoteDesktop<'a>,
session: Session<'a>,
}
impl EventConsumer for DesktopPortalConsumer {
fn consume(&mut self, _: crate::event::Event, _: crate::client::ClientHandle) {
log::error!("xdg_desktop_portal backend not yet implemented!");
impl<'a> DesktopPortalConsumer<'a> {
pub async fn new() -> Result<DesktopPortalConsumer<'a>> {
let proxy = RemoteDesktop::new().await?;
let session = proxy.create_session().await?;
proxy
.select_devices(&session, DeviceType::Keyboard | DeviceType::Pointer)
.await?;
let _ = proxy
.start(&session, &WindowIdentifier::default())
.await?
.response()?;
Ok(Self { proxy, session })
}
}
#[async_trait]
impl<'a> AsyncConsumer for DesktopPortalConsumer<'a> {
async fn consume(&mut self, event: crate::event::Event, _client: crate::client::ClientHandle) {
match event {
crate::event::Event::Pointer(p) => {
match p {
crate::event::PointerEvent::Motion { time: _, relative_x, relative_y } => {
if let Err(e) = self.proxy.notify_pointer_motion(&self.session, relative_x, relative_y).await {
log::warn!("{e}");
}
},
crate::event::PointerEvent::Button { time: _, button, state } => {
let state = match state {
0 => KeyState::Released,
_ => KeyState::Pressed,
};
if let Err(e) = self.proxy.notify_pointer_button(&self.session, button as i32, state).await {
log::warn!("{e}");
}
},
crate::event::PointerEvent::Axis { time: _, axis, value } => {
let axis = match axis {
0 => Axis::Vertical,
_ => Axis::Horizontal,
};
// TODO smooth scrolling
if let Err(e) = self.proxy.notify_pointer_axis_discrete(&self.session, axis, value as i32).await {
log::warn!("{e}");
}
},
crate::event::PointerEvent::Frame { } => {},
}
},
crate::event::Event::Keyboard(k) => {
match k {
crate::event::KeyboardEvent::Key { time: _, key, state } => {
let state = match state {
0 => KeyState::Released,
_ => KeyState::Pressed,
};
if let Err(e) = self.proxy.notify_keyboard_keycode(&self.session, key as i32, state).await {
log::warn!("{e}");
}
},
crate::event::KeyboardEvent::Modifiers { .. } => {
// ignore
},
}
},
_ => {},
}
}
fn notify(&mut self, _: crate::client::ClientEvent) {}
async fn notify(&mut self, _client: crate::client::ClientEvent) { }
async fn destroy(&mut self) {
log::debug!("closing remote desktop session");
if let Err(e) = self.session.close().await {
log::error!("failed to close remote desktop session: {e}");
}
}
}