wip: screencopy
This commit is contained in:
parent
dd100d65e4
commit
5a4df346a8
26 changed files with 2046 additions and 327 deletions
|
|
@ -6,8 +6,10 @@ use std::{
|
|||
};
|
||||
|
||||
use cosmic_protocols::screencopy::v1::server::{
|
||||
zcosmic_screencopy_manager_v1::{self, CursorMode, ZcosmicScreencopyManagerV1},
|
||||
zcosmic_screencopy_session_v1::{self, FailureReason, InputType, ZcosmicScreencopySessionV1},
|
||||
zcosmic_screencopy_manager_v1::{self, CursorMode as WlCursorMode, ZcosmicScreencopyManagerV1},
|
||||
zcosmic_screencopy_session_v1::{
|
||||
self, BufferType, FailureReason, InputType, ZcosmicScreencopySessionV1,
|
||||
},
|
||||
};
|
||||
use smithay::{
|
||||
backend::{
|
||||
|
|
@ -15,15 +17,20 @@ use smithay::{
|
|||
drm::{DrmNode, NodeType},
|
||||
},
|
||||
desktop::Window,
|
||||
input::{Seat, SeatHandler},
|
||||
output::Output,
|
||||
reexports::wayland_server::{
|
||||
protocol::{
|
||||
wl_buffer::WlBuffer, wl_output::WlOutput, wl_seat::WlSeat, wl_shm::Format as ShmFormat,
|
||||
},
|
||||
protocol::{wl_buffer::WlBuffer, wl_output, wl_seat::WlSeat, wl_shm::Format as ShmFormat},
|
||||
Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New, Resource,
|
||||
},
|
||||
utils::{user_data::UserDataMap, Buffer, Point, Rectangle, Size, Transform},
|
||||
utils::{user_data::UserDataMap, Buffer, IsAlive, Physical, Point, Rectangle, Size, Transform},
|
||||
};
|
||||
use wayland_backend::{protocol::WEnum, server::GlobalId};
|
||||
use wayland_backend::{
|
||||
protocol::WEnum,
|
||||
server::{GlobalId, ObjectId},
|
||||
};
|
||||
|
||||
use crate::state::State;
|
||||
|
||||
use super::{
|
||||
toplevel_info::window_from_handle,
|
||||
|
|
@ -36,7 +43,7 @@ pub struct ScreencopyState {
|
|||
}
|
||||
|
||||
pub struct ScreencopyGlobalData {
|
||||
cursor_modes: Vec<CursorMode>,
|
||||
cursor_modes: Vec<WlCursorMode>,
|
||||
filter: Box<dyn for<'a> Fn(&'a Client) -> bool + Send + Sync>,
|
||||
}
|
||||
|
||||
|
|
@ -54,7 +61,7 @@ impl ScreencopyState {
|
|||
+ ScreencopyHandler
|
||||
+ WorkspaceHandler
|
||||
+ 'static,
|
||||
I: IntoIterator<Item = CursorMode>,
|
||||
I: IntoIterator<Item = WlCursorMode>,
|
||||
F: for<'a> Fn(&'a Client) -> bool + Send + Sync + 'static,
|
||||
{
|
||||
ScreencopyState {
|
||||
|
|
@ -92,6 +99,7 @@ pub enum BufferInfo {
|
|||
pub struct SessionDataInnerInner {
|
||||
gone: bool,
|
||||
pending_buffer: Option<BufferParams>,
|
||||
_type: SessionType,
|
||||
aux: AuxData,
|
||||
}
|
||||
|
||||
|
|
@ -104,12 +112,29 @@ impl SessionDataInnerInner {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum SessionType {
|
||||
Output(Output),
|
||||
Workspace(Output, WorkspaceHandle),
|
||||
Window(Window),
|
||||
Cursor(Seat<State>),
|
||||
#[doc(hidden)]
|
||||
Unknown,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum AuxData {
|
||||
Normal { cursor_sessions: Vec<CursorSession> },
|
||||
Normal { cursor: CursorMode },
|
||||
Cursor { seat: WlSeat },
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum CursorMode {
|
||||
Captured(Vec<CursorSession>),
|
||||
Embedded,
|
||||
None,
|
||||
}
|
||||
|
||||
impl AuxData {
|
||||
pub fn seat(&self) -> &WlSeat {
|
||||
match self {
|
||||
|
|
@ -118,10 +143,19 @@ impl AuxData {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn cursor_sessions(&self) -> &[CursorSession] {
|
||||
pub fn cursor(&self) -> &CursorMode {
|
||||
match self {
|
||||
AuxData::Normal { cursor_sessions } => &cursor_sessions,
|
||||
_ => unreachable!("Unwrapped cursor_session from aux data"),
|
||||
AuxData::Normal { cursor } => &cursor,
|
||||
_ => unreachable!("Unwrapped cursor from aux data"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CursorMode {
|
||||
pub fn sessions<'a>(&'a self) -> impl Iterator<Item = &'a CursorSession> {
|
||||
match self {
|
||||
CursorMode::Captured(sessions) => Some(sessions.iter()).into_iter().flatten(),
|
||||
_ => None.into_iter().flatten(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -136,65 +170,197 @@ pub type SessionData = Arc<SessionDataInner>;
|
|||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Session {
|
||||
obj: ZcosmicScreencopySessionV1,
|
||||
obj: SessionResource,
|
||||
data: SessionData,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
enum SessionResource {
|
||||
Alive(ZcosmicScreencopySessionV1),
|
||||
Destroyed(ObjectId),
|
||||
}
|
||||
|
||||
impl SessionResource {
|
||||
fn client(&self) -> Option<Client> {
|
||||
match self {
|
||||
SessionResource::Alive(obj) => obj.client(),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn buffer_info(
|
||||
&self,
|
||||
_type: BufferType,
|
||||
node: Option<String>,
|
||||
format: u32,
|
||||
width: u32,
|
||||
height: u32,
|
||||
stride: u32,
|
||||
) {
|
||||
if let SessionResource::Alive(obj) = self {
|
||||
obj.buffer_info(_type, node, format, width, height, stride)
|
||||
}
|
||||
}
|
||||
|
||||
fn init_done(&self) {
|
||||
if let SessionResource::Alive(obj) = self {
|
||||
obj.init_done()
|
||||
}
|
||||
}
|
||||
|
||||
fn transform(&self, transform: wl_output::Transform) {
|
||||
if let SessionResource::Alive(obj) = self {
|
||||
obj.transform(transform)
|
||||
}
|
||||
}
|
||||
|
||||
fn damage(&self, x: u32, y: u32, w: u32, h: u32) {
|
||||
if let SessionResource::Alive(obj) = self {
|
||||
obj.damage(x, y, w, h)
|
||||
}
|
||||
}
|
||||
|
||||
fn commit_time(&self, time_sec_hi: u32, time_sec_lo: u32, time_nsec: u32) {
|
||||
if let SessionResource::Alive(obj) = self {
|
||||
obj.commit_time(time_sec_hi, time_sec_lo, time_nsec)
|
||||
}
|
||||
}
|
||||
|
||||
fn ready(&self) {
|
||||
if let SessionResource::Alive(obj) = self {
|
||||
obj.ready()
|
||||
}
|
||||
}
|
||||
|
||||
fn failed(&self, reason: FailureReason) {
|
||||
if let SessionResource::Alive(obj) = self {
|
||||
obj.failed(reason)
|
||||
}
|
||||
}
|
||||
|
||||
fn cursor_enter(&self, wl_seat: &WlSeat, input_type: InputType) {
|
||||
if let SessionResource::Alive(obj) = self {
|
||||
obj.cursor_enter(wl_seat, input_type)
|
||||
}
|
||||
}
|
||||
|
||||
fn cursor_info(
|
||||
&self,
|
||||
wl_seat: &WlSeat,
|
||||
input_type: InputType,
|
||||
x: i32,
|
||||
y: i32,
|
||||
w: i32,
|
||||
h: i32,
|
||||
dx: i32,
|
||||
dy: i32,
|
||||
) {
|
||||
if let SessionResource::Alive(obj) = self {
|
||||
obj.cursor_info(wl_seat, input_type, x, y, w, h, dx, dy)
|
||||
}
|
||||
}
|
||||
|
||||
fn cursor_leave(&self, wl_seat: &WlSeat, input_type: InputType) {
|
||||
if let SessionResource::Alive(obj) = self {
|
||||
obj.cursor_leave(wl_seat, input_type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for SessionResource {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
match (self, other) {
|
||||
(SessionResource::Alive(obj1), SessionResource::Alive(obj2)) => obj1 == obj2,
|
||||
(SessionResource::Alive(obj), SessionResource::Destroyed(id))
|
||||
| (SessionResource::Destroyed(id), SessionResource::Alive(obj)) => obj.id() == *id,
|
||||
(SessionResource::Destroyed(id1), SessionResource::Destroyed(id2)) => id1 == id2,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Session {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.obj == other.obj
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Handle Alive
|
||||
|
||||
// TODO: Better errors
|
||||
|
||||
impl Session {
|
||||
pub fn cursor_enter(&self, seat: &WlSeat, input_type: InputType) {
|
||||
self.obj.cursor_enter(seat, input_type)
|
||||
pub fn cursor_enter<D: SeatHandler + 'static>(&self, seat: &Seat<D>, input_type: InputType) {
|
||||
if !self.alive() {
|
||||
return;
|
||||
}
|
||||
if let Some(client) = self.obj.client() {
|
||||
for wl_seat in seat.client_seats(&client) {
|
||||
self.obj.cursor_enter(&wl_seat, input_type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cursor_info(
|
||||
pub fn cursor_info<D: SeatHandler + 'static>(
|
||||
&self,
|
||||
seat: &WlSeat,
|
||||
seat: &Seat<D>,
|
||||
input_type: InputType,
|
||||
geometry: Rectangle<i32, Buffer>,
|
||||
offset: Point<i32, Buffer>,
|
||||
) {
|
||||
self.obj.cursor_info(
|
||||
seat,
|
||||
input_type,
|
||||
geometry.loc.x,
|
||||
geometry.loc.y,
|
||||
geometry.size.w,
|
||||
geometry.size.h,
|
||||
offset.x,
|
||||
offset.y,
|
||||
);
|
||||
let data = self.data.inner.lock().unwrap();
|
||||
for cursor_session in data.aux.cursor_sessions() {
|
||||
cursor_session.obj.cursor_info(
|
||||
seat,
|
||||
input_type,
|
||||
geometry.loc.x,
|
||||
geometry.loc.y,
|
||||
geometry.size.w,
|
||||
geometry.size.h,
|
||||
offset.x,
|
||||
offset.y,
|
||||
);
|
||||
if !self.alive() {
|
||||
return;
|
||||
}
|
||||
if let Some(client) = self.obj.client() {
|
||||
for wl_seat in seat.client_seats(&client) {
|
||||
self.obj.cursor_info(
|
||||
&wl_seat,
|
||||
input_type,
|
||||
geometry.loc.x,
|
||||
geometry.loc.y,
|
||||
geometry.size.w,
|
||||
geometry.size.h,
|
||||
offset.x,
|
||||
offset.y,
|
||||
);
|
||||
let data = self.data.inner.lock().unwrap();
|
||||
for cursor_session in data.aux.cursor().sessions() {
|
||||
cursor_session.obj.cursor_info(
|
||||
&wl_seat,
|
||||
input_type,
|
||||
geometry.loc.x,
|
||||
geometry.loc.y,
|
||||
geometry.size.w,
|
||||
geometry.size.h,
|
||||
offset.x,
|
||||
offset.y,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cursor_leave(&self, seat: &WlSeat, input_type: InputType) {
|
||||
self.obj.cursor_leave(seat, input_type)
|
||||
pub fn cursor_leave<D: SeatHandler + 'static>(&self, seat: &Seat<D>, input_type: InputType) {
|
||||
if !self.alive() {
|
||||
return;
|
||||
}
|
||||
if let Some(client) = self.obj.client() {
|
||||
for wl_seat in seat.client_seats(&client) {
|
||||
self.obj.cursor_leave(&wl_seat, input_type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cursor_sessions(&self) -> impl Iterator<Item = CursorSession> {
|
||||
if !self.alive() {
|
||||
return Vec::new().into_iter();
|
||||
}
|
||||
self.data
|
||||
.inner
|
||||
.lock()
|
||||
.unwrap()
|
||||
.aux
|
||||
.cursor_sessions()
|
||||
.iter()
|
||||
.cursor()
|
||||
.sessions()
|
||||
.cloned()
|
||||
.collect::<Vec<_>>()
|
||||
.into_iter()
|
||||
|
|
@ -203,9 +369,12 @@ impl Session {
|
|||
pub fn commit_buffer(
|
||||
&self,
|
||||
transform: Transform,
|
||||
damage: Vec<Rectangle<i32, Buffer>>,
|
||||
damage: Vec<Rectangle<i32, Physical>>,
|
||||
time: Option<Duration>,
|
||||
) {
|
||||
if !self.alive() {
|
||||
return;
|
||||
}
|
||||
self.obj.transform(transform.into());
|
||||
for rect in damage {
|
||||
self.obj.damage(
|
||||
|
|
@ -225,6 +394,9 @@ impl Session {
|
|||
}
|
||||
|
||||
pub fn failed(&self, reason: FailureReason) {
|
||||
if !self.alive() {
|
||||
return;
|
||||
}
|
||||
self.obj.failed(reason);
|
||||
self.data.inner.lock().unwrap().gone = true;
|
||||
}
|
||||
|
|
@ -232,11 +404,25 @@ impl Session {
|
|||
pub fn user_data(&self) -> &UserDataMap {
|
||||
&self.data.user_data
|
||||
}
|
||||
|
||||
pub fn session_type(&self) -> SessionType {
|
||||
self.data.inner.lock().unwrap()._type.clone()
|
||||
}
|
||||
|
||||
pub fn cursor_mode(&self) -> CursorMode {
|
||||
self.data.inner.lock().unwrap().aux.cursor().clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl IsAlive for Session {
|
||||
fn alive(&self) -> bool {
|
||||
!self.data.inner.lock().unwrap().gone
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CursorSession {
|
||||
obj: ZcosmicScreencopySessionV1,
|
||||
obj: SessionResource,
|
||||
data: SessionData,
|
||||
}
|
||||
|
||||
|
|
@ -281,7 +467,13 @@ impl CursorSession {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
impl IsAlive for CursorSession {
|
||||
fn alive(&self) -> bool {
|
||||
!self.data.inner.lock().unwrap().gone
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct BufferParams {
|
||||
pub buffer: WlBuffer,
|
||||
pub node: Option<DrmNode>,
|
||||
|
|
@ -289,33 +481,28 @@ pub struct BufferParams {
|
|||
}
|
||||
|
||||
pub trait ScreencopyHandler {
|
||||
fn capture_output(
|
||||
&mut self,
|
||||
output: WlOutput,
|
||||
cursor: CursorMode,
|
||||
session: Session,
|
||||
) -> Vec<BufferInfo>;
|
||||
fn capture_output(&mut self, output: Output, session: Session) -> Vec<BufferInfo>;
|
||||
|
||||
fn capture_workspace(
|
||||
&mut self,
|
||||
workspace: WorkspaceHandle,
|
||||
output: WlOutput,
|
||||
cursor: CursorMode,
|
||||
output: Output,
|
||||
session: Session,
|
||||
) -> Vec<BufferInfo>;
|
||||
|
||||
fn capture_toplevel(
|
||||
&mut self,
|
||||
toplevel: Window,
|
||||
cursor: CursorMode,
|
||||
session: Session,
|
||||
) -> Vec<BufferInfo>;
|
||||
fn capture_toplevel(&mut self, toplevel: Window, session: Session) -> Vec<BufferInfo>;
|
||||
|
||||
fn capture_cursor(&mut self, session: CursorSession) -> Vec<BufferInfo>;
|
||||
|
||||
fn buffer_attached(&mut self, session: Session, buffer: BufferParams, on_damage: bool);
|
||||
|
||||
fn session_destroyed(&mut self, session: Session);
|
||||
fn cursor_session_destroyed(&mut self, session: CursorSession) {
|
||||
let _ = session;
|
||||
}
|
||||
|
||||
fn session_destroyed(&mut self, session: Session) {
|
||||
let _ = session;
|
||||
}
|
||||
}
|
||||
|
||||
impl<D> GlobalDispatch<ZcosmicScreencopyManagerV1, ScreencopyGlobalData, D> for ScreencopyState
|
||||
|
|
@ -349,8 +536,9 @@ where
|
|||
fn init_session<D>(
|
||||
data_init: &mut DataInit<'_, D>,
|
||||
session: New<ZcosmicScreencopySessionV1>,
|
||||
cursor: WEnum<CursorMode>,
|
||||
) -> Option<(Session, CursorMode)>
|
||||
cursor: WEnum<WlCursorMode>,
|
||||
_type: SessionType,
|
||||
) -> Option<Session>
|
||||
where
|
||||
D: GlobalDispatch<ZcosmicScreencopyManagerV1, ScreencopyGlobalData>
|
||||
+ Dispatch<ZcosmicScreencopyManagerV1, ()>
|
||||
|
|
@ -364,25 +552,29 @@ where
|
|||
gone: false,
|
||||
pending_buffer: None,
|
||||
aux: AuxData::Normal {
|
||||
cursor_sessions: Vec::new(),
|
||||
cursor: match cursor.into_result() {
|
||||
Ok(WlCursorMode::Capture) => CursorMode::Captured(Vec::new()),
|
||||
Ok(WlCursorMode::Embedded) => CursorMode::Embedded,
|
||||
_ => CursorMode::None,
|
||||
},
|
||||
},
|
||||
_type,
|
||||
}),
|
||||
user_data: UserDataMap::new(),
|
||||
});
|
||||
let session = data_init.init(session, data.clone());
|
||||
|
||||
let cursor_mode = match cursor.into_result() {
|
||||
Ok(mode) => mode,
|
||||
Err(err) => {
|
||||
slog_scope::warn!("Client did send unknown cursor mode: {}", err);
|
||||
session.failed(FailureReason::UnknownInput);
|
||||
return None;
|
||||
}
|
||||
if let Err(err) = cursor.into_result() {
|
||||
slog_scope::warn!("Client did send unknown cursor mode: {}", err);
|
||||
session.failed(FailureReason::UnknownInput);
|
||||
return None;
|
||||
};
|
||||
let session = Session {
|
||||
obj: SessionResource::Alive(session),
|
||||
data,
|
||||
};
|
||||
|
||||
let session = Session { obj: session, data };
|
||||
|
||||
Some((session, cursor_mode))
|
||||
Some(session)
|
||||
}
|
||||
|
||||
impl<D> Dispatch<ZcosmicScreencopyManagerV1, (), D> for ScreencopyState
|
||||
|
|
@ -408,68 +600,119 @@ where
|
|||
session,
|
||||
output,
|
||||
cursor,
|
||||
} => {
|
||||
let (session, cursor_mode) = match init_session(data_init, session, cursor) {
|
||||
Some(result) => result,
|
||||
None => {
|
||||
return;
|
||||
} => match Output::from_resource(&output) {
|
||||
Some(output) => {
|
||||
let session = match init_session(
|
||||
data_init,
|
||||
session,
|
||||
cursor,
|
||||
SessionType::Output(output.clone()),
|
||||
) {
|
||||
Some(result) => result,
|
||||
None => {
|
||||
return;
|
||||
}
|
||||
};
|
||||
let formats = state.capture_output(output, session.clone());
|
||||
if !session.data.inner.lock().unwrap().gone {
|
||||
send_formats(&session.obj, formats);
|
||||
}
|
||||
};
|
||||
let formats = state.capture_output(output, cursor_mode, session.clone());
|
||||
if !session.data.inner.lock().unwrap().gone {
|
||||
send_formats(&session.obj, formats);
|
||||
}
|
||||
}
|
||||
None => {
|
||||
let session =
|
||||
match init_session(data_init, session, cursor, SessionType::Unknown) {
|
||||
Some(result) => result,
|
||||
None => {
|
||||
return;
|
||||
}
|
||||
};
|
||||
session.failed(FailureReason::InvalidOutput);
|
||||
return;
|
||||
}
|
||||
},
|
||||
zcosmic_screencopy_manager_v1::Request::CaptureToplevel {
|
||||
session,
|
||||
toplevel,
|
||||
cursor,
|
||||
} => {
|
||||
let (session, cursor_mode) = match init_session(data_init, session, cursor) {
|
||||
Some(result) => result,
|
||||
None => {
|
||||
return;
|
||||
}
|
||||
};
|
||||
match window_from_handle(toplevel) {
|
||||
Some(window) => {
|
||||
let formats = state.capture_toplevel(window, cursor_mode, session.clone());
|
||||
if !session.data.inner.lock().unwrap().gone {
|
||||
send_formats(&session.obj, formats);
|
||||
} => match window_from_handle(toplevel) {
|
||||
Some(window) => {
|
||||
let session = match init_session(
|
||||
data_init,
|
||||
session,
|
||||
cursor,
|
||||
SessionType::Window(window.clone()),
|
||||
) {
|
||||
Some(result) => result,
|
||||
None => {
|
||||
return;
|
||||
}
|
||||
}
|
||||
None => {
|
||||
session.obj.failed(FailureReason::ToplevelDestroyed);
|
||||
return;
|
||||
};
|
||||
|
||||
let formats = state.capture_toplevel(window, session.clone());
|
||||
if !session.data.inner.lock().unwrap().gone {
|
||||
send_formats(&session.obj, formats);
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {
|
||||
let session =
|
||||
match init_session(data_init, session, cursor, SessionType::Unknown) {
|
||||
Some(result) => result,
|
||||
None => {
|
||||
return;
|
||||
}
|
||||
};
|
||||
session.obj.failed(FailureReason::ToplevelDestroyed);
|
||||
return;
|
||||
}
|
||||
},
|
||||
zcosmic_screencopy_manager_v1::Request::CaptureWorkspace {
|
||||
session,
|
||||
workspace,
|
||||
output,
|
||||
cursor,
|
||||
} => {
|
||||
let (session, cursor_mode) = match init_session(data_init, session, cursor) {
|
||||
Some(result) => result,
|
||||
None => {
|
||||
return;
|
||||
}
|
||||
};
|
||||
match state.workspace_state().workspace_handle(&workspace) {
|
||||
} => match Output::from_resource(&output) {
|
||||
Some(output) => match state.workspace_state().workspace_handle(&workspace) {
|
||||
Some(handle) => {
|
||||
let formats =
|
||||
state.capture_workspace(handle, output, cursor_mode, session.clone());
|
||||
let session = match init_session(
|
||||
data_init,
|
||||
session,
|
||||
cursor,
|
||||
SessionType::Workspace(output.clone(), handle.clone()),
|
||||
) {
|
||||
Some(result) => result,
|
||||
None => {
|
||||
return;
|
||||
}
|
||||
};
|
||||
let formats = state.capture_workspace(handle, output, session.clone());
|
||||
if !session.data.inner.lock().unwrap().gone {
|
||||
send_formats(&session.obj, formats);
|
||||
}
|
||||
}
|
||||
None => {
|
||||
let session =
|
||||
match init_session(data_init, session, cursor, SessionType::Unknown) {
|
||||
Some(result) => result,
|
||||
None => {
|
||||
return;
|
||||
}
|
||||
};
|
||||
session.failed(FailureReason::InvalidOutput);
|
||||
return;
|
||||
}
|
||||
},
|
||||
None => {
|
||||
let session =
|
||||
match init_session(data_init, session, cursor, SessionType::Unknown) {
|
||||
Some(result) => result,
|
||||
None => {
|
||||
return;
|
||||
}
|
||||
};
|
||||
session.failed(FailureReason::InvalidOutput);
|
||||
return;
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
@ -481,6 +724,7 @@ where
|
|||
+ Dispatch<ZcosmicScreencopyManagerV1, ()>
|
||||
+ Dispatch<ZcosmicScreencopySessionV1, SessionData>
|
||||
+ ScreencopyHandler
|
||||
+ WorkspaceHandler
|
||||
+ 'static,
|
||||
{
|
||||
fn request(
|
||||
|
|
@ -493,31 +737,55 @@ where
|
|||
data_init: &mut DataInit<'_, D>,
|
||||
) {
|
||||
match request {
|
||||
zcosmic_screencopy_session_v1::Request::CaptureCursor { session, seat } => {
|
||||
{
|
||||
let resource_data = data.inner.lock().unwrap();
|
||||
if resource_data.is_cursor() || resource_data.gone {
|
||||
resource.failed(FailureReason::Unspec);
|
||||
return;
|
||||
zcosmic_screencopy_session_v1::Request::CaptureCursor {
|
||||
session,
|
||||
seat: wl_seat,
|
||||
} => match Seat::from_resource(&wl_seat) {
|
||||
Some(seat) => {
|
||||
{
|
||||
let resource_data = data.inner.lock().unwrap();
|
||||
if resource_data.is_cursor() || resource_data.gone {
|
||||
resource.failed(FailureReason::Unspec);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let data = Arc::new(SessionDataInner {
|
||||
inner: Mutex::new(SessionDataInnerInner {
|
||||
gone: false,
|
||||
pending_buffer: None,
|
||||
aux: AuxData::Cursor { seat: wl_seat },
|
||||
_type: SessionType::Cursor(seat),
|
||||
}),
|
||||
user_data: UserDataMap::new(),
|
||||
});
|
||||
let session = data_init.init(session, data.clone());
|
||||
|
||||
let cursor_session = CursorSession {
|
||||
obj: SessionResource::Alive(session),
|
||||
data,
|
||||
};
|
||||
let formats = state.capture_cursor(cursor_session.clone());
|
||||
if !cursor_session.data.inner.lock().unwrap().gone {
|
||||
send_formats(&cursor_session.obj, formats);
|
||||
}
|
||||
}
|
||||
|
||||
let data = Arc::new(SessionDataInner {
|
||||
inner: Mutex::new(SessionDataInnerInner {
|
||||
gone: false,
|
||||
pending_buffer: None,
|
||||
aux: AuxData::Cursor { seat },
|
||||
}),
|
||||
user_data: UserDataMap::new(),
|
||||
});
|
||||
let session = data_init.init(session, data.clone());
|
||||
|
||||
let cursor_session = CursorSession { obj: session, data };
|
||||
let formats = state.capture_cursor(cursor_session.clone());
|
||||
if !cursor_session.data.inner.lock().unwrap().gone {
|
||||
send_formats(&cursor_session.obj, formats);
|
||||
None => {
|
||||
let session = match init_session(
|
||||
data_init,
|
||||
session,
|
||||
WEnum::Value(WlCursorMode::Capture),
|
||||
SessionType::Unknown,
|
||||
) {
|
||||
Some(result) => result,
|
||||
None => {
|
||||
return;
|
||||
}
|
||||
};
|
||||
session.failed(FailureReason::UnknownInput);
|
||||
return;
|
||||
}
|
||||
}
|
||||
},
|
||||
zcosmic_screencopy_session_v1::Request::AttachBuffer { buffer, node, age } => {
|
||||
if data.inner.lock().unwrap().gone {
|
||||
resource.failed(FailureReason::Unspec);
|
||||
|
|
@ -541,7 +809,7 @@ where
|
|||
|
||||
if let Some(buffer) = data.inner.lock().unwrap().pending_buffer.take() {
|
||||
let session = Session {
|
||||
obj: resource.clone(),
|
||||
obj: SessionResource::Alive(resource.clone()),
|
||||
data: data.clone(),
|
||||
};
|
||||
state.buffer_attached(
|
||||
|
|
@ -563,9 +831,30 @@ where
|
|||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn destroyed(
|
||||
state: &mut D,
|
||||
_client: wayland_backend::server::ClientId,
|
||||
resource: wayland_backend::server::ObjectId,
|
||||
data: &SessionData,
|
||||
) {
|
||||
if data.inner.lock().unwrap().is_cursor() {
|
||||
let session = CursorSession {
|
||||
obj: SessionResource::Destroyed(resource),
|
||||
data: data.clone(),
|
||||
};
|
||||
state.cursor_session_destroyed(session)
|
||||
} else {
|
||||
let session = Session {
|
||||
obj: SessionResource::Destroyed(resource),
|
||||
data: data.clone(),
|
||||
};
|
||||
state.session_destroyed(session)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn send_formats(session: &ZcosmicScreencopySessionV1, formats: Vec<BufferInfo>) {
|
||||
fn send_formats(session: &SessionResource, formats: Vec<BufferInfo>) {
|
||||
for format in formats {
|
||||
match format {
|
||||
BufferInfo::Dmabuf { node, format, size } => {
|
||||
|
|
|
|||
|
|
@ -413,9 +413,9 @@ fn send_toplevel_to_client<D>(
|
|||
.iter()
|
||||
.filter(|o| !handle_state.outputs.contains(o))
|
||||
{
|
||||
new_output.with_client_outputs(&client, |wl_output| {
|
||||
instance.output_enter(wl_output);
|
||||
});
|
||||
for wl_output in new_output.client_outputs(&client) {
|
||||
instance.output_enter(&wl_output);
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
for old_output in handle_state
|
||||
|
|
@ -423,9 +423,9 @@ fn send_toplevel_to_client<D>(
|
|||
.iter()
|
||||
.filter(|o| !state.outputs.contains(o))
|
||||
{
|
||||
old_output.with_client_outputs(&client, |wl_output| {
|
||||
instance.output_leave(wl_output);
|
||||
});
|
||||
for wl_output in old_output.client_outputs(&client) {
|
||||
instance.output_leave(&wl_output);
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
handle_state.outputs = state.outputs.clone();
|
||||
|
|
|
|||
|
|
@ -182,12 +182,12 @@ where
|
|||
let window = window_from_handle(toplevel).unwrap();
|
||||
if let Some(toplevel_state) = window.user_data().get::<ToplevelState>() {
|
||||
let mut toplevel_state = toplevel_state.lock().unwrap();
|
||||
if let Some(client) = surface.client_id() {
|
||||
if let Some(client) = surface.client() {
|
||||
if width == 0 && height == 0 {
|
||||
toplevel_state.rectangles.remove(&client);
|
||||
toplevel_state.rectangles.remove(&client.id());
|
||||
} else {
|
||||
toplevel_state.rectangles.insert(
|
||||
client,
|
||||
client.id(),
|
||||
(
|
||||
surface,
|
||||
Rectangle::from_loc_and_size((x, y), (width, height)),
|
||||
|
|
@ -207,7 +207,7 @@ where
|
|||
if !mng_state
|
||||
.instances
|
||||
.iter()
|
||||
.any(|i| i.client_id().map(|c| c == client).unwrap_or(false))
|
||||
.any(|i| i.client().map(|c| c.id() == client).unwrap_or(false))
|
||||
{
|
||||
for toplevel in state.toplevel_info_state_mut().toplevels.iter() {
|
||||
if let Some(toplevel_state) = toplevel.user_data().get::<ToplevelState>() {
|
||||
|
|
|
|||
|
|
@ -821,9 +821,9 @@ where
|
|||
.iter()
|
||||
.filter(|o| !handle_state.outputs.contains(o))
|
||||
{
|
||||
new_output.with_client_outputs(&client, |wl_output| {
|
||||
instance.output_enter(wl_output);
|
||||
});
|
||||
for wl_output in new_output.client_outputs(&client) {
|
||||
instance.output_enter(&wl_output);
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
for old_output in handle_state
|
||||
|
|
@ -831,9 +831,9 @@ where
|
|||
.iter()
|
||||
.filter(|o| !group.outputs.contains(o))
|
||||
{
|
||||
old_output.with_client_outputs(&client, |wl_output| {
|
||||
instance.output_leave(wl_output);
|
||||
});
|
||||
for wl_output in old_output.client_outputs(&client) {
|
||||
instance.output_leave(&wl_output);
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
handle_state.outputs = group.outputs.clone();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue