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