Checkpoint
This commit is contained in:
@@ -375,10 +375,17 @@ where
|
||||
element_state: Option<Self::ElementState>,
|
||||
cx: &mut ViewContext<Self::ViewState>,
|
||||
) -> Self::ElementState {
|
||||
for child in &mut self.children {
|
||||
child.initialize(view_state, cx);
|
||||
}
|
||||
element_state.unwrap_or_default()
|
||||
cx.with_focus(
|
||||
self.focusability.focus_handle().cloned(),
|
||||
self.listeners.key_down.clone(),
|
||||
self.listeners.key_up.clone(),
|
||||
|cx| {
|
||||
for child in &mut self.children {
|
||||
child.initialize(view_state, cx);
|
||||
}
|
||||
element_state.unwrap_or_default()
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fn layout(
|
||||
@@ -408,68 +415,57 @@ where
|
||||
cx: &mut ViewContext<Self::ViewState>,
|
||||
) {
|
||||
self.with_element_id(cx, |this, cx| {
|
||||
cx.with_key_listeners(
|
||||
this.focusability.focus_handle().cloned(),
|
||||
this.listeners.key_down.clone(),
|
||||
this.listeners.key_up.clone(),
|
||||
|cx| {
|
||||
if let Some(group) = this.group.clone() {
|
||||
cx.default_global::<GroupBounds>()
|
||||
.0
|
||||
.entry(group)
|
||||
.or_default()
|
||||
.push(bounds);
|
||||
}
|
||||
if let Some(group) = this.group.clone() {
|
||||
cx.default_global::<GroupBounds>()
|
||||
.0
|
||||
.entry(group)
|
||||
.or_default()
|
||||
.push(bounds);
|
||||
}
|
||||
|
||||
let hover_group_bounds = this
|
||||
.group_hover
|
||||
.as_ref()
|
||||
.and_then(|group_hover| group_bounds(&group_hover.group, cx));
|
||||
let active_group_bounds = this
|
||||
.group_active
|
||||
.as_ref()
|
||||
.and_then(|group_active| group_bounds(&group_active.group, cx));
|
||||
let style = this.compute_style(bounds, element_state, cx);
|
||||
let z_index = style.z_index.unwrap_or(0);
|
||||
let hover_group_bounds = this
|
||||
.group_hover
|
||||
.as_ref()
|
||||
.and_then(|group_hover| group_bounds(&group_hover.group, cx));
|
||||
let active_group_bounds = this
|
||||
.group_active
|
||||
.as_ref()
|
||||
.and_then(|group_active| group_bounds(&group_active.group, cx));
|
||||
let style = this.compute_style(bounds, element_state, cx);
|
||||
let z_index = style.z_index.unwrap_or(0);
|
||||
|
||||
// Paint background and event handlers.
|
||||
cx.stack(z_index, |cx| {
|
||||
cx.stack(0, |cx| {
|
||||
style.paint(bounds, cx);
|
||||
this.paint_hover_listeners(bounds, hover_group_bounds, cx);
|
||||
this.paint_active_listener(
|
||||
bounds,
|
||||
active_group_bounds,
|
||||
element_state.active_state.clone(),
|
||||
cx,
|
||||
);
|
||||
this.paint_event_listeners(
|
||||
bounds,
|
||||
element_state.pending_click.clone(),
|
||||
cx,
|
||||
);
|
||||
});
|
||||
// Paint background and event handlers.
|
||||
cx.stack(z_index, |cx| {
|
||||
cx.stack(0, |cx| {
|
||||
style.paint(bounds, cx);
|
||||
this.paint_hover_listeners(bounds, hover_group_bounds, cx);
|
||||
this.paint_active_listener(
|
||||
bounds,
|
||||
active_group_bounds,
|
||||
element_state.active_state.clone(),
|
||||
cx,
|
||||
);
|
||||
this.paint_event_listeners(bounds, element_state.pending_click.clone(), cx);
|
||||
});
|
||||
|
||||
cx.stack(1, |cx| {
|
||||
style.apply_text_style(cx, |cx| {
|
||||
style.apply_overflow(bounds, cx, |cx| {
|
||||
for child in &mut this.children {
|
||||
child.paint(view_state, None, cx);
|
||||
}
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
cx.stack(1, |cx| {
|
||||
style.apply_text_style(cx, |cx| {
|
||||
style.apply_overflow(bounds, cx, |cx| {
|
||||
for child in &mut this.children {
|
||||
child.paint(view_state, None, cx);
|
||||
}
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
if let Some(group) = this.group.as_ref() {
|
||||
cx.default_global::<GroupBounds>()
|
||||
.0
|
||||
.get_mut(group)
|
||||
.unwrap()
|
||||
.pop();
|
||||
}
|
||||
},
|
||||
)
|
||||
if let Some(group) = this.group.as_ref() {
|
||||
cx.default_global::<GroupBounds>()
|
||||
.0
|
||||
.get_mut(group)
|
||||
.unwrap()
|
||||
.pop();
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
+67
-43
@@ -9,7 +9,7 @@ use crate::{
|
||||
Task, Underline, UnderlineStyle, WeakHandle, WindowOptions, SUBPIXEL_VARIANTS,
|
||||
};
|
||||
use anyhow::Result;
|
||||
use collections::HashMap;
|
||||
use collections::{HashMap, HashSet};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use smallvec::SmallVec;
|
||||
use std::{
|
||||
@@ -42,7 +42,7 @@ pub enum DispatchPhase {
|
||||
type MouseEventHandler =
|
||||
Arc<dyn Fn(&dyn Any, DispatchPhase, &mut WindowContext) + Send + Sync + 'static>;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct FocusId(usize);
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -64,10 +64,13 @@ pub struct Window {
|
||||
element_states: HashMap<GlobalElementId, AnyBox>,
|
||||
z_index_stack: StackingOrder,
|
||||
content_mask_stack: Vec<ContentMask<Pixels>>,
|
||||
mouse_event_handlers: HashMap<TypeId, Vec<(StackingOrder, MouseEventHandler)>>,
|
||||
key_down_listener_stack:
|
||||
mouse_listeners: HashMap<TypeId, Vec<(StackingOrder, MouseEventHandler)>>,
|
||||
focus_stack: Vec<FocusStackFrame>,
|
||||
focus_parents_by_child: HashMap<FocusId, FocusId>,
|
||||
focused_in: HashSet<FocusId>,
|
||||
key_down_listeners:
|
||||
Vec<Arc<dyn Fn(&KeyDownEvent, DispatchPhase, &mut WindowContext) + Send + Sync + 'static>>,
|
||||
key_up_listener_stack:
|
||||
key_up_listeners:
|
||||
Vec<Arc<dyn Fn(&KeyUpEvent, DispatchPhase, &mut WindowContext) + Send + Sync + 'static>>,
|
||||
propagate_event: bool,
|
||||
mouse_position: Point<Pixels>,
|
||||
@@ -76,7 +79,6 @@ pub struct Window {
|
||||
pub(crate) dirty: bool,
|
||||
focus: Option<FocusId>,
|
||||
next_focus_id: FocusId,
|
||||
painted_focused_element: bool,
|
||||
}
|
||||
|
||||
impl Window {
|
||||
@@ -135,9 +137,12 @@ impl Window {
|
||||
element_states: HashMap::default(),
|
||||
z_index_stack: StackingOrder(SmallVec::new()),
|
||||
content_mask_stack: Vec::new(),
|
||||
mouse_event_handlers: HashMap::default(),
|
||||
key_down_listener_stack: Vec::new(),
|
||||
key_up_listener_stack: Vec::new(),
|
||||
focus_stack: Vec::new(),
|
||||
focus_parents_by_child: HashMap::default(),
|
||||
focused_in: HashSet::default(),
|
||||
mouse_listeners: HashMap::default(),
|
||||
key_down_listeners: Vec::new(),
|
||||
key_up_listeners: Vec::new(),
|
||||
propagate_event: true,
|
||||
mouse_position,
|
||||
scale_factor,
|
||||
@@ -145,7 +150,6 @@ impl Window {
|
||||
dirty: true,
|
||||
focus: None,
|
||||
next_focus_id: FocusId(0),
|
||||
painted_focused_element: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -169,6 +173,16 @@ impl ContentMask<Pixels> {
|
||||
}
|
||||
}
|
||||
|
||||
struct FocusStackFrame {
|
||||
handle: FocusHandle,
|
||||
key_down_listeners: SmallVec<
|
||||
[Arc<dyn Fn(&KeyDownEvent, DispatchPhase, &mut WindowContext) + Send + Sync + 'static>; 2],
|
||||
>,
|
||||
key_up_listeners: SmallVec<
|
||||
[Arc<dyn Fn(&KeyUpEvent, DispatchPhase, &mut WindowContext) + Send + Sync + 'static>; 2],
|
||||
>,
|
||||
}
|
||||
|
||||
pub struct WindowContext<'a, 'w> {
|
||||
app: Reference<'a, AppContext>,
|
||||
pub(crate) window: Reference<'w, Window>,
|
||||
@@ -323,7 +337,7 @@ impl<'a, 'w> WindowContext<'a, 'w> {
|
||||
) {
|
||||
let order = self.window.z_index_stack.clone();
|
||||
self.window
|
||||
.mouse_event_handlers
|
||||
.mouse_listeners
|
||||
.entry(TypeId::of::<Event>())
|
||||
.or_default()
|
||||
.push((
|
||||
@@ -675,12 +689,14 @@ impl<'a, 'w> WindowContext<'a, 'w> {
|
||||
|
||||
// Clear mouse event listeners, because elements add new element listeners
|
||||
// when the upcoming frame is painted.
|
||||
window
|
||||
.mouse_event_handlers
|
||||
.values_mut()
|
||||
.for_each(Vec::clear);
|
||||
window.mouse_listeners.values_mut().for_each(Vec::clear);
|
||||
|
||||
window.painted_focused_element = false;
|
||||
// Clear focus state, because we determine what is focused when the new elements
|
||||
// in the upcoming frame are initialized.
|
||||
window.key_down_listeners.clear();
|
||||
window.key_up_listeners.clear();
|
||||
window.focused_in.clear();
|
||||
window.focus_parents_by_child.clear();
|
||||
}
|
||||
|
||||
fn end_frame(&mut self) {
|
||||
@@ -695,7 +711,7 @@ impl<'a, 'w> WindowContext<'a, 'w> {
|
||||
|
||||
if let Some(mut handlers) = self
|
||||
.window
|
||||
.mouse_event_handlers
|
||||
.mouse_listeners
|
||||
.remove(&any_mouse_event.type_id())
|
||||
{
|
||||
// Because handlers may add other handlers, we sort every time.
|
||||
@@ -726,13 +742,13 @@ impl<'a, 'w> WindowContext<'a, 'w> {
|
||||
// Just in case any handlers added new handlers, which is weird, but possible.
|
||||
handlers.extend(
|
||||
self.window
|
||||
.mouse_event_handlers
|
||||
.mouse_listeners
|
||||
.get_mut(&any_mouse_event.type_id())
|
||||
.into_iter()
|
||||
.flat_map(|handlers| handlers.drain(..)),
|
||||
);
|
||||
self.window
|
||||
.mouse_event_handlers
|
||||
.mouse_listeners
|
||||
.insert(any_mouse_event.type_id(), handlers);
|
||||
}
|
||||
}
|
||||
@@ -1030,7 +1046,7 @@ impl<'a, 'w, V: Send + Sync + 'static> ViewContext<'a, 'w, V> {
|
||||
});
|
||||
}
|
||||
|
||||
pub fn with_key_listeners<R>(
|
||||
pub fn with_focus<R>(
|
||||
&mut self,
|
||||
focus_handle: Option<FocusHandle>,
|
||||
key_down: impl IntoIterator<Item = KeyDownListener<V>>,
|
||||
@@ -1040,20 +1056,25 @@ impl<'a, 'w, V: Send + Sync + 'static> ViewContext<'a, 'w, V> {
|
||||
let Some(focus_handle) = focus_handle else {
|
||||
return f(self);
|
||||
};
|
||||
let Some(focused_id) = self.window.focus else {
|
||||
return f(self);
|
||||
};
|
||||
if self.window.painted_focused_element {
|
||||
return f(self);
|
||||
|
||||
let handle = self.handle();
|
||||
let window = &mut *self.window;
|
||||
if let Some(parent_frame) = window.focus_stack.last() {
|
||||
window
|
||||
.focus_parents_by_child
|
||||
.insert(focus_handle.id, parent_frame.handle.id);
|
||||
}
|
||||
|
||||
let prev_key_down_len = self.window.key_down_listener_stack.len();
|
||||
let prev_key_up_len = self.window.key_up_listener_stack.len();
|
||||
let mut frame = FocusStackFrame {
|
||||
handle: focus_handle.clone(),
|
||||
key_down_listeners: SmallVec::new(),
|
||||
key_up_listeners: SmallVec::new(),
|
||||
};
|
||||
|
||||
for listener in key_down {
|
||||
let handle = self.handle();
|
||||
self.window
|
||||
.key_down_listener_stack
|
||||
let handle = handle.clone();
|
||||
frame
|
||||
.key_down_listeners
|
||||
.push(Arc::new(move |event, phase, cx| {
|
||||
handle
|
||||
.update(cx, |view, cx| listener(view, event, phase, cx))
|
||||
@@ -1061,9 +1082,9 @@ impl<'a, 'w, V: Send + Sync + 'static> ViewContext<'a, 'w, V> {
|
||||
}));
|
||||
}
|
||||
for listener in key_up {
|
||||
let handle = self.handle();
|
||||
self.window
|
||||
.key_up_listener_stack
|
||||
let handle = handle.clone();
|
||||
frame
|
||||
.key_up_listeners
|
||||
.push(Arc::new(move |event, phase, cx| {
|
||||
handle
|
||||
.update(cx, |view, cx| listener(view, event, phase, cx))
|
||||
@@ -1071,19 +1092,22 @@ impl<'a, 'w, V: Send + Sync + 'static> ViewContext<'a, 'w, V> {
|
||||
}));
|
||||
}
|
||||
|
||||
if focus_handle.id == focused_id {
|
||||
self.window.painted_focused_element = true;
|
||||
window.focus_stack.push(frame);
|
||||
|
||||
if Some(focus_handle.id) == window.focus {
|
||||
for frame in &window.focus_stack {
|
||||
window.focused_in.insert(frame.handle.id);
|
||||
window
|
||||
.key_down_listeners
|
||||
.extend_from_slice(&frame.key_down_listeners);
|
||||
window
|
||||
.key_up_listeners
|
||||
.extend_from_slice(&frame.key_up_listeners);
|
||||
}
|
||||
}
|
||||
|
||||
let result = f(self);
|
||||
|
||||
if focus_handle.id != focused_id {
|
||||
self.window
|
||||
.key_down_listener_stack
|
||||
.truncate(prev_key_down_len);
|
||||
self.window.key_up_listener_stack.truncate(prev_key_up_len);
|
||||
}
|
||||
|
||||
self.window.focus_stack.pop();
|
||||
result
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user