From 0c48bd7ed05bf50f2eb46a5462fb23013fb8cd65 Mon Sep 17 00:00:00 2001 From: Richard Acayan Date: Thu, 17 Oct 2024 21:32:15 -0400 Subject: [PATCH] add KDE target Key presses can be sent to kwin with the EI (Emulated Input) protocol. Connecting is handled by the xdg-desktop-portal D-Bus APIs and the current D-Bus implementation is large. Add a separate target for KDE. --- Cargo.toml | 4 ++ src/ufkbd_kde.rs | 104 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 src/ufkbd_kde.rs diff --git a/Cargo.toml b/Cargo.toml index 9e82e3b..435ce53 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,6 +33,10 @@ bindgen = "0.70.1" name = "ufkbd-gnome" path = "src/ufkbd_gnome.rs" +[[bin]] +name = "ufkbd-kde" +path = "src/ufkbd_kde.rs" + [[bin]] name = "ufkbd-sxmo" path = "src/ufkbd_sxmo.rs" diff --git a/src/ufkbd_kde.rs b/src/ufkbd_kde.rs new file mode 100644 index 0000000..5effe14 --- /dev/null +++ b/src/ufkbd_kde.rs @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Copyright (c) 2024, Richard Acayan. All rights reserved. + */ + +mod core; +// mod libei; +mod wayland; + +use ashpd::WindowIdentifier; +use ashpd::desktop::PersistMode; +use ashpd::desktop::remote_desktop::DeviceType; +use ashpd::desktop::remote_desktop::RemoteDesktop; +use crate::core::Configuration; +use crate::wayland::Dispatcher; +use polling::Event; +use polling::Events; +use polling::Poller; +use std::future::pending; +use std::time::Instant; +use reis::ei::Context; +use reis::ei::handshake::ContextType; +use reis::handshake; +use tokio::task; +use wayland_client::globals; + +pub struct VisibilityManager(); + +impl VisibilityManager { + pub fn set_visible(&self, _visible: bool) + { + unreachable!(); + } +} + +#[tokio::main(flavor = "current_thread")] +async fn main() +{ + let conn = wayland_client::Connection::connect_to_env().unwrap(); + + let (globals, mut queue) = globals::registry_queue_init::(&conn) + .expect("Registry required"); + + let config = Configuration::load().unwrap(); + + let mut dispatcher = Dispatcher::new(&config, queue.handle(), &globals).unwrap(); + + let wl_evt = Event::readable(0); + + let mut events = Events::new(); + let poller = Poller::new().unwrap(); + + let wi = WindowIdentifier::default(); + let rd = RemoteDesktop::new().await.unwrap(); + let session = rd.create_session().await.unwrap(); + rd.select_devices(&session, + DeviceType::Keyboard.into(), + None, + PersistMode::DoNot).await.unwrap(); + rd.start(&session, &wi).await.unwrap(); + let eifd = rd.connect_to_eis(&session).await.unwrap(); + let ei_ctx = Context::new(eifd.into()).unwrap(); + + let ei_evt = Event::readable(1); + + task::spawn_blocking(move || { + handshake::ei_handshake_blocking(&ei_ctx, "ufkbd-kde", + ContextType::Sender).unwrap(); + + loop { + conn.flush().unwrap(); + ei_ctx.flush().unwrap(); + + let guard = queue.prepare_read().unwrap(); + let wlfd = guard.connection_fd(); + let timer = dispatcher.button().next_time().map(|t| t - Instant::now()); + + unsafe { + poller.add(&wlfd, wl_evt).unwrap(); + } + + unsafe { + poller.add(&ei_ctx, ei_evt).unwrap(); + } + + events.clear(); + poller.wait(&mut events, timer).unwrap(); + poller.delete(wlfd).unwrap(); + poller.delete(&ei_ctx).unwrap(); + + if !events.is_empty() { + let _ = guard.read(); + let _ = ei_ctx.read(); + + queue.dispatch_pending(&mut dispatcher).unwrap(); + dispatcher.dispatch_ei(&ei_ctx); + } + + dispatcher.dispatch_timers(); + } + }); + + pending::<()>().await; +}