Checkpoint
This commit is contained in:
parent
e979d75cb8
commit
343c426307
10 changed files with 401 additions and 368 deletions
|
@ -3,13 +3,12 @@ use crate::{
|
||||||
WindowContext, WindowHandle, WindowId,
|
WindowContext, WindowHandle, WindowId,
|
||||||
};
|
};
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use async_task::Runnable;
|
|
||||||
use futures::Future;
|
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
use slotmap::SlotMap;
|
use slotmap::SlotMap;
|
||||||
use std::{
|
use std::{
|
||||||
any::Any,
|
any::Any,
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
|
mem,
|
||||||
sync::{Arc, Weak},
|
sync::{Arc, Weak},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -19,17 +18,43 @@ pub struct App(Arc<RwLock<AppContext<()>>>);
|
||||||
pub struct MainThread;
|
pub struct MainThread;
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
pub fn new() -> Self {
|
pub fn production() -> Self {
|
||||||
Self(Arc::new(RwLock::new(AppContext::new(current_platform()))))
|
Self::new(current_platform())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(any(test, feature = "test"))]
|
||||||
|
pub fn test() -> Self {
|
||||||
|
Self::new(Arc::new(super::TestPlatform::new()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new(platform: Arc<dyn Platform>) -> Self {
|
||||||
|
let text_system = Arc::new(TextSystem::new(platform.text_system()));
|
||||||
|
let mut entities = SlotMap::with_key();
|
||||||
|
let unit_entity_id = entities.insert(Some(Box::new(()) as Box<dyn Any>));
|
||||||
|
Self(Arc::new_cyclic(|this| {
|
||||||
|
RwLock::new(AppContext {
|
||||||
|
this: this.clone(),
|
||||||
|
thread: PhantomData,
|
||||||
|
platform,
|
||||||
|
text_system,
|
||||||
|
unit_entity_id,
|
||||||
|
entities,
|
||||||
|
windows: SlotMap::with_key(),
|
||||||
|
layout_id_buffer: Default::default(),
|
||||||
|
})
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run<F>(self, on_finish_launching: F)
|
pub fn run<F>(self, on_finish_launching: F)
|
||||||
where
|
where
|
||||||
F: 'static + FnOnce(&mut AppContext<MainThread>),
|
F: 'static + FnOnce(&mut AppContext<MainThread>),
|
||||||
{
|
{
|
||||||
|
let platform = self.0.read().platform.clone();
|
||||||
platform.run(Box::new(move || {
|
platform.run(Box::new(move || {
|
||||||
let mut cx = self.0.write();
|
let mut cx = self.0.write();
|
||||||
on_finish_launching(&mut *cx);
|
let cx: &mut AppContext<()> = &mut cx;
|
||||||
|
let cx: &mut AppContext<MainThread> = unsafe { mem::transmute(cx) };
|
||||||
|
on_finish_launching(cx);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,7 +62,7 @@ impl App {
|
||||||
pub struct AppContext<Thread = ()> {
|
pub struct AppContext<Thread = ()> {
|
||||||
this: Weak<RwLock<AppContext>>,
|
this: Weak<RwLock<AppContext>>,
|
||||||
thread: PhantomData<Thread>,
|
thread: PhantomData<Thread>,
|
||||||
platform: Box<dyn Platform>,
|
platform: Arc<dyn Platform>,
|
||||||
text_system: Arc<TextSystem>,
|
text_system: Arc<TextSystem>,
|
||||||
pub(crate) unit_entity_id: EntityId,
|
pub(crate) unit_entity_id: EntityId,
|
||||||
pub(crate) entities: SlotMap<EntityId, Option<Box<dyn Any>>>,
|
pub(crate) entities: SlotMap<EntityId, Option<Box<dyn Any>>>,
|
||||||
|
@ -47,53 +72,33 @@ pub struct AppContext<Thread = ()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AppContext<()> {
|
impl AppContext<()> {
|
||||||
pub fn run_on_main<F: 'static, T: 'static>(
|
// pub fn run_on_main<F: 'static, T: 'static>(
|
||||||
&self,
|
// &self,
|
||||||
to_call: F,
|
// to_call: F,
|
||||||
) -> Result<T, impl Future<Output = T>>
|
// ) -> Result<T, impl Future<Output = T>>
|
||||||
where
|
// where
|
||||||
F: Fn(&mut AppContext<MainThread>) -> T + Send + Sync,
|
// F: Fn(&mut AppContext<MainThread>) -> T + Send + Sync,
|
||||||
{
|
// {
|
||||||
let dispatcher = self.platform().dispatcher();
|
// todo!();
|
||||||
if dispatcher.is_main_thread() {
|
|
||||||
} else {
|
|
||||||
let future = async move {
|
|
||||||
// let cx = unsafe { };
|
|
||||||
};
|
|
||||||
let schedule = move |runnable: Runnable| dispatcher.run_on_main_thread(runnable);
|
|
||||||
|
|
||||||
let (runnable, task) = async_task::spawn_local();
|
// // let dispatcher = self.platform().dispatcher();
|
||||||
runnable.schedule();
|
// // if dispatcher.is_main_thread() {
|
||||||
}
|
// // } else {
|
||||||
|
// // let future = async move {
|
||||||
|
// // // let cx = unsafe { };
|
||||||
|
// // };
|
||||||
|
// // let schedule = move |runnable: Runnable| dispatcher.run_on_main_thread(runnable);
|
||||||
|
// // // let (runnable, task) = async_task::spawn_local();
|
||||||
|
// // // runnable.schedule();
|
||||||
|
// // }
|
||||||
|
|
||||||
let (runnable, task) = async_task::spawn_local(future, schedule);
|
// // let (runnable, task) = async_task::spawn_local(future, schedule);
|
||||||
runnable.schedule();
|
// // runnable.schedule();
|
||||||
task
|
// // task
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Thread> AppContext<Thread> {
|
impl<Thread> AppContext<Thread> {
|
||||||
pub fn new(platform: Arc<dyn Platform>) -> Self {
|
|
||||||
let text_system = Arc::new(TextSystem::new(platform.text_system()));
|
|
||||||
let mut entities = SlotMap::with_key();
|
|
||||||
let unit_entity_id = entities.insert(Some(Box::new(()) as Box<dyn Any>));
|
|
||||||
|
|
||||||
AppContext {
|
|
||||||
thread: PhantomData,
|
|
||||||
platform,
|
|
||||||
text_system,
|
|
||||||
unit_entity_id,
|
|
||||||
entities,
|
|
||||||
windows: SlotMap::with_key(),
|
|
||||||
layout_id_buffer: Default::default(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(any(test, feature = "test"))]
|
|
||||||
pub fn test() -> Self {
|
|
||||||
Self::new(Arc::new(super::TestPlatform::new()))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn text_system(&self) -> &Arc<TextSystem> {
|
pub fn text_system(&self) -> &Arc<TextSystem> {
|
||||||
&self.text_system
|
&self.text_system
|
||||||
}
|
}
|
||||||
|
@ -101,7 +106,7 @@ impl<Thread> AppContext<Thread> {
|
||||||
pub fn open_window<S: 'static>(
|
pub fn open_window<S: 'static>(
|
||||||
&mut self,
|
&mut self,
|
||||||
options: crate::WindowOptions,
|
options: crate::WindowOptions,
|
||||||
build_root_view: impl FnOnce(&mut WindowContext) -> RootView<S>,
|
build_root_view: impl FnOnce(&mut WindowContext<Thread>) -> RootView<S>,
|
||||||
) -> WindowHandle<S> {
|
) -> WindowHandle<S> {
|
||||||
let id = self.windows.insert(None);
|
let id = self.windows.insert(None);
|
||||||
let handle = WindowHandle::new(id);
|
let handle = WindowHandle::new(id);
|
||||||
|
@ -118,7 +123,7 @@ impl<Thread> AppContext<Thread> {
|
||||||
pub(crate) fn update_window<R>(
|
pub(crate) fn update_window<R>(
|
||||||
&mut self,
|
&mut self,
|
||||||
window_id: WindowId,
|
window_id: WindowId,
|
||||||
update: impl FnOnce(&mut WindowContext) -> R,
|
update: impl FnOnce(&mut WindowContext<Thread>) -> R,
|
||||||
) -> Result<R> {
|
) -> Result<R> {
|
||||||
let mut window = self
|
let mut window = self
|
||||||
.windows
|
.windows
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use super::{Layout, LayoutId, Pixels, Point, Result, ViewContext};
|
use super::{Layout, LayoutId, Pixels, Point, Result, ViewContext};
|
||||||
pub(crate) use smallvec::SmallVec;
|
pub(crate) use smallvec::SmallVec;
|
||||||
use std::{any::Any, cell::RefCell, marker::PhantomData, rc::Rc};
|
|
||||||
|
|
||||||
pub trait Element: 'static {
|
pub trait Element: 'static {
|
||||||
type State;
|
type State;
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
use crate::util;
|
use crate::util;
|
||||||
|
use crate::PlatformDispatcher;
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use async_task::Runnable;
|
use async_task::Runnable;
|
||||||
use futures::channel::mpsc;
|
use futures::channel::{mpsc, oneshot};
|
||||||
use smol::{channel, prelude::*, Executor};
|
use smol::{channel, prelude::*, Executor};
|
||||||
use std::{
|
use std::{
|
||||||
any::Any,
|
any::Any,
|
||||||
|
@ -16,7 +17,51 @@ use std::{
|
||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::PlatformDispatcher;
|
/// Enqueues the given closure to be run on the application's event loop. Can be
|
||||||
|
/// called on any thread.
|
||||||
|
pub(crate) fn spawn_on_main<R>(
|
||||||
|
dispatcher: Arc<dyn PlatformDispatcher>,
|
||||||
|
future: impl Future<Output = R> + Send + 'static,
|
||||||
|
) -> impl Future<Output = R>
|
||||||
|
where
|
||||||
|
R: Send + 'static,
|
||||||
|
{
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
let (runnable, task) = async_task::spawn(
|
||||||
|
async move {
|
||||||
|
let result = future.await;
|
||||||
|
let _ = tx.send(result);
|
||||||
|
},
|
||||||
|
move |runnable| dispatcher.run_on_main_thread(runnable),
|
||||||
|
);
|
||||||
|
runnable.schedule();
|
||||||
|
task.detach();
|
||||||
|
async move { rx.await.unwrap() }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Enqueues the given closure to be run on the application's event loop. Must
|
||||||
|
/// be called on the main thread.
|
||||||
|
pub(crate) fn spawn_on_main_local<R>(
|
||||||
|
dispatcher: Arc<dyn PlatformDispatcher>,
|
||||||
|
future: impl Future<Output = R> + 'static,
|
||||||
|
) -> impl Future<Output = R>
|
||||||
|
where
|
||||||
|
R: 'static,
|
||||||
|
{
|
||||||
|
assert!(dispatcher.is_main_thread(), "must be called on main thread");
|
||||||
|
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
let (runnable, task) = async_task::spawn_local(
|
||||||
|
async move {
|
||||||
|
let result = future.await;
|
||||||
|
let _ = tx.send(result);
|
||||||
|
},
|
||||||
|
move |runnable| dispatcher.run_on_main_thread(runnable),
|
||||||
|
);
|
||||||
|
runnable.schedule();
|
||||||
|
task.detach();
|
||||||
|
async move { rx.await.unwrap() }
|
||||||
|
}
|
||||||
|
|
||||||
pub enum ForegroundExecutor {
|
pub enum ForegroundExecutor {
|
||||||
Platform {
|
Platform {
|
||||||
|
|
|
@ -6,8 +6,8 @@ mod mac;
|
||||||
mod test;
|
mod test;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
AnyWindowHandle, Bounds, FontFeatures, FontId, FontMetrics, FontStyle, FontWeight,
|
AnyWindowHandle, Bounds, FontFeatures, FontId, FontMetrics, FontStyle, FontWeight, GlyphId,
|
||||||
ForegroundExecutor, GlyphId, LineLayout, Pixels, Point, Result, RunStyle, SharedString, Size,
|
LineLayout, Pixels, Point, Result, RunStyle, SharedString, Size,
|
||||||
};
|
};
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use async_task::Runnable;
|
use async_task::Runnable;
|
||||||
|
@ -37,14 +37,14 @@ pub use test::*;
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
pub(crate) fn current_platform() -> Arc<dyn Platform> {
|
pub(crate) fn current_platform() -> Arc<dyn Platform> {
|
||||||
Rc::new(MacPlatform::new())
|
Arc::new(MacPlatform::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Platform {
|
pub trait Platform {
|
||||||
fn dispatcher(&self) -> Arc<dyn PlatformDispatcher>;
|
fn dispatcher(&self) -> Arc<dyn PlatformDispatcher>;
|
||||||
fn text_system(&self) -> Arc<dyn PlatformTextSystem>;
|
fn text_system(&self) -> Arc<dyn PlatformTextSystem>;
|
||||||
|
|
||||||
fn run(&self, on_finish_launching: Box<dyn FnOnce()>);
|
fn run(&self, on_finish_launching: Box<dyn 'static + FnOnce()>);
|
||||||
fn quit(&self);
|
fn quit(&self);
|
||||||
fn restart(&self);
|
fn restart(&self);
|
||||||
fn activate(&self, ignoring_other_apps: bool);
|
fn activate(&self, ignoring_other_apps: bool);
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use super::BoolExt;
|
use super::BoolExt;
|
||||||
use crate::{
|
use crate::{
|
||||||
AnyWindowHandle, ClipboardItem, CursorStyle, Event, ForegroundExecutor, MacDispatcher,
|
AnyWindowHandle, ClipboardItem, CursorStyle, Event, MacDispatcher, MacScreen, MacTextSystem,
|
||||||
MacScreen, MacTextSystem, MacWindow, PathPromptOptions, Platform, PlatformScreen,
|
MacWindow, PathPromptOptions, Platform, PlatformScreen, PlatformTextSystem, PlatformWindow,
|
||||||
PlatformTextSystem, PlatformWindow, Result, SemanticVersion, WindowOptions,
|
Result, SemanticVersion, WindowOptions,
|
||||||
};
|
};
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use block::ConcreteBlock;
|
use block::ConcreteBlock;
|
||||||
|
@ -33,9 +33,10 @@ use objc::{
|
||||||
runtime::{Class, Object, Sel},
|
runtime::{Class, Object, Sel},
|
||||||
sel, sel_impl,
|
sel, sel_impl,
|
||||||
};
|
};
|
||||||
|
use parking_lot::Mutex;
|
||||||
use ptr::null_mut;
|
use ptr::null_mut;
|
||||||
use std::{
|
use std::{
|
||||||
cell::{Cell, RefCell},
|
cell::Cell,
|
||||||
convert::TryInto,
|
convert::TryInto,
|
||||||
ffi::{c_void, CStr, OsStr},
|
ffi::{c_void, CStr, OsStr},
|
||||||
os::{raw::c_char, unix::ffi::OsStrExt},
|
os::{raw::c_char, unix::ffi::OsStrExt},
|
||||||
|
@ -138,10 +139,10 @@ unsafe fn build_classes() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct MacPlatform(RefCell<MacPlatformState>);
|
pub struct MacPlatform(Mutex<MacPlatformState>);
|
||||||
|
|
||||||
pub struct MacPlatformState {
|
pub struct MacPlatformState {
|
||||||
executor: Rc<ForegroundExecutor>,
|
dispatcher: Arc<MacDispatcher>,
|
||||||
text_system: Arc<MacTextSystem>,
|
text_system: Arc<MacTextSystem>,
|
||||||
pasteboard: id,
|
pasteboard: id,
|
||||||
text_hash_pasteboard_type: id,
|
text_hash_pasteboard_type: id,
|
||||||
|
@ -161,8 +162,8 @@ pub struct MacPlatformState {
|
||||||
|
|
||||||
impl MacPlatform {
|
impl MacPlatform {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self(RefCell::new(MacPlatformState {
|
Self(Mutex::new(MacPlatformState {
|
||||||
executor: Rc::new(ForegroundExecutor::new(Arc::new(MacDispatcher)).unwrap()),
|
dispatcher: Arc::new(MacDispatcher),
|
||||||
text_system: Arc::new(MacTextSystem::new()),
|
text_system: Arc::new(MacTextSystem::new()),
|
||||||
pasteboard: unsafe { NSPasteboard::generalPasteboard(nil) },
|
pasteboard: unsafe { NSPasteboard::generalPasteboard(nil) },
|
||||||
text_hash_pasteboard_type: unsafe { ns_string("zed-text-hash") },
|
text_hash_pasteboard_type: unsafe { ns_string("zed-text-hash") },
|
||||||
|
@ -182,7 +183,7 @@ impl MacPlatform {
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn read_from_pasteboard(&self, kind: id) -> Option<&[u8]> {
|
unsafe fn read_from_pasteboard(&self, kind: id) -> Option<&[u8]> {
|
||||||
let pasteboard = self.0.borrow().pasteboard;
|
let pasteboard = self.0.lock().pasteboard;
|
||||||
let data = pasteboard.dataForType(kind);
|
let data = pasteboard.dataForType(kind);
|
||||||
if data == nil {
|
if data == nil {
|
||||||
None
|
None
|
||||||
|
@ -342,16 +343,16 @@ impl MacPlatform {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Platform for MacPlatform {
|
impl Platform for MacPlatform {
|
||||||
fn executor(&self) -> Rc<ForegroundExecutor> {
|
fn dispatcher(&self) -> Arc<dyn crate::PlatformDispatcher> {
|
||||||
self.0.borrow().executor.clone()
|
Arc::new(MacDispatcher)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn text_system(&self) -> Arc<dyn PlatformTextSystem> {
|
fn text_system(&self) -> Arc<dyn PlatformTextSystem> {
|
||||||
self.0.borrow().text_system.clone()
|
self.0.lock().text_system.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(&self, on_finish_launching: Box<dyn FnOnce()>) {
|
fn run(&self, on_finish_launching: Box<dyn FnOnce()>) {
|
||||||
self.0.borrow_mut().finish_launching = Some(on_finish_launching);
|
self.0.lock().finish_launching = Some(on_finish_launching);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let app: id = msg_send![APP_CLASS, sharedApplication];
|
let app: id = msg_send![APP_CLASS, sharedApplication];
|
||||||
|
@ -465,25 +466,21 @@ impl Platform for MacPlatform {
|
||||||
MacScreen::find_by_id(id).map(|screen| Rc::new(screen) as Rc<_>)
|
MacScreen::find_by_id(id).map(|screen| Rc::new(screen) as Rc<_>)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main_window(&self) -> Option<AnyWindowHandle> {
|
|
||||||
MacWindow::main_window()
|
|
||||||
}
|
|
||||||
|
|
||||||
// fn add_status_item(&self, _handle: AnyWindowHandle) -> Box<dyn platform::Window> {
|
// fn add_status_item(&self, _handle: AnyWindowHandle) -> Box<dyn platform::Window> {
|
||||||
// Box::new(StatusItem::add(self.fonts()))
|
// Box::new(StatusItem::add(self.fonts()))
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
fn main_window(&self) -> Option<AnyWindowHandle> {
|
||||||
|
MacWindow::main_window()
|
||||||
|
}
|
||||||
|
|
||||||
fn open_window(
|
fn open_window(
|
||||||
&self,
|
&self,
|
||||||
handle: AnyWindowHandle,
|
handle: AnyWindowHandle,
|
||||||
options: WindowOptions,
|
options: WindowOptions,
|
||||||
) -> Box<dyn PlatformWindow> {
|
) -> Box<dyn PlatformWindow> {
|
||||||
Box::new(MacWindow::open(
|
let dispatcher = self.0.lock().dispatcher.clone();
|
||||||
handle,
|
Box::new(MacWindow::open(handle, options, dispatcher))
|
||||||
options,
|
|
||||||
self.executor(),
|
|
||||||
self.text_system(),
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn open_url(&self, url: &str) {
|
fn open_url(&self, url: &str) {
|
||||||
|
@ -497,7 +494,7 @@ impl Platform for MacPlatform {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_open_urls(&self, callback: Box<dyn FnMut(Vec<String>)>) {
|
fn on_open_urls(&self, callback: Box<dyn FnMut(Vec<String>)>) {
|
||||||
self.0.borrow_mut().open_urls = Some(callback);
|
self.0.lock().open_urls = Some(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prompt_for_paths(
|
fn prompt_for_paths(
|
||||||
|
@ -570,41 +567,38 @@ impl Platform for MacPlatform {
|
||||||
fn reveal_path(&self, path: &Path) {
|
fn reveal_path(&self, path: &Path) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let path = path.to_path_buf();
|
let path = path.to_path_buf();
|
||||||
self.0
|
let dispatcher = self.0.lock().dispatcher.clone();
|
||||||
.borrow()
|
let _ = crate::spawn_on_main_local(dispatcher, async move {
|
||||||
.executor
|
let full_path = ns_string(path.to_str().unwrap_or(""));
|
||||||
.spawn(async move {
|
let root_full_path = ns_string("");
|
||||||
let full_path = ns_string(path.to_str().unwrap_or(""));
|
let workspace: id = msg_send![class!(NSWorkspace), sharedWorkspace];
|
||||||
let root_full_path = ns_string("");
|
let _: BOOL = msg_send![
|
||||||
let workspace: id = msg_send![class!(NSWorkspace), sharedWorkspace];
|
workspace,
|
||||||
let _: BOOL = msg_send![
|
selectFile: full_path
|
||||||
workspace,
|
inFileViewerRootedAtPath: root_full_path
|
||||||
selectFile: full_path
|
];
|
||||||
inFileViewerRootedAtPath: root_full_path
|
});
|
||||||
];
|
|
||||||
})
|
|
||||||
.detach();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_become_active(&self, callback: Box<dyn FnMut()>) {
|
fn on_become_active(&self, callback: Box<dyn FnMut()>) {
|
||||||
self.0.borrow_mut().become_active = Some(callback);
|
self.0.lock().become_active = Some(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_resign_active(&self, callback: Box<dyn FnMut()>) {
|
fn on_resign_active(&self, callback: Box<dyn FnMut()>) {
|
||||||
self.0.borrow_mut().resign_active = Some(callback);
|
self.0.lock().resign_active = Some(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_quit(&self, callback: Box<dyn FnMut()>) {
|
fn on_quit(&self, callback: Box<dyn FnMut()>) {
|
||||||
self.0.borrow_mut().quit = Some(callback);
|
self.0.lock().quit = Some(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_reopen(&self, callback: Box<dyn FnMut()>) {
|
fn on_reopen(&self, callback: Box<dyn FnMut()>) {
|
||||||
self.0.borrow_mut().reopen = Some(callback);
|
self.0.lock().reopen = Some(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_event(&self, callback: Box<dyn FnMut(Event) -> bool>) {
|
fn on_event(&self, callback: Box<dyn FnMut(Event) -> bool>) {
|
||||||
self.0.borrow_mut().event = Some(callback);
|
self.0.lock().event = Some(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn os_name(&self) -> &'static str {
|
fn os_name(&self) -> &'static str {
|
||||||
|
@ -704,7 +698,7 @@ impl Platform for MacPlatform {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_to_clipboard(&self, item: ClipboardItem) {
|
fn write_to_clipboard(&self, item: ClipboardItem) {
|
||||||
let state = self.0.borrow();
|
let state = self.0.lock();
|
||||||
unsafe {
|
unsafe {
|
||||||
state.pasteboard.clearContents();
|
state.pasteboard.clearContents();
|
||||||
|
|
||||||
|
@ -741,7 +735,7 @@ impl Platform for MacPlatform {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_from_clipboard(&self) -> Option<ClipboardItem> {
|
fn read_from_clipboard(&self) -> Option<ClipboardItem> {
|
||||||
let state = self.0.borrow();
|
let state = self.0.lock();
|
||||||
unsafe {
|
unsafe {
|
||||||
if let Some(text_bytes) = self.read_from_pasteboard(NSPasteboardTypeString) {
|
if let Some(text_bytes) = self.read_from_pasteboard(NSPasteboardTypeString) {
|
||||||
let text = String::from_utf8_lossy(text_bytes).to_string();
|
let text = String::from_utf8_lossy(text_bytes).to_string();
|
||||||
|
@ -777,6 +771,32 @@ impl Platform for MacPlatform {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fn on_menu_command(&self, callback: Box<dyn FnMut(&dyn Action)>) {
|
||||||
|
// self.0.lock().menu_command = Some(callback);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn on_will_open_menu(&self, callback: Box<dyn FnMut()>) {
|
||||||
|
// self.0.lock().will_open_menu = Some(callback);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn on_validate_menu_command(&self, callback: Box<dyn FnMut(&dyn Action) -> bool>) {
|
||||||
|
// self.0.lock().validate_menu_command = Some(callback);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn set_menus(&self, menus: Vec<Menu>, keystroke_matcher: &KeymapMatcher) {
|
||||||
|
// unsafe {
|
||||||
|
// let app: id = msg_send![APP_CLASS, sharedApplication];
|
||||||
|
// let mut state = self.0.lock();
|
||||||
|
// let actions = &mut state.menu_actions;
|
||||||
|
// app.setMainMenu_(self.create_menu_bar(
|
||||||
|
// menus,
|
||||||
|
// app.delegate(),
|
||||||
|
// actions,
|
||||||
|
// keystroke_matcher,
|
||||||
|
// ));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
fn write_credentials(&self, url: &str, username: &str, password: &[u8]) -> Result<()> {
|
fn write_credentials(&self, url: &str, username: &str, password: &[u8]) -> Result<()> {
|
||||||
let url = CFString::from(url);
|
let url = CFString::from(url);
|
||||||
let username = CFString::from(username);
|
let username = CFString::from(username);
|
||||||
|
@ -816,32 +836,6 @@ impl Platform for MacPlatform {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// fn on_menu_command(&self, callback: Box<dyn FnMut(&dyn Action)>) {
|
|
||||||
// self.0.borrow_mut().menu_command = Some(callback);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn on_will_open_menu(&self, callback: Box<dyn FnMut()>) {
|
|
||||||
// self.0.borrow_mut().will_open_menu = Some(callback);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn on_validate_menu_command(&self, callback: Box<dyn FnMut(&dyn Action) -> bool>) {
|
|
||||||
// self.0.borrow_mut().validate_menu_command = Some(callback);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn set_menus(&self, menus: Vec<Menu>, keystroke_matcher: &KeymapMatcher) {
|
|
||||||
// unsafe {
|
|
||||||
// let app: id = msg_send![APP_CLASS, sharedApplication];
|
|
||||||
// let mut state = self.0.borrow_mut();
|
|
||||||
// let actions = &mut state.menu_actions;
|
|
||||||
// app.setMainMenu_(self.create_menu_bar(
|
|
||||||
// menus,
|
|
||||||
// app.delegate(),
|
|
||||||
// actions,
|
|
||||||
// keystroke_matcher,
|
|
||||||
// ));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
fn read_credentials(&self, url: &str) -> Result<Option<(String, Vec<u8>)>> {
|
fn read_credentials(&self, url: &str) -> Result<Option<(String, Vec<u8>)>> {
|
||||||
let url = CFString::from(url);
|
let url = CFString::from(url);
|
||||||
let cf_true = CFBoolean::true_value().as_CFTypeRef();
|
let cf_true = CFBoolean::true_value().as_CFTypeRef();
|
||||||
|
@ -921,7 +915,7 @@ extern "C" fn send_event(this: &mut Object, _sel: Sel, native_event: id) {
|
||||||
unsafe {
|
unsafe {
|
||||||
if let Some(event) = Event::from_native(native_event, None) {
|
if let Some(event) = Event::from_native(native_event, None) {
|
||||||
let platform = get_foreground_platform(this);
|
let platform = get_foreground_platform(this);
|
||||||
if let Some(callback) = platform.0.borrow_mut().event.as_mut() {
|
if let Some(callback) = platform.0.lock().event.as_mut() {
|
||||||
if callback(event) {
|
if callback(event) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -937,7 +931,7 @@ extern "C" fn did_finish_launching(this: &mut Object, _: Sel, _: id) {
|
||||||
app.setActivationPolicy_(NSApplicationActivationPolicyRegular);
|
app.setActivationPolicy_(NSApplicationActivationPolicyRegular);
|
||||||
|
|
||||||
let platform = get_foreground_platform(this);
|
let platform = get_foreground_platform(this);
|
||||||
let callback = platform.0.borrow_mut().finish_launching.take();
|
let callback = platform.0.lock().finish_launching.take();
|
||||||
if let Some(callback) = callback {
|
if let Some(callback) = callback {
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
|
@ -947,7 +941,7 @@ extern "C" fn did_finish_launching(this: &mut Object, _: Sel, _: id) {
|
||||||
extern "C" fn should_handle_reopen(this: &mut Object, _: Sel, _: id, has_open_windows: bool) {
|
extern "C" fn should_handle_reopen(this: &mut Object, _: Sel, _: id, has_open_windows: bool) {
|
||||||
if !has_open_windows {
|
if !has_open_windows {
|
||||||
let platform = unsafe { get_foreground_platform(this) };
|
let platform = unsafe { get_foreground_platform(this) };
|
||||||
if let Some(callback) = platform.0.borrow_mut().reopen.as_mut() {
|
if let Some(callback) = platform.0.lock().reopen.as_mut() {
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -955,21 +949,21 @@ extern "C" fn should_handle_reopen(this: &mut Object, _: Sel, _: id, has_open_wi
|
||||||
|
|
||||||
extern "C" fn did_become_active(this: &mut Object, _: Sel, _: id) {
|
extern "C" fn did_become_active(this: &mut Object, _: Sel, _: id) {
|
||||||
let platform = unsafe { get_foreground_platform(this) };
|
let platform = unsafe { get_foreground_platform(this) };
|
||||||
if let Some(callback) = platform.0.borrow_mut().become_active.as_mut() {
|
if let Some(callback) = platform.0.lock().become_active.as_mut() {
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn did_resign_active(this: &mut Object, _: Sel, _: id) {
|
extern "C" fn did_resign_active(this: &mut Object, _: Sel, _: id) {
|
||||||
let platform = unsafe { get_foreground_platform(this) };
|
let platform = unsafe { get_foreground_platform(this) };
|
||||||
if let Some(callback) = platform.0.borrow_mut().resign_active.as_mut() {
|
if let Some(callback) = platform.0.lock().resign_active.as_mut() {
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn will_terminate(this: &mut Object, _: Sel, _: id) {
|
extern "C" fn will_terminate(this: &mut Object, _: Sel, _: id) {
|
||||||
let platform = unsafe { get_foreground_platform(this) };
|
let platform = unsafe { get_foreground_platform(this) };
|
||||||
if let Some(callback) = platform.0.borrow_mut().quit.as_mut() {
|
if let Some(callback) = platform.0.lock().quit.as_mut() {
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -991,7 +985,7 @@ extern "C" fn open_urls(this: &mut Object, _: Sel, _: id, urls: id) {
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
};
|
};
|
||||||
let platform = unsafe { get_foreground_platform(this) };
|
let platform = unsafe { get_foreground_platform(this) };
|
||||||
if let Some(callback) = platform.0.borrow_mut().open_urls.as_mut() {
|
if let Some(callback) = platform.0.lock().open_urls.as_mut() {
|
||||||
callback(urls);
|
callback(urls);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1000,7 +994,7 @@ extern "C" fn handle_menu_item(__this: &mut Object, _: Sel, __item: id) {
|
||||||
todo!()
|
todo!()
|
||||||
// unsafe {
|
// unsafe {
|
||||||
// let platform = get_foreground_platform(this);
|
// let platform = get_foreground_platform(this);
|
||||||
// let mut platform = platform.0.borrow_mut();
|
// let mut platform = platform.0.lock();
|
||||||
// if let Some(mut callback) = platform.menu_command.take() {
|
// if let Some(mut callback) = platform.menu_command.take() {
|
||||||
// let tag: NSInteger = msg_send![item, tag];
|
// let tag: NSInteger = msg_send![item, tag];
|
||||||
// let index = tag as usize;
|
// let index = tag as usize;
|
||||||
|
@ -1017,7 +1011,7 @@ extern "C" fn validate_menu_item(__this: &mut Object, _: Sel, __item: id) -> boo
|
||||||
// unsafe {
|
// unsafe {
|
||||||
// let mut result = false;
|
// let mut result = false;
|
||||||
// let platform = get_foreground_platform(this);
|
// let platform = get_foreground_platform(this);
|
||||||
// let mut platform = platform.0.borrow_mut();
|
// let mut platform = platform.0.lock();
|
||||||
// if let Some(mut callback) = platform.validate_menu_command.take() {
|
// if let Some(mut callback) = platform.validate_menu_command.take() {
|
||||||
// let tag: NSInteger = msg_send![item, tag];
|
// let tag: NSInteger = msg_send![item, tag];
|
||||||
// let index = tag as usize;
|
// let index = tag as usize;
|
||||||
|
@ -1033,7 +1027,7 @@ extern "C" fn validate_menu_item(__this: &mut Object, _: Sel, __item: id) -> boo
|
||||||
extern "C" fn menu_will_open(this: &mut Object, _: Sel, _: id) {
|
extern "C" fn menu_will_open(this: &mut Object, _: Sel, _: id) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let platform = get_foreground_platform(this);
|
let platform = get_foreground_platform(this);
|
||||||
let mut platform = platform.0.borrow_mut();
|
let mut platform = platform.0.lock();
|
||||||
if let Some(mut callback) = platform.will_open_menu.take() {
|
if let Some(mut callback) = platform.will_open_menu.take() {
|
||||||
callback();
|
callback();
|
||||||
platform.will_open_menu = Some(callback);
|
platform.will_open_menu = Some(callback);
|
||||||
|
@ -1112,7 +1106,7 @@ mod tests {
|
||||||
);
|
);
|
||||||
platform
|
platform
|
||||||
.0
|
.0
|
||||||
.borrow_mut()
|
.lock()
|
||||||
.pasteboard
|
.pasteboard
|
||||||
.setData_forType(bytes, NSPasteboardTypeString);
|
.setData_forType(bytes, NSPasteboardTypeString);
|
||||||
}
|
}
|
||||||
|
@ -1124,7 +1118,7 @@ mod tests {
|
||||||
|
|
||||||
fn build_platform() -> MacPlatform {
|
fn build_platform() -> MacPlatform {
|
||||||
let platform = MacPlatform::new();
|
let platform = MacPlatform::new();
|
||||||
platform.0.borrow_mut().pasteboard = unsafe { NSPasteboard::pasteboardWithUniqueName(nil) };
|
platform.0.lock().pasteboard = unsafe { NSPasteboard::pasteboardWithUniqueName(nil) };
|
||||||
platform
|
platform
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
point, px, size, AnyWindowHandle, Bounds, Event, ForegroundExecutor, InputHandler,
|
point, px, size, AnyWindowHandle, Bounds, Event, InputHandler, KeyDownEvent, Keystroke,
|
||||||
KeyDownEvent, Keystroke, MacScreen, Modifiers, ModifiersChangedEvent, MouseButton,
|
MacDispatcher, MacScreen, Modifiers, ModifiersChangedEvent, MouseButton, MouseDownEvent,
|
||||||
MouseDownEvent, MouseMovedEvent, MouseUpEvent, NSRectExt, Pixels, PlatformScreen,
|
MouseMovedEvent, MouseUpEvent, NSRectExt, Pixels, PlatformDispatcher, PlatformScreen,
|
||||||
PlatformTextSystem, PlatformWindow, Point, Size, Timer, WindowAppearance, WindowBounds,
|
PlatformWindow, Point, Size, Timer, WindowAppearance, WindowBounds, WindowKind, WindowOptions,
|
||||||
WindowKind, WindowOptions, WindowPromptLevel,
|
WindowPromptLevel,
|
||||||
};
|
};
|
||||||
use block::ConcreteBlock;
|
use block::ConcreteBlock;
|
||||||
use cocoa::{
|
use cocoa::{
|
||||||
|
@ -25,6 +25,7 @@ use objc::{
|
||||||
runtime::{Class, Object, Protocol, Sel, BOOL, NO, YES},
|
runtime::{Class, Object, Protocol, Sel, BOOL, NO, YES},
|
||||||
sel, sel_impl,
|
sel, sel_impl,
|
||||||
};
|
};
|
||||||
|
use parking_lot::Mutex;
|
||||||
use raw_window_handle::{
|
use raw_window_handle::{
|
||||||
AppKitDisplayHandle, AppKitWindowHandle, HasRawDisplayHandle, HasRawWindowHandle,
|
AppKitDisplayHandle, AppKitWindowHandle, HasRawDisplayHandle, HasRawWindowHandle,
|
||||||
RawDisplayHandle, RawWindowHandle,
|
RawDisplayHandle, RawWindowHandle,
|
||||||
|
@ -282,6 +283,7 @@ struct InsertText {
|
||||||
|
|
||||||
struct WindowState {
|
struct WindowState {
|
||||||
handle: AnyWindowHandle,
|
handle: AnyWindowHandle,
|
||||||
|
dispatcher: Arc<dyn PlatformDispatcher>,
|
||||||
native_window: id,
|
native_window: id,
|
||||||
kind: WindowKind,
|
kind: WindowKind,
|
||||||
event_callback: Option<Box<dyn FnMut(Event) -> bool>>,
|
event_callback: Option<Box<dyn FnMut(Event) -> bool>>,
|
||||||
|
@ -296,7 +298,6 @@ struct WindowState {
|
||||||
pending_key_down: Option<(KeyDownEvent, Option<InsertText>)>,
|
pending_key_down: Option<(KeyDownEvent, Option<InsertText>)>,
|
||||||
last_key_equivalent: Option<KeyDownEvent>,
|
last_key_equivalent: Option<KeyDownEvent>,
|
||||||
synthetic_drag_counter: usize,
|
synthetic_drag_counter: usize,
|
||||||
executor: Rc<ForegroundExecutor>,
|
|
||||||
last_fresh_keydown: Option<Keystroke>,
|
last_fresh_keydown: Option<Keystroke>,
|
||||||
traffic_light_position: Option<Point<Pixels>>,
|
traffic_light_position: Option<Point<Pixels>>,
|
||||||
previous_modifiers_changed_event: Option<Event>,
|
previous_modifiers_changed_event: Option<Event>,
|
||||||
|
@ -411,14 +412,15 @@ impl WindowState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct MacWindow(Rc<RefCell<WindowState>>);
|
unsafe impl Send for WindowState {}
|
||||||
|
|
||||||
|
pub struct MacWindow(Arc<Mutex<WindowState>>);
|
||||||
|
|
||||||
impl MacWindow {
|
impl MacWindow {
|
||||||
pub fn open(
|
pub fn open(
|
||||||
handle: AnyWindowHandle,
|
handle: AnyWindowHandle,
|
||||||
options: WindowOptions,
|
options: WindowOptions,
|
||||||
executor: Rc<ForegroundExecutor>,
|
dispatcher: Arc<MacDispatcher>,
|
||||||
text_system: Arc<dyn PlatformTextSystem>,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
unsafe {
|
unsafe {
|
||||||
let pool = NSAutoreleasePool::new(nil);
|
let pool = NSAutoreleasePool::new(nil);
|
||||||
|
@ -483,8 +485,9 @@ impl MacWindow {
|
||||||
|
|
||||||
assert!(!native_view.is_null());
|
assert!(!native_view.is_null());
|
||||||
|
|
||||||
let window = Self(Rc::new(RefCell::new(WindowState {
|
let window = Self(Arc::new(Mutex::new(WindowState {
|
||||||
handle,
|
handle,
|
||||||
|
dispatcher,
|
||||||
native_window,
|
native_window,
|
||||||
kind: options.kind,
|
kind: options.kind,
|
||||||
event_callback: None,
|
event_callback: None,
|
||||||
|
@ -499,7 +502,6 @@ impl MacWindow {
|
||||||
pending_key_down: None,
|
pending_key_down: None,
|
||||||
last_key_equivalent: None,
|
last_key_equivalent: None,
|
||||||
synthetic_drag_counter: 0,
|
synthetic_drag_counter: 0,
|
||||||
executor,
|
|
||||||
last_fresh_keydown: None,
|
last_fresh_keydown: None,
|
||||||
traffic_light_position: options
|
traffic_light_position: options
|
||||||
.titlebar
|
.titlebar
|
||||||
|
@ -512,12 +514,12 @@ impl MacWindow {
|
||||||
|
|
||||||
(*native_window).set_ivar(
|
(*native_window).set_ivar(
|
||||||
WINDOW_STATE_IVAR,
|
WINDOW_STATE_IVAR,
|
||||||
Rc::into_raw(window.0.clone()) as *const c_void,
|
Arc::into_raw(window.0.clone()) as *const c_void,
|
||||||
);
|
);
|
||||||
native_window.setDelegate_(native_window);
|
native_window.setDelegate_(native_window);
|
||||||
(*native_view).set_ivar(
|
(*native_view).set_ivar(
|
||||||
WINDOW_STATE_IVAR,
|
WINDOW_STATE_IVAR,
|
||||||
Rc::into_raw(window.0.clone()) as *const c_void,
|
Arc::into_raw(window.0.clone()) as *const c_void,
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(title) = options
|
if let Some(title) = options
|
||||||
|
@ -596,7 +598,7 @@ impl MacWindow {
|
||||||
native_window.orderFront_(nil);
|
native_window.orderFront_(nil);
|
||||||
}
|
}
|
||||||
|
|
||||||
window.0.borrow().move_traffic_light();
|
window.0.lock().move_traffic_light();
|
||||||
pool.drain();
|
pool.drain();
|
||||||
|
|
||||||
window
|
window
|
||||||
|
@ -619,21 +621,19 @@ impl MacWindow {
|
||||||
|
|
||||||
impl Drop for MacWindow {
|
impl Drop for MacWindow {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
let this = self.0.borrow();
|
let this = self.0.clone();
|
||||||
let window = this.native_window;
|
let dispatcher = self.0.lock().dispatcher.clone();
|
||||||
this.executor
|
let _ = crate::spawn_on_main(dispatcher, async move {
|
||||||
.spawn(async move {
|
unsafe {
|
||||||
unsafe {
|
this.lock().native_window.close();
|
||||||
window.close();
|
}
|
||||||
}
|
});
|
||||||
})
|
|
||||||
.detach();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl HasRawWindowHandle for MacWindow {
|
unsafe impl HasRawWindowHandle for MacWindow {
|
||||||
fn raw_window_handle(&self) -> RawWindowHandle {
|
fn raw_window_handle(&self) -> RawWindowHandle {
|
||||||
let ns_window = self.0.borrow().native_window;
|
let ns_window = self.0.lock().native_window;
|
||||||
let ns_view = unsafe { ns_window.contentView() };
|
let ns_view = unsafe { ns_window.contentView() };
|
||||||
let mut handle = AppKitWindowHandle::empty();
|
let mut handle = AppKitWindowHandle::empty();
|
||||||
handle.ns_window = ns_window as *mut c_void;
|
handle.ns_window = ns_window as *mut c_void;
|
||||||
|
@ -650,24 +650,24 @@ unsafe impl HasRawDisplayHandle for MacWindow {
|
||||||
|
|
||||||
impl PlatformWindow for MacWindow {
|
impl PlatformWindow for MacWindow {
|
||||||
fn bounds(&self) -> WindowBounds {
|
fn bounds(&self) -> WindowBounds {
|
||||||
self.0.as_ref().borrow().bounds()
|
self.0.as_ref().lock().bounds()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn content_size(&self) -> Size<Pixels> {
|
fn content_size(&self) -> Size<Pixels> {
|
||||||
self.0.as_ref().borrow().content_size().into()
|
self.0.as_ref().lock().content_size().into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scale_factor(&self) -> f32 {
|
fn scale_factor(&self) -> f32 {
|
||||||
self.0.as_ref().borrow().scale_factor()
|
self.0.as_ref().lock().scale_factor()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn titlebar_height(&self) -> Pixels {
|
fn titlebar_height(&self) -> Pixels {
|
||||||
self.0.as_ref().borrow().titlebar_height()
|
self.0.as_ref().lock().titlebar_height()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn appearance(&self) -> WindowAppearance {
|
fn appearance(&self) -> WindowAppearance {
|
||||||
unsafe {
|
unsafe {
|
||||||
let appearance: id = msg_send![self.0.borrow().native_window, effectiveAppearance];
|
let appearance: id = msg_send![self.0.lock().native_window, effectiveAppearance];
|
||||||
WindowAppearance::from_native(appearance)
|
WindowAppearance::from_native(appearance)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -675,7 +675,7 @@ impl PlatformWindow for MacWindow {
|
||||||
fn screen(&self) -> Rc<dyn PlatformScreen> {
|
fn screen(&self) -> Rc<dyn PlatformScreen> {
|
||||||
unsafe {
|
unsafe {
|
||||||
Rc::new(MacScreen {
|
Rc::new(MacScreen {
|
||||||
native_screen: self.0.as_ref().borrow().native_window.screen(),
|
native_screen: self.0.as_ref().lock().native_window.screen(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -683,7 +683,7 @@ impl PlatformWindow for MacWindow {
|
||||||
fn mouse_position(&self) -> Point<Pixels> {
|
fn mouse_position(&self) -> Point<Pixels> {
|
||||||
let position = unsafe {
|
let position = unsafe {
|
||||||
self.0
|
self.0
|
||||||
.borrow()
|
.lock()
|
||||||
.native_window
|
.native_window
|
||||||
.mouseLocationOutsideOfEventStream()
|
.mouseLocationOutsideOfEventStream()
|
||||||
};
|
};
|
||||||
|
@ -695,7 +695,7 @@ impl PlatformWindow for MacWindow {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_input_handler(&mut self, input_handler: Box<dyn InputHandler>) {
|
fn set_input_handler(&mut self, input_handler: Box<dyn InputHandler>) {
|
||||||
self.0.as_ref().borrow_mut().input_handler = Some(input_handler);
|
self.0.as_ref().lock().input_handler = Some(input_handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prompt(
|
fn prompt(
|
||||||
|
@ -761,131 +761,123 @@ impl PlatformWindow for MacWindow {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
let block = block.copy();
|
let block = block.copy();
|
||||||
let native_window = self.0.borrow().native_window;
|
let native_window = self.0.lock().native_window;
|
||||||
self.0
|
let dispatcher = self.0.lock().dispatcher.clone();
|
||||||
.borrow()
|
let _ = crate::spawn_on_main_local(dispatcher, async move {
|
||||||
.executor
|
let _: () = msg_send![
|
||||||
.spawn(async move {
|
alert,
|
||||||
let _: () = msg_send![
|
beginSheetModalForWindow: native_window
|
||||||
alert,
|
completionHandler: block
|
||||||
beginSheetModalForWindow: native_window
|
];
|
||||||
completionHandler: block
|
});
|
||||||
];
|
|
||||||
})
|
|
||||||
.detach();
|
|
||||||
|
|
||||||
done_rx
|
done_rx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn activate(&self) {
|
fn activate(&self) {
|
||||||
let window = self.0.borrow().native_window;
|
let window = self.0.lock().native_window;
|
||||||
self.0
|
let dispatcher = self.0.lock().dispatcher.clone();
|
||||||
.borrow()
|
let _ = crate::spawn_on_main_local(dispatcher.clone(), async move {
|
||||||
.executor
|
unsafe {
|
||||||
.spawn(async move {
|
let _: () = msg_send![window, makeKeyAndOrderFront: nil];
|
||||||
unsafe {
|
}
|
||||||
let _: () = msg_send![window, makeKeyAndOrderFront: nil];
|
});
|
||||||
}
|
|
||||||
})
|
|
||||||
.detach();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_title(&mut self, title: &str) {
|
fn set_title(&mut self, title: &str) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let app = NSApplication::sharedApplication(nil);
|
let app = NSApplication::sharedApplication(nil);
|
||||||
let window = self.0.borrow().native_window;
|
let window = self.0.lock().native_window;
|
||||||
let title = ns_string(title);
|
let title = ns_string(title);
|
||||||
let _: () = msg_send![app, changeWindowsItem:window title:title filename:false];
|
let _: () = msg_send![app, changeWindowsItem:window title:title filename:false];
|
||||||
let _: () = msg_send![window, setTitle: title];
|
let _: () = msg_send![window, setTitle: title];
|
||||||
self.0.borrow().move_traffic_light();
|
self.0.lock().move_traffic_light();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_edited(&mut self, edited: bool) {
|
fn set_edited(&mut self, edited: bool) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let window = self.0.borrow().native_window;
|
let window = self.0.lock().native_window;
|
||||||
msg_send![window, setDocumentEdited: edited as BOOL]
|
msg_send![window, setDocumentEdited: edited as BOOL]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Changing the document edited state resets the traffic light position,
|
// Changing the document edited state resets the traffic light position,
|
||||||
// so we have to move it again.
|
// so we have to move it again.
|
||||||
self.0.borrow().move_traffic_light();
|
self.0.lock().move_traffic_light();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show_character_palette(&self) {
|
fn show_character_palette(&self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let app = NSApplication::sharedApplication(nil);
|
let app = NSApplication::sharedApplication(nil);
|
||||||
let window = self.0.borrow().native_window;
|
let window = self.0.lock().native_window;
|
||||||
let _: () = msg_send![app, orderFrontCharacterPalette: window];
|
let _: () = msg_send![app, orderFrontCharacterPalette: window];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn minimize(&self) {
|
fn minimize(&self) {
|
||||||
let window = self.0.borrow().native_window;
|
let window = self.0.lock().native_window;
|
||||||
unsafe {
|
unsafe {
|
||||||
window.miniaturize_(nil);
|
window.miniaturize_(nil);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn zoom(&self) {
|
fn zoom(&self) {
|
||||||
let this = self.0.borrow();
|
let this = self.0.lock();
|
||||||
let window = this.native_window;
|
let window = this.native_window;
|
||||||
this.executor
|
let dispatcher = this.dispatcher.clone();
|
||||||
.spawn(async move {
|
let _ = crate::spawn_on_main_local(dispatcher, async move {
|
||||||
unsafe {
|
unsafe {
|
||||||
window.zoom_(nil);
|
window.zoom_(nil);
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
.detach();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn toggle_full_screen(&self) {
|
fn toggle_full_screen(&self) {
|
||||||
let this = self.0.borrow();
|
let this = self.0.lock();
|
||||||
let window = this.native_window;
|
let window = this.native_window;
|
||||||
this.executor
|
let dispatcher = this.dispatcher.clone();
|
||||||
.spawn(async move {
|
let _ = crate::spawn_on_main_local(dispatcher, async move {
|
||||||
unsafe {
|
unsafe {
|
||||||
window.toggleFullScreen_(nil);
|
window.toggleFullScreen_(nil);
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
.detach();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_event(&mut self, callback: Box<dyn FnMut(Event) -> bool>) {
|
fn on_event(&mut self, callback: Box<dyn FnMut(Event) -> bool>) {
|
||||||
self.0.as_ref().borrow_mut().event_callback = Some(callback);
|
self.0.as_ref().lock().event_callback = Some(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_active_status_change(&mut self, callback: Box<dyn FnMut(bool)>) {
|
fn on_active_status_change(&mut self, callback: Box<dyn FnMut(bool)>) {
|
||||||
self.0.as_ref().borrow_mut().activate_callback = Some(callback);
|
self.0.as_ref().lock().activate_callback = Some(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_resize(&mut self, callback: Box<dyn FnMut()>) {
|
fn on_resize(&mut self, callback: Box<dyn FnMut()>) {
|
||||||
self.0.as_ref().borrow_mut().resize_callback = Some(callback);
|
self.0.as_ref().lock().resize_callback = Some(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_fullscreen(&mut self, callback: Box<dyn FnMut(bool)>) {
|
fn on_fullscreen(&mut self, callback: Box<dyn FnMut(bool)>) {
|
||||||
self.0.as_ref().borrow_mut().fullscreen_callback = Some(callback);
|
self.0.as_ref().lock().fullscreen_callback = Some(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_moved(&mut self, callback: Box<dyn FnMut()>) {
|
fn on_moved(&mut self, callback: Box<dyn FnMut()>) {
|
||||||
self.0.as_ref().borrow_mut().moved_callback = Some(callback);
|
self.0.as_ref().lock().moved_callback = Some(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_should_close(&mut self, callback: Box<dyn FnMut() -> bool>) {
|
fn on_should_close(&mut self, callback: Box<dyn FnMut() -> bool>) {
|
||||||
self.0.as_ref().borrow_mut().should_close_callback = Some(callback);
|
self.0.as_ref().lock().should_close_callback = Some(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_close(&mut self, callback: Box<dyn FnOnce()>) {
|
fn on_close(&mut self, callback: Box<dyn FnOnce()>) {
|
||||||
self.0.as_ref().borrow_mut().close_callback = Some(callback);
|
self.0.as_ref().lock().close_callback = Some(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_appearance_changed(&mut self, callback: Box<dyn FnMut()>) {
|
fn on_appearance_changed(&mut self, callback: Box<dyn FnMut()>) {
|
||||||
self.0.borrow_mut().appearance_changed_callback = Some(callback);
|
self.0.lock().appearance_changed_callback = Some(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_topmost_for_position(&self, position: Point<Pixels>) -> bool {
|
fn is_topmost_for_position(&self, position: Point<Pixels>) -> bool {
|
||||||
let self_borrow = self.0.borrow();
|
let self_borrow = self.0.lock();
|
||||||
let self_handle = self_borrow.handle;
|
let self_handle = self_borrow.handle;
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -1133,14 +1125,15 @@ extern "C" fn handle_view_event(this: &Object, _: Sel, native_event: id) {
|
||||||
},
|
},
|
||||||
) => {
|
) => {
|
||||||
window_state_borrow.synthetic_drag_counter += 1;
|
window_state_borrow.synthetic_drag_counter += 1;
|
||||||
window_state_borrow
|
let dispatcher = window_state_borrow.dispatcher.clone();
|
||||||
.executor
|
let _ = crate::spawn_on_main_local(
|
||||||
.spawn(synthetic_drag(
|
dispatcher,
|
||||||
|
synthetic_drag(
|
||||||
weak_window_state,
|
weak_window_state,
|
||||||
window_state_borrow.synthetic_drag_counter,
|
window_state_borrow.synthetic_drag_counter,
|
||||||
event.clone(),
|
event.clone(),
|
||||||
))
|
),
|
||||||
.detach();
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Event::MouseMoved(_)
|
Event::MouseMoved(_)
|
||||||
|
@ -1263,18 +1256,16 @@ extern "C" fn window_did_change_key_status(this: &Object, selector: Sel, _: id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let executor = window_state_borrow.executor.clone();
|
let dispatcher = window_state_borrow.dispatcher.clone();
|
||||||
drop(window_state_borrow);
|
drop(window_state_borrow);
|
||||||
executor
|
let _ = crate::spawn_on_main_local(dispatcher, async move {
|
||||||
.spawn(async move {
|
let mut window_state_borrow = window_state.as_ref().borrow_mut();
|
||||||
let mut window_state_borrow = window_state.as_ref().borrow_mut();
|
if let Some(mut callback) = window_state_borrow.activate_callback.take() {
|
||||||
if let Some(mut callback) = window_state_borrow.activate_callback.take() {
|
drop(window_state_borrow);
|
||||||
drop(window_state_borrow);
|
callback(is_active);
|
||||||
callback(is_active);
|
window_state.borrow_mut().activate_callback = Some(callback);
|
||||||
window_state.borrow_mut().activate_callback = Some(callback);
|
};
|
||||||
};
|
});
|
||||||
})
|
|
||||||
.detach();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn window_should_close(this: &Object, _: Sel, _: id) -> BOOL {
|
extern "C" fn window_should_close(this: &Object, _: Sel, _: id) -> BOOL {
|
||||||
|
|
|
@ -9,7 +9,7 @@ impl TestPlatform {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Platform for TestPlatform {
|
impl Platform for TestPlatform {
|
||||||
fn executor(&self) -> std::rc::Rc<crate::ForegroundExecutor> {
|
fn dispatcher(&self) -> std::sync::Arc<dyn crate::PlatformDispatcher> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -215,133 +215,134 @@ impl Boundary {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{AppContext, FontWeight};
|
use crate::{App, AppContext, FontWeight};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_wrap_line() {
|
fn test_wrap_line() {
|
||||||
let cx = AppContext::test();
|
App::test().run(|cx| {
|
||||||
|
let text_system = cx.text_system().clone();
|
||||||
|
let family = text_system
|
||||||
|
.load_font_family(&["Courier"], &Default::default())
|
||||||
|
.unwrap();
|
||||||
|
let font_id = text_system
|
||||||
|
.select_font(family, Default::default(), Default::default())
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let text_system = cx.text_system().clone();
|
let mut wrapper =
|
||||||
let family = text_system
|
LineWrapper::new(font_id, px(16.), text_system.platform_text_system.clone());
|
||||||
.load_font_family(&["Courier"], &Default::default())
|
assert_eq!(
|
||||||
.unwrap();
|
wrapper
|
||||||
let font_id = text_system
|
.wrap_line("aa bbb cccc ddddd eeee", px(72.))
|
||||||
.select_font(family, Default::default(), Default::default())
|
.collect::<Vec<_>>(),
|
||||||
.unwrap();
|
&[
|
||||||
|
Boundary::new(7, 0),
|
||||||
let mut wrapper =
|
Boundary::new(12, 0),
|
||||||
LineWrapper::new(font_id, px(16.), text_system.platform_text_system.clone());
|
Boundary::new(18, 0)
|
||||||
assert_eq!(
|
],
|
||||||
wrapper
|
);
|
||||||
.wrap_line("aa bbb cccc ddddd eeee", px(72.))
|
assert_eq!(
|
||||||
.collect::<Vec<_>>(),
|
wrapper
|
||||||
&[
|
.wrap_line("aaa aaaaaaaaaaaaaaaaaa", px(72.0))
|
||||||
Boundary::new(7, 0),
|
.collect::<Vec<_>>(),
|
||||||
Boundary::new(12, 0),
|
&[
|
||||||
Boundary::new(18, 0)
|
Boundary::new(4, 0),
|
||||||
],
|
Boundary::new(11, 0),
|
||||||
);
|
Boundary::new(18, 0)
|
||||||
assert_eq!(
|
],
|
||||||
wrapper
|
);
|
||||||
.wrap_line("aaa aaaaaaaaaaaaaaaaaa", px(72.0))
|
assert_eq!(
|
||||||
.collect::<Vec<_>>(),
|
wrapper
|
||||||
&[
|
.wrap_line(" aaaaaaa", px(72.))
|
||||||
Boundary::new(4, 0),
|
.collect::<Vec<_>>(),
|
||||||
Boundary::new(11, 0),
|
&[
|
||||||
Boundary::new(18, 0)
|
Boundary::new(7, 5),
|
||||||
],
|
Boundary::new(9, 5),
|
||||||
);
|
Boundary::new(11, 5),
|
||||||
assert_eq!(
|
]
|
||||||
wrapper
|
);
|
||||||
.wrap_line(" aaaaaaa", px(72.))
|
assert_eq!(
|
||||||
.collect::<Vec<_>>(),
|
wrapper
|
||||||
&[
|
.wrap_line(" ", px(72.))
|
||||||
Boundary::new(7, 5),
|
.collect::<Vec<_>>(),
|
||||||
Boundary::new(9, 5),
|
&[
|
||||||
Boundary::new(11, 5),
|
Boundary::new(7, 0),
|
||||||
]
|
Boundary::new(14, 0),
|
||||||
);
|
Boundary::new(21, 0)
|
||||||
assert_eq!(
|
]
|
||||||
wrapper
|
);
|
||||||
.wrap_line(" ", px(72.))
|
assert_eq!(
|
||||||
.collect::<Vec<_>>(),
|
wrapper
|
||||||
&[
|
.wrap_line(" aaaaaaaaaaaaaa", px(72.))
|
||||||
Boundary::new(7, 0),
|
.collect::<Vec<_>>(),
|
||||||
Boundary::new(14, 0),
|
&[
|
||||||
Boundary::new(21, 0)
|
Boundary::new(7, 0),
|
||||||
]
|
Boundary::new(14, 3),
|
||||||
);
|
Boundary::new(18, 3),
|
||||||
assert_eq!(
|
Boundary::new(22, 3),
|
||||||
wrapper
|
]
|
||||||
.wrap_line(" aaaaaaaaaaaaaa", px(72.))
|
);
|
||||||
.collect::<Vec<_>>(),
|
});
|
||||||
&[
|
|
||||||
Boundary::new(7, 0),
|
|
||||||
Boundary::new(14, 3),
|
|
||||||
Boundary::new(18, 3),
|
|
||||||
Boundary::new(22, 3),
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo! repeat this test
|
// todo! repeat this test
|
||||||
#[test]
|
#[test]
|
||||||
fn test_wrap_shaped_line() {
|
fn test_wrap_shaped_line() {
|
||||||
let cx = AppContext::test();
|
App::test().run(|cx| {
|
||||||
let text_system = cx.text_system().clone();
|
let text_system = cx.text_system().clone();
|
||||||
|
|
||||||
let family = text_system
|
let family = text_system
|
||||||
.load_font_family(&["Helvetica"], &Default::default())
|
.load_font_family(&["Helvetica"], &Default::default())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let font_id = text_system
|
let font_id = text_system
|
||||||
.select_font(family, Default::default(), Default::default())
|
.select_font(family, Default::default(), Default::default())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let normal = RunStyle {
|
let normal = RunStyle {
|
||||||
font_id,
|
font_id,
|
||||||
color: Default::default(),
|
color: Default::default(),
|
||||||
underline: Default::default(),
|
underline: Default::default(),
|
||||||
};
|
};
|
||||||
let bold = RunStyle {
|
let bold = RunStyle {
|
||||||
font_id: text_system
|
font_id: text_system
|
||||||
.select_font(family, FontWeight::BOLD, Default::default())
|
.select_font(family, FontWeight::BOLD, Default::default())
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
color: Default::default(),
|
color: Default::default(),
|
||||||
underline: Default::default(),
|
underline: Default::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let text = "aa bbb cccc ddddd eeee";
|
let text = "aa bbb cccc ddddd eeee";
|
||||||
let line = text_system.layout_str(
|
let line = text_system.layout_str(
|
||||||
text,
|
text,
|
||||||
px(16.),
|
px(16.),
|
||||||
&[
|
&[
|
||||||
(4, normal.clone()),
|
(4, normal.clone()),
|
||||||
(5, bold.clone()),
|
(5, bold.clone()),
|
||||||
(6, normal.clone()),
|
(6, normal.clone()),
|
||||||
(1, bold),
|
(1, bold),
|
||||||
(7, normal),
|
(7, normal),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut wrapper =
|
let mut wrapper =
|
||||||
LineWrapper::new(font_id, px(16.), text_system.platform_text_system.clone());
|
LineWrapper::new(font_id, px(16.), text_system.platform_text_system.clone());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
wrapper
|
wrapper
|
||||||
.wrap_shaped_line(text, &line, px(72.))
|
.wrap_shaped_line(text, &line, px(72.))
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
&[
|
&[
|
||||||
ShapedBoundary {
|
ShapedBoundary {
|
||||||
run_ix: 1,
|
run_ix: 1,
|
||||||
glyph_ix: 3
|
glyph_ix: 3
|
||||||
},
|
},
|
||||||
ShapedBoundary {
|
ShapedBoundary {
|
||||||
run_ix: 2,
|
run_ix: 2,
|
||||||
glyph_ix: 3
|
glyph_ix: 3
|
||||||
},
|
},
|
||||||
ShapedBoundary {
|
ShapedBoundary {
|
||||||
run_ix: 4,
|
run_ix: 4,
|
||||||
glyph_ix: 2
|
glyph_ix: 2
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
use crate::{
|
use crate::{AvailableSpace, PlatformWindow, Point, Size, Style, TextStyle, TextStyleRefinement};
|
||||||
AvailableSpace, Bg, PlatformWindow, Point, Size, Style, TextStyle, TextStyleRefinement,
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
px, taffy::LayoutId, AppContext, Bounds, Context, EntityId, Handle, Pixels, Reference,
|
px, taffy::LayoutId, AppContext, Bounds, Context, EntityId, Handle, Pixels, Reference,
|
||||||
|
@ -39,22 +37,22 @@ impl Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deref, DerefMut)]
|
#[derive(Deref, DerefMut)]
|
||||||
pub struct WindowContext<'a, 'b> {
|
pub struct WindowContext<'a, 'b, Thread = ()> {
|
||||||
#[deref]
|
#[deref]
|
||||||
#[deref_mut]
|
#[deref_mut]
|
||||||
app: Reference<'a, AppContext>,
|
app: Reference<'a, AppContext<Thread>>,
|
||||||
window: Reference<'b, Window>,
|
window: Reference<'b, Window>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'w> WindowContext<'a, 'w> {
|
impl<'a, 'w, Thread> WindowContext<'a, 'w, Thread> {
|
||||||
pub(crate) fn mutable(app: &'a mut AppContext<Bg>, window: &'w mut Window) -> Self {
|
pub(crate) fn mutable(app: &'a mut AppContext<Thread>, window: &'w mut Window) -> Self {
|
||||||
Self {
|
Self {
|
||||||
app: Reference::Mutable(app),
|
app: Reference::Mutable(app),
|
||||||
window: Reference::Mutable(window),
|
window: Reference::Mutable(window),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn immutable(app: &'a AppContext, window: &'w Window) -> Self {
|
pub(crate) fn immutable(app: &'a AppContext<Thread>, window: &'w Window) -> Self {
|
||||||
Self {
|
Self {
|
||||||
app: Reference::Immutable(app),
|
app: Reference::Immutable(app),
|
||||||
window: Reference::Immutable(window),
|
window: Reference::Immutable(window),
|
||||||
|
@ -123,7 +121,7 @@ impl<'a, 'w> WindowContext<'a, 'w> {
|
||||||
fn update_window<R>(
|
fn update_window<R>(
|
||||||
&mut self,
|
&mut self,
|
||||||
window_id: WindowId,
|
window_id: WindowId,
|
||||||
update: impl FnOnce(&mut WindowContext) -> R,
|
update: impl FnOnce(&mut WindowContext<Thread>) -> R,
|
||||||
) -> Result<R> {
|
) -> Result<R> {
|
||||||
if window_id == self.window.id {
|
if window_id == self.window.id {
|
||||||
Ok(update(self))
|
Ok(update(self))
|
||||||
|
|
|
@ -21,7 +21,7 @@ mod workspace;
|
||||||
fn main() {
|
fn main() {
|
||||||
SimpleLogger::init(LevelFilter::Info, Default::default()).expect("could not initialize logger");
|
SimpleLogger::init(LevelFilter::Info, Default::default()).expect("could not initialize logger");
|
||||||
|
|
||||||
gpui3::App::new().run(|cx| {
|
gpui3::App::production().run(|cx| {
|
||||||
let window: gpui3::WindowHandle<()> = cx.open_window(Default::default(), |cx| todo!());
|
let window: gpui3::WindowHandle<()> = cx.open_window(Default::default(), |cx| todo!());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue