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,
|
zwp_primary_selection_source_v1::ZwpPrimarySelectionSourceV1,
|
||||||
},
|
},
|
||||||
jay_output::JayOutput,
|
jay_output::JayOutput,
|
||||||
jay_screencast::JayScreencast,
|
|
||||||
jay_toplevel::JayToplevel,
|
jay_toplevel::JayToplevel,
|
||||||
jay_workspace::JayWorkspace,
|
jay_workspace::JayWorkspace,
|
||||||
wl_buffer::WlBuffer,
|
wl_buffer::WlBuffer,
|
||||||
|
|
@ -49,9 +48,9 @@ use {
|
||||||
wire::{
|
wire::{
|
||||||
ExtDataControlSourceV1Id, ExtForeignToplevelHandleV1Id, ExtImageCaptureSourceV1Id,
|
ExtDataControlSourceV1Id, ExtForeignToplevelHandleV1Id, ExtImageCaptureSourceV1Id,
|
||||||
ExtImageCopyCaptureSessionV1Id, ExtWorkspaceGroupHandleV1Id, JayHeadErrorV1Id,
|
ExtImageCopyCaptureSessionV1Id, ExtWorkspaceGroupHandleV1Id, JayHeadErrorV1Id,
|
||||||
JayOutputId, JayScreencastId, JayToplevelId, JayWorkspaceId, WlBufferId,
|
JayOutputId, JayToplevelId, JayWorkspaceId, WlBufferId, WlDataSourceId, WlOutputId,
|
||||||
WlDataSourceId, WlOutputId, WlPointerId, WlRegionId, WlRegistryId, WlSeatId,
|
WlPointerId, WlRegionId, WlRegistryId, WlSeatId, WlSurfaceId,
|
||||||
WlSurfaceId, WpDrmLeaseConnectorV1Id, WpImageDescriptionReferenceV1Id,
|
WpDrmLeaseConnectorV1Id, WpImageDescriptionReferenceV1Id,
|
||||||
WpImageDescriptionV1Id, WpLinuxDrmSyncobjTimelineV1Id, XdgPopupId, XdgPositionerId,
|
WpImageDescriptionV1Id, WpLinuxDrmSyncobjTimelineV1Id, XdgPopupId, XdgPositionerId,
|
||||||
XdgSurfaceId, XdgToplevelId, XdgWmBaseId, ZwlrDataControlSourceV1Id,
|
XdgSurfaceId, XdgToplevelId, XdgWmBaseId, ZwlrDataControlSourceV1Id,
|
||||||
ZwlrOutputHeadV1Id, ZwlrOutputModeV1Id, ZwpPrimarySelectionSourceV1Id,
|
ZwlrOutputHeadV1Id, ZwlrOutputModeV1Id, ZwpPrimarySelectionSourceV1Id,
|
||||||
|
|
@ -80,7 +79,6 @@ pub struct Objects {
|
||||||
pub pointers: CopyHashMap<WlPointerId, Rc<WlPointer>>,
|
pub pointers: CopyHashMap<WlPointerId, Rc<WlPointer>>,
|
||||||
pub xdg_wm_bases: CopyHashMap<XdgWmBaseId, Rc<XdgWmBase>>,
|
pub xdg_wm_bases: CopyHashMap<XdgWmBaseId, Rc<XdgWmBase>>,
|
||||||
pub seats: CopyHashMap<WlSeatId, Rc<WlSeat>>,
|
pub seats: CopyHashMap<WlSeatId, Rc<WlSeat>>,
|
||||||
pub screencasts: CopyHashMap<JayScreencastId, Rc<JayScreencast>>,
|
|
||||||
pub timelines: CopyHashMap<WpLinuxDrmSyncobjTimelineV1Id, Rc<WpLinuxDrmSyncobjTimelineV1>>,
|
pub timelines: CopyHashMap<WpLinuxDrmSyncobjTimelineV1Id, Rc<WpLinuxDrmSyncobjTimelineV1>>,
|
||||||
pub zwlr_data_sources: CopyHashMap<ZwlrDataControlSourceV1Id, Rc<ZwlrDataControlSourceV1>>,
|
pub zwlr_data_sources: CopyHashMap<ZwlrDataControlSourceV1Id, Rc<ZwlrDataControlSourceV1>>,
|
||||||
pub zwlr_output_heads: CopyHashMap<ZwlrOutputHeadV1Id, Rc<ZwlrOutputHeadV1>>,
|
pub zwlr_output_heads: CopyHashMap<ZwlrOutputHeadV1Id, Rc<ZwlrOutputHeadV1>>,
|
||||||
|
|
@ -127,7 +125,6 @@ impl Objects {
|
||||||
pointers: Default::default(),
|
pointers: Default::default(),
|
||||||
xdg_wm_bases: Default::default(),
|
xdg_wm_bases: Default::default(),
|
||||||
seats: Default::default(),
|
seats: Default::default(),
|
||||||
screencasts: Default::default(),
|
|
||||||
timelines: Default::default(),
|
timelines: Default::default(),
|
||||||
zwlr_data_sources: Default::default(),
|
zwlr_data_sources: Default::default(),
|
||||||
zwlr_output_heads: Default::default(),
|
zwlr_output_heads: Default::default(),
|
||||||
|
|
@ -176,7 +173,6 @@ impl Objects {
|
||||||
self.xdg_wm_bases.clear();
|
self.xdg_wm_bases.clear();
|
||||||
self.seats.clear();
|
self.seats.clear();
|
||||||
self.pointers.clear();
|
self.pointers.clear();
|
||||||
self.screencasts.clear();
|
|
||||||
self.timelines.clear();
|
self.timelines.clear();
|
||||||
self.zwlr_data_sources.clear();
|
self.zwlr_data_sources.clear();
|
||||||
self.jay_toplevels.clear();
|
self.jay_toplevels.clear();
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,6 @@ use {
|
||||||
head_management::{
|
head_management::{
|
||||||
HeadManagers, HeadState, jay_head_manager_session_v1::handle_jay_head_manager_done,
|
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_output::{BlendSpace, OutputId, PersistentOutputState, WlOutputGlobal},
|
||||||
wl_seat::{handle_position_hint_requests, handle_warp_mouse_to_focus},
|
wl_seat::{handle_position_hint_requests, handle_warp_mouse_to_focus},
|
||||||
wl_surface::{
|
wl_surface::{
|
||||||
|
|
@ -247,8 +246,6 @@ fn start_compositor2(
|
||||||
pending_output_render_data: Default::default(),
|
pending_output_render_data: Default::default(),
|
||||||
pending_float_layout: Default::default(),
|
pending_float_layout: Default::default(),
|
||||||
pending_input_popup_positioning: 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_placeholder_render_textures: Default::default(),
|
||||||
pending_container_tab_render_textures: Default::default(),
|
pending_container_tab_render_textures: Default::default(),
|
||||||
dbus: Dbus::new(&engine, &ring, &run_toplevel),
|
dbus: Dbus::new(&engine, &ring, &run_toplevel),
|
||||||
|
|
@ -514,16 +511,6 @@ fn start_global_event_handlers(state: &Rc<State>) -> Vec<SpawnedFuture<()>> {
|
||||||
Phase::PostLayout,
|
Phase::PostLayout,
|
||||||
input_popup_positioning(state.clone()),
|
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(
|
eng.spawn2(
|
||||||
"visualize damage",
|
"visualize damage",
|
||||||
Phase::PostLayout,
|
Phase::PostLayout,
|
||||||
|
|
@ -759,7 +746,6 @@ fn create_dummy_output(state: &Rc<State>) {
|
||||||
lock_surface: Default::default(),
|
lock_surface: Default::default(),
|
||||||
hardware_cursor: Default::default(),
|
hardware_cursor: Default::default(),
|
||||||
update_render_data_scheduled: Cell::new(false),
|
update_render_data_scheduled: Cell::new(false),
|
||||||
screencasts: Default::default(),
|
|
||||||
hardware_cursor_needs_render: Cell::new(false),
|
hardware_cursor_needs_render: Cell::new(false),
|
||||||
screencopies: Default::default(),
|
screencopies: Default::default(),
|
||||||
title_visible: Cell::new(false),
|
title_visible: Cell::new(false),
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,6 @@ pub mod jay_popup_ext_manager_v1;
|
||||||
pub mod jay_randr;
|
pub mod jay_randr;
|
||||||
pub mod jay_reexec;
|
pub mod jay_reexec;
|
||||||
pub mod jay_render_ctx;
|
pub mod jay_render_ctx;
|
||||||
pub mod jay_screencast;
|
|
||||||
pub mod jay_screenshot;
|
pub mod jay_screenshot;
|
||||||
pub mod jay_seat_events;
|
pub mod jay_seat_events;
|
||||||
pub mod jay_select_toplevel;
|
pub mod jay_select_toplevel;
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,6 @@ use {
|
||||||
jay_randr::JayRandr,
|
jay_randr::JayRandr,
|
||||||
jay_reexec::JayReexec,
|
jay_reexec::JayReexec,
|
||||||
jay_render_ctx::JayRenderCtx,
|
jay_render_ctx::JayRenderCtx,
|
||||||
jay_screencast::JayScreencast,
|
|
||||||
jay_screenshot::JayScreenshot,
|
jay_screenshot::JayScreenshot,
|
||||||
jay_seat_events::JaySeatEvents,
|
jay_seat_events::JaySeatEvents,
|
||||||
jay_select_toplevel::{JaySelectToplevel, JayToplevelSelector},
|
jay_select_toplevel::{JaySelectToplevel, JayToplevelSelector},
|
||||||
|
|
@ -95,7 +94,6 @@ pub struct Cap;
|
||||||
|
|
||||||
impl Cap {
|
impl Cap {
|
||||||
pub const NONE: u16 = 0;
|
pub const NONE: u16 = 0;
|
||||||
pub const WINDOW_CAPTURE: u16 = 1;
|
|
||||||
pub const SELECT_WORKSPACE: u16 = 2;
|
pub const SELECT_WORKSPACE: u16 = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -103,7 +101,7 @@ impl JayCompositor {
|
||||||
fn send_capabilities(&self) {
|
fn send_capabilities(&self) {
|
||||||
self.client.event(Capabilities {
|
self.client.event(Capabilities {
|
||||||
self_id: self.id,
|
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(())
|
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> {
|
fn get_randr(&self, req: GetRandr, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||||
let sc = Rc::new(JayRandr::new(req.id, &self.client, self.version));
|
let sc = Rc::new(JayRandr::new(req.id, &self.client, self.version));
|
||||||
track!(self.client, sc);
|
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 {
|
impl SurfaceSendPreferredScaleVisitor {
|
||||||
fn schedule_realloc(&self, tl: &impl ToplevelNode) {
|
fn schedule_realloc(&self, tl: &impl ToplevelNode) {
|
||||||
let data = tl.tl_data();
|
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() {
|
for sc in data.ext_copy_sessions.lock().values() {
|
||||||
sc.buffer_size_changed();
|
sc.buffer_size_changed();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
12
src/state.rs
12
src/state.rs
|
|
@ -68,7 +68,6 @@ use {
|
||||||
x_data_device::XTransferDeviceIds,
|
x_data_device::XTransferDeviceIds,
|
||||||
},
|
},
|
||||||
jay_render_ctx::JayRenderCtx,
|
jay_render_ctx::JayRenderCtx,
|
||||||
jay_screencast::JayScreencast,
|
|
||||||
jay_seat_events::JaySeatEvents,
|
jay_seat_events::JaySeatEvents,
|
||||||
jay_workspace_watcher::JayWorkspaceWatcher,
|
jay_workspace_watcher::JayWorkspaceWatcher,
|
||||||
wl_buffer::WlBuffer,
|
wl_buffer::WlBuffer,
|
||||||
|
|
@ -294,8 +293,6 @@ pub struct State {
|
||||||
pub pending_output_render_data: AsyncQueue<Rc<OutputNode>>,
|
pub pending_output_render_data: AsyncQueue<Rc<OutputNode>>,
|
||||||
pub pending_float_layout: AsyncQueue<Rc<FloatNode>>,
|
pub pending_float_layout: AsyncQueue<Rc<FloatNode>>,
|
||||||
pub pending_input_popup_positioning: AsyncQueue<Rc<ZwpInputPopupSurfaceV2>>,
|
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_placeholder_render_textures: AsyncQueue<Rc<PlaceholderNode>>,
|
||||||
pub pending_container_tab_render_textures: AsyncQueue<Rc<ContainerNode>>,
|
pub pending_container_tab_render_textures: AsyncQueue<Rc<ContainerNode>>,
|
||||||
pub dbus: Dbus,
|
pub dbus: Dbus,
|
||||||
|
|
@ -854,18 +851,11 @@ impl State {
|
||||||
watcher.send_render_ctx(ctx.clone());
|
watcher.send_render_ctx(ctx.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut scs = vec![];
|
|
||||||
for client in self.clients.clients.borrow_mut().values() {
|
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() {
|
for sc in client.data.objects.ext_copy_sessions.lock().values() {
|
||||||
sc.stop();
|
sc.stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for sc in scs {
|
|
||||||
sc.do_destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
self.expose_new_singletons();
|
self.expose_new_singletons();
|
||||||
}
|
}
|
||||||
|
|
@ -1234,8 +1224,6 @@ impl State {
|
||||||
self.pending_output_render_data.clear();
|
self.pending_output_render_data.clear();
|
||||||
self.pending_float_layout.clear();
|
self.pending_float_layout.clear();
|
||||||
self.pending_input_popup_positioning.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_placeholder_render_textures.clear();
|
||||||
self.pending_container_tab_render_textures.clear();
|
self.pending_container_tab_render_textures.clear();
|
||||||
self.animations.clear();
|
self.animations.clear();
|
||||||
|
|
|
||||||
|
|
@ -218,7 +218,6 @@ impl ConnectorHandler {
|
||||||
lock_surface: Default::default(),
|
lock_surface: Default::default(),
|
||||||
hardware_cursor: Default::default(),
|
hardware_cursor: Default::default(),
|
||||||
jay_outputs: Default::default(),
|
jay_outputs: Default::default(),
|
||||||
screencasts: Default::default(),
|
|
||||||
update_render_data_scheduled: Cell::new(false),
|
update_render_data_scheduled: Cell::new(false),
|
||||||
hardware_cursor_needs_render: Cell::new(false),
|
hardware_cursor_needs_render: Cell::new(false),
|
||||||
screencopies: Default::default(),
|
screencopies: Default::default(),
|
||||||
|
|
@ -341,10 +340,6 @@ impl ConnectorHandler {
|
||||||
for jo in on.jay_outputs.lock().drain_values() {
|
for jo in on.jay_outputs.lock().drain_values() {
|
||||||
jo.send_destroyed();
|
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() {
|
for sc in on.screencopies.lock().drain_values() {
|
||||||
sc.send_failed();
|
sc.send_failed();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@ use {
|
||||||
ifs::{
|
ifs::{
|
||||||
ext_image_copy::ext_image_copy_capture_session_v1::ExtImageCopyCaptureSessionV1,
|
ext_image_copy::ext_image_copy_capture_session_v1::ExtImageCopyCaptureSessionV1,
|
||||||
jay_output::JayOutput,
|
jay_output::JayOutput,
|
||||||
jay_screencast::JayScreencast,
|
|
||||||
wl_buffer::WlBufferStorage,
|
wl_buffer::WlBufferStorage,
|
||||||
wl_output::{BlendSpace, WlOutputGlobal},
|
wl_output::{BlendSpace, WlOutputGlobal},
|
||||||
wl_seat::{
|
wl_seat::{
|
||||||
|
|
@ -63,7 +62,7 @@ use {
|
||||||
scroller::Scroller,
|
scroller::Scroller,
|
||||||
},
|
},
|
||||||
wire::{
|
wire::{
|
||||||
ExtImageCopyCaptureSessionV1Id, JayOutputId, JayScreencastId, ZwlrScreencopyFrameV1Id,
|
ExtImageCopyCaptureSessionV1Id, JayOutputId, ZwlrScreencopyFrameV1Id,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ahash::AHashMap,
|
ahash::AHashMap,
|
||||||
|
|
@ -109,7 +108,6 @@ pub struct OutputNode {
|
||||||
pub hardware_cursor: CloneCell<Option<Rc<dyn HardwareCursor>>>,
|
pub hardware_cursor: CloneCell<Option<Rc<dyn HardwareCursor>>>,
|
||||||
pub hardware_cursor_needs_render: Cell<bool>,
|
pub hardware_cursor_needs_render: Cell<bool>,
|
||||||
pub update_render_data_scheduled: Cell<bool>,
|
pub update_render_data_scheduled: Cell<bool>,
|
||||||
pub screencasts: CopyHashMap<(ClientId, JayScreencastId), Rc<JayScreencast>>,
|
|
||||||
pub screencopies: CopyHashMap<(ClientId, ZwlrScreencopyFrameV1Id), Rc<ZwlrScreencopyFrameV1>>,
|
pub screencopies: CopyHashMap<(ClientId, ZwlrScreencopyFrameV1Id), Rc<ZwlrScreencopyFrameV1>>,
|
||||||
pub title_visible: Cell<bool>,
|
pub title_visible: Cell<bool>,
|
||||||
pub schedule: Rc<OutputSchedule>,
|
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) {
|
pub fn screencast_changed(&self) {
|
||||||
for ws in self.workspaces.iter() {
|
for ws in self.workspaces.iter() {
|
||||||
ws.update_has_captures();
|
ws.update_has_captures();
|
||||||
|
|
@ -315,20 +303,6 @@ impl OutputNode {
|
||||||
y_off,
|
y_off,
|
||||||
size,
|
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() {
|
for sc in self.ext_copy_sessions.lock().values() {
|
||||||
sc.copy_texture(
|
sc.copy_texture(
|
||||||
self,
|
self,
|
||||||
|
|
@ -460,7 +434,6 @@ impl OutputNode {
|
||||||
}
|
}
|
||||||
self.lock_surface.take();
|
self.lock_surface.take();
|
||||||
self.jay_outputs.clear();
|
self.jay_outputs.clear();
|
||||||
self.screencasts.clear();
|
|
||||||
self.screencopies.clear();
|
self.screencopies.clear();
|
||||||
self.ext_copy_sessions.clear();
|
self.ext_copy_sessions.clear();
|
||||||
self.ext_workspace_groups.clear();
|
self.ext_workspace_groups.clear();
|
||||||
|
|
@ -885,9 +858,6 @@ impl OutputNode {
|
||||||
self.change_extents_(&self.calculate_extents());
|
self.change_extents_(&self.calculate_extents());
|
||||||
|
|
||||||
if (old_width, old_height) != (new_width, new_height) {
|
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() {
|
for sc in self.ext_copy_sessions.lock().values() {
|
||||||
sc.buffer_size_changed();
|
sc.buffer_size_changed();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,6 @@ use {
|
||||||
ext_foreign_toplevel_handle_v1::ExtForeignToplevelHandleV1,
|
ext_foreign_toplevel_handle_v1::ExtForeignToplevelHandleV1,
|
||||||
ext_foreign_toplevel_list_v1::ExtForeignToplevelListV1,
|
ext_foreign_toplevel_list_v1::ExtForeignToplevelListV1,
|
||||||
ext_image_copy::ext_image_copy_capture_session_v1::ExtImageCopyCaptureSessionV1,
|
ext_image_copy::ext_image_copy_capture_session_v1::ExtImageCopyCaptureSessionV1,
|
||||||
jay_screencast::JayScreencast,
|
|
||||||
jay_toplevel::JayToplevel,
|
jay_toplevel::JayToplevel,
|
||||||
wl_seat::{NodeSeatState, SeatId, collect_kb_foci, collect_kb_foci2},
|
wl_seat::{NodeSeatState, SeatId, collect_kb_foci, collect_kb_foci2},
|
||||||
wl_surface::{
|
wl_surface::{
|
||||||
|
|
@ -44,8 +43,8 @@ use {
|
||||||
rc_eq::rc_eq, threshold_counter::ThresholdCounter,
|
rc_eq::rc_eq, threshold_counter::ThresholdCounter,
|
||||||
},
|
},
|
||||||
wire::{
|
wire::{
|
||||||
ExtForeignToplevelHandleV1Id, ExtImageCopyCaptureSessionV1Id, JayScreencastId,
|
ExtForeignToplevelHandleV1Id, ExtImageCopyCaptureSessionV1Id, JayToplevelId,
|
||||||
JayToplevelId, XxForeignToplevelGeometryTrackerV1Id, ZwlrForeignToplevelHandleV1Id,
|
XxForeignToplevelGeometryTrackerV1Id, ZwlrForeignToplevelHandleV1Id,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
jay_config::{window, window::WindowType},
|
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>) {
|
fn tl_workspace_output_changed(&self, prev: &Rc<OutputNode>, new: &Rc<OutputNode>) {
|
||||||
let data = self.tl_data();
|
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() {
|
for sc in data.ext_copy_sessions.lock().values() {
|
||||||
sc.update_latch_listener();
|
sc.update_latch_listener();
|
||||||
}
|
}
|
||||||
|
|
@ -244,9 +240,6 @@ impl<T: ToplevelNodeBase> ToplevelNode for T {
|
||||||
data.spawn_in_pending.set(false);
|
data.spawn_in_pending.set(false);
|
||||||
}
|
}
|
||||||
if prev.size() != rect.size() {
|
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() {
|
for sc in data.ext_copy_sessions.lock().values() {
|
||||||
sc.buffer_size_changed();
|
sc.buffer_size_changed();
|
||||||
}
|
}
|
||||||
|
|
@ -543,7 +536,6 @@ pub struct ToplevelData {
|
||||||
CopyHashMap<(ClientId, ZwlrForeignToplevelHandleV1Id), Rc<ZwlrForeignToplevelHandleV1>>,
|
CopyHashMap<(ClientId, ZwlrForeignToplevelHandleV1Id), Rc<ZwlrForeignToplevelHandleV1>>,
|
||||||
pub render_highlight: NumCell<u32>,
|
pub render_highlight: NumCell<u32>,
|
||||||
pub jay_toplevels: CopyHashMap<(ClientId, JayToplevelId), Rc<JayToplevel>>,
|
pub jay_toplevels: CopyHashMap<(ClientId, JayToplevelId), Rc<JayToplevel>>,
|
||||||
pub jay_screencasts: CopyHashMap<(ClientId, JayScreencastId), Rc<JayScreencast>>,
|
|
||||||
pub ext_copy_sessions:
|
pub ext_copy_sessions:
|
||||||
CopyHashMap<(ClientId, ExtImageCopyCaptureSessionV1Id), Rc<ExtImageCopyCaptureSessionV1>>,
|
CopyHashMap<(ClientId, ExtImageCopyCaptureSessionV1Id), Rc<ExtImageCopyCaptureSessionV1>>,
|
||||||
pub slf: Weak<dyn ToplevelNode>,
|
pub slf: Weak<dyn ToplevelNode>,
|
||||||
|
|
@ -603,7 +595,6 @@ impl ToplevelData {
|
||||||
manager_handles: Default::default(),
|
manager_handles: Default::default(),
|
||||||
render_highlight: Default::default(),
|
render_highlight: Default::default(),
|
||||||
jay_toplevels: Default::default(),
|
jay_toplevels: Default::default(),
|
||||||
jay_screencasts: Default::default(),
|
|
||||||
ext_copy_sessions: Default::default(),
|
ext_copy_sessions: Default::default(),
|
||||||
slf: slf.clone(),
|
slf: slf.clone(),
|
||||||
destroyed: Default::default(),
|
destroyed: Default::default(),
|
||||||
|
|
@ -680,9 +671,6 @@ impl ToplevelData {
|
||||||
for jay_tl in self.jay_toplevels.lock().drain_values() {
|
for jay_tl in self.jay_toplevels.lock().drain_values() {
|
||||||
jay_tl.destroy();
|
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() {
|
for screencast in self.ext_copy_sessions.lock().drain_values() {
|
||||||
screencast.stop();
|
screencast.stop();
|
||||||
}
|
}
|
||||||
|
|
@ -1003,9 +991,6 @@ impl ToplevelData {
|
||||||
self.property_changed(TL_CHANGED_VISIBLE);
|
self.property_changed(TL_CHANGED_VISIBLE);
|
||||||
}
|
}
|
||||||
self.seat_state.set_visible(node, 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() {
|
for sc in self.ext_copy_sessions.lock().values() {
|
||||||
sc.update_latch_listener();
|
sc.update_latch_listener();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -119,12 +119,6 @@ impl WorkspaceNode {
|
||||||
if !self.may_capture.get() {
|
if !self.may_capture.get() {
|
||||||
break 'update;
|
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() {
|
if output.screencopies.is_not_empty() {
|
||||||
has_capture = true;
|
has_capture = true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ pub mod usr_jay_ei_session_builder;
|
||||||
pub mod usr_jay_output;
|
pub mod usr_jay_output;
|
||||||
pub mod usr_jay_pointer;
|
pub mod usr_jay_pointer;
|
||||||
pub mod usr_jay_render_ctx;
|
pub mod usr_jay_render_ctx;
|
||||||
pub mod usr_jay_screencast;
|
|
||||||
pub mod usr_jay_select_toplevel;
|
pub mod usr_jay_select_toplevel;
|
||||||
pub mod usr_jay_select_workspace;
|
pub mod usr_jay_select_workspace;
|
||||||
pub mod usr_jay_sync_file_release;
|
pub mod usr_jay_sync_file_release;
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ use {
|
||||||
usr_ifs::{
|
usr_ifs::{
|
||||||
usr_jay_ei_session_builder::UsrJayEiSessionBuilder, usr_jay_output::UsrJayOutput,
|
usr_jay_ei_session_builder::UsrJayEiSessionBuilder, usr_jay_output::UsrJayOutput,
|
||||||
usr_jay_pointer::UsrJayPointer, usr_jay_render_ctx::UsrJayRenderCtx,
|
usr_jay_pointer::UsrJayPointer, usr_jay_render_ctx::UsrJayRenderCtx,
|
||||||
usr_jay_screencast::UsrJayScreencast,
|
|
||||||
usr_jay_select_toplevel::UsrJaySelectToplevel,
|
usr_jay_select_toplevel::UsrJaySelectToplevel,
|
||||||
usr_jay_select_workspace::UsrJaySelectWorkspace,
|
usr_jay_select_workspace::UsrJaySelectWorkspace,
|
||||||
usr_jay_workspace_watcher::UsrJayWorkspaceWatcher, usr_wl_output::UsrWlOutput,
|
usr_jay_workspace_watcher::UsrJayWorkspaceWatcher, usr_wl_output::UsrWlOutput,
|
||||||
|
|
@ -31,7 +30,6 @@ pub struct UsrJayCompositor {
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct UsrJayCompositorCaps {
|
pub struct UsrJayCompositorCaps {
|
||||||
pub window_capture: Cell<bool>,
|
|
||||||
pub select_workspace: Cell<bool>,
|
pub select_workspace: Cell<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -62,24 +60,6 @@ impl UsrJayCompositor {
|
||||||
rc
|
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> {
|
pub fn get_output(&self, output: &UsrWlOutput) -> Rc<UsrJayOutput> {
|
||||||
let jo = Rc::new(UsrJayOutput {
|
let jo = Rc::new(UsrJayOutput {
|
||||||
id: self.con.id(),
|
id: self.con.id(),
|
||||||
|
|
@ -210,7 +190,6 @@ impl JayCompositorEventHandler for UsrJayCompositor {
|
||||||
for &cap in ev.cap {
|
for &cap in ev.cap {
|
||||||
match cap {
|
match cap {
|
||||||
Cap::NONE => {}
|
Cap::NONE => {}
|
||||||
Cap::WINDOW_CAPTURE => self.caps.window_capture.set(true),
|
|
||||||
Cap::SELECT_WORKSPACE => self.caps.select_workspace.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),
|
id: id(jay_workspace_watcher),
|
||||||
}
|
}
|
||||||
|
|
||||||
request create_screencast {
|
|
||||||
id: id(jay_screencast),
|
|
||||||
}
|
|
||||||
|
|
||||||
request get_randr {
|
request get_randr {
|
||||||
id: id(jay_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