Detailed changes
@@ -39,7 +39,10 @@ use std::{
sync::{atomic::Ordering::SeqCst, Arc},
time::Duration,
};
-use util::http::{self, HttpClient};
+use util::{
+ http::{self, HttpClient},
+ ResultExt,
+};
/// Temporary(?) wrapper around RefCell<AppContext> to help us debug any double borrows.
/// Strongly consider removing after stabilization.
@@ -1055,6 +1058,62 @@ impl AppContext {
self.global_action_listeners
.contains_key(&action.as_any().type_id())
}
+
+ pub fn dispatch_action(&mut self, action: &dyn Action) {
+ self.propagate_event = true;
+
+ if let Some(mut global_listeners) = self
+ .global_action_listeners
+ .remove(&action.as_any().type_id())
+ {
+ for listener in &global_listeners {
+ listener(action, DispatchPhase::Capture, self);
+ if !self.propagate_event {
+ break;
+ }
+ }
+
+ global_listeners.extend(
+ self.global_action_listeners
+ .remove(&action.as_any().type_id())
+ .unwrap_or_default(),
+ );
+
+ self.global_action_listeners
+ .insert(action.as_any().type_id(), global_listeners);
+ }
+
+ if self.propagate_event {
+ if let Some(active_window) = self.active_window() {
+ active_window
+ .update(self, |_, cx| cx.dispatch_action(action.boxed_clone()))
+ .log_err();
+ }
+ }
+
+ if self.propagate_event {
+ if let Some(mut global_listeners) = self
+ .global_action_listeners
+ .remove(&action.as_any().type_id())
+ {
+ for listener in global_listeners.iter().rev() {
+ listener(action, DispatchPhase::Bubble, self);
+ if !self.propagate_event {
+ break;
+ }
+ }
+
+ global_listeners.extend(
+ self.global_action_listeners
+ .remove(&action.as_any().type_id())
+ .unwrap_or_default(),
+ );
+
+ self.global_action_listeners
+ .insert(action.as_any().type_id(), global_listeners);
+ }
+ }
+ }
}
impl Context for AppContext {
@@ -92,9 +92,9 @@ pub trait Platform: 'static {
fn on_reopen(&self, callback: Box<dyn FnMut()>);
fn on_event(&self, callback: Box<dyn FnMut(InputEvent) -> bool>);
- fn on_menu_command(&self, callback: Box<dyn FnMut(&dyn Action)>);
- fn on_will_open_menu(&self, callback: Box<dyn FnMut()>);
- fn on_validate_menu_command(&self, callback: Box<dyn FnMut(&dyn Action) -> bool>);
+ fn on_app_menu_action(&self, callback: Box<dyn FnMut(&dyn Action)>);
+ fn on_will_open_app_menu(&self, callback: Box<dyn FnMut()>);
+ fn on_validate_app_menu_command(&self, callback: Box<dyn FnMut(&dyn Action) -> bool>);
fn os_name(&self) -> &'static str;
fn os_version(&self) -> Result<SemanticVersion>;
@@ -53,14 +53,14 @@ pub enum OsAction {
}
pub(crate) fn init(platform: &dyn Platform, cx: &mut AppContext) {
- platform.on_will_open_menu(Box::new({
+ platform.on_will_open_app_menu(Box::new({
let cx = cx.to_async();
move || {
cx.update(|cx| cx.clear_pending_keystrokes()).ok();
}
}));
- platform.on_validate_menu_command(Box::new({
+ platform.on_validate_app_menu_command(Box::new({
let cx = cx.to_async();
move |action| {
cx.update(|cx| cx.is_action_available(action))
@@ -68,29 +68,10 @@ pub(crate) fn init(platform: &dyn Platform, cx: &mut AppContext) {
}
}));
- platform.on_menu_command(Box::new({
+ platform.on_app_menu_action(Box::new({
let cx = cx.to_async();
move |action| {
- cx.update(|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
- // } else {
- // false
- // }
- // })
- // .unwrap_or(false);
-
- // if dispatched {
- // return;
- // }
- // }
- // cx.dispatch_global_action_any(action);
- })
- .log_err();
+ cx.update(|cx| cx.dispatch_action(action)).log_err();
}
}));
}
@@ -683,15 +683,15 @@ impl Platform for MacPlatform {
}
}
- fn on_menu_command(&self, callback: Box<dyn FnMut(&dyn Action)>) {
+ fn on_app_menu_action(&self, callback: Box<dyn FnMut(&dyn Action)>) {
self.0.lock().menu_command = Some(callback);
}
- fn on_will_open_menu(&self, callback: Box<dyn FnMut()>) {
+ fn on_will_open_app_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>) {
+ fn on_validate_app_menu_command(&self, callback: Box<dyn FnMut(&dyn Action) -> bool>) {
self.0.lock().validate_menu_command = Some(callback);
}
@@ -205,15 +205,15 @@ impl Platform for TestPlatform {
unimplemented!()
}
- fn on_menu_command(&self, _callback: Box<dyn FnMut(&dyn crate::Action)>) {
+ fn on_app_menu_action(&self, _callback: Box<dyn FnMut(&dyn crate::Action)>) {
unimplemented!()
}
- fn on_will_open_menu(&self, _callback: Box<dyn FnMut()>) {
+ fn on_will_open_app_menu(&self, _callback: Box<dyn FnMut()>) {
unimplemented!()
}
- fn on_validate_menu_command(&self, _callback: Box<dyn FnMut(&dyn crate::Action) -> bool>) {
+ fn on_validate_app_menu_command(&self, _callback: Box<dyn FnMut(&dyn crate::Action) -> bool>) {
unimplemented!()
}