fix: subsurface improvements

this fixes a couple issues in the greeter
This commit is contained in:
Ashley Wulber 2026-02-27 17:23:10 -05:00
parent 2a680eeb32
commit f7dc180371
No known key found for this signature in database
GPG key ID: 5216D4F46A90A820
7 changed files with 100 additions and 25 deletions

View file

@ -186,7 +186,6 @@ pub fn present(
}) })
.unwrap_or_else(|| vec![Rectangle::with_size(viewport.logical_size())]); .unwrap_or_else(|| vec![Rectangle::with_size(viewport.logical_size())]);
/// XXX winit shell does not handle skipped present well.
if damage.is_empty() { if damage.is_empty() {
if let Some(last_layers) = last_layers { if let Some(last_layers) = last_layers {
surface.layer_stack.push_front(last_layers.clone()); surface.layer_stack.push_front(last_layers.clone());

View file

@ -70,6 +70,7 @@ use crate::runtime::image;
use crate::runtime::system; use crate::runtime::system;
use crate::runtime::user_interface::{self, UserInterface}; use crate::runtime::user_interface::{self, UserInterface};
use crate::runtime::{Action, Task}; use crate::runtime::{Action, Task};
use crate::subsurface_widget::is_subsurface;
use program::Program; use program::Program;
use window::WindowManager; use window::WindowManager;
@ -77,7 +78,6 @@ use window::WindowManager;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use std::borrow::Cow; use std::borrow::Cow;
use std::mem::ManuallyDrop; use std::mem::ManuallyDrop;
use std::ops::ControlFlow;
use std::slice; use std::slice;
use std::sync::Arc; use std::sync::Arc;
@ -254,6 +254,29 @@ where
| winit::event::WindowEvent::Moved(_) | 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( self.process_event(
event_loop, event_loop,
Some(Event::Winit(window_id, event)), Some(Event::Winit(window_id, event)),
@ -531,6 +554,32 @@ where
.expect("Send event"); .expect("Send event");
} }
Control::Winit(id, e) => { 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 self.sender
.start_send(Event::Winit(id, e)) .start_send(Event::Winit(id, e))
.expect("Send event"); .expect("Send event");
@ -759,8 +808,8 @@ async fn run_instance<P>(
'next_event: loop { 'next_event: loop {
// Empty the queue if possible // Empty the queue if possible
let event = if let Ok(event) = event_receiver.try_next() { let event = if let Ok(event) = event_receiver.try_recv() {
event Some(event)
} else { } else {
event_receiver.next().await event_receiver.next().await
}; };
@ -950,13 +999,16 @@ async fn run_instance<P>(
else { else {
continue; continue;
}; };
window.redraw_requested = false;
if !window.state.ready { if !window.state.ready {
continue; continue;
} }
// XX must force update to corner radius before the surface is committed. // XX must force update to corner radius before the surface is committed.
#[cfg(feature = "wayland")] #[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() || window.logical_size() != window.state.logical_size()
) && !is_subsurface(window_id)
{ {
platform_specific_handler.send_wayland( platform_specific_handler.send_wayland(
platform_specific::Action::ResizeWindow(id), platform_specific::Action::ResizeWindow(id),
@ -1295,8 +1347,6 @@ async fn run_instance<P>(
let skip = events.is_empty() && messages.is_empty(); let skip = events.is_empty() && messages.is_empty();
if skip && window_manager.is_idle() { if skip && window_manager.is_idle() {
_ = control_sender
.start_send(Control::ChangeFlow(ControlFlow::Wait));
continue; continue;
} }
@ -1416,18 +1466,6 @@ async fn run_instance<P>(
} }
for (id, event) in events.drain(..) { 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 { runtime.broadcast(subscription::Event::Interaction {
window: id.unwrap_or(window::Id::NONE), window: id.unwrap_or(window::Id::NONE),
event, event,
@ -1484,6 +1522,14 @@ async fn run_instance<P>(
} }
} }
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() { if let Some(redraw_at) = window_manager.redraw_at() {
let _ = control_sender.start_send(Control::ChangeFlow( let _ = control_sender.start_send(Control::ChangeFlow(
ControlFlow::WaitUntil(redraw_at), ControlFlow::WaitUntil(redraw_at),

View file

@ -206,6 +206,7 @@ pub enum CommonSurface {
Layer(LayerSurface), Layer(LayerSurface),
Lock(SessionLockSurface), Lock(SessionLockSurface),
Subsurface { Subsurface {
parent: WlSurface,
wl_surface: WlSurface, wl_surface: WlSurface,
wl_subsurface: WlSubsurface, wl_subsurface: WlSubsurface,
}, },
@ -1821,6 +1822,7 @@ impl SctkState {
parent.wl_surface().clone(), parent.wl_surface().clone(),
wl_surface.clone(), wl_surface.clone(),
CommonSurface::Subsurface { CommonSurface::Subsurface {
parent: parent.wl_surface().clone(),
wl_surface, wl_surface,
wl_subsurface, wl_subsurface,
}, },

View file

@ -3,8 +3,8 @@ use cctk::sctk::{
compositor::CompositorHandler, compositor::CompositorHandler,
delegate_compositor, delegate_compositor,
reexports::client::{ reexports::client::{
Connection, QueueHandle,
protocol::{wl_output, wl_surface}, protocol::{wl_output, wl_surface},
Connection, Proxy, QueueHandle,
}, },
}; };

View file

@ -1498,6 +1498,7 @@ impl SctkEvent {
display, display,
} => { } => {
let CommonSurface::Subsurface { let CommonSurface::Subsurface {
parent: _,
wl_surface, wl_surface,
wl_subsurface, wl_subsurface,
} = &common_surface } = &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()); _ = surface_ids.insert(wl_surface.id(), wrapper.clone());
let sctk_winit = SctkWinitWindow::new( let sctk_winit = SctkWinitWindow::new(
sctk_tx.clone(), sctk_tx.clone(),
@ -1542,10 +1543,25 @@ impl SctkEvent {
}, },
); );
} }
let Some(compositor) = compositor.as_mut() else { if compositor.is_none() {
log::error!("compositor missing"); match create_compositor(
return; 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( let window = window_manager.insert(
surface_id, surface_id,

View file

@ -747,6 +747,14 @@ pub(crate) fn take_subsurfaces() -> Vec<SubsurfaceInfo> {
SUBSURFACES.with(|subsurfaces| mem::take(&mut *subsurfaces.borrow_mut())) 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<WindowId> { pub(crate) fn subsurface_ids(parent: WindowId) -> Vec<WindowId> {
ICED_SUBSURFACES.with(|subsurfaces| { ICED_SUBSURFACES.with(|subsurfaces| {
subsurfaces subsurfaces

View file

@ -67,7 +67,11 @@ impl winit::window::Window for SctkWinitWindow {
} }
fn request_redraw(&self) { fn request_redraw(&self) {
if let CommonSurface::Subsurface { parent, .. } = &self.surface {
_ = self.tx.send(Action::RequestRedraw(parent.id()));
}
let surface = self.surface.wl_surface(); let surface = self.surface.wl_surface();
_ = self.tx.send(Action::RequestRedraw(surface.id())); _ = self.tx.send(Action::RequestRedraw(surface.id()));
} }