@@ -4,7 +4,7 @@ use collections::{HashMap, HashSet};
use std::any::Any;
pub trait Action: Any + Send + Sync {
- fn partial_eq(&self, action: &dyn Action) -> bool;
+ fn eq(&self, action: &dyn Action) -> bool;
fn boxed_clone(&self) -> Box<dyn Action>;
fn as_any(&self) -> &dyn Any;
}
@@ -112,7 +112,7 @@ pub struct AppContext {
pub(crate) unit_entity: Handle<()>,
pub(crate) entities: EntityMap,
pub(crate) windows: SlotMap<WindowId, Option<Window>>,
- keymap: Arc<RwLock<Keymap>>,
+ pub(crate) keymap: Arc<RwLock<Keymap>>,
pub(crate) pending_notifications: HashSet<EntityId>,
pending_effects: VecDeque<Effect>,
pub(crate) observers: SubscriberSet<EntityId, Handler>,
@@ -33,7 +33,7 @@ pub trait Element: 'static + Send + Sync + IntoAnyElement<Self::ViewState> {
}
#[derive(Deref, DerefMut, Default, Clone, Debug, Eq, PartialEq, Hash)]
-pub struct GlobalElementId(SmallVec<[ElementId; 8]>);
+pub struct GlobalElementId(SmallVec<[ElementId; 32]>);
pub trait ElementIdentity: 'static + Send + Sync {
fn id(&self) -> Option<ElementId>;
@@ -1035,8 +1035,21 @@ pub trait BorrowWindow: BorrowAppContext {
id: impl Into<ElementId>,
f: impl FnOnce(GlobalElementId, &mut Self) -> R,
) -> R {
- self.window_mut().element_id_stack.push(id.into());
- let global_id = self.window_mut().element_id_stack.clone();
+ let keymap = self.app_mut().keymap.clone();
+ let window = self.window_mut();
+ window.element_id_stack.push(id.into());
+ let global_id = window.element_id_stack.clone();
+
+ if window.key_matchers.get(&global_id).is_none() {
+ window.key_matchers.insert(
+ global_id.clone(),
+ window
+ .prev_frame_key_matchers
+ .remove(&global_id)
+ .unwrap_or_else(|| KeyMatcher::new(keymap)),
+ );
+ }
+
let result = f(global_id, self);
self.window_mut().element_id_stack.pop();
result
@@ -1,13 +1,56 @@
-use gpui3::{div, view, Context, Focus, ParentElement, Styled, View, WindowContext};
+use std::any::Any;
+
+use gpui3::{
+ div, view, Action, Context, Focus, Interactive, KeyBinding, ParentElement, Styled, View,
+ WindowContext,
+};
use crate::themes::rose_pine;
+#[derive(Clone)]
+struct ActionA;
+
+impl Action for ActionA {
+ fn eq(&self, action: &dyn Action) -> bool {
+ action.as_any().downcast_ref::<Self>().is_some()
+ }
+
+ fn boxed_clone(&self) -> Box<dyn Action> {
+ Box::new(self.clone())
+ }
+
+ fn as_any(&self) -> &dyn Any {
+ self
+ }
+}
+
+#[derive(Clone)]
+struct ActionB;
+
+impl Action for ActionB {
+ fn eq(&self, action: &dyn Action) -> bool {
+ action.as_any().downcast_ref::<Self>().is_some()
+ }
+
+ fn boxed_clone(&self) -> Box<dyn Action> {
+ Box::new(self.clone())
+ }
+
+ fn as_any(&self) -> &dyn Any {
+ self
+ }
+}
+
pub struct FocusStory {
text: View<()>,
}
impl FocusStory {
pub fn view(cx: &mut WindowContext) -> View<()> {
+ cx.bind_keys([
+ KeyBinding::new("cmd-a", ActionA, None),
+ KeyBinding::new("cmd-b", ActionB, None),
+ ]);
let theme = rose_pine();
let color_1 = theme.lowest.negative.default.foreground;
@@ -22,6 +65,12 @@ impl FocusStory {
let child_2 = cx.focus_handle();
view(cx.entity(|cx| ()), move |_, cx| {
div()
+ .on_action(|_, action: &ActionA, phase, cx| {
+ println!("Action A dispatched on parent during {:?}", phase);
+ })
+ .on_action(|_, action: &ActionB, phase, cx| {
+ println!("Action A dispatched on parent during {:?}", phase);
+ })
.focusable(&parent)
.on_focus(|_, _, _| println!("Parent focused"))
.on_blur(|_, _, _| println!("Parent blurred"))
@@ -39,6 +88,10 @@ impl FocusStory {
.focus_in(|style| style.bg(color_3))
.child(
div()
+ .id("child 1")
+ .on_action(|_, action: &ActionA, phase, cx| {
+ println!("Action A dispatched on child 1 during {:?}", phase);
+ })
.focusable(&child_1)
.w_full()
.h_6()
@@ -59,6 +112,10 @@ impl FocusStory {
)
.child(
div()
+ .id("child 2")
+ .on_action(|_, action: &ActionB, phase, cx| {
+ println!("Action B dispatched on child 2 during {:?}", phase);
+ })
.focusable(&child_2)
.w_full()
.h_6()