protocols/screencopy: Make frame/session send stopped/fail on drop

Previously, `Frame` was stored in KMS frame udata, but in some cases the
udata was dropped without a capture happening, and `Frame` did not
implement `Drop`, so `fail` was never sent.

Instead, rename `DropableFrame` to `Frame` and `Frame` to `FrameRef`, so
we can have a single instance of `Frame`, that will send `fail` on drop.
This guarantees either `.success` or `.fail` are send, as long as its
not leaked.

This seems to fix https://github.com/pop-os/cosmic-comp/issues/1305.
xdg-desktop-portal-cosmic prints an error, buy retries (as it should for
an `Unknown` error; though maybe there should be a retry limit) and the
session continues working.

(Not sure if it should be sending `failed`, or queing it with the next
frame so it can send `success` to the client, but this works and is
desirable as a failsafe anyway.)

`Session` and `CursorSession` are similiarly updated.

`.fail()`, `.success()`, and `.stop()` now consume
`Frame`/`Session`/`CursorSession`. So to stop a session, it is now
necessary to call `.remove_session()`, but then simply dropping with
send `.stop()`.

Factoring out some `Request::Capture` handling into a `capture_frame`
function seems to clean up error handling and such a bit.
This commit is contained in:
Ian Douglas Scott 2025-04-30 14:32:33 -07:00 committed by Ian Douglas Scott
parent 9c7033df10
commit 194d5c8967
7 changed files with 346 additions and 367 deletions

View file

@ -27,7 +27,7 @@ use crate::{
utils::{float::NextDown, prelude::*, quirks::workspace_overview_is_open},
wayland::{
handlers::screencopy::SessionHolder,
protocols::screencopy::{BufferConstraints, CursorSession},
protocols::screencopy::{BufferConstraints, CursorSessionRef},
},
};
use calloop::{
@ -2262,7 +2262,7 @@ impl State {
fn cursor_sessions_for_output<'a>(
shell: &'a Shell,
output: &'a Output,
) -> impl Iterator<Item = CursorSession> + 'a {
) -> impl Iterator<Item = CursorSessionRef> + 'a {
shell
.active_space(&output)
.into_iter()