Merge remote-tracking branch 'origin/main' into paint-context
This commit is contained in:
commit
db96fb1307
163 changed files with 9459 additions and 4729 deletions
|
@ -22,6 +22,7 @@ sqlez = { path = "../sqlez" }
|
|||
async-task = "4.0.3"
|
||||
backtrace = { version = "0.3", optional = true }
|
||||
ctor.workspace = true
|
||||
derive_more.workspace = true
|
||||
dhat = { version = "0.3", optional = true }
|
||||
env_logger = { version = "0.9", optional = true }
|
||||
etagere = "0.2"
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -77,9 +77,9 @@ pub(crate) fn setup_menu_handlers(foreground_platform: &dyn ForegroundPlatform,
|
|||
let cx = app.0.clone();
|
||||
move |action| {
|
||||
let mut cx = cx.borrow_mut();
|
||||
if let Some(main_window_id) = cx.platform.main_window_id() {
|
||||
let dispatched = cx
|
||||
.update_window(main_window_id, |cx| {
|
||||
if let Some(main_window) = cx.active_window() {
|
||||
let dispatched = main_window
|
||||
.update(&mut *cx, |cx| {
|
||||
if let Some(view_id) = cx.focused_view_id() {
|
||||
cx.dispatch_action(Some(view_id), action);
|
||||
true
|
||||
|
|
|
@ -9,7 +9,7 @@ use collections::{hash_map::Entry, HashMap, HashSet};
|
|||
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
use crate::util::post_inc;
|
||||
use crate::ElementStateId;
|
||||
use crate::{AnyWindowHandle, ElementStateId};
|
||||
|
||||
lazy_static! {
|
||||
static ref LEAK_BACKTRACE: bool =
|
||||
|
@ -26,7 +26,7 @@ pub struct RefCounts {
|
|||
entity_counts: HashMap<usize, usize>,
|
||||
element_state_counts: HashMap<ElementStateId, ElementStateRefCount>,
|
||||
dropped_models: HashSet<usize>,
|
||||
dropped_views: HashSet<(usize, usize)>,
|
||||
dropped_views: HashSet<(AnyWindowHandle, usize)>,
|
||||
dropped_element_states: HashSet<ElementStateId>,
|
||||
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
|
@ -55,12 +55,12 @@ impl RefCounts {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn inc_view(&mut self, window_id: usize, view_id: usize) {
|
||||
pub fn inc_view(&mut self, window: AnyWindowHandle, view_id: usize) {
|
||||
match self.entity_counts.entry(view_id) {
|
||||
Entry::Occupied(mut entry) => *entry.get_mut() += 1,
|
||||
Entry::Vacant(entry) => {
|
||||
entry.insert(1);
|
||||
self.dropped_views.remove(&(window_id, view_id));
|
||||
self.dropped_views.remove(&(window, view_id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -94,12 +94,12 @@ impl RefCounts {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn dec_view(&mut self, window_id: usize, view_id: usize) {
|
||||
pub fn dec_view(&mut self, window: AnyWindowHandle, view_id: usize) {
|
||||
let count = self.entity_counts.get_mut(&view_id).unwrap();
|
||||
*count -= 1;
|
||||
if *count == 0 {
|
||||
self.entity_counts.remove(&view_id);
|
||||
self.dropped_views.insert((window_id, view_id));
|
||||
self.dropped_views.insert((window, view_id));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -120,7 +120,7 @@ impl RefCounts {
|
|||
&mut self,
|
||||
) -> (
|
||||
HashSet<usize>,
|
||||
HashSet<(usize, usize)>,
|
||||
HashSet<(AnyWindowHandle, usize)>,
|
||||
HashSet<ElementStateId>,
|
||||
) {
|
||||
(
|
||||
|
|
|
@ -4,9 +4,9 @@ use crate::{
|
|||
keymap_matcher::{Binding, Keystroke},
|
||||
platform,
|
||||
platform::{Event, InputHandler, KeyDownEvent, Platform},
|
||||
Action, AppContext, BorrowAppContext, BorrowWindowContext, Entity, FontCache, Handle,
|
||||
ModelContext, ModelHandle, Subscription, Task, View, ViewContext, ViewHandle, WeakHandle,
|
||||
WindowContext,
|
||||
Action, AnyWindowHandle, AppContext, BorrowAppContext, BorrowWindowContext, Entity, FontCache,
|
||||
Handle, ModelContext, ModelHandle, Subscription, Task, View, ViewContext, ViewHandle,
|
||||
WeakHandle, WindowContext, WindowHandle,
|
||||
};
|
||||
use collections::BTreeMap;
|
||||
use futures::Future;
|
||||
|
@ -60,7 +60,7 @@ impl TestAppContext {
|
|||
RefCounts::new(leak_detector),
|
||||
(),
|
||||
);
|
||||
cx.next_entity_id = first_entity_id;
|
||||
cx.next_id = first_entity_id;
|
||||
let cx = TestAppContext {
|
||||
cx: Rc::new(RefCell::new(cx)),
|
||||
foreground_platform,
|
||||
|
@ -72,8 +72,8 @@ impl TestAppContext {
|
|||
cx
|
||||
}
|
||||
|
||||
pub fn dispatch_action<A: Action>(&mut self, window_id: usize, action: A) {
|
||||
self.update_window(window_id, |window| {
|
||||
pub fn dispatch_action<A: Action>(&mut self, window: AnyWindowHandle, action: A) {
|
||||
self.update_window(window, |window| {
|
||||
window.dispatch_action(window.focused_view_id(), &action);
|
||||
})
|
||||
.expect("window not found");
|
||||
|
@ -81,10 +81,10 @@ impl TestAppContext {
|
|||
|
||||
pub fn available_actions(
|
||||
&self,
|
||||
window_id: usize,
|
||||
window: AnyWindowHandle,
|
||||
view_id: usize,
|
||||
) -> Vec<(&'static str, Box<dyn Action>, SmallVec<[Binding; 1]>)> {
|
||||
self.read_window(window_id, |cx| cx.available_actions(view_id))
|
||||
self.read_window(window, |cx| cx.available_actions(view_id))
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
|
@ -92,33 +92,34 @@ impl TestAppContext {
|
|||
self.update(|cx| cx.dispatch_global_action_any(&action));
|
||||
}
|
||||
|
||||
pub fn dispatch_keystroke(&mut self, window_id: usize, keystroke: Keystroke, is_held: bool) {
|
||||
let handled = self
|
||||
.cx
|
||||
.borrow_mut()
|
||||
.update_window(window_id, |cx| {
|
||||
if cx.dispatch_keystroke(&keystroke) {
|
||||
return true;
|
||||
}
|
||||
pub fn dispatch_keystroke(
|
||||
&mut self,
|
||||
window: AnyWindowHandle,
|
||||
keystroke: Keystroke,
|
||||
is_held: bool,
|
||||
) {
|
||||
let handled = window.update(self, |cx| {
|
||||
if cx.dispatch_keystroke(&keystroke) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if cx.dispatch_event(
|
||||
Event::KeyDown(KeyDownEvent {
|
||||
keystroke: keystroke.clone(),
|
||||
is_held,
|
||||
}),
|
||||
false,
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
if cx.dispatch_event(
|
||||
Event::KeyDown(KeyDownEvent {
|
||||
keystroke: keystroke.clone(),
|
||||
is_held,
|
||||
}),
|
||||
false,
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
false
|
||||
})
|
||||
.unwrap_or(false);
|
||||
false
|
||||
});
|
||||
|
||||
if !handled && !keystroke.cmd && !keystroke.ctrl {
|
||||
WindowInputHandler {
|
||||
app: self.cx.clone(),
|
||||
window_id,
|
||||
window,
|
||||
}
|
||||
.replace_text_in_range(None, &keystroke.key)
|
||||
}
|
||||
|
@ -126,18 +127,18 @@ impl TestAppContext {
|
|||
|
||||
pub fn read_window<T, F: FnOnce(&WindowContext) -> T>(
|
||||
&self,
|
||||
window_id: usize,
|
||||
window: AnyWindowHandle,
|
||||
callback: F,
|
||||
) -> Option<T> {
|
||||
self.cx.borrow().read_window(window_id, callback)
|
||||
self.cx.borrow().read_window(window, callback)
|
||||
}
|
||||
|
||||
pub fn update_window<T, F: FnOnce(&mut WindowContext) -> T>(
|
||||
&mut self,
|
||||
window_id: usize,
|
||||
window: AnyWindowHandle,
|
||||
callback: F,
|
||||
) -> Option<T> {
|
||||
self.cx.borrow_mut().update_window(window_id, callback)
|
||||
self.cx.borrow_mut().update_window(window, callback)
|
||||
}
|
||||
|
||||
pub fn add_model<T, F>(&mut self, build_model: F) -> ModelHandle<T>
|
||||
|
@ -148,26 +149,17 @@ impl TestAppContext {
|
|||
self.cx.borrow_mut().add_model(build_model)
|
||||
}
|
||||
|
||||
pub fn add_window<T, F>(&mut self, build_root_view: F) -> (usize, ViewHandle<T>)
|
||||
pub fn add_window<V, F>(&mut self, build_root_view: F) -> WindowHandle<V>
|
||||
where
|
||||
T: View,
|
||||
F: FnOnce(&mut ViewContext<T>) -> T,
|
||||
V: View,
|
||||
F: FnOnce(&mut ViewContext<V>) -> V,
|
||||
{
|
||||
let (window_id, view) = self
|
||||
let window = self
|
||||
.cx
|
||||
.borrow_mut()
|
||||
.add_window(Default::default(), build_root_view);
|
||||
self.simulate_window_activation(Some(window_id));
|
||||
(window_id, view)
|
||||
}
|
||||
|
||||
pub fn add_view<T, F>(&mut self, window_id: usize, build_view: F) -> ViewHandle<T>
|
||||
where
|
||||
T: View,
|
||||
F: FnOnce(&mut ViewContext<T>) -> T,
|
||||
{
|
||||
self.update_window(window_id, |cx| cx.add_view(build_view))
|
||||
.expect("window not found")
|
||||
window.simulate_activation(self);
|
||||
window
|
||||
}
|
||||
|
||||
pub fn observe_global<E, F>(&mut self, callback: F) -> Subscription
|
||||
|
@ -190,8 +182,8 @@ impl TestAppContext {
|
|||
self.cx.borrow_mut().subscribe_global(callback)
|
||||
}
|
||||
|
||||
pub fn window_ids(&self) -> Vec<usize> {
|
||||
self.cx.borrow().windows.keys().copied().collect()
|
||||
pub fn windows(&self) -> Vec<AnyWindowHandle> {
|
||||
self.cx.borrow().windows().collect()
|
||||
}
|
||||
|
||||
pub fn remove_all_windows(&mut self) {
|
||||
|
@ -261,76 +253,6 @@ impl TestAppContext {
|
|||
self.foreground_platform.as_ref().did_prompt_for_new_path()
|
||||
}
|
||||
|
||||
pub fn simulate_prompt_answer(&self, window_id: usize, answer: usize) {
|
||||
use postage::prelude::Sink as _;
|
||||
|
||||
let mut done_tx = self
|
||||
.platform_window_mut(window_id)
|
||||
.pending_prompts
|
||||
.borrow_mut()
|
||||
.pop_front()
|
||||
.expect("prompt was not called");
|
||||
done_tx.try_send(answer).ok();
|
||||
}
|
||||
|
||||
pub fn has_pending_prompt(&self, window_id: usize) -> bool {
|
||||
let window = self.platform_window_mut(window_id);
|
||||
let prompts = window.pending_prompts.borrow_mut();
|
||||
!prompts.is_empty()
|
||||
}
|
||||
|
||||
pub fn current_window_title(&self, window_id: usize) -> Option<String> {
|
||||
self.platform_window_mut(window_id).title.clone()
|
||||
}
|
||||
|
||||
pub fn simulate_window_close(&self, window_id: usize) -> bool {
|
||||
let handler = self
|
||||
.platform_window_mut(window_id)
|
||||
.should_close_handler
|
||||
.take();
|
||||
if let Some(mut handler) = handler {
|
||||
let should_close = handler();
|
||||
self.platform_window_mut(window_id).should_close_handler = Some(handler);
|
||||
should_close
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn simulate_window_resize(&self, window_id: usize, size: Vector2F) {
|
||||
let mut window = self.platform_window_mut(window_id);
|
||||
window.size = size;
|
||||
let mut handlers = mem::take(&mut window.resize_handlers);
|
||||
drop(window);
|
||||
for handler in &mut handlers {
|
||||
handler();
|
||||
}
|
||||
self.platform_window_mut(window_id).resize_handlers = handlers;
|
||||
}
|
||||
|
||||
pub fn simulate_window_activation(&self, to_activate: Option<usize>) {
|
||||
self.cx.borrow_mut().update(|cx| {
|
||||
let other_window_ids = cx
|
||||
.windows
|
||||
.keys()
|
||||
.filter(|window_id| Some(**window_id) != to_activate)
|
||||
.copied()
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
for window_id in other_window_ids {
|
||||
cx.window_changed_active_status(window_id, false)
|
||||
}
|
||||
|
||||
if let Some(to_activate) = to_activate {
|
||||
cx.window_changed_active_status(to_activate, true)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
pub fn is_window_edited(&self, window_id: usize) -> bool {
|
||||
self.platform_window_mut(window_id).edited
|
||||
}
|
||||
|
||||
pub fn leak_detector(&self) -> Arc<Mutex<LeakDetector>> {
|
||||
self.cx.borrow().leak_detector()
|
||||
}
|
||||
|
@ -351,18 +273,6 @@ impl TestAppContext {
|
|||
self.assert_dropped(weak);
|
||||
}
|
||||
|
||||
fn platform_window_mut(&self, window_id: usize) -> std::cell::RefMut<platform::test::Window> {
|
||||
std::cell::RefMut::map(self.cx.borrow_mut(), |state| {
|
||||
let window = state.windows.get_mut(&window_id).unwrap();
|
||||
let test_window = window
|
||||
.platform_window
|
||||
.as_any_mut()
|
||||
.downcast_mut::<platform::test::Window>()
|
||||
.unwrap();
|
||||
test_window
|
||||
})
|
||||
}
|
||||
|
||||
pub fn set_condition_duration(&mut self, duration: Option<Duration>) {
|
||||
self.condition_duration = duration;
|
||||
}
|
||||
|
@ -405,19 +315,39 @@ impl BorrowAppContext for TestAppContext {
|
|||
}
|
||||
|
||||
impl BorrowWindowContext for TestAppContext {
|
||||
fn read_with<T, F: FnOnce(&WindowContext) -> T>(&self, window_id: usize, f: F) -> T {
|
||||
type Result<T> = T;
|
||||
|
||||
fn read_window<T, F: FnOnce(&WindowContext) -> T>(&self, window: AnyWindowHandle, f: F) -> T {
|
||||
self.cx
|
||||
.borrow()
|
||||
.read_window(window_id, f)
|
||||
.read_window(window, f)
|
||||
.expect("window was closed")
|
||||
}
|
||||
|
||||
fn update<T, F: FnOnce(&mut WindowContext) -> T>(&mut self, window_id: usize, f: F) -> T {
|
||||
fn read_window_optional<T, F>(&self, window: AnyWindowHandle, f: F) -> Option<T>
|
||||
where
|
||||
F: FnOnce(&WindowContext) -> Option<T>,
|
||||
{
|
||||
BorrowWindowContext::read_window(self, window, f)
|
||||
}
|
||||
|
||||
fn update_window<T, F: FnOnce(&mut WindowContext) -> T>(
|
||||
&mut self,
|
||||
window: AnyWindowHandle,
|
||||
f: F,
|
||||
) -> T {
|
||||
self.cx
|
||||
.borrow_mut()
|
||||
.update_window(window_id, f)
|
||||
.update_window(window, f)
|
||||
.expect("window was closed")
|
||||
}
|
||||
|
||||
fn update_window_optional<T, F>(&mut self, window: AnyWindowHandle, f: F) -> Option<T>
|
||||
where
|
||||
F: FnOnce(&mut WindowContext) -> Option<T>,
|
||||
{
|
||||
BorrowWindowContext::update_window(self, window, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Entity> ModelHandle<T> {
|
||||
|
@ -532,6 +462,71 @@ impl<T: Entity> ModelHandle<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl AnyWindowHandle {
|
||||
pub fn has_pending_prompt(&self, cx: &mut TestAppContext) -> bool {
|
||||
let window = self.platform_window_mut(cx);
|
||||
let prompts = window.pending_prompts.borrow_mut();
|
||||
!prompts.is_empty()
|
||||
}
|
||||
|
||||
pub fn current_title(&self, cx: &mut TestAppContext) -> Option<String> {
|
||||
self.platform_window_mut(cx).title.clone()
|
||||
}
|
||||
|
||||
pub fn simulate_close(&self, cx: &mut TestAppContext) -> bool {
|
||||
let handler = self.platform_window_mut(cx).should_close_handler.take();
|
||||
if let Some(mut handler) = handler {
|
||||
let should_close = handler();
|
||||
self.platform_window_mut(cx).should_close_handler = Some(handler);
|
||||
should_close
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn simulate_resize(&self, size: Vector2F, cx: &mut TestAppContext) {
|
||||
let mut window = self.platform_window_mut(cx);
|
||||
window.size = size;
|
||||
let mut handlers = mem::take(&mut window.resize_handlers);
|
||||
drop(window);
|
||||
for handler in &mut handlers {
|
||||
handler();
|
||||
}
|
||||
self.platform_window_mut(cx).resize_handlers = handlers;
|
||||
}
|
||||
|
||||
pub fn is_edited(&self, cx: &mut TestAppContext) -> bool {
|
||||
self.platform_window_mut(cx).edited
|
||||
}
|
||||
|
||||
pub fn simulate_prompt_answer(&self, answer: usize, cx: &mut TestAppContext) {
|
||||
use postage::prelude::Sink as _;
|
||||
|
||||
let mut done_tx = self
|
||||
.platform_window_mut(cx)
|
||||
.pending_prompts
|
||||
.borrow_mut()
|
||||
.pop_front()
|
||||
.expect("prompt was not called");
|
||||
done_tx.try_send(answer).ok();
|
||||
}
|
||||
|
||||
fn platform_window_mut<'a>(
|
||||
&self,
|
||||
cx: &'a mut TestAppContext,
|
||||
) -> std::cell::RefMut<'a, platform::test::Window> {
|
||||
std::cell::RefMut::map(cx.cx.borrow_mut(), |state| {
|
||||
let window = state.windows.get_mut(&self).unwrap();
|
||||
let test_window = window
|
||||
.platform_window
|
||||
.as_any_mut()
|
||||
.downcast_mut::<platform::test::Window>()
|
||||
.unwrap();
|
||||
test_window
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: View> ViewHandle<T> {
|
||||
pub fn next_notification(&self, cx: &TestAppContext) -> impl Future<Output = ()> {
|
||||
use postage::prelude::{Sink as _, Stream as _};
|
||||
|
|
|
@ -13,9 +13,10 @@ use crate::{
|
|||
},
|
||||
text_layout::TextLayoutCache,
|
||||
util::post_inc,
|
||||
Action, AnyView, AnyViewHandle, AppContext, BorrowAppContext, BorrowWindowContext, Effect,
|
||||
Element, Entity, Handle, LayoutContext, MouseRegion, MouseRegionId, PaintContext, SceneBuilder,
|
||||
Subscription, View, ViewContext, ViewHandle, WindowInvalidation,
|
||||
Action, AnyView, AnyViewHandle, AnyWindowHandle, AppContext, BorrowAppContext,
|
||||
BorrowWindowContext, Effect, Element, Entity, Handle, LayoutContext, MouseRegion,
|
||||
MouseRegionId, PaintContext, SceneBuilder, Subscription, View, ViewContext, ViewHandle,
|
||||
WindowInvalidation,
|
||||
};
|
||||
use anyhow::{anyhow, bail, Result};
|
||||
use collections::{HashMap, HashSet};
|
||||
|
@ -60,7 +61,7 @@ pub struct Window {
|
|||
|
||||
impl Window {
|
||||
pub fn new<V, F>(
|
||||
window_id: usize,
|
||||
handle: AnyWindowHandle,
|
||||
platform_window: Box<dyn platform::Window>,
|
||||
cx: &mut AppContext,
|
||||
build_view: F,
|
||||
|
@ -92,7 +93,7 @@ impl Window {
|
|||
appearance,
|
||||
};
|
||||
|
||||
let mut window_context = WindowContext::mutable(cx, &mut window, window_id);
|
||||
let mut window_context = WindowContext::mutable(cx, &mut window, handle);
|
||||
let root_view = window_context.add_view(|cx| build_view(cx));
|
||||
if let Some(invalidation) = window_context.window.invalidation.take() {
|
||||
window_context.invalidate(invalidation, appearance);
|
||||
|
@ -113,7 +114,7 @@ impl Window {
|
|||
pub struct WindowContext<'a> {
|
||||
pub(crate) app_context: Reference<'a, AppContext>,
|
||||
pub(crate) window: Reference<'a, Window>,
|
||||
pub(crate) window_id: usize,
|
||||
pub(crate) window_handle: AnyWindowHandle,
|
||||
pub(crate) removed: bool,
|
||||
}
|
||||
|
||||
|
@ -142,42 +143,66 @@ impl BorrowAppContext for WindowContext<'_> {
|
|||
}
|
||||
|
||||
impl BorrowWindowContext for WindowContext<'_> {
|
||||
fn read_with<T, F: FnOnce(&WindowContext) -> T>(&self, window_id: usize, f: F) -> T {
|
||||
if self.window_id == window_id {
|
||||
type Result<T> = T;
|
||||
|
||||
fn read_window<T, F: FnOnce(&WindowContext) -> T>(&self, handle: AnyWindowHandle, f: F) -> T {
|
||||
if self.window_handle == handle {
|
||||
f(self)
|
||||
} else {
|
||||
panic!("read_with called with id of window that does not belong to this context")
|
||||
}
|
||||
}
|
||||
|
||||
fn update<T, F: FnOnce(&mut WindowContext) -> T>(&mut self, window_id: usize, f: F) -> T {
|
||||
if self.window_id == window_id {
|
||||
fn read_window_optional<T, F>(&self, window: AnyWindowHandle, f: F) -> Option<T>
|
||||
where
|
||||
F: FnOnce(&WindowContext) -> Option<T>,
|
||||
{
|
||||
BorrowWindowContext::read_window(self, window, f)
|
||||
}
|
||||
|
||||
fn update_window<T, F: FnOnce(&mut WindowContext) -> T>(
|
||||
&mut self,
|
||||
handle: AnyWindowHandle,
|
||||
f: F,
|
||||
) -> T {
|
||||
if self.window_handle == handle {
|
||||
f(self)
|
||||
} else {
|
||||
panic!("update called with id of window that does not belong to this context")
|
||||
}
|
||||
}
|
||||
|
||||
fn update_window_optional<T, F>(&mut self, handle: AnyWindowHandle, f: F) -> Option<T>
|
||||
where
|
||||
F: FnOnce(&mut WindowContext) -> Option<T>,
|
||||
{
|
||||
BorrowWindowContext::update_window(self, handle, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> WindowContext<'a> {
|
||||
pub fn mutable(
|
||||
app_context: &'a mut AppContext,
|
||||
window: &'a mut Window,
|
||||
window_id: usize,
|
||||
handle: AnyWindowHandle,
|
||||
) -> Self {
|
||||
Self {
|
||||
app_context: Reference::Mutable(app_context),
|
||||
window: Reference::Mutable(window),
|
||||
window_id,
|
||||
window_handle: handle,
|
||||
removed: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn immutable(app_context: &'a AppContext, window: &'a Window, window_id: usize) -> Self {
|
||||
pub fn immutable(
|
||||
app_context: &'a AppContext,
|
||||
window: &'a Window,
|
||||
handle: AnyWindowHandle,
|
||||
) -> Self {
|
||||
Self {
|
||||
app_context: Reference::Immutable(app_context),
|
||||
window: Reference::Immutable(window),
|
||||
window_id,
|
||||
window_handle: handle,
|
||||
removed: false,
|
||||
}
|
||||
}
|
||||
|
@ -186,8 +211,8 @@ impl<'a> WindowContext<'a> {
|
|||
self.removed = true;
|
||||
}
|
||||
|
||||
pub fn window_id(&self) -> usize {
|
||||
self.window_id
|
||||
pub fn window(&self) -> AnyWindowHandle {
|
||||
self.window_handle
|
||||
}
|
||||
|
||||
pub fn app_context(&mut self) -> &mut AppContext {
|
||||
|
@ -210,10 +235,10 @@ impl<'a> WindowContext<'a> {
|
|||
where
|
||||
F: FnOnce(&mut dyn AnyView, &mut Self) -> T,
|
||||
{
|
||||
let window_id = self.window_id;
|
||||
let mut view = self.views.remove(&(window_id, view_id))?;
|
||||
let handle = self.window_handle;
|
||||
let mut view = self.views.remove(&(handle, view_id))?;
|
||||
let result = f(view.as_mut(), self);
|
||||
self.views.insert((window_id, view_id), view);
|
||||
self.views.insert((handle, view_id), view);
|
||||
Some(result)
|
||||
}
|
||||
|
||||
|
@ -238,9 +263,9 @@ impl<'a> WindowContext<'a> {
|
|||
}
|
||||
|
||||
pub fn defer(&mut self, callback: impl 'static + FnOnce(&mut WindowContext)) {
|
||||
let window_id = self.window_id;
|
||||
let handle = self.window_handle;
|
||||
self.app_context.defer(move |cx| {
|
||||
cx.update_window(window_id, |cx| callback(cx));
|
||||
cx.update_window(handle, |cx| callback(cx));
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -280,10 +305,10 @@ impl<'a> WindowContext<'a> {
|
|||
H: Handle<E>,
|
||||
F: 'static + FnMut(H, &E::Event, &mut WindowContext) -> bool,
|
||||
{
|
||||
let window_id = self.window_id;
|
||||
let window_handle = self.window_handle;
|
||||
self.app_context
|
||||
.subscribe_internal(handle, move |emitter, event, cx| {
|
||||
cx.update_window(window_id, |cx| callback(emitter, event, cx))
|
||||
cx.update_window(window_handle, |cx| callback(emitter, event, cx))
|
||||
.unwrap_or(false)
|
||||
})
|
||||
}
|
||||
|
@ -292,17 +317,17 @@ impl<'a> WindowContext<'a> {
|
|||
where
|
||||
F: 'static + FnMut(bool, &mut WindowContext) -> bool,
|
||||
{
|
||||
let window_id = self.window_id;
|
||||
let handle = self.window_handle;
|
||||
let subscription_id = post_inc(&mut self.next_subscription_id);
|
||||
self.pending_effects
|
||||
.push_back(Effect::WindowActivationObservation {
|
||||
window_id,
|
||||
window: handle,
|
||||
subscription_id,
|
||||
callback: Box::new(callback),
|
||||
});
|
||||
Subscription::WindowActivationObservation(
|
||||
self.window_activation_observations
|
||||
.subscribe(window_id, subscription_id),
|
||||
.subscribe(handle, subscription_id),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -310,17 +335,17 @@ impl<'a> WindowContext<'a> {
|
|||
where
|
||||
F: 'static + FnMut(bool, &mut WindowContext) -> bool,
|
||||
{
|
||||
let window_id = self.window_id;
|
||||
let window = self.window_handle;
|
||||
let subscription_id = post_inc(&mut self.next_subscription_id);
|
||||
self.pending_effects
|
||||
.push_back(Effect::WindowFullscreenObservation {
|
||||
window_id,
|
||||
window,
|
||||
subscription_id,
|
||||
callback: Box::new(callback),
|
||||
});
|
||||
Subscription::WindowActivationObservation(
|
||||
self.window_activation_observations
|
||||
.subscribe(window_id, subscription_id),
|
||||
.subscribe(window, subscription_id),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -328,17 +353,17 @@ impl<'a> WindowContext<'a> {
|
|||
where
|
||||
F: 'static + FnMut(WindowBounds, Uuid, &mut WindowContext) -> bool,
|
||||
{
|
||||
let window_id = self.window_id;
|
||||
let window = self.window_handle;
|
||||
let subscription_id = post_inc(&mut self.next_subscription_id);
|
||||
self.pending_effects
|
||||
.push_back(Effect::WindowBoundsObservation {
|
||||
window_id,
|
||||
window,
|
||||
subscription_id,
|
||||
callback: Box::new(callback),
|
||||
});
|
||||
Subscription::WindowBoundsObservation(
|
||||
self.window_bounds_observations
|
||||
.subscribe(window_id, subscription_id),
|
||||
.subscribe(window, subscription_id),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -347,13 +372,13 @@ impl<'a> WindowContext<'a> {
|
|||
F: 'static
|
||||
+ FnMut(&Keystroke, &MatchResult, Option<&Box<dyn Action>>, &mut WindowContext) -> bool,
|
||||
{
|
||||
let window_id = self.window_id;
|
||||
let window = self.window_handle;
|
||||
let subscription_id = post_inc(&mut self.next_subscription_id);
|
||||
self.keystroke_observations
|
||||
.add_callback(window_id, subscription_id, Box::new(callback));
|
||||
.add_callback(window, subscription_id, Box::new(callback));
|
||||
Subscription::KeystrokeObservation(
|
||||
self.keystroke_observations
|
||||
.subscribe(window_id, subscription_id),
|
||||
.subscribe(window, subscription_id),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -361,11 +386,11 @@ impl<'a> WindowContext<'a> {
|
|||
&self,
|
||||
view_id: usize,
|
||||
) -> Vec<(&'static str, Box<dyn Action>, SmallVec<[Binding; 1]>)> {
|
||||
let window_id = self.window_id;
|
||||
let handle = self.window_handle;
|
||||
let mut contexts = Vec::new();
|
||||
let mut handler_depths_by_action_id = HashMap::<TypeId, usize>::default();
|
||||
for (depth, view_id) in self.ancestors(view_id).enumerate() {
|
||||
if let Some(view_metadata) = self.views_metadata.get(&(window_id, view_id)) {
|
||||
if let Some(view_metadata) = self.views_metadata.get(&(handle, view_id)) {
|
||||
contexts.push(view_metadata.keymap_context.clone());
|
||||
if let Some(actions) = self.actions.get(&view_metadata.type_id) {
|
||||
handler_depths_by_action_id
|
||||
|
@ -410,13 +435,13 @@ impl<'a> WindowContext<'a> {
|
|||
}
|
||||
|
||||
pub(crate) fn dispatch_keystroke(&mut self, keystroke: &Keystroke) -> bool {
|
||||
let window_id = self.window_id;
|
||||
let handle = self.window_handle;
|
||||
if let Some(focused_view_id) = self.focused_view_id() {
|
||||
let dispatch_path = self
|
||||
.ancestors(focused_view_id)
|
||||
.filter_map(|view_id| {
|
||||
self.views_metadata
|
||||
.get(&(window_id, view_id))
|
||||
.get(&(handle, view_id))
|
||||
.map(|view| (view_id, view.keymap_context.clone()))
|
||||
})
|
||||
.collect();
|
||||
|
@ -441,15 +466,10 @@ impl<'a> WindowContext<'a> {
|
|||
}
|
||||
};
|
||||
|
||||
self.keystroke(
|
||||
window_id,
|
||||
keystroke.clone(),
|
||||
handled_by,
|
||||
match_result.clone(),
|
||||
);
|
||||
self.keystroke(handle, keystroke.clone(), handled_by, match_result.clone());
|
||||
keystroke_handled
|
||||
} else {
|
||||
self.keystroke(window_id, keystroke.clone(), None, MatchResult::None);
|
||||
self.keystroke(handle, keystroke.clone(), None, MatchResult::None);
|
||||
false
|
||||
}
|
||||
}
|
||||
|
@ -457,7 +477,7 @@ impl<'a> WindowContext<'a> {
|
|||
pub(crate) fn dispatch_event(&mut self, event: Event, event_reused: bool) -> bool {
|
||||
let mut mouse_events = SmallVec::<[_; 2]>::new();
|
||||
let mut notified_views: HashSet<usize> = Default::default();
|
||||
let window_id = self.window_id;
|
||||
let handle = self.window_handle;
|
||||
|
||||
// 1. Handle platform event. Keyboard events get dispatched immediately, while mouse events
|
||||
// get mapped into the mouse-specific MouseEvent type.
|
||||
|
@ -518,6 +538,18 @@ impl<'a> WindowContext<'a> {
|
|||
// NOTE: The order of event pushes is important! MouseUp events MUST be fired
|
||||
// before click events, and so the MouseUp events need to be pushed before
|
||||
// MouseClick events.
|
||||
|
||||
// Synthesize one last drag event to end the drag
|
||||
mouse_events.push(MouseEvent::Drag(MouseDrag {
|
||||
region: Default::default(),
|
||||
prev_mouse_position: self.window.mouse_position,
|
||||
platform_event: MouseMovedEvent {
|
||||
position: e.position,
|
||||
pressed_button: Some(e.button),
|
||||
modifiers: e.modifiers,
|
||||
},
|
||||
end: true,
|
||||
}));
|
||||
mouse_events.push(MouseEvent::Up(MouseUp {
|
||||
region: Default::default(),
|
||||
platform_event: e.clone(),
|
||||
|
@ -565,8 +597,16 @@ impl<'a> WindowContext<'a> {
|
|||
region: Default::default(),
|
||||
prev_mouse_position: self.window.mouse_position,
|
||||
platform_event: e.clone(),
|
||||
end: false,
|
||||
}));
|
||||
} else if let Some((_, clicked_button)) = self.window.clicked_region {
|
||||
mouse_events.push(MouseEvent::Drag(MouseDrag {
|
||||
region: Default::default(),
|
||||
prev_mouse_position: self.window.mouse_position,
|
||||
platform_event: e.clone(),
|
||||
end: true,
|
||||
}));
|
||||
|
||||
// Mouse up event happened outside the current window. Simulate mouse up button event
|
||||
let button_event = e.to_button_event(clicked_button);
|
||||
mouse_events.push(MouseEvent::Up(MouseUp {
|
||||
|
@ -801,19 +841,19 @@ impl<'a> WindowContext<'a> {
|
|||
}
|
||||
|
||||
for view_id in notified_views {
|
||||
self.notify_view(window_id, view_id);
|
||||
self.notify_view(handle, view_id);
|
||||
}
|
||||
|
||||
any_event_handled
|
||||
}
|
||||
|
||||
pub(crate) fn dispatch_key_down(&mut self, event: &KeyDownEvent) -> bool {
|
||||
let window_id = self.window_id;
|
||||
let handle = self.window_handle;
|
||||
if let Some(focused_view_id) = self.window.focused_view_id {
|
||||
for view_id in self.ancestors(focused_view_id).collect::<Vec<_>>() {
|
||||
if let Some(mut view) = self.views.remove(&(window_id, view_id)) {
|
||||
if let Some(mut view) = self.views.remove(&(handle, view_id)) {
|
||||
let handled = view.key_down(event, self, view_id);
|
||||
self.views.insert((window_id, view_id), view);
|
||||
self.views.insert((handle, view_id), view);
|
||||
if handled {
|
||||
return true;
|
||||
}
|
||||
|
@ -827,12 +867,12 @@ impl<'a> WindowContext<'a> {
|
|||
}
|
||||
|
||||
pub(crate) fn dispatch_key_up(&mut self, event: &KeyUpEvent) -> bool {
|
||||
let window_id = self.window_id;
|
||||
let handle = self.window_handle;
|
||||
if let Some(focused_view_id) = self.window.focused_view_id {
|
||||
for view_id in self.ancestors(focused_view_id).collect::<Vec<_>>() {
|
||||
if let Some(mut view) = self.views.remove(&(window_id, view_id)) {
|
||||
if let Some(mut view) = self.views.remove(&(handle, view_id)) {
|
||||
let handled = view.key_up(event, self, view_id);
|
||||
self.views.insert((window_id, view_id), view);
|
||||
self.views.insert((handle, view_id), view);
|
||||
if handled {
|
||||
return true;
|
||||
}
|
||||
|
@ -846,12 +886,12 @@ impl<'a> WindowContext<'a> {
|
|||
}
|
||||
|
||||
pub(crate) fn dispatch_modifiers_changed(&mut self, event: &ModifiersChangedEvent) -> bool {
|
||||
let window_id = self.window_id;
|
||||
let handle = self.window_handle;
|
||||
if let Some(focused_view_id) = self.window.focused_view_id {
|
||||
for view_id in self.ancestors(focused_view_id).collect::<Vec<_>>() {
|
||||
if let Some(mut view) = self.views.remove(&(window_id, view_id)) {
|
||||
if let Some(mut view) = self.views.remove(&(handle, view_id)) {
|
||||
let handled = view.modifiers_changed(event, self, view_id);
|
||||
self.views.insert((window_id, view_id), view);
|
||||
self.views.insert((handle, view_id), view);
|
||||
if handled {
|
||||
return true;
|
||||
}
|
||||
|
@ -886,14 +926,14 @@ impl<'a> WindowContext<'a> {
|
|||
}
|
||||
|
||||
pub fn render_view(&mut self, params: RenderParams) -> Result<Box<dyn AnyRootElement>> {
|
||||
let window_id = self.window_id;
|
||||
let handle = self.window_handle;
|
||||
let view_id = params.view_id;
|
||||
let mut view = self
|
||||
.views
|
||||
.remove(&(window_id, view_id))
|
||||
.remove(&(handle, view_id))
|
||||
.ok_or_else(|| anyhow!("view not found"))?;
|
||||
let element = view.render(self, view_id);
|
||||
self.views.insert((window_id, view_id), view);
|
||||
self.views.insert((handle, view_id), view);
|
||||
Ok(element)
|
||||
}
|
||||
|
||||
|
@ -921,9 +961,9 @@ impl<'a> WindowContext<'a> {
|
|||
} else if old_parent_id == new_parent_id {
|
||||
current_view_id = *old_parent_id.unwrap();
|
||||
} else {
|
||||
let window_id = self.window_id;
|
||||
let handle = self.window_handle;
|
||||
for view_id_to_notify in view_ids_to_notify {
|
||||
self.notify_view(window_id, view_id_to_notify);
|
||||
self.notify_view(handle, view_id_to_notify);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1091,7 +1131,7 @@ impl<'a> WindowContext<'a> {
|
|||
}
|
||||
|
||||
pub fn focus(&mut self, view_id: Option<usize>) {
|
||||
self.app_context.focus(self.window_id, view_id);
|
||||
self.app_context.focus(self.window_handle, view_id);
|
||||
}
|
||||
|
||||
pub fn window_bounds(&self) -> WindowBounds {
|
||||
|
@ -1131,17 +1171,6 @@ impl<'a> WindowContext<'a> {
|
|||
self.window.platform_window.prompt(level, msg, answers)
|
||||
}
|
||||
|
||||
pub fn replace_root_view<V, F>(&mut self, build_root_view: F) -> ViewHandle<V>
|
||||
where
|
||||
V: View,
|
||||
F: FnOnce(&mut ViewContext<V>) -> V,
|
||||
{
|
||||
let root_view = self.add_view(|cx| build_root_view(cx));
|
||||
self.window.root_view = Some(root_view.clone().into_any());
|
||||
self.window.focused_view_id = Some(root_view.id());
|
||||
root_view
|
||||
}
|
||||
|
||||
pub fn add_view<T, F>(&mut self, build_view: F) -> ViewHandle<T>
|
||||
where
|
||||
T: View,
|
||||
|
@ -1155,26 +1184,26 @@ impl<'a> WindowContext<'a> {
|
|||
T: View,
|
||||
F: FnOnce(&mut ViewContext<T>) -> Option<T>,
|
||||
{
|
||||
let window_id = self.window_id;
|
||||
let view_id = post_inc(&mut self.next_entity_id);
|
||||
let handle = self.window_handle;
|
||||
let view_id = post_inc(&mut self.next_id);
|
||||
let mut cx = ViewContext::mutable(self, view_id);
|
||||
let handle = if let Some(view) = build_view(&mut cx) {
|
||||
let mut keymap_context = KeymapContext::default();
|
||||
view.update_keymap_context(&mut keymap_context, cx.app_context());
|
||||
self.views_metadata.insert(
|
||||
(window_id, view_id),
|
||||
(handle, view_id),
|
||||
ViewMetadata {
|
||||
type_id: TypeId::of::<T>(),
|
||||
keymap_context,
|
||||
},
|
||||
);
|
||||
self.views.insert((window_id, view_id), Box::new(view));
|
||||
self.views.insert((handle, view_id), Box::new(view));
|
||||
self.window
|
||||
.invalidation
|
||||
.get_or_insert_with(Default::default)
|
||||
.updated
|
||||
.insert(view_id);
|
||||
Some(ViewHandle::new(window_id, view_id, &self.ref_counts))
|
||||
Some(ViewHandle::new(handle, view_id, &self.ref_counts))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
@ -1351,7 +1380,7 @@ pub struct ChildView {
|
|||
|
||||
impl ChildView {
|
||||
pub fn new(view: &AnyViewHandle, cx: &AppContext) -> Self {
|
||||
let view_name = cx.view_ui_name(view.window_id(), view.id()).unwrap();
|
||||
let view_name = cx.view_ui_name(view.window, view.id()).unwrap();
|
||||
Self {
|
||||
view_id: view.id(),
|
||||
view_name,
|
||||
|
|
|
@ -2,11 +2,11 @@ use std::{cell::RefCell, ops::Range, rc::Rc};
|
|||
|
||||
use pathfinder_geometry::rect::RectF;
|
||||
|
||||
use crate::{platform::InputHandler, window::WindowContext, AnyView, AppContext};
|
||||
use crate::{platform::InputHandler, window::WindowContext, AnyView, AnyWindowHandle, AppContext};
|
||||
|
||||
pub struct WindowInputHandler {
|
||||
pub app: Rc<RefCell<AppContext>>,
|
||||
pub window_id: usize,
|
||||
pub window: AnyWindowHandle,
|
||||
}
|
||||
|
||||
impl WindowInputHandler {
|
||||
|
@ -21,13 +21,12 @@ impl WindowInputHandler {
|
|||
//
|
||||
// See https://github.com/zed-industries/community/issues/444
|
||||
let mut app = self.app.try_borrow_mut().ok()?;
|
||||
app.update_window(self.window_id, |cx| {
|
||||
self.window.update_optional(&mut *app, |cx| {
|
||||
let view_id = cx.window.focused_view_id?;
|
||||
let view = cx.views.get(&(self.window_id, view_id))?;
|
||||
let view = cx.views.get(&(self.window, view_id))?;
|
||||
let result = f(view.as_ref(), &cx);
|
||||
Some(result)
|
||||
})
|
||||
.flatten()
|
||||
}
|
||||
|
||||
fn update_focused_view<T, F>(&mut self, f: F) -> Option<T>
|
||||
|
@ -35,11 +34,12 @@ impl WindowInputHandler {
|
|||
F: FnOnce(&mut dyn AnyView, &mut WindowContext, usize) -> T,
|
||||
{
|
||||
let mut app = self.app.try_borrow_mut().ok()?;
|
||||
app.update_window(self.window_id, |cx| {
|
||||
let view_id = cx.window.focused_view_id?;
|
||||
cx.update_any_view(view_id, |view, cx| f(view, cx, view_id))
|
||||
})
|
||||
.flatten()
|
||||
self.window
|
||||
.update(&mut *app, |cx| {
|
||||
let view_id = cx.window.focused_view_id?;
|
||||
cx.update_any_view(view_id, |view, cx| f(view, cx, view_id))
|
||||
})
|
||||
.flatten()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -83,9 +83,8 @@ impl InputHandler for WindowInputHandler {
|
|||
}
|
||||
|
||||
fn rect_for_range(&self, range_utf16: Range<usize>) -> Option<RectF> {
|
||||
self.app
|
||||
.borrow()
|
||||
.read_window(self.window_id, |cx| cx.rect_for_text_range(range_utf16))
|
||||
.flatten()
|
||||
self.window.read_optional_with(&*self.app.borrow(), |cx| {
|
||||
cx.rect_for_text_range(range_utf16)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -147,6 +147,9 @@ impl<V: View> Element<V> for Resizable<V> {
|
|||
let max_size = side.relevant_component(constraint.max);
|
||||
let on_resize = self.on_resize.clone();
|
||||
move |event, view: &mut V, cx| {
|
||||
if event.end {
|
||||
return;
|
||||
}
|
||||
let new_size = min_size
|
||||
.max(prev_size + side.compute_delta(event))
|
||||
.min(max_size)
|
||||
|
|
|
@ -19,7 +19,7 @@ use crate::{
|
|||
},
|
||||
keymap_matcher::KeymapMatcher,
|
||||
text_layout::{LineLayout, RunStyle},
|
||||
Action, ClipboardItem, Menu, Scene,
|
||||
Action, AnyWindowHandle, ClipboardItem, Menu, Scene,
|
||||
};
|
||||
use anyhow::{anyhow, bail, Result};
|
||||
use async_task::Runnable;
|
||||
|
@ -58,13 +58,13 @@ pub trait Platform: Send + Sync {
|
|||
|
||||
fn open_window(
|
||||
&self,
|
||||
id: usize,
|
||||
handle: AnyWindowHandle,
|
||||
options: WindowOptions,
|
||||
executor: Rc<executor::Foreground>,
|
||||
) -> Box<dyn Window>;
|
||||
fn main_window_id(&self) -> Option<usize>;
|
||||
fn main_window(&self) -> Option<AnyWindowHandle>;
|
||||
|
||||
fn add_status_item(&self, id: usize) -> Box<dyn Window>;
|
||||
fn add_status_item(&self, handle: AnyWindowHandle) -> Box<dyn Window>;
|
||||
|
||||
fn write_to_clipboard(&self, item: ClipboardItem);
|
||||
fn read_from_clipboard(&self) -> Option<ClipboardItem>;
|
||||
|
|
|
@ -21,7 +21,7 @@ pub use fonts::FontSystem;
|
|||
use platform::{MacForegroundPlatform, MacPlatform};
|
||||
pub use renderer::Surface;
|
||||
use std::{ops::Range, rc::Rc, sync::Arc};
|
||||
use window::Window;
|
||||
use window::MacWindow;
|
||||
|
||||
use crate::executor;
|
||||
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
use super::{
|
||||
event::key_to_native, screen::Screen, status_item::StatusItem, BoolExt as _, Dispatcher,
|
||||
FontSystem, Window,
|
||||
FontSystem, MacWindow,
|
||||
};
|
||||
use crate::{
|
||||
executor,
|
||||
keymap_matcher::KeymapMatcher,
|
||||
platform::{self, AppVersion, CursorStyle, Event},
|
||||
Action, ClipboardItem, Menu, MenuItem,
|
||||
Action, AnyWindowHandle, ClipboardItem, Menu, MenuItem,
|
||||
};
|
||||
use anyhow::{anyhow, Result};
|
||||
use block::ConcreteBlock;
|
||||
|
@ -590,18 +590,18 @@ impl platform::Platform for MacPlatform {
|
|||
|
||||
fn open_window(
|
||||
&self,
|
||||
id: usize,
|
||||
handle: AnyWindowHandle,
|
||||
options: platform::WindowOptions,
|
||||
executor: Rc<executor::Foreground>,
|
||||
) -> Box<dyn platform::Window> {
|
||||
Box::new(Window::open(id, options, executor, self.fonts()))
|
||||
Box::new(MacWindow::open(handle, options, executor, self.fonts()))
|
||||
}
|
||||
|
||||
fn main_window_id(&self) -> Option<usize> {
|
||||
Window::main_window_id()
|
||||
fn main_window(&self) -> Option<AnyWindowHandle> {
|
||||
MacWindow::main_window()
|
||||
}
|
||||
|
||||
fn add_status_item(&self, _id: usize) -> Box<dyn platform::Window> {
|
||||
fn add_status_item(&self, _handle: AnyWindowHandle) -> Box<dyn platform::Window> {
|
||||
Box::new(StatusItem::add(self.fonts()))
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ use crate::{
|
|||
Event, InputHandler, KeyDownEvent, Modifiers, ModifiersChangedEvent, MouseButton,
|
||||
MouseButtonEvent, MouseMovedEvent, Scene, WindowBounds, WindowKind,
|
||||
},
|
||||
AnyWindowHandle,
|
||||
};
|
||||
use block::ConcreteBlock;
|
||||
use cocoa::{
|
||||
|
@ -282,7 +283,7 @@ struct InsertText {
|
|||
}
|
||||
|
||||
struct WindowState {
|
||||
id: usize,
|
||||
handle: AnyWindowHandle,
|
||||
native_window: id,
|
||||
kind: WindowKind,
|
||||
event_callback: Option<Box<dyn FnMut(Event) -> bool>>,
|
||||
|
@ -422,11 +423,11 @@ impl WindowState {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct Window(Rc<RefCell<WindowState>>);
|
||||
pub struct MacWindow(Rc<RefCell<WindowState>>);
|
||||
|
||||
impl Window {
|
||||
impl MacWindow {
|
||||
pub fn open(
|
||||
id: usize,
|
||||
handle: AnyWindowHandle,
|
||||
options: platform::WindowOptions,
|
||||
executor: Rc<executor::Foreground>,
|
||||
fonts: Arc<dyn platform::FontSystem>,
|
||||
|
@ -504,7 +505,7 @@ impl Window {
|
|||
assert!(!native_view.is_null());
|
||||
|
||||
let window = Self(Rc::new(RefCell::new(WindowState {
|
||||
id,
|
||||
handle,
|
||||
native_window,
|
||||
kind: options.kind,
|
||||
event_callback: None,
|
||||
|
@ -621,13 +622,13 @@ impl Window {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn main_window_id() -> Option<usize> {
|
||||
pub fn main_window() -> Option<AnyWindowHandle> {
|
||||
unsafe {
|
||||
let app = NSApplication::sharedApplication(nil);
|
||||
let main_window: id = msg_send![app, mainWindow];
|
||||
if msg_send![main_window, isKindOfClass: WINDOW_CLASS] {
|
||||
let id = get_window_state(&*main_window).borrow().id;
|
||||
Some(id)
|
||||
let handle = get_window_state(&*main_window).borrow().handle;
|
||||
Some(handle)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -635,7 +636,7 @@ impl Window {
|
|||
}
|
||||
}
|
||||
|
||||
impl Drop for Window {
|
||||
impl Drop for MacWindow {
|
||||
fn drop(&mut self) {
|
||||
let this = self.0.borrow();
|
||||
let window = this.native_window;
|
||||
|
@ -649,7 +650,7 @@ impl Drop for Window {
|
|||
}
|
||||
}
|
||||
|
||||
impl platform::Window for Window {
|
||||
impl platform::Window for MacWindow {
|
||||
fn bounds(&self) -> WindowBounds {
|
||||
self.0.as_ref().borrow().bounds()
|
||||
}
|
||||
|
@ -881,7 +882,7 @@ impl platform::Window for Window {
|
|||
|
||||
fn is_topmost_for_position(&self, position: Vector2F) -> bool {
|
||||
let self_borrow = self.0.borrow();
|
||||
let self_id = self_borrow.id;
|
||||
let self_handle = self_borrow.handle;
|
||||
|
||||
unsafe {
|
||||
let app = NSApplication::sharedApplication(nil);
|
||||
|
@ -898,8 +899,8 @@ impl platform::Window for Window {
|
|||
let is_panel: BOOL = msg_send![top_most_window, isKindOfClass: PANEL_CLASS];
|
||||
let is_window: BOOL = msg_send![top_most_window, isKindOfClass: WINDOW_CLASS];
|
||||
if is_panel == YES || is_window == YES {
|
||||
let topmost_window_id = get_window_state(&*top_most_window).borrow().id;
|
||||
topmost_window_id == self_id
|
||||
let topmost_window = get_window_state(&*top_most_window).borrow().handle;
|
||||
topmost_window == self_handle
|
||||
} else {
|
||||
// Someone else's window is on top
|
||||
false
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::{
|
|||
vector::{vec2f, Vector2F},
|
||||
},
|
||||
keymap_matcher::KeymapMatcher,
|
||||
Action, ClipboardItem, Menu,
|
||||
Action, AnyWindowHandle, ClipboardItem, Menu,
|
||||
};
|
||||
use anyhow::{anyhow, Result};
|
||||
use collections::VecDeque;
|
||||
|
@ -102,7 +102,7 @@ pub struct Platform {
|
|||
fonts: Arc<dyn super::FontSystem>,
|
||||
current_clipboard_item: Mutex<Option<ClipboardItem>>,
|
||||
cursor: Mutex<CursorStyle>,
|
||||
active_window_id: Arc<Mutex<Option<usize>>>,
|
||||
active_window: Arc<Mutex<Option<AnyWindowHandle>>>,
|
||||
}
|
||||
|
||||
impl Platform {
|
||||
|
@ -112,7 +112,7 @@ impl Platform {
|
|||
fonts: Arc::new(super::current::FontSystem::new()),
|
||||
current_clipboard_item: Default::default(),
|
||||
cursor: Mutex::new(CursorStyle::Arrow),
|
||||
active_window_id: Default::default(),
|
||||
active_window: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -146,30 +146,30 @@ impl super::Platform for Platform {
|
|||
|
||||
fn open_window(
|
||||
&self,
|
||||
id: usize,
|
||||
handle: AnyWindowHandle,
|
||||
options: super::WindowOptions,
|
||||
_executor: Rc<super::executor::Foreground>,
|
||||
) -> Box<dyn super::Window> {
|
||||
*self.active_window_id.lock() = Some(id);
|
||||
*self.active_window.lock() = Some(handle);
|
||||
Box::new(Window::new(
|
||||
id,
|
||||
handle,
|
||||
match options.bounds {
|
||||
WindowBounds::Maximized | WindowBounds::Fullscreen => vec2f(1024., 768.),
|
||||
WindowBounds::Fixed(rect) => rect.size(),
|
||||
},
|
||||
self.active_window_id.clone(),
|
||||
self.active_window.clone(),
|
||||
))
|
||||
}
|
||||
|
||||
fn main_window_id(&self) -> Option<usize> {
|
||||
self.active_window_id.lock().clone()
|
||||
fn main_window(&self) -> Option<AnyWindowHandle> {
|
||||
self.active_window.lock().clone()
|
||||
}
|
||||
|
||||
fn add_status_item(&self, id: usize) -> Box<dyn crate::platform::Window> {
|
||||
fn add_status_item(&self, handle: AnyWindowHandle) -> Box<dyn crate::platform::Window> {
|
||||
Box::new(Window::new(
|
||||
id,
|
||||
handle,
|
||||
vec2f(24., 24.),
|
||||
self.active_window_id.clone(),
|
||||
self.active_window.clone(),
|
||||
))
|
||||
}
|
||||
|
||||
|
@ -256,7 +256,7 @@ impl super::Screen for Screen {
|
|||
}
|
||||
|
||||
pub struct Window {
|
||||
id: usize,
|
||||
handle: AnyWindowHandle,
|
||||
pub(crate) size: Vector2F,
|
||||
scale_factor: f32,
|
||||
current_scene: Option<crate::Scene>,
|
||||
|
@ -270,13 +270,17 @@ pub struct Window {
|
|||
pub(crate) title: Option<String>,
|
||||
pub(crate) edited: bool,
|
||||
pub(crate) pending_prompts: RefCell<VecDeque<oneshot::Sender<usize>>>,
|
||||
active_window_id: Arc<Mutex<Option<usize>>>,
|
||||
active_window: Arc<Mutex<Option<AnyWindowHandle>>>,
|
||||
}
|
||||
|
||||
impl Window {
|
||||
pub fn new(id: usize, size: Vector2F, active_window_id: Arc<Mutex<Option<usize>>>) -> Self {
|
||||
pub fn new(
|
||||
handle: AnyWindowHandle,
|
||||
size: Vector2F,
|
||||
active_window: Arc<Mutex<Option<AnyWindowHandle>>>,
|
||||
) -> Self {
|
||||
Self {
|
||||
id,
|
||||
handle,
|
||||
size,
|
||||
event_handlers: Default::default(),
|
||||
resize_handlers: Default::default(),
|
||||
|
@ -290,7 +294,7 @@ impl Window {
|
|||
title: None,
|
||||
edited: false,
|
||||
pending_prompts: Default::default(),
|
||||
active_window_id,
|
||||
active_window,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -342,7 +346,7 @@ impl super::Window for Window {
|
|||
}
|
||||
|
||||
fn activate(&self) {
|
||||
*self.active_window_id.lock() = Some(self.id);
|
||||
*self.active_window.lock() = Some(self.handle);
|
||||
}
|
||||
|
||||
fn set_title(&mut self, title: &str) {
|
||||
|
|
|
@ -32,6 +32,7 @@ pub struct MouseDrag {
|
|||
pub region: RectF,
|
||||
pub prev_mouse_position: Vector2F,
|
||||
pub platform_event: MouseMovedEvent,
|
||||
pub end: bool,
|
||||
}
|
||||
|
||||
impl Deref for MouseDrag {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue