tree: fix per-workspace capture tracking
This commit is contained in:
parent
670588fe4d
commit
c6864a6d85
10 changed files with 191 additions and 145 deletions
|
|
@ -451,6 +451,7 @@ fn create_dummy_output(state: &Rc<State>) {
|
|||
update_render_data_scheduled: Cell::new(false),
|
||||
screencasts: Default::default(),
|
||||
hardware_cursor_needs_render: Cell::new(false),
|
||||
screencopies: Default::default(),
|
||||
});
|
||||
let dummy_workspace = Rc::new(WorkspaceNode {
|
||||
id: state.node_ids.next(),
|
||||
|
|
@ -467,7 +468,8 @@ fn create_dummy_output(state: &Rc<State>) {
|
|||
visible_on_desired_output: Default::default(),
|
||||
desired_output: CloneCell::new(dummy_output.global.output_id.clone()),
|
||||
jay_workspaces: Default::default(),
|
||||
capture: Cell::new(false),
|
||||
may_capture: Cell::new(false),
|
||||
has_capture: Cell::new(false),
|
||||
title_texture: Cell::new(None),
|
||||
attention_requests: Default::default(),
|
||||
});
|
||||
|
|
|
|||
|
|
@ -655,7 +655,7 @@ impl ConfigProxyHandler {
|
|||
fn handle_get_workspace_capture(&self, workspace: Workspace) -> Result<(), CphError> {
|
||||
let name = self.get_workspace(workspace)?;
|
||||
let capture = match self.state.workspaces.get(name.as_str()) {
|
||||
Some(ws) => ws.capture.get(),
|
||||
Some(ws) => ws.may_capture.get(),
|
||||
None => self.state.default_workspace_capture.get(),
|
||||
};
|
||||
self.respond(Response::GetWorkspaceCapture { capture });
|
||||
|
|
@ -669,7 +669,8 @@ impl ConfigProxyHandler {
|
|||
) -> Result<(), CphError> {
|
||||
let name = self.get_workspace(workspace)?;
|
||||
if let Some(ws) = self.state.workspaces.get(name.as_str()) {
|
||||
ws.capture.set(capture);
|
||||
ws.may_capture.set(capture);
|
||||
ws.update_has_captures();
|
||||
ws.output.get().schedule_update_render_data();
|
||||
self.state.damage();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use {
|
|||
object::{Object, Version},
|
||||
scale::Scale,
|
||||
state::State,
|
||||
tree::{OutputNode, ToplevelNode, WorkspaceNodeId},
|
||||
tree::{OutputNode, ToplevelNode, WorkspaceNode, WorkspaceNodeId},
|
||||
utils::{
|
||||
clonecell::{CloneCell, UnsafeCellCloneSafe},
|
||||
errorfmt::ErrorFmt,
|
||||
|
|
@ -106,6 +106,18 @@ struct ScreencastBuffer {
|
|||
}
|
||||
|
||||
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>) -> Self {
|
||||
Self {
|
||||
id,
|
||||
|
|
@ -309,10 +321,7 @@ impl JayScreencast {
|
|||
if let Some(target) = self.target.take() {
|
||||
match target {
|
||||
Target::Output(output) => {
|
||||
output.screencasts.remove(&(self.client.id, self.id));
|
||||
if output.screencasts.is_empty() {
|
||||
output.state.damage();
|
||||
}
|
||||
output.remove_screencast(self);
|
||||
}
|
||||
Target::Toplevel(tl) => {
|
||||
let data = tl.tl_data();
|
||||
|
|
@ -514,10 +523,7 @@ impl JayScreencastRequestHandler for JayScreencast {
|
|||
self.do_destroy();
|
||||
return Ok(());
|
||||
};
|
||||
if o.screencasts.is_empty() {
|
||||
o.state.damage();
|
||||
}
|
||||
o.screencasts.set((self.client.id, self.id), slf.clone());
|
||||
o.add_screencast(slf);
|
||||
new_target = Some(Target::Output(o));
|
||||
}
|
||||
PendingTarget::Toplevel(t) => {
|
||||
|
|
@ -546,11 +552,14 @@ impl JayScreencastRequestHandler for JayScreencast {
|
|||
need_realloc = 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);
|
||||
|
|
@ -560,6 +569,12 @@ impl JayScreencastRequestHandler for JayScreencast {
|
|||
slf.schedule_realloc();
|
||||
}
|
||||
|
||||
if capture_rules_changed {
|
||||
if let Some(Target::Output(o)) = self.target.get() {
|
||||
o.screencast_changed();
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,22 +2,14 @@ use {
|
|||
crate::{
|
||||
backend,
|
||||
client::{Client, ClientError, ClientId},
|
||||
gfx_api::GfxTexture,
|
||||
globals::{Global, GlobalName},
|
||||
ifs::{
|
||||
wl_buffer::WlBufferStorage, wl_surface::WlSurface,
|
||||
zwlr_screencopy_frame_v1::ZwlrScreencopyFrameV1, zxdg_output_v1::ZxdgOutputV1,
|
||||
},
|
||||
ifs::{wl_surface::WlSurface, zxdg_output_v1::ZxdgOutputV1},
|
||||
leaks::Tracker,
|
||||
object::{Object, Version},
|
||||
rect::Rect,
|
||||
state::{ConnectorData, State},
|
||||
time::Time,
|
||||
tree::{calculate_logical_size, OutputNode},
|
||||
utils::{
|
||||
clonecell::CloneCell, copyhashmap::CopyHashMap, errorfmt::ErrorFmt,
|
||||
linkedlist::LinkedList, transform_ext::TransformExt,
|
||||
},
|
||||
utils::{clonecell::CloneCell, copyhashmap::CopyHashMap, transform_ext::TransformExt},
|
||||
wire::{wl_output::*, WlOutputId, ZxdgOutputV1Id},
|
||||
},
|
||||
ahash::AHashMap,
|
||||
|
|
@ -25,7 +17,6 @@ use {
|
|||
std::{
|
||||
cell::{Cell, RefCell},
|
||||
collections::hash_map::Entry,
|
||||
ops::Deref,
|
||||
rc::Rc,
|
||||
},
|
||||
thiserror::Error,
|
||||
|
|
@ -68,8 +59,6 @@ pub struct WlOutputGlobal {
|
|||
pub width_mm: i32,
|
||||
pub height_mm: i32,
|
||||
pub bindings: RefCell<AHashMap<ClientId, AHashMap<WlOutputId, Rc<WlOutput>>>>,
|
||||
pub unused_captures: LinkedList<Rc<ZwlrScreencopyFrameV1>>,
|
||||
pub pending_captures: LinkedList<Rc<ZwlrScreencopyFrameV1>>,
|
||||
pub destroyed: Cell<bool>,
|
||||
pub legacy_scale: Cell<u32>,
|
||||
pub persistent: Rc<PersistentOutputState>,
|
||||
|
|
@ -125,8 +114,6 @@ impl WlOutputGlobal {
|
|||
width_mm,
|
||||
height_mm,
|
||||
bindings: Default::default(),
|
||||
unused_captures: Default::default(),
|
||||
pending_captures: Default::default(),
|
||||
destroyed: Cell::new(false),
|
||||
legacy_scale: Cell::new(scale.round_up()),
|
||||
persistent: persistent_state.clone(),
|
||||
|
|
@ -210,88 +197,6 @@ impl WlOutputGlobal {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn perform_screencopies(
|
||||
&self,
|
||||
tex: &Rc<dyn GfxTexture>,
|
||||
render_hardware_cursors: bool,
|
||||
x_off: i32,
|
||||
y_off: i32,
|
||||
size: Option<(i32, i32)>,
|
||||
) {
|
||||
if self.pending_captures.is_empty() {
|
||||
return;
|
||||
}
|
||||
let now = Time::now().unwrap();
|
||||
let mut captures = vec![];
|
||||
for capture in self.pending_captures.iter() {
|
||||
captures.push(capture.deref().clone());
|
||||
let wl_buffer = match capture.buffer.take() {
|
||||
Some(b) => b,
|
||||
_ => {
|
||||
log::warn!("Capture frame is pending but has no buffer attached");
|
||||
capture.send_failed();
|
||||
continue;
|
||||
}
|
||||
};
|
||||
if wl_buffer.destroyed() {
|
||||
capture.send_failed();
|
||||
continue;
|
||||
}
|
||||
if let Some(WlBufferStorage::Shm { mem, stride }) =
|
||||
wl_buffer.storage.borrow_mut().deref()
|
||||
{
|
||||
let res = self.state.perform_shm_screencopy(
|
||||
tex,
|
||||
self.pos.get(),
|
||||
x_off,
|
||||
y_off,
|
||||
size,
|
||||
&capture,
|
||||
mem,
|
||||
*stride,
|
||||
wl_buffer.format,
|
||||
Transform::None,
|
||||
);
|
||||
if let Err(e) = res {
|
||||
log::warn!("Could not perform shm screencopy: {}", ErrorFmt(e));
|
||||
capture.send_failed();
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
let fb = match wl_buffer.famebuffer.get() {
|
||||
Some(fb) => fb,
|
||||
_ => {
|
||||
log::warn!("Capture buffer has no framebuffer");
|
||||
capture.send_failed();
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let res = self.state.perform_screencopy(
|
||||
tex,
|
||||
&fb,
|
||||
self.pos.get(),
|
||||
render_hardware_cursors,
|
||||
x_off - capture.rect.x1(),
|
||||
y_off - capture.rect.y1(),
|
||||
size,
|
||||
Transform::None,
|
||||
);
|
||||
if let Err(e) = res {
|
||||
log::warn!("Could not perform screencopy: {}", ErrorFmt(e));
|
||||
capture.send_failed();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if capture.with_damage.get() {
|
||||
capture.send_damage();
|
||||
}
|
||||
capture.send_ready(now.0.tv_sec as _, now.0.tv_nsec as _);
|
||||
}
|
||||
for capture in captures {
|
||||
capture.output_link.take();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pixel_size(&self) -> (i32, i32) {
|
||||
let mode = self.mode.get();
|
||||
self.persistent
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ use {
|
|||
leaks::Tracker,
|
||||
object::{Object, Version},
|
||||
rect::Rect,
|
||||
utils::linkedlist::LinkedNode,
|
||||
wire::{zwlr_screencopy_frame_v1::*, WlBufferId, ZwlrScreencopyFrameV1Id},
|
||||
},
|
||||
std::{cell::Cell, ops::Deref, rc::Rc},
|
||||
|
|
@ -28,7 +27,6 @@ pub struct ZwlrScreencopyFrameV1 {
|
|||
pub overlay_cursor: bool,
|
||||
pub used: Cell<bool>,
|
||||
pub with_damage: Cell<bool>,
|
||||
pub output_link: Cell<Option<LinkedNode<Rc<Self>>>>,
|
||||
pub buffer: Cell<Option<Rc<WlBuffer>>>,
|
||||
pub version: Version,
|
||||
}
|
||||
|
|
@ -90,19 +88,16 @@ impl ZwlrScreencopyFrameV1 {
|
|||
}
|
||||
|
||||
fn do_copy(
|
||||
&self,
|
||||
self: &Rc<Self>,
|
||||
buffer_id: WlBufferId,
|
||||
with_damage: bool,
|
||||
) -> Result<(), ZwlrScreencopyFrameV1Error> {
|
||||
if self.used.replace(true) {
|
||||
return Err(ZwlrScreencopyFrameV1Error::AlreadyUsed);
|
||||
}
|
||||
let link = match self.output_link.take() {
|
||||
Some(l) => l,
|
||||
_ => {
|
||||
self.send_failed();
|
||||
return Ok(());
|
||||
}
|
||||
let Some(node) = self.output.node.get() else {
|
||||
self.send_failed();
|
||||
return Ok(());
|
||||
};
|
||||
let buffer = self.client.lookup(buffer_id)?;
|
||||
if (buffer.rect.width(), buffer.rect.height()) != (self.rect.width(), self.rect.height()) {
|
||||
|
|
@ -122,27 +117,35 @@ impl ZwlrScreencopyFrameV1 {
|
|||
self.output.connector.connector.damage();
|
||||
}
|
||||
self.with_damage.set(with_damage);
|
||||
self.output.pending_captures.add_last_existing(&link);
|
||||
self.output_link.set(Some(link));
|
||||
node.screencopies
|
||||
.set((self.client.id, self.id), self.clone());
|
||||
node.screencast_changed();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn detach(&self) {
|
||||
if let Some(node) = self.output.node.get() {
|
||||
node.screencopies.remove(&(self.client.id, self.id));
|
||||
node.screencast_changed();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ZwlrScreencopyFrameV1RequestHandler for ZwlrScreencopyFrameV1 {
|
||||
type Error = ZwlrScreencopyFrameV1Error;
|
||||
|
||||
fn copy(&self, req: Copy, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
self.do_copy(req.buffer, false)
|
||||
fn copy(&self, req: Copy, slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
slf.do_copy(req.buffer, false)
|
||||
}
|
||||
|
||||
fn destroy(&self, _req: Destroy, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
self.detach();
|
||||
self.client.remove_obj(self)?;
|
||||
self.output_link.take();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn copy_with_damage(&self, req: CopyWithDamage, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
self.do_copy(req.buffer, true)
|
||||
fn copy_with_damage(&self, req: CopyWithDamage, slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
slf.do_copy(req.buffer, true)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -155,7 +158,7 @@ simple_add_obj!(ZwlrScreencopyFrameV1);
|
|||
|
||||
impl Object for ZwlrScreencopyFrameV1 {
|
||||
fn break_loops(&self) {
|
||||
self.output_link.take();
|
||||
self.detach();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -125,7 +125,6 @@ impl ZwlrScreencopyManagerV1 {
|
|||
overlay_cursor,
|
||||
used: Cell::new(false),
|
||||
with_damage: Cell::new(false),
|
||||
output_link: Cell::new(None),
|
||||
buffer: Cell::new(None),
|
||||
version: self.version,
|
||||
});
|
||||
|
|
@ -136,9 +135,6 @@ impl ZwlrScreencopyManagerV1 {
|
|||
frame.send_linux_dmabuf();
|
||||
frame.send_buffer_done();
|
||||
}
|
||||
frame
|
||||
.output_link
|
||||
.set(Some(output.global.unused_captures.add_last(frame.clone())));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -132,11 +132,9 @@ impl Renderer<'_> {
|
|||
x,
|
||||
y,
|
||||
);
|
||||
let has_captures =
|
||||
!output.screencasts.is_empty() || !output.global.pending_captures.is_empty();
|
||||
let rd = output.render_data.borrow_mut();
|
||||
if let Some(aw) = &rd.active_workspace {
|
||||
let c = match has_captures && aw.captured {
|
||||
let c = match aw.captured {
|
||||
true => theme.colors.captured_focused_title_background.get(),
|
||||
false => theme.colors.focused_title_background.get(),
|
||||
};
|
||||
|
|
@ -147,10 +145,7 @@ impl Renderer<'_> {
|
|||
.fill_boxes2(slice::from_ref(&rd.underline), &c, x, y);
|
||||
let c = theme.colors.unfocused_title_background.get();
|
||||
self.base.fill_boxes2(&rd.inactive_workspaces, &c, x, y);
|
||||
let c = match has_captures {
|
||||
true => theme.colors.captured_unfocused_title_background.get(),
|
||||
false => theme.colors.unfocused_title_background.get(),
|
||||
};
|
||||
let c = theme.colors.captured_unfocused_title_background.get();
|
||||
self.base
|
||||
.fill_boxes2(&rd.captured_inactive_workspaces, &c, x, y);
|
||||
let c = theme.colors.attention_requested_background.get();
|
||||
|
|
|
|||
|
|
@ -148,6 +148,7 @@ impl ConnectorHandler {
|
|||
screencasts: Default::default(),
|
||||
update_render_data_scheduled: Cell::new(false),
|
||||
hardware_cursor_needs_render: Cell::new(false),
|
||||
screencopies: Default::default(),
|
||||
});
|
||||
self.state
|
||||
.add_output_scale(on.global.persistent.scale.get());
|
||||
|
|
@ -235,6 +236,9 @@ impl ConnectorHandler {
|
|||
for sc in screencasts {
|
||||
sc.do_destroy();
|
||||
}
|
||||
for (_, sc) in on.screencopies.lock().drain() {
|
||||
sc.send_failed();
|
||||
}
|
||||
global.destroyed.set(true);
|
||||
self.state.root.outputs.remove(&self.id);
|
||||
self.state.root.update_extents();
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ use {
|
|||
ifs::{
|
||||
jay_output::JayOutput,
|
||||
jay_screencast::JayScreencast,
|
||||
wl_buffer::WlBufferStorage,
|
||||
wl_output::WlOutputGlobal,
|
||||
wl_seat::{
|
||||
collect_kb_foci2, wl_pointer::PendingScroll, NodeSeatState, SeatId, WlSeatGlobal,
|
||||
|
|
@ -19,12 +20,14 @@ use {
|
|||
SurfaceSendPreferredTransformVisitor,
|
||||
},
|
||||
zwlr_layer_shell_v1::{BACKGROUND, BOTTOM, OVERLAY, TOP},
|
||||
zwlr_screencopy_frame_v1::ZwlrScreencopyFrameV1,
|
||||
},
|
||||
rect::Rect,
|
||||
renderer::Renderer,
|
||||
scale::Scale,
|
||||
state::State,
|
||||
text::{self, TextTexture},
|
||||
time::Time,
|
||||
tree::{
|
||||
walker::NodeVisitor, Direction, FindTreeResult, FindTreeUsecase, FoundNode, Node,
|
||||
NodeId, WorkspaceNode,
|
||||
|
|
@ -33,7 +36,7 @@ use {
|
|||
clonecell::CloneCell, copyhashmap::CopyHashMap, errorfmt::ErrorFmt,
|
||||
linkedlist::LinkedList, scroller::Scroller, transform_ext::TransformExt,
|
||||
},
|
||||
wire::{JayOutputId, JayScreencastId},
|
||||
wire::{JayOutputId, JayScreencastId, ZwlrScreencopyFrameV1Id},
|
||||
},
|
||||
ahash::AHashMap,
|
||||
jay_config::video::Transform,
|
||||
|
|
@ -66,6 +69,7 @@ pub struct OutputNode {
|
|||
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 async fn output_render_data(state: Rc<State>) {
|
||||
|
|
@ -81,6 +85,22 @@ pub async fn output_render_data(state: Rc<State>) {
|
|||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn perform_screencopies(
|
||||
&self,
|
||||
tex: &Rc<dyn GfxTexture>,
|
||||
|
|
@ -90,17 +110,94 @@ impl OutputNode {
|
|||
size: Option<(i32, i32)>,
|
||||
) {
|
||||
if let Some(workspace) = self.workspace.get() {
|
||||
if !workspace.capture.get() {
|
||||
if !workspace.may_capture.get() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
self.global
|
||||
.perform_screencopies(tex, render_hardware_cursor, x_off, y_off, size);
|
||||
self.perform_wlr_screencopies(tex, render_hardware_cursor, x_off, y_off, size);
|
||||
for sc in self.screencasts.lock().values() {
|
||||
sc.copy_texture(self, tex, render_hardware_cursor, x_off, y_off, size);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn perform_wlr_screencopies(
|
||||
&self,
|
||||
tex: &Rc<dyn GfxTexture>,
|
||||
render_hardware_cursors: bool,
|
||||
x_off: i32,
|
||||
y_off: i32,
|
||||
size: Option<(i32, i32)>,
|
||||
) {
|
||||
if self.screencopies.is_empty() {
|
||||
return;
|
||||
}
|
||||
let now = Time::now().unwrap();
|
||||
for (_, capture) in self.screencopies.lock().drain() {
|
||||
let wl_buffer = match capture.buffer.take() {
|
||||
Some(b) => b,
|
||||
_ => {
|
||||
log::warn!("Capture frame is pending but has no buffer attached");
|
||||
capture.send_failed();
|
||||
continue;
|
||||
}
|
||||
};
|
||||
if wl_buffer.destroyed() {
|
||||
capture.send_failed();
|
||||
continue;
|
||||
}
|
||||
if let Some(WlBufferStorage::Shm { mem, stride }) =
|
||||
wl_buffer.storage.borrow_mut().deref()
|
||||
{
|
||||
let res = self.state.perform_shm_screencopy(
|
||||
tex,
|
||||
self.global.pos.get(),
|
||||
x_off,
|
||||
y_off,
|
||||
size,
|
||||
&capture,
|
||||
mem,
|
||||
*stride,
|
||||
wl_buffer.format,
|
||||
Transform::None,
|
||||
);
|
||||
if let Err(e) = res {
|
||||
log::warn!("Could not perform shm screencopy: {}", ErrorFmt(e));
|
||||
capture.send_failed();
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
let fb = match wl_buffer.famebuffer.get() {
|
||||
Some(fb) => fb,
|
||||
_ => {
|
||||
log::warn!("Capture buffer has no framebuffer");
|
||||
capture.send_failed();
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let res = self.state.perform_screencopy(
|
||||
tex,
|
||||
&fb,
|
||||
self.global.pos.get(),
|
||||
render_hardware_cursors,
|
||||
x_off - capture.rect.x1(),
|
||||
y_off - capture.rect.y1(),
|
||||
size,
|
||||
Transform::None,
|
||||
);
|
||||
if let Err(e) = res {
|
||||
log::warn!("Could not perform screencopy: {}", ErrorFmt(e));
|
||||
capture.send_failed();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if capture.with_damage.get() {
|
||||
capture.send_damage();
|
||||
}
|
||||
capture.send_ready(now.0.tv_sec as _, now.0.tv_nsec as _);
|
||||
}
|
||||
self.screencast_changed();
|
||||
}
|
||||
|
||||
pub fn clear(&self) {
|
||||
self.global.clear();
|
||||
self.workspace.set(None);
|
||||
|
|
@ -111,6 +208,8 @@ impl OutputNode {
|
|||
self.render_data.borrow_mut().titles.clear();
|
||||
self.lock_surface.take();
|
||||
self.jay_outputs.clear();
|
||||
self.screencasts.clear();
|
||||
self.screencopies.clear();
|
||||
}
|
||||
|
||||
pub fn on_spaces_changed(self: &Rc<Self>) {
|
||||
|
|
@ -228,13 +327,13 @@ impl OutputNode {
|
|||
if Some(ws.id) == active_id {
|
||||
rd.active_workspace = Some(OutputWorkspaceRenderData {
|
||||
rect,
|
||||
captured: ws.capture.get(),
|
||||
captured: ws.has_capture.get(),
|
||||
});
|
||||
} else {
|
||||
if ws.attention_requests.active() {
|
||||
rd.attention_requested_workspaces.push(rect);
|
||||
}
|
||||
if ws.capture.get() {
|
||||
if ws.has_capture.get() {
|
||||
rd.captured_inactive_workspaces.push(rect);
|
||||
} else {
|
||||
rd.inactive_workspaces.push(rect);
|
||||
|
|
@ -345,10 +444,12 @@ impl OutputNode {
|
|||
visible_on_desired_output: Cell::new(false),
|
||||
desired_output: CloneCell::new(self.global.output_id.clone()),
|
||||
jay_workspaces: Default::default(),
|
||||
capture: self.state.default_workspace_capture.clone(),
|
||||
may_capture: self.state.default_workspace_capture.clone(),
|
||||
has_capture: Cell::new(false),
|
||||
title_texture: Default::default(),
|
||||
attention_requests: Default::default(),
|
||||
});
|
||||
ws.update_has_captures();
|
||||
*ws.output_link.borrow_mut() = Some(self.workspaces.add_last(ws.clone()));
|
||||
self.state.workspaces.set(name.to_string(), ws.clone());
|
||||
if self.workspace.is_none() {
|
||||
|
|
|
|||
|
|
@ -49,7 +49,8 @@ pub struct WorkspaceNode {
|
|||
pub visible_on_desired_output: Cell<bool>,
|
||||
pub desired_output: CloneCell<Rc<OutputId>>,
|
||||
pub jay_workspaces: CopyHashMap<(ClientId, JayWorkspaceId), Rc<JayWorkspace>>,
|
||||
pub capture: Cell<bool>,
|
||||
pub may_capture: Cell<bool>,
|
||||
pub has_capture: Cell<bool>,
|
||||
pub title_texture: Cell<Option<TextTexture>>,
|
||||
pub attention_requests: ThresholdCounter,
|
||||
}
|
||||
|
|
@ -62,11 +63,34 @@ impl WorkspaceNode {
|
|||
self.jay_workspaces.clear();
|
||||
}
|
||||
|
||||
pub fn update_has_captures(&self) {
|
||||
let mut has_capture = false;
|
||||
let output = self.output.get();
|
||||
'update: {
|
||||
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;
|
||||
}
|
||||
}
|
||||
if self.has_capture.replace(has_capture) != has_capture {
|
||||
output.schedule_update_render_data();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_output(&self, output: &Rc<OutputNode>) {
|
||||
self.output.set(output.clone());
|
||||
for jw in self.jay_workspaces.lock().values() {
|
||||
jw.send_output(output);
|
||||
}
|
||||
self.update_has_captures();
|
||||
struct OutputSetter<'a>(&'a Rc<OutputNode>);
|
||||
impl NodeVisitorBase for OutputSetter<'_> {
|
||||
fn visit_surface(&mut self, node: &Rc<WlSurface>) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue