diff --git a/tiny_skia/src/window/compositor.rs b/tiny_skia/src/window/compositor.rs index e5303567..b841c242 100644 --- a/tiny_skia/src/window/compositor.rs +++ b/tiny_skia/src/window/compositor.rs @@ -186,7 +186,6 @@ pub fn present( }) .unwrap_or_else(|| vec![Rectangle::with_size(viewport.logical_size())]); - /// XXX winit shell does not handle skipped present well. if damage.is_empty() { if let Some(last_layers) = last_layers { surface.layer_stack.push_front(last_layers.clone()); diff --git a/winit/src/lib.rs b/winit/src/lib.rs index 1243376c..1a50505b 100644 --- a/winit/src/lib.rs +++ b/winit/src/lib.rs @@ -70,6 +70,7 @@ use crate::runtime::image; use crate::runtime::system; use crate::runtime::user_interface::{self, UserInterface}; use crate::runtime::{Action, Task}; +use crate::subsurface_widget::is_subsurface; use program::Program; use window::WindowManager; @@ -77,7 +78,6 @@ use window::WindowManager; use rustc_hash::FxHashMap; use std::borrow::Cow; use std::mem::ManuallyDrop; -use std::ops::ControlFlow; use std::slice; use std::sync::Arc; @@ -254,6 +254,29 @@ where | winit::event::WindowEvent::Moved(_) ); + #[cfg(feature = "wayland")] + { + if matches!(event, WindowEvent::RedrawRequested) { + for id in + crate::subsurface_widget::subsurface_ids(window_id) + { + _ = self.sender.start_send(Event::Winit( + id, + WindowEvent::RedrawRequested, + )); + } + } else if matches!(event, WindowEvent::CloseRequested) { + for id in + crate::subsurface_widget::subsurface_ids(window_id) + { + _ = self.sender.start_send(Event::Winit( + id, + WindowEvent::CloseRequested, + )); + } + } + } + self.process_event( event_loop, Some(Event::Winit(window_id, event)), @@ -531,6 +554,32 @@ where .expect("Send event"); } Control::Winit(id, e) => { + #[cfg(feature = "wayland")] + { + if matches!(e, WindowEvent::RedrawRequested) + { + + for id in crate::subsurface_widget::subsurface_ids(id) { + _ = self.sender + .unbounded_send(Event::Winit( + id, + WindowEvent::RedrawRequested, + )); + } + } else if matches!( + e, + WindowEvent::CloseRequested + ) { + for id in crate::subsurface_widget::subsurface_ids(id) { + _ = self.sender + .start_send(Event::Winit( + id, + WindowEvent::CloseRequested, + )); + } + } + } + self.sender .start_send(Event::Winit(id, e)) .expect("Send event"); @@ -759,8 +808,8 @@ async fn run_instance

