diff --git a/Cargo.toml b/Cargo.toml index 7cb22471d..e3604898c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,12 +23,18 @@ lazy_static = "1.0" memmap2 = "0.5.0" log = "0.4" thiserror = "1.0.30" -wayland-backend = "=0.1.0-beta.14" -wayland-client = "=0.30.0-beta.14" -wayland-protocols = { version = "=0.30.0-beta.14", features = ["client", "unstable"] } -wayland-protocols-wlr = { version = "=0.1.0-beta.14", features = ["client"] } -wayland-cursor = "=0.30.0-beta.14" -wayland-scanner = "=0.30.0-beta.14" +# wayland-backend = "=0.1.0-beta.14" +# wayland-client = "=0.30.0-beta.14" +# wayland-protocols = { version = "=0.30.0-beta.14", features = ["client", "unstable"] } +# wayland-protocols-wlr = { version = "=0.1.0-beta.14", features = ["client"] } +# wayland-cursor = "=0.30.0-beta.14" +# wayland-scanner = "=0.30.0-beta.14" +wayland-backend = { git = "https://github.com/ids1024/wayland-rs", branch = "ext-screencopy" } +wayland-client = { git = "https://github.com/ids1024/wayland-rs", branch = "ext-screencopy" } +wayland-protocols = { git = "https://github.com/ids1024/wayland-rs", branch = "ext-screencopy", features = ["client", "staging", "unstable"] } +wayland-protocols-wlr = { git = "https://github.com/ids1024/wayland-rs", branch = "ext-screencopy", features = ["client"] } +wayland-cursor = { git = "https://github.com/ids1024/wayland-rs", branch = "ext-screencopy" } +wayland-scanner = { git = "https://github.com/ids1024/wayland-rs", branch = "ext-screencopy" } xkbcommon = { version = "0.5", optional = true, features = ["wayland"] } calloop = { version = "0.10.0", optional = true } diff --git a/src/lib.rs b/src/lib.rs index 1dfedc4d6..b5e09e02a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -22,6 +22,7 @@ pub mod event_loop; pub mod globals; pub mod output; pub mod registry; +pub mod screencopy; pub mod seat; pub mod shell; pub mod shm; diff --git a/src/screencopy.rs b/src/screencopy.rs new file mode 100644 index 000000000..73effc4e5 --- /dev/null +++ b/src/screencopy.rs @@ -0,0 +1,223 @@ +// TODO: Cursor session +// TODO: wrapper around a session + +use crate::registry::GlobalProxy; + +use std::sync::Mutex; +use wayland_client::protocol::wl_shm; +use wayland_client::{globals::GlobalList, Connection, Dispatch, QueueHandle, WEnum}; +use wayland_protocols::ext::{ + image_source::v1::client::{ext_image_source_manager_v1, ext_image_source_v1}, + screencopy::v1::client::{ext_screencopy_manager_v1, ext_screencopy_session_v1}, +}; + +#[derive(Clone, Debug)] +pub struct BufferConstraintsShm { + pub format: WEnum, + pub min_width: u32, + pub min_height: u32, + pub optimal_stride: u32, +} + +#[derive(Clone, Debug)] +pub struct BufferConstraintsDmabuf { + pub format: u32, + pub min_width: u32, + pub min_height: u32, +} + +#[derive(Debug)] +pub struct ScreencopyState { + pub screencopy_manager: GlobalProxy, // XXX pub +} + +impl ScreencopyState { + pub fn new(globals: &GlobalList, qh: &QueueHandle) -> Self + where + D: Dispatch + 'static, + { + let screencopy_manager = GlobalProxy::from(globals.bind(qh, 1..=1, ())); + Self { screencopy_manager } + } +} + +pub trait ScreencopyHandler: Sized { + fn screencopy_state(&mut self) -> &mut ScreencopyState; + + fn buffer_constraints( + &mut self, + conn: &Connection, + qh: &QueueHandle, + session: &ext_screencopy_session_v1::ExtScreencopySessionV1, + shm_constraints: &[BufferConstraintsShm], + dmabuf_constraints: &[BufferConstraintsDmabuf], + ); + + // needs to take transform, damage, presentatation_time + fn ready( + &mut self, + conn: &Connection, + qh: &QueueHandle, + session: &ext_screencopy_session_v1::ExtScreencopySessionV1, + ); + + fn failed( + &mut self, + conn: &Connection, + qh: &QueueHandle, + session: &ext_screencopy_session_v1::ExtScreencopySessionV1, + reason: WEnum, + ); +} + +#[derive(Default)] +pub struct ScreencopySessionData { + shm_constraints: Mutex>, + dmabuf_constraints: Mutex>, +} + +impl Dispatch for ScreencopyState +where + D: Dispatch + ScreencopyHandler, +{ + fn event( + state: &mut D, + _: &ext_image_source_v1::ExtImageSourceV1, + event: ext_image_source_v1::Event, + _: &(), + _: &Connection, + _: &QueueHandle, + ) { + match event { + _ => unreachable!(), + } + } +} + +impl Dispatch for ScreencopyState +where + D: Dispatch + ScreencopyHandler, +{ + fn event( + state: &mut D, + _: &ext_image_source_manager_v1::ExtImageSourceManagerV1, + event: ext_image_source_manager_v1::Event, + _: &(), + _: &Connection, + _: &QueueHandle, + ) { + match event { + _ => unreachable!(), + } + } +} + +impl Dispatch for ScreencopyState +where + D: Dispatch + ScreencopyHandler, +{ + fn event( + state: &mut D, + _: &ext_screencopy_manager_v1::ExtScreencopyManagerV1, + event: ext_screencopy_manager_v1::Event, + _: &(), + _: &Connection, + _: &QueueHandle, + ) { + match event { + _ => unreachable!(), + } + } +} + +impl Dispatch + for ScreencopyState +where + D: Dispatch + + ScreencopyHandler, +{ + fn event( + app_data: &mut D, + session: &ext_screencopy_session_v1::ExtScreencopySessionV1, + event: ext_screencopy_session_v1::Event, + data: &ScreencopySessionData, + conn: &Connection, + qh: &QueueHandle, + ) { + //println!("{:?}", event); + match event { + ext_screencopy_session_v1::Event::BufferConstraintsShm { + format, + min_width, + min_height, + optimal_stride, + } => { + let constraints = + BufferConstraintsShm { format, min_width, min_height, optimal_stride }; + data.shm_constraints.lock().unwrap().push(constraints); + } + + ext_screencopy_session_v1::Event::BufferConstraintsDmabuf { + format, + min_width, + min_height, + } => { + let constraints = BufferConstraintsDmabuf { format, min_width, min_height }; + data.dmabuf_constraints.lock().unwrap().push(constraints); + } + + ext_screencopy_session_v1::Event::BufferConstraintsDone => { + let shm_constraints = data.shm_constraints.lock().unwrap(); + let dmabuf_constraints = data.dmabuf_constraints.lock().unwrap(); + app_data.buffer_constraints( + conn, + qh, + session, + &*shm_constraints, + &*dmabuf_constraints, + ); + } + + ext_screencopy_session_v1::Event::Transform { transform } => {} + + ext_screencopy_session_v1::Event::Damage { x, y, width, height } => {} + + ext_screencopy_session_v1::Event::Failed { reason } => { + app_data.failed(conn, qh, session, reason); + } + + ext_screencopy_session_v1::Event::PresentationTime { + tv_sec_hi, + tv_sec_lo, + tv_nsec, + } => { + let secs = (u64::from(tv_sec_hi) << 32) + u64::from(tv_sec_lo); + // TODO + } + + ext_screencopy_session_v1::Event::Ready => { + app_data.ready(conn, qh, session); // pass other info? + } + + _ => unreachable!(), + } + } +} + +#[macro_export] +macro_rules! delegate_screencopy { + ($ty: ty) => { + $crate::wayland_client::delegate_dispatch!($ty: [ + $crate::cosmic_protocols::image_source::v1::client::ext_image_source_manager_v1::ExtImageSourceManagerV1: () + ] => $crate::screencopy::ScreencopyState); + $crate::wayland_client::delegate_dispatch!($ty: [ + $crate::cosmic_protocols::image_source::v1::client::ext_image_source_v1::ExtImageSourceV1: () + ] => $crate::screencopy::ScreencopyState); + $crate::wayland_client::delegate_dispatch!($ty: [ + $crate::cosmic_protocols::screencopy::v1::client::ext_screencopy_manager_v1::ExtScreencopyManagerV1: () + ] => $crate::screencopy::ScreencopyState); + $crate::wayland_client::delegate_dispatch!($ty: [ + $crate::cosmic_protocols::screencopy::v1::client::ext_screencopy_session_v1::ExtScreencopySessionV1: $crate::screencopy::ScreencopySessionData + ] => $crate::screencopy::ScreencopyState); + }; +}