Skip to main content

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}