Text, many performance improvements

This commit is contained in:
2026-03-20 19:23:55 -04:00
parent 39ede248cf
commit 00fe1daa0c
18 changed files with 3432 additions and 26 deletions

View File

@@ -4,7 +4,9 @@ version = "0.1.0"
edition = "2024"
[dependencies]
libc = "0.2"
raw-window-handle = "0.6"
ruin_runtime = { package = "ruin-runtime", path = "../runtime" }
ruin_ui = { path = "../ui" }
wayland-backend = { version = "0.3", features = ["client_system"] }
wayland-client = "0.31"

View File

@@ -1,7 +1,10 @@
use std::error::Error;
use std::ffi::c_void;
use std::io::ErrorKind;
use std::num::NonZeroU32;
use std::os::fd::{AsFd, AsRawFd};
use std::ptr::NonNull;
use std::time::Duration;
use raw_window_handle::{
DisplayHandle, HandleError, HasDisplayHandle, HasWindowHandle, RawDisplayHandle,
@@ -44,6 +47,12 @@ pub struct FrameRequest {
pub resized: bool,
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub struct WaitOutcome {
pub dispatched: usize,
pub external_ready: bool,
}
pub struct WaylandWindow {
event_queue: wayland_client::EventQueue<State>,
surface_target: WaylandSurfaceTarget,
@@ -139,6 +148,127 @@ impl WaylandWindow {
Ok(())
}
pub fn dispatch_pending(&mut self) -> Result<usize, Box<dyn Error>> {
let dispatched = self.event_queue.dispatch_pending(&mut self.state)?;
self.event_queue.flush()?;
Ok(dispatched)
}
pub fn wait_for_events(&mut self, timeout: Duration) -> Result<usize, Box<dyn Error>> {
Ok(self.wait_for_events_or_fd(None, timeout)?.dispatched)
}
pub fn poll_fd(&self) -> i32 {
self.state._connection.as_fd().as_raw_fd()
}
pub fn dispatch_ready(&mut self) -> Result<usize, Box<dyn Error>> {
self.event_queue.flush()?;
let dispatched = self.event_queue.dispatch_pending(&mut self.state)?;
if dispatched > 0 {
return Ok(dispatched);
}
let Some(read_guard) = self.event_queue.prepare_read() else {
return Ok(self.event_queue.dispatch_pending(&mut self.state)?);
};
match read_guard.read() {
Ok(_) => {}
Err(wayland_client::backend::WaylandError::Io(e))
if e.kind() == ErrorKind::WouldBlock =>
{
return Ok(0);
}
Err(error) => return Err(Box::new(error)),
}
Ok(self.event_queue.dispatch_pending(&mut self.state)?)
}
pub fn wait_for_events_or_fd(
&mut self,
external_fd: Option<i32>,
timeout: Duration,
) -> Result<WaitOutcome, Box<dyn Error>> {
self.event_queue.flush()?;
let dispatched = self.event_queue.dispatch_pending(&mut self.state)?;
if dispatched > 0 {
return Ok(WaitOutcome {
dispatched,
external_ready: false,
});
}
let Some(read_guard) = self.event_queue.prepare_read() else {
return Ok(WaitOutcome {
dispatched: self.event_queue.dispatch_pending(&mut self.state)?,
external_ready: false,
});
};
let fd = read_guard.connection_fd();
let mut pollfds = [
libc::pollfd {
fd: fd.as_raw_fd(),
events: libc::POLLIN | libc::POLLERR,
revents: 0,
},
libc::pollfd {
fd: external_fd.unwrap_or(-1),
events: libc::POLLIN | libc::POLLERR,
revents: 0,
},
];
let pollfd_count = if external_fd.is_some() { 2 } else { 1 };
let timeout_ms = timeout.as_millis().min(i32::MAX as u128) as i32;
let ready = loop {
let ready = unsafe { libc::poll(pollfds.as_mut_ptr(), pollfd_count, timeout_ms) };
if ready >= 0 {
break ready;
}
let error = std::io::Error::last_os_error();
if error.kind() == ErrorKind::Interrupted {
continue;
}
return Err(Box::new(error));
};
if ready == 0 {
drop(read_guard);
return Ok(WaitOutcome::default());
}
let external_ready =
external_fd.is_some() && (pollfds[1].revents & (libc::POLLIN | libc::POLLERR)) != 0;
let wayland_ready = (pollfds[0].revents & (libc::POLLIN | libc::POLLERR)) != 0;
if !wayland_ready {
drop(read_guard);
return Ok(WaitOutcome {
dispatched: 0,
external_ready,
});
}
match read_guard.read() {
Ok(_) => {}
Err(wayland_client::backend::WaylandError::Io(e))
if e.kind() == ErrorKind::WouldBlock =>
{
return Ok(WaitOutcome {
dispatched: 0,
external_ready,
});
}
Err(error) => return Err(Box::new(error)),
}
Ok(WaitOutcome {
dispatched: self.event_queue.dispatch_pending(&mut self.state)?,
external_ready,
})
}
pub fn request_redraw(&mut self) {
self.state.request_redraw();
}