Start on view-level dispatch approach for keyboard events
This commit is contained in:
parent
6e53deb1b2
commit
6e363e464c
22 changed files with 191 additions and 53 deletions
|
@ -41,8 +41,8 @@ use crate::{
|
|||
platform::{self, KeyDownEvent, Platform, PromptLevel, WindowOptions},
|
||||
presenter::Presenter,
|
||||
util::post_inc,
|
||||
Appearance, AssetCache, AssetSource, ClipboardItem, FontCache, InputHandler, MouseButton,
|
||||
MouseRegionId, PathPromptOptions, TextLayoutCache,
|
||||
Appearance, AssetCache, AssetSource, ClipboardItem, FontCache, InputHandler, KeyUpEvent,
|
||||
ModifiersChangedEvent, MouseButton, MouseRegionId, PathPromptOptions, TextLayoutCache,
|
||||
};
|
||||
|
||||
pub trait Entity: 'static {
|
||||
|
@ -60,8 +60,18 @@ pub trait Entity: 'static {
|
|||
pub trait View: Entity + Sized {
|
||||
fn ui_name() -> &'static str;
|
||||
fn render(&mut self, cx: &mut RenderContext<'_, Self>) -> ElementBox;
|
||||
fn on_focus_in(&mut self, _: AnyViewHandle, _: &mut ViewContext<Self>) {}
|
||||
fn on_focus_out(&mut self, _: AnyViewHandle, _: &mut ViewContext<Self>) {}
|
||||
fn focus_in(&mut self, _: AnyViewHandle, _: &mut ViewContext<Self>) {}
|
||||
fn focus_out(&mut self, _: AnyViewHandle, _: &mut ViewContext<Self>) {}
|
||||
fn key_down(&mut self, _: &KeyDownEvent, _: &mut ViewContext<Self>) -> bool {
|
||||
false
|
||||
}
|
||||
fn key_up(&mut self, _: &KeyUpEvent, _: &mut ViewContext<Self>) -> bool {
|
||||
false
|
||||
}
|
||||
fn modifiers_changed(&mut self, _: &ModifiersChangedEvent, _: &mut ViewContext<Self>) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn keymap_context(&self, _: &AppContext) -> keymap::Context {
|
||||
Self::default_keymap_context()
|
||||
}
|
||||
|
@ -1297,7 +1307,7 @@ impl MutableAppContext {
|
|||
) -> impl Iterator<Item = (&'static str, Box<dyn Action>, SmallVec<[&Binding; 1]>)> {
|
||||
let mut action_types: HashSet<_> = self.global_actions.keys().copied().collect();
|
||||
|
||||
for view_id in self.parents(window_id, view_id) {
|
||||
for view_id in self.ancestors(window_id, view_id) {
|
||||
if let Some(view) = self.views.get(&(window_id, view_id)) {
|
||||
let view_type = view.as_any().type_id();
|
||||
if let Some(actions) = self.actions.get(&view_type) {
|
||||
|
@ -1327,7 +1337,7 @@ impl MutableAppContext {
|
|||
let action_type = action.as_any().type_id();
|
||||
if let Some(window_id) = self.cx.platform.key_window_id() {
|
||||
if let Some(focused_view_id) = self.focused_view_id(window_id) {
|
||||
for view_id in self.parents(window_id, focused_view_id) {
|
||||
for view_id in self.ancestors(window_id, focused_view_id) {
|
||||
if let Some(view) = self.views.get(&(window_id, view_id)) {
|
||||
let view_type = view.as_any().type_id();
|
||||
if let Some(actions) = self.actions.get(&view_type) {
|
||||
|
@ -1376,7 +1386,7 @@ impl MutableAppContext {
|
|||
mut visit: impl FnMut(usize, bool, &mut MutableAppContext) -> bool,
|
||||
) -> bool {
|
||||
// List of view ids from the leaf to the root of the window
|
||||
let path = self.parents(window_id, view_id).collect::<Vec<_>>();
|
||||
let path = self.ancestors(window_id, view_id).collect::<Vec<_>>();
|
||||
|
||||
// Walk down from the root to the leaf calling visit with capture_phase = true
|
||||
for view_id in path.iter().rev() {
|
||||
|
@ -1397,7 +1407,7 @@ impl MutableAppContext {
|
|||
|
||||
// Returns an iterator over all of the view ids from the passed view up to the root of the window
|
||||
// Includes the passed view itself
|
||||
fn parents(&self, window_id: usize, mut view_id: usize) -> impl Iterator<Item = usize> + '_ {
|
||||
fn ancestors(&self, window_id: usize, mut view_id: usize) -> impl Iterator<Item = usize> + '_ {
|
||||
std::iter::once(view_id)
|
||||
.into_iter()
|
||||
.chain(std::iter::from_fn(move || {
|
||||
|
@ -1445,11 +1455,81 @@ impl MutableAppContext {
|
|||
self.keystroke_matcher.clear_bindings();
|
||||
}
|
||||
|
||||
pub fn dispatch_key_down(&mut self, window_id: usize, event: &KeyDownEvent) -> bool {
|
||||
if let Some(focused_view_id) = self.focused_view_id(window_id) {
|
||||
for view_id in self
|
||||
.ancestors(window_id, focused_view_id)
|
||||
.collect::<Vec<_>>()
|
||||
{
|
||||
if let Some(mut view) = self.cx.views.remove(&(window_id, view_id)) {
|
||||
let handled = view.key_down(event, self, window_id, view_id);
|
||||
self.cx.views.insert((window_id, view_id), view);
|
||||
if handled {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
log::error!("view {} does not exist", view_id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
pub fn dispatch_key_up(&mut self, window_id: usize, event: &KeyUpEvent) -> bool {
|
||||
if let Some(focused_view_id) = self.focused_view_id(window_id) {
|
||||
for view_id in self
|
||||
.ancestors(window_id, focused_view_id)
|
||||
.collect::<Vec<_>>()
|
||||
{
|
||||
if let Some(mut view) = self.cx.views.remove(&(window_id, view_id)) {
|
||||
let handled = view.key_up(event, self, window_id, view_id);
|
||||
self.cx.views.insert((window_id, view_id), view);
|
||||
if handled {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
log::error!("view {} does not exist", view_id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
pub fn dispatch_modifiers_changed(
|
||||
&mut self,
|
||||
window_id: usize,
|
||||
event: &ModifiersChangedEvent,
|
||||
) -> bool {
|
||||
if let Some(focused_view_id) = self.focused_view_id(window_id) {
|
||||
for view_id in self
|
||||
.ancestors(window_id, focused_view_id)
|
||||
.collect::<Vec<_>>()
|
||||
{
|
||||
if let Some(mut view) = self.cx.views.remove(&(window_id, view_id)) {
|
||||
let handled = view.modifiers_changed(event, self, window_id, view_id);
|
||||
self.cx.views.insert((window_id, view_id), view);
|
||||
if handled {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
log::error!("view {} does not exist", view_id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
pub fn dispatch_keystroke(&mut self, window_id: usize, keystroke: &Keystroke) -> bool {
|
||||
let mut pending = false;
|
||||
|
||||
if let Some(focused_view_id) = self.focused_view_id(window_id) {
|
||||
for view_id in self.parents(window_id, focused_view_id).collect::<Vec<_>>() {
|
||||
for view_id in self
|
||||
.ancestors(window_id, focused_view_id)
|
||||
.collect::<Vec<_>>()
|
||||
{
|
||||
let keymap_context = self
|
||||
.cx
|
||||
.views
|
||||
|
@ -1580,7 +1660,7 @@ impl MutableAppContext {
|
|||
is_fullscreen: false,
|
||||
},
|
||||
);
|
||||
root_view.update(this, |view, cx| view.on_focus_in(cx.handle().into(), cx));
|
||||
root_view.update(this, |view, cx| view.focus_in(cx.handle().into(), cx));
|
||||
|
||||
let window =
|
||||
this.cx
|
||||
|
@ -1612,7 +1692,7 @@ impl MutableAppContext {
|
|||
is_fullscreen: false,
|
||||
},
|
||||
);
|
||||
root_view.update(this, |view, cx| view.on_focus_in(cx.handle().into(), cx));
|
||||
root_view.update(this, |view, cx| view.focus_in(cx.handle().into(), cx));
|
||||
|
||||
let status_item = this.cx.platform.add_status_item();
|
||||
this.register_platform_window(window_id, status_item);
|
||||
|
@ -2235,12 +2315,12 @@ impl MutableAppContext {
|
|||
|
||||
//Handle focus
|
||||
let focused_id = window.focused_view_id?;
|
||||
for view_id in this.parents(window_id, focused_id).collect::<Vec<_>>() {
|
||||
for view_id in this.ancestors(window_id, focused_id).collect::<Vec<_>>() {
|
||||
if let Some(mut view) = this.cx.views.remove(&(window_id, view_id)) {
|
||||
if active {
|
||||
view.on_focus_in(this, window_id, view_id, focused_id);
|
||||
view.focus_in(this, window_id, view_id, focused_id);
|
||||
} else {
|
||||
view.on_focus_out(this, window_id, view_id, focused_id);
|
||||
view.focus_out(this, window_id, view_id, focused_id);
|
||||
}
|
||||
this.cx.views.insert((window_id, view_id), view);
|
||||
}
|
||||
|
@ -2272,16 +2352,16 @@ impl MutableAppContext {
|
|||
});
|
||||
|
||||
let blurred_parents = blurred_id
|
||||
.map(|blurred_id| this.parents(window_id, blurred_id).collect::<Vec<_>>())
|
||||
.map(|blurred_id| this.ancestors(window_id, blurred_id).collect::<Vec<_>>())
|
||||
.unwrap_or_default();
|
||||
let focused_parents = focused_id
|
||||
.map(|focused_id| this.parents(window_id, focused_id).collect::<Vec<_>>())
|
||||
.map(|focused_id| this.ancestors(window_id, focused_id).collect::<Vec<_>>())
|
||||
.unwrap_or_default();
|
||||
|
||||
if let Some(blurred_id) = blurred_id {
|
||||
for view_id in blurred_parents.iter().copied() {
|
||||
if let Some(mut view) = this.cx.views.remove(&(window_id, view_id)) {
|
||||
view.on_focus_out(this, window_id, view_id, blurred_id);
|
||||
view.focus_out(this, window_id, view_id, blurred_id);
|
||||
this.cx.views.insert((window_id, view_id), view);
|
||||
}
|
||||
}
|
||||
|
@ -2294,7 +2374,7 @@ impl MutableAppContext {
|
|||
if let Some(focused_id) = focused_id {
|
||||
for view_id in focused_parents {
|
||||
if let Some(mut view) = this.cx.views.remove(&(window_id, view_id)) {
|
||||
view.on_focus_in(this, window_id, view_id, focused_id);
|
||||
view.focus_in(this, window_id, view_id, focused_id);
|
||||
this.cx.views.insert((window_id, view_id), view);
|
||||
}
|
||||
}
|
||||
|
@ -2961,20 +3041,41 @@ pub trait AnyView {
|
|||
) -> Option<Pin<Box<dyn 'static + Future<Output = ()>>>>;
|
||||
fn ui_name(&self) -> &'static str;
|
||||
fn render(&mut self, params: RenderParams, cx: &mut MutableAppContext) -> ElementBox;
|
||||
fn on_focus_in(
|
||||
fn focus_in(
|
||||
&mut self,
|
||||
cx: &mut MutableAppContext,
|
||||
window_id: usize,
|
||||
view_id: usize,
|
||||
focused_id: usize,
|
||||
);
|
||||
fn on_focus_out(
|
||||
fn focus_out(
|
||||
&mut self,
|
||||
cx: &mut MutableAppContext,
|
||||
window_id: usize,
|
||||
view_id: usize,
|
||||
focused_id: usize,
|
||||
);
|
||||
fn key_down(
|
||||
&mut self,
|
||||
event: &KeyDownEvent,
|
||||
cx: &mut MutableAppContext,
|
||||
window_id: usize,
|
||||
view_id: usize,
|
||||
) -> bool;
|
||||
fn key_up(
|
||||
&mut self,
|
||||
event: &KeyUpEvent,
|
||||
cx: &mut MutableAppContext,
|
||||
window_id: usize,
|
||||
view_id: usize,
|
||||
) -> bool;
|
||||
fn modifiers_changed(
|
||||
&mut self,
|
||||
event: &ModifiersChangedEvent,
|
||||
cx: &mut MutableAppContext,
|
||||
window_id: usize,
|
||||
view_id: usize,
|
||||
) -> bool;
|
||||
fn keymap_context(&self, cx: &AppContext) -> keymap::Context;
|
||||
fn debug_json(&self, cx: &AppContext) -> serde_json::Value;
|
||||
|
||||
|
@ -3040,7 +3141,7 @@ where
|
|||
View::render(self, &mut RenderContext::new(params, cx))
|
||||
}
|
||||
|
||||
fn on_focus_in(
|
||||
fn focus_in(
|
||||
&mut self,
|
||||
cx: &mut MutableAppContext,
|
||||
window_id: usize,
|
||||
|
@ -3059,10 +3160,10 @@ where
|
|||
.type_id();
|
||||
AnyViewHandle::new(window_id, focused_id, focused_type, cx.ref_counts.clone())
|
||||
};
|
||||
View::on_focus_in(self, focused_view_handle, &mut cx);
|
||||
View::focus_in(self, focused_view_handle, &mut cx);
|
||||
}
|
||||
|
||||
fn on_focus_out(
|
||||
fn focus_out(
|
||||
&mut self,
|
||||
cx: &mut MutableAppContext,
|
||||
window_id: usize,
|
||||
|
@ -3081,7 +3182,40 @@ where
|
|||
.type_id();
|
||||
AnyViewHandle::new(window_id, blurred_id, blurred_type, cx.ref_counts.clone())
|
||||
};
|
||||
View::on_focus_out(self, blurred_view_handle, &mut cx);
|
||||
View::focus_out(self, blurred_view_handle, &mut cx);
|
||||
}
|
||||
|
||||
fn key_down(
|
||||
&mut self,
|
||||
event: &KeyDownEvent,
|
||||
cx: &mut MutableAppContext,
|
||||
window_id: usize,
|
||||
view_id: usize,
|
||||
) -> bool {
|
||||
let mut cx = ViewContext::new(cx, window_id, view_id);
|
||||
View::key_down(self, event, &mut cx)
|
||||
}
|
||||
|
||||
fn key_up(
|
||||
&mut self,
|
||||
event: &KeyUpEvent,
|
||||
cx: &mut MutableAppContext,
|
||||
window_id: usize,
|
||||
view_id: usize,
|
||||
) -> bool {
|
||||
let mut cx = ViewContext::new(cx, window_id, view_id);
|
||||
View::key_up(self, event, &mut cx)
|
||||
}
|
||||
|
||||
fn modifiers_changed(
|
||||
&mut self,
|
||||
event: &ModifiersChangedEvent,
|
||||
cx: &mut MutableAppContext,
|
||||
window_id: usize,
|
||||
view_id: usize,
|
||||
) -> bool {
|
||||
let mut cx = ViewContext::new(cx, window_id, view_id);
|
||||
View::modifiers_changed(self, event, &mut cx)
|
||||
}
|
||||
|
||||
fn keymap_context(&self, cx: &AppContext) -> keymap::Context {
|
||||
|
@ -3463,7 +3597,7 @@ impl<'a, T: View> ViewContext<'a, T> {
|
|||
if self.window_id != view.window_id {
|
||||
return false;
|
||||
}
|
||||
self.parents(view.window_id, view.view_id)
|
||||
self.ancestors(view.window_id, view.view_id)
|
||||
.any(|parent| parent == self.view_id)
|
||||
}
|
||||
|
||||
|
@ -6354,13 +6488,13 @@ mod tests {
|
|||
"View"
|
||||
}
|
||||
|
||||
fn on_focus_in(&mut self, focused: AnyViewHandle, cx: &mut ViewContext<Self>) {
|
||||
fn focus_in(&mut self, focused: AnyViewHandle, cx: &mut ViewContext<Self>) {
|
||||
if cx.handle().id() == focused.id() {
|
||||
self.events.lock().push(format!("{} focused", &self.name));
|
||||
}
|
||||
}
|
||||
|
||||
fn on_focus_out(&mut self, blurred: AnyViewHandle, cx: &mut ViewContext<Self>) {
|
||||
fn focus_out(&mut self, blurred: AnyViewHandle, cx: &mut ViewContext<Self>) {
|
||||
if cx.handle().id() == blurred.id() {
|
||||
self.events.lock().push(format!("{} blurred", &self.name));
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue