Linux: Rewrite the event loop using calloop (#8314)

This PR unifies the event loop code for Wayland and X11. On Wayland,
blocking dispatch is now used. On X11, the invisible window is no longer
needed.

Release Notes:

- N/A

---------

Co-authored-by: Dzmitry Malyshau <kvark@fastmail.com>
Co-authored-by: Tadeo Kondrak <me@tadeo.ca>
Co-authored-by: Mikayla Maki <mikayla@zed.dev>
Co-authored-by: julia <julia@zed.dev>
This commit is contained in:
Roman 2024-02-28 14:59:11 -08:00 committed by GitHub
parent 198dfe0097
commit b76e0d997e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 615 additions and 632 deletions

View file

@ -4,7 +4,7 @@
use crate::{
platform::blade::BladeRenderer, size, Bounds, GlobalPixels, Modifiers, Pixels, PlatformAtlas,
PlatformDisplay, PlatformInput, PlatformInputHandler, PlatformWindow, Point, PromptLevel,
Scene, Size, WindowAppearance, WindowBounds, WindowOptions, X11Display,
Scene, Size, WindowAppearance, WindowBounds, WindowOptions,
};
use blade_graphics as gpu;
use parking_lot::Mutex;
@ -16,6 +16,7 @@ use xcb::{
};
use std::{
cell::RefCell,
ffi::c_void,
mem,
num::NonZeroU32,
@ -24,6 +25,8 @@ use std::{
sync::{self, Arc},
};
use super::X11Display;
#[derive(Default)]
struct Callbacks {
request_frame: Option<Box<dyn FnMut()>>,
@ -85,12 +88,12 @@ struct RawWindow {
}
pub(crate) struct X11WindowState {
xcb_connection: Arc<xcb::Connection>,
xcb_connection: Rc<xcb::Connection>,
display: Rc<dyn PlatformDisplay>,
raw: RawWindow,
x_window: x::Window,
callbacks: Mutex<Callbacks>,
inner: Mutex<LinuxWindowInner>,
callbacks: RefCell<Callbacks>,
inner: RefCell<LinuxWindowInner>,
}
#[derive(Clone)]
@ -136,7 +139,7 @@ impl rwh::HasDisplayHandle for X11Window {
impl X11WindowState {
pub fn new(
options: WindowOptions,
xcb_connection: &Arc<xcb::Connection>,
xcb_connection: &Rc<xcb::Connection>,
x_main_screen_index: i32,
x_window: x::Window,
atoms: &XcbAtoms,
@ -253,12 +256,12 @@ impl X11WindowState {
let gpu_extent = query_render_extent(xcb_connection, x_window);
Self {
xcb_connection: Arc::clone(xcb_connection),
xcb_connection: xcb_connection.clone(),
display: Rc::new(X11Display::new(xcb_connection, x_screen_index)),
raw,
x_window,
callbacks: Mutex::new(Callbacks::default()),
inner: Mutex::new(LinuxWindowInner {
callbacks: RefCell::new(Callbacks::default()),
inner: RefCell::new(LinuxWindowInner {
bounds,
scale_factor: 1.0,
renderer: BladeRenderer::new(gpu, gpu_extent),
@ -268,23 +271,26 @@ impl X11WindowState {
}
pub fn destroy(&self) {
self.inner.lock().renderer.destroy();
self.inner.borrow_mut().renderer.destroy();
self.xcb_connection.send_request(&x::UnmapWindow {
window: self.x_window,
});
self.xcb_connection.send_request(&x::DestroyWindow {
window: self.x_window,
});
if let Some(fun) = self.callbacks.lock().close.take() {
if let Some(fun) = self.callbacks.borrow_mut().close.take() {
fun();
}
self.xcb_connection.flush().unwrap();
}
pub fn refresh(&self) {
let mut cb = self.callbacks.lock();
if let Some(ref mut fun) = cb.request_frame {
let mut cb = self.callbacks.borrow_mut();
if let Some(mut fun) = cb.request_frame.take() {
drop(cb);
fun();
let mut cb = self.callbacks.borrow_mut();
cb.request_frame = Some(fun);
}
}
@ -292,7 +298,7 @@ impl X11WindowState {
let mut resize_args = None;
let do_move;
{
let mut inner = self.inner.lock();
let mut inner = self.inner.borrow_mut();
let old_bounds = mem::replace(&mut inner.bounds, bounds);
do_move = old_bounds.origin != bounds.origin;
//todo!(linux): use normal GPUI types here, refactor out the double
@ -306,7 +312,7 @@ impl X11WindowState {
}
}
let mut callbacks = self.callbacks.lock();
let mut callbacks = self.callbacks.borrow_mut();
if let Some((content_size, scale_factor)) = resize_args {
if let Some(ref mut fun) = callbacks.resize {
fun(content_size, scale_factor)
@ -330,13 +336,13 @@ impl X11WindowState {
}
pub fn handle_input(&self, input: PlatformInput) {
if let Some(ref mut fun) = self.callbacks.lock().input {
if let Some(ref mut fun) = self.callbacks.borrow_mut().input {
if fun(input.clone()) {
return;
}
}
if let PlatformInput::KeyDown(event) = input {
let mut inner = self.inner.lock();
let mut inner = self.inner.borrow_mut();
if let Some(ref mut input_handler) = inner.input_handler {
if let Some(ime_key) = &event.keystroke.ime_key {
input_handler.replace_text_in_range(None, ime_key);
@ -346,7 +352,7 @@ impl X11WindowState {
}
pub fn set_focused(&self, focus: bool) {
if let Some(ref mut fun) = self.callbacks.lock().active_status_change {
if let Some(ref mut fun) = self.callbacks.borrow_mut().active_status_change {
fun(focus);
}
}
@ -354,15 +360,21 @@ impl X11WindowState {
impl PlatformWindow for X11Window {
fn bounds(&self) -> WindowBounds {
WindowBounds::Fixed(self.0.inner.lock().bounds.map(|v| GlobalPixels(v as f32)))
WindowBounds::Fixed(
self.0
.inner
.borrow_mut()
.bounds
.map(|v| GlobalPixels(v as f32)),
)
}
fn content_size(&self) -> Size<Pixels> {
self.0.inner.lock().content_size()
self.0.inner.borrow_mut().content_size()
}
fn scale_factor(&self) -> f32 {
self.0.inner.lock().scale_factor
self.0.inner.borrow_mut().scale_factor
}
//todo!(linux)
@ -400,11 +412,11 @@ impl PlatformWindow for X11Window {
}
fn set_input_handler(&mut self, input_handler: PlatformInputHandler) {
self.0.inner.lock().input_handler = Some(input_handler);
self.0.inner.borrow_mut().input_handler = Some(input_handler);
}
fn take_input_handler(&mut self) -> Option<PlatformInputHandler> {
self.0.inner.lock().input_handler.take()
self.0.inner.borrow_mut().input_handler.take()
}
//todo!(linux)
@ -464,39 +476,39 @@ impl PlatformWindow for X11Window {
}
fn on_request_frame(&self, callback: Box<dyn FnMut()>) {
self.0.callbacks.lock().request_frame = Some(callback);
self.0.callbacks.borrow_mut().request_frame = Some(callback);
}
fn on_input(&self, callback: Box<dyn FnMut(PlatformInput) -> bool>) {
self.0.callbacks.lock().input = Some(callback);
self.0.callbacks.borrow_mut().input = Some(callback);
}
fn on_active_status_change(&self, callback: Box<dyn FnMut(bool)>) {
self.0.callbacks.lock().active_status_change = Some(callback);
self.0.callbacks.borrow_mut().active_status_change = Some(callback);
}
fn on_resize(&self, callback: Box<dyn FnMut(Size<Pixels>, f32)>) {
self.0.callbacks.lock().resize = Some(callback);
self.0.callbacks.borrow_mut().resize = Some(callback);
}
fn on_fullscreen(&self, callback: Box<dyn FnMut(bool)>) {
self.0.callbacks.lock().fullscreen = Some(callback);
self.0.callbacks.borrow_mut().fullscreen = Some(callback);
}
fn on_moved(&self, callback: Box<dyn FnMut()>) {
self.0.callbacks.lock().moved = Some(callback);
self.0.callbacks.borrow_mut().moved = Some(callback);
}
fn on_should_close(&self, callback: Box<dyn FnMut() -> bool>) {
self.0.callbacks.lock().should_close = Some(callback);
self.0.callbacks.borrow_mut().should_close = Some(callback);
}
fn on_close(&self, callback: Box<dyn FnOnce()>) {
self.0.callbacks.lock().close = Some(callback);
self.0.callbacks.borrow_mut().close = Some(callback);
}
fn on_appearance_changed(&self, callback: Box<dyn FnMut()>) {
self.0.callbacks.lock().appearance_changed = Some(callback);
self.0.callbacks.borrow_mut().appearance_changed = Some(callback);
}
//todo!(linux)
@ -505,12 +517,12 @@ impl PlatformWindow for X11Window {
}
fn draw(&self, scene: &Scene) {
let mut inner = self.0.inner.lock();
let mut inner = self.0.inner.borrow_mut();
inner.renderer.draw(scene);
}
fn sprite_atlas(&self) -> sync::Arc<dyn PlatformAtlas> {
let inner = self.0.inner.lock();
let inner = self.0.inner.borrow_mut();
inner.renderer.sprite_atlas().clone()
}