History

Introduce more GPUI2 APIs needed for transitioning the workspace (#3208)

Release Notes: - N/A

Antonio Scandurra committed 3 years ago

Commit 6d2e1a82 parents 8793300 76c675a7 files · +81 −101Browse files

Unified · Split

7 files
  1. crates/gpui2/src/app.rs +34 −43
  2. crates/gpui2/src/app/async_context.rs +10 −6
  3. crates/gpui2/src/app/test_context.rs +0 −9
  4. crates/gpui2/src/platform.rs +1 −14
  5. crates/gpui2/src/platform/mac/window.rs +6 −11
  6. crates/gpui2/src/view.rs +4 −0
  7. crates/gpui2/src/window.rs +26 −18
crates/gpui2/src/app.rs+34−43
@@ -16,13 +16,13 @@ use crate::{ · 15 unmodified lines
16 current_platform, image_cache::ImageCache, Action, AnyBox, AnyView, AnyWindowHandle,16 current_platform, image_cache::ImageCache, Action, AnyBox, AnyView, AnyWindowHandle,
17 AppMetadata, AssetSource, BackgroundExecutor, ClipboardItem, Context, DispatchPhase, DisplayId,17 AppMetadata, AssetSource, BackgroundExecutor, ClipboardItem, Context, DispatchPhase, DisplayId,
18 Entity, FocusEvent, FocusHandle, FocusId, ForegroundExecutor, KeyBinding, Keymap, LayoutId,18 Entity, FocusEvent, FocusHandle, FocusId, ForegroundExecutor, KeyBinding, Keymap, LayoutId,
19 Pixels, Platform, Point, Render, SharedString, SubscriberSet, Subscription, SvgRenderer, Task,19 PathPromptOptions, Pixels, Platform, PlatformDisplay, Point, Render, SharedString,
20 TextStyle, TextStyleRefinement, TextSystem, View, Window, WindowContext, WindowHandle,20 SubscriberSet, Subscription, SvgRenderer, Task, TextStyle, TextStyleRefinement, TextSystem,
21 WindowId,21 View, Window, WindowContext, WindowHandle, WindowId,
22};22};
23use anyhow::{anyhow, Result};23use anyhow::{anyhow, Result};
24use collections::{HashMap, HashSet, VecDeque};24use collections::{HashMap, HashSet, VecDeque};
25use futures::{future::LocalBoxFuture, Future};25use futures::{channel::oneshot, future::LocalBoxFuture, Future};
26use parking_lot::Mutex;26use parking_lot::Mutex;
27use slotmap::SlotMap;27use slotmap::SlotMap;
28use std::{28use std::{
@@ -31,7 +31,7 @@ use std::{ · 2 unmodified lines
31 marker::PhantomData,31 marker::PhantomData,
32 mem,32 mem,
33 ops::{Deref, DerefMut},33 ops::{Deref, DerefMut},
34 path::PathBuf,34 path::{Path, PathBuf},
35 rc::{Rc, Weak},35 rc::{Rc, Weak},
36 sync::{atomic::Ordering::SeqCst, Arc},36 sync::{atomic::Ordering::SeqCst, Arc},
37 time::Duration,37 time::Duration,
@@ -262,38 +262,13 @@ impl AppContext { · 224 unmodified lines
262 .collect()262 .collect()
263 }263 }
264 264
265 pub(crate) fn update_window<R>(
266 &mut self,
267 handle: AnyWindowHandle,
268 update: impl FnOnce(AnyView, &mut WindowContext) -> R,
269 ) -> Result<R> {
270 self.update(|cx| {
271 let mut window = cx
272 .windows
273 .get_mut(handle.id)
274 .ok_or_else(|| anyhow!("window not found"))?
275 .take()
276 .unwrap();
277
278 let root_view = window.root_view.clone().unwrap();
279 let result = update(root_view, &mut WindowContext::new(cx, &mut window));
280
281 cx.windows
282 .get_mut(handle.id)
283 .ok_or_else(|| anyhow!("window not found"))?
284 .replace(window);
285
286 Ok(result)
287 })
288 }
289
290 /// Opens a new window with the given option and the root view returned by the given function.265 /// Opens a new window with the given option and the root view returned by the given function.
291 /// The function is invoked with a `WindowContext`, which can be used to interact with window-specific266 /// The function is invoked with a `WindowContext`, which can be used to interact with window-specific
292 /// functionality.267 /// functionality.
293 pub fn open_window<V: Render>(268 pub fn open_window<V: Render>(
294 &mut self,269 &mut self,
295 options: crate::WindowOptions,270 options: crate::WindowOptions,
296 build_root_view: impl FnOnce(&mut WindowContext) -> View<V> + 'static,271 build_root_view: impl FnOnce(&mut WindowContext) -> View<V>,
297 ) -> WindowHandle<V> {272 ) -> WindowHandle<V> {
298 self.update(|cx| {273 self.update(|cx| {
299 let id = cx.windows.insert(None);274 let id = cx.windows.insert(None);
@@ -306,47 +281,63 @@ impl AppContext { · 6 unmodified lines
306 })281 })
307 }282 }
308 283
309 pub(crate) fn platform(&self) -> &Rc<dyn Platform> {
310 &self.platform
311 }
312
313 /// Instructs the platform to activate the application by bringing it to the foreground.284 /// Instructs the platform to activate the application by bringing it to the foreground.
314 pub fn activate(&self, ignoring_other_apps: bool) {285 pub fn activate(&self, ignoring_other_apps: bool) {
315 self.platform().activate(ignoring_other_apps);286 self.platform.activate(ignoring_other_apps);
287 }
288
289 /// Returns the list of currently active displays.
290 pub fn displays(&self) -> Vec<Rc<dyn PlatformDisplay>> {
291 self.platform.displays()
316 }292 }
317 293
318 /// Writes data to the platform clipboard.294 /// Writes data to the platform clipboard.
319 pub fn write_to_clipboard(&self, item: ClipboardItem) {295 pub fn write_to_clipboard(&self, item: ClipboardItem) {
320 self.platform().write_to_clipboard(item)296 self.platform.write_to_clipboard(item)
321 }297 }
322 298
323 /// Reads data from the platform clipboard.299 /// Reads data from the platform clipboard.
324 pub fn read_from_clipboard(&self) -> Option<ClipboardItem> {300 pub fn read_from_clipboard(&self) -> Option<ClipboardItem> {
325 self.platform().read_from_clipboard()301 self.platform.read_from_clipboard()
326 }302 }
327 303
328 /// Writes credentials to the platform keychain.304 /// Writes credentials to the platform keychain.
329 pub fn write_credentials(&self, url: &str, username: &str, password: &[u8]) -> Result<()> {305 pub fn write_credentials(&self, url: &str, username: &str, password: &[u8]) -> Result<()> {
330 self.platform().write_credentials(url, username, password)306 self.platform.write_credentials(url, username, password)
331 }307 }
332 308
333 /// Reads credentials from the platform keychain.309 /// Reads credentials from the platform keychain.
334 pub fn read_credentials(&self, url: &str) -> Result<Option<(String, Vec<u8>)>> {310 pub fn read_credentials(&self, url: &str) -> Result<Option<(String, Vec<u8>)>> {
335 self.platform().read_credentials(url)311 self.platform.read_credentials(url)
336 }312 }
337 313
338 /// Deletes credentials from the platform keychain.314 /// Deletes credentials from the platform keychain.
339 pub fn delete_credentials(&self, url: &str) -> Result<()> {315 pub fn delete_credentials(&self, url: &str) -> Result<()> {
340 self.platform().delete_credentials(url)316 self.platform.delete_credentials(url)
341 }317 }
342 318
343 /// Directs the platform's default browser to open the given URL.319 /// Directs the platform's default browser to open the given URL.
344 pub fn open_url(&self, url: &str) {320 pub fn open_url(&self, url: &str) {
345 self.platform().open_url(url);321 self.platform.open_url(url);
346 }322 }
347 323
348 pub fn path_for_auxiliary_executable(&self, name: &str) -> Result<PathBuf> {324 pub fn path_for_auxiliary_executable(&self, name: &str) -> Result<PathBuf> {
349 self.platform().path_for_auxiliary_executable(name)325 self.platform.path_for_auxiliary_executable(name)
326 }
327
328 pub fn prompt_for_paths(
329 &self,
330 options: PathPromptOptions,
331 ) -> oneshot::Receiver<Option<Vec<PathBuf>>> {
332 self.platform.prompt_for_paths(options)
333 }
334
335 pub fn prompt_for_new_path(&self, directory: &Path) -> oneshot::Receiver<Option<PathBuf>> {
336 self.platform.prompt_for_new_path(directory)
337 }
338
339 pub fn reveal_path(&self, path: &Path) {
340 self.platform.reveal_path(path)
350 }341 }
351 342
352 pub(crate) fn push_effect(&mut self, effect: Effect) {343 pub(crate) fn push_effect(&mut self, effect: Effect) {
crates/gpui2/src/app/async_context.rs+10−6
@@ -1,6 +1,7 @@
1use crate::{1use crate::{
2 AnyView, AnyWindowHandle, AppContext, BackgroundExecutor, Context, ForegroundExecutor, Model,2 AnyView, AnyWindowHandle, AppContext, BackgroundExecutor, Context, ForegroundExecutor, Model,
3 ModelContext, Render, Result, Task, View, ViewContext, VisualContext, WindowContext,3 ModelContext, Render, Result, Task, View, ViewContext, VisualContext, WindowContext,
4 WindowHandle,
4};5};
5use anyhow::{anyhow, Context as _};6use anyhow::{anyhow, Context as _};
6use derive_more::{Deref, DerefMut};7use derive_more::{Deref, DerefMut};
@@ -82,17 +83,20 @@ impl AsyncAppContext { · 75 unmodified lines
82 Ok(f(&mut *lock))83 Ok(f(&mut *lock))
83 }84 }
84 85
85 pub fn update_window<R>(86 pub fn open_window<V>(
86 &self,87 &self,
87 handle: AnyWindowHandle,88 options: crate::WindowOptions,
88 update: impl FnOnce(AnyView, &mut WindowContext) -> R,89 build_root_view: impl FnOnce(&mut WindowContext) -> View<V>,
89 ) -> Result<R> {90 ) -> Result<WindowHandle<V>>
91 where
92 V: Render,
93 {
90 let app = self94 let app = self
91 .app95 .app
92 .upgrade()96 .upgrade()
93 .ok_or_else(|| anyhow!("app was released"))?;97 .ok_or_else(|| anyhow!("app was released"))?;
94 let mut app_context = app.borrow_mut();98 let mut lock = app.borrow_mut();
95 app_context.update_window(handle, update)99 Ok(lock.open_window(options, build_root_view))
96 }100 }
97 101
98 pub fn spawn<Fut, R>(&self, f: impl FnOnce(AsyncAppContext) -> Fut) -> Task<R>102 pub fn spawn<Fut, R>(&self, f: impl FnOnce(AsyncAppContext) -> Fut) -> Task<R>
crates/gpui2/src/app/test_context.rs+0−9
@@ -87,15 +87,6 @@ impl TestAppContext { · 86 unmodified lines
87 cx.update(f)87 cx.update(f)
88 }88 }
89 89
90 pub fn update_window<R>(
91 &self,
92 handle: AnyWindowHandle,
93 update: impl FnOnce(AnyView, &mut WindowContext) -> R,
94 ) -> R {
95 let mut app = self.app.borrow_mut();
96 app.update_window(handle, update).unwrap()
97 }
98
99 pub fn spawn<Fut, R>(&self, f: impl FnOnce(AsyncAppContext) -> Fut) -> Task<R>90 pub fn spawn<Fut, R>(&self, f: impl FnOnce(AsyncAppContext) -> Fut) -> Task<R>
100 where91 where
101 Fut: Future<Output = R> + 'static,92 Fut: Future<Output = R> + 'static,
crates/gpui2/src/platform.rs+1−14
@@ -138,12 +138,7 @@ pub(crate) trait PlatformWindow { · 137 unmodified lines
138 fn mouse_position(&self) -> Point<Pixels>;138 fn mouse_position(&self) -> Point<Pixels>;
139 fn as_any_mut(&mut self) -> &mut dyn Any;139 fn as_any_mut(&mut self) -> &mut dyn Any;
140 fn set_input_handler(&mut self, input_handler: Box<dyn PlatformInputHandler>);140 fn set_input_handler(&mut self, input_handler: Box<dyn PlatformInputHandler>);
141 fn prompt(141 fn prompt(&self, level: PromptLevel, msg: &str, answers: &[&str]) -> oneshot::Receiver<usize>;
142 &self,
143 level: WindowPromptLevel,
144 msg: &str,
145 answers: &[&str],
146 ) -> oneshot::Receiver<usize>;
147 fn activate(&self);142 fn activate(&self);
148 fn set_title(&mut self, title: &str);143 fn set_title(&mut self, title: &str);
149 fn set_edited(&mut self, edited: bool);144 fn set_edited(&mut self, edited: bool);
@@ -454,14 +449,6 @@ impl Default for WindowAppearance { · 304 unmodified lines
454 }449 }
455}450}
456 451
457#[derive(Copy, Clone, Debug, PartialEq, Default)]
458pub enum WindowPromptLevel {
459 #[default]
460 Info,
461 Warning,
462 Critical,
463}
464
465#[derive(Copy, Clone, Debug)]452#[derive(Copy, Clone, Debug)]
466pub struct PathPromptOptions {453pub struct PathPromptOptions {
467 pub files: bool,454 pub files: bool,
crates/gpui2/src/platform/mac/window.rs+6−11
@@ -3,8 +3,8 @@ use crate::{ · 2 unmodified lines
3 display_bounds_to_native, point, px, size, AnyWindowHandle, Bounds, ExternalPaths,3 display_bounds_to_native, point, px, size, AnyWindowHandle, Bounds, ExternalPaths,
4 FileDropEvent, ForegroundExecutor, GlobalPixels, InputEvent, KeyDownEvent, Keystroke,4 FileDropEvent, ForegroundExecutor, GlobalPixels, InputEvent, KeyDownEvent, Keystroke,
5 Modifiers, ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent,5 Modifiers, ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent,
6 Pixels, PlatformAtlas, PlatformDisplay, PlatformInputHandler, PlatformWindow, Point, Scene,6 Pixels, PlatformAtlas, PlatformDisplay, PlatformInputHandler, PlatformWindow, Point,
7 Size, Timer, WindowAppearance, WindowBounds, WindowKind, WindowOptions, WindowPromptLevel,7 PromptLevel, Scene, Size, Timer, WindowAppearance, WindowBounds, WindowKind, WindowOptions,
8};8};
9use block::ConcreteBlock;9use block::ConcreteBlock;
10use cocoa::{10use cocoa::{
@@ -742,12 +742,7 @@ impl PlatformWindow for MacWindow { · 731 unmodified lines
742 self.0.as_ref().lock().input_handler = Some(input_handler);742 self.0.as_ref().lock().input_handler = Some(input_handler);
743 }743 }
744 744
745 fn prompt(745 fn prompt(&self, level: PromptLevel, msg: &str, answers: &[&str]) -> oneshot::Receiver<usize> {
746 &self,
747 level: WindowPromptLevel,
748 msg: &str,
749 answers: &[&str],
750 ) -> oneshot::Receiver<usize> {
751 // macOs applies overrides to modal window buttons after they are added.746 // macOs applies overrides to modal window buttons after they are added.
752 // Two most important for this logic are:747 // Two most important for this logic are:
753 // * Buttons with "Cancel" title will be displayed as the last buttons in the modal748 // * Buttons with "Cancel" title will be displayed as the last buttons in the modal
@@ -777,9 +772,9 @@ impl PlatformWindow for MacWindow { · 23 unmodified lines
777 let alert: id = msg_send![class!(NSAlert), alloc];772 let alert: id = msg_send![class!(NSAlert), alloc];
778 let alert: id = msg_send![alert, init];773 let alert: id = msg_send![alert, init];
779 let alert_style = match level {774 let alert_style = match level {
780 WindowPromptLevel::Info => 1,775 PromptLevel::Info => 1,
781 WindowPromptLevel::Warning => 0,776 PromptLevel::Warning => 0,
782 WindowPromptLevel::Critical => 2,777 PromptLevel::Critical => 2,
783 };778 };
784 let _: () = msg_send![alert, setAlertStyle: alert_style];779 let _: () = msg_send![alert, setAlertStyle: alert_style];
785 let _: () = msg_send![alert, setMessageText: ns_string(msg)];780 let _: () = msg_send![alert, setMessageText: ns_string(msg)];
crates/gpui2/src/view.rs+4−0
@@ -98,6 +98,10 @@ pub struct WeakView<V> { · 97 unmodified lines
98}98}
99 99
100impl<V: 'static> WeakView<V> {100impl<V: 'static> WeakView<V> {
101 pub fn entity_id(&self) -> EntityId {
102 self.model.entity_id
103 }
104
101 pub fn upgrade(&self) -> Option<View<V>> {105 pub fn upgrade(&self) -> Option<View<V>> {
102 Entity::upgrade_from(self)106 Entity::upgrade_from(self)
103 }107 }
crates/gpui2/src/window.rs+26−18
@@ -4,14 +4,15 @@ use crate::{ · 3 unmodified lines
4 Entity, EntityId, EventEmitter, FileDropEvent, FocusEvent, FontId, GlobalElementId, GlyphId,4 Entity, EntityId, EventEmitter, FileDropEvent, FocusEvent, FontId, GlobalElementId, GlyphId,
5 Hsla, ImageData, InputEvent, IsZero, KeyListener, KeyMatch, KeyMatcher, Keystroke, LayoutId,5 Hsla, ImageData, InputEvent, IsZero, KeyListener, KeyMatch, KeyMatcher, Keystroke, LayoutId,
6 Model, ModelContext, Modifiers, MonochromeSprite, MouseButton, MouseDownEvent, MouseMoveEvent,6 Model, ModelContext, Modifiers, MonochromeSprite, MouseButton, MouseDownEvent, MouseMoveEvent,
7 MouseUpEvent, Path, Pixels, PlatformAtlas, PlatformWindow, Point, PolychromeSprite, Quad,7 MouseUpEvent, Path, Pixels, PlatformAtlas, PlatformWindow, Point, PolychromeSprite,
8 Render, RenderGlyphParams, RenderImageParams, RenderSvgParams, ScaledPixels, SceneBuilder,8 PromptLevel, Quad, Render, RenderGlyphParams, RenderImageParams, RenderSvgParams, ScaledPixels,
9 Shadow, SharedString, Size, Style, Subscription, TaffyLayoutEngine, Task, Underline,9 SceneBuilder, Shadow, SharedString, Size, Style, Subscription, TaffyLayoutEngine, Task,
10 UnderlineStyle, View, VisualContext, WeakView, WindowOptions, SUBPIXEL_VARIANTS,10 Underline, UnderlineStyle, View, VisualContext, WeakView, WindowOptions, SUBPIXEL_VARIANTS,
11};11};
12use anyhow::{anyhow, Result};12use anyhow::{anyhow, Result};
13use collections::HashMap;13use collections::HashMap;
14use derive_more::{Deref, DerefMut};14use derive_more::{Deref, DerefMut};
15use futures::channel::oneshot;
15use parking_lot::RwLock;16use parking_lot::RwLock;
16use slotmap::SlotMap;17use slotmap::SlotMap;
17use smallvec::SmallVec;18use smallvec::SmallVec;
@@ -195,7 +196,7 @@ impl Window { · 177 unmodified lines
195 options: WindowOptions,196 options: WindowOptions,
196 cx: &mut AppContext,197 cx: &mut AppContext,
197 ) -> Self {198 ) -> Self {
198 let platform_window = cx.platform().open_window(handle, options);199 let platform_window = cx.platform.open_window(handle, options);
199 let display_id = platform_window.display().id();200 let display_id = platform_window.display().id();
200 let sprite_atlas = platform_window.sprite_atlas();201 let sprite_atlas = platform_window.sprite_atlas();
201 let mouse_position = platform_window.mouse_position();202 let mouse_position = platform_window.mouse_position();
@@ -419,7 +420,7 @@ impl<'a> WindowContext<'a> { · 217 unmodified lines
419 } else {420 } else {
420 let mut async_cx = self.to_async();421 let mut async_cx = self.to_async();
421 self.next_frame_callbacks.insert(display_id, vec![f]);422 self.next_frame_callbacks.insert(display_id, vec![f]);
422 self.platform().set_display_link_output_callback(423 self.platform.set_display_link_output_callback(
423 display_id,424 display_id,
424 Box::new(move |_current_time, _output_time| {425 Box::new(move |_current_time, _output_time| {
425 let _ = async_cx.update(|_, cx| {426 let _ = async_cx.update(|_, cx| {
@@ -434,32 +435,26 @@ impl<'a> WindowContext<'a> { · 8 unmodified lines
434 }435 }
435 436
436 if cx.next_frame_callbacks.get(&display_id).unwrap().is_empty() {437 if cx.next_frame_callbacks.get(&display_id).unwrap().is_empty() {
437 cx.platform().stop_display_link(display_id);438 cx.platform.stop_display_link(display_id);
438 }439 }
439 });440 });
440 }),441 }),
441 );442 );
442 }443 }
443 444
444 self.platform().start_display_link(display_id);445 self.platform.start_display_link(display_id);
445 }446 }
446 447
447 /// Spawn the future returned by the given closure on the application thread pool.448 /// Spawn the future returned by the given closure on the application thread pool.
448 /// The closure is provided a handle to the current window and an `AsyncWindowContext` for449 /// The closure is provided a handle to the current window and an `AsyncWindowContext` for
449 /// use within your future.450 /// use within your future.
450 pub fn spawn<Fut, R>(451 pub fn spawn<Fut, R>(&mut self, f: impl FnOnce(AsyncWindowContext) -> Fut) -> Task<R>
451 &mut self,
452 f: impl FnOnce(AnyWindowHandle, AsyncWindowContext) -> Fut,
453 ) -> Task<R>
454 where452 where
455 R: 'static,453 R: 'static,
456 Fut: Future<Output = R> + 'static,454 Fut: Future<Output = R> + 'static,
457 {455 {
458 let window = self.window.handle;456 self.app
459 self.app.spawn(move |app| {457 .spawn(|app| f(AsyncWindowContext::new(app, self.window.handle)))
460 let cx = AsyncWindowContext::new(app, window);
461 f(window, cx)
462 })
463 }458 }
464 459
465 /// Update the global of the given type. The given closure is given simultaneous mutable460 /// Update the global of the given type. The given closure is given simultaneous mutable
@@ -1153,6 +1148,19 @@ impl<'a> WindowContext<'a> { · 687 unmodified lines
1153 )1148 )
1154 }1149 }
1155 1150
1151 pub fn activate_window(&self) {
1152 self.window.platform_window.activate();
1153 }
1154
1155 pub fn prompt(
1156 &self,
1157 level: PromptLevel,
1158 msg: &str,
1159 answers: &[&str],
1160 ) -> oneshot::Receiver<usize> {
1161 self.window.platform_window.prompt(level, msg, answers)
1162 }
1163
1156 fn dispatch_action(1164 fn dispatch_action(
1157 &mut self,1165 &mut self,
1158 action: Box<dyn Action>,1166 action: Box<dyn Action>,
@@ -1809,7 +1817,7 @@ impl<'a, V: 'static> ViewContext<'a, V> { · 650 unmodified lines
1809 Fut: Future<Output = R> + 'static,1817 Fut: Future<Output = R> + 'static,
1810 {1818 {
1811 let view = self.view().downgrade();1819 let view = self.view().downgrade();
1812 self.window_cx.spawn(move |_, cx| f(view, cx))1820 self.window_cx.spawn(|cx| f(view, cx))
1813 }1821 }
1814 1822
1815 pub fn update_global<G, R>(&mut self, f: impl FnOnce(&mut G, &mut Self) -> R) -> R1823 pub fn update_global<G, R>(&mut self, f: impl FnOnce(&mut G, &mut Self) -> R) -> R

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t