Instead of selecting a screen to share arbitrarily, we'll now allow user to select the screen to share. Note that sharing multiple screens at the time is still not supported (though prolly not too far-fetched). Related to #4666  Release Notes: - Added screen selector dropdown to screen share button --------- Co-authored-by: Kirill Bulatov <kirill@zed.dev> Co-authored-by: Cole Miller <cole@zed.dev>
135 lines
3.5 KiB
Rust
135 lines
3.5 KiB
Rust
use std::cell::RefCell;
|
|
use std::rc::Rc;
|
|
|
|
use calloop::{EventLoop, LoopHandle};
|
|
use util::ResultExt;
|
|
|
|
use crate::platform::linux::LinuxClient;
|
|
use crate::platform::{LinuxCommon, PlatformWindow};
|
|
use crate::{
|
|
AnyWindowHandle, CursorStyle, DisplayId, LinuxKeyboardLayout, PlatformDisplay,
|
|
PlatformKeyboardLayout, WindowParams,
|
|
};
|
|
|
|
pub struct HeadlessClientState {
|
|
pub(crate) _loop_handle: LoopHandle<'static, HeadlessClient>,
|
|
pub(crate) event_loop: Option<calloop::EventLoop<'static, HeadlessClient>>,
|
|
pub(crate) common: LinuxCommon,
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
pub(crate) struct HeadlessClient(Rc<RefCell<HeadlessClientState>>);
|
|
|
|
impl HeadlessClient {
|
|
pub(crate) fn new() -> Self {
|
|
let event_loop = EventLoop::try_new().unwrap();
|
|
|
|
let (common, main_receiver) = LinuxCommon::new(event_loop.get_signal());
|
|
|
|
let handle = event_loop.handle();
|
|
|
|
handle
|
|
.insert_source(main_receiver, |event, _, _: &mut HeadlessClient| {
|
|
if let calloop::channel::Event::Msg(runnable) = event {
|
|
runnable.run();
|
|
}
|
|
})
|
|
.ok();
|
|
|
|
HeadlessClient(Rc::new(RefCell::new(HeadlessClientState {
|
|
event_loop: Some(event_loop),
|
|
_loop_handle: handle,
|
|
common,
|
|
})))
|
|
}
|
|
}
|
|
|
|
impl LinuxClient for HeadlessClient {
|
|
fn with_common<R>(&self, f: impl FnOnce(&mut LinuxCommon) -> R) -> R {
|
|
f(&mut self.0.borrow_mut().common)
|
|
}
|
|
|
|
fn keyboard_layout(&self) -> Box<dyn PlatformKeyboardLayout> {
|
|
Box::new(LinuxKeyboardLayout::new("unknown".into()))
|
|
}
|
|
|
|
fn displays(&self) -> Vec<Rc<dyn PlatformDisplay>> {
|
|
vec![]
|
|
}
|
|
|
|
fn primary_display(&self) -> Option<Rc<dyn PlatformDisplay>> {
|
|
None
|
|
}
|
|
|
|
fn display(&self, _id: DisplayId) -> Option<Rc<dyn PlatformDisplay>> {
|
|
None
|
|
}
|
|
|
|
#[cfg(feature = "screen-capture")]
|
|
fn is_screen_capture_supported(&self) -> bool {
|
|
false
|
|
}
|
|
|
|
#[cfg(feature = "screen-capture")]
|
|
fn screen_capture_sources(
|
|
&self,
|
|
) -> futures::channel::oneshot::Receiver<anyhow::Result<Vec<Rc<dyn crate::ScreenCaptureSource>>>>
|
|
{
|
|
let (mut tx, rx) = futures::channel::oneshot::channel();
|
|
tx.send(Err(anyhow::anyhow!(
|
|
"Headless mode does not support screen capture."
|
|
)))
|
|
.ok();
|
|
rx
|
|
}
|
|
|
|
fn active_window(&self) -> Option<AnyWindowHandle> {
|
|
None
|
|
}
|
|
|
|
fn window_stack(&self) -> Option<Vec<AnyWindowHandle>> {
|
|
None
|
|
}
|
|
|
|
fn open_window(
|
|
&self,
|
|
_handle: AnyWindowHandle,
|
|
_params: WindowParams,
|
|
) -> anyhow::Result<Box<dyn PlatformWindow>> {
|
|
anyhow::bail!("neither DISPLAY nor WAYLAND_DISPLAY is set. You can run in headless mode");
|
|
}
|
|
|
|
fn compositor_name(&self) -> &'static str {
|
|
"headless"
|
|
}
|
|
|
|
fn set_cursor_style(&self, _style: CursorStyle) {}
|
|
|
|
fn open_uri(&self, _uri: &str) {}
|
|
|
|
fn reveal_path(&self, _path: std::path::PathBuf) {}
|
|
|
|
fn write_to_primary(&self, _item: crate::ClipboardItem) {}
|
|
|
|
fn write_to_clipboard(&self, _item: crate::ClipboardItem) {}
|
|
|
|
fn read_from_primary(&self) -> Option<crate::ClipboardItem> {
|
|
None
|
|
}
|
|
|
|
fn read_from_clipboard(&self) -> Option<crate::ClipboardItem> {
|
|
None
|
|
}
|
|
|
|
fn run(&self) {
|
|
let mut event_loop = self
|
|
.0
|
|
.borrow_mut()
|
|
.event_loop
|
|
.take()
|
|
.expect("App is already running");
|
|
|
|
event_loop.run(None, &mut self.clone(), |_| {}).log_err();
|
|
}
|
|
}
|