image-copy: Use abstraction that's now provided by Smithay

This doesn't change much, since the Smithay implementation is based on
the `cosmic-comp` version, but made more generic. We provide our own
implementation for our workspace capture protocol, but otherwise Smithay
handles the boilerplate now.

This should not cause any change in behavior.
This commit is contained in:
Ian Douglas Scott 2026-01-13 18:26:26 -08:00 committed by Victoria Brekenfeld
parent 0f7e53b600
commit cac7a5aca6
16 changed files with 285 additions and 1536 deletions

View file

@ -1,10 +1,8 @@
use super::{
toplevel_info::window_from_ext_handle,
workspace::{WorkspaceHandle, WorkspaceHandler},
};
use crate::{
shell::CosmicSurface,
wayland::protocols::toplevel_info::ToplevelInfoHandler,
};
use cosmic_protocols::image_capture_source::v1::server::{
zcosmic_workspace_image_capture_source_manager_v1::{
@ -12,75 +10,54 @@ use cosmic_protocols::image_capture_source::v1::server::{
},
};
use smithay::reexports::wayland_protocols::ext::image_capture_source::v1::server::{
ext_foreign_toplevel_image_capture_source_manager_v1::{
Request as ToplevelSourceRequest, ExtForeignToplevelImageCaptureSourceManagerV1,
},
ext_image_capture_source_v1::ExtImageCaptureSourceV1,
ext_output_image_capture_source_manager_v1::{
Request as OutputSourceRequest, ExtOutputImageCaptureSourceManagerV1,
},
};
use smithay::{
output::{Output, WeakOutput},
output::WeakOutput,
reexports::wayland_server::{
Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New, Resource,
},
wayland::image_capture_source::{ImageCaptureSource, ImageCaptureSourceData},
};
use wayland_backend::server::GlobalId;
#[derive(Debug)]
pub struct ImageCaptureSourceState {
output_source_global: GlobalId,
pub struct CosmicImageCaptureSourceState {
workspace_source_global: GlobalId,
toplevel_source_global: GlobalId,
}
pub struct OutputImageCaptureSourceManagerGlobalData {
filter: Box<dyn for<'a> Fn(&'a Client) -> bool + Send + Sync>,
}
pub struct WorkspaceImageCaptureSourceManagerGlobalData {
filter: Box<dyn for<'a> Fn(&'a Client) -> bool + Send + Sync>,
}
pub struct ToplevelImageCaptureSourceManagerGlobalData {
filter: Box<dyn for<'a> Fn(&'a Client) -> bool + Send + Sync>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum ImageCaptureSourceData {
pub enum ImageCaptureSourceKind {
Output(WeakOutput),
Workspace(WorkspaceHandle),
Toplevel(CosmicSurface),
Destroyed,
}
impl ImageCaptureSourceState {
pub fn new<D, F>(display: &DisplayHandle, client_filter: F) -> ImageCaptureSourceState
impl ImageCaptureSourceKind {
pub fn from_resource(resource: &ExtImageCaptureSourceV1) -> Option<Self> {
let source = ImageCaptureSource::from_resource(resource)?;
source.user_data().get::<ImageCaptureSourceKind>().cloned()
}
}
impl CosmicImageCaptureSourceState {
pub fn new<D, F>(display: &DisplayHandle, client_filter: F) -> CosmicImageCaptureSourceState
where
D: GlobalDispatch<
ExtOutputImageCaptureSourceManagerV1,
OutputImageCaptureSourceManagerGlobalData,
> + Dispatch<ExtOutputImageCaptureSourceManagerV1, ()>
+ GlobalDispatch<
ZcosmicWorkspaceImageCaptureSourceManagerV1,
WorkspaceImageCaptureSourceManagerGlobalData,
> + Dispatch<ZcosmicWorkspaceImageCaptureSourceManagerV1, ()>
+ GlobalDispatch<
ExtForeignToplevelImageCaptureSourceManagerV1,
ToplevelImageCaptureSourceManagerGlobalData,
> + Dispatch<ExtForeignToplevelImageCaptureSourceManagerV1, ()>
+ Dispatch<ExtImageCaptureSourceV1, ImageCaptureSourceData>
+ WorkspaceHandler
+ 'static,
F: for<'a> Fn(&'a Client) -> bool + Send + Sync + Clone + 'static,
{
ImageCaptureSourceState {
output_source_global: display
.create_global::<D, ExtOutputImageCaptureSourceManagerV1, _>(
1,
OutputImageCaptureSourceManagerGlobalData {
filter: Box::new(client_filter.clone()),
},
),
CosmicImageCaptureSourceState {
workspace_source_global: display
.create_global::<D, ZcosmicWorkspaceImageCaptureSourceManagerV1, _>(
1,
@ -88,57 +65,12 @@ impl ImageCaptureSourceState {
filter: Box::new(client_filter.clone()),
},
),
toplevel_source_global: display
.create_global::<D, ExtForeignToplevelImageCaptureSourceManagerV1, _>(
1,
ToplevelImageCaptureSourceManagerGlobalData {
filter: Box::new(client_filter),
},
),
}
}
pub fn output_source_id(&self) -> &GlobalId {
&self.output_source_global
}
pub fn workspace_source_id(&self) -> &GlobalId {
&self.workspace_source_global
}
pub fn toplevel_source_id(&self) -> &GlobalId {
&self.toplevel_source_global
}
}
impl<D>
GlobalDispatch<
ExtOutputImageCaptureSourceManagerV1,
OutputImageCaptureSourceManagerGlobalData,
D,
> for ImageCaptureSourceState
where
D: GlobalDispatch<
ExtOutputImageCaptureSourceManagerV1,
OutputImageCaptureSourceManagerGlobalData,
> + Dispatch<ExtOutputImageCaptureSourceManagerV1, ()>
+ Dispatch<ExtImageCaptureSourceV1, ImageCaptureSourceData>
+ 'static,
{
fn bind(
_state: &mut D,
_handle: &DisplayHandle,
_client: &Client,
resource: New<ExtOutputImageCaptureSourceManagerV1>,
_global_data: &OutputImageCaptureSourceManagerGlobalData,
data_init: &mut DataInit<'_, D>,
) {
data_init.init(resource, ());
}
fn can_view(client: Client, global_data: &OutputImageCaptureSourceManagerGlobalData) -> bool {
(global_data.filter)(&client)
}
}
impl<D>
@ -146,7 +78,7 @@ impl<D>
ZcosmicWorkspaceImageCaptureSourceManagerV1,
WorkspaceImageCaptureSourceManagerGlobalData,
D,
> for ImageCaptureSourceState
> for CosmicImageCaptureSourceState
where
D: GlobalDispatch<
ZcosmicWorkspaceImageCaptureSourceManagerV1,
@ -174,70 +106,8 @@ where
}
}
impl<D>
GlobalDispatch<
ExtForeignToplevelImageCaptureSourceManagerV1,
ToplevelImageCaptureSourceManagerGlobalData,
D,
> for ImageCaptureSourceState
where
D: GlobalDispatch<
ExtForeignToplevelImageCaptureSourceManagerV1,
ToplevelImageCaptureSourceManagerGlobalData,
> + Dispatch<ExtForeignToplevelImageCaptureSourceManagerV1, ()>
+ Dispatch<ExtImageCaptureSourceV1, ImageCaptureSourceData>
+ 'static,
{
fn bind(
_state: &mut D,
_handle: &DisplayHandle,
_client: &Client,
resource: New<ExtForeignToplevelImageCaptureSourceManagerV1>,
_global_data: &ToplevelImageCaptureSourceManagerGlobalData,
data_init: &mut DataInit<'_, D>,
) {
data_init.init(resource, ());
}
fn can_view(client: Client, global_data: &ToplevelImageCaptureSourceManagerGlobalData) -> bool {
(global_data.filter)(&client)
}
}
impl<D> Dispatch<ExtOutputImageCaptureSourceManagerV1, (), D> for ImageCaptureSourceState
where
D: Dispatch<ExtOutputImageCaptureSourceManagerV1, ()>
+ Dispatch<ExtImageCaptureSourceV1, ImageCaptureSourceData>
+ 'static,
{
fn request(
_state: &mut D,
_client: &Client,
_resource: &ExtOutputImageCaptureSourceManagerV1,
request: <ExtOutputImageCaptureSourceManagerV1 as Resource>::Request,
_data: &(),
_dhandle: &DisplayHandle,
data_init: &mut DataInit<'_, D>,
) {
if let OutputSourceRequest::CreateSource { source, output } = request {
let data = match Output::from_resource(&output) {
Some(output) => ImageCaptureSourceData::Output(output.downgrade()),
None => ImageCaptureSourceData::Destroyed,
};
data_init.init(source, data);
}
}
fn destroyed(
_state: &mut D,
_client: wayland_backend::server::ClientId,
_resource: &ExtOutputImageCaptureSourceManagerV1,
_data: &(),
) {
}
}
impl<D> Dispatch<ZcosmicWorkspaceImageCaptureSourceManagerV1, (), D> for ImageCaptureSourceState
impl<D> Dispatch<ZcosmicWorkspaceImageCaptureSourceManagerV1, (), D>
for CosmicImageCaptureSourceState
where
D: Dispatch<ZcosmicWorkspaceImageCaptureSourceManagerV1, ()>
+ Dispatch<ExtImageCaptureSourceV1, ImageCaptureSourceData>
@ -253,110 +123,36 @@ where
_dhandle: &DisplayHandle,
data_init: &mut DataInit<'_, D>,
) {
if let CosmicWorkspaceSourceRequest::CreateSource { source, output } = request {
let data = match state.workspace_state().get_ext_workspace_handle(&output) {
Some(workspace) => ImageCaptureSourceData::Workspace(workspace),
None => ImageCaptureSourceData::Destroyed,
};
data_init.init(source, data);
}
}
fn destroyed(
_state: &mut D,
_client: wayland_backend::server::ClientId,
_resource: &ZcosmicWorkspaceImageCaptureSourceManagerV1,
_data: &(),
) {
}
}
impl<D> Dispatch<ExtForeignToplevelImageCaptureSourceManagerV1, (), D> for ImageCaptureSourceState
where
D: Dispatch<ExtForeignToplevelImageCaptureSourceManagerV1, ()>
+ Dispatch<ExtImageCaptureSourceV1, ImageCaptureSourceData>
+ ToplevelInfoHandler<Window = CosmicSurface>
+ 'static,
{
fn request(
state: &mut D,
_client: &Client,
_resource: &ExtForeignToplevelImageCaptureSourceManagerV1,
request: <ExtForeignToplevelImageCaptureSourceManagerV1 as Resource>::Request,
_data: &(),
_dhandle: &DisplayHandle,
data_init: &mut DataInit<'_, D>,
) {
if let ToplevelSourceRequest::CreateSource {
source,
toplevel_handle,
if let CosmicWorkspaceSourceRequest::CreateSource {
source: source_handle,
output,
} = request
{
let data = match window_from_ext_handle(state, &toplevel_handle) {
Some(toplevel) => ImageCaptureSourceData::Toplevel(toplevel.clone()),
None => ImageCaptureSourceData::Destroyed,
let data = match state.workspace_state().get_ext_workspace_handle(&output) {
Some(workspace) => ImageCaptureSourceKind::Workspace(workspace),
None => ImageCaptureSourceKind::Destroyed,
};
data_init.init(source, data);
let source = ImageCaptureSource::new();
source.user_data().insert_if_missing(|| data);
let instance = data_init.init(
source_handle,
ImageCaptureSourceData {
source: source.clone(),
},
);
source.add_instance(&instance);
}
}
fn destroyed(
_state: &mut D,
_client: wayland_backend::server::ClientId,
_resource: &ExtForeignToplevelImageCaptureSourceManagerV1,
_data: &(),
) {
}
}
impl<D> Dispatch<ExtImageCaptureSourceV1, ImageCaptureSourceData, D> for ImageCaptureSourceState
where
D: Dispatch<ExtImageCaptureSourceV1, ImageCaptureSourceData> + 'static,
{
fn request(
_state: &mut D,
_client: &Client,
_resource: &ExtImageCaptureSourceV1,
_request: <ExtImageCaptureSourceV1 as Resource>::Request,
_data: &ImageCaptureSourceData,
_dhandle: &DisplayHandle,
_data_init: &mut DataInit<'_, D>,
) {
{}
}
fn destroyed(
_state: &mut D,
_client: wayland_backend::server::ClientId,
_resource: &ExtImageCaptureSourceV1,
_data: &ImageCaptureSourceData,
) {
}
}
macro_rules! delegate_image_capture_source {
macro_rules! delegate_cosmic_image_capture_source {
($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => {
smithay::reexports::wayland_server::delegate_global_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
smithay::reexports::wayland_protocols::ext::image_capture_source::v1::server::ext_output_image_capture_source_manager_v1::ExtOutputImageCaptureSourceManagerV1: $crate::wayland::protocols::image_capture_source::OutputImageCaptureSourceManagerGlobalData
] => $crate::wayland::protocols::image_capture_source::ImageCaptureSourceState);
smithay::reexports::wayland_server::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
smithay::reexports::wayland_protocols::ext::image_capture_source::v1::server::ext_output_image_capture_source_manager_v1::ExtOutputImageCaptureSourceManagerV1: ()
] => $crate::wayland::protocols::image_capture_source::ImageCaptureSourceState);
smithay::reexports::wayland_server::delegate_global_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
cosmic_protocols::image_capture_source::v1::server::zcosmic_workspace_image_capture_source_manager_v1::ZcosmicWorkspaceImageCaptureSourceManagerV1: $crate::wayland::protocols::image_capture_source::WorkspaceImageCaptureSourceManagerGlobalData
] => $crate::wayland::protocols::image_capture_source::ImageCaptureSourceState);
] => $crate::wayland::protocols::image_capture_source::CosmicImageCaptureSourceState);
smithay::reexports::wayland_server::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
cosmic_protocols::image_capture_source::v1::server::zcosmic_workspace_image_capture_source_manager_v1::ZcosmicWorkspaceImageCaptureSourceManagerV1: ()
] => $crate::wayland::protocols::image_capture_source::ImageCaptureSourceState);
smithay::reexports::wayland_server::delegate_global_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
smithay::reexports::wayland_protocols::ext::image_capture_source::v1::server::ext_foreign_toplevel_image_capture_source_manager_v1::ExtForeignToplevelImageCaptureSourceManagerV1: $crate::wayland::protocols::image_capture_source::ToplevelImageCaptureSourceManagerGlobalData
] => $crate::wayland::protocols::image_capture_source::ImageCaptureSourceState);
smithay::reexports::wayland_server::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
smithay::reexports::wayland_protocols::ext::image_capture_source::v1::server::ext_foreign_toplevel_image_capture_source_manager_v1::ExtForeignToplevelImageCaptureSourceManagerV1: ()
] => $crate::wayland::protocols::image_capture_source::ImageCaptureSourceState);
smithay::reexports::wayland_server::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
smithay::reexports::wayland_protocols::ext::image_capture_source::v1::server::ext_image_capture_source_v1::ExtImageCaptureSourceV1: $crate::wayland::protocols::image_capture_source::ImageCaptureSourceData
] => $crate::wayland::protocols::image_capture_source::ImageCaptureSourceState);
] => $crate::wayland::protocols::image_capture_source::CosmicImageCaptureSourceState);
};
}
pub(crate) use delegate_image_capture_source;
pub(crate) use delegate_cosmic_image_capture_source;