( 'next_event: loop { // Empty the queue if possible - let event = if let Ok(event) = event_receiver.try_next() { - event + let event = if let Ok(event) = event_receiver.try_recv() { + Some(event) } else { event_receiver.next().await }; @@ -950,13 +999,16 @@ async fn run_instance

( else { continue; }; + window.redraw_requested = false; + if !window.state.ready { continue; } // XX must force update to corner radius before the surface is committed. #[cfg(feature = "wayland")] - if window.surface_version != window.state.surface_version() + if (window.surface_version != window.state.surface_version() || window.logical_size() != window.state.logical_size() + ) && !is_subsurface(window_id) { platform_specific_handler.send_wayland( platform_specific::Action::ResizeWindow(id), @@ -1295,8 +1347,6 @@ async fn run_instance

( let skip = events.is_empty() && messages.is_empty(); if skip && window_manager.is_idle() { - _ = control_sender - .start_send(Control::ChangeFlow(ControlFlow::Wait)); continue; } @@ -1416,18 +1466,6 @@ async fn run_instance

( } for (id, event) in events.drain(..) { - if id.is_none() - && matches!( - event, - core::Event::Keyboard(_) - | core::Event::Touch(_) - | core::Event::Mouse(_) - ) - { - _ = control_sender - .start_send(Control::ChangeFlow(ControlFlow::Wait)); - continue; - } runtime.broadcast(subscription::Event::Interaction { window: id.unwrap_or(window::Id::NONE), event, @@ -1484,6 +1522,14 @@ async fn run_instance

( } } + for (_id, window) in window_manager.iter_mut() { + if let Some(redraw_at) = window.redraw_at + && redraw_at <= Instant::now() + { + window.raw.request_redraw(); + window.redraw_at = None; + } + } if let Some(redraw_at) = window_manager.redraw_at() { let _ = control_sender.start_send(Control::ChangeFlow( ControlFlow::WaitUntil(redraw_at), diff --git a/winit/src/platform_specific/wayland/event_loop/state.rs b/winit/src/platform_specific/wayland/event_loop/state.rs index 69113743..51ab8d90 100644 --- a/winit/src/platform_specific/wayland/event_loop/state.rs +++ b/winit/src/platform_specific/wayland/event_loop/state.rs @@ -206,6 +206,7 @@ pub enum CommonSurface { Layer(LayerSurface), Lock(SessionLockSurface), Subsurface { + parent: WlSurface, wl_surface: WlSurface, wl_subsurface: WlSubsurface, }, @@ -1821,6 +1822,7 @@ impl SctkState { parent.wl_surface().clone(), wl_surface.clone(), CommonSurface::Subsurface { + parent: parent.wl_surface().clone(), wl_surface, wl_subsurface, }, diff --git a/winit/src/platform_specific/wayland/handlers/compositor.rs b/winit/src/platform_specific/wayland/handlers/compositor.rs index 92b5c773..422a561d 100644 --- a/winit/src/platform_specific/wayland/handlers/compositor.rs +++ b/winit/src/platform_specific/wayland/handlers/compositor.rs @@ -3,8 +3,8 @@ use cctk::sctk::{ compositor::CompositorHandler, delegate_compositor, reexports::client::{ + Connection, QueueHandle, protocol::{wl_output, wl_surface}, - Connection, Proxy, QueueHandle, }, }; diff --git a/winit/src/platform_specific/wayland/sctk_event.rs b/winit/src/platform_specific/wayland/sctk_event.rs index fa512bf3..1e621451 100755 --- a/winit/src/platform_specific/wayland/sctk_event.rs +++ b/winit/src/platform_specific/wayland/sctk_event.rs @@ -1498,6 +1498,7 @@ impl SctkEvent { display, } => { let CommonSurface::Subsurface { + parent: _, wl_surface, wl_subsurface, } = &common_surface @@ -1515,7 +1516,7 @@ impl SctkEvent { )); } - let wrapper = SurfaceIdWrapper::Popup(surface_id); + let wrapper = SurfaceIdWrapper::Subsurface(surface_id); _ = surface_ids.insert(wl_surface.id(), wrapper.clone()); let sctk_winit = SctkWinitWindow::new( sctk_tx.clone(), @@ -1542,10 +1543,25 @@ impl SctkEvent { }, ); } - let Some(compositor) = compositor.as_mut() else { - log::error!("compositor missing"); - return; - }; + if compositor.is_none() { + match create_compositor( + sctk_winit.clone(), + create_compositor_data, + ) + .await + { + Ok(c) => *compositor = Some(c), + Err(error) => { + control_sender + .start_send(Control::Crash( + Error::GraphicsCreationFailed(error), + )) + .expect("Send control message"); + return; + } + }; + } + let compositor = compositor.as_mut().unwrap(); let window = window_manager.insert( surface_id, diff --git a/winit/src/platform_specific/wayland/subsurface_widget.rs b/winit/src/platform_specific/wayland/subsurface_widget.rs index b082bf3b..ed53d9ea 100644 --- a/winit/src/platform_specific/wayland/subsurface_widget.rs +++ b/winit/src/platform_specific/wayland/subsurface_widget.rs @@ -747,6 +747,14 @@ pub(crate) fn take_subsurfaces() -> Vec { SUBSURFACES.with(|subsurfaces| mem::take(&mut *subsurfaces.borrow_mut())) } +pub(crate) fn is_subsurface(id: WindowId) -> bool { + ICED_SUBSURFACES.with(|subsurfaces| { + subsurfaces.borrow_mut().iter().any(|s| { + winit::window::WindowId::from_raw(s.4.id().as_ptr() as usize) == id + }) + }) +} + pub(crate) fn subsurface_ids(parent: WindowId) -> Vec { ICED_SUBSURFACES.with(|subsurfaces| { subsurfaces diff --git a/winit/src/platform_specific/wayland/winit_window.rs b/winit/src/platform_specific/wayland/winit_window.rs index 3061e709..a63e00b7 100644 --- a/winit/src/platform_specific/wayland/winit_window.rs +++ b/winit/src/platform_specific/wayland/winit_window.rs @@ -67,7 +67,11 @@ impl winit::window::Window for SctkWinitWindow { } fn request_redraw(&self) { + if let CommonSurface::Subsurface { parent, .. } = &self.surface { + _ = self.tx.send(Action::RequestRedraw(parent.id())); + } let surface = self.surface.wl_surface(); + _ = self.tx.send(Action::RequestRedraw(surface.id())); }