client_dispatcher.rs

 1use std::sync::Arc;
 2
 3use xcb::x;
 4
 5use crate::platform::linux::client_dispatcher::ClientDispatcher;
 6
 7pub(crate) struct X11ClientDispatcher {
 8    xcb_connection: Arc<xcb::Connection>,
 9    x_listener_window: x::Window,
10}
11
12impl X11ClientDispatcher {
13    pub fn new(xcb_connection: &Arc<xcb::Connection>, x_root_index: i32) -> Self {
14        let x_listener_window = xcb_connection.generate_id();
15        let screen = xcb_connection
16            .get_setup()
17            .roots()
18            .nth(x_root_index as usize)
19            .unwrap();
20        xcb_connection.send_request(&x::CreateWindow {
21            depth: 0,
22            wid: x_listener_window,
23            parent: screen.root(),
24            x: 0,
25            y: 0,
26            width: 1,
27            height: 1,
28            border_width: 0,
29            class: x::WindowClass::InputOnly,
30            visual: screen.root_visual(),
31            value_list: &[],
32        });
33
34        Self {
35            xcb_connection: Arc::clone(xcb_connection),
36            x_listener_window,
37        }
38    }
39}
40
41impl Drop for X11ClientDispatcher {
42    fn drop(&mut self) {
43        self.xcb_connection.send_request(&x::DestroyWindow {
44            window: self.x_listener_window,
45        });
46    }
47}
48
49impl ClientDispatcher for X11ClientDispatcher {
50    fn dispatch_on_main_thread(&self) {
51        // Send a message to the invisible window, forcing
52        // the main loop to wake up and dispatch the runnable.
53        self.xcb_connection.send_request(&x::SendEvent {
54            propagate: false,
55            destination: x::SendEventDest::Window(self.x_listener_window),
56            event_mask: x::EventMask::NO_EVENT,
57            event: &x::VisibilityNotifyEvent::new(
58                self.x_listener_window,
59                x::Visibility::Unobscured,
60            ),
61        });
62        self.xcb_connection.flush().unwrap();
63    }
64}