From 40bce507a6299bbed1f0ec053d72adcf561b30a3 Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Tue, 8 Oct 2024 17:46:22 +0200 Subject: [PATCH] screencapture: implement ext_output_image_capture_source_manager_v1 --- docs/features.md | 89 +++++++-------- release-notes.md | 1 + src/client/objects.rs | 14 ++- src/globals.rs | 2 + src/ifs.rs | 2 + src/ifs/ext_image_capture_source_v1.rs | 54 +++++++++ ..._output_image_capture_source_manager_v1.rs | 104 ++++++++++++++++++ wire/ext_image_capture_source_v1.txt | 3 + ...output_image_capture_source_manager_v1.txt | 8 ++ 9 files changed, 228 insertions(+), 49 deletions(-) create mode 100644 src/ifs/ext_image_capture_source_v1.rs create mode 100644 src/ifs/ext_output_image_capture_source_manager_v1.rs create mode 100644 wire/ext_image_capture_source_v1.txt create mode 100644 wire/ext_output_image_capture_source_manager_v1.txt diff --git a/docs/features.md b/docs/features.md index 2409c02d..4bed484a 100644 --- a/docs/features.md +++ b/docs/features.md @@ -138,50 +138,51 @@ Jay uses frame scheduling to achieve input latency as low as 1.5 ms. Jay supports the following wayland protocols: -| Global | Version | Privileged | -|-----------------------------------------|:----------------|---------------| -| ext_foreign_toplevel_list_v1 | 1 | Yes | -| ext_idle_notifier_v1 | 1 | Yes | -| ext_session_lock_manager_v1 | 1 | Yes | -| ext_transient_seat_manager_v1 | 1[^ts_rejected] | Yes | -| org_kde_kwin_server_decoration_manager | 1 | | -| wl_compositor | 6 | | -| wl_data_device_manager | 3 | | -| wl_drm | 2 | | -| wl_output | 4 | | -| wl_seat | 9 | | -| wl_shm | 2 | | -| wl_subcompositor | 1 | | -| wp_alpha_modifier_v1 | 1 | | -| wp_content_type_manager_v1 | 1 | | -| wp_cursor_shape_manager_v1 | 1 | | -| wp_drm_lease_device_v1 | 1 | | -| wp_fractional_scale_manager_v1 | 1 | | -| wp_linux_drm_syncobj_manager_v1 | 1 | | -| wp_presentation | 1 | | -| wp_security_context_manager_v1 | 1 | | -| wp_single_pixel_buffer_manager_v1 | 1 | | -| wp_tearing_control_manager_v1 | 1 | | -| wp_viewporter | 1 | | -| xdg_activation_v1 | 1 | | -| xdg_toplevel_drag_manager_v1 | 1 | | -| xdg_wm_base | 6 | | -| xdg_wm_dialog_v1 | 1 | | -| zwlr_data_control_manager_v1 | 2 | Yes | -| zwlr_layer_shell_v1 | 5 | No[^lsaccess] | -| zwlr_screencopy_manager_v1 | 3 | Yes | -| zwp_idle_inhibit_manager_v1 | 1 | | -| zwp_input_method_manager_v2 | 1 | Yes | -| zwp_linux_dmabuf_v1 | 5 | | -| zwp_pointer_constraints_v1 | 1 | | -| zwp_pointer_gestures_v1 | 3 | | -| zwp_primary_selection_device_manager_v1 | 1 | | -| zwp_relative_pointer_manager_v1 | 1 | | -| zwp_tablet_manager_v2 | 1 | | -| zwp_text_input_manager_v3 | 1 | | -| zwp_virtual_keyboard_manager_v1 | 1 | Yes | -| zxdg_decoration_manager_v1 | 1 | | -| zxdg_output_manager_v1 | 3 | | +| Global | Version | Privileged | +|--------------------------------------------|:----------------|---------------| +| ext_foreign_toplevel_list_v1 | 1 | Yes | +| ext_idle_notifier_v1 | 1 | Yes | +| ext_output_image_capture_source_manager_v1 | 1 | | +| ext_session_lock_manager_v1 | 1 | Yes | +| ext_transient_seat_manager_v1 | 1[^ts_rejected] | Yes | +| org_kde_kwin_server_decoration_manager | 1 | | +| wl_compositor | 6 | | +| wl_data_device_manager | 3 | | +| wl_drm | 2 | | +| wl_output | 4 | | +| wl_seat | 9 | | +| wl_shm | 2 | | +| wl_subcompositor | 1 | | +| wp_alpha_modifier_v1 | 1 | | +| wp_content_type_manager_v1 | 1 | | +| wp_cursor_shape_manager_v1 | 1 | | +| wp_drm_lease_device_v1 | 1 | | +| wp_fractional_scale_manager_v1 | 1 | | +| wp_linux_drm_syncobj_manager_v1 | 1 | | +| wp_presentation | 1 | | +| wp_security_context_manager_v1 | 1 | | +| wp_single_pixel_buffer_manager_v1 | 1 | | +| wp_tearing_control_manager_v1 | 1 | | +| wp_viewporter | 1 | | +| xdg_activation_v1 | 1 | | +| xdg_toplevel_drag_manager_v1 | 1 | | +| xdg_wm_base | 6 | | +| xdg_wm_dialog_v1 | 1 | | +| zwlr_data_control_manager_v1 | 2 | Yes | +| zwlr_layer_shell_v1 | 5 | No[^lsaccess] | +| zwlr_screencopy_manager_v1 | 3 | Yes | +| zwp_idle_inhibit_manager_v1 | 1 | | +| zwp_input_method_manager_v2 | 1 | Yes | +| zwp_linux_dmabuf_v1 | 5 | | +| zwp_pointer_constraints_v1 | 1 | | +| zwp_pointer_gestures_v1 | 3 | | +| zwp_primary_selection_device_manager_v1 | 1 | | +| zwp_relative_pointer_manager_v1 | 1 | | +| zwp_tablet_manager_v2 | 1 | | +| zwp_text_input_manager_v3 | 1 | | +| zwp_virtual_keyboard_manager_v1 | 1 | Yes | +| zxdg_decoration_manager_v1 | 1 | | +| zxdg_output_manager_v1 | 3 | | [^lsaccess]: Sandboxes can restrict access to this protocol. [^ts_rejected]: Seat creation is always rejected. diff --git a/release-notes.md b/release-notes.md index 5ce19817..2fbc1490 100644 --- a/release-notes.md +++ b/release-notes.md @@ -5,6 +5,7 @@ - Vulkan is now the default renderer. - Emulate vblank events on the nvidia driver. - Allow X windows to scale themselves. +- Implement ext-image-capture-source-v1. # 1.6.0 (2024-09-25) diff --git a/src/client/objects.rs b/src/client/objects.rs index 599fafdf..8eba416c 100644 --- a/src/client/objects.rs +++ b/src/client/objects.rs @@ -2,6 +2,7 @@ use { crate::{ client::{Client, ClientError}, ifs::{ + ext_image_capture_source_v1::ExtImageCaptureSourceV1, ipc::{ wl_data_source::WlDataSource, zwlr_data_control_source_v1::ZwlrDataControlSourceV1, zwp_primary_selection_source_v1::ZwpPrimarySelectionSourceV1, @@ -31,11 +32,11 @@ use { copyhashmap::{CopyHashMap, Locked}, }, wire::{ - JayOutputId, JayScreencastId, JayToplevelId, JayWorkspaceId, WlBufferId, - WlDataSourceId, WlOutputId, WlPointerId, WlRegionId, WlRegistryId, WlSeatId, - WlSurfaceId, WpDrmLeaseConnectorV1Id, WpLinuxDrmSyncobjTimelineV1Id, XdgPopupId, - XdgPositionerId, XdgSurfaceId, XdgToplevelId, XdgWmBaseId, ZwlrDataControlSourceV1Id, - ZwpPrimarySelectionSourceV1Id, ZwpTabletToolV2Id, + ExtImageCaptureSourceV1Id, JayOutputId, JayScreencastId, JayToplevelId, JayWorkspaceId, + WlBufferId, WlDataSourceId, WlOutputId, WlPointerId, WlRegionId, WlRegistryId, + WlSeatId, WlSurfaceId, WpDrmLeaseConnectorV1Id, WpLinuxDrmSyncobjTimelineV1Id, + XdgPopupId, XdgPositionerId, XdgSurfaceId, XdgToplevelId, XdgWmBaseId, + ZwlrDataControlSourceV1Id, ZwpPrimarySelectionSourceV1Id, ZwpTabletToolV2Id, }, }, std::{cell::RefCell, mem, rc::Rc}, @@ -67,6 +68,7 @@ pub struct Objects { pub drm_lease_outputs: CopyHashMap>, pub tablet_tools: CopyHashMap>, pub xdg_popups: CopyHashMap>, + pub image_capture_sources: CopyHashMap>, ids: RefCell>, } @@ -100,6 +102,7 @@ impl Objects { drm_lease_outputs: Default::default(), tablet_tools: Default::default(), xdg_popups: Default::default(), + image_capture_sources: Default::default(), ids: RefCell::new(vec![]), } } @@ -137,6 +140,7 @@ impl Objects { self.drm_lease_outputs.clear(); self.tablet_tools.clear(); self.xdg_popups.clear(); + self.image_capture_sources.clear(); } pub fn id(&self, client_data: &Client) -> Result diff --git a/src/globals.rs b/src/globals.rs index c8595388..eb8b3cb4 100644 --- a/src/globals.rs +++ b/src/globals.rs @@ -5,6 +5,7 @@ use { ifs::{ ext_foreign_toplevel_list_v1::ExtForeignToplevelListV1Global, ext_idle_notifier_v1::ExtIdleNotifierV1Global, + ext_output_image_capture_source_manager_v1::ExtOutputImageCaptureSourceManagerV1Global, ext_session_lock_manager_v1::ExtSessionLockManagerV1Global, ipc::{ wl_data_device_manager::WlDataDeviceManagerGlobal, @@ -197,6 +198,7 @@ impl Globals { add_singleton!(ZwpPointerGesturesV1Global); add_singleton!(ZwpTabletManagerV2Global); add_singleton!(JayDamageTrackingGlobal); + add_singleton!(ExtOutputImageCaptureSourceManagerV1Global); } pub fn add_backend_singletons(&self, backend: &Rc) { diff --git a/src/ifs.rs b/src/ifs.rs index 173493d7..2d5352b3 100644 --- a/src/ifs.rs +++ b/src/ifs.rs @@ -2,6 +2,8 @@ pub mod ext_foreign_toplevel_handle_v1; pub mod ext_foreign_toplevel_list_v1; pub mod ext_idle_notification_v1; pub mod ext_idle_notifier_v1; +pub mod ext_image_capture_source_v1; +pub mod ext_output_image_capture_source_manager_v1; pub mod ext_session_lock_manager_v1; pub mod ext_session_lock_v1; pub mod ipc; diff --git a/src/ifs/ext_image_capture_source_v1.rs b/src/ifs/ext_image_capture_source_v1.rs new file mode 100644 index 00000000..45b0180d --- /dev/null +++ b/src/ifs/ext_image_capture_source_v1.rs @@ -0,0 +1,54 @@ +use { + crate::{ + client::{Client, ClientError}, + ifs::wl_output::OutputGlobalOpt, + leaks::Tracker, + object::{Object, Version}, + wire::{ext_image_capture_source_v1::*, ExtImageCaptureSourceV1Id}, + }, + std::rc::Rc, + thiserror::Error, +}; + +#[expect(dead_code)] +#[derive(Clone)] +pub enum ImageCaptureSource { + Output(Rc), +} + +pub struct ExtImageCaptureSourceV1 { + pub id: ExtImageCaptureSourceV1Id, + pub client: Rc, + pub tracker: Tracker, + #[expect(dead_code)] + pub ty: ImageCaptureSource, +} + +impl ExtImageCaptureSourceV1RequestHandler for ExtImageCaptureSourceV1 { + type Error = ExtImageCaptureSourceError; + + fn destroy(&self, _req: Destroy, _slf: &Rc) -> Result<(), Self::Error> { + self.client.remove_obj(self)?; + Ok(()) + } +} + +object_base! { + self = ExtImageCaptureSourceV1; + version = Version(1); +} + +impl Object for ExtImageCaptureSourceV1 {} + +dedicated_add_obj!( + ExtImageCaptureSourceV1, + ExtImageCaptureSourceV1Id, + image_capture_sources +); + +#[derive(Debug, Error)] +pub enum ExtImageCaptureSourceError { + #[error(transparent)] + ClientError(Box), +} +efrom!(ExtImageCaptureSourceError, ClientError); diff --git a/src/ifs/ext_output_image_capture_source_manager_v1.rs b/src/ifs/ext_output_image_capture_source_manager_v1.rs new file mode 100644 index 00000000..ad8763e6 --- /dev/null +++ b/src/ifs/ext_output_image_capture_source_manager_v1.rs @@ -0,0 +1,104 @@ +use { + crate::{ + client::{Client, ClientError}, + globals::{Global, GlobalName}, + ifs::ext_image_capture_source_v1::{ExtImageCaptureSourceV1, ImageCaptureSource}, + leaks::Tracker, + object::{Object, Version}, + wire::{ + ext_output_image_capture_source_manager_v1::*, ExtOutputImageCaptureSourceManagerV1Id, + }, + }, + std::rc::Rc, + thiserror::Error, +}; + +pub struct ExtOutputImageCaptureSourceManagerV1Global { + pub name: GlobalName, +} + +impl ExtOutputImageCaptureSourceManagerV1Global { + pub fn new(name: GlobalName) -> Self { + Self { name } + } + + fn bind_( + self: Rc, + id: ExtOutputImageCaptureSourceManagerV1Id, + client: &Rc, + version: Version, + ) -> Result<(), ExtOutputImageCaptureSourceManagerV1Error> { + let obj = Rc::new(ExtOutputImageCaptureSourceManagerV1 { + id, + client: client.clone(), + tracker: Default::default(), + version, + }); + track!(client, obj); + client.add_client_obj(&obj)?; + Ok(()) + } +} + +pub struct ExtOutputImageCaptureSourceManagerV1 { + pub id: ExtOutputImageCaptureSourceManagerV1Id, + pub client: Rc, + pub tracker: Tracker, + pub version: Version, +} + +impl ExtOutputImageCaptureSourceManagerV1RequestHandler for ExtOutputImageCaptureSourceManagerV1 { + type Error = ExtOutputImageCaptureSourceManagerV1Error; + + fn create_source(&self, req: CreateSource, _slf: &Rc) -> Result<(), Self::Error> { + let output = self.client.lookup(req.output)?; + let obj = Rc::new(ExtImageCaptureSourceV1 { + id: req.source, + client: self.client.clone(), + tracker: Default::default(), + ty: ImageCaptureSource::Output(output.global.clone()), + }); + track!(self.client, obj); + self.client.add_client_obj(&obj)?; + Ok(()) + } + + fn destroy(&self, _req: Destroy, _slf: &Rc) -> Result<(), Self::Error> { + self.client.remove_obj(self)?; + Ok(()) + } +} + +global_base!( + ExtOutputImageCaptureSourceManagerV1Global, + ExtOutputImageCaptureSourceManagerV1, + ExtOutputImageCaptureSourceManagerV1Error +); + +impl Global for ExtOutputImageCaptureSourceManagerV1Global { + fn singleton(&self) -> bool { + true + } + + fn version(&self) -> u32 { + 1 + } +} + +simple_add_global!(ExtOutputImageCaptureSourceManagerV1Global); + +object_base! { + self = ExtOutputImageCaptureSourceManagerV1; + version = self.version; +} + +impl Object for ExtOutputImageCaptureSourceManagerV1 {} + +simple_add_obj!(ExtOutputImageCaptureSourceManagerV1); + +#[derive(Debug, Error)] +pub enum ExtOutputImageCaptureSourceManagerV1Error { + #[error(transparent)] + ClientError(Box), +} +efrom!(ExtOutputImageCaptureSourceManagerV1Error, ClientError); diff --git a/wire/ext_image_capture_source_v1.txt b/wire/ext_image_capture_source_v1.txt new file mode 100644 index 00000000..c8816211 --- /dev/null +++ b/wire/ext_image_capture_source_v1.txt @@ -0,0 +1,3 @@ +request destroy { + +} diff --git a/wire/ext_output_image_capture_source_manager_v1.txt b/wire/ext_output_image_capture_source_manager_v1.txt new file mode 100644 index 00000000..0664c20f --- /dev/null +++ b/wire/ext_output_image_capture_source_manager_v1.txt @@ -0,0 +1,8 @@ +request create_source { + source: id(ext_image_capture_source_v1), + output: id(wl_output), +} + +request destroy { + +}