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}