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:
parent
198dfe0097
commit
b76e0d997e
15 changed files with 615 additions and 632 deletions
|
@ -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()
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue