Skip to main content

waydriver_input_mutter/
lib.rs

1//! Mutter implementation of [`waydriver::InputBackend`].
2//!
3//! Wraps an `Arc<MutterState>` obtained from [`waydriver_compositor_mutter::MutterCompositor::state`]
4//! and sends keyboard / pointer events via
5//! `org.gnome.Mutter.RemoteDesktop.Session.{NotifyKeyboardKeysym, NotifyPointerMotionRelative}`.
6
7use std::sync::Arc;
8
9use async_trait::async_trait;
10
11use waydriver::{Error, InputBackend, Result};
12use waydriver_compositor_mutter::MutterState;
13
14/// Mutter RemoteDesktop input backend.
15pub struct MutterInput {
16    state: Arc<MutterState>,
17}
18
19impl MutterInput {
20    /// Create a new input backend from shared compositor state.
21    pub fn new(state: Arc<MutterState>) -> Self {
22        Self { state }
23    }
24}
25
26#[async_trait]
27impl InputBackend for MutterInput {
28    async fn press_keysym(&self, keysym: u32) -> Result<()> {
29        self.state
30            .conn
31            .call_method(
32                Some("org.gnome.Mutter.RemoteDesktop"),
33                self.state.rd_session_path.as_str(),
34                Some("org.gnome.Mutter.RemoteDesktop.Session"),
35                "NotifyKeyboardKeysym",
36                &(keysym, true),
37            )
38            .await
39            .map_err(|e| Error::Process(format!("NotifyKeyboardKeysym press: {e}")))?;
40        tokio::time::sleep(std::time::Duration::from_millis(20)).await;
41        self.state
42            .conn
43            .call_method(
44                Some("org.gnome.Mutter.RemoteDesktop"),
45                self.state.rd_session_path.as_str(),
46                Some("org.gnome.Mutter.RemoteDesktop.Session"),
47                "NotifyKeyboardKeysym",
48                &(keysym, false),
49            )
50            .await
51            .map_err(|e| Error::Process(format!("NotifyKeyboardKeysym release: {e}")))?;
52        tokio::time::sleep(std::time::Duration::from_millis(30)).await;
53        Ok(())
54    }
55
56    async fn pointer_motion_relative(&self, dx: f64, dy: f64) -> Result<()> {
57        self.state
58            .conn
59            .call_method(
60                Some("org.gnome.Mutter.RemoteDesktop"),
61                self.state.rd_session_path.as_str(),
62                Some("org.gnome.Mutter.RemoteDesktop.Session"),
63                "NotifyPointerMotionRelative",
64                &(dx, dy),
65            )
66            .await
67            .map_err(|e| Error::Process(format!("NotifyPointerMotionRelative: {e}")))?;
68        Ok(())
69    }
70
71    async fn pointer_button(&self, button: u32) -> Result<()> {
72        let button: i32 = button
73            .try_into()
74            .map_err(|_| Error::Process(format!("button code {button} exceeds i32::MAX")))?;
75        self.state
76            .conn
77            .call_method(
78                Some("org.gnome.Mutter.RemoteDesktop"),
79                self.state.rd_session_path.as_str(),
80                Some("org.gnome.Mutter.RemoteDesktop.Session"),
81                "NotifyPointerButton",
82                &(button, true),
83            )
84            .await
85            .map_err(|e| Error::Process(format!("NotifyPointerButton press: {e}")))?;
86        tokio::time::sleep(std::time::Duration::from_millis(20)).await;
87        self.state
88            .conn
89            .call_method(
90                Some("org.gnome.Mutter.RemoteDesktop"),
91                self.state.rd_session_path.as_str(),
92                Some("org.gnome.Mutter.RemoteDesktop.Session"),
93                "NotifyPointerButton",
94                &(button, false),
95            )
96            .await
97            .map_err(|e| Error::Process(format!("NotifyPointerButton release: {e}")))?;
98        tokio::time::sleep(std::time::Duration::from_millis(30)).await;
99        Ok(())
100    }
101}