Compare commits
2 Commits
scan-code
...
no-panic-o
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f802444e79 | ||
|
|
7716fa8312 |
7
Cargo.lock
generated
7
Cargo.lock
generated
@@ -1511,7 +1511,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "blade-graphics"
|
||||
version = "0.4.0"
|
||||
source = "git+https://github.com/kvark/blade?rev=bdaf8c534fbbc9fbca71d1cf272f45640b3a068d#bdaf8c534fbbc9fbca71d1cf272f45640b3a068d"
|
||||
source = "git+https://github.com/zed-industries/blade?rev=86bf7228f50f44058edf7872055261efd9eca9de#86bf7228f50f44058edf7872055261efd9eca9de"
|
||||
dependencies = [
|
||||
"ash",
|
||||
"ash-window",
|
||||
@@ -1541,7 +1541,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "blade-macros"
|
||||
version = "0.2.1"
|
||||
source = "git+https://github.com/kvark/blade?rev=bdaf8c534fbbc9fbca71d1cf272f45640b3a068d#bdaf8c534fbbc9fbca71d1cf272f45640b3a068d"
|
||||
source = "git+https://github.com/zed-industries/blade?rev=86bf7228f50f44058edf7872055261efd9eca9de#86bf7228f50f44058edf7872055261efd9eca9de"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1551,7 +1551,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "blade-util"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/kvark/blade?rev=bdaf8c534fbbc9fbca71d1cf272f45640b3a068d#bdaf8c534fbbc9fbca71d1cf272f45640b3a068d"
|
||||
source = "git+https://github.com/zed-industries/blade?rev=86bf7228f50f44058edf7872055261efd9eca9de#86bf7228f50f44058edf7872055261efd9eca9de"
|
||||
dependencies = [
|
||||
"blade-graphics",
|
||||
"bytemuck",
|
||||
@@ -13152,6 +13152,7 @@ version = "0.140.0"
|
||||
dependencies = [
|
||||
"activity_indicator",
|
||||
"anyhow",
|
||||
"ashpd",
|
||||
"assets",
|
||||
"assistant",
|
||||
"audio",
|
||||
|
||||
@@ -267,9 +267,9 @@ async-tar = "0.4.2"
|
||||
async-trait = "0.1"
|
||||
async_zip = { version = "0.0.17", features = ["deflate", "deflate64"] }
|
||||
bitflags = "2.4.2"
|
||||
blade-graphics = { git = "https://github.com/kvark/blade", rev = "bdaf8c534fbbc9fbca71d1cf272f45640b3a068d" }
|
||||
blade-macros = { git = "https://github.com/kvark/blade", rev = "bdaf8c534fbbc9fbca71d1cf272f45640b3a068d" }
|
||||
blade-util = { git = "https://github.com/kvark/blade", rev = "bdaf8c534fbbc9fbca71d1cf272f45640b3a068d" }
|
||||
blade-graphics = { git = "https://github.com/zed-industries/blade", rev = "86bf7228f50f44058edf7872055261efd9eca9de" }
|
||||
blade-macros = { git = "https://github.com/zed-industries/blade", rev = "86bf7228f50f44058edf7872055261efd9eca9de" }
|
||||
blade-util = { git = "https://github.com/zed-industries/blade", rev = "86bf7228f50f44058edf7872055261efd9eca9de" }
|
||||
cap-std = "3.0"
|
||||
cargo_toml = "0.20"
|
||||
chrono = { version = "0.4", features = ["serde"] }
|
||||
|
||||
@@ -97,7 +97,7 @@ pub fn open_prompt_library(
|
||||
},
|
||||
|cx| cx.new_view(|cx| PromptLibrary::new(store, language_registry, cx)),
|
||||
)
|
||||
})
|
||||
})?
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ use settings::Settings;
|
||||
use std::sync::{Arc, Weak};
|
||||
use theme::ThemeSettings;
|
||||
use ui::{prelude::*, Button, Label};
|
||||
use util::ResultExt;
|
||||
use workspace::AppState;
|
||||
|
||||
pub fn init(app_state: &Arc<AppState>, cx: &mut AppContext) {
|
||||
@@ -27,16 +28,21 @@ pub fn init(app_state: &Arc<AppState>, cx: &mut AppContext) {
|
||||
|
||||
for screen in cx.displays() {
|
||||
let options = notification_window_options(screen, window_size, cx);
|
||||
let window = cx.open_window(options, |cx| {
|
||||
cx.new_view(|_| {
|
||||
ProjectSharedNotification::new(
|
||||
owner.clone(),
|
||||
*project_id,
|
||||
worktree_root_names.clone(),
|
||||
app_state.clone(),
|
||||
)
|
||||
let Some(window) = cx
|
||||
.open_window(options, |cx| {
|
||||
cx.new_view(|_| {
|
||||
ProjectSharedNotification::new(
|
||||
owner.clone(),
|
||||
*project_id,
|
||||
worktree_root_names.clone(),
|
||||
app_state.clone(),
|
||||
)
|
||||
})
|
||||
})
|
||||
});
|
||||
.log_err()
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
notification_windows
|
||||
.entry(*project_id)
|
||||
.or_insert(Vec::new())
|
||||
|
||||
@@ -509,6 +509,7 @@ fn test_clone(cx: &mut TestAppContext) {
|
||||
.update(cx, |editor, cx| {
|
||||
cx.open_window(Default::default(), |cx| cx.new_view(|cx| editor.clone(cx)))
|
||||
})
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
let snapshot = editor.update(cx, |e, cx| e.snapshot(cx)).unwrap();
|
||||
@@ -7657,6 +7658,7 @@ async fn test_following(cx: &mut gpui::TestAppContext) {
|
||||
},
|
||||
|cx| cx.new_view(|cx| build_editor(buffer.clone(), cx)),
|
||||
)
|
||||
.unwrap()
|
||||
});
|
||||
|
||||
let is_still_following = Rc::new(RefCell::new(true));
|
||||
|
||||
@@ -76,6 +76,7 @@ fn main() {
|
||||
cx.open_window(options, |cx| {
|
||||
cx.activate(false);
|
||||
cx.new_view(|_cx| AnimationExample {})
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ fn main() {
|
||||
text: "World".into(),
|
||||
})
|
||||
},
|
||||
);
|
||||
)
|
||||
.unwrap();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -93,6 +93,7 @@ fn main() {
|
||||
local_resource: Arc::new(PathBuf::from_str("examples/image/app-icon.png").unwrap()),
|
||||
remote_resource: "https://picsum.photos/512/512".into(),
|
||||
})
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -29,7 +29,8 @@ fn main() {
|
||||
}]);
|
||||
cx.open_window(WindowOptions::default(), |cx| {
|
||||
cx.new_view(|_cx| SetMenus {})
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,8 @@ fn main() {
|
||||
cx.new_view(|_| WindowContent {
|
||||
text: format!("{:?}", screen.id()).into(),
|
||||
})
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -490,26 +490,26 @@ impl AppContext {
|
||||
&mut self,
|
||||
options: crate::WindowOptions,
|
||||
build_root_view: impl FnOnce(&mut WindowContext) -> View<V>,
|
||||
) -> WindowHandle<V> {
|
||||
) -> anyhow::Result<WindowHandle<V>> {
|
||||
self.update(|cx| {
|
||||
let id = cx.windows.insert(None);
|
||||
let handle = WindowHandle::new(id);
|
||||
let mut window = Window::new(handle.into(), options, cx);
|
||||
let root_view = build_root_view(&mut WindowContext::new(cx, &mut window));
|
||||
window.root_view.replace(root_view.into());
|
||||
cx.window_handles.insert(id, window.handle);
|
||||
cx.windows.get_mut(id).unwrap().replace(window);
|
||||
handle
|
||||
match Window::new(handle.into(), options, cx) {
|
||||
Ok(mut window) => {
|
||||
let root_view = build_root_view(&mut WindowContext::new(cx, &mut window));
|
||||
window.root_view.replace(root_view.into());
|
||||
cx.window_handles.insert(id, window.handle);
|
||||
cx.windows.get_mut(id).unwrap().replace(window);
|
||||
Ok(handle)
|
||||
}
|
||||
Err(e) => {
|
||||
cx.windows.remove(id);
|
||||
return Err(e);
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns Ok() if the platform supports opening windows.
|
||||
/// This returns false (for example) on linux when we could
|
||||
/// not establish a connection to X or Wayland.
|
||||
pub fn can_open_windows(&self) -> anyhow::Result<()> {
|
||||
self.platform.can_open_windows()
|
||||
}
|
||||
|
||||
/// Instructs the platform to activate the application by bringing it to the foreground.
|
||||
pub fn activate(&self, ignoring_other_apps: bool) {
|
||||
self.platform.activate(ignoring_other_apps);
|
||||
|
||||
@@ -151,7 +151,7 @@ impl AsyncAppContext {
|
||||
.upgrade()
|
||||
.ok_or_else(|| anyhow!("app was released"))?;
|
||||
let mut lock = app.borrow_mut();
|
||||
Ok(lock.open_window(options, build_root_view))
|
||||
lock.open_window(options, build_root_view)
|
||||
}
|
||||
|
||||
/// Schedule a future to be polled in the background.
|
||||
|
||||
@@ -193,19 +193,22 @@ impl TestAppContext {
|
||||
},
|
||||
|cx| cx.new_view(build_window),
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
/// Adds a new window with no content.
|
||||
pub fn add_empty_window(&mut self) -> &mut VisualTestContext {
|
||||
let mut cx = self.app.borrow_mut();
|
||||
let bounds = Bounds::maximized(None, &mut cx);
|
||||
let window = cx.open_window(
|
||||
WindowOptions {
|
||||
window_bounds: Some(WindowBounds::Windowed(bounds)),
|
||||
..Default::default()
|
||||
},
|
||||
|cx| cx.new_view(|_| Empty),
|
||||
);
|
||||
let window = cx
|
||||
.open_window(
|
||||
WindowOptions {
|
||||
window_bounds: Some(WindowBounds::Windowed(bounds)),
|
||||
..Default::default()
|
||||
},
|
||||
|cx| cx.new_view(|_| Empty),
|
||||
)
|
||||
.unwrap();
|
||||
drop(cx);
|
||||
let cx = VisualTestContext::from_window(*window.deref(), self).as_mut();
|
||||
cx.run_until_parked();
|
||||
@@ -222,13 +225,15 @@ impl TestAppContext {
|
||||
{
|
||||
let mut cx = self.app.borrow_mut();
|
||||
let bounds = Bounds::maximized(None, &mut cx);
|
||||
let window = cx.open_window(
|
||||
WindowOptions {
|
||||
window_bounds: Some(WindowBounds::Windowed(bounds)),
|
||||
..Default::default()
|
||||
},
|
||||
|cx| cx.new_view(build_root_view),
|
||||
);
|
||||
let window = cx
|
||||
.open_window(
|
||||
WindowOptions {
|
||||
window_bounds: Some(WindowBounds::Windowed(bounds)),
|
||||
..Default::default()
|
||||
},
|
||||
|cx| cx.new_view(build_root_view),
|
||||
)
|
||||
.unwrap();
|
||||
drop(cx);
|
||||
let view = window.root_view(self).unwrap();
|
||||
let cx = VisualTestContext::from_window(*window.deref(), self).as_mut();
|
||||
|
||||
@@ -486,6 +486,7 @@ mod test {
|
||||
focus_handle: cx.focus_handle(),
|
||||
})
|
||||
})
|
||||
.unwrap()
|
||||
});
|
||||
|
||||
cx.update(|cx| {
|
||||
|
||||
@@ -106,14 +106,12 @@ pub(crate) trait Platform: 'static {
|
||||
fn displays(&self) -> Vec<Rc<dyn PlatformDisplay>>;
|
||||
fn primary_display(&self) -> Option<Rc<dyn PlatformDisplay>>;
|
||||
fn active_window(&self) -> Option<AnyWindowHandle>;
|
||||
fn can_open_windows(&self) -> anyhow::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn open_window(
|
||||
&self,
|
||||
handle: AnyWindowHandle,
|
||||
options: WindowParams,
|
||||
) -> Box<dyn PlatformWindow>;
|
||||
) -> anyhow::Result<Box<dyn PlatformWindow>>;
|
||||
|
||||
/// Returns the appearance of the application's windows.
|
||||
fn window_appearance(&self) -> WindowAppearance;
|
||||
|
||||
@@ -59,10 +59,6 @@ impl LinuxClient for HeadlessClient {
|
||||
None
|
||||
}
|
||||
|
||||
fn can_open_windows(&self) -> anyhow::Result<()> {
|
||||
return Err(anyhow::anyhow!("neither DISPLAY, nor WAYLAND_DISPLAY found. You can still run zed for remote development with --dev-server-token."));
|
||||
}
|
||||
|
||||
fn active_window(&self) -> Option<AnyWindowHandle> {
|
||||
None
|
||||
}
|
||||
@@ -71,8 +67,10 @@ impl LinuxClient for HeadlessClient {
|
||||
&self,
|
||||
_handle: AnyWindowHandle,
|
||||
_params: WindowParams,
|
||||
) -> Box<dyn PlatformWindow> {
|
||||
unimplemented!()
|
||||
) -> anyhow::Result<Box<dyn PlatformWindow>> {
|
||||
Err(anyhow::anyhow!(
|
||||
"neither DISPLAY nor WAYLAND_DISPLAY is set. You can run in headless mode"
|
||||
))
|
||||
}
|
||||
|
||||
fn set_cursor_style(&self, _style: CursorStyle) {}
|
||||
|
||||
@@ -65,7 +65,7 @@ pub trait LinuxClient {
|
||||
&self,
|
||||
handle: AnyWindowHandle,
|
||||
options: WindowParams,
|
||||
) -> Box<dyn PlatformWindow>;
|
||||
) -> anyhow::Result<Box<dyn PlatformWindow>>;
|
||||
fn set_cursor_style(&self, style: CursorStyle);
|
||||
fn open_uri(&self, uri: &str);
|
||||
fn write_to_primary(&self, item: ClipboardItem);
|
||||
@@ -245,7 +245,7 @@ impl<P: LinuxClient + 'static> Platform for P {
|
||||
&self,
|
||||
handle: AnyWindowHandle,
|
||||
options: WindowParams,
|
||||
) -> Box<dyn PlatformWindow> {
|
||||
) -> anyhow::Result<Box<dyn PlatformWindow>> {
|
||||
self.open_window(handle, options)
|
||||
}
|
||||
|
||||
|
||||
@@ -559,7 +559,7 @@ impl LinuxClient for WaylandClient {
|
||||
&self,
|
||||
handle: AnyWindowHandle,
|
||||
params: WindowParams,
|
||||
) -> Box<dyn PlatformWindow> {
|
||||
) -> anyhow::Result<Box<dyn PlatformWindow>> {
|
||||
let mut state = self.0.borrow_mut();
|
||||
|
||||
let (window, surface_id) = WaylandWindow::new(
|
||||
@@ -568,10 +568,10 @@ impl LinuxClient for WaylandClient {
|
||||
WaylandClientStatePtr(Rc::downgrade(&self.0)),
|
||||
params,
|
||||
state.common.appearance,
|
||||
);
|
||||
)?;
|
||||
state.windows.insert(surface_id, window.0.clone());
|
||||
|
||||
Box::new(window)
|
||||
Ok(Box::new(window))
|
||||
}
|
||||
|
||||
fn set_cursor_style(&self, style: CursorStyle) {
|
||||
|
||||
@@ -107,7 +107,7 @@ impl WaylandWindowState {
|
||||
client: WaylandClientStatePtr,
|
||||
globals: Globals,
|
||||
options: WindowParams,
|
||||
) -> Self {
|
||||
) -> anyhow::Result<Self> {
|
||||
let bounds = options.bounds.map(|p| p.0 as u32);
|
||||
|
||||
let raw = RawWindow {
|
||||
@@ -130,7 +130,7 @@ impl WaylandWindowState {
|
||||
},
|
||||
)
|
||||
}
|
||||
.unwrap(),
|
||||
.map_err(|e| anyhow::anyhow!("{:?}", e))?,
|
||||
);
|
||||
let config = BladeSurfaceConfig {
|
||||
size: gpu::Extent {
|
||||
@@ -141,7 +141,7 @@ impl WaylandWindowState {
|
||||
transparent: options.window_background != WindowBackgroundAppearance::Opaque,
|
||||
};
|
||||
|
||||
Self {
|
||||
Ok(Self {
|
||||
xdg_surface,
|
||||
acknowledged_first_configure: false,
|
||||
surface,
|
||||
@@ -164,7 +164,7 @@ impl WaylandWindowState {
|
||||
appearance,
|
||||
handle,
|
||||
active: false,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,7 +224,7 @@ impl WaylandWindow {
|
||||
client: WaylandClientStatePtr,
|
||||
params: WindowParams,
|
||||
appearance: WindowAppearance,
|
||||
) -> (Self, ObjectId) {
|
||||
) -> anyhow::Result<(Self, ObjectId)> {
|
||||
let surface = globals.compositor.create_surface(&globals.qh, ());
|
||||
let xdg_surface = globals
|
||||
.wm_base
|
||||
@@ -267,14 +267,14 @@ impl WaylandWindow {
|
||||
client,
|
||||
globals,
|
||||
params,
|
||||
))),
|
||||
)?)),
|
||||
callbacks: Rc::new(RefCell::new(Callbacks::default())),
|
||||
});
|
||||
|
||||
// Kick things off
|
||||
surface.commit();
|
||||
|
||||
(this, surface.id())
|
||||
Ok((this, surface.id()))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -923,7 +923,7 @@ impl LinuxClient for X11Client {
|
||||
&self,
|
||||
handle: AnyWindowHandle,
|
||||
params: WindowParams,
|
||||
) -> Box<dyn PlatformWindow> {
|
||||
) -> anyhow::Result<Box<dyn PlatformWindow>> {
|
||||
let mut state = self.0.borrow_mut();
|
||||
let x_window = state.xcb_connection.generate_id().unwrap();
|
||||
|
||||
@@ -938,7 +938,7 @@ impl LinuxClient for X11Client {
|
||||
&state.atoms,
|
||||
state.scale_factor,
|
||||
state.common.appearance,
|
||||
);
|
||||
)?;
|
||||
|
||||
let screen_resources = state
|
||||
.xcb_connection
|
||||
@@ -1006,7 +1006,7 @@ impl LinuxClient for X11Client {
|
||||
};
|
||||
|
||||
state.windows.insert(x_window, window_ref);
|
||||
Box::new(window)
|
||||
Ok(Box::new(window))
|
||||
}
|
||||
|
||||
fn set_cursor_style(&self, style: CursorStyle) {
|
||||
|
||||
@@ -216,7 +216,7 @@ impl X11WindowState {
|
||||
atoms: &XcbAtoms,
|
||||
scale_factor: f32,
|
||||
appearance: WindowAppearance,
|
||||
) -> Self {
|
||||
) -> anyhow::Result<Self> {
|
||||
let x_screen_index = params
|
||||
.display_id
|
||||
.map_or(x_main_screen_index, |did| did.0 as usize);
|
||||
@@ -248,8 +248,7 @@ impl X11WindowState {
|
||||
xcb_connection
|
||||
.create_colormap(xproto::ColormapAlloc::NONE, id, visual_set.root, visual.id)
|
||||
.unwrap()
|
||||
.check()
|
||||
.unwrap();
|
||||
.check()?;
|
||||
id
|
||||
};
|
||||
|
||||
@@ -281,8 +280,7 @@ impl X11WindowState {
|
||||
&win_aux,
|
||||
)
|
||||
.unwrap()
|
||||
.check()
|
||||
.unwrap();
|
||||
.check()?;
|
||||
|
||||
if let Some(titlebar) = params.titlebar {
|
||||
if let Some(title) = titlebar.title {
|
||||
@@ -345,7 +343,7 @@ impl X11WindowState {
|
||||
},
|
||||
)
|
||||
}
|
||||
.unwrap(),
|
||||
.map_err(|e| anyhow::anyhow!("{:?}", e))?,
|
||||
);
|
||||
|
||||
let config = BladeSurfaceConfig {
|
||||
@@ -355,7 +353,7 @@ impl X11WindowState {
|
||||
transparent: params.window_background != WindowBackgroundAppearance::Opaque,
|
||||
};
|
||||
|
||||
Self {
|
||||
Ok(Self {
|
||||
client,
|
||||
executor,
|
||||
display: Rc::new(X11Display::new(xcb_connection, x_screen_index).unwrap()),
|
||||
@@ -368,7 +366,7 @@ impl X11WindowState {
|
||||
input_handler: None,
|
||||
appearance,
|
||||
handle,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn content_size(&self) -> Size<Pixels> {
|
||||
@@ -426,8 +424,8 @@ impl X11Window {
|
||||
atoms: &XcbAtoms,
|
||||
scale_factor: f32,
|
||||
appearance: WindowAppearance,
|
||||
) -> Self {
|
||||
Self(X11WindowStatePtr {
|
||||
) -> anyhow::Result<Self> {
|
||||
Ok(Self(X11WindowStatePtr {
|
||||
state: Rc::new(RefCell::new(X11WindowState::new(
|
||||
handle,
|
||||
client,
|
||||
@@ -439,11 +437,11 @@ impl X11Window {
|
||||
atoms,
|
||||
scale_factor,
|
||||
appearance,
|
||||
))),
|
||||
)?)),
|
||||
callbacks: Rc::new(RefCell::new(Callbacks::default())),
|
||||
xcb_connection: xcb_connection.clone(),
|
||||
x_window,
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
fn set_wm_hints(&self, wm_hint_property_state: WmHintPropertyState, prop1: u32, prop2: u32) {
|
||||
|
||||
@@ -187,14 +187,14 @@ impl Platform for TestPlatform {
|
||||
&self,
|
||||
handle: AnyWindowHandle,
|
||||
params: WindowParams,
|
||||
) -> Box<dyn crate::PlatformWindow> {
|
||||
) -> anyhow::Result<Box<dyn crate::PlatformWindow>> {
|
||||
let window = TestWindow::new(
|
||||
handle,
|
||||
params,
|
||||
self.weak.clone(),
|
||||
self.active_display.clone(),
|
||||
);
|
||||
Box::new(window)
|
||||
Ok(Box::new(window))
|
||||
}
|
||||
|
||||
fn window_appearance(&self) -> WindowAppearance {
|
||||
|
||||
@@ -605,7 +605,7 @@ impl Window {
|
||||
handle: AnyWindowHandle,
|
||||
options: WindowOptions,
|
||||
cx: &mut AppContext,
|
||||
) -> Self {
|
||||
) -> Result<Self> {
|
||||
let WindowOptions {
|
||||
window_bounds,
|
||||
titlebar,
|
||||
@@ -633,7 +633,7 @@ impl Window {
|
||||
display_id,
|
||||
window_background,
|
||||
},
|
||||
);
|
||||
)?;
|
||||
let display_id = platform_window.display().map(|display| display.id());
|
||||
let sprite_atlas = platform_window.sprite_atlas();
|
||||
let mouse_position = platform_window.mouse_position();
|
||||
@@ -761,7 +761,7 @@ impl Window {
|
||||
platform_window.set_app_id(&app_id);
|
||||
}
|
||||
|
||||
Window {
|
||||
Ok(Window {
|
||||
handle,
|
||||
removed: false,
|
||||
platform_window,
|
||||
@@ -807,7 +807,7 @@ impl Window {
|
||||
focus_enabled: true,
|
||||
pending_input: None,
|
||||
prompt: None,
|
||||
}
|
||||
})
|
||||
}
|
||||
fn new_focus_listener(
|
||||
&mut self,
|
||||
|
||||
@@ -147,7 +147,8 @@ pub fn main() {
|
||||
cx,
|
||||
)
|
||||
})
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ use client::{telemetry::Telemetry, TelemetrySettings};
|
||||
use db::kvp::KEY_VALUE_STORE;
|
||||
use gpui::{
|
||||
svg, AnyElement, AppContext, EventEmitter, FocusHandle, FocusableView, InteractiveElement,
|
||||
ParentElement, Render, Styled, Subscription, View, ViewContext, VisualContext, WeakView,
|
||||
ParentElement, Render, Styled, Subscription, Task, View, ViewContext, VisualContext, WeakView,
|
||||
WindowContext,
|
||||
};
|
||||
use settings::{Settings, SettingsStore};
|
||||
@@ -36,19 +36,21 @@ pub fn init(cx: &mut AppContext) {
|
||||
base_keymap_picker::init(cx);
|
||||
}
|
||||
|
||||
pub fn show_welcome_view(app_state: Arc<AppState>, cx: &mut AppContext) {
|
||||
pub fn show_welcome_view(
|
||||
app_state: Arc<AppState>,
|
||||
cx: &mut AppContext,
|
||||
) -> Task<anyhow::Result<()>> {
|
||||
open_new(app_state, cx, |workspace, cx| {
|
||||
workspace.toggle_dock(DockPosition::Left, cx);
|
||||
let welcome_page = WelcomePage::new(workspace, cx);
|
||||
workspace.add_item_to_center(Box::new(welcome_page.clone()), cx);
|
||||
cx.focus_view(&welcome_page);
|
||||
cx.notify();
|
||||
})
|
||||
.detach();
|
||||
|
||||
db::write_and_log(cx, || {
|
||||
KEY_VALUE_STORE.write_kvp(FIRST_OPEN.to_string(), "false".to_string())
|
||||
});
|
||||
db::write_and_log(cx, || {
|
||||
KEY_VALUE_STORE.write_kvp(FIRST_OPEN.to_string(), "false".to_string())
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
pub struct WelcomePage {
|
||||
|
||||
@@ -4839,18 +4839,16 @@ pub fn open_new(
|
||||
app_state: Arc<AppState>,
|
||||
cx: &mut AppContext,
|
||||
init: impl FnOnce(&mut Workspace, &mut ViewContext<Workspace>) + 'static + Send,
|
||||
) -> Task<()> {
|
||||
) -> Task<anyhow::Result<()>> {
|
||||
let task = Workspace::new_local(Vec::new(), app_state, None, cx);
|
||||
cx.spawn(|mut cx| async move {
|
||||
if let Some((workspace, opened_paths)) = task.await.log_err() {
|
||||
workspace
|
||||
.update(&mut cx, |workspace, cx| {
|
||||
if opened_paths.is_empty() {
|
||||
init(workspace, cx)
|
||||
}
|
||||
})
|
||||
.log_err();
|
||||
}
|
||||
let (workspace, opened_paths) = task.await?;
|
||||
workspace.update(&mut cx, |workspace, cx| {
|
||||
if opened_paths.is_empty() {
|
||||
init(workspace, cx)
|
||||
}
|
||||
})?;
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
@@ -4922,7 +4920,7 @@ pub fn join_hosted_project(
|
||||
Workspace::new(Default::default(), project, app_state.clone(), cx)
|
||||
})
|
||||
})
|
||||
})?
|
||||
})??
|
||||
};
|
||||
|
||||
workspace.update(&mut cx, |_, cx| {
|
||||
@@ -4987,7 +4985,7 @@ pub fn join_dev_server_project(
|
||||
Workspace::new(Default::default(), project, app_state.clone(), cx)
|
||||
})
|
||||
})
|
||||
})?
|
||||
})??
|
||||
}
|
||||
};
|
||||
|
||||
@@ -5050,7 +5048,7 @@ pub fn join_in_room_project(
|
||||
Workspace::new(Default::default(), project, app_state.clone(), cx)
|
||||
})
|
||||
})
|
||||
})?
|
||||
})??
|
||||
};
|
||||
|
||||
workspace.update(&mut cx, |workspace, cx| {
|
||||
|
||||
@@ -103,6 +103,9 @@ zed_actions.workspace = true
|
||||
[target.'cfg(target_os = "windows")'.build-dependencies]
|
||||
winresource = "0.1"
|
||||
|
||||
[target.'cfg(target_os = "linux")'.dependencies]
|
||||
ashpd.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
call = { workspace = true, features = ["test-support"] }
|
||||
editor = { workspace = true, features = ["test-support"] }
|
||||
|
||||
@@ -56,21 +56,58 @@ use crate::zed::inline_completion_registry;
|
||||
static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc;
|
||||
|
||||
fn fail_to_launch(e: anyhow::Error) {
|
||||
eprintln!("Zed failed to launch: {:?}", e);
|
||||
App::new().run(move |cx| {
|
||||
let window = cx.open_window(gpui::WindowOptions::default(), |cx| cx.new_view(|_| gpui::Empty));
|
||||
window.update(cx, |_, cx| {
|
||||
let response = cx.prompt(gpui::PromptLevel::Critical, "Zed failed to launch", Some(&format!("{}\n\nFor help resolving this, please open an issue on https://github.com/zed-industries/zed", e)), &["Exit"]);
|
||||
if let Ok(window) = cx.open_window(gpui::WindowOptions::default(), |cx| cx.new_view(|_| gpui::Empty)) {
|
||||
window.update(cx, |_, cx| {
|
||||
let response = cx.prompt(gpui::PromptLevel::Critical, "Zed failed to launch", Some(&format!("{}\n\nFor help resolving this, please open an issue on https://github.com/zed-industries/zed", e)), &["Exit"]);
|
||||
|
||||
cx.spawn(|_, mut cx| async move {
|
||||
response.await?;
|
||||
cx.update(|cx| {
|
||||
cx.quit()
|
||||
})
|
||||
}).detach_and_log_err(cx);
|
||||
}).log_err();
|
||||
cx.spawn(|_, mut cx| async move {
|
||||
response.await?;
|
||||
cx.update(|cx| {
|
||||
cx.quit()
|
||||
})
|
||||
}).detach_and_log_err(cx);
|
||||
}).log_err();
|
||||
} else {
|
||||
fail_to_open_window(e, cx)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn fail_to_open_window_async(e: anyhow::Error, cx: &mut AsyncAppContext) {
|
||||
cx.update(|cx| fail_to_open_window(e, cx)).log_err();
|
||||
}
|
||||
|
||||
fn fail_to_open_window(e: anyhow::Error, _cx: &mut AppContext) {
|
||||
eprintln!("Zed failed to open a window: {:?}", e);
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
use ashpd::desktop::notification::{Notification, NotificationProxy, Priority};
|
||||
_cx.spawn(|cx| async move {
|
||||
let proxy = NotificationProxy::new().await?;
|
||||
|
||||
let notification_id = "dev.zed.Oops";
|
||||
proxy
|
||||
.add_notification(
|
||||
notification_id,
|
||||
Notification::new("Zed failed to launch")
|
||||
.body(Some(format!("{:?}", e).as_str()))
|
||||
.priority(Priority::High)
|
||||
.icon(ashpd::desktop::Icon::with_names(&[
|
||||
"dialog-question-symbolic",
|
||||
])),
|
||||
)
|
||||
.await?;
|
||||
|
||||
cx.update(|cx| {
|
||||
cx.quit();
|
||||
})
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
}
|
||||
|
||||
enum AppMode {
|
||||
Headless(DevServerToken),
|
||||
Ui,
|
||||
@@ -122,10 +159,6 @@ fn init_ui(app_state: Arc<AppState>, cx: &mut AppContext) -> Result<()> {
|
||||
}
|
||||
};
|
||||
|
||||
if let Err(err) = cx.can_open_windows() {
|
||||
return Err(err);
|
||||
}
|
||||
|
||||
SystemAppearance::init(cx);
|
||||
load_embedded_fonts(cx);
|
||||
|
||||
@@ -319,7 +352,11 @@ fn main() {
|
||||
{
|
||||
cx.spawn({
|
||||
let app_state = app_state.clone();
|
||||
|cx| async move { restore_or_create_workspace(app_state, cx).await }
|
||||
|mut cx| async move {
|
||||
if let Err(e) = restore_or_create_workspace(app_state, &mut cx).await {
|
||||
fail_to_open_window_async(e, &mut cx)
|
||||
}
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
@@ -421,7 +458,11 @@ fn main() {
|
||||
init_ui(app_state.clone(), cx).unwrap();
|
||||
cx.spawn({
|
||||
let app_state = app_state.clone();
|
||||
|cx| async move { restore_or_create_workspace(app_state, cx).await }
|
||||
|mut cx| async move {
|
||||
if let Err(e) = restore_or_create_workspace(app_state, &mut cx).await {
|
||||
fail_to_open_window_async(e, &mut cx)
|
||||
}
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
@@ -448,13 +489,12 @@ fn handle_open_request(request: OpenRequest, app_state: Arc<AppState>, cx: &mut
|
||||
let app_state = app_state.clone();
|
||||
cx.spawn(move |cx| handle_cli_connection(connection, app_state, cx))
|
||||
.detach();
|
||||
return;
|
||||
}
|
||||
|
||||
if let Err(e) = init_ui(app_state.clone(), cx) {
|
||||
log::error!("{}", e);
|
||||
fail_to_open_window(e, cx);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let mut task = None;
|
||||
if !request.open_paths.is_empty() {
|
||||
@@ -478,48 +518,59 @@ fn handle_open_request(request: OpenRequest, app_state: Arc<AppState>, cx: &mut
|
||||
|
||||
if !request.open_channel_notes.is_empty() || request.join_channel.is_some() {
|
||||
cx.spawn(|mut cx| async move {
|
||||
if let Some(task) = task {
|
||||
task.await?;
|
||||
}
|
||||
let client = app_state.client.clone();
|
||||
// we continue even if authentication fails as join_channel/ open channel notes will
|
||||
// show a visible error message.
|
||||
authenticate(client, &cx).await.log_err();
|
||||
let result = maybe!(async {
|
||||
if let Some(task) = task {
|
||||
task.await?;
|
||||
}
|
||||
let client = app_state.client.clone();
|
||||
// we continue even if authentication fails as join_channel/ open channel notes will
|
||||
// show a visible error message.
|
||||
authenticate(client, &cx).await.log_err();
|
||||
|
||||
if let Some(channel_id) = request.join_channel {
|
||||
cx.update(|cx| {
|
||||
workspace::join_channel(
|
||||
client::ChannelId(channel_id),
|
||||
app_state.clone(),
|
||||
None,
|
||||
cx,
|
||||
)
|
||||
})?
|
||||
.await?;
|
||||
}
|
||||
if let Some(channel_id) = request.join_channel {
|
||||
cx.update(|cx| {
|
||||
workspace::join_channel(
|
||||
client::ChannelId(channel_id),
|
||||
app_state.clone(),
|
||||
None,
|
||||
cx,
|
||||
)
|
||||
})?
|
||||
.await?;
|
||||
}
|
||||
|
||||
let workspace_window =
|
||||
workspace::get_any_active_workspace(app_state, cx.clone()).await?;
|
||||
let workspace = workspace_window.root_view(&cx)?;
|
||||
let workspace_window =
|
||||
workspace::get_any_active_workspace(app_state, cx.clone()).await?;
|
||||
let workspace = workspace_window.root_view(&cx)?;
|
||||
|
||||
let mut promises = Vec::new();
|
||||
for (channel_id, heading) in request.open_channel_notes {
|
||||
promises.push(cx.update_window(workspace_window.into(), |_, cx| {
|
||||
ChannelView::open(
|
||||
client::ChannelId(channel_id),
|
||||
heading,
|
||||
workspace.clone(),
|
||||
cx,
|
||||
)
|
||||
.log_err()
|
||||
})?)
|
||||
let mut promises = Vec::new();
|
||||
for (channel_id, heading) in request.open_channel_notes {
|
||||
promises.push(cx.update_window(workspace_window.into(), |_, cx| {
|
||||
ChannelView::open(
|
||||
client::ChannelId(channel_id),
|
||||
heading,
|
||||
workspace.clone(),
|
||||
cx,
|
||||
)
|
||||
.log_err()
|
||||
})?)
|
||||
}
|
||||
future::join_all(promises).await;
|
||||
anyhow::Ok(())
|
||||
})
|
||||
.await;
|
||||
if let Err(err) = result {
|
||||
fail_to_open_window_async(err, &mut cx);
|
||||
}
|
||||
future::join_all(promises).await;
|
||||
anyhow::Ok(())
|
||||
})
|
||||
.detach_and_log_err(cx);
|
||||
.detach()
|
||||
} else if let Some(task) = task {
|
||||
task.detach_and_log_err(cx)
|
||||
cx.spawn(|mut cx| async move {
|
||||
if let Err(err) = task.await {
|
||||
fail_to_open_window_async(err, &mut cx);
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -562,41 +613,39 @@ async fn installation_id() -> Result<(String, bool)> {
|
||||
Ok((installation_id, false))
|
||||
}
|
||||
|
||||
async fn restore_or_create_workspace(app_state: Arc<AppState>, cx: AsyncAppContext) {
|
||||
maybe!(async {
|
||||
let restore_behaviour =
|
||||
cx.update(|cx| WorkspaceSettings::get(None, cx).restore_on_startup)?;
|
||||
let location = match restore_behaviour {
|
||||
workspace::RestoreOnStartupBehaviour::LastWorkspace => {
|
||||
workspace::last_opened_workspace_paths().await
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
if let Some(location) = location {
|
||||
cx.update(|cx| {
|
||||
workspace::open_paths(
|
||||
location.paths().as_ref(),
|
||||
app_state,
|
||||
workspace::OpenOptions::default(),
|
||||
cx,
|
||||
)
|
||||
})?
|
||||
.await
|
||||
.log_err();
|
||||
} else if matches!(KEY_VALUE_STORE.read_kvp(FIRST_OPEN), Ok(None)) {
|
||||
cx.update(|cx| show_welcome_view(app_state, cx)).log_err();
|
||||
} else {
|
||||
cx.update(|cx| {
|
||||
workspace::open_new(app_state, cx, |workspace, cx| {
|
||||
Editor::new_file(workspace, &Default::default(), cx)
|
||||
})
|
||||
.detach();
|
||||
})?;
|
||||
async fn restore_or_create_workspace(
|
||||
app_state: Arc<AppState>,
|
||||
cx: &mut AsyncAppContext,
|
||||
) -> Result<()> {
|
||||
let restore_behaviour = cx.update(|cx| WorkspaceSettings::get(None, cx).restore_on_startup)?;
|
||||
let location = match restore_behaviour {
|
||||
workspace::RestoreOnStartupBehaviour::LastWorkspace => {
|
||||
workspace::last_opened_workspace_paths().await
|
||||
}
|
||||
anyhow::Ok(())
|
||||
})
|
||||
.await
|
||||
.log_err();
|
||||
_ => None,
|
||||
};
|
||||
if let Some(location) = location {
|
||||
cx.update(|cx| {
|
||||
workspace::open_paths(
|
||||
location.paths().as_ref(),
|
||||
app_state,
|
||||
workspace::OpenOptions::default(),
|
||||
cx,
|
||||
)
|
||||
})?
|
||||
.await?;
|
||||
} else if matches!(KEY_VALUE_STORE.read_kvp(FIRST_OPEN), Ok(None)) {
|
||||
cx.update(|cx| show_welcome_view(app_state, cx))?.await?;
|
||||
} else {
|
||||
cx.update(|cx| {
|
||||
workspace::open_new(app_state, cx, |workspace, cx| {
|
||||
Editor::new_file(workspace, &Default::default(), cx)
|
||||
})
|
||||
})?
|
||||
.await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn init_paths() -> anyhow::Result<()> {
|
||||
|
||||
@@ -1314,7 +1314,8 @@ mod tests {
|
||||
Editor::new_file(workspace, &Default::default(), cx)
|
||||
})
|
||||
})
|
||||
.await;
|
||||
.await
|
||||
.unwrap();
|
||||
cx.run_until_parked();
|
||||
|
||||
let workspace = cx
|
||||
|
||||
Reference in New Issue
Block a user