Text, many performance improvements
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user