Reapplies #27807 after [revert due to not building on ARM](https://github.com/zed-industries/zed/pull/28141) by updating scap to include [a fix to its build on ARM](https://github.com/zed-industries/scap/commit/08f0a01417505cc0990b9931a37e5120db92e0d0) Release Notes: - N/A --------- Co-authored-by: Marshall Bowers <git@maxdeviant.com>
135 lines
3.4 KiB
Rust
135 lines
3.4 KiB
Rust
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,
|
|
};
|
|
|
|
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) -> String {
|
|
"unknown".to_string()
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
fn window_stack(&self) -> Option<Vec<AnyWindowHandle>> {
|
|
None
|
|
}
|
|
|
|
fn open_window(
|
|
&self,
|
|
_handle: AnyWindowHandle,
|
|
_params: WindowParams,
|
|
) -> anyhow::Result<Box<dyn PlatformWindow>> {
|
|
Err(anyhow::anyhow!(
|
|
"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();
|
|
}
|
|
}
|