refactor: event loop clarity and correctness

This commit is contained in:
drendog 2025-10-25 20:33:10 +02:00
parent 6a72d83d0f
commit db46d7ce8a
Signed by: dwenya
GPG key ID: 8DD77074645332D0

View file

@ -63,7 +63,8 @@ impl WindowingSystem {
let pointer = Rc::new(global_ctx.seat.get_pointer(&event_queue.handle(), ())); let pointer = Rc::new(global_ctx.seat.get_pointer(&event_queue.handle(), ()));
let output = Rc::new(global_ctx.output); let output = Rc::new(global_ctx.output);
let window = Self::initialize_renderer(&surface_ctx.surface, &connection.display(), &config) let window =
Self::initialize_renderer(&surface_ctx.surface, &connection.display(), &config)
.map_err(|e| LayerShikaError::EGLContextCreation(e.to_string()))?; .map_err(|e| LayerShikaError::EGLContextCreation(e.to_string()))?;
let mut builder = WindowStateBuilder::new() let mut builder = WindowStateBuilder::new()
@ -132,26 +133,38 @@ impl WindowingSystem {
pub fn run(&mut self) -> Result<()> { pub fn run(&mut self) -> Result<()> {
info!("Starting WindowingSystem main loop"); info!("Starting WindowingSystem main loop");
// Process all initial configuration events by repeatedly dispatching until queue is empty.
// After each batch, flush and render to allow compositor to respond with additional
// configure events (e.g., after fractional scale is applied).
// This ensures proper initialization.
info!("Processing initial Wayland configuration events");
while self while self
.event_queue .event_queue
.blocking_dispatch(&mut self.state) .blocking_dispatch(&mut self.state)
.map_err(|e| LayerShikaError::WaylandProtocol(e.to_string()))? .map_err(|e| LayerShikaError::WaylandProtocol(e.to_string()))?
> 0 > 0
{ {
// Flush requests to compositor after processing each event batch
self.connection self.connection
.flush() .flush()
.map_err(|e| LayerShikaError::WaylandProtocol(e.to_string()))?; .map_err(|e| LayerShikaError::WaylandProtocol(e.to_string()))?;
// Render if window was marked dirty by the configure events
update_timers_and_animations();
self.state self.state
.window() .window()
.render_frame_if_dirty() .render_frame_if_dirty()
.map_err(|e| LayerShikaError::Rendering(e.to_string()))?; .map_err(|e| LayerShikaError::Rendering(e.to_string()))?;
} }
// Setup Wayland file descriptor as event source for ongoing events
self.setup_wayland_event_source()?; self.setup_wayland_event_source()?;
let event_queue = &mut self.event_queue; let event_queue = &mut self.event_queue;
let connection = &self.connection; let connection = &self.connection;
// Enter the main event loop with consistent event processing:
// read -> dispatch -> animate -> render -> flush
self.event_loop self.event_loop
.run(None, &mut self.state, move |shared_data| { .run(None, &mut self.state, move |shared_data| {
if let Err(e) = Self::process_events(connection, event_queue, shared_data) { if let Err(e) = Self::process_events(connection, event_queue, shared_data) {
@ -180,24 +193,32 @@ impl WindowingSystem {
event_queue: &mut EventQueue<WindowState>, event_queue: &mut EventQueue<WindowState>,
shared_data: &mut WindowState, shared_data: &mut WindowState,
) -> Result<()> { ) -> Result<()> {
// 1. READ: Read pending events from Wayland socket if available
if let Some(guard) = event_queue.prepare_read() { if let Some(guard) = event_queue.prepare_read() {
guard guard
.read() .read()
.map_err(|e| LayerShikaError::WaylandProtocol(e.to_string()))?; .map_err(|e| LayerShikaError::WaylandProtocol(e.to_string()))?;
} }
connection.flush()?;
// 2. DISPATCH: Process all queued Wayland events
event_queue event_queue
.dispatch_pending(shared_data) .dispatch_pending(shared_data)
.map_err(|e| LayerShikaError::WaylandProtocol(e.to_string()))?; .map_err(|e| LayerShikaError::WaylandProtocol(e.to_string()))?;
// 3. ANIMATE: Update Slint timers and animations
update_timers_and_animations(); update_timers_and_animations();
// 4. RENDER: Render frame if window was marked dirty
shared_data shared_data
.window() .window()
.render_frame_if_dirty() .render_frame_if_dirty()
.map_err(|e| LayerShikaError::Rendering(e.to_string()))?; .map_err(|e| LayerShikaError::Rendering(e.to_string()))?;
// 5. FLUSH: Send buffered Wayland requests to compositor
connection
.flush()
.map_err(|e| LayerShikaError::WaylandProtocol(e.to_string()))?;
Ok(()) Ok(())
} }