winit/wayland: Subsurfaces for drag surfaces

Use `Icon::Surface` instead of `Icon::Buffer`, so we can then create
subsurfaces of the `wl_surface`.

Using `.screenshot()` then copying to an shm buffer is suboptimal, but
this does seem overall better than with the older Iced version when a
drag surface didn't appear until a Vulkan surface could be created for
it.

This re-uses `Connection` in the platform-specific code, instead of
creating from display handle on each call.
This commit is contained in:
Ian Douglas Scott 2024-12-17 15:13:24 -08:00 committed by Ashley Wulber
parent 545ecb8a8a
commit fde0689def
No known key found for this signature in database
GPG key ID: 5216D4F46A90A820
6 changed files with 190 additions and 26 deletions

View file

@ -7,6 +7,7 @@ use std::collections::HashMap;
use cctk::sctk::reexports::client::Connection;
use iced_graphics::{Compositor, compositor};
use iced_runtime::{core::window, platform_specific, user_interface};
use raw_window_handle::HasWindowHandle;
#[cfg(all(feature = "wayland", target_os = "linux"))]
pub mod wayland;
@ -82,7 +83,7 @@ impl PlatformSpecific {
pub(crate) fn update_subsurfaces(
&mut self,
id: window::Id,
window: &dyn winit::window::Window,
window: &dyn HasWindowHandle,
) {
#[cfg(all(feature = "wayland", target_os = "linux"))]
{
@ -91,31 +92,12 @@ impl PlatformSpecific {
};
use wayland_backend::client::ObjectId;
let Ok(backend) = window.rwh_06_display_handle().display_handle()
else {
log::error!("No display handle");
let Some(conn) = self.wayland.conn() else {
log::error!("No Wayland conn");
return;
};
let conn = match backend.as_raw() {
raw_window_handle::RawDisplayHandle::Wayland(
wayland_display_handle,
) => {
let backend = unsafe {
Backend::from_foreign_display(
wayland_display_handle.display.as_ptr().cast(),
)
};
cctk::sctk::reexports::client::Connection::from_backend(
backend,
)
}
_ => {
return;
}
};
let Ok(raw) = window.rwh_06_window_handle().window_handle() else {
let Ok(raw) = window.window_handle() else {
log::error!("Invalid window handle {id:?}");
return;
};
@ -150,6 +132,31 @@ impl PlatformSpecific {
self.wayland.update_subsurfaces(id, &wl_surface);
}
}
pub(crate) fn create_surface(
&mut self,
) -> Option<Box<dyn HasWindowHandle + Send + Sync + 'static>> {
#[cfg(all(feature = "wayland", target_os = "linux"))]
{
return self.wayland.create_surface();
}
None
}
pub(crate) fn update_surface_shm(
&mut self,
surface: &dyn HasWindowHandle,
width: u32,
height: u32,
data: &[u8],
) {
#[cfg(all(feature = "wayland", target_os = "linux"))]
{
return self
.wayland
.update_surface_shm(surface, width, height, data);
}
}
}
pub(crate) fn handle_event<'a, P>(