Skip to content

Commit

Permalink
drag surface subsurface fixes
Browse files Browse the repository at this point in the history
use seperate update_surface_shm to avoid commit on each update to
subsurfaces.

re-use `Connection`.
  • Loading branch information
ids1024 committed Dec 30, 2024
1 parent f9e674f commit 4ed2c07
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 41 deletions.
37 changes: 12 additions & 25 deletions winit/src/platform_specific/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,31 +79,11 @@ impl PlatformSpecific {
};
use wayland_backend::client::ObjectId;

let Some(backend) = self.wayland.display_handle()
else {
log::error!("No display handle");
let Some(conn) = self.wayland.conn() else {
log::error!("No Wayland conn");
return;
};

// TODO use existing conn
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.window_handle() else {
log::error!("Invalid window handle {id:?}");
return;
Expand Down Expand Up @@ -140,13 +120,20 @@ impl PlatformSpecific {
}
}

pub(crate) fn create_surface(&mut self, width: u32, height: u32, data: &[u8]) -> Option<Box<dyn HasWindowHandle + Send + Sync + 'static>> {
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(width, height, data);
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 type UserInterfaces<'a, P> = HashMap<
Expand Down Expand Up @@ -195,4 +182,4 @@ pub(crate) fn handle_event<'a, P, C>(
);
}
}
}
}
52 changes: 43 additions & 9 deletions winit/src/platform_specific/wayland/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,12 @@ use iced_graphics::Compositor;
use iced_runtime::core::window;
use iced_runtime::Debug;
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::Proxy;
use wayland_client::{Connection, Proxy};
use winit::event_loop::OwnedDisplayHandle;
use winit::window::CursorIcon;

Expand Down Expand Up @@ -62,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>,
destroyed_surface_ids: HashMap<ObjectId, SurfaceIdWrapper>,
Expand All @@ -77,6 +79,28 @@ 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
Expand Down Expand Up @@ -114,8 +138,8 @@ impl PlatformSpecific {
}

impl WaylandSpecific {
pub(crate) fn display_handle(&self) -> Option<DisplayHandle> {
self.display_handle.as_ref()?.display_handle().ok()
pub(crate) fn conn(&self) -> Option<&Connection> {
self.conn.as_ref()
}

pub(crate) fn handle_event<'a, P, C>(
Expand All @@ -141,6 +165,7 @@ impl WaylandSpecific {
proxy,
sender,
display_handle,
conn,
surface_ids,
destroyed_surface_ids,
modifiers,
Expand Down Expand Up @@ -205,22 +230,30 @@ impl WaylandSpecific {
surface_subsurfaces,
&subsurfaces,
);

// Yeah, this is necessary for subsurfaces. should use unsync?
wl_surface.commit(); // XXX for drag surface
}

// WIP cfg raw-window-handle
pub(crate) fn create_surface(&mut self, width: u32, height: u32, data: &[u8]) -> Option<Box<dyn HasWindowHandle + Send + Sync + 'static>> {
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(width, height, data);
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 {
Expand All @@ -232,6 +265,7 @@ impl HasWindowHandle for Window {
})
}
}

impl Drop for Window {
fn drop(&mut self) {
self.0.destroy();
Expand Down
13 changes: 7 additions & 6 deletions winit/src/platform_specific/wayland/subsurface_widget.rs
Original file line number Diff line number Diff line change
Expand Up @@ -371,19 +371,20 @@ pub struct SubsurfaceState {
}

impl SubsurfaceState {
pub fn create_surface(&self, width: u32, height: u32, data: &[u8]) -> WlSurface {
pub fn create_surface(&self) -> WlSurface {
self
.wl_compositor
.create_surface(&self.qh, SurfaceData::new(None, 1))
}

pub fn update_surface_shm(&self, surface: &WlSurface, width: u32, height: u32, data: &[u8]) {
let shm = ShmGlobal(&self.wl_shm);
let mut pool = SlotPool::new(width as usize * height as usize * 4, &shm).unwrap();
let (buffer, canvas) = pool.create_buffer(width as i32, height as i32, width as i32 * 4, wl_shm::Format::Argb8888).unwrap();
canvas[0..width as usize * height as usize * 4].copy_from_slice(data);

let surface = self
.wl_compositor
.create_surface(&self.qh, SurfaceData::new(None, 1));
surface.damage_buffer(0, 0, width as i32, height as i32);
buffer.attach_to(&surface);
surface.commit();
surface
}

fn create_subsurface(&self, parent: &WlSurface) -> SubsurfaceInstance {
Expand Down
3 changes: 2 additions & 1 deletion winit/src/program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -978,11 +978,12 @@ async fn run_instance<'a, P, C>(
pix.swap(0, 2);
}
// update subsurfaces
if let Some(surface) = platform_specific_handler.create_surface(viewport.physical_width(), viewport.physical_height(), &bytes) {
if let Some(surface) = platform_specific_handler.create_surface() {
// TODO Remove id
let id = window::Id::unique();
platform_specific_handler
.update_subsurfaces(id, &surface);
platform_specific_handler.update_surface_shm(&surface, viewport.physical_width(), viewport.physical_height(), &bytes);
let surface = Arc::new(surface);
dnd_surface = Some(surface.clone());
Icon::Surface(dnd::DndSurface(surface))
Expand Down

0 comments on commit 4ed2c07

Please sign in to comment.