gpui: Decouple X11 logic from LinuxPlatform (#7598)

Release Notes:

- Separated Linux platform and X11-specific code, so that we can add
Wayland support now.

---------

Co-authored-by: Mikayla <mikayla@zed.dev>
This commit is contained in:
Roman 2024-02-12 21:44:34 +03:00 committed by GitHub
parent 2e7db57e16
commit 266988adea
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 337 additions and 215 deletions

View file

@ -4,6 +4,7 @@
//todo!(linux): remove
#![allow(unused_variables)]
use crate::platform::linux::client_dispatcher::ClientDispatcher;
use crate::{PlatformDispatcher, TaskLabel};
use async_task::Runnable;
use parking::{Parker, Unparker};
@ -14,11 +15,9 @@ use std::{
thread,
time::{Duration, Instant},
};
use xcb::x;
pub(crate) struct LinuxDispatcher {
xcb_connection: Arc<xcb::Connection>,
x_listener_window: x::Window,
client_dispatcher: Arc<dyn ClientDispatcher + Send + Sync>,
parker: Mutex<Parker>,
timed_tasks: Mutex<Vec<(Instant, Runnable)>>,
main_sender: flume::Sender<Runnable>,
@ -30,38 +29,16 @@ pub(crate) struct LinuxDispatcher {
impl LinuxDispatcher {
pub fn new(
main_sender: flume::Sender<Runnable>,
xcb_connection: &Arc<xcb::Connection>,
x_root_index: i32,
client_dispatcher: &Arc<dyn ClientDispatcher + Send + Sync>,
) -> Self {
let x_listener_window = xcb_connection.generate_id();
let screen = xcb_connection
.get_setup()
.roots()
.nth(x_root_index as usize)
.unwrap();
xcb_connection.send_request(&x::CreateWindow {
depth: 0,
wid: x_listener_window,
parent: screen.root(),
x: 0,
y: 0,
width: 1,
height: 1,
border_width: 0,
class: x::WindowClass::InputOnly,
visual: screen.root_visual(),
value_list: &[],
});
let (background_sender, background_receiver) = flume::unbounded::<Runnable>();
let background_thread = thread::spawn(move || {
for runnable in background_receiver {
let _ignore_panic = panic::catch_unwind(|| runnable.run());
}
});
LinuxDispatcher {
xcb_connection: Arc::clone(xcb_connection),
x_listener_window,
Self {
client_dispatcher: Arc::clone(client_dispatcher),
parker: Mutex::new(Parker::new()),
timed_tasks: Mutex::new(Vec::new()),
main_sender,
@ -72,14 +49,6 @@ impl LinuxDispatcher {
}
}
impl Drop for LinuxDispatcher {
fn drop(&mut self) {
self.xcb_connection.send_request(&x::DestroyWindow {
window: self.x_listener_window,
});
}
}
impl PlatformDispatcher for LinuxDispatcher {
fn is_main_thread(&self) -> bool {
thread::current().id() == self.main_thread_id
@ -91,18 +60,7 @@ impl PlatformDispatcher for LinuxDispatcher {
fn dispatch_on_main_thread(&self, runnable: Runnable) {
self.main_sender.send(runnable).unwrap();
// Send a message to the invisible window, forcing
// the main loop to wake up and dispatch the runnable.
self.xcb_connection.send_request(&x::SendEvent {
propagate: false,
destination: x::SendEventDest::Window(self.x_listener_window),
event_mask: x::EventMask::NO_EVENT,
event: &x::VisibilityNotifyEvent::new(
self.x_listener_window,
x::Visibility::Unobscured,
),
});
self.xcb_connection.flush().unwrap();
self.client_dispatcher.dispatch_on_main_thread();
}
fn dispatch_after(&self, duration: Duration, runnable: Runnable) {