Ported example 5

This commit is contained in:
2026-03-22 02:30:11 -04:00
parent 0d73e43a92
commit cf53a9f86d
5 changed files with 815 additions and 38 deletions

View File

@@ -666,6 +666,11 @@ impl WaylandWindow {
self.state.frame_callback = None;
}
fn flush_connection(&mut self) -> Result<(), Box<dyn Error>> {
self.state._connection.flush()?;
Ok(())
}
pub fn apply_spec(&mut self, spec: &WindowSpec) -> Result<(), Box<dyn Error>> {
self.state._toplevel.set_title(spec.title.clone());
if let Some(app_id) = spec.app_id.as_ref() {
@@ -1194,12 +1199,8 @@ fn pump_window_worker(state: Rc<RefCell<WindowWorkerState>>) {
let mut reschedule = true;
{
let mut state_ref = state.borrow_mut();
if state_ref.shutdown_requested
|| state_ref
.window
.wait_for_events(Duration::from_millis(16))
.is_err()
{
let wait_result = state_ref.window.wait_for_events(Duration::from_millis(16));
if state_ref.shutdown_requested || wait_result.is_err() {
emit_window_closed(&mut state_ref, false);
reschedule = false;
} else {
@@ -1261,6 +1262,7 @@ fn pump_window_worker(state: Rc<RefCell<WindowWorkerState>>) {
let scene = state_ref.latest_scene.clone();
if let Some(scene) = scene.as_ref() {
if !state_ref.window.presentation_ready() {
state_ref.window.request_redraw();
// Wait for the compositor frame callback before attempting another present.
} else if scene.logical_size != current_viewport {
debug!(
@@ -1278,20 +1280,37 @@ fn pump_window_worker(state: Rc<RefCell<WindowWorkerState>>) {
preview_scene.logical_size = current_viewport;
state_ref.window.arm_frame_callback();
if state_ref.renderer.render(&preview_scene).is_ok() {
trace!(
target: "ruin_ui_platform_wayland::scene",
window_id = state_ref.window_id.raw(),
scene_version = scene.version,
width = current_viewport.width,
height = current_viewport.height,
"presented scaled preview scene for current viewport"
);
let _ = state_ref.event_tx.send(PlatformEvent::FramePresented {
window_id: state_ref.window_id,
scene_version: scene.version,
item_count: scene.item_count(),
});
finish_presented_viewport_request(&mut state_ref, scene.logical_size);
match state_ref.window.flush_connection() {
Ok(()) => {
trace!(
target: "ruin_ui_platform_wayland::scene",
window_id = state_ref.window_id.raw(),
scene_version = scene.version,
width = current_viewport.width,
height = current_viewport.height,
"presented scaled preview scene for current viewport"
);
let _ = state_ref.event_tx.send(PlatformEvent::FramePresented {
window_id: state_ref.window_id,
scene_version: scene.version,
item_count: scene.item_count(),
});
finish_presented_viewport_request(
&mut state_ref,
scene.logical_size,
);
}
Err(error) => {
debug!(
target: "ruin_ui_platform_wayland::scene",
window_id = state_ref.window_id.raw(),
error = %error,
"failed to flush presented preview scene"
);
state_ref.window.clear_frame_callback();
state_ref.window.request_redraw();
}
}
} else {
state_ref.window.clear_frame_callback();
}
@@ -1299,23 +1318,38 @@ fn pump_window_worker(state: Rc<RefCell<WindowWorkerState>>) {
state_ref.window.arm_frame_callback();
match state_ref.renderer.render(scene) {
Ok(()) => {
trace!(
target: "ruin_ui_platform_wayland::scene",
window_id = state_ref.window_id.raw(),
scene_version = scene.version,
width = scene.logical_size.width,
height = scene.logical_size.height,
"presented matching scene"
);
finish_presented_viewport_request(
&mut state_ref,
scene.logical_size,
);
let _ = state_ref.event_tx.send(PlatformEvent::FramePresented {
window_id: state_ref.window_id,
scene_version: scene.version,
item_count: scene.item_count(),
});
match state_ref.window.flush_connection() {
Ok(()) => {
trace!(
target: "ruin_ui_platform_wayland::scene",
window_id = state_ref.window_id.raw(),
scene_version = scene.version,
width = scene.logical_size.width,
height = scene.logical_size.height,
"presented matching scene"
);
finish_presented_viewport_request(
&mut state_ref,
scene.logical_size,
);
let _ =
state_ref.event_tx.send(PlatformEvent::FramePresented {
window_id: state_ref.window_id,
scene_version: scene.version,
item_count: scene.item_count(),
});
}
Err(error) => {
debug!(
target: "ruin_ui_platform_wayland::scene",
window_id = state_ref.window_id.raw(),
error = %error,
"failed to flush presented scene"
);
state_ref.window.clear_frame_callback();
state_ref.window.request_redraw();
}
}
}
Err(RenderError::Lost | RenderError::Outdated) => {
state_ref.window.clear_frame_callback();