From 97f0be27b58bce629802694b64d3620bbd20cdf8 Mon Sep 17 00:00:00 2001 From: Victoria Brekenfeld Date: Mon, 11 Mar 2024 17:53:49 +0100 Subject: [PATCH] protocols: Add cosmic-screencopy-v2 --- client-toolkit/src/lib.rs | 1 - client-toolkit/src/screencopy.rs | 222 --------- src/lib.rs | 17 +- unstable/cosmic-image-source-unstable-v1.xml | 133 ++++++ unstable/cosmic-screencopy-unstable-v2.xml | 446 +++++++++++++++++++ 5 files changed, 594 insertions(+), 225 deletions(-) delete mode 100644 client-toolkit/src/screencopy.rs create mode 100644 unstable/cosmic-image-source-unstable-v1.xml create mode 100644 unstable/cosmic-screencopy-unstable-v2.xml diff --git a/client-toolkit/src/lib.rs b/client-toolkit/src/lib.rs index 769953998b..3747992762 100644 --- a/client-toolkit/src/lib.rs +++ b/client-toolkit/src/lib.rs @@ -6,7 +6,6 @@ pub use wayland_client; pub mod egl; #[cfg(feature = "gl")] pub mod gl; -pub mod screencopy; pub mod toplevel_info; pub mod toplevel_management; pub mod workspace; diff --git a/client-toolkit/src/screencopy.rs b/client-toolkit/src/screencopy.rs deleted file mode 100644 index e96ffbb9f7..0000000000 --- a/client-toolkit/src/screencopy.rs +++ /dev/null @@ -1,222 +0,0 @@ -use cosmic_protocols::screencopy::v1::client::{ - zcosmic_screencopy_manager_v1, zcosmic_screencopy_session_v1, -}; -use std::{sync::Mutex, time::Duration}; -use wayland_client::{ - backend::ObjectId, globals::GlobalList, Connection, Dispatch, Proxy, QueueHandle, WEnum, -}; - -struct Frame { - // transform - // damage - commit_time: Duration, // XXX monotonic? Is this used elsewhere in wayland? -} - -struct CursorInfo {} - -#[derive(Clone, Debug, PartialEq, Eq)] -pub struct BufferInfo { - pub type_: WEnum, - pub node: Option, - pub format: u32, - pub width: u32, - pub height: u32, - pub stride: u32, -} - -#[derive(Debug)] -pub struct ScreencopyState { - pub screencopy_manager: zcosmic_screencopy_manager_v1::ZcosmicScreencopyManagerV1, // XXX pub - supported_cursor_modes: Vec, -} - -impl ScreencopyState { - pub fn new(globals: &GlobalList, qh: &QueueHandle) -> Self - where - D: Dispatch + 'static, - { - // TODO bind - let screencopy_manager = globals.bind(qh, 1..=1, ()).unwrap(); // XXX - Self { - screencopy_manager, - supported_cursor_modes: Vec::new(), - } - } -} - -pub trait ScreencopyHandler: Sized { - fn screencopy_state(&mut self) -> &mut ScreencopyState; - - fn init_done( - &mut self, - conn: &Connection, - qh: &QueueHandle, - session: &zcosmic_screencopy_session_v1::ZcosmicScreencopySessionV1, - buffer_infos: &[BufferInfo], - ); - - // needs to take transform, damage, cursor_{enter, leave, info} - // I assume commit_time is also before ready? - fn ready( - &mut self, - conn: &Connection, - qh: &QueueHandle, - session: &zcosmic_screencopy_session_v1::ZcosmicScreencopySessionV1, - ); - - fn failed( - &mut self, - conn: &Connection, - qh: &QueueHandle, - session: &zcosmic_screencopy_session_v1::ZcosmicScreencopySessionV1, - reason: WEnum, - ); -} - -pub trait ScreencopySessionDataExt { - fn screencopy_session_data(&self) -> &ScreencopySessionData; -} - -#[derive(Default)] -pub struct ScreencopySessionData { - buffer_infos: Mutex>, - // damage, transform -} - -impl ScreencopySessionDataExt for ScreencopySessionData { - fn screencopy_session_data(&self) -> &ScreencopySessionData { - self - } -} - -impl Dispatch - for ScreencopyState -where - D: Dispatch + ScreencopyHandler, -{ - fn event( - state: &mut D, - _: &zcosmic_screencopy_manager_v1::ZcosmicScreencopyManagerV1, - event: zcosmic_screencopy_manager_v1::Event, - _: &(), - _: &Connection, - _: &QueueHandle, - ) { - match event { - zcosmic_screencopy_manager_v1::Event::SupportedCursorMode { mode } => { - if let WEnum::Value(mode) = mode { - state.screencopy_state().supported_cursor_modes.push(mode); - } - } - _ => unreachable!(), - } - } -} - -impl Dispatch - for ScreencopyState -where - D: Dispatch + ScreencopyHandler, - U: ScreencopySessionDataExt, -{ - fn event( - app_data: &mut D, - session: &zcosmic_screencopy_session_v1::ZcosmicScreencopySessionV1, - event: zcosmic_screencopy_session_v1::Event, - udata: &U, - conn: &Connection, - qh: &QueueHandle, - ) { - let data = udata.screencopy_session_data(); - match event { - zcosmic_screencopy_session_v1::Event::BufferInfo { - _type, - node, - format, - width, - height, - stride, - } => { - let info = BufferInfo { - type_: _type, - node, - format, - width, - height, - stride, - }; - data.buffer_infos.lock().unwrap().push(info); - } - - zcosmic_screencopy_session_v1::Event::InitDone => { - let buffer_infos = data.buffer_infos.lock().unwrap(); - //println!("{:?}", &buffer_infos); - app_data.init_done(conn, qh, session, &*buffer_infos); - } - - zcosmic_screencopy_session_v1::Event::Transform { transform } => {} - - zcosmic_screencopy_session_v1::Event::Damage { - x, - y, - width, - height, - } => {} - - zcosmic_screencopy_session_v1::Event::CursorEnter { seat, input_type } => {} - - zcosmic_screencopy_session_v1::Event::CursorLeave { seat, input_type } => {} - - zcosmic_screencopy_session_v1::Event::CursorInfo { - seat, - input_type, - position_x, - position_y, - width, - height, - hotspot_x, - hotspot_y, - } => {} - - zcosmic_screencopy_session_v1::Event::Failed { reason } => { - app_data.failed(conn, qh, session, reason); - } - - zcosmic_screencopy_session_v1::Event::CommitTime { - tv_sec_hi, - tv_sec_lo, - tv_nsec, - } => { - let secs = (u64::from(tv_sec_hi) << 32) + u64::from(tv_sec_lo); - let duration = Duration::new(secs, tv_nsec); - // TODO - } - - zcosmic_screencopy_session_v1::Event::Ready => { - app_data.ready(conn, qh, session); // pass other info? - } - - _ => unreachable!(), - } - } -} - -// Type representing screencopy session? How to handle events? - -#[macro_export] -macro_rules! delegate_screencopy { - ($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => { - $crate::delegate_screencopy($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty, - session: $crate::screencopy::ScreencopySessionData); - }; - ($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty, session: [$($session_data:ty),* $(,)?]) => { - $crate::wayland_client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [ - $crate::cosmic_protocols::screencopy::v1::client::zcosmic_screencopy_manager_v1::ZcosmicScreencopyManagerV1: () - ] => $crate::screencopy::ScreencopyState); - $crate::wayland_client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [ - $( - $crate::cosmic_protocols::screencopy::v1::client::zcosmic_screencopy_session_v1::ZcosmicScreencopySessionV1: $session_data - ),* - ] => $crate::screencopy::ScreencopyState); - }; -} diff --git a/src/lib.rs b/src/lib.rs index 7cd358e083..d314c8f19a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,21 +13,34 @@ #![cfg_attr(docsrs, feature(doc_auto_cfg))] #![cfg_attr(rustfmt, rustfmt_skip)] + #[macro_use] mod protocol_macro; -pub mod screencopy { +pub mod image_source { //! Capture interface. #[allow(missing_docs)] pub mod v1 { wayland_protocol!( - "./unstable/cosmic-screencopy-unstable-v1.xml", + "./unstable/cosmic-image-source-unstable-v1.xml", [crate::workspace::v1, crate::toplevel_info::v1] ); } } +pub mod screencopy { + //! Capture interface. + + #[allow(missing_docs)] + pub mod v2 { + wayland_protocol!( + "./unstable/cosmic-screencopy-unstable-v2.xml", + [crate::image_source::v1] + ); + } +} + pub mod toplevel_info { //! Receive information about toplevel surfaces. diff --git a/unstable/cosmic-image-source-unstable-v1.xml b/unstable/cosmic-image-source-unstable-v1.xml new file mode 100644 index 0000000000..57ae970517 --- /dev/null +++ b/unstable/cosmic-image-source-unstable-v1.xml @@ -0,0 +1,133 @@ + + + + Copyright © 2022 Andri Yngvason + Copyright © 2024 Simon Ser + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice (including the next + paragraph) shall be included in all copies or substantial portions of the + Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + + + This protocol serves as an intermediary between screen capturing protocols + and potential image sources such as outputs and toplevels. + + This protocol may be extended to support more image sources in the future, + thereby adding those image sources to other protocols that use the image + source object without having to modify those protocols. + + Warning! The protocol described in this file is currently in the testing + phase. Backward compatible changes may be added together with the + corresponding interface version bump. Backward incompatible changes can + only be done by creating a new major version of the extension. + + + + + The image source object is an opaque descriptor for a capturable resource. + This resource may be any sort of entity from which an image may be + derived. + + Note, because zcosmic_image_source_v1 objects are created from multiple + independent factory interfaces, the zcosmic_image_source_v1 interface is + frozen at version 1. + + + + + Destroys the image source. This request may be sent at any time by the + client. + + + + + + + A manager for creating image source objects for wl_output objects. + + + + + Creates a source object for an output. Images captured from this source + will show the same content as the output. Some elements may be omitted, + such as cursors and overlays that have been marked as transparent to + capturing. + + + + + + + + Destroys the manager. This request may be sent at any time by the client + and objects created by the manager will remain valid after its + destruction. + + + + + + + A manager for creating image source objects for wl_output objects. + + + + + Creates a source object for a workspaces. Images captured from this source + will show the same content as the workspace. Some elements may be omitted, + such as cursors and overlays that have been marked as transparent to + capturing. + + + + + + + + Destroys the manager. This request may be sent at any time by the client + and objects created by the manager will remain valid after its + destruction. + + + + + + + A manager for creating image source objects for + zcosmic_toplevel_handle_v1 objects. + + + + + Creates a source object for a toplevel handle. Images captured + from this source will show the same content as the toplevel. + + + + + + + + Destroys the manager. This request may be sent at any time by the client + and objects created by the manager will remain valid after its + destruction. + + + + \ No newline at end of file diff --git a/unstable/cosmic-screencopy-unstable-v2.xml b/unstable/cosmic-screencopy-unstable-v2.xml new file mode 100644 index 0000000000..fd10a7cdf8 --- /dev/null +++ b/unstable/cosmic-screencopy-unstable-v2.xml @@ -0,0 +1,446 @@ + + + + Copyright © 2021-2023 Andri Yngvason + Copyright © 2024 Simon Ser + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice (including the next + paragraph) shall be included in all copies or substantial portions of the + Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + + + This protocol allows clients to ask the compositor to capture screen + contents to user submitted buffers. + + Warning! The protocol described in this file is currently in the testing + phase. Backward compatible changes may be added together with the + corresponding interface version bump. Backward incompatible changes can + only be done by creating a new major version of the extension. + + + + + This object is a manager which offers requests to start capturing from a + source. + + + + + + + + + + + + + Create a capturing session for an image source. + + If the paint_cursors option is set, cursors shall be composited onto + the captured frame. The cursor shall not be composited onto the frame + if this flag is not set. + + + + + + + + + Create a cursor capturing session for the pointer of an image source. + + The options argument has no effect and must be set to 0. This is + intended for any future flags that might be added. + + + + + + + + + + Destroy the manager object. + + Other objects created via this interface are unaffected. + + + + + + + This object represents an active screencopy session. + + After a screencopy session is created, buffer constraint events will be + emitted from the compositor to tell the client which buffer types and + formats are supported for reading from the session. The compositor may + re-send buffer constraint events whenever they change. + + The advertise buffer constraints, the compositor must send in no + particular order: zero or more shm_format and dmabuf_format events, zero + or one dmabuf_device event, and exactly one buffer_size event. Then the + compositor must send a done event. + + When the client has received all the buffer constraints, it can create a + buffer accordingly, attach it to the screencopy session using the + attach_buffer request, set the buffer damage using the damage_buffer + request and then send the capture request. + + + + + Provides the dimensions of the source image in buffer pixel coordinates. + + The client must attach buffers that match this size. + + + + + + + + Provides the format that must be used for shared-memory buffers. + + This event may be emitted multiple times, in which case the client may + choose any given format. + + + + + + + This event advertises the device buffers must be allocated on for + dma-buf buffers. + + In general the device is a DRM node. The DRM node type (primary vs. + render) is unspecified. Clients must not rely on the compositor sending + a particular node type. Clients cannot check two devices for equality + by comparing the dev_t value. + + + + + + + Provides the format that must be used for dma-buf buffers. + + The client may choose any of the modifiers advertised in the array of + 64-bit unsigned integers. + + This event may be emitted multiple times, in which case the client may + choose any given format. + + + + + + + + This event is sent once when all buffer constraint events have been + sent. + + The compositor must always end a batch of buffer constraint events with + this event, regardless of whether it sends the initial constraints or + an update. + + + + + + This event indicates that the capture session has stopped and is no + longer available. This can happen in a number of cases, e.g. when the + underlying source is destroyed, if the user decides to end the screen + capture, or if an unrecoverable runtime error has occurred. + + The client should destroy the session after receiving this event. + + + + + + Create a capture frame for this session. + + + + + + + Destroys the session. This request can be sent at any time by the + client. + + This request doesn't affect zcosmic_screencopy_frame_v2 objects created by + this object. + + + + + + + This object represents a screen capture frame. + + The client should attach a buffer, damage the buffer, and then send a + capture request. + + If the screen capture is successful, the compositor will send the frame + metadata (transform, damage, presentation_time in any order) followed by + the ready event. + + If the screen capture fails, the compositor will send the failed event. + + + + + + + + + + + Destroys the session. This request can be sent at any time by the + client. + + + + + + Attach a buffer to the session. + + The wl_buffer.release request is unused. + + This request must not be sent after capture, or else the + already_captured protocol error is raised. + + + + + + + Apply damage to the buffer which is to be captured next. This request + may be sent multiple times to describe a region. + + The client indicates the accumulated damage since this wl_buffer was + last captured. During capture, the compositor will update the buffer + with at least the union of the region passed by the client and the + region advertised by zcosmic_screencopy_frame_v2.damage. + + When a wl_buffer is captured for the first time, or when the client + doesn't track damage, the client must damage the whole buffer. + + This is for optimisation purposes. The compositor may use this + information to reduce copying. + + These coordinates originate from the upper left corner of the buffer. + + If x or y are strictly negative, or if width or height are negative or + zero, the invalid_buffer_damage protocol error is raised. + + This request must not be sent after capture, or else the + already_captured protocol error is raised. + + + + + + + + + + Capture a frame. + + Unless this is the first successful captured frame performed in this + session, the compositor may wait an indefinite amount of time for the + source content to change before performing the copy. + + This request may only be sent once, or else the already_captured + protocol error is raised. A buffer must be attached before this request + is sent, or else the no_buffer protocol error is raised. + + + + + + This event is sent before the ready event and holds the transform of + the source buffer. + + + + + + + This event is sent before the ready event. It may be generated multiple + times to describe a region. + + The first captured frame in a session will always carry full damage. + Subsequent frames' damaged regions describe which parts of the buffer + have changed since the last ready event. + + These coordinates originate in the upper left corner of the buffer. + + + + + + + + + + This event indicates the time at which the frame is presented to the + output in system monotonic time. This event is sent before the ready + event. + + The timestamp is expressed as tv_sec_hi, tv_sec_lo, tv_nsec triples, + each component being an unsigned 32-bit value. Whole seconds are in + tv_sec which is a 64-bit value combined from tv_sec_hi and tv_sec_lo, + and the additional fractional part in tv_nsec as nanoseconds. Hence, + for valid timestamps tv_nsec must be in [0, 999999999]. + + + + + + + + + Called as soon as the frame is copied, indicating it is available + for reading. + + The buffer may be re-used by the client after this event. + + After receiving this event, the client must destroy the object. + + + + + + + An unspecified runtime error has occurred. The client may retry. + + + + + The buffer submitted by the client doesn't match the latest session + constraints. The client should re-allocate its buffers and retry. + + + + + The session has stopped. See zcosmic_screencopy_session_v2.stopped. + + + + + + + This event indicates that the attempted frame copy has failed. + + After receiving this event, the client must destroy the object. + + + + + + + + This object represents a cursor capture session. It extends the base + capture session with cursor-specific metadata. + + + + + + + + + Destroys the session. This request can be sent at any time by the + client. + + This request doesn't affect zcosmic_screencopy_frame_v2 objects created by + this object. + + + + + + Gets the screencopy session for this cursor session. + + The session will produce frames of the cursor image. The compositor may + pause the session when the cursor leaves the captured area. + + This request must not be sent more than once, or else the + duplicate_session protocol error is raised. + + + + + + + Sent when a cursor enters the captured area. It shall be generated + before the "position" and "hotspot" events when and only when a cursor + enters the area. + + The cursor enters the captured area when the cursor image intersects + with the captured area. Note, this is different from e.g. + wl_pointer.enter. + + + + + + Sent when a cursor leaves the captured area. No "position" or "hotspot" + event is generated for the cursor until the cursor enters the captured + area again. + + + + + + Cursors outside the image source do not get captured and no event will + be generated for them. + + The given position is the position of the cursor's hotspot and it is + relative to the main buffer's top left corner in transformed buffer + pixel coordinates. + + The position coordinates are relative to the main buffer's upper left + corner. The coordinates may be negative or greater than the main buffer + size. + + + + + + + + The hotspot describes the offset between the cursor image and the + position of the input device. + + The given coordinates are the hotspot's offset from the origin in + buffer coordinates. + + Clients should not apply the hotspot immediately: the hotspot becomes + effective when the next zcosmic_screencopy_frame_v2.ready event is received. + + + + + +