Revert "Use scap library to implement screensharing on X11 (#27807)" (#28141)

This reverts commit c2afc2271b.

Build on ARM if failing, likely because `c_char` is `u8` on arm and `i8`
on x86:

```
error[E0308]: mismatched types
   --> /home/runner/.cargo/git/checkouts/scap-40ad33e1dd47aaea/5715067/src/targets/linux/mod.rs:75:74
    |
75  |     let result = unsafe { XmbTextPropertyToTextList(display, &mut xname, &mut list, &mut count) };
    |                           -------------------------                      ^^^^^^^^^ expected `*mut *mut *mut u8`, found `&mut *mut *mut i8`
    |                           |
    |                           arguments to this function are incorrect
    |
    = note:    expected raw pointer `*mut *mut *mut u8`
            found mutable reference `&mut *mut *mut i8`
note: function defined here
   --> /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/x11-2.21.0/src/xlib.rs:552:10
    |
552 |   pub fn XmbTextPropertyToTextList (_4: *mut Display, _3: *const XTextProperty, _2: *mut *mut *mut c_char, _1: *mut c_int) -> c_int,
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^
```

Release Notes:

- N/A
This commit is contained in:
Michael Sloan 2025-04-05 00:01:27 -06:00 committed by GitHub
parent 6ddad64af1
commit c1259c136e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 49 additions and 624 deletions

View file

@ -49,7 +49,6 @@ wayland = [
"filedescriptor",
"xkbcommon",
"open",
"scap",
]
x11 = [
"blade-graphics",
@ -66,7 +65,6 @@ x11 = [
"x11-clipboard",
"filedescriptor",
"open",
"scap"
]
@ -101,11 +99,7 @@ profiling.workspace = true
rand = { optional = true, workspace = true }
raw-window-handle = "0.6"
refineable.workspace = true
resvg = { version = "0.45.0", default-features = false, features = [
"text",
"system-fonts",
"memmap-fonts",
] }
resvg = { version = "0.45.0", default-features = false, features = ["text", "system-fonts", "memmap-fonts"] }
usvg = { version = "0.45.0", default-features = false }
schemars.workspace = true
seahash = "4.1"
@ -165,7 +159,6 @@ cosmic-text = { version = "0.13.2", optional = true }
font-kit = { git = "https://github.com/zed-industries/font-kit", rev = "5474cfad4b719a72ec8ed2cb7327b2b01fd10568", features = [
"source-fontconfig-dlopen",
], optional = true }
scap = { workspace = true, optional = true }
calloop = { version = "0.13.0" }
filedescriptor = { version = "0.8.2", optional = true }
@ -200,10 +193,7 @@ x11rb = { version = "0.13.1", features = [
"resource_manager",
"sync",
], optional = true }
xkbcommon = { version = "0.8.0", features = [
"wayland",
"x11",
], optional = true }
xkbcommon = { version = "0.8.0", features = ["wayland", "x11"], optional = true }
xim = { git = "https://github.com/XDeme1/xim-rs", rev = "d50d461764c2213655cd9cf65a0ea94c70d3c4fd", features = [
"x11rb-xcb",
"x11rb-client",

View file

@ -650,11 +650,6 @@ impl App {
self.platform.primary_display()
}
/// Returns whether `screen_capture_sources` may work.
pub fn is_screen_capture_supported(&self) -> bool {
self.platform.is_screen_capture_supported()
}
/// Returns a list of available screen capture sources.
pub fn screen_capture_sources(
&self,

View file

@ -26,12 +26,6 @@ mod test;
#[cfg(target_os = "windows")]
mod windows;
#[cfg(all(
any(target_os = "linux", target_os = "freebsd"),
any(feature = "wayland", feature = "x11"),
))]
pub(crate) mod scap_screen_capture;
use crate::{
Action, AnyWindowHandle, App, AsyncWindowContext, BackgroundExecutor, Bounds,
DEFAULT_WINDOW_SIZE, DevicePixels, DispatchEventResult, Font, FontId, FontMetrics, FontRun,
@ -164,7 +158,6 @@ pub(crate) trait Platform: 'static {
None
}
fn is_screen_capture_supported(&self) -> bool;
fn screen_capture_sources(
&self,
) -> oneshot::Receiver<Result<Vec<Box<dyn ScreenCaptureSource>>>>;
@ -253,14 +246,13 @@ pub trait PlatformDisplay: Send + Sync + Debug {
/// A source of on-screen video content that can be captured.
pub trait ScreenCaptureSource {
/// Returns the video resolution of this source.
fn resolution(&self) -> Result<Size<DevicePixels>>;
fn resolution(&self) -> Result<Size<Pixels>>;
/// Start capture video from this source, invoking the given callback
/// with each frame.
fn stream(
&self,
foreground_executor: &ForegroundExecutor,
frame_callback: Box<dyn Fn(ScreenCaptureFrame) + Send>,
frame_callback: Box<dyn Fn(ScreenCaptureFrame)>,
) -> oneshot::Receiver<Result<Box<dyn ScreenCaptureStream>>>;
}

View file

@ -21,7 +21,4 @@ pub(crate) use wayland::*;
#[cfg(feature = "x11")]
pub(crate) use x11::*;
#[cfg(any(feature = "wayland", feature = "x11"))]
pub(crate) type PlatformScreenCaptureFrame = scap::frame::Frame;
#[cfg(not(any(feature = "wayland", feature = "x11")))]
pub(crate) type PlatformScreenCaptureFrame = ();

View file

@ -1,16 +1,13 @@
use std::cell::RefCell;
use std::rc::Rc;
use anyhow::anyhow;
use calloop::{EventLoop, LoopHandle};
use futures::channel::oneshot;
use util::ResultExt;
use crate::platform::linux::LinuxClient;
use crate::platform::{LinuxCommon, PlatformWindow};
use crate::{
AnyWindowHandle, CursorStyle, DisplayId, PlatformDisplay, ScreenCaptureSource, WindowParams,
};
use crate::{AnyWindowHandle, CursorStyle, DisplayId, PlatformDisplay, WindowParams};
pub struct HeadlessClientState {
pub(crate) _loop_handle: LoopHandle<'static, HeadlessClient>,
@ -66,21 +63,6 @@ impl LinuxClient for HeadlessClient {
None
}
fn is_screen_capture_supported(&self) -> bool {
false
}
fn screen_capture_sources(
&self,
) -> oneshot::Receiver<anyhow::Result<Vec<Box<dyn ScreenCaptureSource>>>> {
let (mut tx, rx) = oneshot::channel();
tx.send(Err(anyhow!(
"Headless mode does not support screen capture."
)))
.ok();
rx
}
fn active_window(&self) -> Option<AnyWindowHandle> {
None
}

View file

@ -28,7 +28,6 @@ use crate::{
Pixels, Platform, PlatformDisplay, PlatformTextSystem, PlatformWindow, Point, Result,
ScreenCaptureSource, Task, WindowAppearance, WindowParams, px,
};
#[cfg(any(feature = "wayland", feature = "x11"))]
pub(crate) const SCROLL_LINES: f32 = 3.0;
@ -51,10 +50,6 @@ pub trait LinuxClient {
#[allow(unused)]
fn display(&self, id: DisplayId) -> Option<Rc<dyn PlatformDisplay>>;
fn primary_display(&self) -> Option<Rc<dyn PlatformDisplay>>;
fn is_screen_capture_supported(&self) -> bool;
fn screen_capture_sources(
&self,
) -> oneshot::Receiver<Result<Vec<Box<dyn ScreenCaptureSource>>>>;
fn open_window(
&self,
@ -235,14 +230,12 @@ impl<P: LinuxClient + 'static> Platform for P {
self.displays()
}
fn is_screen_capture_supported(&self) -> bool {
self.is_screen_capture_supported()
}
fn screen_capture_sources(
&self,
) -> oneshot::Receiver<Result<Vec<Box<dyn ScreenCaptureSource>>>> {
self.screen_capture_sources()
let (mut tx, rx) = oneshot::channel();
tx.send(Err(anyhow!("screen capture not implemented"))).ok();
rx
}
fn active_window(&self) -> Option<AnyWindowHandle> {

View file

@ -7,7 +7,6 @@ use std::{
time::{Duration, Instant},
};
use anyhow::anyhow;
use calloop::{
EventLoop, LoopHandle,
timer::{TimeoutAction, Timer},
@ -15,7 +14,7 @@ use calloop::{
use calloop_wayland_source::WaylandSource;
use collections::HashMap;
use filedescriptor::Pipe;
use futures::channel::oneshot;
use http_client::Url;
use smallvec::SmallVec;
use util::ResultExt;
@ -86,8 +85,7 @@ use crate::{
FileDropEvent, ForegroundExecutor, KeyDownEvent, KeyUpEvent, Keystroke, LinuxCommon, Modifiers,
ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseExitEvent, MouseMoveEvent,
MouseUpEvent, NavigationDirection, Pixels, PlatformDisplay, PlatformInput, Point, SCROLL_LINES,
ScaledPixels, ScreenCaptureSource, ScrollDelta, ScrollWheelEvent, Size, TouchPhase,
WindowParams, point, px, size,
ScaledPixels, ScrollDelta, ScrollWheelEvent, Size, TouchPhase, WindowParams, point, px, size,
};
/// Used to convert evdev scancode to xkb scancode
@ -635,24 +633,6 @@ impl LinuxClient for WaylandClient {
None
}
fn is_screen_capture_supported(&self) -> bool {
false
}
fn screen_capture_sources(
&self,
) -> oneshot::Receiver<anyhow::Result<Vec<Box<dyn ScreenCaptureSource>>>> {
// TODO: Get screen capture working on wayland. Be sure to try window resizing as that may
// be tricky.
//
// start_scap_default_target_source()
let (sources_tx, sources_rx) = oneshot::channel();
sources_tx
.send(Err(anyhow!("Wayland screen capture not yet implemented.")))
.ok();
sources_rx
}
fn open_window(
&self,
handle: AnyWindowHandle,

View file

@ -1,4 +1,3 @@
use crate::platform::scap_screen_capture::scap_screen_sources;
use core::str;
use std::{
cell::RefCell,
@ -9,13 +8,13 @@ use std::{
time::{Duration, Instant},
};
use anyhow::Context as _;
use calloop::{
EventLoop, LoopHandle, RegistrationToken,
generic::{FdWrapper, Generic},
};
use anyhow::Context as _;
use collections::HashMap;
use futures::channel::oneshot;
use http_client::Url;
use smallvec::SmallVec;
use util::ResultExt;
@ -60,8 +59,8 @@ use crate::platform::{
use crate::{
AnyWindowHandle, Bounds, ClipboardItem, CursorStyle, DisplayId, FileDropEvent, Keystroke,
Modifiers, ModifiersChangedEvent, MouseButton, Pixels, Platform, PlatformDisplay,
PlatformInput, Point, RequestFrameOptions, ScaledPixels, ScreenCaptureSource, ScrollDelta,
Size, TouchPhase, WindowParams, X11Window, modifiers_from_xinput_info, point, px,
PlatformInput, Point, RequestFrameOptions, ScaledPixels, ScrollDelta, Size, TouchPhase,
WindowParams, X11Window, modifiers_from_xinput_info, point, px,
};
/// Value for DeviceId parameters which selects all devices.
@ -1328,16 +1327,6 @@ impl LinuxClient for X11Client {
))
}
fn is_screen_capture_supported(&self) -> bool {
true
}
fn screen_capture_sources(
&self,
) -> oneshot::Receiver<anyhow::Result<Vec<Box<dyn ScreenCaptureSource>>>> {
scap_screen_sources(&self.0.borrow().common.foreground_executor)
}
fn open_window(
&self,
handle: AnyWindowHandle,

View file

@ -552,10 +552,6 @@ impl Platform for MacPlatform {
.collect()
}
fn is_screen_capture_supported(&self) -> bool {
true
}
fn screen_capture_sources(
&self,
) -> oneshot::Receiver<Result<Vec<Box<dyn ScreenCaptureSource>>>> {

View file

@ -1,7 +1,7 @@
use crate::{
DevicePixels, ForegroundExecutor, Size,
Pixels, Size,
platform::{ScreenCaptureFrame, ScreenCaptureSource, ScreenCaptureStream},
size,
px, size,
};
use anyhow::{Result, anyhow};
use block::ConcreteBlock;
@ -48,7 +48,7 @@ const FRAME_CALLBACK_IVAR: &str = "frame_callback";
const SCStreamOutputTypeScreen: NSInteger = 0;
impl ScreenCaptureSource for MacScreenCaptureSource {
fn resolution(&self) -> Result<Size<DevicePixels>> {
fn resolution(&self) -> Result<Size<Pixels>> {
unsafe {
let display_id: CGDirectDisplayID = msg_send![self.sc_display, displayID];
let display_mode_ref = CGDisplayCopyDisplayMode(display_id);
@ -56,17 +56,13 @@ impl ScreenCaptureSource for MacScreenCaptureSource {
let height = CGDisplayModeGetPixelHeight(display_mode_ref);
CGDisplayModeRelease(display_mode_ref);
Ok(size(
DevicePixels(width as i32),
DevicePixels(height as i32),
))
Ok(size(px(width as f32), px(height as f32)))
}
}
fn stream(
&self,
_foreground_executor: &ForegroundExecutor,
frame_callback: Box<dyn Fn(ScreenCaptureFrame) + Send>,
frame_callback: Box<dyn Fn(ScreenCaptureFrame)>,
) -> oneshot::Receiver<Result<Box<dyn ScreenCaptureStream>>> {
unsafe {
let stream: id = msg_send![class!(SCStream), alloc];

View file

@ -1,282 +0,0 @@
//! Screen capture for Linux and Windows
use crate::{
DevicePixels, ForegroundExecutor, ScreenCaptureFrame, ScreenCaptureSource, ScreenCaptureStream,
Size, size,
};
use anyhow::{Context as _, Result, anyhow};
use futures::channel::oneshot;
use std::sync::Arc;
use std::sync::atomic::{self, AtomicBool};
/// Populates the receiver with the screens that can be captured.
///
/// `scap_default_target_source` should be used instead on Wayland, since `scap_screen_sources`
/// won't return any results.
#[allow(dead_code)]
pub(crate) fn scap_screen_sources(
foreground_executor: &ForegroundExecutor,
) -> oneshot::Receiver<Result<Vec<Box<dyn ScreenCaptureSource>>>> {
let (sources_tx, sources_rx) = oneshot::channel();
get_screen_targets(sources_tx);
to_dyn_screen_capture_sources(sources_rx, foreground_executor)
}
/// Starts screen capture for the default target, and populates the receiver with a single source
/// for it. The first frame of the screen capture is used to determine the size of the stream.
///
/// On Wayland (Linux), prompts the user to select a target, and populates the receiver with a
/// single screen capture source for their selection.
#[allow(dead_code)]
pub(crate) fn start_scap_default_target_source(
foreground_executor: &ForegroundExecutor,
) -> oneshot::Receiver<Result<Vec<Box<dyn ScreenCaptureSource>>>> {
let (sources_tx, sources_rx) = oneshot::channel();
start_default_target_screen_capture(sources_tx);
to_dyn_screen_capture_sources(sources_rx, foreground_executor)
}
struct ScapCaptureSource {
target: scap::Target,
size: Size<DevicePixels>,
}
/// Populates the sender with the screens available for capture.
fn get_screen_targets(sources_tx: oneshot::Sender<Result<Vec<ScapCaptureSource>>>) {
// Due to use of blocking APIs, a new thread is used.
std::thread::spawn(|| {
let targets = match scap::get_all_targets() {
Ok(targets) => targets,
Err(err) => {
sources_tx.send(Err(err)).ok();
return;
}
};
let sources = targets
.iter()
.filter_map(|target| match target {
scap::Target::Display(display) => {
let size = Size {
width: DevicePixels(display.width as i32),
height: DevicePixels(display.height as i32),
};
Some(ScapCaptureSource {
target: target.clone(),
size,
})
}
scap::Target::Window(_) => None,
})
.collect::<Vec<_>>();
sources_tx.send(Ok(sources)).ok();
});
}
impl ScreenCaptureSource for ScapCaptureSource {
fn resolution(&self) -> Result<Size<DevicePixels>> {
Ok(self.size)
}
fn stream(
&self,
foreground_executor: &ForegroundExecutor,
frame_callback: Box<dyn Fn(ScreenCaptureFrame) + Send>,
) -> oneshot::Receiver<Result<Box<dyn ScreenCaptureStream>>> {
let (stream_tx, stream_rx) = oneshot::channel();
let target = self.target.clone();
// Due to use of blocking APIs, a dedicated thread is used.
std::thread::spawn(move || match new_scap_capturer(Some(target)) {
Ok(mut capturer) => {
capturer.start_capture();
run_capture(capturer, frame_callback, stream_tx);
}
Err(e) => {
stream_tx.send(Err(e)).ok();
}
});
to_dyn_screen_capture_stream(stream_rx, foreground_executor)
}
}
struct ScapDefaultTargetCaptureSource {
// Sender populated by single call to `ScreenCaptureSource::stream`.
stream_call_tx: std::sync::mpsc::SyncSender<(
// Provides the result of `ScreenCaptureSource::stream`.
oneshot::Sender<Result<ScapStream>>,
// Callback for frames.
Box<dyn Fn(ScreenCaptureFrame) + Send>,
)>,
size: Size<DevicePixels>,
}
/// Starts screen capture on the default capture target, and populates the sender with the source.
fn start_default_target_screen_capture(
sources_tx: oneshot::Sender<Result<Vec<ScapDefaultTargetCaptureSource>>>,
) {
// Due to use of blocking APIs, a dedicated thread is used.
std::thread::spawn(|| {
let start_result = util::maybe!({
let mut capturer = new_scap_capturer(None)?;
capturer.start_capture();
let first_frame = capturer
.get_next_frame()
.context("Failed to get first frame of screenshare to get the size.")?;
let size = frame_size(&first_frame);
Ok((capturer, size))
});
match start_result {
Err(e) => {
sources_tx.send(Err(e)).ok();
}
Ok((capturer, size)) => {
let (stream_call_tx, stream_rx) = std::sync::mpsc::sync_channel(1);
sources_tx
.send(Ok(vec![ScapDefaultTargetCaptureSource {
stream_call_tx,
size,
}]))
.ok();
let Ok((stream_tx, frame_callback)) = stream_rx.recv() else {
return;
};
run_capture(capturer, frame_callback, stream_tx);
}
}
});
}
impl ScreenCaptureSource for ScapDefaultTargetCaptureSource {
fn resolution(&self) -> Result<Size<DevicePixels>> {
Ok(self.size)
}
fn stream(
&self,
foreground_executor: &ForegroundExecutor,
frame_callback: Box<dyn Fn(ScreenCaptureFrame) + Send>,
) -> oneshot::Receiver<Result<Box<dyn ScreenCaptureStream>>> {
let (tx, rx) = oneshot::channel();
match self.stream_call_tx.try_send((tx, frame_callback)) {
Ok(()) => {}
Err(std::sync::mpsc::TrySendError::Full((tx, _)))
| Err(std::sync::mpsc::TrySendError::Disconnected((tx, _))) => {
// Note: support could be added for being called again after end of prior stream.
tx.send(Err(anyhow!(
"Can't call ScapDefaultTargetCaptureSource::stream multiple times."
)))
.ok();
}
}
to_dyn_screen_capture_stream(rx, foreground_executor)
}
}
fn new_scap_capturer(target: Option<scap::Target>) -> Result<scap::capturer::Capturer> {
scap::capturer::Capturer::build(scap::capturer::Options {
fps: 60,
show_cursor: true,
show_highlight: true,
// Note that the actual frame output type may differ.
output_type: scap::frame::FrameType::YUVFrame,
output_resolution: scap::capturer::Resolution::Captured,
crop_area: None,
target,
excluded_targets: None,
})
}
fn run_capture(
mut capturer: scap::capturer::Capturer,
frame_callback: Box<dyn Fn(ScreenCaptureFrame) + Send>,
stream_tx: oneshot::Sender<Result<ScapStream>>,
) {
let cancel_stream = Arc::new(AtomicBool::new(false));
let stream_send_result = stream_tx.send(Ok(ScapStream {
cancel_stream: cancel_stream.clone(),
}));
if let Err(_) = stream_send_result {
return;
}
while !cancel_stream.load(std::sync::atomic::Ordering::SeqCst) {
match capturer.get_next_frame() {
Ok(frame) => frame_callback(ScreenCaptureFrame(frame)),
Err(err) => {
log::error!("Halting screen capture due to error: {err}");
break;
}
}
}
capturer.stop_capture();
}
struct ScapStream {
cancel_stream: Arc<AtomicBool>,
}
impl ScreenCaptureStream for ScapStream {}
impl Drop for ScapStream {
fn drop(&mut self) {
self.cancel_stream.store(true, atomic::Ordering::SeqCst);
}
}
fn frame_size(frame: &scap::frame::Frame) -> Size<DevicePixels> {
let (width, height) = match frame {
scap::frame::Frame::YUVFrame(frame) => (frame.width, frame.height),
scap::frame::Frame::RGB(frame) => (frame.width, frame.height),
scap::frame::Frame::RGBx(frame) => (frame.width, frame.height),
scap::frame::Frame::XBGR(frame) => (frame.width, frame.height),
scap::frame::Frame::BGRx(frame) => (frame.width, frame.height),
scap::frame::Frame::BGR0(frame) => (frame.width, frame.height),
scap::frame::Frame::BGRA(frame) => (frame.width, frame.height),
};
size(DevicePixels(width), DevicePixels(height))
}
/// This is used by `get_screen_targets` and `start_default_target_screen_capture` to turn their
/// results into `Box<dyn ScreenCaptureSource>`. They need to `Send` their capture source, and so
/// the capture source structs are used as `Box<dyn ScreenCaptureSource>` is not `Send`.
fn to_dyn_screen_capture_sources<T: ScreenCaptureSource + 'static>(
sources_rx: oneshot::Receiver<Result<Vec<T>>>,
foreground_executor: &ForegroundExecutor,
) -> oneshot::Receiver<Result<Vec<Box<dyn ScreenCaptureSource>>>> {
let (dyn_sources_tx, dyn_sources_rx) = oneshot::channel();
foreground_executor
.spawn(async move {
match sources_rx.await {
Ok(Ok(results)) => dyn_sources_tx
.send(Ok(results
.into_iter()
.map(|source| Box::new(source) as Box<dyn ScreenCaptureSource>)
.collect::<Vec<_>>()))
.ok(),
Ok(Err(err)) => dyn_sources_tx.send(Err(err)).ok(),
Err(oneshot::Canceled) => None,
}
})
.detach();
dyn_sources_rx
}
/// Same motivation as `to_dyn_screen_capture_sources` above.
fn to_dyn_screen_capture_stream<T: ScreenCaptureStream + 'static>(
sources_rx: oneshot::Receiver<Result<T>>,
foreground_executor: &ForegroundExecutor,
) -> oneshot::Receiver<Result<Box<dyn ScreenCaptureStream>>> {
let (dyn_sources_tx, dyn_sources_rx) = oneshot::channel();
foreground_executor
.spawn(async move {
match sources_rx.await {
Ok(Ok(stream)) => dyn_sources_tx
.send(Ok(Box::new(stream) as Box<dyn ScreenCaptureStream>))
.ok(),
Ok(Err(err)) => dyn_sources_tx.send(Err(err)).ok(),
Err(oneshot::Canceled) => None,
}
})
.detach();
dyn_sources_rx
}

View file

@ -1,8 +1,7 @@
use crate::{
AnyWindowHandle, BackgroundExecutor, ClipboardItem, CursorStyle, DevicePixels,
ForegroundExecutor, Keymap, Platform, PlatformDisplay, PlatformTextSystem, ScreenCaptureFrame,
ScreenCaptureSource, ScreenCaptureStream, Size, Task, TestDisplay, TestWindow,
WindowAppearance, WindowParams, size,
AnyWindowHandle, BackgroundExecutor, ClipboardItem, CursorStyle, ForegroundExecutor, Keymap,
Platform, PlatformDisplay, PlatformTextSystem, ScreenCaptureFrame, ScreenCaptureSource,
ScreenCaptureStream, Task, TestDisplay, TestWindow, WindowAppearance, WindowParams, px, size,
};
use anyhow::Result;
use collections::VecDeque;
@ -47,14 +46,13 @@ pub struct TestScreenCaptureSource {}
pub struct TestScreenCaptureStream {}
impl ScreenCaptureSource for TestScreenCaptureSource {
fn resolution(&self) -> Result<Size<DevicePixels>> {
Ok(size(DevicePixels(1), DevicePixels(1)))
fn resolution(&self) -> Result<crate::Size<crate::Pixels>> {
Ok(size(px(1.), px(1.)))
}
fn stream(
&self,
_foreground_executor: &ForegroundExecutor,
_frame_callback: Box<dyn Fn(ScreenCaptureFrame) + Send>,
_frame_callback: Box<dyn Fn(ScreenCaptureFrame)>,
) -> oneshot::Receiver<Result<Box<dyn ScreenCaptureStream>>> {
let (mut tx, rx) = oneshot::channel();
let stream = TestScreenCaptureStream {};
@ -273,10 +271,6 @@ impl Platform for TestPlatform {
Some(self.active_display.clone())
}
fn is_screen_capture_supported(&self) -> bool {
true
}
fn screen_capture_sources(
&self,
) -> oneshot::Receiver<Result<Vec<Box<dyn ScreenCaptureSource>>>> {

View file

@ -396,10 +396,6 @@ impl Platform for WindowsPlatform {
WindowsDisplay::primary_monitor().map(|display| Rc::new(display) as Rc<dyn PlatformDisplay>)
}
fn is_screen_capture_supported(&self) -> bool {
false
}
fn screen_capture_sources(
&self,
) -> oneshot::Receiver<Result<Vec<Box<dyn ScreenCaptureSource>>>> {