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:
parent
545ecb8a8a
commit
fde0689def
6 changed files with 190 additions and 26 deletions
|
|
@ -18,10 +18,13 @@ use cursor_icon::CursorIcon;
|
|||
use iced_futures::futures::channel::mpsc;
|
||||
use iced_graphics::{Compositor, compositor};
|
||||
use iced_runtime::core::window;
|
||||
use raw_window_handle::{DisplayHandle, HasDisplayHandle, HasWindowHandle};
|
||||
use raw_window_handle::{HasRawDisplayHandle, RawWindowHandle};
|
||||
use sctk_event::SctkEvent;
|
||||
use std::{collections::HashMap, sync::Arc};
|
||||
use subsurface_widget::{SubsurfaceInstance, SubsurfaceState};
|
||||
use wayland_backend::client::ObjectId;
|
||||
use wayland_client::{Connection, Proxy};
|
||||
use winit::event_loop::OwnedDisplayHandle;
|
||||
|
||||
pub(crate) enum Action {
|
||||
|
|
@ -60,6 +63,7 @@ pub(crate) struct WaylandSpecific {
|
|||
proxy: Option<winit::event_loop::EventLoopProxy>,
|
||||
sender: Option<calloop::channel::Sender<Action>>,
|
||||
display_handle: Option<OwnedDisplayHandle>,
|
||||
conn: Option<Connection>,
|
||||
modifiers: Modifiers,
|
||||
surface_ids: HashMap<ObjectId, SurfaceIdWrapper>,
|
||||
subsurface_state: Option<SubsurfaceState>,
|
||||
|
|
@ -74,6 +78,26 @@ impl PlatformSpecific {
|
|||
display: OwnedDisplayHandle,
|
||||
) -> Self {
|
||||
self.wayland.winit_event_sender = Some(tx);
|
||||
self.wayland.conn = match display.raw_display_handle() {
|
||||
Ok(raw_window_handle::RawDisplayHandle::Wayland(
|
||||
wayland_display_handle,
|
||||
)) => {
|
||||
let backend = unsafe {
|
||||
wayland_backend::client::Backend::from_foreign_display(
|
||||
wayland_display_handle.display.as_ptr().cast(),
|
||||
)
|
||||
};
|
||||
Some(Connection::from_backend(backend))
|
||||
}
|
||||
Ok(_) => {
|
||||
log::error!("Non-Wayland display handle");
|
||||
None
|
||||
}
|
||||
Err(_) => {
|
||||
log::error!("No display handle");
|
||||
None
|
||||
}
|
||||
};
|
||||
self.wayland.display_handle = Some(display);
|
||||
self.wayland.proxy = Some(raw);
|
||||
// TODO remove this
|
||||
|
|
@ -111,6 +135,10 @@ impl PlatformSpecific {
|
|||
}
|
||||
|
||||
impl WaylandSpecific {
|
||||
pub(crate) fn conn(&self) -> Option<&Connection> {
|
||||
self.conn.as_ref()
|
||||
}
|
||||
|
||||
pub(crate) fn handle_event<'a, P>(
|
||||
&mut self,
|
||||
e: SctkEvent,
|
||||
|
|
@ -135,6 +163,7 @@ impl WaylandSpecific {
|
|||
proxy,
|
||||
sender,
|
||||
display_handle,
|
||||
conn,
|
||||
surface_ids,
|
||||
modifiers,
|
||||
subsurface_state,
|
||||
|
|
@ -198,4 +227,70 @@ impl WaylandSpecific {
|
|||
&subsurfaces,
|
||||
);
|
||||
}
|
||||
|
||||
pub(crate) fn create_surface(
|
||||
&mut self,
|
||||
) -> Option<Box<dyn HasWindowHandle + Send + Sync + 'static>> {
|
||||
if let Some(subsurface_state) = self.subsurface_state.as_mut() {
|
||||
let wl_surface = subsurface_state.create_surface();
|
||||
Some(Box::new(Window(wl_surface)))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn update_surface_shm(
|
||||
&mut self,
|
||||
window: &dyn HasWindowHandle,
|
||||
width: u32,
|
||||
height: u32,
|
||||
data: &[u8],
|
||||
) {
|
||||
if let Some(subsurface_state) = self.subsurface_state.as_mut() {
|
||||
if let RawWindowHandle::Wayland(window) =
|
||||
window.window_handle().unwrap().as_raw()
|
||||
{
|
||||
let id = unsafe {
|
||||
ObjectId::from_ptr(
|
||||
WlSurface::interface(),
|
||||
window.surface.as_ptr().cast(),
|
||||
)
|
||||
.unwrap()
|
||||
};
|
||||
let surface =
|
||||
WlSurface::from_id(self.conn.as_ref().unwrap(), id)
|
||||
.unwrap();
|
||||
subsurface_state
|
||||
.update_surface_shm(&surface, width, height, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Window(WlSurface);
|
||||
|
||||
impl HasWindowHandle for Window {
|
||||
fn window_handle(
|
||||
&self,
|
||||
) -> Result<
|
||||
raw_window_handle::WindowHandle<'_>,
|
||||
raw_window_handle::HandleError,
|
||||
> {
|
||||
Ok(unsafe {
|
||||
raw_window_handle::WindowHandle::borrow_raw(
|
||||
raw_window_handle::RawWindowHandle::Wayland(
|
||||
raw_window_handle::WaylandWindowHandle::new(
|
||||
std::ptr::NonNull::new(self.0.id().as_ptr() as *mut _)
|
||||
.unwrap(),
|
||||
),
|
||||
),
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Window {
|
||||
fn drop(&mut self) {
|
||||
self.0.destroy();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue