1use std::cell::RefCell;
2use std::ops::Deref;
3use std::rc::Rc;
4use std::time::{Duration, Instant};
5
6use calloop::{EventLoop, LoopHandle};
7use collections::HashMap;
8
9use util::ResultExt;
10
11use crate::platform::linux::LinuxClient;
12use crate::platform::{LinuxCommon, PlatformWindow};
13use crate::{
14 px, AnyWindowHandle, Bounds, CursorStyle, DisplayId, Modifiers, ModifiersChangedEvent, Pixels,
15 PlatformDisplay, PlatformInput, Point, ScrollDelta, Size, TouchPhase, WindowParams,
16};
17
18use calloop::{
19 generic::{FdWrapper, Generic},
20 RegistrationToken,
21};
22
23pub struct HeadlessClientState {
24 pub(crate) loop_handle: LoopHandle<'static, HeadlessClient>,
25 pub(crate) event_loop: Option<calloop::EventLoop<'static, HeadlessClient>>,
26 pub(crate) common: LinuxCommon,
27}
28
29#[derive(Clone)]
30pub(crate) struct HeadlessClient(Rc<RefCell<HeadlessClientState>>);
31
32impl HeadlessClient {
33 pub(crate) fn new() -> Self {
34 let event_loop = EventLoop::try_new().unwrap();
35
36 let (common, main_receiver) = LinuxCommon::new(event_loop.get_signal());
37
38 let handle = event_loop.handle();
39
40 handle.insert_source(main_receiver, |event, _, _: &mut HeadlessClient| {
41 if let calloop::channel::Event::Msg(runnable) = event {
42 runnable.run();
43 }
44 });
45
46 HeadlessClient(Rc::new(RefCell::new(HeadlessClientState {
47 event_loop: Some(event_loop),
48 loop_handle: handle,
49 common,
50 })))
51 }
52}
53
54impl LinuxClient for HeadlessClient {
55 fn with_common<R>(&self, f: impl FnOnce(&mut LinuxCommon) -> R) -> R {
56 f(&mut self.0.borrow_mut().common)
57 }
58
59 fn displays(&self) -> Vec<Rc<dyn PlatformDisplay>> {
60 vec![]
61 }
62
63 fn primary_display(&self) -> Option<Rc<dyn PlatformDisplay>> {
64 None
65 }
66
67 fn display(&self, id: DisplayId) -> Option<Rc<dyn PlatformDisplay>> {
68 None
69 }
70
71 fn can_open_windows(&self) -> anyhow::Result<()> {
72 return Err(anyhow::anyhow!("neither DISPLAY, nor WAYLAND_DISPLAY found. You can still run zed for remote development with --dev-server-token."));
73 }
74
75 fn open_window(
76 &self,
77 _handle: AnyWindowHandle,
78 params: WindowParams,
79 ) -> Box<dyn PlatformWindow> {
80 unimplemented!()
81 }
82
83 fn set_cursor_style(&self, _style: CursorStyle) {}
84
85 fn open_uri(&self, _uri: &str) {}
86
87 fn write_to_primary(&self, item: crate::ClipboardItem) {}
88
89 fn write_to_clipboard(&self, item: crate::ClipboardItem) {}
90
91 fn read_from_primary(&self) -> Option<crate::ClipboardItem> {
92 None
93 }
94
95 fn read_from_clipboard(&self) -> Option<crate::ClipboardItem> {
96 None
97 }
98
99 fn run(&self) {
100 let mut event_loop = self
101 .0
102 .borrow_mut()
103 .event_loop
104 .take()
105 .expect("App is already running");
106
107 event_loop.run(None, &mut self.clone(), |_| {}).log_err();
108 }
109}