
This changes the workspace/session serialization to also persist the order of windows across restarts. Release Notes: - Improved restoring of windows across restarts: the order of the windows is now also restored. That means windows that were in the foreground when Zed was quit will be in the foreground after restart. (Right now only supported on Linux/X11, not on Linux/Wayland.) Demo: https://github.com/user-attachments/assets/0b8162f8-f06d-43df-88d3-c45d8460fb68
112 lines
2.9 KiB
Rust
112 lines
2.9 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, PlatformDisplay, 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 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 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();
|
|
}
|
|
}
|