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

@ -1,4 +1,5 @@
use std::any::Any;
use std::cell::RefCell;
use std::ffi::c_void;
use std::rc::Rc;
use std::sync::Arc;
@ -6,7 +7,6 @@ use std::sync::Arc;
use blade_graphics as gpu;
use blade_rwh::{HasRawDisplayHandle, HasRawWindowHandle, RawDisplayHandle, RawWindowHandle};
use futures::channel::oneshot::Receiver;
use parking_lot::Mutex;
use raw_window_handle::{
DisplayHandle, HandleError, HasDisplayHandle, HasWindowHandle, WindowHandle,
};
@ -66,14 +66,15 @@ unsafe impl HasRawDisplayHandle for RawWindow {
}
impl WaylandWindowInner {
fn new(
conn: &Arc<wayland_client::Connection>,
wl_surf: &Arc<wl_surface::WlSurface>,
bounds: Bounds<i32>,
) -> Self {
fn new(wl_surf: &Arc<wl_surface::WlSurface>, bounds: Bounds<i32>) -> Self {
let raw = RawWindow {
window: wl_surf.id().as_ptr().cast::<c_void>(),
display: conn.backend().display_ptr().cast::<c_void>(),
display: wl_surf
.backend()
.upgrade()
.unwrap()
.display_ptr()
.cast::<c_void>(),
};
let gpu = Arc::new(
unsafe {
@ -105,9 +106,8 @@ impl WaylandWindowInner {
}
pub(crate) struct WaylandWindowState {
conn: Arc<wayland_client::Connection>,
inner: Mutex<WaylandWindowInner>,
pub(crate) callbacks: Mutex<Callbacks>,
inner: RefCell<WaylandWindowInner>,
pub(crate) callbacks: RefCell<Callbacks>,
pub(crate) surface: Arc<wl_surface::WlSurface>,
pub(crate) toplevel: Arc<xdg_toplevel::XdgToplevel>,
viewport: Option<wp_viewport::WpViewport>,
@ -115,7 +115,6 @@ pub(crate) struct WaylandWindowState {
impl WaylandWindowState {
pub(crate) fn new(
conn: &Arc<wayland_client::Connection>,
wl_surf: Arc<wl_surface::WlSurface>,
viewport: Option<wp_viewport::WpViewport>,
toplevel: Arc<xdg_toplevel::XdgToplevel>,
@ -139,34 +138,33 @@ impl WaylandWindowState {
};
Self {
conn: Arc::clone(conn),
surface: Arc::clone(&wl_surf),
inner: Mutex::new(WaylandWindowInner::new(&Arc::clone(conn), &wl_surf, bounds)),
callbacks: Mutex::new(Callbacks::default()),
inner: RefCell::new(WaylandWindowInner::new(&wl_surf, bounds)),
callbacks: RefCell::new(Callbacks::default()),
toplevel,
viewport,
}
}
pub fn update(&self) {
let mut cb = self.callbacks.lock();
let mut cb = self.callbacks.borrow_mut();
if let Some(mut fun) = cb.request_frame.take() {
drop(cb);
fun();
self.callbacks.lock().request_frame = Some(fun);
self.callbacks.borrow_mut().request_frame = Some(fun);
}
}
pub fn set_size_and_scale(&self, width: i32, height: i32, scale: f32) {
self.inner.lock().scale = scale;
self.inner.lock().bounds.size.width = width;
self.inner.lock().bounds.size.height = height;
self.inner.lock().renderer.update_drawable_size(size(
self.inner.borrow_mut().scale = scale;
self.inner.borrow_mut().bounds.size.width = width;
self.inner.borrow_mut().bounds.size.height = height;
self.inner.borrow_mut().renderer.update_drawable_size(size(
width as f64 * scale as f64,
height as f64 * scale as f64,
));
if let Some(ref mut fun) = self.callbacks.lock().resize {
if let Some(ref mut fun) = self.callbacks.borrow_mut().resize {
fun(
Size {
width: px(width as f32),
@ -182,12 +180,12 @@ impl WaylandWindowState {
}
pub fn resize(&self, width: i32, height: i32) {
let scale = self.inner.lock().scale;
let scale = self.inner.borrow_mut().scale;
self.set_size_and_scale(width, height, scale);
}
pub fn rescale(&self, scale: f32) {
let bounds = self.inner.lock().bounds;
let bounds = self.inner.borrow_mut().bounds;
self.set_size_and_scale(bounds.size.width, bounds.size.height, scale)
}
@ -200,13 +198,13 @@ impl WaylandWindowState {
/// of the decorations. This is because the state of the decorations
/// is managed by the compositor and not the client.
pub fn set_decoration_state(&self, state: WaylandDecorationState) {
self.inner.lock().decoration_state = state;
self.inner.borrow_mut().decoration_state = state;
log::trace!("Window decorations are now handled by {:?}", state);
// todo!(linux) - Handle this properly
}
pub fn close(&self) {
let mut callbacks = self.callbacks.lock();
let mut callbacks = self.callbacks.borrow_mut();
if let Some(fun) = callbacks.close.take() {
fun()
}
@ -214,13 +212,13 @@ impl WaylandWindowState {
}
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);
@ -230,7 +228,7 @@ impl WaylandWindowState {
}
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);
}
}
@ -258,7 +256,7 @@ impl PlatformWindow for WaylandWindow {
}
fn content_size(&self) -> Size<Pixels> {
let inner = self.0.inner.lock();
let inner = self.0.inner.borrow_mut();
Size {
width: Pixels(inner.bounds.size.width as f32),
height: Pixels(inner.bounds.size.height as f32),
@ -266,7 +264,7 @@ impl PlatformWindow for WaylandWindow {
}
fn scale_factor(&self) -> f32 {
self.0.inner.lock().scale
self.0.inner.borrow_mut().scale
}
//todo!(linux)
@ -300,11 +298,11 @@ impl PlatformWindow for WaylandWindow {
}
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)
@ -347,19 +345,19 @@ impl PlatformWindow for WaylandWindow {
}
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)>) {
@ -367,15 +365,15 @@ impl PlatformWindow for WaylandWindow {
}
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()>) {
@ -388,12 +386,12 @@ impl PlatformWindow for WaylandWindow {
}
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) -> Arc<dyn PlatformAtlas> {
let inner = self.0.inner.lock();
let inner = self.0.inner.borrow_mut();
inner.renderer.sprite_atlas().clone()
}