Exclude "cosmic-workspace-overview" from workspace screencopy

This commit is contained in:
Ian Douglas Scott 2023-02-10 14:32:56 -08:00
parent 5ba068ec82
commit 26a652f039
4 changed files with 113 additions and 40 deletions

View file

@ -239,10 +239,12 @@ pub fn init_backend(
); );
} }
} else { } else {
if let Err(err) = if let Err(err) = data.state.device_added(
data.state dev,
.device_added(dev, path.into(), &data.display.handle(), true) path.into(),
{ &data.display.handle(),
true,
) {
slog_scope::error!( slog_scope::error!(
"Failed to add drm device {}: {}", "Failed to add drm device {}: {}",
path.display(), path.display(),
@ -322,10 +324,16 @@ pub fn init_backend(
.device_added(dev, path.into(), dh, false) .device_added(dev, path.into(), dh, false)
.with_context(|| format!("Failed to add drm device: {}", path.display()))?; .with_context(|| format!("Failed to add drm device: {}", path.display()))?;
} }
// HACK: amdgpu doesn't like us initializing vulkan too early.. // HACK: amdgpu doesn't like us initializing vulkan too early..
// so lets do that delayed until mesa fixes that. // so lets do that delayed until mesa fixes that.
let devices = state.backend.kms().devices.iter().map(|(drm_node, device)| (*drm_node, device.render_node)).collect::<Vec<_>>(); let devices = state
.backend
.kms()
.devices
.iter()
.map(|(drm_node, device)| (*drm_node, device.render_node))
.collect::<Vec<_>>();
for (drm_node, render_node) in devices { for (drm_node, render_node) in devices {
state.init_vulkan(drm_node, render_node); state.init_vulkan(drm_node, render_node);
} }
@ -333,7 +341,13 @@ pub fn init_backend(
} }
impl State { impl State {
fn device_added(&mut self, dev: dev_t, path: PathBuf, dh: &DisplayHandle, try_vulkan: bool) -> Result<()> { fn device_added(
&mut self,
dev: dev_t,
path: PathBuf,
dh: &DisplayHandle,
try_vulkan: bool,
) -> Result<()> {
if !self.backend.kms().session.is_active() { if !self.backend.kms().session.is_active() {
return Ok(()); return Ok(());
} }

View file

@ -158,6 +158,7 @@ where
cursor_mode, cursor_mode,
screencopy, screencopy,
fps, fps,
false,
); );
result result
@ -175,6 +176,7 @@ pub fn render_workspace<'frame, R, Target, OffTarget, Source>(
mut cursor_mode: CursorMode, mut cursor_mode: CursorMode,
screencopy: Option<(Source, &[(ScreencopySession, BufferParams)])>, screencopy: Option<(Source, &[(ScreencopySession, BufferParams)])>,
mut fps: Option<&mut Fps>, mut fps: Option<&mut Fps>,
exclude_workspace_overview: bool,
) -> Result<(Option<Vec<Rectangle<i32, Physical>>>, RenderElementStates), RenderError<R>> ) -> Result<(Option<Vec<Rectangle<i32, Physical>>>, RenderElementStates), RenderError<R>>
where where
R: Renderer R: Renderer
@ -254,6 +256,7 @@ where
output, output,
&state.shell.override_redirect_windows, &state.shell.override_redirect_windows,
state.xwayland_state.values_mut(), state.xwayland_state.values_mut(),
exclude_workspace_overview,
) )
.map_err(|_| OutputNoMode)? .map_err(|_| OutputNoMode)?
.into_iter() .into_iter()

View file

@ -7,7 +7,7 @@ use crate::{
state::State, state::State,
utils::prelude::*, utils::prelude::*,
wayland::{ wayland::{
handlers::screencopy::DropableSession, handlers::screencopy::{DropableSession, WORKSPACE_OVERVIEW_NAMESPACE},
protocols::{ protocols::{
screencopy::{BufferParams, Session as ScreencopySession}, screencopy::{BufferParams, Session as ScreencopySession},
toplevel_info::ToplevelInfoState, toplevel_info::ToplevelInfoState,
@ -434,6 +434,7 @@ impl Workspace {
output: &Output, output: &Output,
override_redirect_windows: &[X11Surface], override_redirect_windows: &[X11Surface],
xwm_state: impl Iterator<Item = &'a mut XWaylandState>, xwm_state: impl Iterator<Item = &'a mut XWaylandState>,
exclude_workspace_overview: bool,
) -> Result<Vec<WorkspaceRenderElement<R>>, OutputNotMapped> ) -> Result<Vec<WorkspaceRenderElement<R>>, OutputNotMapped>
where where
R: Renderer + ImportAll + ImportMem + AsGlowRenderer, R: Renderer + ImportAll + ImportMem + AsGlowRenderer,
@ -451,7 +452,11 @@ impl Workspace {
layer_map layer_map
.layers() .layers()
.rev() .rev()
.filter(|s| s.layer() == Layer::Overlay) .filter(|s| {
s.layer() == Layer::Overlay
&& !(exclude_workspace_overview
&& s.namespace() == WORKSPACE_OVERVIEW_NAMESPACE)
})
.filter_map(|surface| { .filter_map(|surface| {
layer_map layer_map
.layer_geometry(surface) .layer_geometry(surface)
@ -510,6 +515,10 @@ impl Workspace {
let (lower, upper): (Vec<&LayerSurface>, Vec<&LayerSurface>) = layer_map let (lower, upper): (Vec<&LayerSurface>, Vec<&LayerSurface>) = layer_map
.layers() .layers()
.rev() .rev()
.filter(|s| {
!(exclude_workspace_overview
&& s.namespace() == "cosmic-workspace-overview")
})
.partition(|s| matches!(s.layer(), Layer::Background | Layer::Bottom)); .partition(|s| matches!(s.layer(), Layer::Background | Layer::Bottom));
render_elements.extend( render_elements.extend(

View file

@ -5,6 +5,7 @@ use std::{
}; };
use anyhow::anyhow; use anyhow::anyhow;
use calloop::LoopHandle;
use cosmic_protocols::screencopy::v1::server::zcosmic_screencopy_session_v1::{ use cosmic_protocols::screencopy::v1::server::zcosmic_screencopy_session_v1::{
FailureReason, InputType, FailureReason, InputType,
}; };
@ -24,7 +25,7 @@ use smithay::{
Bind, Blit, BufferType, ExportMem, ImportAll, ImportMem, Offscreen, Renderer, Bind, Blit, BufferType, ExportMem, ImportAll, ImportMem, Offscreen, Renderer,
}, },
}, },
desktop::space::SpaceElement, desktop::{layer_map_for_output, space::SpaceElement},
output::Output, output::Output,
reexports::wayland_server::{ reexports::wayland_server::{
protocol::{wl_buffer::WlBuffer, wl_shm::Format as ShmFormat, wl_surface::WlSurface}, protocol::{wl_buffer::WlBuffer, wl_shm::Format as ShmFormat, wl_surface::WlSurface},
@ -46,7 +47,7 @@ use crate::{
render_output, render_workspace, CursorMode, CLEAR_COLOR, render_output, render_workspace, CursorMode, CLEAR_COLOR,
}, },
shell::{CosmicMappedRenderElement, CosmicSurface}, shell::{CosmicMappedRenderElement, CosmicSurface},
state::{BackendData, ClientState, Common, State}, state::{BackendData, ClientState, Common, Data, State},
utils::prelude::OutputExt, utils::prelude::OutputExt,
wayland::protocols::{ wayland::protocols::{
screencopy::{ screencopy::{
@ -59,6 +60,8 @@ use crate::{
use super::data_device::get_dnd_icon; use super::data_device::get_dnd_icon;
pub const WORKSPACE_OVERVIEW_NAMESPACE: &str = "cosmic-workspace-overview";
pub type PendingScreencopyBuffers = RefCell<Vec<(Session, BufferParams)>>; pub type PendingScreencopyBuffers = RefCell<Vec<(Session, BufferParams)>>;
#[derive(Debug, Default)] #[derive(Debug, Default)]
@ -767,6 +770,7 @@ pub fn render_workspace_to_buffer(
cursor_mode, cursor_mode,
None, None,
None, None,
true,
) )
} else { } else {
let size = buffer_dimensions(buffer).unwrap(); let size = buffer_dimensions(buffer).unwrap();
@ -784,6 +788,7 @@ pub fn render_workspace_to_buffer(
cursor_mode, cursor_mode,
None, None,
None, None,
true,
) )
} }
} }
@ -1144,8 +1149,30 @@ impl State {
output: &Output, output: &Output,
) -> Option<Vec<(Session, BufferParams)>> { ) -> Option<Vec<(Session, BufferParams)>> {
let workspace = self.common.shell.active_space_mut(output); let workspace = self.common.shell.active_space_mut(output);
if !workspace.pending_buffers.is_empty() { let mut pending_buffers = std::mem::take(&mut workspace.pending_buffers);
Some(std::mem::take(&mut workspace.pending_buffers))
let mut i = 0;
while i < pending_buffers.len() {
let layer_map = layer_map_for_output(&output);
if layer_map
.layers()
.any(|s| s.namespace() == WORKSPACE_OVERVIEW_NAMESPACE)
{
let (session, params) = pending_buffers.remove(i);
schedule_offscreen_workspace_session(
&self.common.event_loop_handle,
session,
params,
output.clone(),
workspace.handle.clone(),
);
} else {
i += 1;
}
}
if !pending_buffers.is_empty() {
Some(pending_buffers)
} else { } else {
None None
} }
@ -1174,7 +1201,12 @@ impl State {
if let SessionType::Workspace(o, w) = if let SessionType::Workspace(o, w) =
workspace.pending_buffers[i].0.session_type() workspace.pending_buffers[i].0.session_type()
{ {
if active_spaces.contains(&(o.clone(), w)) { let layer_map = layer_map_for_output(&o);
if active_spaces.contains(&(o.clone(), w))
&& !layer_map
.layers()
.any(|s| s.namespace() == WORKSPACE_OVERVIEW_NAMESPACE)
{
// surface is on an active workspace/output combo, add to workspace_sessions // surface is on an active workspace/output combo, add to workspace_sessions
let (session, params) = workspace.pending_buffers.remove(i); let (session, params) = workspace.pending_buffers.remove(i);
output_sessions output_sessions
@ -1183,32 +1215,13 @@ impl State {
} else if handle == w && output == o { } else if handle == w && output == o {
// surface is visible on an offscreen workspace session, schedule a new render // surface is visible on an offscreen workspace session, schedule a new render
let (session, params) = workspace.pending_buffers.remove(i); let (session, params) = workspace.pending_buffers.remove(i);
let output = output.clone(); schedule_offscreen_workspace_session(
self.common.event_loop_handle.insert_idle(move |data| { &self.common.event_loop_handle,
if !session.alive() { session,
return; params,
} output.clone(),
if !data.state.common.shell.outputs.contains(&output) { handle,
return; );
}
match render_workspace_to_buffer(
&mut data.state,
&session,
params.clone(),
&output,
&handle,
) {
Ok(false) => {
// rendering yielded no new damage, buffer still pending
data.state.common.still_pending(session, params);
}
Ok(true) => {}
Err((reason, err)) => {
slog_scope::warn!("Screencopy session failed: {}", err);
session.failed(reason);
}
}
});
} else { } else {
i += 1; i += 1;
} }
@ -1223,4 +1236,38 @@ impl State {
} }
} }
pub fn schedule_offscreen_workspace_session(
event_loop_handle: &LoopHandle<'static, Data>,
session: Session,
params: BufferParams,
output: Output,
handle: WorkspaceHandle,
) {
event_loop_handle.insert_idle(move |data| {
if !session.alive() {
return;
}
if !data.state.common.shell.outputs.contains(&output) {
return;
}
match render_workspace_to_buffer(
&mut data.state,
&session,
params.clone(),
&output,
&handle,
) {
Ok(false) => {
// rendering yielded no new damage, buffer still pending
data.state.common.still_pending(session, params);
}
Ok(true) => {}
Err((reason, err)) => {
slog_scope::warn!("Screencopy session failed: {}", err);
session.failed(reason);
}
}
});
}
delegate_screencopy!(State); delegate_screencopy!(State);