pixelflux/sink.rs
1/*
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
5 */
6
7//! What a capture hands its consumer, and the traits a consumer implements to receive it:
8//! the encoded frames of a capture ([`FrameSink`]), the pointer's image as it changes
9//! ([`CursorSink`]), the clipboard a client application copies to ([`ClipboardSink`]), and
10//! the selection of an application compositor watched from outside ([`SelectionWatch`]).
11//!
12//! Every sink is called on a thread pixelflux owns and never on a capture or compositor
13//! thread: a capture's deliver thread hands frames one batch at a time with one batch in
14//! flight, so a consumer that blocks holds the encoder back by exactly one frame and loses
15//! none; cursor images come from the `wl-cursor` worker or the X11 cursor monitor,
16//! clipboard contents from a reader thread per copy. The Python bridge implements each
17//! trait by taking the GIL and calling the registered callable; a Rust host implements it
18//! directly, or hands a closure, which every trait here accepts.
19
20pub use crate::encoders::reference::Reference;
21pub use crate::encoders::software::{EncodedStripe as Frame, FrameTiming};
22
23/// A consumer of the frames a capture encodes.
24pub trait FrameSink: Send + Sync + 'static {
25 /// Every stripe of one encoded frame, in capture order, each sharing the encoder's
26 /// buffer.
27 fn frames(&self, frames: Vec<Frame>);
28}
29
30impl<F: Fn(Vec<Frame>) + Send + Sync + 'static> FrameSink for F {
31 fn frames(&self, frames: Vec<Frame>) {
32 self(frames)
33 }
34}
35
36/// The pointer's image as the compositor or the X server shows it.
37#[derive(Clone, Debug, PartialEq, Eq)]
38pub struct CursorImage {
39 /// `png` for an image, `hide` for a pointer that shows nothing, `error` where the
40 /// sprite could not be read.
41 pub kind: &'static str,
42 /// The sprite as a straight-alpha PNG, empty unless `kind` is `png`.
43 pub png: Vec<u8>,
44 /// The hotspot within the sprite, in its pixels.
45 pub hot_x: i32,
46 pub hot_y: i32,
47}
48
49/// A consumer of cursor images.
50pub trait CursorSink: Send + Sync + 'static {
51 fn cursor(&self, image: CursorImage);
52}
53
54impl<F: Fn(CursorImage) + Send + Sync + 'static> CursorSink for F {
55 fn cursor(&self, image: CursorImage) {
56 self(image)
57 }
58}
59
60/// A consumer of what client applications copy to the compositor's clipboard.
61pub trait ClipboardSink: Send + Sync + 'static {
62 /// The flavors of one copy as `(mime, bytes)` entries: the picture, or the markup and
63 /// the text beneath it, and a password manager's hint beside a secret. A client
64 /// clearing the clipboard hands over no entries.
65 fn selection(&self, entries: Vec<(String, Vec<u8>)>);
66}
67
68impl<F: Fn(Vec<(String, Vec<u8>)>) + Send + Sync + 'static> ClipboardSink for F {
69 fn selection(&self, entries: Vec<(String, Vec<u8>)>) {
70 self(entries)
71 }
72}
73
74/// A consumer of the selection changes of an application compositor watched over its own
75/// socket (`ScreenCapture::clipboard_watch_app`).
76pub trait SelectionWatch: Send + Sync + 'static {
77 /// The mime types the new selection offers, none for a cleared selection.
78 fn mimes(&self, mimes: Vec<String>);
79}
80
81impl<F: Fn(Vec<String>) + Send + Sync + 'static> SelectionWatch for F {
82 fn mimes(&self, mimes: Vec<String>) {
83 self(mimes)
84 }
85}