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

@ -8,7 +8,7 @@ use crate::{
config::{CompTransformDef, EdidProduct, ScreenFilter},
shell::Shell,
utils::{env::dev_list_var, prelude::*},
wayland::handlers::screencopy::PendingImageCopyData,
wayland::handlers::image_copy_capture::PendingImageCopyData,
};
use anyhow::{Context, Result};

View file

@ -11,14 +11,9 @@ use crate::{
shell::Shell,
state::SurfaceDmabufFeedback,
utils::prelude::*,
wayland::{
handlers::{
compositor::recursive_frame_time_estimation,
screencopy::{FrameHolder, PendingImageCopyData, SessionData, submit_buffer},
},
protocols::screencopy::{
FailureReason, Frame as ScreencopyFrame, SessionRef as ScreencopySessionRef,
},
wayland::handlers::{
compositor::recursive_frame_time_estimation,
image_copy_capture::{FrameHolder, PendingImageCopyData, SessionData, submit_buffer},
},
};
@ -82,6 +77,9 @@ use smithay::{
utils::{Clock, Monotonic, Physical, Point, Rectangle, Transform},
wayland::{
dmabuf::{DmabufFeedbackBuilder, get_dmabuf},
image_copy_capture::{
CaptureFailureReason, Frame as ScreencopyFrame, SessionRef as ScreencopySessionRef,
},
presentation::Refresh,
seat::WaylandFocus,
shm::{shm_format_to_fourcc, with_buffer_contents},
@ -1398,7 +1396,7 @@ impl SurfaceThreadState {
.lock()
.unwrap()
.reset();
frame.fail(FailureReason::Unknown);
frame.fail(CaptureFailureReason::Unknown);
}
return Err(err).with_context(|| "Failed to submit result for display");
}

View file

@ -35,7 +35,7 @@ use crate::{
handlers::{
compositor::FRAME_TIME_FILTER,
data_device::get_dnd_icon,
screencopy::{FrameHolder, SessionData, render_session},
image_copy_capture::{FrameHolder, SessionData, render_session},
},
protocols::workspace::WorkspaceHandle,
},

View file

@ -24,9 +24,8 @@ use crate::{
zoom::ZoomState,
},
utils::{prelude::*, quirks::workspace_overview_is_open},
wayland::{
handlers::{screencopy::SessionHolder, xwayland_keyboard_grab::XWaylandGrabSeat},
protocols::screencopy::{BufferConstraints, CursorSessionRef},
wayland::handlers::{
image_copy_capture::SessionHolder, xwayland_keyboard_grab::XWaylandGrabSeat,
},
};
use calloop::{
@ -62,6 +61,7 @@ use smithay::{
},
utils::{Point, Rectangle, SERIAL_COUNTER, Serial},
wayland::{
image_copy_capture::{BufferConstraints, CursorSessionRef},
keyboard_shortcuts_inhibit::KeyboardShortcutsInhibitorSeat,
pointer_constraints::{PointerConstraint, with_pointer_constraint},
seat::WaylandFocus,

View file

@ -12,7 +12,7 @@ use crate::{
zoom::ZoomFocusTarget,
},
utils::prelude::*,
wayland::handlers::{screencopy::SessionHolder, xdg_shell::popup::get_popup_toplevel},
wayland::handlers::{image_copy_capture::SessionHolder, xdg_shell::popup::get_popup_toplevel},
};
use id_tree::NodeId;
use smithay::{

View file

@ -13,7 +13,7 @@ use crate::{
state::State,
utils::{prelude::*, tween::EaseRectangle},
wayland::{
handlers::screencopy::ScreencopySessions,
handlers::image_copy_capture::ImageCopySessions,
protocols::{
toplevel_info::{toplevel_enter_output, toplevel_leave_output},
workspace::{WorkspaceHandle, WorkspaceUpdateGuard},
@ -110,7 +110,7 @@ pub struct Workspace {
pub handle: WorkspaceHandle,
pub focus_stack: FocusStacks,
pub screencopy: ScreencopySessions,
pub image_copy: ImageCopySessions,
output_stack: VecDeque<OutputMatch>,
pub(super) backdrop_id: Id,
pub dirty: AtomicBool,
@ -377,7 +377,7 @@ impl Workspace {
id: None,
handle,
focus_stack: FocusStacks::default(),
screencopy: ScreencopySessions::default(),
image_copy: ImageCopySessions::default(),
output_stack: {
let mut queue = VecDeque::new();
queue.push_back(output_match);
@ -410,7 +410,7 @@ impl Workspace {
id: pinned.id.clone(),
handle,
focus_stack: FocusStacks::default(),
screencopy: ScreencopySessions::default(),
image_copy: ImageCopySessions::default(),
output_stack: {
let mut queue = VecDeque::new();
queue.push_back(pinned.output.clone());

View file

@ -13,16 +13,15 @@ use crate::{
shell::{CosmicSurface, SeatExt, Shell, grabs::SeatMoveGrabState},
utils::prelude::OutputExt,
wayland::{
handlers::{data_device::get_dnd_icon, screencopy::SessionHolder},
handlers::{data_device::get_dnd_icon, image_copy_capture::SessionHolder},
protocols::{
a11y::A11yState,
corner_radius::CornerRadiusState,
drm::WlDrmState,
image_capture_source::ImageCaptureSourceState,
image_capture_source::CosmicImageCaptureSourceState,
output_configuration::OutputConfigurationState,
output_power::OutputPowerState,
overlap_notify::OverlapNotifyState,
screencopy::ScreencopyState,
toplevel_info::ToplevelInfoState,
toplevel_management::{ManagementCapabilities, ToplevelManagementState},
workspace::{WorkspaceState, WorkspaceUpdateGuard},
@ -80,6 +79,8 @@ use smithay::{
fractional_scale::{FractionalScaleManagerState, with_fractional_scale},
idle_inhibit::IdleInhibitManagerState,
idle_notify::IdleNotifierState,
image_capture_source::{OutputCaptureSourceState, ToplevelCaptureSourceState},
image_copy_capture::ImageCopyCaptureState,
input_method::InputMethodManagerState,
keyboard_shortcuts_inhibit::KeyboardShortcutsInhibitState,
output::OutputManagerState,
@ -260,8 +261,10 @@ pub struct Common {
pub primary_selection_state: PrimarySelectionState,
pub ext_data_control_state: ExtDataControlState,
pub wlr_data_control_state: WlrDataControlState,
pub image_capture_source_state: ImageCaptureSourceState,
pub screencopy_state: ScreencopyState,
pub cosmic_image_capture_source_state: CosmicImageCaptureSourceState,
pub output_capture_source_state: OutputCaptureSourceState,
pub toplevel_capture_source_state: ToplevelCaptureSourceState,
pub image_copy_capture_state: ImageCopyCaptureState,
pub seat_state: SeatState<State>,
pub session_lock_manager_state: SessionLockManagerState,
pub idle_notifier_state: IdleNotifierState<State>,
@ -645,9 +648,14 @@ impl State {
OverlapNotifyState::new::<Self, _>(dh, client_has_no_security_context);
let presentation_state = PresentationState::new::<Self>(dh, clock.id() as u32);
let primary_selection_state = PrimarySelectionState::new::<Self>(dh);
let image_capture_source_state =
ImageCaptureSourceState::new::<Self, _>(dh, client_not_sandboxed);
let screencopy_state = ScreencopyState::new::<Self, _>(dh, client_not_sandboxed);
let cosmic_image_capture_source_state =
CosmicImageCaptureSourceState::new::<Self, _>(dh, client_not_sandboxed);
let output_capture_source_state =
OutputCaptureSourceState::new_with_filter::<State, _>(&dh, client_not_sandboxed);
let toplevel_capture_source_state =
ToplevelCaptureSourceState::new_with_filter::<State, _>(&dh, client_not_sandboxed);
let image_copy_capture_state =
ImageCopyCaptureState::new_with_filter::<Self, _>(dh, client_not_sandboxed);
let shm_state =
ShmState::new::<Self>(dh, vec![wl_shm::Format::Xbgr8888, wl_shm::Format::Abgr8888]);
let cursor_shape_manager_state = CursorShapeManagerState::new::<State>(dh);
@ -754,8 +762,10 @@ impl State {
idle_notifier_state,
idle_inhibit_manager_state,
idle_inhibiting_surfaces,
image_capture_source_state,
screencopy_state,
cosmic_image_capture_source_state,
output_capture_source_state,
toplevel_capture_source_state,
image_copy_capture_state,
shm_state,
cursor_shape_manager_state,
seat_state,

View file

@ -1,4 +1,59 @@
use crate::state::State;
use crate::wayland::protocols::image_capture_source::delegate_image_capture_source;
// SPDX-License-Identifier: GPL-3.0-only
delegate_image_capture_source!(State);
use crate::{
state::State,
wayland::protocols::{
image_capture_source::{ImageCaptureSourceKind, delegate_cosmic_image_capture_source},
toplevel_info::window_from_ext,
},
};
use smithay::{
output::Output,
wayland::{
foreign_toplevel_list::ForeignToplevelHandle,
image_capture_source::{
ImageCaptureSource, ImageCaptureSourceHandler, OutputCaptureSourceHandler,
OutputCaptureSourceState, ToplevelCaptureSourceHandler, ToplevelCaptureSourceState,
},
},
};
impl ImageCaptureSourceHandler for State {
fn source_destroyed(&mut self, _source: ImageCaptureSource) {}
}
impl OutputCaptureSourceHandler for State {
fn output_capture_source_state(&mut self) -> &mut OutputCaptureSourceState {
&mut self.common.output_capture_source_state
}
fn output_source_created(&mut self, source: ImageCaptureSource, output: &Output) {
source
.user_data()
.insert_if_missing(|| ImageCaptureSourceKind::Output(output.downgrade()));
}
}
impl ToplevelCaptureSourceHandler for State {
fn toplevel_capture_source_state(&mut self) -> &mut ToplevelCaptureSourceState {
&mut self.common.toplevel_capture_source_state
}
fn toplevel_source_created(
&mut self,
source: ImageCaptureSource,
toplevel: &ForeignToplevelHandle,
) {
let data = match window_from_ext(self, toplevel) {
Some(toplevel) => ImageCaptureSourceKind::Toplevel(toplevel.clone()),
None => ImageCaptureSourceKind::Destroyed,
};
source.user_data().insert_if_missing(|| data);
}
}
smithay::delegate_image_capture_source!(State);
smithay::delegate_output_capture_source!(State);
smithay::delegate_toplevel_capture_source!(State);
delegate_cosmic_image_capture_source!(State);

View file

@ -1,3 +1,5 @@
// SPDX-License-Identifier: GPL-3.0-only
use std::{borrow::Borrow, collections::HashMap, sync::Mutex};
use smithay::{
@ -15,7 +17,15 @@ use smithay::{
output::Output,
reexports::wayland_server::protocol::wl_shm::Format as ShmFormat,
utils::{Buffer as BufferCoords, Point, Size, Transform},
wayland::{dmabuf::get_dmabuf, seat::WaylandFocus},
wayland::{
dmabuf::get_dmabuf,
image_capture_source::ImageCaptureSource,
image_copy_capture::{
BufferConstraints, CursorSession, CursorSessionRef, DmabufConstraints, Frame, FrameRef,
ImageCopyCaptureHandler, ImageCopyCaptureState, Session, SessionRef,
},
seat::WaylandFocus,
},
};
use crate::{
@ -24,45 +34,41 @@ use crate::{
utils::prelude::{
OutputExt, PointExt, PointGlobalExt, PointLocalExt, RectExt, RectLocalExt, SeatExt,
},
wayland::protocols::{
image_capture_source::ImageCaptureSourceData,
screencopy::{
BufferConstraints, CursorSession, CursorSessionRef, DmabufConstraints, Frame, FrameRef,
ScreencopyHandler, ScreencopyState, Session, SessionRef, delegate_screencopy,
},
},
wayland::protocols::image_capture_source::ImageCaptureSourceKind,
};
mod render;
mod user_data;
pub use self::render::*;
use self::user_data::*;
pub use self::user_data::{FrameHolder, ScreencopySessions, SessionData, SessionHolder};
pub use self::user_data::{FrameHolder, ImageCopySessions, SessionData, SessionHolder};
impl ScreencopyHandler for State {
fn screencopy_state(&mut self) -> &mut ScreencopyState {
&mut self.common.screencopy_state
impl ImageCopyCaptureHandler for State {
fn image_copy_capture_state(&mut self) -> &mut ImageCopyCaptureState {
&mut self.common.image_copy_capture_state
}
fn capture_source(&mut self, source: &ImageCaptureSourceData) -> Option<BufferConstraints> {
match source {
ImageCaptureSourceData::Output(weak) => weak
fn capture_constraints(&mut self, source: &ImageCaptureSource) -> Option<BufferConstraints> {
let kind = source.user_data().get::<ImageCaptureSourceKind>().unwrap();
match kind {
ImageCaptureSourceKind::Output(weak) => weak
.upgrade()
.and_then(|output| constraints_for_output(&output, &mut self.backend)),
ImageCaptureSourceData::Workspace(handle) => {
ImageCaptureSourceKind::Workspace(handle) => {
let shell = self.common.shell.read();
let output = shell.workspaces.space_for_handle(handle)?.output();
constraints_for_output(output, &mut self.backend)
}
ImageCaptureSourceData::Toplevel(window) => {
ImageCaptureSourceKind::Toplevel(window) => {
constraints_for_toplevel(window, &mut self.backend)
}
_ => None,
}
}
fn capture_cursor_source(
fn cursor_capture_constraints(
&mut self,
_source: &ImageCaptureSourceData,
_source: &ImageCaptureSource,
) -> Option<BufferConstraints> {
let size = if let Some((geometry, _)) = self
.common
@ -85,8 +91,14 @@ impl ScreencopyHandler for State {
}
fn new_session(&mut self, session: Session) {
match session.source() {
ImageCaptureSourceData::Output(weak) => {
let kind = session
.source()
.user_data()
.get::<ImageCaptureSourceKind>()
.unwrap()
.clone();
match kind {
ImageCaptureSourceKind::Output(weak) => {
let Some(mut output) = weak.upgrade() else {
session.stop();
return;
@ -100,7 +112,7 @@ impl ScreencopyHandler for State {
output.add_session(session);
}
ImageCaptureSourceData::Workspace(handle) => {
ImageCaptureSourceKind::Workspace(handle) => {
let mut shell = self.common.shell.write();
let Some(workspace) = shell.workspaces.space_for_handle_mut(&handle) else {
session.stop();
@ -114,7 +126,7 @@ impl ScreencopyHandler for State {
});
workspace.add_session(session);
}
ImageCaptureSourceData::Toplevel(mut toplevel) => {
ImageCaptureSourceKind::Toplevel(mut toplevel) => {
let size = toplevel.geometry().size.to_physical(1);
session.user_data().insert_if_missing_threadsafe(|| {
Mutex::new(SessionUserData::new(OutputDamageTracker::new(
@ -125,9 +137,10 @@ impl ScreencopyHandler for State {
});
toplevel.add_session(session);
}
ImageCaptureSourceData::Destroyed => unreachable!(),
ImageCaptureSourceKind::Destroyed => unreachable!(),
}
}
fn new_cursor_session(&mut self, session: CursorSession) {
let (pointer_loc, pointer_size, hotspot) = {
let seat = self.common.shell.read().seats.last_active().clone();
@ -154,8 +167,14 @@ impl ScreencopyHandler for State {
)))
});
match session.source() {
ImageCaptureSourceData::Output(weak) => {
let kind = session
.source()
.user_data()
.get::<ImageCaptureSourceKind>()
.unwrap()
.clone();
match kind {
ImageCaptureSourceKind::Output(weak) => {
let Some(mut output) = weak.upgrade() else {
return;
};
@ -184,7 +203,7 @@ impl ScreencopyHandler for State {
output.add_cursor_session(session);
}
ImageCaptureSourceData::Workspace(handle) => {
ImageCaptureSourceKind::Workspace(handle) => {
let mut shell = self.common.shell.write();
let Some(workspace) = shell.workspaces.space_for_handle_mut(&handle) else {
return;
@ -215,7 +234,7 @@ impl ScreencopyHandler for State {
workspace.add_cursor_session(session);
}
ImageCaptureSourceData::Toplevel(mut toplevel) => {
ImageCaptureSourceKind::Toplevel(mut toplevel) => {
let shell = self.common.shell.read();
if let Some(element) = shell.element_for_surface(&toplevel) {
if element.has_active_window(&toplevel) {
@ -238,38 +257,44 @@ impl ScreencopyHandler for State {
toplevel.add_cursor_session(session);
}
ImageCaptureSourceData::Destroyed => unreachable!(),
ImageCaptureSourceKind::Destroyed => unreachable!(),
}
}
fn frame(&mut self, session: SessionRef, frame: Frame) {
match session.source() {
ImageCaptureSourceData::Output(weak) => {
fn frame(&mut self, session: &SessionRef, frame: Frame) {
let kind = session
.source()
.user_data()
.get::<ImageCaptureSourceKind>()
.unwrap()
.clone();
match kind {
ImageCaptureSourceKind::Output(weak) => {
let Some(mut output) = weak.upgrade() else {
return;
};
output.add_frame(session, frame);
output.add_frame(session.clone(), frame);
self.backend.schedule_render(&output);
}
ImageCaptureSourceData::Workspace(handle) => {
ImageCaptureSourceKind::Workspace(handle) => {
render_workspace_to_buffer(self, session, frame, handle)
}
ImageCaptureSourceData::Toplevel(toplevel) => {
ImageCaptureSourceKind::Toplevel(toplevel) => {
render_window_to_buffer(self, session, frame, &toplevel)
}
ImageCaptureSourceData::Destroyed => unreachable!(),
ImageCaptureSourceKind::Destroyed => unreachable!(),
}
}
fn cursor_frame(&mut self, session: CursorSessionRef, frame: Frame) {
fn cursor_frame(&mut self, session: &CursorSessionRef, frame: Frame) {
if !session.has_cursor() {
frame.success(Transform::Normal, Vec::new(), self.common.clock.now());
return;
}
let seat = self.common.shell.read().seats.last_active().clone();
render_cursor_to_buffer(self, &session, frame, &seat);
render_cursor_to_buffer(self, session, frame, &seat);
}
fn frame_aborted(&mut self, frame: FrameRef) {
@ -280,13 +305,19 @@ impl ScreencopyHandler for State {
}
fn session_destroyed(&mut self, session: SessionRef) {
match session.source() {
ImageCaptureSourceData::Output(weak) => {
let kind = session
.source()
.user_data()
.get::<ImageCaptureSourceKind>()
.unwrap()
.clone();
match kind {
ImageCaptureSourceKind::Output(weak) => {
if let Some(mut output) = weak.upgrade() {
output.remove_session(&session);
}
}
ImageCaptureSourceData::Workspace(handle) => {
ImageCaptureSourceKind::Workspace(handle) => {
if let Some(workspace) = self
.common
.shell
@ -297,19 +328,25 @@ impl ScreencopyHandler for State {
workspace.remove_session(&session)
}
}
ImageCaptureSourceData::Toplevel(mut toplevel) => toplevel.remove_session(&session),
ImageCaptureSourceData::Destroyed => unreachable!(),
ImageCaptureSourceKind::Toplevel(mut toplevel) => toplevel.remove_session(&session),
ImageCaptureSourceKind::Destroyed => unreachable!(),
}
}
fn cursor_session_destroyed(&mut self, session: CursorSessionRef) {
match session.source() {
ImageCaptureSourceData::Output(weak) => {
let kind = session
.source()
.user_data()
.get::<ImageCaptureSourceKind>()
.unwrap()
.clone();
match kind {
ImageCaptureSourceKind::Output(weak) => {
if let Some(mut output) = weak.upgrade() {
output.remove_cursor_session(&session);
}
}
ImageCaptureSourceData::Workspace(handle) => {
ImageCaptureSourceKind::Workspace(handle) => {
if let Some(workspace) = self
.common
.shell
@ -320,10 +357,10 @@ impl ScreencopyHandler for State {
workspace.remove_cursor_session(&session)
}
}
ImageCaptureSourceData::Toplevel(mut toplevel) => {
ImageCaptureSourceKind::Toplevel(mut toplevel) => {
toplevel.remove_cursor_session(&session)
}
ImageCaptureSourceData::Destroyed => unreachable!(),
ImageCaptureSourceKind::Destroyed => unreachable!(),
}
}
}
@ -413,4 +450,4 @@ fn constraints_for_renderer(
constraints
}
delegate_screencopy!(State);
smithay::delegate_image_copy_capture!(State);

View file

@ -1,3 +1,5 @@
// SPDX-License-Identifier: GPL-3.0-only
use calloop::LoopHandle;
use smithay::{
backend::{
@ -26,6 +28,9 @@ use smithay::{
},
wayland::{
dmabuf::get_dmabuf,
image_copy_capture::{
BufferConstraints, CaptureFailureReason, CursorSessionRef, Frame, SessionRef,
},
seat::WaylandFocus,
shm::{shm_format_to_fourcc, with_buffer_contents, with_buffer_contents_mut},
},
@ -43,13 +48,10 @@ use crate::{
state::{Common, KmsNodes, State},
utils::prelude::{PointExt, PointGlobalExt, RectExt, RectLocalExt, SeatExt},
wayland::{
handlers::screencopy::{
handlers::image_copy_capture::{
SessionData, SessionUserData, constraints_for_output, constraints_for_toplevel,
},
protocols::{
screencopy::{BufferConstraints, CursorSessionRef, FailureReason, Frame, SessionRef},
workspace::WorkspaceHandle,
},
protocols::workspace::WorkspaceHandle,
},
};
@ -165,7 +167,7 @@ where
.map_err(|err| R::Error::from_gles_error(GlesError::BufferAccessError(err)))
.and_then(|x| x)
{
frame.fail(FailureReason::Unknown);
frame.fail(CaptureFailureReason::Unknown);
return Err(err);
}
}
@ -249,7 +251,7 @@ where
)
.map_err(DTError::Rendering),
Err(err) => {
frame.fail(FailureReason::Unknown);
frame.fail(CaptureFailureReason::Unknown);
Err(err)
}
}
@ -257,7 +259,7 @@ where
pub fn render_workspace_to_buffer(
state: &mut State,
session: SessionRef,
session: &SessionRef,
frame: Frame,
handle: WorkspaceHandle,
) {
@ -278,14 +280,14 @@ pub fn render_workspace_to_buffer(
let buffer_size = buffer_dimensions(&buffer).unwrap();
if mode != Some(buffer_size) {
let Some(constraints) = constraints_for_output(&output, &mut state.backend) else {
output.remove_session(&session);
output.remove_session(session);
return;
};
session.update_constraints(constraints);
if let Some(data) = session.user_data().get::<SessionData>() {
*data.lock().unwrap() = SessionUserData::new(OutputDamageTracker::from_output(&output));
}
frame.fail(FailureReason::BufferConstraints);
frame.fail(CaptureFailureReason::BufferConstraints);
return;
}
@ -414,7 +416,7 @@ pub fn render_workspace_to_buffer(
Ok(renderer) => renderer,
Err(err) => {
warn!(?err, "Couldn't use node for screencopy");
frame.fail(FailureReason::Unknown);
frame.fail(CaptureFailureReason::Unknown);
return;
}
};
@ -495,12 +497,12 @@ smithay::render_elements! {
pub fn render_window_to_buffer(
state: &mut State,
session: SessionRef,
session: &SessionRef,
frame: Frame,
toplevel: &CosmicSurface,
) {
if !toplevel.alive() {
toplevel.clone().remove_session(&session);
toplevel.clone().remove_session(session);
return;
}
@ -509,7 +511,7 @@ pub fn render_window_to_buffer(
let buffer_size = buffer_dimensions(&buffer).unwrap();
if buffer_size != geometry.size.to_buffer(1, Transform::Normal) {
let Some(constraints) = constraints_for_toplevel(toplevel, &mut state.backend) else {
toplevel.clone().remove_session(&session);
toplevel.clone().remove_session(session);
return;
};
session.update_constraints(constraints);
@ -518,7 +520,7 @@ pub fn render_window_to_buffer(
*data.lock().unwrap() =
SessionUserData::new(OutputDamageTracker::new(size, 1.0, Transform::Normal));
}
frame.fail(FailureReason::BufferConstraints);
frame.fail(CaptureFailureReason::BufferConstraints);
return;
}
@ -666,7 +668,7 @@ pub fn render_window_to_buffer(
Ok(renderer) => renderer,
Err(err) => {
warn!(?err, "Couldn't use node for screencopy");
frame.fail(FailureReason::Unknown);
frame.fail(CaptureFailureReason::Unknown);
return;
}
};
@ -760,7 +762,7 @@ pub fn render_cursor_to_buffer(
Transform::Normal,
));
}
frame.fail(FailureReason::BufferConstraints);
frame.fail(CaptureFailureReason::BufferConstraints);
return;
}
@ -826,7 +828,7 @@ pub fn render_cursor_to_buffer(
Ok(renderer) => renderer,
Err(err) => {
warn!(?err, "Couldn't use node for screencopy");
frame.fail(FailureReason::Unknown);
frame.fail(CaptureFailureReason::Unknown);
return;
}
};

View file

@ -1,20 +1,20 @@
// SPDX-License-Identifier: GPL-3.0-only
use std::{cell::RefCell, collections::HashMap, sync::Mutex};
use smithay::{
backend::renderer::{damage::OutputDamageTracker, utils::CommitCounter},
output::Output,
reexports::wayland_server::{Resource, Weak, protocol::wl_buffer::WlBuffer},
};
use crate::{
shell::{CosmicSurface, Workspace},
wayland::protocols::screencopy::{
wayland::image_copy_capture::{
CursorSession, CursorSessionRef, Frame, FrameRef, Session, SessionRef,
},
};
type ScreencopySessionsData = RefCell<ScreencopySessions>;
type PendingScreencopyBuffers = Mutex<Vec<(SessionRef, Frame)>>;
use crate::shell::{CosmicSurface, Workspace};
type ImageCopySessionsData = RefCell<ImageCopySessions>;
type PendingImageCopyBuffers = Mutex<Vec<(SessionRef, Frame)>>;
pub type SessionData = Mutex<SessionUserData>;
@ -54,7 +54,7 @@ impl SessionUserData {
}
#[derive(Debug, Default)]
pub struct ScreencopySessions {
pub struct ImageCopySessions {
sessions: Vec<Session>,
cursor_sessions: Vec<CursorSession>,
}
@ -78,9 +78,9 @@ pub trait FrameHolder {
impl SessionHolder for Output {
fn add_session(&mut self, session: Session) {
self.user_data()
.insert_if_missing(ScreencopySessionsData::default);
.insert_if_missing(ImageCopySessionsData::default);
self.user_data()
.get::<ScreencopySessionsData>()
.get::<ImageCopySessionsData>()
.unwrap()
.borrow_mut()
.sessions
@ -89,7 +89,7 @@ impl SessionHolder for Output {
fn remove_session(&mut self, session: &SessionRef) {
self.user_data()
.get::<ScreencopySessionsData>()
.get::<ImageCopySessionsData>()
.unwrap()
.borrow_mut()
.sessions
@ -98,7 +98,7 @@ impl SessionHolder for Output {
fn sessions(&self) -> Vec<SessionRef> {
self.user_data()
.get::<ScreencopySessionsData>()
.get::<ImageCopySessionsData>()
.map_or(Vec::new(), |sessions| {
sessions
.borrow()
@ -111,9 +111,9 @@ impl SessionHolder for Output {
fn add_cursor_session(&mut self, session: CursorSession) {
self.user_data()
.insert_if_missing(ScreencopySessionsData::default);
.insert_if_missing(ImageCopySessionsData::default);
self.user_data()
.get::<ScreencopySessionsData>()
.get::<ImageCopySessionsData>()
.unwrap()
.borrow_mut()
.cursor_sessions
@ -122,7 +122,7 @@ impl SessionHolder for Output {
fn remove_cursor_session(&mut self, session: &CursorSessionRef) {
self.user_data()
.get::<ScreencopySessionsData>()
.get::<ImageCopySessionsData>()
.unwrap()
.borrow_mut()
.cursor_sessions
@ -131,7 +131,7 @@ impl SessionHolder for Output {
fn cursor_sessions(&self) -> Vec<CursorSessionRef> {
self.user_data()
.get::<ScreencopySessionsData>()
.get::<ImageCopySessionsData>()
.map_or(Vec::new(), |sessions| {
sessions
.borrow()
@ -146,22 +146,22 @@ impl SessionHolder for Output {
impl FrameHolder for Output {
fn add_frame(&mut self, session: SessionRef, frame: Frame) {
self.user_data()
.insert_if_missing_threadsafe(PendingScreencopyBuffers::default);
.insert_if_missing_threadsafe(PendingImageCopyBuffers::default);
self.user_data()
.get::<PendingScreencopyBuffers>()
.get::<PendingImageCopyBuffers>()
.unwrap()
.lock()
.unwrap()
.push((session, frame));
}
fn remove_frame(&mut self, frame: &FrameRef) {
if let Some(pending) = self.user_data().get::<PendingScreencopyBuffers>() {
if let Some(pending) = self.user_data().get::<PendingImageCopyBuffers>() {
pending.lock().unwrap().retain(|(_, f)| f != frame);
}
}
fn take_pending_frames(&self) -> Vec<(SessionRef, Frame)> {
self.user_data()
.get::<PendingScreencopyBuffers>()
.get::<PendingImageCopyBuffers>()
.map(|pending| std::mem::take(&mut *pending.lock().unwrap()))
.unwrap_or_default()
}
@ -169,14 +169,14 @@ impl FrameHolder for Output {
impl SessionHolder for Workspace {
fn add_session(&mut self, session: Session) {
self.screencopy.sessions.push(session);
self.image_copy.sessions.push(session);
}
fn remove_session(&mut self, session: &SessionRef) {
self.screencopy.sessions.retain(|s| s != session);
self.image_copy.sessions.retain(|s| s != session);
}
fn sessions(&self) -> Vec<SessionRef> {
self.screencopy
self.image_copy
.sessions
.iter()
.map(|s| (*s).clone())
@ -184,14 +184,14 @@ impl SessionHolder for Workspace {
}
fn add_cursor_session(&mut self, session: CursorSession) {
self.screencopy.cursor_sessions.push(session);
self.image_copy.cursor_sessions.push(session);
}
fn remove_cursor_session(&mut self, session: &CursorSessionRef) {
self.screencopy.cursor_sessions.retain(|s| s != session);
self.image_copy.cursor_sessions.retain(|s| s != session);
}
fn cursor_sessions(&self) -> Vec<CursorSessionRef> {
self.screencopy
self.image_copy
.cursor_sessions
.iter()
.map(|s| (*s).clone())
@ -202,9 +202,9 @@ impl SessionHolder for Workspace {
impl SessionHolder for CosmicSurface {
fn add_session(&mut self, session: Session) {
self.user_data()
.insert_if_missing(ScreencopySessionsData::default);
.insert_if_missing(ImageCopySessionsData::default);
self.user_data()
.get::<ScreencopySessionsData>()
.get::<ImageCopySessionsData>()
.unwrap()
.borrow_mut()
.sessions
@ -213,7 +213,7 @@ impl SessionHolder for CosmicSurface {
fn remove_session(&mut self, session: &SessionRef) {
self.user_data()
.get::<ScreencopySessionsData>()
.get::<ImageCopySessionsData>()
.unwrap()
.borrow_mut()
.sessions
@ -221,7 +221,7 @@ impl SessionHolder for CosmicSurface {
}
fn sessions(&self) -> Vec<SessionRef> {
self.user_data()
.get::<ScreencopySessionsData>()
.get::<ImageCopySessionsData>()
.map_or(Vec::new(), |sessions| {
sessions
.borrow()
@ -234,9 +234,9 @@ impl SessionHolder for CosmicSurface {
fn add_cursor_session(&mut self, session: CursorSession) {
self.user_data()
.insert_if_missing(ScreencopySessionsData::default);
.insert_if_missing(ImageCopySessionsData::default);
self.user_data()
.get::<ScreencopySessionsData>()
.get::<ImageCopySessionsData>()
.unwrap()
.borrow_mut()
.cursor_sessions
@ -245,7 +245,7 @@ impl SessionHolder for CosmicSurface {
fn remove_cursor_session(&mut self, session: &CursorSessionRef) {
self.user_data()
.get::<ScreencopySessionsData>()
.get::<ImageCopySessionsData>()
.unwrap()
.borrow_mut()
.cursor_sessions
@ -254,7 +254,7 @@ impl SessionHolder for CosmicSurface {
fn cursor_sessions(&self) -> Vec<CursorSessionRef> {
self.user_data()
.get::<ScreencopySessionsData>()
.get::<ImageCopySessionsData>()
.map_or(Vec::new(), |sessions| {
sessions
.borrow()

View file

@ -17,6 +17,7 @@ pub mod fractional_scale;
pub mod idle_inhibit;
pub mod idle_notify;
pub mod image_capture_source;
pub mod image_copy_capture;
pub mod input_method;
pub mod keyboard_shortcuts_inhibit;
pub mod layer_shell;
@ -29,7 +30,6 @@ pub mod pointer_gestures;
pub mod presentation;
pub mod primary_selection;
pub mod relative_pointer;
pub mod screencopy;
pub mod seat;
pub mod security_context;
pub mod selection;

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: [