mirror of
https://github.com/feschber/lan-mouse.git
synced 2026-03-30 08:30:55 +03:00
implement xdg-foreign to put capture dialog on top
This commit is contained in:
committed by
Ferdinand Schober
parent
be27e337f4
commit
a5bdcd0972
@@ -2,6 +2,7 @@ use std::{
|
||||
collections::{HashMap, HashSet, VecDeque},
|
||||
fmt::Display,
|
||||
mem::swap,
|
||||
sync::{Arc, Mutex},
|
||||
task::{Poll, ready},
|
||||
};
|
||||
|
||||
@@ -129,6 +130,23 @@ pub struct InputCapture {
|
||||
pending: VecDeque<(CaptureHandle, CaptureEvent)>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum WindowIdentifier {
|
||||
Wayland(String),
|
||||
X11(u32),
|
||||
}
|
||||
|
||||
impl Into<ashpd::WindowIdentifier> for WindowIdentifier {
|
||||
fn into(self) -> ashpd::WindowIdentifier {
|
||||
match self {
|
||||
WindowIdentifier::Wayland(handle) => {
|
||||
ashpd::WindowIdentifier::from_xdg_foreign_exported_v2(handle)
|
||||
}
|
||||
WindowIdentifier::X11(_) => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl InputCapture {
|
||||
/// create a new client with the given id
|
||||
pub async fn create(&mut self, id: CaptureHandle, pos: Position) -> Result<(), CaptureError> {
|
||||
@@ -177,8 +195,11 @@ impl InputCapture {
|
||||
}
|
||||
|
||||
/// creates a new [`InputCapture`]
|
||||
pub async fn new(backend: Option<Backend>) -> Result<Self, CaptureCreationError> {
|
||||
let capture = create(backend).await?;
|
||||
pub async fn new(
|
||||
backend: Option<Backend>,
|
||||
window_identifier: Arc<Mutex<Option<WindowIdentifier>>>,
|
||||
) -> Result<Self, CaptureCreationError> {
|
||||
let capture = create(backend, window_identifier).await?;
|
||||
Ok(Self {
|
||||
capture,
|
||||
id_map: Default::default(),
|
||||
@@ -280,13 +301,16 @@ trait Capture: Stream<Item = Result<(Position, CaptureEvent), CaptureError>> + U
|
||||
|
||||
async fn create_backend(
|
||||
backend: Backend,
|
||||
window_identifier: Arc<Mutex<Option<WindowIdentifier>>>,
|
||||
) -> Result<
|
||||
Box<dyn Capture<Item = Result<(Position, CaptureEvent), CaptureError>>>,
|
||||
CaptureCreationError,
|
||||
> {
|
||||
match backend {
|
||||
#[cfg(all(unix, feature = "libei", not(target_os = "macos")))]
|
||||
Backend::InputCapturePortal => Ok(Box::new(libei::LibeiInputCapture::new().await?)),
|
||||
Backend::InputCapturePortal => Ok(Box::new(
|
||||
libei::LibeiInputCapture::new(window_identifier).await?,
|
||||
)),
|
||||
#[cfg(all(unix, feature = "layer_shell", not(target_os = "macos")))]
|
||||
Backend::LayerShell => Ok(Box::new(layer_shell::LayerShellInputCapture::new()?)),
|
||||
#[cfg(all(unix, feature = "x11", not(target_os = "macos")))]
|
||||
@@ -301,12 +325,13 @@ async fn create_backend(
|
||||
|
||||
async fn create(
|
||||
backend: Option<Backend>,
|
||||
window_identifier: Arc<Mutex<Option<WindowIdentifier>>>,
|
||||
) -> Result<
|
||||
Box<dyn Capture<Item = Result<(Position, CaptureEvent), CaptureError>>>,
|
||||
CaptureCreationError,
|
||||
> {
|
||||
if let Some(backend) = backend {
|
||||
let b = create_backend(backend).await;
|
||||
let b = create_backend(backend, window_identifier).await;
|
||||
if b.is_ok() {
|
||||
log::info!("using capture backend: {backend}");
|
||||
}
|
||||
@@ -325,7 +350,7 @@ async fn create(
|
||||
#[cfg(target_os = "macos")]
|
||||
Backend::MacOs,
|
||||
] {
|
||||
match create_backend(backend).await {
|
||||
match create_backend(backend, window_identifier.clone()).await {
|
||||
Ok(b) => {
|
||||
log::info!("using capture backend: {backend}");
|
||||
return Ok(b);
|
||||
|
||||
@@ -23,7 +23,7 @@ use std::{
|
||||
os::unix::net::UnixStream,
|
||||
pin::Pin,
|
||||
rc::Rc,
|
||||
sync::Arc,
|
||||
sync::{Arc, Mutex},
|
||||
task::{Context, Poll},
|
||||
};
|
||||
use tokio::{
|
||||
@@ -39,7 +39,7 @@ use futures_core::Stream;
|
||||
|
||||
use input_event::Event;
|
||||
|
||||
use crate::CaptureEvent;
|
||||
use crate::{CaptureEvent, WindowIdentifier};
|
||||
|
||||
use super::{
|
||||
Capture as LanMouseInputCapture, Position,
|
||||
@@ -153,11 +153,15 @@ async fn update_barriers(
|
||||
|
||||
async fn create_session(
|
||||
input_capture: &InputCapture,
|
||||
window_identifier: Arc<Mutex<Option<WindowIdentifier>>>,
|
||||
) -> std::result::Result<(Session<InputCapture>, BitFlags<Capabilities>), ashpd::Error> {
|
||||
log::debug!("creating input capture session");
|
||||
let window_identifier = window_identifier.lock().unwrap().clone();
|
||||
log::debug!("creating input capture session: {window_identifier:?}");
|
||||
let ashpd_window_identifier: Option<ashpd::WindowIdentifier> =
|
||||
window_identifier.map(|i| i.into());
|
||||
input_capture
|
||||
.create_session(
|
||||
None,
|
||||
ashpd_window_identifier.as_ref(),
|
||||
Capabilities::Keyboard | Capabilities::Pointer | Capabilities::Touchscreen,
|
||||
)
|
||||
.await
|
||||
@@ -202,10 +206,15 @@ async fn libei_event_handler(
|
||||
}
|
||||
|
||||
impl LibeiInputCapture {
|
||||
pub async fn new() -> std::result::Result<Self, LibeiCaptureCreationError> {
|
||||
/// creates a new libei input capture
|
||||
/// `window_id` is a window identifier for user prompts
|
||||
pub async fn new(
|
||||
window_identifier: Arc<Mutex<Option<WindowIdentifier>>>,
|
||||
) -> std::result::Result<Self, LibeiCaptureCreationError> {
|
||||
let input_capture = Box::pin(InputCapture::new().await?);
|
||||
let input_capture_ptr = input_capture.as_ref().get_ref() as *const InputCapture;
|
||||
let first_session = Some(create_session(unsafe { &*input_capture_ptr }).await?);
|
||||
let first_session =
|
||||
Some(create_session(unsafe { &*input_capture_ptr }, window_identifier.clone()).await?);
|
||||
|
||||
let (event_tx, event_rx) = mpsc::channel(1);
|
||||
let (notify_capture, notify_rx) = mpsc::channel(1);
|
||||
@@ -220,6 +229,7 @@ impl LibeiInputCapture {
|
||||
first_session,
|
||||
event_tx,
|
||||
cancellation_token.clone(),
|
||||
window_identifier,
|
||||
);
|
||||
let capture_task = tokio::task::spawn_local(capture);
|
||||
|
||||
@@ -244,6 +254,7 @@ async fn do_capture(
|
||||
session: Option<(Session<InputCapture>, BitFlags<Capabilities>)>,
|
||||
event_tx: Sender<(Position, CaptureEvent)>,
|
||||
cancellation_token: CancellationToken,
|
||||
window_identifier: Arc<Mutex<Option<WindowIdentifier>>>,
|
||||
) -> Result<(), CaptureError> {
|
||||
let mut session = session.map(|s| s.0);
|
||||
|
||||
@@ -289,7 +300,11 @@ async fn do_capture(
|
||||
// create session
|
||||
let mut session = match session.take() {
|
||||
Some(s) => s,
|
||||
None => create_session(input_capture).await?.0,
|
||||
None => {
|
||||
create_session(input_capture, window_identifier.clone())
|
||||
.await?
|
||||
.0
|
||||
}
|
||||
};
|
||||
|
||||
let capture_session = do_capture_session(
|
||||
|
||||
Reference in New Issue
Block a user