Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Subsurfaces for drag surfaces #205

Merged
merged 2 commits into from
Jan 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ wasm-timer = "0.2"
web-time = "1.1"
wgpu = "22.0"
wayland-protocols = { version = "0.32.1", features = ["staging"] }
wayland-client = { version = "0.31.5" }
# web-time = "1.1"


Expand All @@ -222,9 +223,9 @@ wayland-protocols = { version = "0.32.1", features = ["staging"] }
winapi = "0.3"
# window_clipboard = "0.4.1"

window_clipboard = { git = "https://github.com/pop-os/window_clipboard.git", tag = "pop-0.13" }
dnd = { git = "https://github.com/pop-os/window_clipboard.git", tag = "pop-0.13" }
mime = { git = "https://github.com/pop-os/window_clipboard.git", tag = "pop-0.13" }
window_clipboard = { git = "https://github.com/pop-os/window_clipboard.git", tag = "pop-0.13-2" }
dnd = { git = "https://github.com/pop-os/window_clipboard.git", tag = "pop-0.13-2" }
mime = { git = "https://github.com/pop-os/window_clipboard.git", tag = "pop-0.13-2" }
winit = { git = "https://github.com/pop-os/winit.git", tag = "iced-xdg-surface-0.13" }
# winit = { path = "../../winit" }
# winit = { git = "https://github.com/iced-rs/winit.git", rev = "254d6b3420ce4e674f516f7a2bd440665e05484d" }
Expand Down
2 changes: 2 additions & 0 deletions winit/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,14 @@ cctk.workspace = true
cctk.optional = true
wayland-protocols.workspace = true
wayland-protocols.optional = true
wayland-client.workspace = true
wayland-backend = { version = "0.3.1", features = [
"client_system",
], optional = true }
xkbcommon = { version = "0.7", features = ["wayland"], optional = true }
xkbcommon-dl = { version = "0.4.1", optional = true }
xkeysym = { version = "0.2.0", optional = true }
rustix = { version = "0.38" }

[target.'cfg(target_os = "windows")'.dependencies]
winapi.workspace = true
Expand Down
43 changes: 20 additions & 23 deletions winit/src/platform_specific/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

use iced_graphics::Compositor;
use iced_runtime::{core::window, user_interface, Debug};
use raw_window_handle::HasWindowHandle;

Check failure on line 8 in winit/src/platform_specific/mod.rs

View workflow job for this annotation

GitHub Actions / web

unresolved import `raw_window_handle`

Check failure on line 8 in winit/src/platform_specific/mod.rs

View workflow job for this annotation

GitHub Actions / wasm

unresolved import `raw_window_handle`

Check failure on line 8 in winit/src/platform_specific/mod.rs

View workflow job for this annotation

GitHub Actions / wasm

unresolved import `raw_window_handle`

Check failure on line 8 in winit/src/platform_specific/mod.rs

View workflow job for this annotation

GitHub Actions / web

unresolved import `raw_window_handle`

#[cfg(all(feature = "wayland", target_os = "linux"))]
pub mod wayland;
Expand Down Expand Up @@ -69,7 +70,7 @@
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"))]
{
Expand All @@ -78,31 +79,12 @@
};
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;
};
Expand Down Expand Up @@ -137,6 +119,21 @@
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 type UserInterfaces<'a, P> = HashMap<
Expand Down
72 changes: 70 additions & 2 deletions winit/src/platform_specific/wayland/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,13 @@ use iced_futures::futures::channel::mpsc;
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::{Connection, Proxy};
use winit::event_loop::OwnedDisplayHandle;
use winit::window::CursorIcon;

Expand Down Expand Up @@ -60,9 +63,9 @@ 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>,
subsurface_state: Option<SubsurfaceState>,
surface_subsurfaces: HashMap<window::Id, Vec<SubsurfaceInstance>>,
}
Expand All @@ -75,6 +78,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 @@ -112,6 +137,10 @@ impl PlatformSpecific {
}

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

pub(crate) fn handle_event<'a, P, C>(
&mut self,
e: SctkEvent,
Expand All @@ -135,8 +164,8 @@ impl WaylandSpecific {
proxy,
sender,
display_handle,
conn,
surface_ids,
destroyed_surface_ids,
modifiers,
subsurface_state,
surface_subsurfaces,
Expand Down Expand Up @@ -200,4 +229,43 @@ 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();
}
}
48 changes: 47 additions & 1 deletion winit/src/platform_specific/wayland/subsurface_widget.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ use std::{
use crate::futures::futures::channel::oneshot;
use cctk::sctk::{
compositor::SurfaceData,
globals::GlobalData,
error::GlobalError,
globals::{GlobalData, ProvidesBoundGlobal},
shm::slot::SlotPool,
reexports::client::{
delegate_noop,
protocol::{
Expand Down Expand Up @@ -251,6 +253,7 @@ impl PartialEq for SubsurfaceBuffer {
}
}


impl Dispatch<WlShmPool, GlobalData> for SctkState {
fn event(
_: &mut SctkState,
Expand Down Expand Up @@ -288,6 +291,23 @@ impl Dispatch<ZwpLinuxBufferParamsV1, GlobalData> for SctkState {
}
}

impl Dispatch<WlBuffer, GlobalData> for SctkState {
fn event(
_: &mut SctkState,
_: &WlBuffer,
event: wl_buffer::Event,
_: &GlobalData,
_: &Connection,
_: &QueueHandle<SctkState>,
) {
match event {
wl_buffer::Event::Release => {
}
_ => unreachable!(),
}
}
}

impl Dispatch<WlBuffer, BufferData> for SctkState {
fn event(
_: &mut SctkState,
Expand Down Expand Up @@ -325,6 +345,15 @@ impl Hash for WeakBufferSource {
}
}

// Implement `ProvidesBoundGlobal` to use `SlotPool`
struct ShmGlobal<'a>(&'a WlShm);

impl<'a> ProvidesBoundGlobal<WlShm, 1> for ShmGlobal<'a> {
fn bound_global(&self) -> Result<WlShm, GlobalError> {
Ok(self.0.clone())
}
}

// create wl_buffer from BufferSource (avoid create_immed?)
// release
#[derive(Debug, Clone)]
Expand All @@ -342,6 +371,22 @@ pub struct SubsurfaceState {
}

impl SubsurfaceState {
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);
surface.damage_buffer(0, 0, width as i32, height as i32);
buffer.attach_to(&surface);
surface.commit();
}

fn create_subsurface(&self, parent: &WlSurface) -> SubsurfaceInstance {
let wl_surface = self
.wl_compositor
Expand Down Expand Up @@ -572,6 +617,7 @@ impl Drop for SubsurfaceInstance {
}
}

#[derive(Debug)]
pub(crate) struct SubsurfaceInfo {
pub buffer: SubsurfaceBuffer,
pub bounds: Rectangle<f32>,
Expand Down
Loading
Loading