From e91993fb1817b59feadc7e578749aaa9768b8e8f Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Tue, 8 Oct 2024 22:36:47 +0200 Subject: [PATCH] screencapture: implement ext_foreign_toplevel_image_capture_source_manager_v1 --- docs/features.md | 91 ++++++++------- src/client/objects.rs | 16 ++- src/globals.rs | 2 + src/ifs.rs | 1 + src/ifs/ext_foreign_toplevel_handle_v1.rs | 6 +- ...oplevel_image_capture_source_manager_v1.rs | 110 ++++++++++++++++++ src/ifs/ext_image_capture_source_v1.rs | 2 + ...plevel_image_capture_source_manager_v1.txt | 8 ++ 8 files changed, 185 insertions(+), 51 deletions(-) create mode 100644 src/ifs/ext_foreign_toplevel_image_capture_source_manager_v1.rs create mode 100644 wire/ext_foreign_toplevel_image_capture_source_manager_v1.txt diff --git a/docs/features.md b/docs/features.md index 4bed484a..6759a6eb 100644 --- a/docs/features.md +++ b/docs/features.md @@ -138,51 +138,52 @@ 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_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 | | +| Global | Version | Privileged | +|------------------------------------------------------|:----------------|---------------| +| ext_foreign_toplevel_image_capture_source_manager_v1 | 1 | | +| 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/src/client/objects.rs b/src/client/objects.rs index 8eba416c..1ec73b23 100644 --- a/src/client/objects.rs +++ b/src/client/objects.rs @@ -2,6 +2,7 @@ use { crate::{ client::{Client, ClientError}, ifs::{ + ext_foreign_toplevel_handle_v1::ExtForeignToplevelHandleV1, ext_image_capture_source_v1::ExtImageCaptureSourceV1, ipc::{ wl_data_source::WlDataSource, zwlr_data_control_source_v1::ZwlrDataControlSourceV1, @@ -32,11 +33,12 @@ use { copyhashmap::{CopyHashMap, Locked}, }, wire::{ - ExtImageCaptureSourceV1Id, JayOutputId, JayScreencastId, JayToplevelId, JayWorkspaceId, - WlBufferId, WlDataSourceId, WlOutputId, WlPointerId, WlRegionId, WlRegistryId, - WlSeatId, WlSurfaceId, WpDrmLeaseConnectorV1Id, WpLinuxDrmSyncobjTimelineV1Id, - XdgPopupId, XdgPositionerId, XdgSurfaceId, XdgToplevelId, XdgWmBaseId, - ZwlrDataControlSourceV1Id, ZwpPrimarySelectionSourceV1Id, ZwpTabletToolV2Id, + ExtForeignToplevelHandleV1Id, 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}, @@ -69,6 +71,8 @@ pub struct Objects { pub tablet_tools: CopyHashMap>, pub xdg_popups: CopyHashMap>, pub image_capture_sources: CopyHashMap>, + pub foreign_toplevel_handles: + CopyHashMap>, ids: RefCell>, } @@ -103,6 +107,7 @@ impl Objects { tablet_tools: Default::default(), xdg_popups: Default::default(), image_capture_sources: Default::default(), + foreign_toplevel_handles: Default::default(), ids: RefCell::new(vec![]), } } @@ -141,6 +146,7 @@ impl Objects { self.tablet_tools.clear(); self.xdg_popups.clear(); self.image_capture_sources.clear(); + self.foreign_toplevel_handles.clear(); } pub fn id(&self, client_data: &Client) -> Result diff --git a/src/globals.rs b/src/globals.rs index eb8b3cb4..5560d9bd 100644 --- a/src/globals.rs +++ b/src/globals.rs @@ -3,6 +3,7 @@ use { backend::Backend, client::{Client, ClientCaps}, ifs::{ + ext_foreign_toplevel_image_capture_source_manager_v1::ExtForeignToplevelImageCaptureSourceManagerV1Global, ext_foreign_toplevel_list_v1::ExtForeignToplevelListV1Global, ext_idle_notifier_v1::ExtIdleNotifierV1Global, ext_output_image_capture_source_manager_v1::ExtOutputImageCaptureSourceManagerV1Global, @@ -199,6 +200,7 @@ impl Globals { add_singleton!(ZwpTabletManagerV2Global); add_singleton!(JayDamageTrackingGlobal); add_singleton!(ExtOutputImageCaptureSourceManagerV1Global); + add_singleton!(ExtForeignToplevelImageCaptureSourceManagerV1Global); } pub fn add_backend_singletons(&self, backend: &Rc) { diff --git a/src/ifs.rs b/src/ifs.rs index 2d5352b3..5eda2065 100644 --- a/src/ifs.rs +++ b/src/ifs.rs @@ -1,4 +1,5 @@ pub mod ext_foreign_toplevel_handle_v1; +pub mod ext_foreign_toplevel_image_capture_source_manager_v1; pub mod ext_foreign_toplevel_list_v1; pub mod ext_idle_notification_v1; pub mod ext_idle_notifier_v1; diff --git a/src/ifs/ext_foreign_toplevel_handle_v1.rs b/src/ifs/ext_foreign_toplevel_handle_v1.rs index 750507d6..e5d90dbd 100644 --- a/src/ifs/ext_foreign_toplevel_handle_v1.rs +++ b/src/ifs/ext_foreign_toplevel_handle_v1.rs @@ -78,7 +78,11 @@ impl Object for ExtForeignToplevelHandleV1 { } } -simple_add_obj!(ExtForeignToplevelHandleV1); +dedicated_add_obj!( + ExtForeignToplevelHandleV1, + ExtForeignToplevelHandleV1Id, + foreign_toplevel_handles +); #[derive(Debug, Error)] pub enum ExtForeignToplevelHandleV1Error { diff --git a/src/ifs/ext_foreign_toplevel_image_capture_source_manager_v1.rs b/src/ifs/ext_foreign_toplevel_image_capture_source_manager_v1.rs new file mode 100644 index 00000000..4ce2c6db --- /dev/null +++ b/src/ifs/ext_foreign_toplevel_image_capture_source_manager_v1.rs @@ -0,0 +1,110 @@ +use { + crate::{ + client::{Client, ClientError}, + globals::{Global, GlobalName}, + ifs::ext_image_capture_source_v1::{ExtImageCaptureSourceV1, ImageCaptureSource}, + leaks::Tracker, + object::{Object, Version}, + wire::{ + ext_foreign_toplevel_image_capture_source_manager_v1::*, + ExtForeignToplevelImageCaptureSourceManagerV1Id, + }, + }, + std::rc::Rc, + thiserror::Error, +}; + +pub struct ExtForeignToplevelImageCaptureSourceManagerV1Global { + pub name: GlobalName, +} + +impl ExtForeignToplevelImageCaptureSourceManagerV1Global { + pub fn new(name: GlobalName) -> Self { + Self { name } + } + + fn bind_( + self: Rc, + id: ExtForeignToplevelImageCaptureSourceManagerV1Id, + client: &Rc, + version: Version, + ) -> Result<(), ExtForeignToplevelImageCaptureSourceManagerV1Error> { + let obj = Rc::new(ExtForeignToplevelImageCaptureSourceManagerV1 { + id, + client: client.clone(), + tracker: Default::default(), + version, + }); + track!(client, obj); + client.add_client_obj(&obj)?; + Ok(()) + } +} + +pub struct ExtForeignToplevelImageCaptureSourceManagerV1 { + pub id: ExtForeignToplevelImageCaptureSourceManagerV1Id, + pub client: Rc, + pub tracker: Tracker, + pub version: Version, +} + +impl ExtForeignToplevelImageCaptureSourceManagerV1RequestHandler + for ExtForeignToplevelImageCaptureSourceManagerV1 +{ + type Error = ExtForeignToplevelImageCaptureSourceManagerV1Error; + + fn create_source(&self, req: CreateSource, _slf: &Rc) -> Result<(), Self::Error> { + let handle = self.client.lookup(req.toplevel_handle)?; + let obj = Rc::new(ExtImageCaptureSourceV1 { + id: req.source, + client: self.client.clone(), + tracker: Default::default(), + ty: ImageCaptureSource::Toplevel(handle.toplevel.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!( + ExtForeignToplevelImageCaptureSourceManagerV1Global, + ExtForeignToplevelImageCaptureSourceManagerV1, + ExtForeignToplevelImageCaptureSourceManagerV1Error +); + +impl Global for ExtForeignToplevelImageCaptureSourceManagerV1Global { + fn singleton(&self) -> bool { + true + } + + fn version(&self) -> u32 { + 1 + } +} + +simple_add_global!(ExtForeignToplevelImageCaptureSourceManagerV1Global); + +object_base! { + self = ExtForeignToplevelImageCaptureSourceManagerV1; + version = self.version; +} + +impl Object for ExtForeignToplevelImageCaptureSourceManagerV1 {} + +simple_add_obj!(ExtForeignToplevelImageCaptureSourceManagerV1); + +#[derive(Debug, Error)] +pub enum ExtForeignToplevelImageCaptureSourceManagerV1Error { + #[error(transparent)] + ClientError(Box), +} +efrom!( + ExtForeignToplevelImageCaptureSourceManagerV1Error, + ClientError +); diff --git a/src/ifs/ext_image_capture_source_v1.rs b/src/ifs/ext_image_capture_source_v1.rs index 45b0180d..7a12ee7d 100644 --- a/src/ifs/ext_image_capture_source_v1.rs +++ b/src/ifs/ext_image_capture_source_v1.rs @@ -4,6 +4,7 @@ use { ifs::wl_output::OutputGlobalOpt, leaks::Tracker, object::{Object, Version}, + tree::ToplevelOpt, wire::{ext_image_capture_source_v1::*, ExtImageCaptureSourceV1Id}, }, std::rc::Rc, @@ -14,6 +15,7 @@ use { #[derive(Clone)] pub enum ImageCaptureSource { Output(Rc), + Toplevel(ToplevelOpt), } pub struct ExtImageCaptureSourceV1 { diff --git a/wire/ext_foreign_toplevel_image_capture_source_manager_v1.txt b/wire/ext_foreign_toplevel_image_capture_source_manager_v1.txt new file mode 100644 index 00000000..314b62ae --- /dev/null +++ b/wire/ext_foreign_toplevel_image_capture_source_manager_v1.txt @@ -0,0 +1,8 @@ +request create_source { + source: id(ext_image_capture_source_v1), + toplevel_handle: id(ext_foreign_toplevel_handle_v1), +} + +request destroy { + +}