Release Notes: - N/A
Unified · Split
| @@ -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 | }; |
| 23 | use anyhow::{anyhow, Result}; | 23 | use anyhow::{anyhow, Result}; |
| 24 | use collections::{HashMap, HashSet, VecDeque}; | 24 | use collections::{HashMap, HashSet, VecDeque}; |
| 25 | use futures::{future::LocalBoxFuture, Future}; | 25 | use futures::{channel::oneshot, future::LocalBoxFuture, Future}; |
| 26 | use parking_lot::Mutex; | 26 | use parking_lot::Mutex; |
| 27 | use slotmap::SlotMap; | 27 | use slotmap::SlotMap; |
| 28 | use std::{ | 28 | use 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-specific | 266 | /// 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) { |
| @@ -1,6 +1,7 @@ | |||
| 1 | use crate::{ | 1 | use 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 | }; |
| 5 | use anyhow::{anyhow, Context as _}; | 6 | use anyhow::{anyhow, Context as _}; |
| 6 | use derive_more::{Deref, DerefMut}; | 7 | use 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 = self | 94 | let app = self |
| 91 | .app | 95 | .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> |
| @@ -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 | where | 91 | where |
| 101 | Fut: Future<Output = R> + 'static, | 92 | Fut: Future<Output = R> + 'static, |
| @@ -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)] | ||
| 458 | pub enum WindowPromptLevel { | ||
| 459 | #[default] | ||
| 460 | Info, | ||
| 461 | Warning, | ||
| 462 | Critical, | ||
| 463 | } | ||
| 464 | |||
| 465 | #[derive(Copy, Clone, Debug)] | 452 | #[derive(Copy, Clone, Debug)] |
| 466 | pub struct PathPromptOptions { | 453 | pub struct PathPromptOptions { |
| 467 | pub files: bool, | 454 | pub files: bool, |
| @@ -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 | }; |
| 9 | use block::ConcreteBlock; | 9 | use block::ConcreteBlock; |
| 10 | use cocoa::{ | 10 | use 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 modal | 748 | // * 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)]; |
| @@ -98,6 +98,10 @@ pub struct WeakView<V> { · 97 unmodified lines | |||
| 98 | } | 98 | } |
| 99 | 99 | ||
| 100 | impl<V: 'static> WeakView<V> { | 100 | impl<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 | } |
| @@ -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 | }; |
| 12 | use anyhow::{anyhow, Result}; | 12 | use anyhow::{anyhow, Result}; |
| 13 | use collections::HashMap; | 13 | use collections::HashMap; |
| 14 | use derive_more::{Deref, DerefMut}; | 14 | use derive_more::{Deref, DerefMut}; |
| 15 | use futures::channel::oneshot; | ||
| 15 | use parking_lot::RwLock; | 16 | use parking_lot::RwLock; |
| 16 | use slotmap::SlotMap; | 17 | use slotmap::SlotMap; |
| 17 | use smallvec::SmallVec; | 18 | use 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` for | 449 | /// 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 | where | 452 | 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 mutable | 460 | /// 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) -> R | 1823 | pub fn update_global<G, R>(&mut self, f: impl FnOnce(&mut G, &mut Self) -> R) -> R |