wayland: Explicitly handle destroyed surfaces
This commit is contained in:
parent
78b9b07cec
commit
38c0acb943
7 changed files with 191 additions and 157 deletions
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue