cosmic_client_toolkit/screencopy/
capture_source.rs

1use std::{error::Error, fmt};
2use wayland_client::{Dispatch, QueueHandle, protocol::wl_output};
3use wayland_protocols::ext::{
4    foreign_toplevel_list::v1::client::ext_foreign_toplevel_handle_v1::ExtForeignToplevelHandleV1,
5    image_capture_source::v1::client::ext_image_capture_source_v1,
6    workspace::v1::client::ext_workspace_handle_v1::ExtWorkspaceHandleV1,
7};
8
9use super::Capturer;
10use crate::GlobalData;
11
12#[derive(Debug)]
13pub struct CaptureSourceError(CaptureSourceKind);
14
15impl fmt::Display for CaptureSourceError {
16    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
17        write!(f, "capture kind '{:?}' unsupported by compositor", self.0)
18    }
19}
20
21impl Error for CaptureSourceError {}
22
23#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
24pub enum CaptureSourceKind {
25    Output,
26    Toplevel,
27    Workspace,
28}
29
30#[derive(Clone, Debug, Hash, PartialEq, Eq)]
31pub enum CaptureSource {
32    Output(wl_output::WlOutput),
33    Toplevel(ExtForeignToplevelHandleV1),
34    Workspace(ExtWorkspaceHandleV1),
35}
36
37impl CaptureSource {
38    pub fn kind(&self) -> CaptureSourceKind {
39        match self {
40            Self::Output(_) => CaptureSourceKind::Output,
41            Self::Toplevel(_) => CaptureSourceKind::Toplevel,
42            Self::Workspace(_) => CaptureSourceKind::Workspace,
43        }
44    }
45
46    pub(crate) fn create_source<D>(
47        &self,
48        capturer: &Capturer,
49        qh: &QueueHandle<D>,
50    ) -> Result<WlCaptureSource, CaptureSourceError>
51    where
52        D: 'static,
53        D: Dispatch<ext_image_capture_source_v1::ExtImageCaptureSourceV1, GlobalData>,
54    {
55        match self {
56            CaptureSource::Output(output) => {
57                if let Some(manager) = &capturer.0.output_source_manager {
58                    return Ok(WlCaptureSource(
59                        manager.create_source(output, qh, GlobalData),
60                    ));
61                }
62            }
63            CaptureSource::Toplevel(toplevel) => {
64                if let Some(manager) = &capturer.0.foreign_toplevel_source_manager {
65                    return Ok(WlCaptureSource(
66                        manager.create_source(toplevel, qh, GlobalData),
67                    ));
68                }
69            }
70            CaptureSource::Workspace(workspace) => {
71                if let Some(manager) = &capturer.0.workspace_source_manager {
72                    return Ok(WlCaptureSource(
73                        manager.create_source(workspace, qh, GlobalData),
74                    ));
75                }
76            }
77        }
78        Err(CaptureSourceError(self.kind()))
79    }
80}
81
82// TODO name?
83pub(crate) struct WlCaptureSource(pub ext_image_capture_source_v1::ExtImageCaptureSourceV1);
84
85impl Drop for WlCaptureSource {
86    fn drop(&mut self) {
87        self.0.destroy();
88    }
89}