Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 16 additions & 9 deletions src/client/objects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ use {
},
ext_foreign_toplevel_handle_v1::ExtForeignToplevelHandleV1,
ext_image_capture_source_v1::ExtImageCaptureSourceV1,
ext_image_copy::ext_image_copy_capture_session_v1::ExtImageCopyCaptureSessionV1,
ext_image_copy::{
ext_image_copy_capture_frame_v1::ExtImageCopyCaptureFrameV1,
ext_image_copy_capture_session_v1::ExtImageCopyCaptureSessionV1,
},
head_management::jay_head_error_v1::JayHeadErrorV1,
ipc::{
data_control::{
Expand Down Expand Up @@ -48,14 +51,14 @@ use {
},
wire::{
ExtDataControlSourceV1Id, ExtForeignToplevelHandleV1Id, ExtImageCaptureSourceV1Id,
ExtImageCopyCaptureSessionV1Id, ExtWorkspaceGroupHandleV1Id, JayHeadErrorV1Id,
JayOutputId, JayScreencastId, JayToplevelId, JayWorkspaceId, WlBufferId,
WlDataSourceId, WlOutputId, WlPointerId, WlRegionId, WlRegistryId, WlSeatId,
WlSurfaceId, WpDrmLeaseConnectorV1Id, WpImageDescriptionReferenceV1Id,
WpImageDescriptionV1Id, WpLinuxDrmSyncobjTimelineV1Id, XdgPopupId, XdgPositionerId,
XdgSurfaceId, XdgToplevelId, XdgWmBaseId, ZwlrDataControlSourceV1Id,
ZwlrOutputHeadV1Id, ZwlrOutputModeV1Id, ZwpPrimarySelectionSourceV1Id,
ZwpTabletToolV2Id,
ExtImageCopyCaptureFrameV1Id, ExtImageCopyCaptureSessionV1Id,
ExtWorkspaceGroupHandleV1Id, JayHeadErrorV1Id, JayOutputId, JayScreencastId,
JayToplevelId, JayWorkspaceId, WlBufferId, WlDataSourceId, WlOutputId, WlPointerId,
WlRegionId, WlRegistryId, WlSeatId, WlSurfaceId, WpDrmLeaseConnectorV1Id,
WpImageDescriptionReferenceV1Id, WpImageDescriptionV1Id, WpLinuxDrmSyncobjTimelineV1Id,
XdgPopupId, XdgPositionerId, XdgSurfaceId, XdgToplevelId, XdgWmBaseId,
ZwlrDataControlSourceV1Id, ZwlrOutputHeadV1Id, ZwlrOutputModeV1Id,
ZwpPrimarySelectionSourceV1Id, ZwpTabletToolV2Id,
},
},
std::{cell::RefCell, rc::Rc},
Expand Down Expand Up @@ -90,6 +93,8 @@ pub struct Objects {
pub tablet_tools: CopyHashMap<ZwpTabletToolV2Id, Rc<ZwpTabletToolV2>>,
pub xdg_popups: CopyHashMap<XdgPopupId, Rc<XdgPopup>>,
pub image_capture_sources: CopyHashMap<ExtImageCaptureSourceV1Id, Rc<ExtImageCaptureSourceV1>>,
pub image_capture_frames:
CopyHashMap<ExtImageCopyCaptureFrameV1Id, Rc<ExtImageCopyCaptureFrameV1>>,
pub foreign_toplevel_handles:
CopyHashMap<ExtForeignToplevelHandleV1Id, Rc<ExtForeignToplevelHandleV1>>,
pub ext_copy_sessions:
Expand Down Expand Up @@ -137,6 +142,7 @@ impl Objects {
tablet_tools: Default::default(),
xdg_popups: Default::default(),
image_capture_sources: Default::default(),
image_capture_frames: Default::default(),
foreign_toplevel_handles: Default::default(),
ext_copy_sessions: Default::default(),
ext_data_sources: Default::default(),
Expand Down Expand Up @@ -184,6 +190,7 @@ impl Objects {
self.tablet_tools.clear();
self.xdg_popups.clear();
self.image_capture_sources.clear();
self.image_capture_frames.clear();
self.foreign_toplevel_handles.clear();
self.ext_copy_sessions.clear();
self.ext_data_sources.clear();
Expand Down
6 changes: 5 additions & 1 deletion src/globals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ use {
ext_foreign_toplevel_image_capture_source_manager_v1::ExtForeignToplevelImageCaptureSourceManagerV1Global,
ext_foreign_toplevel_list_v1::ExtForeignToplevelListV1Global,
ext_idle_notifier_v1::ExtIdleNotifierV1Global,
ext_image_copy::ext_image_copy_capture_manager_v1::ExtImageCopyCaptureManagerV1Global,
ext_image_copy::{
ext_image_capture_color_manager_v1::ExtImageCaptureColorManagerV1Global,
ext_image_copy_capture_manager_v1::ExtImageCopyCaptureManagerV1Global,
},
ext_output_image_capture_source_manager_v1::ExtOutputImageCaptureSourceManagerV1Global,
ext_session_lock_manager_v1::ExtSessionLockManagerV1Global,
head_management::jay_head_manager_v1::JayHeadManagerV1Global,
Expand Down Expand Up @@ -231,6 +234,7 @@ impl Globals {
add_singleton!(XdgToplevelTagManagerV1Global);
add_singleton!(JayHeadManagerV1Global);
add_singleton!(WpPointerWarpV1Global);
add_singleton!(ExtImageCaptureColorManagerV1Global);
}

pub fn add_backend_singletons(&self, backend: &Rc<dyn Backend>) {
Expand Down
1 change: 1 addition & 0 deletions src/ifs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ 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;
pub mod ext_image_capture_source_colors_v1;
pub mod ext_image_capture_source_v1;
pub mod ext_image_copy;
pub mod ext_output_image_capture_source_manager_v1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ use {
thiserror::Error,
};

#[expect(dead_code)]
pub struct WpImageDescriptionReferenceV1 {
pub id: WpImageDescriptionReferenceV1Id,
pub client: Rc<Client>,
Expand Down
112 changes: 112 additions & 0 deletions src/ifs/ext_image_capture_source_colors_v1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
use {
crate::{
client::{Client, ClientError},
cmm::cmm_description::ColorDescription,
ifs::color_management::wp_image_description_reference_v1::WpImageDescriptionReferenceV1,
leaks::Tracker,
object::{Object, Version},
utils::{
clonecell::CloneCell,
event_listener::{EventListener, EventSource},
},
wire::{ExtImageCaptureSourceColorsV1Id, ext_image_capture_source_colors_v1::*},
},
std::{
cell::{Cell, LazyCell},
ops::Deref,
rc::Rc,
},
thiserror::Error,
};

#[derive(Default)]
pub struct PreferredColorDescriptionListeners {
init: Cell<bool>,
source: LazyCell<EventSource<dyn PreferredColorDescriptionListener>>,
}

impl PreferredColorDescriptionListeners {
pub fn changed(&self, desc: impl FnOnce() -> Rc<ColorDescription>) {
if !self.init.get() {
return;
}
let source = self.source.deref();
if source.has_listeners() {
let desc = desc();
for listener in source.iter() {
listener.changed(&desc);
}
}
}

pub fn attach(&self, listener: &EventListener<dyn PreferredColorDescriptionListener>) {
self.init.set(true);
listener.attach(&self.source);
}
}

pub trait PreferredColorDescriptionListener {
fn changed(&self, new: &Rc<ColorDescription>);
}

pub struct ExtImageCaptureSourceColorsV1 {
pub id: ExtImageCaptureSourceColorsV1Id,
pub client: Rc<Client>,
pub version: Version,
pub tracker: Tracker<Self>,
pub desc: CloneCell<Rc<ColorDescription>>,
pub listener: EventListener<dyn PreferredColorDescriptionListener>,
}

impl ExtImageCaptureSourceColorsV1 {
fn send_preferred_changed(&self, new: &Rc<ColorDescription>) {
self.client.event(PreferredChanged {
self_id: self.id,
identity: new.id.raw(),
});
}
}

impl PreferredColorDescriptionListener for ExtImageCaptureSourceColorsV1 {
fn changed(&self, new: &Rc<ColorDescription>) {
self.desc.set(new.clone());
self.send_preferred_changed(new);
}
}

impl ExtImageCaptureSourceColorsV1RequestHandler for ExtImageCaptureSourceColorsV1 {
type Error = ExtImageCaptureSourceColorsError;

fn destroy(&self, _req: Destroy, _slf: &Rc<Self>) -> Result<(), Self::Error> {
self.client.remove_obj(self)?;
Ok(())
}

fn get_preferred(&self, req: GetPreferred, _slf: &Rc<Self>) -> Result<(), Self::Error> {
let ref_ = Rc::new(WpImageDescriptionReferenceV1 {
id: req.id,
client: self.client.clone(),
tracker: Default::default(),
description: self.desc.get(),
});
track!(self.client, ref_);
self.client.add_client_obj(&ref_)?;
Ok(())
}
}

object_base! {
self = ExtImageCaptureSourceColorsV1;
version = self.version;
}

impl Object for ExtImageCaptureSourceColorsV1 {}

simple_add_obj!(ExtImageCaptureSourceColorsV1);

#[derive(Debug, Error)]
pub enum ExtImageCaptureSourceColorsError {
#[error(transparent)]
ClientError(Box<ClientError>),
}
efrom!(ExtImageCaptureSourceColorsError, ClientError);
1 change: 1 addition & 0 deletions src/ifs/ext_image_copy.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod ext_image_capture_color_manager_v1;
pub mod ext_image_copy_capture_cursor_session_v1;
pub mod ext_image_copy_capture_frame_v1;
pub mod ext_image_copy_capture_manager_v1;
Expand Down
167 changes: 167 additions & 0 deletions src/ifs/ext_image_copy/ext_image_capture_color_manager_v1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
use {
crate::{
client::{CAP_SCREENCOPY_MANAGER, Client, ClientCaps, ClientError},
globals::{Global, GlobalName},
ifs::{
ext_image_capture_source_colors_v1::ExtImageCaptureSourceColorsV1,
ext_image_capture_source_v1::ImageCaptureSource,
ext_image_copy::ext_image_copy_capture_frame_v1::ExtImageCopyCaptureFrameV1Error,
},
leaks::Tracker,
object::{Object, Version},
state::State,
utils::{clonecell::CloneCell, event_listener::EventListener},
wire::{ExtImageCaptureColorManagerV1Id, ext_image_capture_color_manager_v1::*},
},
std::rc::{Rc, Weak},
thiserror::Error,
};

pub struct ExtImageCaptureColorManagerV1Global {
pub name: GlobalName,
}

impl ExtImageCaptureColorManagerV1Global {
pub fn new(name: GlobalName) -> Self {
Self { name }
}

fn bind_(
self: Rc<Self>,
id: ExtImageCaptureColorManagerV1Id,
client: &Rc<Client>,
version: Version,
) -> Result<(), ExtImageCaptureColorManagerV1Error> {
let obj = Rc::new(ExtImageCaptureColorManagerV1 {
id,
client: client.clone(),
tracker: Default::default(),
version,
});
track!(client, obj);
client.add_client_obj(&obj)?;
Ok(())
}
}

pub struct ExtImageCaptureColorManagerV1 {
pub(super) id: ExtImageCaptureColorManagerV1Id,
pub(super) client: Rc<Client>,
pub(super) tracker: Tracker<Self>,
pub(super) version: Version,
}

impl ExtImageCaptureColorManagerV1RequestHandler for ExtImageCaptureColorManagerV1 {
type Error = ExtImageCaptureColorManagerV1Error;

fn destroy(&self, _req: Destroy, _slf: &Rc<Self>) -> Result<(), Self::Error> {
self.client.remove_obj(self)?;
Ok(())
}

fn get_capture_source_colors(
&self,
req: GetCaptureSourceColors,
_slf: &Rc<Self>,
) -> Result<(), Self::Error> {
let source = self.client.lookup(req.source)?;
let output;
let surface;
let mut event_source = None;
let mut desc = self.client.state.color_manager.srgb_gamma22().clone();
match &source.ty {
ImageCaptureSource::Output(o) => {
if let Some(o) = o.get() {
desc = o.color_description.get();
output = o;
event_source = Some(&output.color_description_listeners2);
}
}
ImageCaptureSource::Toplevel(tl) => {
if let Some(tl) = tl.get()
&& let Some(s) = tl.tl_scanout_surface()
{
desc = s.color_description();
surface = s;
event_source = Some(&surface.color_description_listeners);
}
}
}
let obj = Rc::new_cyclic(|slf: &Weak<ExtImageCaptureSourceColorsV1>| {
ExtImageCaptureSourceColorsV1 {
id: req.colors,
client: self.client.clone(),
version: self.version,
tracker: Default::default(),
desc: CloneCell::new(desc),
listener: EventListener::new(slf.clone()),
}
});
track!(self.client, &obj);
self.client.add_client_obj(&obj)?;
if let Some(source) = event_source {
source.attach(&obj.listener);
}
Ok(())
}

fn set_frame_image_description(
&self,
req: SetFrameImageDescription,
_slf: &Rc<Self>,
) -> Result<(), Self::Error> {
let cd = self.client.lookup(req.image_description)?;
let Some(desc) = &cd.description else {
return Err(ExtImageCaptureColorManagerV1Error::NotReady);
};
let frame = self.client.lookup(req.frame)?;
frame.set_color_description(desc)?;
Ok(())
}
}

global_base!(
ExtImageCaptureColorManagerV1Global,
ExtImageCaptureColorManagerV1,
ExtImageCaptureColorManagerV1Error
);

impl Global for ExtImageCaptureColorManagerV1Global {
fn singleton(&self) -> bool {
true
}

fn version(&self) -> u32 {
1
}

fn required_caps(&self) -> ClientCaps {
CAP_SCREENCOPY_MANAGER
}

fn exposed(&self, state: &State) -> bool {
state.color_management_available()
}
}

simple_add_global!(ExtImageCaptureColorManagerV1Global);

object_base! {
self = ExtImageCaptureColorManagerV1;
version = self.version;
}

impl Object for ExtImageCaptureColorManagerV1 {}

simple_add_obj!(ExtImageCaptureColorManagerV1);

#[derive(Debug, Error)]
pub enum ExtImageCaptureColorManagerV1Error {
#[error(transparent)]
ClientError(Box<ClientError>),
#[error("The image description is not ready")]
NotReady,
#[error(transparent)]
FrameError(#[from] ExtImageCopyCaptureFrameV1Error),
}
efrom!(ExtImageCaptureColorManagerV1Error, ClientError);
Loading