View file

@ -7,7 +7,6 @@ pub mod image_capture_source;
pub mod output_configuration;
pub mod output_power;
pub mod overlap_notify;
pub mod screencopy;
pub mod toplevel_info;
pub mod toplevel_management;
pub mod workspace;

File diff suppressed because it is too large Load diff

View file

@ -635,14 +635,13 @@ pub fn window_from_handle<W: Window + 'static>(handle: ZcosmicToplevelHandleV1)
.and_then(|state| state.lock().unwrap().window.clone())
}
pub fn window_from_ext_handle<'a, W: Window + 'static, D>(
pub fn window_from_ext<'a, W: Window + 'static, D>(
state: &'a D,
foreign_toplevel: &ExtForeignToplevelHandleV1,
handle: &ForeignToplevelHandle,
) -> Option<&'a W>
where
D: ToplevelInfoHandler<Window = W>,
{
let handle = ForeignToplevelHandle::from_resource(foreign_toplevel)?;
state.toplevel_info_state().toplevels.iter().find(|w| {
w.user_data().get::<ToplevelState>().and_then(|inner| {
inner
@ -655,6 +654,17 @@ where
})
}
pub fn window_from_ext_handle<'a, W: Window + 'static, D>(
state: &'a D,
foreign_toplevel: &ExtForeignToplevelHandleV1,
) -> Option<&'a W>
where
D: ToplevelInfoHandler<Window = W>,
{
let handle = ForeignToplevelHandle::from_resource(foreign_toplevel)?;
window_from_ext(state, &handle)
}
macro_rules! delegate_toplevel_info {
($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty, $window: ty) => {
smithay::reexports::wayland_server::delegate_global_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [