cosmic-screencopy-v2 (#288)
This commit is contained in:
parent
608d7837b5
commit
8128b6cf89
3 changed files with 241 additions and 194 deletions
318
Cargo.lock
generated
318
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
|
@ -21,10 +21,10 @@ resolver = "2"
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
anyhow = "1.0.81"
|
anyhow = "1.0.81"
|
||||||
cctk = { git = "https://github.com/pop-os/cosmic-protocols", package = "cosmic-client-toolkit", rev = "e65fa5e" }
|
cctk = { git = "https://github.com/pop-os/cosmic-protocols", package = "cosmic-client-toolkit", rev = "1cc4a13" }
|
||||||
cosmic-protocols = { git = "https://github.com/pop-os/cosmic-protocols", default-features = false, features = [
|
cosmic-protocols = { git = "https://github.com/pop-os/cosmic-protocols", default-features = false, features = [
|
||||||
"client",
|
"client",
|
||||||
], rev = "e65fa5e" }
|
], rev = "1cc4a13" }
|
||||||
cosmic-time = { git = "https://github.com/pop-os/cosmic-time", default-features = false, features = [
|
cosmic-time = { git = "https://github.com/pop-os/cosmic-time", default-features = false, features = [
|
||||||
"libcosmic",
|
"libcosmic",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
|
|
||||||
|
|
@ -24,14 +24,16 @@ use cosmic::{
|
||||||
self,
|
self,
|
||||||
cosmic_protocols::{
|
cosmic_protocols::{
|
||||||
self,
|
self,
|
||||||
screencopy::v1::client::{
|
image_source::v1::client::zcosmic_toplevel_image_source_manager_v1::ZcosmicToplevelImageSourceManagerV1,
|
||||||
zcosmic_screencopy_manager_v1, zcosmic_screencopy_session_v1,
|
screencopy::v2::client::{
|
||||||
|
zcosmic_screencopy_frame_v2, zcosmic_screencopy_manager_v2,
|
||||||
|
zcosmic_screencopy_session_v2,
|
||||||
},
|
},
|
||||||
toplevel_info::v1::client::zcosmic_toplevel_handle_v1::ZcosmicToplevelHandleV1,
|
toplevel_info::v1::client::zcosmic_toplevel_handle_v1::ZcosmicToplevelHandleV1,
|
||||||
},
|
},
|
||||||
screencopy::{
|
screencopy::{
|
||||||
BufferInfo, ScreencopyHandler, ScreencopySessionData, ScreencopySessionDataExt,
|
capture, Formats, Frame, ScreencopyFrameData, ScreencopyFrameDataExt,
|
||||||
ScreencopyState,
|
ScreencopyHandler, ScreencopySessionData, ScreencopySessionDataExt, ScreencopyState,
|
||||||
},
|
},
|
||||||
sctk::shm::{Shm, ShmHandler},
|
sctk::shm::{Shm, ShmHandler},
|
||||||
wayland_client::{
|
wayland_client::{
|
||||||
|
|
@ -55,8 +57,8 @@ use wayland_client::{globals::registry_queue_init, Connection, QueueHandle};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct SessionInner {
|
struct SessionInner {
|
||||||
buffer_infos: Option<Vec<BufferInfo>>,
|
formats: Option<Formats>,
|
||||||
res: Option<Result<(), WEnum<zcosmic_screencopy_session_v1::FailureReason>>>,
|
res: Option<Result<(), WEnum<zcosmic_screencopy_frame_v2::FailureReason>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: dmabuf? need to handle modifier negotation
|
// TODO: dmabuf? need to handle modifier negotation
|
||||||
|
|
@ -72,9 +74,14 @@ struct SessionData {
|
||||||
session_data: ScreencopySessionData,
|
session_data: ScreencopySessionData,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct FrameData {
|
||||||
|
frame_data: ScreencopyFrameData,
|
||||||
|
session: zcosmic_screencopy_session_v2::ZcosmicScreencopySessionV2,
|
||||||
|
}
|
||||||
|
|
||||||
impl Session {
|
impl Session {
|
||||||
pub fn for_session(
|
pub fn for_session(
|
||||||
session: &zcosmic_screencopy_session_v1::ZcosmicScreencopySessionV1,
|
session: &zcosmic_screencopy_session_v2::ZcosmicScreencopySessionV2,
|
||||||
) -> Option<&Self> {
|
) -> Option<&Self> {
|
||||||
Some(&session.data::<SessionData>()?.session)
|
Some(&session.data::<SessionData>()?.session)
|
||||||
}
|
}
|
||||||
|
|
@ -96,6 +103,13 @@ impl ScreencopySessionDataExt for SessionData {
|
||||||
&self.session_data
|
&self.session_data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ScreencopyFrameDataExt for FrameData {
|
||||||
|
fn screencopy_frame_data(&self) -> &ScreencopyFrameData {
|
||||||
|
&self.frame_data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct AppData {
|
struct AppData {
|
||||||
exit: bool,
|
exit: bool,
|
||||||
tx: UnboundedSender<WaylandUpdate>,
|
tx: UnboundedSender<WaylandUpdate>,
|
||||||
|
|
@ -113,7 +127,8 @@ struct CaptureData {
|
||||||
qh: QueueHandle<AppData>,
|
qh: QueueHandle<AppData>,
|
||||||
conn: Connection,
|
conn: Connection,
|
||||||
wl_shm: WlShm,
|
wl_shm: WlShm,
|
||||||
screencopy_manager: zcosmic_screencopy_manager_v1::ZcosmicScreencopyManagerV1,
|
screencopy_manager: zcosmic_screencopy_manager_v2::ZcosmicScreencopyManagerV2,
|
||||||
|
toplevel_source_manager: ZcosmicToplevelImageSourceManagerV1,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CaptureData {
|
impl CaptureData {
|
||||||
|
|
@ -131,9 +146,12 @@ impl CaptureData {
|
||||||
let overlay_cursor = if overlay_cursor { 1 } else { 0 };
|
let overlay_cursor = if overlay_cursor { 1 } else { 0 };
|
||||||
|
|
||||||
let session = Arc::new(Session::default());
|
let session = Arc::new(Session::default());
|
||||||
let screencopy_session = self.screencopy_manager.capture_toplevel(
|
let image_source = self
|
||||||
&source,
|
.toplevel_source_manager
|
||||||
zcosmic_screencopy_manager_v1::CursorMode::Hidden, // XXX take into account adventised capabilities
|
.create_source(&source, &self.qh, ());
|
||||||
|
let screencopy_session = self.screencopy_manager.create_session(
|
||||||
|
&image_source,
|
||||||
|
zcosmic_screencopy_manager_v2::Options::empty(),
|
||||||
&self.qh,
|
&self.qh,
|
||||||
SessionData {
|
SessionData {
|
||||||
session: session.clone(),
|
session: session.clone(),
|
||||||
|
|
@ -142,23 +160,24 @@ impl CaptureData {
|
||||||
);
|
);
|
||||||
self.conn.flush().unwrap();
|
self.conn.flush().unwrap();
|
||||||
|
|
||||||
let buffer_infos = session
|
let formats = session
|
||||||
.wait_while(|data| data.buffer_infos.is_none())
|
.wait_while(|data| data.formats.is_none())
|
||||||
.buffer_infos
|
.formats
|
||||||
.take()
|
.take()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
let (width, height) = formats.buffer_size;
|
||||||
|
|
||||||
// XXX
|
// XXX
|
||||||
let Some(buffer_info) = buffer_infos.iter().find(|x| {
|
if !formats
|
||||||
x.type_ == WEnum::Value(zcosmic_screencopy_session_v1::BufferType::WlShm)
|
.shm_formats
|
||||||
&& x.format == wl_shm::Format::Abgr8888.into()
|
.contains(&wl_shm::Format::Abgr8888.into())
|
||||||
}) else {
|
{
|
||||||
tracing::error!("No suitable buffer format found");
|
tracing::error!("No suitable buffer format found");
|
||||||
tracing::warn!("Available formats: {:#?}", buffer_infos);
|
tracing::warn!("Available formats: {:#?}", formats);
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
|
|
||||||
let buf_len = buffer_info.stride * buffer_info.height;
|
let buf_len = width * height * 4;
|
||||||
if let Some(len) = len {
|
if let Some(len) = len {
|
||||||
if len != buf_len {
|
if len != buf_len {
|
||||||
return None;
|
return None;
|
||||||
|
|
@ -170,16 +189,24 @@ impl CaptureData {
|
||||||
.create_pool(fd.as_fd(), buf_len as i32, &self.qh, ());
|
.create_pool(fd.as_fd(), buf_len as i32, &self.qh, ());
|
||||||
let buffer = pool.create_buffer(
|
let buffer = pool.create_buffer(
|
||||||
0,
|
0,
|
||||||
buffer_info.width as i32,
|
width as i32,
|
||||||
buffer_info.height as i32,
|
height as i32,
|
||||||
buffer_info.stride as i32,
|
width as i32 * 4,
|
||||||
wl_shm::Format::Abgr8888,
|
wl_shm::Format::Abgr8888,
|
||||||
&self.qh,
|
&self.qh,
|
||||||
(),
|
(),
|
||||||
);
|
);
|
||||||
|
|
||||||
screencopy_session.attach_buffer(&buffer, None, 0); // XXX age?
|
capture(
|
||||||
screencopy_session.commit(zcosmic_screencopy_session_v1::Options::empty());
|
&screencopy_session,
|
||||||
|
&buffer,
|
||||||
|
&[],
|
||||||
|
&self.qh,
|
||||||
|
FrameData {
|
||||||
|
frame_data: Default::default(),
|
||||||
|
session: screencopy_session.clone(),
|
||||||
|
},
|
||||||
|
);
|
||||||
self.conn.flush().unwrap();
|
self.conn.flush().unwrap();
|
||||||
|
|
||||||
// TODO: wait for server to release buffer?
|
// TODO: wait for server to release buffer?
|
||||||
|
|
@ -194,11 +221,7 @@ impl CaptureData {
|
||||||
//std::thread::sleep(std::time::Duration::from_millis(16));
|
//std::thread::sleep(std::time::Duration::from_millis(16));
|
||||||
|
|
||||||
if res.is_ok() {
|
if res.is_ok() {
|
||||||
Some(ShmImage {
|
Some(ShmImage { fd, width, height })
|
||||||
fd,
|
|
||||||
width: buffer_info.width,
|
|
||||||
height: buffer_info.height,
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
@ -277,6 +300,11 @@ impl AppData {
|
||||||
conn: self.conn.clone(),
|
conn: self.conn.clone(),
|
||||||
wl_shm: self.shm_state.wl_shm().clone(),
|
wl_shm: self.shm_state.wl_shm().clone(),
|
||||||
screencopy_manager: self.screencopy_state.screencopy_manager.clone(),
|
screencopy_manager: self.screencopy_state.screencopy_manager.clone(),
|
||||||
|
toplevel_source_manager: self
|
||||||
|
.screencopy_state
|
||||||
|
.toplevel_source_manager
|
||||||
|
.clone()
|
||||||
|
.unwrap(),
|
||||||
};
|
};
|
||||||
std::thread::spawn(move || {
|
std::thread::spawn(move || {
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
|
|
@ -488,11 +516,11 @@ impl ScreencopyHandler for AppData {
|
||||||
&mut self,
|
&mut self,
|
||||||
_conn: &Connection,
|
_conn: &Connection,
|
||||||
_qh: &QueueHandle<Self>,
|
_qh: &QueueHandle<Self>,
|
||||||
session: &zcosmic_screencopy_session_v1::ZcosmicScreencopySessionV1,
|
session: &zcosmic_screencopy_session_v2::ZcosmicScreencopySessionV2,
|
||||||
buffer_infos: &[BufferInfo],
|
formats: &Formats,
|
||||||
) {
|
) {
|
||||||
Session::for_session(session).unwrap().update(|data| {
|
Session::for_session(session).unwrap().update(|data| {
|
||||||
data.buffer_infos = Some(buffer_infos.to_vec());
|
data.formats = Some(formats.clone());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -500,8 +528,10 @@ impl ScreencopyHandler for AppData {
|
||||||
&mut self,
|
&mut self,
|
||||||
_conn: &Connection,
|
_conn: &Connection,
|
||||||
_qh: &QueueHandle<Self>,
|
_qh: &QueueHandle<Self>,
|
||||||
session: &zcosmic_screencopy_session_v1::ZcosmicScreencopySessionV1,
|
screencopy_frame: &zcosmic_screencopy_frame_v2::ZcosmicScreencopyFrameV2,
|
||||||
|
_frame: Frame,
|
||||||
) {
|
) {
|
||||||
|
let session = &screencopy_frame.data::<FrameData>().unwrap().session;
|
||||||
Session::for_session(session).unwrap().update(|data| {
|
Session::for_session(session).unwrap().update(|data| {
|
||||||
data.res = Some(Ok(()));
|
data.res = Some(Ok(()));
|
||||||
});
|
});
|
||||||
|
|
@ -512,15 +542,24 @@ impl ScreencopyHandler for AppData {
|
||||||
&mut self,
|
&mut self,
|
||||||
_conn: &Connection,
|
_conn: &Connection,
|
||||||
_qh: &QueueHandle<Self>,
|
_qh: &QueueHandle<Self>,
|
||||||
session: &zcosmic_screencopy_session_v1::ZcosmicScreencopySessionV1,
|
screencopy_frame: &zcosmic_screencopy_frame_v2::ZcosmicScreencopyFrameV2,
|
||||||
reason: WEnum<zcosmic_screencopy_session_v1::FailureReason>,
|
reason: WEnum<zcosmic_screencopy_frame_v2::FailureReason>,
|
||||||
) {
|
) {
|
||||||
// TODO send message to thread
|
// TODO send message to thread
|
||||||
|
let session = &screencopy_frame.data::<FrameData>().unwrap().session;
|
||||||
Session::for_session(session).unwrap().update(|data| {
|
Session::for_session(session).unwrap().update(|data| {
|
||||||
data.res = Some(Err(reason));
|
data.res = Some(Err(reason));
|
||||||
});
|
});
|
||||||
session.destroy();
|
session.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn stopped(
|
||||||
|
&mut self,
|
||||||
|
_conn: &Connection,
|
||||||
|
_qh: &QueueHandle<Self>,
|
||||||
|
_session: &zcosmic_screencopy_session_v2::ZcosmicScreencopySessionV2,
|
||||||
|
) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Dispatch<wl_shm_pool::WlShmPool, ()> for AppData {
|
impl Dispatch<wl_shm_pool::WlShmPool, ()> for AppData {
|
||||||
|
|
@ -552,4 +591,4 @@ sctk::delegate_seat!(AppData);
|
||||||
sctk::delegate_registry!(AppData);
|
sctk::delegate_registry!(AppData);
|
||||||
cctk::delegate_toplevel_info!(AppData);
|
cctk::delegate_toplevel_info!(AppData);
|
||||||
cctk::delegate_toplevel_manager!(AppData);
|
cctk::delegate_toplevel_manager!(AppData);
|
||||||
cctk::delegate_screencopy!(AppData, session: [SessionData]);
|
cctk::delegate_screencopy!(AppData, session: [SessionData], frame: [FrameData]);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue