Checkpoint

This commit is contained in:
Antonio Scandurra
2023-10-18 14:36:16 +02:00
parent a61b34cab5
commit 5afd83c883
2 changed files with 125 additions and 105 deletions
+58 -62
View File
@@ -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
View File
@@ -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
}