wayland: Explicitly handle destroyed surfaces

This commit is contained in:
Victoria Brekenfeld 2022-11-08 10:32:53 +01:00
parent 78b9b07cec
commit 38c0acb943
7 changed files with 191 additions and 157 deletions

View file

@ -1,19 +1,11 @@
// SPDX-License-Identifier: GPL-3.0-only
use crate::{
state::BackendData,
utils::prelude::*,
wayland::{
handlers::screencopy::UserdataExt,
protocols::screencopy::{BufferParams, Session as ScreencopySession, SessionType},
},
};
use crate::{state::BackendData, utils::prelude::*, wayland::protocols::screencopy::SessionType};
use smithay::{
backend::renderer::utils::{on_commit_buffer_handler, with_renderer_surface_state},
delegate_compositor,
desktop::{layer_map_for_output, Kind, LayerSurface, PopupKind, WindowSurfaceType},
reexports::wayland_server::protocol::wl_surface::WlSurface,
utils::IsAlive,
wayland::{
compositor::{with_states, CompositorHandler, CompositorState},
shell::{
@ -26,7 +18,7 @@ use smithay::{
};
use std::sync::Mutex;
use super::screencopy::{self, PendingScreencopyBuffers};
use super::screencopy::PendingScreencopyBuffers;
impl State {
fn early_import_surface(&mut self, surface: &WlSurface) {
@ -170,36 +162,11 @@ impl CompositorHandler for State {
);
workspace.commit(surface);
}
// handle window screencopy sessions
let active = element.active_window();
if active.toplevel().wl_surface() == surface {
for (session, params) in active.pending_buffers() {
let window = active.clone();
self.common.event_loop_handle.insert_idle(move |data| {
if !session.alive() {
return;
}
match screencopy::render_window_to_buffer(
&mut data.state,
&session,
params.clone(),
&window,
) {
// rendering yielded no damage, buffer is still pending
Ok(false) => data.state.common.still_pending(session, params),
Ok(true) => {} // success
Err((reason, err)) => {
slog_scope::warn!("Screencopy session failed: {}", err);
session.failed(reason);
}
}
});
}
}
}
//handle window screencopy sessions
self.schedule_window_session(surface);
// We need to know every potential output for importing to the right gpu and scheduling a render,
// so call this only after every potential surface map operation has been done.
self.early_import_surface(surface);
@ -216,66 +183,7 @@ impl CompositorHandler for State {
layer_map_for_output(output).arrange();
}
// here we store additional workspace_sessions, we should handle, when rendering the corresponding output anyway
let mut scheduled_sessions: Option<Vec<(ScreencopySession, BufferParams)>> = None;
// lets check which workspaces this surface belongs to
let active_spaces = self
.common
.shell
.outputs()
.map(|o| (o.clone(), self.common.shell.active_space(o).handle.clone()))
.collect::<Vec<_>>();
for (handle, output) in self.common.shell.workspaces_for_surface(surface) {
let workspace = self.common.shell.space_for_handle_mut(&handle).unwrap();
if !workspace.pending_buffers.is_empty() {
// TODO: replace with drain_filter....
let mut i = 0;
while i < workspace.pending_buffers.len() {
if let SessionType::Workspace(o, w) =
workspace.pending_buffers[i].0.session_type()
{
if active_spaces.contains(&(o.clone(), w)) {
// surface is on an active workspace/output combo, add to workspace_sessions
let (session, params) = workspace.pending_buffers.remove(i);
scheduled_sessions
.get_or_insert_with(Vec::new)
.push((session, params));
} else if handle == w && output == o {
// surface is visible on an offscreen workspace session, schedule a new render
let (session, params) = workspace.pending_buffers.remove(i);
let output = output.clone();
self.common.event_loop_handle.insert_idle(move |data| {
if !session.alive() {
return;
}
match screencopy::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 {
i += 1;
}
} else {
unreachable!();
}
}
}
}
let mut scheduled_sessions = self.schedule_workspace_sessions(surface);
// schedule a new render
for output in self.common.shell.visible_outputs_for_surface(surface) {