ifs: remove private screencast interface
This commit is contained in:
parent
698110c265
commit
ce03990ea4
16 changed files with 7 additions and 1315 deletions
|
|
@ -19,7 +19,6 @@ use {
|
|||
zwp_primary_selection_source_v1::ZwpPrimarySelectionSourceV1,
|
||||
},
|
||||
jay_output::JayOutput,
|
||||
jay_screencast::JayScreencast,
|
||||
jay_toplevel::JayToplevel,
|
||||
jay_workspace::JayWorkspace,
|
||||
wl_buffer::WlBuffer,
|
||||
|
|
@ -49,9 +48,9 @@ use {
|
|||
wire::{
|
||||
ExtDataControlSourceV1Id, ExtForeignToplevelHandleV1Id, ExtImageCaptureSourceV1Id,
|
||||
ExtImageCopyCaptureSessionV1Id, ExtWorkspaceGroupHandleV1Id, JayHeadErrorV1Id,
|
||||
JayOutputId, JayScreencastId, JayToplevelId, JayWorkspaceId, WlBufferId,
|
||||
WlDataSourceId, WlOutputId, WlPointerId, WlRegionId, WlRegistryId, WlSeatId,
|
||||
WlSurfaceId, WpDrmLeaseConnectorV1Id, WpImageDescriptionReferenceV1Id,
|
||||
JayOutputId, JayToplevelId, JayWorkspaceId, WlBufferId, WlDataSourceId, WlOutputId,
|
||||
WlPointerId, WlRegionId, WlRegistryId, WlSeatId, WlSurfaceId,
|
||||
WpDrmLeaseConnectorV1Id, WpImageDescriptionReferenceV1Id,
|
||||
WpImageDescriptionV1Id, WpLinuxDrmSyncobjTimelineV1Id, XdgPopupId, XdgPositionerId,
|
||||
XdgSurfaceId, XdgToplevelId, XdgWmBaseId, ZwlrDataControlSourceV1Id,
|
||||
ZwlrOutputHeadV1Id, ZwlrOutputModeV1Id, ZwpPrimarySelectionSourceV1Id,
|
||||
|
|
@ -80,7 +79,6 @@ pub struct Objects {
|
|||
pub pointers: CopyHashMap<WlPointerId, Rc<WlPointer>>,
|
||||
pub xdg_wm_bases: CopyHashMap<XdgWmBaseId, Rc<XdgWmBase>>,
|
||||
pub seats: CopyHashMap<WlSeatId, Rc<WlSeat>>,
|
||||
pub screencasts: CopyHashMap<JayScreencastId, Rc<JayScreencast>>,
|
||||
pub timelines: CopyHashMap<WpLinuxDrmSyncobjTimelineV1Id, Rc<WpLinuxDrmSyncobjTimelineV1>>,
|
||||
pub zwlr_data_sources: CopyHashMap<ZwlrDataControlSourceV1Id, Rc<ZwlrDataControlSourceV1>>,
|
||||
pub zwlr_output_heads: CopyHashMap<ZwlrOutputHeadV1Id, Rc<ZwlrOutputHeadV1>>,
|
||||
|
|
@ -127,7 +125,6 @@ impl Objects {
|
|||
pointers: Default::default(),
|
||||
xdg_wm_bases: Default::default(),
|
||||
seats: Default::default(),
|
||||
screencasts: Default::default(),
|
||||
timelines: Default::default(),
|
||||
zwlr_data_sources: Default::default(),
|
||||
zwlr_output_heads: Default::default(),
|
||||
|
|
@ -176,7 +173,6 @@ impl Objects {
|
|||
self.xdg_wm_bases.clear();
|
||||
self.seats.clear();
|
||||
self.pointers.clear();
|
||||
self.screencasts.clear();
|
||||
self.timelines.clear();
|
||||
self.zwlr_data_sources.clear();
|
||||
self.jay_toplevels.clear();
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@ use {
|
|||
head_management::{
|
||||
HeadManagers, HeadState, jay_head_manager_session_v1::handle_jay_head_manager_done,
|
||||
},
|
||||
jay_screencast::{perform_screencast_realloc, perform_toplevel_screencasts},
|
||||
wl_output::{BlendSpace, OutputId, PersistentOutputState, WlOutputGlobal},
|
||||
wl_seat::{handle_position_hint_requests, handle_warp_mouse_to_focus},
|
||||
wl_surface::{
|
||||
|
|
@ -247,8 +246,6 @@ fn start_compositor2(
|
|||
pending_output_render_data: Default::default(),
|
||||
pending_float_layout: Default::default(),
|
||||
pending_input_popup_positioning: Default::default(),
|
||||
pending_toplevel_screencasts: Default::default(),
|
||||
pending_screencast_reallocs_or_reconfigures: Default::default(),
|
||||
pending_placeholder_render_textures: Default::default(),
|
||||
pending_container_tab_render_textures: Default::default(),
|
||||
dbus: Dbus::new(&engine, &ring, &run_toplevel),
|
||||
|
|
@ -514,16 +511,6 @@ fn start_global_event_handlers(state: &Rc<State>) -> Vec<SpawnedFuture<()>> {
|
|||
Phase::PostLayout,
|
||||
input_popup_positioning(state.clone()),
|
||||
),
|
||||
eng.spawn2(
|
||||
"toplevel screencast present",
|
||||
Phase::Present,
|
||||
perform_toplevel_screencasts(state.clone()),
|
||||
),
|
||||
eng.spawn2(
|
||||
"screencast realloc",
|
||||
Phase::PostLayout,
|
||||
perform_screencast_realloc(state.clone()),
|
||||
),
|
||||
eng.spawn2(
|
||||
"visualize damage",
|
||||
Phase::PostLayout,
|
||||
|
|
@ -759,7 +746,6 @@ fn create_dummy_output(state: &Rc<State>) {
|
|||
lock_surface: Default::default(),
|
||||
hardware_cursor: Default::default(),
|
||||
update_render_data_scheduled: Cell::new(false),
|
||||
screencasts: Default::default(),
|
||||
hardware_cursor_needs_render: Cell::new(false),
|
||||
screencopies: Default::default(),
|
||||
title_visible: Cell::new(false),
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ pub mod jay_popup_ext_manager_v1;
|
|||
pub mod jay_randr;
|
||||
pub mod jay_reexec;
|
||||
pub mod jay_render_ctx;
|
||||
pub mod jay_screencast;
|
||||
pub mod jay_screenshot;
|
||||
pub mod jay_seat_events;
|
||||
pub mod jay_select_toplevel;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ use {
|
|||
jay_randr::JayRandr,
|
||||
jay_reexec::JayReexec,
|
||||
jay_render_ctx::JayRenderCtx,
|
||||
jay_screencast::JayScreencast,
|
||||
jay_screenshot::JayScreenshot,
|
||||
jay_seat_events::JaySeatEvents,
|
||||
jay_select_toplevel::{JaySelectToplevel, JayToplevelSelector},
|
||||
|
|
@ -95,7 +94,6 @@ pub struct Cap;
|
|||
|
||||
impl Cap {
|
||||
pub const NONE: u16 = 0;
|
||||
pub const WINDOW_CAPTURE: u16 = 1;
|
||||
pub const SELECT_WORKSPACE: u16 = 2;
|
||||
}
|
||||
|
||||
|
|
@ -103,7 +101,7 @@ impl JayCompositor {
|
|||
fn send_capabilities(&self) {
|
||||
self.client.event(Capabilities {
|
||||
self_id: self.id,
|
||||
cap: &[Cap::NONE, Cap::WINDOW_CAPTURE, Cap::SELECT_WORKSPACE],
|
||||
cap: &[Cap::NONE, Cap::SELECT_WORKSPACE],
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -332,13 +330,6 @@ impl JayCompositorRequestHandler for JayCompositor {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn create_screencast(&self, req: CreateScreencast, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
let sc = Rc::new_cyclic(|slf| JayScreencast::new(req.id, &self.client, slf, self.version));
|
||||
track!(self.client, sc);
|
||||
self.client.add_client_obj(&sc)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_randr(&self, req: GetRandr, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
let sc = Rc::new(JayRandr::new(req.id, &self.client, self.version));
|
||||
track!(self.client, sc);
|
||||
|
|
|
|||
|
|
@ -1,796 +0,0 @@
|
|||
use {
|
||||
crate::{
|
||||
allocator::{AllocatorError, BO_USE_LINEAR, BO_USE_RENDERING, BufferObject},
|
||||
client::{Client, ClientError},
|
||||
cmm::cmm_description::ColorDescription,
|
||||
format::XRGB8888,
|
||||
gfx_api::{
|
||||
AcquireSync, BufferResv, GfxContext, GfxError, GfxFramebuffer, GfxTexture, ReleaseSync,
|
||||
},
|
||||
ifs::{jay_output::JayOutput, jay_toplevel::JayToplevel, wl_buffer::WlBufferStorage},
|
||||
leaks::Tracker,
|
||||
object::{Object, Version},
|
||||
scale::Scale,
|
||||
state::State,
|
||||
tree::{
|
||||
LatchListener, OutputNode, ToplevelNode, Transform, WorkspaceNode, WorkspaceNodeId,
|
||||
},
|
||||
utils::{
|
||||
clonecell::{CloneCell, UnsafeCellCloneSafe},
|
||||
errorfmt::ErrorFmt,
|
||||
event_listener::EventListener,
|
||||
numcell::NumCell,
|
||||
option_ext::OptionExt,
|
||||
},
|
||||
video::{INVALID_MODIFIER, LINEAR_MODIFIER, dmabuf::DmaBuf},
|
||||
wire::{JayScreencastId, jay_screencast::*},
|
||||
},
|
||||
ahash::AHashSet,
|
||||
std::{
|
||||
cell::{Cell, RefCell},
|
||||
ops::DerefMut,
|
||||
rc::{Rc, Weak},
|
||||
},
|
||||
thiserror::Error,
|
||||
};
|
||||
|
||||
pub async fn perform_toplevel_screencasts(state: Rc<State>) {
|
||||
loop {
|
||||
let screencast = state.pending_toplevel_screencasts.pop().await;
|
||||
screencast.perform_toplevel_screencast();
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn perform_screencast_realloc(state: Rc<State>) {
|
||||
loop {
|
||||
let screencast = state
|
||||
.pending_screencast_reallocs_or_reconfigures
|
||||
.pop()
|
||||
.await;
|
||||
screencast.realloc_or_reconfigure_scheduled.set(false);
|
||||
match state.render_ctx.get() {
|
||||
None => screencast.do_destroy(),
|
||||
Some(ctx) => {
|
||||
if let Err(e) = screencast.realloc(&ctx) {
|
||||
screencast.client.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub const CLIENT_BUFFERS_SINCE: Version = Version(7);
|
||||
|
||||
pub struct JayScreencast {
|
||||
pub id: JayScreencastId,
|
||||
pub version: Version,
|
||||
pub client: Rc<Client>,
|
||||
pub tracker: Tracker<Self>,
|
||||
config_serial: NumCell<u32>,
|
||||
config_acked: Cell<bool>,
|
||||
buffers_serial: NumCell<u32>,
|
||||
buffers_acked: Cell<bool>,
|
||||
buffers: RefCell<Vec<ScreencastBuffer>>,
|
||||
missed_frame: Cell<bool>,
|
||||
target: CloneCell<Option<Target>>,
|
||||
destroyed: Cell<bool>,
|
||||
running: Cell<bool>,
|
||||
show_all: Cell<bool>,
|
||||
show_workspaces: RefCell<AHashSet<WorkspaceNodeId>>,
|
||||
linear: Cell<bool>,
|
||||
pending: Pending,
|
||||
need_realloc_or_reconfigure: Cell<bool>,
|
||||
realloc_or_reconfigure_scheduled: Cell<bool>,
|
||||
latch_listener: EventListener<dyn LatchListener>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
enum Target {
|
||||
Output(Rc<OutputNode>),
|
||||
Toplevel(Rc<dyn ToplevelNode>),
|
||||
}
|
||||
|
||||
impl LatchListener for JayScreencast {
|
||||
fn after_latch(self: Rc<Self>, _on: &OutputNode, _tearing: bool) {
|
||||
self.schedule_toplevel_screencast();
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl UnsafeCellCloneSafe for Target {}
|
||||
|
||||
enum PendingTarget {
|
||||
Output(Rc<JayOutput>),
|
||||
Toplevel(Rc<JayToplevel>),
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct Pending {
|
||||
linear: Cell<Option<bool>>,
|
||||
running: Cell<Option<bool>>,
|
||||
target: Cell<Option<Option<PendingTarget>>>,
|
||||
show_all: Cell<Option<bool>>,
|
||||
show_workspaces: RefCell<Option<AHashSet<WorkspaceNodeId>>>,
|
||||
clear_buffers: Cell<bool>,
|
||||
buffers: RefCell<Vec<Rc<dyn GfxFramebuffer>>>,
|
||||
}
|
||||
|
||||
struct ScreencastBuffer {
|
||||
_bo: Option<Rc<dyn BufferObject>>,
|
||||
dmabuf: Option<DmaBuf>,
|
||||
fb: Rc<dyn GfxFramebuffer>,
|
||||
free: bool,
|
||||
}
|
||||
|
||||
impl JayScreencast {
|
||||
pub fn shows_ws(&self, ws: &WorkspaceNode) -> bool {
|
||||
if self.show_all.get() {
|
||||
return true;
|
||||
}
|
||||
for &id in &*self.show_workspaces.borrow() {
|
||||
if id == ws.id {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
pub fn new(
|
||||
id: JayScreencastId,
|
||||
client: &Rc<Client>,
|
||||
slf: &Weak<Self>,
|
||||
version: Version,
|
||||
) -> Self {
|
||||
Self {
|
||||
id,
|
||||
version,
|
||||
client: client.clone(),
|
||||
tracker: Default::default(),
|
||||
config_serial: Default::default(),
|
||||
config_acked: Cell::new(true),
|
||||
buffers_serial: Default::default(),
|
||||
buffers_acked: Cell::new(true),
|
||||
buffers: Default::default(),
|
||||
missed_frame: Cell::new(false),
|
||||
target: Default::default(),
|
||||
destroyed: Cell::new(false),
|
||||
running: Cell::new(false),
|
||||
show_all: Cell::new(false),
|
||||
show_workspaces: Default::default(),
|
||||
linear: Cell::new(false),
|
||||
pending: Default::default(),
|
||||
need_realloc_or_reconfigure: Cell::new(false),
|
||||
realloc_or_reconfigure_scheduled: Cell::new(false),
|
||||
latch_listener: EventListener::new(slf.clone()),
|
||||
}
|
||||
}
|
||||
|
||||
fn schedule_toplevel_screencast(self: &Rc<Self>) {
|
||||
if !self.running.get() {
|
||||
return;
|
||||
}
|
||||
self.client
|
||||
.state
|
||||
.pending_toplevel_screencasts
|
||||
.push(self.clone());
|
||||
}
|
||||
|
||||
fn perform_toplevel_screencast(&self) {
|
||||
if self.destroyed.get() || !self.running.get() {
|
||||
return;
|
||||
}
|
||||
let Some(target) = self.target.get() else {
|
||||
return;
|
||||
};
|
||||
let Target::Toplevel(tl) = target else {
|
||||
log::warn!("Tried to perform window screencast for output screencast");
|
||||
return;
|
||||
};
|
||||
let scale = match tl.tl_data().workspace.get() {
|
||||
None => Scale::default(),
|
||||
Some(w) => w.output.get().global.persistent.scale.get(),
|
||||
};
|
||||
let mut buffer = self.buffers.borrow_mut();
|
||||
for (idx, buffer) in buffer.deref_mut().iter_mut().enumerate() {
|
||||
if buffer.free {
|
||||
let res = buffer.fb.render_node(
|
||||
AcquireSync::Implicit,
|
||||
ReleaseSync::Implicit,
|
||||
self.client.state.color_manager.srgb_gamma22(),
|
||||
&*tl,
|
||||
&self.client.state,
|
||||
Some(tl.node_absolute_position()),
|
||||
scale,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
Transform::None,
|
||||
None,
|
||||
self.client.state.color_manager.srgb_linear(),
|
||||
);
|
||||
match res {
|
||||
Ok(_) => {
|
||||
self.client.event(Ready {
|
||||
self_id: self.id,
|
||||
idx: idx as _,
|
||||
});
|
||||
buffer.free = false;
|
||||
return;
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("Could not perform window copy: {}", ErrorFmt(e));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
self.missed_frame.set(true);
|
||||
self.client.event(MissedFrame { self_id: self.id })
|
||||
}
|
||||
|
||||
fn send_buffers(&self) {
|
||||
self.buffers_acked.set(false);
|
||||
let serial = self.buffers_serial.fetch_add(1) + 1;
|
||||
let buffers = self.buffers.borrow_mut();
|
||||
for buffer in buffers.iter() {
|
||||
let Some(dmabuf) = &buffer.dmabuf else {
|
||||
log::error!("Trying to send buffers but buffers are client allocated");
|
||||
self.do_destroy();
|
||||
return;
|
||||
};
|
||||
for plane in &dmabuf.planes {
|
||||
self.client.event(Plane {
|
||||
self_id: self.id,
|
||||
fd: plane.fd.clone(),
|
||||
offset: plane.offset,
|
||||
stride: plane.stride,
|
||||
});
|
||||
}
|
||||
self.client.event(Buffer {
|
||||
self_id: self.id,
|
||||
format: dmabuf.format.drm,
|
||||
modifier: dmabuf.modifier,
|
||||
width: dmabuf.width,
|
||||
height: dmabuf.height,
|
||||
});
|
||||
}
|
||||
self.client.event(BuffersDone {
|
||||
self_id: self.id,
|
||||
serial,
|
||||
});
|
||||
}
|
||||
|
||||
fn send_config(&self) {
|
||||
self.need_realloc_or_reconfigure.set(false);
|
||||
self.config_acked.set(false);
|
||||
let serial = self.config_serial.fetch_add(1) + 1;
|
||||
if let Some(target) = self.target.get() {
|
||||
let (width, height) = target_size(Some(&target));
|
||||
if self.version >= CLIENT_BUFFERS_SINCE {
|
||||
self.client.event(ConfigSize {
|
||||
self_id: self.id,
|
||||
width,
|
||||
height,
|
||||
});
|
||||
}
|
||||
if let Target::Output(output) = target {
|
||||
self.client.event(ConfigOutput {
|
||||
self_id: self.id,
|
||||
linear_id: output.id.raw(),
|
||||
});
|
||||
}
|
||||
}
|
||||
self.client.event(ConfigAllowAllWorkspaces {
|
||||
self_id: self.id,
|
||||
allow_all: self.show_all.get() as _,
|
||||
});
|
||||
for &ws in self.show_workspaces.borrow_mut().iter() {
|
||||
self.client.event(ConfigAllowWorkspace {
|
||||
self_id: self.id,
|
||||
linear_id: ws.raw(),
|
||||
});
|
||||
}
|
||||
self.client.event(ConfigUseLinearBuffers {
|
||||
self_id: self.id,
|
||||
use_linear: self.linear.get() as _,
|
||||
});
|
||||
self.client.event(ConfigRunning {
|
||||
self_id: self.id,
|
||||
running: self.running.get() as _,
|
||||
});
|
||||
self.client.event(ConfigDone {
|
||||
self_id: self.id,
|
||||
serial,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn copy_texture(
|
||||
&self,
|
||||
on: &OutputNode,
|
||||
texture: &Rc<dyn GfxTexture>,
|
||||
cd: &Rc<ColorDescription>,
|
||||
resv: Option<&Rc<dyn BufferResv>>,
|
||||
acquire_sync: &AcquireSync,
|
||||
release_sync: ReleaseSync,
|
||||
render_hardware_cursors: bool,
|
||||
x_off: i32,
|
||||
y_off: i32,
|
||||
size: Option<(i32, i32)>,
|
||||
) {
|
||||
if !self.running.get() {
|
||||
return;
|
||||
}
|
||||
if !self.show_all.get() {
|
||||
let ws = match on.workspace.get() {
|
||||
Some(ws) => ws,
|
||||
_ => return,
|
||||
};
|
||||
if !self.show_workspaces.borrow_mut().contains(&ws.id) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
let mut buffer = self.buffers.borrow_mut();
|
||||
for (idx, buffer) in buffer.deref_mut().iter_mut().enumerate() {
|
||||
if buffer.free {
|
||||
let res = self.client.state.perform_screencopy(
|
||||
texture,
|
||||
resv,
|
||||
acquire_sync,
|
||||
release_sync,
|
||||
cd,
|
||||
&buffer.fb,
|
||||
AcquireSync::Implicit,
|
||||
ReleaseSync::Implicit,
|
||||
Transform::None,
|
||||
self.client.state.color_manager.srgb_gamma22(),
|
||||
on.global.pos.get(),
|
||||
render_hardware_cursors,
|
||||
x_off,
|
||||
y_off,
|
||||
size,
|
||||
on.global.persistent.transform.get(),
|
||||
on.global.persistent.scale.get(),
|
||||
);
|
||||
match res {
|
||||
Ok(_) => {
|
||||
self.client.event(Ready {
|
||||
self_id: self.id,
|
||||
idx: idx as _,
|
||||
});
|
||||
buffer.free = false;
|
||||
return;
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("Could not perform screencopy: {}", ErrorFmt(e));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
self.missed_frame.set(true);
|
||||
self.client.event(MissedFrame { self_id: self.id })
|
||||
}
|
||||
|
||||
fn detach(&self) {
|
||||
self.latch_listener.detach();
|
||||
if let Some(target) = self.target.take() {
|
||||
match target {
|
||||
Target::Output(output) => {
|
||||
output.remove_screencast(self);
|
||||
}
|
||||
Target::Toplevel(tl) => {
|
||||
let data = tl.tl_data();
|
||||
data.jay_screencasts.remove(&(self.client.id, self.id));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn do_destroy(&self) {
|
||||
self.detach();
|
||||
self.buffers.borrow_mut().clear();
|
||||
self.destroyed.set(true);
|
||||
self.client.event(Destroyed { self_id: self.id });
|
||||
}
|
||||
|
||||
pub fn schedule_realloc_or_reconfigure(self: &Rc<Self>) {
|
||||
self.need_realloc_or_reconfigure.set(true);
|
||||
if !self.realloc_or_reconfigure_scheduled.replace(true) {
|
||||
self.client
|
||||
.state
|
||||
.pending_screencast_reallocs_or_reconfigures
|
||||
.push(self.clone());
|
||||
}
|
||||
}
|
||||
|
||||
fn realloc(&self, ctx: &Rc<dyn GfxContext>) -> Result<(), JayScreencastError> {
|
||||
if self.destroyed.get() {
|
||||
return Ok(());
|
||||
}
|
||||
if self.version < CLIENT_BUFFERS_SINCE {
|
||||
if self.buffers_acked.get() {
|
||||
return self.do_realloc(ctx);
|
||||
}
|
||||
} else {
|
||||
if self.config_acked.get() {
|
||||
self.send_config();
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn do_realloc(&self, ctx: &Rc<dyn GfxContext>) -> Result<(), JayScreencastError> {
|
||||
self.need_realloc_or_reconfigure.set(false);
|
||||
let mut buffers = vec![];
|
||||
let formats = ctx.formats();
|
||||
let format = match formats.get(&XRGB8888.drm) {
|
||||
Some(f) => f,
|
||||
_ => return Err(JayScreencastError::XRGB8888),
|
||||
};
|
||||
if let Some(target) = self.target.get() {
|
||||
let (width, height) = target_size(Some(&target));
|
||||
let num = 3;
|
||||
for _ in 0..num {
|
||||
if width == 0 || height == 0 {
|
||||
continue;
|
||||
}
|
||||
let mut usage = BO_USE_RENDERING;
|
||||
let modifiers = match self.linear.get() {
|
||||
true if format.write_modifiers.contains_key(&LINEAR_MODIFIER) => {
|
||||
vec![LINEAR_MODIFIER]
|
||||
}
|
||||
true if format.write_modifiers.contains_key(&INVALID_MODIFIER) => {
|
||||
usage |= BO_USE_LINEAR;
|
||||
vec![INVALID_MODIFIER]
|
||||
}
|
||||
true => return Err(JayScreencastError::Modifier),
|
||||
false if format.write_modifiers.is_empty() => {
|
||||
return Err(JayScreencastError::XRGB8888Writing);
|
||||
}
|
||||
false => format.write_modifiers.keys().copied().collect(),
|
||||
};
|
||||
let buffer = ctx.allocator().create_bo(
|
||||
&self.client.state.dma_buf_ids,
|
||||
width,
|
||||
height,
|
||||
format.format,
|
||||
&modifiers,
|
||||
usage,
|
||||
)?;
|
||||
let fb = ctx.clone().dmabuf_img(buffer.dmabuf())?.to_framebuffer()?;
|
||||
buffers.push(ScreencastBuffer {
|
||||
dmabuf: Some(buffer.dmabuf().clone()),
|
||||
_bo: Some(buffer),
|
||||
fb,
|
||||
free: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
*self.buffers.borrow_mut() = buffers;
|
||||
self.send_buffers();
|
||||
self.damage();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn damage(&self) {
|
||||
if let Some(target) = self.target.get() {
|
||||
let rect = match target {
|
||||
Target::Output(o) => o.global.pos.get(),
|
||||
Target::Toplevel(t) => {
|
||||
if !t.node_visible() {
|
||||
return;
|
||||
}
|
||||
t.node_absolute_position()
|
||||
}
|
||||
};
|
||||
self.client.state.damage(rect);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_latch_listener(&self) {
|
||||
let Some(Target::Toplevel(tl)) = self.target.get() else {
|
||||
return;
|
||||
};
|
||||
let data = tl.tl_data();
|
||||
if data.visible.get() {
|
||||
self.latch_listener.attach(&data.output().latch_event);
|
||||
} else {
|
||||
self.latch_listener.detach();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl JayScreencastRequestHandler for JayScreencast {
|
||||
type Error = JayScreencastError;
|
||||
|
||||
fn destroy(&self, _req: Destroy, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
self.detach();
|
||||
self.client.remove_obj(self)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_output(&self, req: SetOutput, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
let output = if req.output.is_some() {
|
||||
Some(PendingTarget::Output(self.client.lookup(req.output)?))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
if self.destroyed.get() {
|
||||
return Ok(());
|
||||
}
|
||||
self.pending.target.set(Some(output));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_allow_all_workspaces(
|
||||
&self,
|
||||
req: SetAllowAllWorkspaces,
|
||||
_slf: &Rc<Self>,
|
||||
) -> Result<(), Self::Error> {
|
||||
if self.destroyed.get() {
|
||||
return Ok(());
|
||||
}
|
||||
self.pending.show_all.set(Some(req.allow_all != 0));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn allow_workspace(&self, req: AllowWorkspace, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
let ws = self.client.lookup(req.workspace)?;
|
||||
if self.destroyed.get() {
|
||||
return Ok(());
|
||||
}
|
||||
let mut sw = self.pending.show_workspaces.borrow_mut();
|
||||
let sw = sw.get_or_insert_default_ext();
|
||||
if let Some(ws) = ws.workspace.get() {
|
||||
sw.insert(ws.id);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn touch_allowed_workspaces(
|
||||
&self,
|
||||
_req: TouchAllowedWorkspaces,
|
||||
_slf: &Rc<Self>,
|
||||
) -> Result<(), Self::Error> {
|
||||
if self.destroyed.get() {
|
||||
return Ok(());
|
||||
}
|
||||
self.pending
|
||||
.show_workspaces
|
||||
.borrow_mut()
|
||||
.get_or_insert_default_ext();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_use_linear_buffers(
|
||||
&self,
|
||||
req: SetUseLinearBuffers,
|
||||
_slf: &Rc<Self>,
|
||||
) -> Result<(), Self::Error> {
|
||||
if self.destroyed.get() {
|
||||
return Ok(());
|
||||
}
|
||||
self.pending.linear.set(Some(req.use_linear != 0));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_running(&self, req: SetRunning, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
if self.destroyed.get() {
|
||||
return Ok(());
|
||||
}
|
||||
self.pending.running.set(Some(req.running != 0));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn configure(&self, _req: Configure, slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
if self.destroyed.get() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut need_realloc_or_reconfigure = false;
|
||||
|
||||
if let Some(target) = self.pending.target.take() {
|
||||
self.detach();
|
||||
let mut new_target = None;
|
||||
if let Some(new) = target {
|
||||
match new {
|
||||
PendingTarget::Output(o) => {
|
||||
let Some(o) = o.output.node() else {
|
||||
self.do_destroy();
|
||||
return Ok(());
|
||||
};
|
||||
o.add_screencast(slf);
|
||||
new_target = Some(Target::Output(o));
|
||||
}
|
||||
PendingTarget::Toplevel(t) => {
|
||||
if t.destroyed.get() {
|
||||
self.do_destroy();
|
||||
return Ok(());
|
||||
}
|
||||
let t = t.toplevel.clone();
|
||||
let data = t.tl_data();
|
||||
data.jay_screencasts
|
||||
.set((self.client.id, self.id), slf.clone());
|
||||
if data.visible.get() {
|
||||
self.latch_listener.attach(&data.output().latch_event);
|
||||
}
|
||||
new_target = Some(Target::Toplevel(t));
|
||||
}
|
||||
}
|
||||
}
|
||||
if target_size(new_target.as_ref()) != target_size(self.target.get().as_ref()) {
|
||||
need_realloc_or_reconfigure = true;
|
||||
}
|
||||
self.target.set(new_target);
|
||||
}
|
||||
if let Some(linear) = self.pending.linear.take() {
|
||||
if self.linear.replace(linear) != linear {
|
||||
need_realloc_or_reconfigure = true;
|
||||
}
|
||||
}
|
||||
if self.pending.clear_buffers.take() {
|
||||
self.buffers.borrow_mut().clear();
|
||||
}
|
||||
for buffer in self.pending.buffers.borrow_mut().drain(..) {
|
||||
self.buffers.borrow_mut().push(ScreencastBuffer {
|
||||
_bo: None,
|
||||
dmabuf: None,
|
||||
fb: buffer,
|
||||
free: true,
|
||||
});
|
||||
}
|
||||
let mut capture_rules_changed = false;
|
||||
if let Some(show_all) = self.pending.show_all.take() {
|
||||
self.show_all.set(show_all);
|
||||
capture_rules_changed = true;
|
||||
}
|
||||
if let Some(new_workspaces) = self.pending.show_workspaces.borrow_mut().take() {
|
||||
*self.show_workspaces.borrow_mut() = new_workspaces;
|
||||
capture_rules_changed = true;
|
||||
}
|
||||
if let Some(running) = self.pending.running.take() {
|
||||
self.running.set(running);
|
||||
}
|
||||
|
||||
if need_realloc_or_reconfigure {
|
||||
slf.schedule_realloc_or_reconfigure();
|
||||
}
|
||||
|
||||
if capture_rules_changed && let Some(Target::Output(o)) = self.target.get() {
|
||||
o.screencast_changed();
|
||||
}
|
||||
|
||||
if self.running.get() {
|
||||
self.damage();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn ack_buffers(&self, req: AckBuffers, slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
if self.destroyed.get() {
|
||||
return Ok(());
|
||||
}
|
||||
if req.serial == self.buffers_serial.get() {
|
||||
self.buffers_acked.set(true);
|
||||
if self.need_realloc_or_reconfigure.get() {
|
||||
slf.schedule_realloc_or_reconfigure();
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn ack_config(&self, req: AckConfig, slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
if self.destroyed.get() {
|
||||
return Ok(());
|
||||
}
|
||||
if req.serial == self.config_serial.get() {
|
||||
self.config_acked.set(true);
|
||||
if self.need_realloc_or_reconfigure.get() {
|
||||
slf.schedule_realloc_or_reconfigure();
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn release_buffer(&self, req: ReleaseBuffer, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
if self.destroyed.get() || !self.buffers_acked.get() {
|
||||
return Ok(());
|
||||
}
|
||||
let idx = req.idx as usize;
|
||||
if idx >= self.buffers.borrow_mut().len() {
|
||||
return Err(JayScreencastError::OutOfBounds(req.idx));
|
||||
}
|
||||
self.buffers.borrow_mut()[idx].free = true;
|
||||
if self.missed_frame.replace(false) {
|
||||
self.damage();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_toplevel(&self, req: SetToplevel, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
let toplevel = if req.id.is_some() {
|
||||
Some(PendingTarget::Toplevel(self.client.lookup(req.id)?))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
if self.destroyed.get() {
|
||||
return Ok(());
|
||||
}
|
||||
self.pending.target.set(Some(toplevel));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn clear_buffers(&self, _req: ClearBuffers, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
if self.destroyed.get() {
|
||||
return Ok(());
|
||||
}
|
||||
self.pending.clear_buffers.set(true);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn add_buffer(&self, req: AddBuffer, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
if self.destroyed.get() {
|
||||
return Ok(());
|
||||
}
|
||||
let buffer = self.client.lookup(req.buffer)?;
|
||||
if let Some(WlBufferStorage::Dmabuf { img, .. }) = &*buffer.storage.borrow() {
|
||||
match img.clone().to_framebuffer() {
|
||||
Ok(fb) => self.pending.buffers.borrow_mut().push(fb),
|
||||
Err(e) => {
|
||||
log::warn!(
|
||||
"Could not turn GfxImage into GfxFramebuffer: {}",
|
||||
ErrorFmt(e)
|
||||
);
|
||||
self.do_destroy();
|
||||
}
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
Err(JayScreencastError::NotDmabuf)
|
||||
}
|
||||
}
|
||||
|
||||
object_base! {
|
||||
self = JayScreencast;
|
||||
version = self.version;
|
||||
}
|
||||
|
||||
impl Object for JayScreencast {
|
||||
fn break_loops(&self) {
|
||||
self.detach();
|
||||
}
|
||||
}
|
||||
|
||||
dedicated_add_obj!(JayScreencast, JayScreencastId, screencasts);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum JayScreencastError {
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
#[error("Buffer index {0} is out-of-bounds")]
|
||||
OutOfBounds(u32),
|
||||
#[error(transparent)]
|
||||
AllocatorError(#[from] AllocatorError),
|
||||
#[error(transparent)]
|
||||
GfxError(#[from] GfxError),
|
||||
#[error("Render context does not support XRGB8888 format")]
|
||||
XRGB8888,
|
||||
#[error("Render context does not support XRGB8888 format for rendering")]
|
||||
XRGB8888Writing,
|
||||
#[error("Render context supports neither linear or invalid modifier")]
|
||||
Modifier,
|
||||
#[error("Buffer is not a dmabuf")]
|
||||
NotDmabuf,
|
||||
}
|
||||
efrom!(JayScreencastError, ClientError);
|
||||
|
||||
fn target_size(target: Option<&Target>) -> (i32, i32) {
|
||||
if let Some(target) = target {
|
||||
return match target {
|
||||
Target::Output(o) => o.global.pixel_size(),
|
||||
Target::Toplevel(t) => t.tl_data().desired_pixel_size(),
|
||||
};
|
||||
}
|
||||
(0, 0)
|
||||
}
|
||||
|
|
@ -164,9 +164,6 @@ pub struct SurfaceSendPreferredScaleVisitor;
|
|||
impl SurfaceSendPreferredScaleVisitor {
|
||||
fn schedule_realloc(&self, tl: &impl ToplevelNode) {
|
||||
let data = tl.tl_data();
|
||||
for sc in data.jay_screencasts.lock().values() {
|
||||
sc.schedule_realloc_or_reconfigure();
|
||||
}
|
||||
for sc in data.ext_copy_sessions.lock().values() {
|
||||
sc.buffer_size_changed();
|
||||
}
|
||||
|
|
|
|||
12
src/state.rs
12
src/state.rs
|
|
@ -68,7 +68,6 @@ use {
|
|||
x_data_device::XTransferDeviceIds,
|
||||
},
|
||||
jay_render_ctx::JayRenderCtx,
|
||||
jay_screencast::JayScreencast,
|
||||
jay_seat_events::JaySeatEvents,
|
||||
jay_workspace_watcher::JayWorkspaceWatcher,
|
||||
wl_buffer::WlBuffer,
|
||||
|
|
@ -294,8 +293,6 @@ pub struct State {
|
|||
pub pending_output_render_data: AsyncQueue<Rc<OutputNode>>,
|
||||
pub pending_float_layout: AsyncQueue<Rc<FloatNode>>,
|
||||
pub pending_input_popup_positioning: AsyncQueue<Rc<ZwpInputPopupSurfaceV2>>,
|
||||
pub pending_toplevel_screencasts: AsyncQueue<Rc<JayScreencast>>,
|
||||
pub pending_screencast_reallocs_or_reconfigures: AsyncQueue<Rc<JayScreencast>>,
|
||||
pub pending_placeholder_render_textures: AsyncQueue<Rc<PlaceholderNode>>,
|
||||
pub pending_container_tab_render_textures: AsyncQueue<Rc<ContainerNode>>,
|
||||
pub dbus: Dbus,
|
||||
|
|
@ -854,18 +851,11 @@ impl State {
|
|||
watcher.send_render_ctx(ctx.clone());
|
||||
}
|
||||
|
||||
let mut scs = vec![];
|
||||
for client in self.clients.clients.borrow_mut().values() {
|
||||
for sc in client.data.objects.screencasts.lock().values() {
|
||||
scs.push(sc.clone());
|
||||
}
|
||||
for sc in client.data.objects.ext_copy_sessions.lock().values() {
|
||||
sc.stop();
|
||||
}
|
||||
}
|
||||
for sc in scs {
|
||||
sc.do_destroy();
|
||||
}
|
||||
|
||||
self.expose_new_singletons();
|
||||
}
|
||||
|
|
@ -1234,8 +1224,6 @@ impl State {
|
|||
self.pending_output_render_data.clear();
|
||||
self.pending_float_layout.clear();
|
||||
self.pending_input_popup_positioning.clear();
|
||||
self.pending_toplevel_screencasts.clear();
|
||||
self.pending_screencast_reallocs_or_reconfigures.clear();
|
||||
self.pending_placeholder_render_textures.clear();
|
||||
self.pending_container_tab_render_textures.clear();
|
||||
self.animations.clear();
|
||||
|
|
|
|||
|
|
@ -218,7 +218,6 @@ impl ConnectorHandler {
|
|||
lock_surface: Default::default(),
|
||||
hardware_cursor: Default::default(),
|
||||
jay_outputs: Default::default(),
|
||||
screencasts: Default::default(),
|
||||
update_render_data_scheduled: Cell::new(false),
|
||||
hardware_cursor_needs_render: Cell::new(false),
|
||||
screencopies: Default::default(),
|
||||
|
|
@ -341,10 +340,6 @@ impl ConnectorHandler {
|
|||
for jo in on.jay_outputs.lock().drain_values() {
|
||||
jo.send_destroyed();
|
||||
}
|
||||
let screencasts: Vec<_> = on.screencasts.lock().values().cloned().collect();
|
||||
for sc in screencasts {
|
||||
sc.do_destroy();
|
||||
}
|
||||
for sc in on.screencopies.lock().drain_values() {
|
||||
sc.send_failed();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ use {
|
|||
ifs::{
|
||||
ext_image_copy::ext_image_copy_capture_session_v1::ExtImageCopyCaptureSessionV1,
|
||||
jay_output::JayOutput,
|
||||
jay_screencast::JayScreencast,
|
||||
wl_buffer::WlBufferStorage,
|
||||
wl_output::{BlendSpace, WlOutputGlobal},
|
||||
wl_seat::{
|
||||
|
|
@ -63,7 +62,7 @@ use {
|
|||
scroller::Scroller,
|
||||
},
|
||||
wire::{
|
||||
ExtImageCopyCaptureSessionV1Id, JayOutputId, JayScreencastId, ZwlrScreencopyFrameV1Id,
|
||||
ExtImageCopyCaptureSessionV1Id, JayOutputId, ZwlrScreencopyFrameV1Id,
|
||||
},
|
||||
},
|
||||
ahash::AHashMap,
|
||||
|
|
@ -109,7 +108,6 @@ pub struct OutputNode {
|
|||
pub hardware_cursor: CloneCell<Option<Rc<dyn HardwareCursor>>>,
|
||||
pub hardware_cursor_needs_render: Cell<bool>,
|
||||
pub update_render_data_scheduled: Cell<bool>,
|
||||
pub screencasts: CopyHashMap<(ClientId, JayScreencastId), Rc<JayScreencast>>,
|
||||
pub screencopies: CopyHashMap<(ClientId, ZwlrScreencopyFrameV1Id), Rc<ZwlrScreencopyFrameV1>>,
|
||||
pub title_visible: Cell<bool>,
|
||||
pub schedule: Rc<OutputSchedule>,
|
||||
|
|
@ -271,16 +269,6 @@ impl OutputNode {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn add_screencast(&self, sc: &Rc<JayScreencast>) {
|
||||
self.screencasts.set((sc.client.id, sc.id), sc.clone());
|
||||
self.screencast_changed();
|
||||
}
|
||||
|
||||
pub fn remove_screencast(&self, sc: &JayScreencast) {
|
||||
self.screencasts.remove(&(sc.client.id, sc.id));
|
||||
self.screencast_changed();
|
||||
}
|
||||
|
||||
pub fn screencast_changed(&self) {
|
||||
for ws in self.workspaces.iter() {
|
||||
ws.update_has_captures();
|
||||
|
|
@ -315,20 +303,6 @@ impl OutputNode {
|
|||
y_off,
|
||||
size,
|
||||
);
|
||||
for sc in self.screencasts.lock().values() {
|
||||
sc.copy_texture(
|
||||
self,
|
||||
tex,
|
||||
cd,
|
||||
resv,
|
||||
acquire_sync,
|
||||
release_sync,
|
||||
render_hardware_cursor,
|
||||
x_off,
|
||||
y_off,
|
||||
size,
|
||||
);
|
||||
}
|
||||
for sc in self.ext_copy_sessions.lock().values() {
|
||||
sc.copy_texture(
|
||||
self,
|
||||
|
|
@ -460,7 +434,6 @@ impl OutputNode {
|
|||
}
|
||||
self.lock_surface.take();
|
||||
self.jay_outputs.clear();
|
||||
self.screencasts.clear();
|
||||
self.screencopies.clear();
|
||||
self.ext_copy_sessions.clear();
|
||||
self.ext_workspace_groups.clear();
|
||||
|
|
@ -885,9 +858,6 @@ impl OutputNode {
|
|||
self.change_extents_(&self.calculate_extents());
|
||||
|
||||
if (old_width, old_height) != (new_width, new_height) {
|
||||
for sc in self.screencasts.lock().values() {
|
||||
sc.schedule_realloc_or_reconfigure();
|
||||
}
|
||||
for sc in self.ext_copy_sessions.lock().values() {
|
||||
sc.buffer_size_changed();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ use {
|
|||
ext_foreign_toplevel_handle_v1::ExtForeignToplevelHandleV1,
|
||||
ext_foreign_toplevel_list_v1::ExtForeignToplevelListV1,
|
||||
ext_image_copy::ext_image_copy_capture_session_v1::ExtImageCopyCaptureSessionV1,
|
||||
jay_screencast::JayScreencast,
|
||||
jay_toplevel::JayToplevel,
|
||||
wl_seat::{NodeSeatState, SeatId, collect_kb_foci, collect_kb_foci2},
|
||||
wl_surface::{
|
||||
|
|
@ -44,8 +43,8 @@ use {
|
|||
rc_eq::rc_eq, threshold_counter::ThresholdCounter,
|
||||
},
|
||||
wire::{
|
||||
ExtForeignToplevelHandleV1Id, ExtImageCopyCaptureSessionV1Id, JayScreencastId,
|
||||
JayToplevelId, XxForeignToplevelGeometryTrackerV1Id, ZwlrForeignToplevelHandleV1Id,
|
||||
ExtForeignToplevelHandleV1Id, ExtImageCopyCaptureSessionV1Id, JayToplevelId,
|
||||
XxForeignToplevelGeometryTrackerV1Id, ZwlrForeignToplevelHandleV1Id,
|
||||
},
|
||||
},
|
||||
jay_config::{window, window::WindowType},
|
||||
|
|
@ -174,9 +173,6 @@ impl<T: ToplevelNodeBase> ToplevelNode for T {
|
|||
|
||||
fn tl_workspace_output_changed(&self, prev: &Rc<OutputNode>, new: &Rc<OutputNode>) {
|
||||
let data = self.tl_data();
|
||||
for sc in data.jay_screencasts.lock().values() {
|
||||
sc.update_latch_listener();
|
||||
}
|
||||
for sc in data.ext_copy_sessions.lock().values() {
|
||||
sc.update_latch_listener();
|
||||
}
|
||||
|
|
@ -244,9 +240,6 @@ impl<T: ToplevelNodeBase> ToplevelNode for T {
|
|||
data.spawn_in_pending.set(false);
|
||||
}
|
||||
if prev.size() != rect.size() {
|
||||
for sc in data.jay_screencasts.lock().values() {
|
||||
sc.schedule_realloc_or_reconfigure();
|
||||
}
|
||||
for sc in data.ext_copy_sessions.lock().values() {
|
||||
sc.buffer_size_changed();
|
||||
}
|
||||
|
|
@ -543,7 +536,6 @@ pub struct ToplevelData {
|
|||
CopyHashMap<(ClientId, ZwlrForeignToplevelHandleV1Id), Rc<ZwlrForeignToplevelHandleV1>>,
|
||||
pub render_highlight: NumCell<u32>,
|
||||
pub jay_toplevels: CopyHashMap<(ClientId, JayToplevelId), Rc<JayToplevel>>,
|
||||
pub jay_screencasts: CopyHashMap<(ClientId, JayScreencastId), Rc<JayScreencast>>,
|
||||
pub ext_copy_sessions:
|
||||
CopyHashMap<(ClientId, ExtImageCopyCaptureSessionV1Id), Rc<ExtImageCopyCaptureSessionV1>>,
|
||||
pub slf: Weak<dyn ToplevelNode>,
|
||||
|
|
@ -603,7 +595,6 @@ impl ToplevelData {
|
|||
manager_handles: Default::default(),
|
||||
render_highlight: Default::default(),
|
||||
jay_toplevels: Default::default(),
|
||||
jay_screencasts: Default::default(),
|
||||
ext_copy_sessions: Default::default(),
|
||||
slf: slf.clone(),
|
||||
destroyed: Default::default(),
|
||||
|
|
@ -680,9 +671,6 @@ impl ToplevelData {
|
|||
for jay_tl in self.jay_toplevels.lock().drain_values() {
|
||||
jay_tl.destroy();
|
||||
}
|
||||
for screencast in self.jay_screencasts.lock().drain_values() {
|
||||
screencast.do_destroy();
|
||||
}
|
||||
for screencast in self.ext_copy_sessions.lock().drain_values() {
|
||||
screencast.stop();
|
||||
}
|
||||
|
|
@ -1003,9 +991,6 @@ impl ToplevelData {
|
|||
self.property_changed(TL_CHANGED_VISIBLE);
|
||||
}
|
||||
self.seat_state.set_visible(node, visible);
|
||||
for sc in self.jay_screencasts.lock().values() {
|
||||
sc.update_latch_listener();
|
||||
}
|
||||
for sc in self.ext_copy_sessions.lock().values() {
|
||||
sc.update_latch_listener();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -119,12 +119,6 @@ impl WorkspaceNode {
|
|||
if !self.may_capture.get() {
|
||||
break 'update;
|
||||
}
|
||||
for sc in output.screencasts.lock().values() {
|
||||
if sc.shows_ws(self) {
|
||||
has_capture = true;
|
||||
break 'update;
|
||||
}
|
||||
}
|
||||
if output.screencopies.is_not_empty() {
|
||||
has_capture = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ pub mod usr_jay_ei_session_builder;
|
|||
pub mod usr_jay_output;
|
||||
pub mod usr_jay_pointer;
|
||||
pub mod usr_jay_render_ctx;
|
||||
pub mod usr_jay_screencast;
|
||||
pub mod usr_jay_select_toplevel;
|
||||
pub mod usr_jay_select_workspace;
|
||||
pub mod usr_jay_sync_file_release;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ use {
|
|||
usr_ifs::{
|
||||
usr_jay_ei_session_builder::UsrJayEiSessionBuilder, usr_jay_output::UsrJayOutput,
|
||||
usr_jay_pointer::UsrJayPointer, usr_jay_render_ctx::UsrJayRenderCtx,
|
||||
usr_jay_screencast::UsrJayScreencast,
|
||||
usr_jay_select_toplevel::UsrJaySelectToplevel,
|
||||
usr_jay_select_workspace::UsrJaySelectWorkspace,
|
||||
usr_jay_workspace_watcher::UsrJayWorkspaceWatcher, usr_wl_output::UsrWlOutput,
|
||||
|
|
@ -31,7 +30,6 @@ pub struct UsrJayCompositor {
|
|||
|
||||
#[derive(Default)]
|
||||
pub struct UsrJayCompositorCaps {
|
||||
pub window_capture: Cell<bool>,
|
||||
pub select_workspace: Cell<bool>,
|
||||
}
|
||||
|
||||
|
|
@ -62,24 +60,6 @@ impl UsrJayCompositor {
|
|||
rc
|
||||
}
|
||||
|
||||
pub fn create_screencast(&self) -> Rc<UsrJayScreencast> {
|
||||
let sc = Rc::new(UsrJayScreencast {
|
||||
id: self.con.id(),
|
||||
con: self.con.clone(),
|
||||
owner: Default::default(),
|
||||
version: self.version,
|
||||
pending_buffers: Default::default(),
|
||||
pending_planes: Default::default(),
|
||||
pending_config: Default::default(),
|
||||
});
|
||||
self.con.request(CreateScreencast {
|
||||
self_id: self.id,
|
||||
id: sc.id,
|
||||
});
|
||||
self.con.add_object(sc.clone());
|
||||
sc
|
||||
}
|
||||
|
||||
pub fn get_output(&self, output: &UsrWlOutput) -> Rc<UsrJayOutput> {
|
||||
let jo = Rc::new(UsrJayOutput {
|
||||
id: self.con.id(),
|
||||
|
|
@ -210,7 +190,6 @@ impl JayCompositorEventHandler for UsrJayCompositor {
|
|||
for &cap in ev.cap {
|
||||
match cap {
|
||||
Cap::NONE => {}
|
||||
Cap::WINDOW_CAPTURE => self.caps.window_capture.set(true),
|
||||
Cap::SELECT_WORKSPACE => self.caps.select_workspace.set(true),
|
||||
_ => {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,272 +0,0 @@
|
|||
use {
|
||||
crate::{
|
||||
format::formats,
|
||||
object::Version,
|
||||
utils::clonecell::CloneCell,
|
||||
video::dmabuf::{DmaBuf, DmaBufPlane, PlaneVec},
|
||||
wire::{JayScreencastId, jay_screencast::*},
|
||||
wl_usr::{
|
||||
UsrCon,
|
||||
usr_ifs::{
|
||||
usr_jay_output::UsrJayOutput, usr_jay_toplevel::UsrJayToplevel,
|
||||
usr_jay_workspace::UsrJayWorkspace, usr_wl_buffer::UsrWlBuffer,
|
||||
},
|
||||
usr_object::UsrObject,
|
||||
},
|
||||
},
|
||||
std::{cell::RefCell, mem, ops::DerefMut, rc::Rc},
|
||||
thiserror::Error,
|
||||
};
|
||||
|
||||
pub struct UsrJayScreencast {
|
||||
pub id: JayScreencastId,
|
||||
pub con: Rc<UsrCon>,
|
||||
pub owner: CloneCell<Option<Rc<dyn UsrJayScreencastOwner>>>,
|
||||
pub version: Version,
|
||||
|
||||
pub pending_buffers: RefCell<Vec<DmaBuf>>,
|
||||
pub pending_planes: RefCell<PlaneVec<DmaBufPlane>>,
|
||||
|
||||
pub pending_config: RefCell<UsrJayScreencastServerConfig>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct UsrJayScreencastServerConfig {
|
||||
pub output: Option<u32>,
|
||||
pub show_all: bool,
|
||||
pub running: bool,
|
||||
pub use_linear_buffers: bool,
|
||||
pub allowed_workspaces: Vec<u32>,
|
||||
pub width: i32,
|
||||
pub height: i32,
|
||||
}
|
||||
|
||||
pub trait UsrJayScreencastOwner {
|
||||
fn buffers(&self, buffers: Vec<DmaBuf>) {
|
||||
let _ = buffers;
|
||||
}
|
||||
|
||||
fn ready(&self, ev: &Ready) {
|
||||
let _ = ev;
|
||||
}
|
||||
|
||||
fn destroyed(&self) {}
|
||||
|
||||
fn missed_frame(&self) {}
|
||||
|
||||
fn config(&self, config: UsrJayScreencastServerConfig) {
|
||||
let _ = config;
|
||||
}
|
||||
}
|
||||
|
||||
impl UsrJayScreencast {
|
||||
pub fn set_output(&self, output: &UsrJayOutput) {
|
||||
self.con.request(SetOutput {
|
||||
self_id: self.id,
|
||||
output: output.id,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn set_toplevel(&self, tl: &UsrJayToplevel) {
|
||||
self.con.request(SetToplevel {
|
||||
self_id: self.id,
|
||||
id: tl.id,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn set_allow_all_workspaces(&self, allow_all: bool) {
|
||||
self.con.request(SetAllowAllWorkspaces {
|
||||
self_id: self.id,
|
||||
allow_all: allow_all as _,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn allow_workspace(&self, ws: &UsrJayWorkspace) {
|
||||
self.con.request(AllowWorkspace {
|
||||
self_id: self.id,
|
||||
workspace: ws.id,
|
||||
});
|
||||
}
|
||||
|
||||
#[expect(dead_code)]
|
||||
pub fn touch_allowed_workspaces(&self) {
|
||||
self.con
|
||||
.request(TouchAllowedWorkspaces { self_id: self.id });
|
||||
}
|
||||
|
||||
pub fn set_use_linear_buffers(&self, linear: bool) {
|
||||
self.con.request(SetUseLinearBuffers {
|
||||
self_id: self.id,
|
||||
use_linear: linear as _,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn set_running(&self, running: bool) {
|
||||
self.con.request(SetRunning {
|
||||
self_id: self.id,
|
||||
running: running as _,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn configure(&self) {
|
||||
self.con.request(Configure { self_id: self.id });
|
||||
}
|
||||
|
||||
pub fn release_buffer(&self, idx: usize) {
|
||||
self.con.request(ReleaseBuffer {
|
||||
self_id: self.id,
|
||||
idx: idx as _,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn clear_buffers(&self) {
|
||||
self.con.request(ClearBuffers { self_id: self.id });
|
||||
}
|
||||
|
||||
pub fn add_buffer(&self, buffer: &UsrWlBuffer) {
|
||||
self.con.request(AddBuffer {
|
||||
self_id: self.id,
|
||||
buffer: buffer.id,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl JayScreencastEventHandler for UsrJayScreencast {
|
||||
type Error = UsrJayScreencastError;
|
||||
|
||||
fn plane(&self, ev: Plane, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
self.pending_planes.borrow_mut().push(DmaBufPlane {
|
||||
offset: ev.offset,
|
||||
stride: ev.stride,
|
||||
fd: ev.fd,
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn buffer(&self, ev: Buffer, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
let format = match formats().get(&ev.format) {
|
||||
Some(f) => f,
|
||||
_ => return Err(UsrJayScreencastError::UnknownFormat(ev.format)),
|
||||
};
|
||||
self.pending_buffers.borrow_mut().push(DmaBuf {
|
||||
id: self.con.dma_buf_ids.next(),
|
||||
width: ev.width,
|
||||
height: ev.height,
|
||||
format,
|
||||
modifier: ev.modifier,
|
||||
planes: mem::take(self.pending_planes.borrow_mut().deref_mut()),
|
||||
is_disjoint: Default::default(),
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn buffers_done(&self, ev: BuffersDone, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.buffers(mem::take(self.pending_buffers.borrow_mut().deref_mut()));
|
||||
}
|
||||
self.con.request(AckBuffers {
|
||||
self_id: self.id,
|
||||
serial: ev.serial,
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn ready(&self, ev: Ready, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.ready(&ev);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn destroyed(&self, _ev: Destroyed, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.destroyed();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn missed_frame(&self, _ev: MissedFrame, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.missed_frame();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn config_output(&self, ev: ConfigOutput, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
self.pending_config.borrow_mut().output = Some(ev.linear_id);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn config_allow_all_workspaces(
|
||||
&self,
|
||||
ev: ConfigAllowAllWorkspaces,
|
||||
_slf: &Rc<Self>,
|
||||
) -> Result<(), Self::Error> {
|
||||
self.pending_config.borrow_mut().show_all = ev.allow_all != 0;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn config_allow_workspace(
|
||||
&self,
|
||||
ev: ConfigAllowWorkspace,
|
||||
_slf: &Rc<Self>,
|
||||
) -> Result<(), Self::Error> {
|
||||
self.pending_config
|
||||
.borrow_mut()
|
||||
.allowed_workspaces
|
||||
.push(ev.linear_id);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn config_use_linear_buffers(
|
||||
&self,
|
||||
ev: ConfigUseLinearBuffers,
|
||||
_slf: &Rc<Self>,
|
||||
) -> Result<(), Self::Error> {
|
||||
self.pending_config.borrow_mut().use_linear_buffers = ev.use_linear != 0;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn config_running(&self, ev: ConfigRunning, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
self.pending_config.borrow_mut().running = ev.running != 0;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn config_done(&self, ev: ConfigDone, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.config(mem::take(self.pending_config.borrow_mut().deref_mut()));
|
||||
}
|
||||
self.con.request(AckConfig {
|
||||
self_id: self.id,
|
||||
serial: ev.serial,
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn config_size(&self, ev: ConfigSize, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
self.pending_config.borrow_mut().width = ev.width;
|
||||
self.pending_config.borrow_mut().height = ev.height;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
usr_object_base! {
|
||||
self = UsrJayScreencast = JayScreencast;
|
||||
version = self.version;
|
||||
}
|
||||
|
||||
impl UsrObject for UsrJayScreencast {
|
||||
fn destroy(&self) {
|
||||
self.con.request(Destroy { self_id: self.id });
|
||||
}
|
||||
|
||||
fn break_loops(&self) {
|
||||
self.owner.take();
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum UsrJayScreencastError {
|
||||
#[error("The server sent an unknown format {0}")]
|
||||
UnknownFormat(u32),
|
||||
}
|
||||
|
|
@ -61,10 +61,6 @@ request watch_workspaces {
|
|||
id: id(jay_workspace_watcher),
|
||||
}
|
||||
|
||||
request create_screencast {
|
||||
id: id(jay_screencast),
|
||||
}
|
||||
|
||||
request get_randr {
|
||||
id: id(jay_randr),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,115 +0,0 @@
|
|||
# requests
|
||||
|
||||
request destroy {
|
||||
|
||||
}
|
||||
|
||||
request set_output {
|
||||
output: id(jay_output),
|
||||
}
|
||||
|
||||
request set_allow_all_workspaces {
|
||||
allow_all: u32,
|
||||
}
|
||||
|
||||
request allow_workspace {
|
||||
workspace: id(jay_workspace),
|
||||
}
|
||||
|
||||
request touch_allowed_workspaces {
|
||||
}
|
||||
|
||||
request set_use_linear_buffers {
|
||||
use_linear: u32,
|
||||
}
|
||||
|
||||
request set_running {
|
||||
running: u32,
|
||||
}
|
||||
|
||||
request configure {
|
||||
|
||||
}
|
||||
|
||||
request ack_buffers {
|
||||
serial: u32,
|
||||
}
|
||||
|
||||
request ack_config {
|
||||
serial: u32,
|
||||
}
|
||||
|
||||
request release_buffer {
|
||||
idx: u32,
|
||||
}
|
||||
|
||||
request set_toplevel {
|
||||
id: id(jay_toplevel),
|
||||
}
|
||||
|
||||
request clear_buffers (since = 7) {
|
||||
}
|
||||
|
||||
request add_buffer (since = 7) {
|
||||
buffer: id(wl_buffer),
|
||||
}
|
||||
|
||||
# events
|
||||
|
||||
event plane {
|
||||
fd: fd,
|
||||
offset: u32,
|
||||
stride: u32,
|
||||
}
|
||||
|
||||
event buffer {
|
||||
format: u32,
|
||||
modifier: pod(u64),
|
||||
width: i32,
|
||||
height: i32,
|
||||
}
|
||||
|
||||
event buffers_done {
|
||||
serial: u32,
|
||||
}
|
||||
|
||||
event ready {
|
||||
idx: u32,
|
||||
}
|
||||
|
||||
event destroyed {
|
||||
|
||||
}
|
||||
|
||||
event missed_frame {
|
||||
|
||||
}
|
||||
|
||||
event config_output {
|
||||
linear_id: u32,
|
||||
}
|
||||
|
||||
event config_allow_all_workspaces {
|
||||
allow_all: u32,
|
||||
}
|
||||
|
||||
event config_allow_workspace {
|
||||
linear_id: u32,
|
||||
}
|
||||
|
||||
event config_use_linear_buffers {
|
||||
use_linear: u32,
|
||||
}
|
||||
|
||||
event config_running {
|
||||
running: u32,
|
||||
}
|
||||
|
||||
event config_done {
|
||||
serial: u32,
|
||||
}
|
||||
|
||||
event config_size (since = 7) {
|
||||
width: i32,
|
||||
height: i32,
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue