File: virtual_pointer.rs

package info (click to toggle)
phrog 0.50.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 716 kB
  • sloc: makefile: 35; sh: 28; xml: 25
file content (146 lines) | stat: -rw-r--r-- 4,741 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
use gtk::prelude::*;
use gtk::{Widget, glib};
use std::time::{Duration, SystemTime};
use wayland_client::protocol::wl_pointer::ButtonState;
use wayland_client::protocol::wl_registry;
use wayland_client::protocol::wl_seat::WlSeat;
use wayland_client::{Connection, Dispatch, EventQueue, QueueHandle, delegate_noop};
use wayland_protocols_wlr::virtual_pointer::v1::client::zwlr_virtual_pointer_manager_v1::ZwlrVirtualPointerManagerV1;
use wayland_protocols_wlr::virtual_pointer::v1::client::zwlr_virtual_pointer_v1::ZwlrVirtualPointerV1;

#[derive(Default)]
struct State {
    seat: Option<WlSeat>,
    pointer_manager: Option<ZwlrVirtualPointerManagerV1>,
}

pub struct VirtualPointer {
    ts: SystemTime,
    event_queue: EventQueue<State>,
    ptr: ZwlrVirtualPointerV1,
    x: u32,
    y: u32,
}

impl Dispatch<wl_registry::WlRegistry, ()> for State {
    fn event(
        state: &mut Self,
        registry: &wl_registry::WlRegistry,
        event: wl_registry::Event,
        _data: &(),
        _conn: &Connection,
        qh: &QueueHandle<Self>,
    ) {
        if let wl_registry::Event::Global {
            name,
            interface,
            version: _,
        } = event
        {
            match &interface[..] {
                "wl_seat" => {
                    state.seat = Some(registry.bind::<WlSeat, _, _>(name, 1, qh, ()));
                }
                "zwlr_virtual_pointer_manager_v1" => {
                    state.pointer_manager =
                        Some(registry.bind::<ZwlrVirtualPointerManagerV1, _, _>(name, 1, qh, ()));
                }
                _ => {}
            }
        }
    }
}

impl VirtualPointer {
    pub fn new(conn: Connection, width: u32, height: u32) -> Self {
        let mut event_queue = conn.new_event_queue();
        let mut state: State = Default::default();
        let _ = conn.display().get_registry(&event_queue.handle(), ());
        let ts = SystemTime::now();
        event_queue.roundtrip(&mut state).unwrap();

        let ptr = state
            .pointer_manager
            .as_ref()
            .unwrap()
            .create_virtual_pointer(state.seat.as_ref(), &event_queue.handle(), ());

        let x = width / 2;
        let y = height / 2;
        ptr.motion_absolute(ts.elapsed().unwrap().as_millis() as _, x, y, width, height);
        ptr.frame();
        event_queue.flush().unwrap();

        Self {
            ts,
            event_queue: conn.new_event_queue(),
            ptr,
            x,
            y,
        }
    }

    pub async fn click_on(&mut self, widget: &impl IsA<Widget>) {
        let (mut x, y) = widget
            .translate_coordinates(&widget.toplevel().unwrap(), 0, 0)
            .unwrap();
        x += widget.allocated_width() / 2;
        self.click_at(x as _, y as _).await;
    }

    pub async fn click_at(&mut self, x: u32, y: u32) {
        while self.x != x || self.y != y {
            fn step(distance: f64) -> f64 {
                let abs = distance.abs();
                let step = distance * (1. / abs);
                (if abs == 0. {
                    0.
                } else if abs > 10. {
                    step * 3.
                } else {
                    step
                })
                .floor()
            }
            let distance_x = x as f64 - self.x as f64;
            let distance_y = y as f64 - self.y as f64;

            let step_x = step(distance_x);
            let step_y = step(distance_y);
            self.ptr
                .motion(self.ts.elapsed().unwrap().as_millis() as _, step_x, step_y);
            self.ptr.frame();
            self.event_queue.flush().unwrap();
            self.x = (self.x as f64 + step_x) as _;
            self.y = (self.y as f64 + step_y) as _;
            glib::timeout_future(Duration::from_millis(1)).await;
        }

        glib::timeout_future(Duration::from_millis(150)).await;
        self.click().await;
    }

    pub async fn click(&self) {
        // I found this magic 272 constant in moverest/wl-kbptr sources.
        // TODO: demystify this voodoo number
        self.ptr.button(
            self.ts.elapsed().unwrap().as_millis() as _,
            272,
            ButtonState::Pressed,
        );
        self.ptr.frame();
        self.event_queue.flush().unwrap();
        glib::timeout_future(Duration::from_millis(50)).await;
        self.ptr.button(
            self.ts.elapsed().unwrap().as_millis() as _,
            272,
            ButtonState::Released,
        );
        self.ptr.frame();
        self.event_queue.flush().unwrap();
    }
}

delegate_noop!(State: ignore WlSeat);
delegate_noop!(State: ignore ZwlrVirtualPointerManagerV1);
delegate_noop!(State: ignore ZwlrVirtualPointerV1);