Compare commits

...

5 Commits

Author SHA1 Message Date
Antonio Scandurra
92fda552d1 WIP 2024-02-22 19:56:15 +01:00
Nathan Sobo
0d764afd4c WIP 2024-02-22 10:56:00 -07:00
Nathan Sobo
678ff835d2 WIP 2024-02-22 09:35:03 -07:00
Nathan Sobo
f531d953e3 WIP 2024-02-21 22:03:43 -07:00
Nathan Sobo
6583c69612 Checkpoint 2024-02-21 20:47:12 -07:00
10 changed files with 959 additions and 778 deletions

View File

@@ -1106,14 +1106,8 @@ impl AppContext {
for window in self.windows() {
window
.update(self, |_, cx| {
cx.window
.rendered_frame
.dispatch_tree
.clear_pending_keystrokes();
cx.window
.next_frame
.dispatch_tree
.clear_pending_keystrokes();
cx.window.rendered_frame.clear_pending_keystrokes();
cx.window.next_frame.clear_pending_keystrokes();
})
.ok();
}

457
crates/gpui/src/frame.rs Normal file
View File

@@ -0,0 +1,457 @@
use crate::{
Action, ActionRegistry, AnyTooltip, Bounds, ContentMask, CursorStyle, DispatchPhase,
ElementContext, EntityId, FocusId, GlobalElementId, KeyBinding, KeyContext, KeyEvent, Keymap,
KeymatchResult, Keystroke, KeystrokeMatcher, MouseEvent, Pixels, PlatformInputHandler,
Primitive, Scene, SceneIndex, SmallVec, WindowContext,
};
use collections::FxHashMap;
use std::{
any::{Any, TypeId},
cell::RefCell,
iter,
ops::Range,
rc::Rc,
};
// pub(crate) struct Frame {
// pub(crate) window_active: bool,
// #[cfg(any(test, feature = "test-support"))]
// pub(crate) debug_bounds: FxHashMap<String, Bounds<Pixels>>,
// }
pub struct Frame {
elements: Vec<PaintedElement>,
pub(crate) scene: Scene,
focus: Option<FocusId>,
pub(crate) window_active: bool,
mouse_listeners: Vec<AnyMouseListener>,
key_listeners: Vec<KeyListener>,
action_listeners: Vec<ActionListener>,
element_states: FxHashMap<GlobalElementId, ElementStateBox>,
element_stack: Vec<PaintedElementId>,
context_stack: Vec<KeyContext>,
content_mask_stack: Vec<ContentMask<Pixels>>,
focusable_node_ids: FxHashMap<FocusId, PaintedElementId>,
view_node_ids: FxHashMap<EntityId, PaintedElementId>,
keystroke_matchers: FxHashMap<SmallVec<[KeyContext; 4]>, KeystrokeMatcher>,
keymap: Rc<RefCell<Keymap>>,
action_registry: Rc<ActionRegistry>,
}
impl Frame {
pub fn new(keymap: Rc<RefCell<Keymap>>, action_registry: Rc<ActionRegistry>) -> Self {
Frame {
keymap,
action_registry,
elements: Vec::new(),
scene: Scene::default(),
focus: None,
window_active: false,
mouse_listeners: Vec::new(),
key_listeners: Vec::new(),
action_listeners: Vec::new(),
element_states: FxHashMap::default(),
element_stack: Vec::new(),
context_stack: Vec::new(),
content_mask_stack: Vec::new(),
focusable_node_ids: FxHashMap::default(),
view_node_ids: FxHashMap::default(),
keystroke_matchers: FxHashMap::default(),
}
}
pub fn clear(&mut self) {
self.elements.clear();
self.scene.clear();
self.focus = None;
self.mouse_listeners.clear();
self.key_listeners.clear();
self.action_listeners.clear();
self.element_states.clear();
self.element_stack.clear();
self.context_stack.clear();
self.content_mask_stack.clear();
self.focusable_node_ids.clear();
self.view_node_ids.clear();
self.keystroke_matchers.clear();
}
pub fn clear_pending_keystrokes(&mut self) {
self.keystroke_matchers.clear();
}
/// Preserve keystroke matchers from previous frames to support multi-stroke
/// bindings across multiple frames.
pub fn preserve_pending_keystrokes(
&mut self,
prev_frame: &mut Self,
focus_id: Option<FocusId>,
) {
self.context_stack.clear();
for element in self.dispatch_path(focus_id) {
if let Some(context) = element.key_context.clone() {
self.context_stack.push(context);
}
if let Some((context_stack, matcher)) = prev_frame
.keystroke_matchers
.remove_entry(self.context_stack.as_slice())
{
self.keystroke_matchers.insert(context_stack, matcher);
}
}
}
pub fn set_focus(&mut self, focus_id: Option<FocusId>) {
self.focus = focus_id;
}
pub fn set_window_active(&mut self, active: bool) {
self.window_active = active;
}
pub fn window_active(&self) -> bool {
self.window_active
}
pub fn focus_contains(&self, parent: FocusId, child: FocusId) -> bool {
if parent == child {
return true;
}
if let Some(parent_node_id) = self.focusable_node_ids.get(&parent) {
let mut current_node_id = self.focusable_node_ids.get(&child).copied();
while let Some(node_id) = current_node_id {
if node_id == *parent_node_id {
return true;
}
current_node_id = self.elements[node_id.0].parent;
}
}
false
}
pub fn focus_path(&self) -> SmallVec<[FocusId; 8]> {
let Some(focus_id) = self.focus else {
return SmallVec::new();
};
let mut focus_path = self
.dispatch_path(Some(focus_id))
.flat_map(|element| element.focus_id)
.collect::<SmallVec<[FocusId; 8]>>();
focus_path.reverse(); // Reverse the path so it goes from the root to the focused node.
focus_path
}
pub fn view_path(&self, view_id: EntityId) -> SmallVec<[EntityId; 8]> {
let Some(element_id) = self.view_node_ids.get(&view_id) else {
return SmallVec::new();
};
let mut view_path = self
.ancestors(Some(*element_id))
.flat_map(|element| element.view_id)
.collect::<SmallVec<[EntityId; 8]>>();
view_path.reverse(); // Reverse the path so it goes from the root to the focused node.
view_path
}
pub fn action_dispatch_path(&self, focus_id: Option<FocusId>) -> SmallVec<[ActionListener; 8]> {
let mut action_dispatch_path = self
.dispatch_path(focus_id)
.flat_map(|element| {
self.action_listeners[element.action_listeners.clone()]
.iter()
.cloned()
})
.collect::<SmallVec<[ActionListener; 8]>>();
action_dispatch_path.reverse(); // Reverse the path so it goes from the root to the focused node.
action_dispatch_path
}
pub fn key_dispatch_path(&self, focus_id: Option<FocusId>) -> SmallVec<[KeyListener; 8]> {
let mut key_dispatch_path: SmallVec<[KeyListener; 8]> = self
.dispatch_path(focus_id)
.flat_map(|element| {
self.key_listeners[element.key_listeners.clone()]
.iter()
.cloned()
})
.collect::<SmallVec<[KeyListener; 8]>>();
key_dispatch_path.reverse(); // Reverse the path so it goes from the root to the focused node.
key_dispatch_path
}
pub fn available_actions(&self, focus_id: Option<FocusId>) -> Vec<Box<dyn Action>> {
let mut actions = Vec::<Box<dyn Action>>::new();
for ActionListener { action_type, .. } in self.action_dispatch_path(focus_id) {
if let Err(ix) = actions.binary_search_by_key(&action_type, |a| a.as_any().type_id()) {
// Intentionally silence these errors without logging.
// If an action cannot be built by default, it's not available.
let action = self.action_registry.build_action_type(&action_type).ok();
if let Some(action) = action {
actions.insert(ix, action);
}
}
}
actions
}
pub fn bindings_for_action(
&self,
action: &dyn Action,
focus_id: Option<FocusId>,
) -> Vec<KeyBinding> {
let context_stack = self
.dispatch_path(focus_id)
.flat_map(|element| element.key_context.clone())
.collect::<SmallVec<[KeyContext; 8]>>();
let keymap = self.keymap.borrow();
keymap
.bindings_for_action(action)
.filter(|binding| {
for i in 0..context_stack.len() {
let context = &context_stack[0..=i];
if keymap.binding_enabled(binding, context) {
return true;
}
}
false
})
.cloned()
.collect()
}
pub fn is_action_available(&self, action: &dyn Action, focus_id: Option<FocusId>) -> bool {
for element in self.dispatch_path(focus_id) {
if self.action_listeners[element.action_listeners.clone()]
.iter()
.any(|listener| listener.action_type == action.as_any().type_id())
{
return true;
}
}
false
}
pub fn match_keystroke(
&mut self,
keystroke: &Keystroke,
focus_id: Option<FocusId>,
) -> KeymatchResult {
let mut bindings = SmallVec::<[KeyBinding; 1]>::new();
let mut pending = false;
let mut context_stack: SmallVec<[KeyContext; 4]> = SmallVec::new();
for element in self.dispatch_path(focus_id) {
if let Some(context) = element.key_context.clone() {
context_stack.push(context);
}
}
while !context_stack.is_empty() {
let keystroke_matcher = self
.keystroke_matchers
.entry(context_stack.clone())
.or_insert_with(|| KeystrokeMatcher::new(self.keymap.clone()));
let result = keystroke_matcher.match_keystroke(keystroke, &context_stack);
if result.pending && !pending && !bindings.is_empty() {
context_stack.pop();
continue;
}
pending = result.pending || pending;
for new_binding in result.bindings {
match bindings
.iter()
.position(|el| el.keystrokes.len() < new_binding.keystrokes.len())
{
Some(idx) => {
bindings.insert(idx, new_binding);
}
None => bindings.push(new_binding),
}
}
context_stack.pop();
}
KeymatchResult { bindings, pending }
}
pub fn has_pending_keystrokes(&self) -> bool {
self.keystroke_matchers
.iter()
.any(|(_, matcher)| matcher.has_pending_keystrokes())
}
fn dispatch_path(&self, focus_id: Option<FocusId>) -> impl Iterator<Item = &PaintedElement> {
let mut current_node_id = focus_id
.and_then(|focus_id| self.focusable_node_ids.get(&focus_id).copied())
.or_else(|| self.elements.is_empty().then(|| PaintedElementId(0)));
self.ancestors(current_node_id)
}
fn ancestors(
&self,
mut current_node_id: Option<PaintedElementId>,
) -> impl Iterator<Item = &PaintedElement> {
iter::from_fn(move || {
let node_id = current_node_id?;
current_node_id = self.elements[node_id.0].parent;
Some(&self.elements[node_id.0])
})
}
pub fn push_element(&mut self) {
let parent = self.element_stack.last().copied();
let element_id = PaintedElementId(self.elements.len());
let scene_index = self.scene.current_index();
self.elements.push(PaintedElement {
parent,
scene_primitives: scene_index.clone()..scene_index,
mouse_listeners: self.mouse_listeners.len()..self.mouse_listeners.len(),
key_listeners: self.key_listeners.len()..self.key_listeners.len(),
action_listeners: self.action_listeners.len()..self.action_listeners.len(),
..Default::default()
});
self.element_stack.push(element_id);
}
pub fn pop_element(&mut self) {
let element = &self.elements[self.active_element_id().0];
if element.key_context.is_some() {
self.context_stack.pop();
}
self.element_stack.pop();
}
pub fn set_key_context(&mut self, context: KeyContext) {
let element_id = self.active_element_id();
self.elements[element_id.0].key_context = Some(context.clone());
self.context_stack.push(context);
}
pub fn set_focus_id(&mut self, focus_id: FocusId) {
let element_id = self.active_element_id();
self.elements[element_id.0].focus_id = Some(focus_id);
self.focusable_node_ids.insert(focus_id, element_id);
}
pub fn set_view_id(&mut self, view_id: EntityId) {
let element_id = self.active_element_id();
self.elements[element_id.0].view_id = Some(view_id);
self.view_node_ids.insert(view_id, element_id);
}
pub fn paint_primitive<P: Into<Primitive>>(&mut self, build_primitive: impl FnOnce(u32) -> P) {
self.scene.paint_primitive(build_primitive);
let element_id = self.active_element_id();
self.elements[element_id.0].scene_primitives.end = self.scene.current_index();
}
pub fn on_mouse_event<E: MouseEvent>(
&mut self,
mut listener: impl 'static + FnMut(&E, DispatchPhase, &mut WindowContext),
) {
self.mouse_listeners.push(Rc::new(move |event, phase, cx| {
if let Some(event) = event.downcast_ref::<E>() {
listener(event, phase, cx);
}
}));
self.active_element().mouse_listeners.end += 1;
}
pub fn on_key_event<E: KeyEvent>(
&mut self,
listener: impl Fn(&E, DispatchPhase, &mut WindowContext) + 'static,
) {
self.key_listeners.push(Rc::new(|event, phase, cx| {
if let Some(event) = event.downcast_ref::<E>() {
listener(event, phase, cx);
}
}));
self.active_element().key_listeners.end += 1;
}
pub fn on_action(
&mut self,
action_type: TypeId,
listener: Rc<dyn Fn(&dyn Any, DispatchPhase, &mut WindowContext) + 'static>,
) {
self.action_listeners.push(ActionListener {
action_type,
listener: Rc::new(|event, phase, cx| listener(event, phase, cx)),
});
self.active_element().action_listeners.end += 1;
}
pub fn set_input_handler(&mut self, handler: Option<PlatformInputHandler>) {
self.active_element().input_handler = handler;
}
pub fn set_tooltip(&mut self, tooltip: Option<AnyTooltip>) {
self.active_element().tooltip = tooltip;
}
pub fn set_cursor_style(&mut self, cursor_style: Option<CursorStyle>) {
self.active_element().cursor_style = cursor_style;
}
fn active_element_id(&self) -> PaintedElementId {
self.element_stack
.last()
.copied()
.expect("There should be an active element")
}
fn active_element(&mut self) -> &mut PaintedElement {
let element_id = self.active_element_id();
&mut self.elements[element_id.0]
}
}
#[derive(Default)]
struct PaintedElement {
id: Option<GlobalElementId>,
bounds: Bounds<Pixels>,
content_mask: ContentMask<Pixels>,
opaque: bool,
scene_primitives: Range<SceneIndex>,
mouse_listeners: Range<usize>,
key_listeners: Range<usize>,
action_listeners: Range<usize>,
input_handler: Option<PlatformInputHandler>,
tooltip: Option<AnyTooltip>,
cursor_style: Option<CursorStyle>,
key_context: Option<KeyContext>,
focus_id: Option<FocusId>,
view_id: Option<EntityId>,
parent: Option<PaintedElementId>,
}
pub(crate) struct ElementStateBox {
pub(crate) inner: Box<dyn Any>,
pub(crate) parent_view_id: EntityId,
#[cfg(debug_assertions)]
pub(crate) type_name: &'static str,
}
#[derive(Copy, Clone, Eq, PartialEq)]
struct PaintedElementId(usize);
type AnyMouseListener = Rc<dyn Fn(&dyn Any, DispatchPhase, &mut ElementContext) + 'static>;
type KeyListener = Rc<dyn Fn(&dyn Any, DispatchPhase, &mut ElementContext)>;
#[derive(Clone)]
pub(crate) struct ActionListener {
pub(crate) action_type: TypeId,
pub(crate) listener: Rc<dyn Fn(&dyn Any, DispatchPhase, &mut WindowContext)>,
}

View File

@@ -74,6 +74,7 @@ mod color;
mod element;
mod elements;
mod executor;
mod frame;
mod geometry;
mod image_cache;
mod input;
@@ -122,6 +123,7 @@ pub use ctor::ctor;
pub use element::*;
pub use elements::*;
pub use executor::*;
pub use frame::*;
pub use geometry::*;
pub use gpui_macros::{register_action, test, IntoElement, Render};
use image_cache::*;

View File

@@ -68,26 +68,22 @@ impl<V: 'static> ElementInputHandler<V> {
}
impl<V: ViewInputHandler> InputHandler for ElementInputHandler<V> {
fn selected_text_range(&mut self, cx: &mut WindowContext) -> Option<Range<usize>> {
fn selected_text_range(&self, cx: &mut WindowContext) -> Option<Range<usize>> {
self.view
.update(cx, |view, cx| view.selected_text_range(cx))
}
fn marked_text_range(&mut self, cx: &mut WindowContext) -> Option<Range<usize>> {
fn marked_text_range(&self, cx: &mut WindowContext) -> Option<Range<usize>> {
self.view.update(cx, |view, cx| view.marked_text_range(cx))
}
fn text_for_range(
&mut self,
range_utf16: Range<usize>,
cx: &mut WindowContext,
) -> Option<String> {
fn text_for_range(&self, range_utf16: Range<usize>, cx: &mut WindowContext) -> Option<String> {
self.view
.update(cx, |view, cx| view.text_for_range(range_utf16, cx))
}
fn replace_text_in_range(
&mut self,
&self,
replacement_range: Option<Range<usize>>,
text: &str,
cx: &mut WindowContext,
@@ -98,7 +94,7 @@ impl<V: ViewInputHandler> InputHandler for ElementInputHandler<V> {
}
fn replace_and_mark_text_in_range(
&mut self,
&self,
range_utf16: Option<Range<usize>>,
new_text: &str,
new_selected_range: Option<Range<usize>>,
@@ -109,12 +105,12 @@ impl<V: ViewInputHandler> InputHandler for ElementInputHandler<V> {
});
}
fn unmark_text(&mut self, cx: &mut WindowContext) {
fn unmark_text(&self, cx: &mut WindowContext) {
self.view.update(cx, |view, cx| view.unmark_text(cx));
}
fn bounds_for_range(
&mut self,
&self,
range_utf16: Range<usize>,
cx: &mut WindowContext,
) -> Option<Bounds<Pixels>> {

View File

@@ -108,6 +108,10 @@ impl DispatchTree {
}
}
pub fn len(&self) -> usize {
self.nodes.len()
}
pub fn clear(&mut self) {
self.node_stack.clear();
self.context_stack.clear();

View File

@@ -430,30 +430,26 @@ pub trait InputHandler: 'static {
/// Corresponds to [selectedRange()](https://developer.apple.com/documentation/appkit/nstextinputclient/1438242-selectedrange)
///
/// Return value is in terms of UTF-16 characters, from 0 to the length of the document
fn selected_text_range(&mut self, cx: &mut WindowContext) -> Option<Range<usize>>;
fn selected_text_range(&self, cx: &mut WindowContext) -> Option<Range<usize>>;
/// Get the range of the currently marked text, if any
/// Corresponds to [markedRange()](https://developer.apple.com/documentation/appkit/nstextinputclient/1438250-markedrange)
///
/// Return value is in terms of UTF-16 characters, from 0 to the length of the document
fn marked_text_range(&mut self, cx: &mut WindowContext) -> Option<Range<usize>>;
fn marked_text_range(&self, cx: &mut WindowContext) -> Option<Range<usize>>;
/// Get the text for the given document range in UTF-16 characters
/// Corresponds to [attributedSubstring(forProposedRange: actualRange:)](https://developer.apple.com/documentation/appkit/nstextinputclient/1438238-attributedsubstring)
///
/// range_utf16 is in terms of UTF-16 characters
fn text_for_range(
&mut self,
range_utf16: Range<usize>,
cx: &mut WindowContext,
) -> Option<String>;
fn text_for_range(&self, range_utf16: Range<usize>, cx: &mut WindowContext) -> Option<String>;
/// Replace the text in the given document range with the given text
/// Corresponds to [insertText(_:replacementRange:)](https://developer.apple.com/documentation/appkit/nstextinputclient/1438258-inserttext)
///
/// replacement_range is in terms of UTF-16 characters
fn replace_text_in_range(
&mut self,
&self,
replacement_range: Option<Range<usize>>,
text: &str,
cx: &mut WindowContext,
@@ -466,7 +462,7 @@ pub trait InputHandler: 'static {
/// range_utf16 is in terms of UTF-16 characters
/// new_selected_range is in terms of UTF-16 characters
fn replace_and_mark_text_in_range(
&mut self,
&self,
range_utf16: Option<Range<usize>>,
new_text: &str,
new_selected_range: Option<Range<usize>>,
@@ -475,14 +471,14 @@ pub trait InputHandler: 'static {
/// Remove the IME 'composing' state from the document
/// Corresponds to [unmarkText()](https://developer.apple.com/documentation/appkit/nstextinputclient/1438239-unmarktext)
fn unmark_text(&mut self, cx: &mut WindowContext);
fn unmark_text(&self, cx: &mut WindowContext);
/// Get the bounds of the given document range in screen coordinates
/// Corresponds to [firstRect(forCharacterRange:actualRange:)](https://developer.apple.com/documentation/appkit/nstextinputclient/1438240-firstrect)
///
/// This is used for positioning the IME candidate window
fn bounds_for_range(
&mut self,
&self,
range_utf16: Range<usize>,
cx: &mut WindowContext,
) -> Option<Bounds<Pixels>>;

View File

@@ -1,16 +1,12 @@
use crate::{
point, AtlasTextureId, AtlasTile, Bounds, ContentMask, Corners, Edges, EntityId, Hsla, Pixels,
Point, ScaledPixels, StackingOrder,
Point, ScaledPixels,
};
use collections::{BTreeMap, FxHashSet};
use std::{fmt::Debug, iter::Peekable, slice};
#[allow(non_camel_case_types, unused)]
pub(crate) type PathVertex_ScaledPixels = PathVertex<ScaledPixels>;
pub(crate) type LayerId = u32;
pub(crate) type DrawOrder = u32;
#[derive(Default, Copy, Clone, Debug, Eq, PartialEq, Hash)]
#[repr(C)]
pub(crate) struct ViewId {
@@ -35,11 +31,20 @@ impl From<ViewId> for EntityId {
}
}
#[derive(Clone, Default)]
/// An index into all the geometry in a `Scene` at a point in time.
pub(crate) struct SceneIndex {
pub(crate) shadows: usize,
pub(crate) quads: usize,
pub(crate) paths: usize,
pub(crate) underlines: usize,
pub(crate) monochrome_sprites: usize,
pub(crate) polychrome_sprites: usize,
pub(crate) surfaces: usize,
}
#[derive(Default)]
pub(crate) struct Scene {
last_layer: Option<(StackingOrder, LayerId)>,
layers_by_order: BTreeMap<StackingOrder, LayerId>,
orders_by_layer: BTreeMap<LayerId, StackingOrder>,
pub(crate) shadows: Vec<Shadow>,
pub(crate) quads: Vec<Quad>,
pub(crate) paths: Vec<Path<ScaledPixels>>,
@@ -47,13 +52,11 @@ pub(crate) struct Scene {
pub(crate) monochrome_sprites: Vec<MonochromeSprite>,
pub(crate) polychrome_sprites: Vec<PolychromeSprite>,
pub(crate) surfaces: Vec<Surface>,
pub(crate) primitive_count: u32,
}
impl Scene {
pub fn clear(&mut self) {
self.last_layer = None;
self.layers_by_order.clear();
self.orders_by_layer.clear();
self.shadows.clear();
self.quads.clear();
self.paths.clear();
@@ -61,6 +64,19 @@ impl Scene {
self.monochrome_sprites.clear();
self.polychrome_sprites.clear();
self.surfaces.clear();
self.primitive_count = 0;
}
pub fn current_index(&self) -> SceneIndex {
SceneIndex {
shadows: self.shadows.len(),
quads: self.quads.len(),
paths: self.paths.len(),
underlines: self.underlines.len(),
monochrome_sprites: self.monochrome_sprites.len(),
polychrome_sprites: self.polychrome_sprites.len(),
surfaces: self.surfaces.len(),
}
}
pub fn paths(&self) -> &[Path<ScaledPixels>] {
@@ -93,8 +109,12 @@ impl Scene {
}
}
pub(crate) fn insert(&mut self, order: &StackingOrder, primitive: impl Into<Primitive>) {
let primitive = primitive.into();
pub(crate) fn paint_primitive<T: Into<Primitive>>(
&mut self,
build_primitive: impl FnOnce(u32) -> T,
) {
let primitive = build_primitive(self.primitive_count).into();
let clipped_bounds = primitive
.bounds()
.intersect(&primitive.content_mask().bounds);
@@ -104,150 +124,57 @@ impl Scene {
return;
}
let layer_id = self.layer_id_for_order(order);
match primitive {
Primitive::Shadow(mut shadow) => {
shadow.layer_id = layer_id;
self.shadows.push(shadow);
}
Primitive::Quad(mut quad) => {
quad.layer_id = layer_id;
self.quads.push(quad);
}
Primitive::Path(mut path) => {
path.layer_id = layer_id;
path.id = PathId(self.paths.len());
self.paths.push(path);
}
Primitive::Underline(mut underline) => {
underline.layer_id = layer_id;
self.underlines.push(underline);
}
Primitive::MonochromeSprite(mut sprite) => {
sprite.layer_id = layer_id;
self.monochrome_sprites.push(sprite);
}
Primitive::PolychromeSprite(mut sprite) => {
sprite.layer_id = layer_id;
self.polychrome_sprites.push(sprite);
}
Primitive::Surface(mut surface) => {
surface.layer_id = layer_id;
self.surfaces.push(surface);
}
}
self.primitive_count += 1;
}
fn layer_id_for_order(&mut self, order: &StackingOrder) -> LayerId {
if let Some((last_order, last_layer_id)) = self.last_layer.as_ref() {
if order == last_order {
return *last_layer_id;
}
}
let layer_id = if let Some(layer_id) = self.layers_by_order.get(order) {
*layer_id
} else {
let next_id = self.layers_by_order.len() as LayerId;
self.layers_by_order.insert(order.clone(), next_id);
self.orders_by_layer.insert(next_id, order.clone());
next_id
};
self.last_layer = Some((order.clone(), layer_id));
layer_id
}
pub fn reuse_views(&mut self, views: &FxHashSet<EntityId>, prev_scene: &mut Self) {
for shadow in prev_scene.shadows.drain(..) {
if views.contains(&shadow.view_id.into()) {
let order = &prev_scene.orders_by_layer[&shadow.layer_id];
self.insert(order, shadow);
}
}
for quad in prev_scene.quads.drain(..) {
if views.contains(&quad.view_id.into()) {
let order = &prev_scene.orders_by_layer[&quad.layer_id];
self.insert(order, quad);
}
}
for path in prev_scene.paths.drain(..) {
if views.contains(&path.view_id.into()) {
let order = &prev_scene.orders_by_layer[&path.layer_id];
self.insert(order, path);
}
}
for underline in prev_scene.underlines.drain(..) {
if views.contains(&underline.view_id.into()) {
let order = &prev_scene.orders_by_layer[&underline.layer_id];
self.insert(order, underline);
}
}
for sprite in prev_scene.monochrome_sprites.drain(..) {
if views.contains(&sprite.view_id.into()) {
let order = &prev_scene.orders_by_layer[&sprite.layer_id];
self.insert(order, sprite);
}
}
for sprite in prev_scene.polychrome_sprites.drain(..) {
if views.contains(&sprite.view_id.into()) {
let order = &prev_scene.orders_by_layer[&sprite.layer_id];
self.insert(order, sprite);
}
}
for surface in prev_scene.surfaces.drain(..) {
if views.contains(&surface.view_id.into()) {
let order = &prev_scene.orders_by_layer[&surface.layer_id];
self.insert(order, surface);
}
}
}
pub fn finish(&mut self) {
let mut orders = vec![0; self.layers_by_order.len()];
for (ix, layer_id) in self.layers_by_order.values().enumerate() {
orders[*layer_id as usize] = ix as u32;
}
for shadow in &mut self.shadows {
shadow.order = orders[shadow.layer_id as usize];
}
self.shadows.sort_by_key(|shadow| shadow.order);
for quad in &mut self.quads {
quad.order = orders[quad.layer_id as usize];
}
self.quads.sort_by_key(|quad| quad.order);
for path in &mut self.paths {
path.order = orders[path.layer_id as usize];
}
self.paths.sort_by_key(|path| path.order);
for underline in &mut self.underlines {
underline.order = orders[underline.layer_id as usize];
}
self.underlines.sort_by_key(|underline| underline.order);
for monochrome_sprite in &mut self.monochrome_sprites {
monochrome_sprite.order = orders[monochrome_sprite.layer_id as usize];
}
self.monochrome_sprites.sort_by_key(|sprite| sprite.order);
for polychrome_sprite in &mut self.polychrome_sprites {
polychrome_sprite.order = orders[polychrome_sprite.layer_id as usize];
}
self.polychrome_sprites.sort_by_key(|sprite| sprite.order);
for surface in &mut self.surfaces {
surface.order = orders[surface.layer_id as usize];
}
self.surfaces.sort_by_key(|surface| surface.order);
pub fn reuse_subscene(&mut self, prev_scene: &mut Self, start: SceneIndex, end: SceneIndex) {
self.shadows
.extend(prev_scene.shadows.drain(start.shadows..end.shadows));
self.quads
.extend(prev_scene.quads.drain(start.quads..end.quads));
self.paths
.extend(prev_scene.paths.drain(start.paths..end.paths));
self.underlines.extend(
prev_scene
.underlines
.drain(start.underlines..end.underlines),
);
self.monochrome_sprites.extend(
prev_scene
.monochrome_sprites
.drain(start.monochrome_sprites..end.monochrome_sprites),
);
self.polychrome_sprites.extend(
prev_scene
.polychrome_sprites
.drain(start.polychrome_sprites..end.polychrome_sprites),
);
self.surfaces
.extend(prev_scene.surfaces.drain(start.surfaces..end.surfaces));
}
}
@@ -281,25 +208,31 @@ impl<'a> Iterator for BatchIterator<'a> {
fn next(&mut self) -> Option<Self::Item> {
let mut orders_and_kinds = [
(
self.shadows_iter.peek().map(|s| s.order),
self.shadows_iter.peek().map(|s| s.draw_order),
PrimitiveKind::Shadow,
),
(self.quads_iter.peek().map(|q| q.order), PrimitiveKind::Quad),
(self.paths_iter.peek().map(|q| q.order), PrimitiveKind::Path),
(
self.underlines_iter.peek().map(|u| u.order),
self.quads_iter.peek().map(|q| q.draw_order),
PrimitiveKind::Quad,
),
(
self.paths_iter.peek().map(|q| q.draw_order),
PrimitiveKind::Path,
),
(
self.underlines_iter.peek().map(|u| u.draw_order),
PrimitiveKind::Underline,
),
(
self.monochrome_sprites_iter.peek().map(|s| s.order),
self.monochrome_sprites_iter.peek().map(|s| s.draw_order),
PrimitiveKind::MonochromeSprite,
),
(
self.polychrome_sprites_iter.peek().map(|s| s.order),
self.polychrome_sprites_iter.peek().map(|s| s.draw_order),
PrimitiveKind::PolychromeSprite,
),
(
self.surfaces_iter.peek().map(|s| s.order),
self.surfaces_iter.peek().map(|s| s.draw_order),
PrimitiveKind::Surface,
),
];
@@ -320,7 +253,7 @@ impl<'a> Iterator for BatchIterator<'a> {
self.shadows_iter.next();
while self
.shadows_iter
.next_if(|shadow| (shadow.order, batch_kind) < max_order_and_kind)
.next_if(|shadow| (shadow.draw_order, batch_kind) < max_order_and_kind)
.is_some()
{
shadows_end += 1;
@@ -336,7 +269,7 @@ impl<'a> Iterator for BatchIterator<'a> {
self.quads_iter.next();
while self
.quads_iter
.next_if(|quad| (quad.order, batch_kind) < max_order_and_kind)
.next_if(|quad| (quad.draw_order, batch_kind) < max_order_and_kind)
.is_some()
{
quads_end += 1;
@@ -350,7 +283,7 @@ impl<'a> Iterator for BatchIterator<'a> {
self.paths_iter.next();
while self
.paths_iter
.next_if(|path| (path.order, batch_kind) < max_order_and_kind)
.next_if(|path| (path.draw_order, batch_kind) < max_order_and_kind)
.is_some()
{
paths_end += 1;
@@ -364,7 +297,7 @@ impl<'a> Iterator for BatchIterator<'a> {
self.underlines_iter.next();
while self
.underlines_iter
.next_if(|underline| (underline.order, batch_kind) < max_order_and_kind)
.next_if(|underline| (underline.draw_order, batch_kind) < max_order_and_kind)
.is_some()
{
underlines_end += 1;
@@ -382,7 +315,7 @@ impl<'a> Iterator for BatchIterator<'a> {
while self
.monochrome_sprites_iter
.next_if(|sprite| {
(sprite.order, batch_kind) < max_order_and_kind
(sprite.draw_order, batch_kind) < max_order_and_kind
&& sprite.tile.texture_id == texture_id
})
.is_some()
@@ -403,7 +336,7 @@ impl<'a> Iterator for BatchIterator<'a> {
while self
.polychrome_sprites_iter
.next_if(|sprite| {
(sprite.order, batch_kind) < max_order_and_kind
(sprite.draw_order, batch_kind) < max_order_and_kind
&& sprite.tile.texture_id == texture_id
})
.is_some()
@@ -422,7 +355,7 @@ impl<'a> Iterator for BatchIterator<'a> {
self.surfaces_iter.next();
while self
.surfaces_iter
.next_if(|surface| (surface.order, batch_kind) < max_order_and_kind)
.next_if(|surface| (surface.draw_order, batch_kind) < max_order_and_kind)
.is_some()
{
surfaces_end += 1;
@@ -504,9 +437,7 @@ pub(crate) enum PrimitiveBatch<'a> {
#[derive(Default, Debug, Clone, Eq, PartialEq)]
#[repr(C)]
pub(crate) struct Quad {
pub view_id: ViewId,
pub layer_id: LayerId,
pub order: DrawOrder,
pub draw_order: u32,
pub bounds: Bounds<ScaledPixels>,
pub content_mask: ContentMask<ScaledPixels>,
pub background: Hsla,
@@ -517,7 +448,7 @@ pub(crate) struct Quad {
impl Ord for Quad {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.order.cmp(&other.order)
self.draw_order.cmp(&other.draw_order)
}
}
@@ -536,9 +467,7 @@ impl From<Quad> for Primitive {
#[derive(Debug, Clone, Eq, PartialEq)]
#[repr(C)]
pub(crate) struct Underline {
pub view_id: ViewId,
pub layer_id: LayerId,
pub order: DrawOrder,
pub draw_order: u32,
pub bounds: Bounds<ScaledPixels>,
pub content_mask: ContentMask<ScaledPixels>,
pub color: Hsla,
@@ -548,7 +477,7 @@ pub(crate) struct Underline {
impl Ord for Underline {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.order.cmp(&other.order)
self.draw_order.cmp(&other.draw_order)
}
}
@@ -567,9 +496,7 @@ impl From<Underline> for Primitive {
#[derive(Debug, Clone, Eq, PartialEq)]
#[repr(C)]
pub(crate) struct Shadow {
pub view_id: ViewId,
pub layer_id: LayerId,
pub order: DrawOrder,
pub draw_order: u32,
pub bounds: Bounds<ScaledPixels>,
pub corner_radii: Corners<ScaledPixels>,
pub content_mask: ContentMask<ScaledPixels>,
@@ -580,7 +507,7 @@ pub(crate) struct Shadow {
impl Ord for Shadow {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.order.cmp(&other.order)
self.draw_order.cmp(&other.draw_order)
}
}
@@ -599,30 +526,13 @@ impl From<Shadow> for Primitive {
#[derive(Clone, Debug, Eq, PartialEq)]
#[repr(C)]
pub(crate) struct MonochromeSprite {
pub view_id: ViewId,
pub layer_id: LayerId,
pub order: DrawOrder,
pub draw_order: u32,
pub bounds: Bounds<ScaledPixels>,
pub content_mask: ContentMask<ScaledPixels>,
pub color: Hsla,
pub tile: AtlasTile,
}
impl Ord for MonochromeSprite {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
match self.order.cmp(&other.order) {
std::cmp::Ordering::Equal => self.tile.tile_id.cmp(&other.tile.tile_id),
order => order,
}
}
}
impl PartialOrd for MonochromeSprite {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl From<MonochromeSprite> for Primitive {
fn from(sprite: MonochromeSprite) -> Self {
Primitive::MonochromeSprite(sprite)
@@ -632,9 +542,7 @@ impl From<MonochromeSprite> for Primitive {
#[derive(Clone, Debug, Eq, PartialEq)]
#[repr(C)]
pub(crate) struct PolychromeSprite {
pub view_id: ViewId,
pub layer_id: LayerId,
pub order: DrawOrder,
pub draw_order: u32,
pub bounds: Bounds<ScaledPixels>,
pub content_mask: ContentMask<ScaledPixels>,
pub corner_radii: Corners<ScaledPixels>,
@@ -643,21 +551,6 @@ pub(crate) struct PolychromeSprite {
pub pad: u32, // align to 8 bytes
}
impl Ord for PolychromeSprite {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
match self.order.cmp(&other.order) {
std::cmp::Ordering::Equal => self.tile.tile_id.cmp(&other.tile.tile_id),
order => order,
}
}
}
impl PartialOrd for PolychromeSprite {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl From<PolychromeSprite> for Primitive {
fn from(sprite: PolychromeSprite) -> Self {
Primitive::PolychromeSprite(sprite)
@@ -666,27 +559,13 @@ impl From<PolychromeSprite> for Primitive {
#[derive(Clone, Debug, Eq, PartialEq)]
pub(crate) struct Surface {
pub view_id: ViewId,
pub layer_id: LayerId,
pub order: DrawOrder,
pub draw_order: u32,
pub bounds: Bounds<ScaledPixels>,
pub content_mask: ContentMask<ScaledPixels>,
#[cfg(target_os = "macos")]
pub image_buffer: media::core_video::CVImageBuffer,
}
impl Ord for Surface {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.order.cmp(&other.order)
}
}
impl PartialOrd for Surface {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl From<Surface> for Primitive {
fn from(surface: Surface) -> Self {
Primitive::Surface(surface)
@@ -699,10 +578,8 @@ pub(crate) struct PathId(pub(crate) usize);
/// A line made up of a series of vertices and control points.
#[derive(Debug)]
pub struct Path<P: Clone + Default + Debug> {
pub(crate) draw_order: u32,
pub(crate) id: PathId,
pub(crate) view_id: ViewId,
layer_id: LayerId,
order: DrawOrder,
pub(crate) bounds: Bounds<P>,
pub(crate) content_mask: ContentMask<P>,
pub(crate) vertices: Vec<PathVertex<P>>,
@@ -716,10 +593,8 @@ impl Path<Pixels> {
/// Create a new path with the given starting point.
pub fn new(start: Point<Pixels>) -> Self {
Self {
draw_order: 0,
id: PathId(0),
view_id: ViewId::default(),
layer_id: LayerId::default(),
order: DrawOrder::default(),
vertices: Vec::new(),
start,
current: start,
@@ -736,10 +611,8 @@ impl Path<Pixels> {
/// Scale this path by the given factor.
pub fn scale(&self, factor: f32) -> Path<ScaledPixels> {
Path {
draw_order: self.draw_order,
id: self.id,
view_id: self.view_id,
layer_id: self.layer_id,
order: self.order,
bounds: self.bounds.scale(factor),
content_mask: self.content_mask.scale(factor),
vertices: self
@@ -825,13 +698,13 @@ impl Eq for Path<ScaledPixels> {}
impl PartialEq for Path<ScaledPixels> {
fn eq(&self, other: &Self) -> bool {
self.order == other.order
self.draw_order == other.draw_order
}
}
impl Ord for Path<ScaledPixels> {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.order.cmp(&other.order)
self.draw_order.cmp(&other.draw_order)
}
}

View File

@@ -1,14 +1,15 @@
use crate::{
seal::Sealed, AnyElement, AnyModel, AnyWeakModel, AppContext, AvailableSpace, Bounds,
ContentMask, Element, ElementContext, ElementId, Entity, EntityId, Flatten, FocusHandle,
FocusableView, IntoElement, LayoutId, Model, Pixels, Point, Render, Size, StackingOrder, Style,
TextStyle, ViewContext, VisualContext, WeakModel,
FocusableView, FrameIndex, IntoElement, LayoutId, Model, Pixels, Point, Render, Size,
StackingOrder, Style, TextStyle, ViewContext, VisualContext, WeakModel,
};
use anyhow::{Context, Result};
use std::{
any::{type_name, TypeId},
fmt,
hash::{Hash, Hasher},
ops::Range,
};
/// A view is a piece of state that can be presented on screen by implementing the [Render] trait.
@@ -24,15 +25,16 @@ impl<V> Sealed for View<V> {}
pub struct AnyViewState {
root_style: Style,
next_stacking_order_id: u16,
cache_key: Option<ViewCacheKey>,
cache_state: Option<ViewCacheState>,
element: Option<AnyElement>,
}
struct ViewCacheKey {
struct ViewCacheState {
bounds: Bounds<Pixels>,
stacking_order: StackingOrder,
content_mask: ContentMask<Pixels>,
text_style: TextStyle,
subframe_range: Range<FrameIndex>,
}
impl<V: 'static> Entity<V> for View<V> {
@@ -297,7 +299,7 @@ impl Element for AnyView {
let state = AnyViewState {
root_style,
next_stacking_order_id: 0,
cache_key: None,
cache_state: None,
element: Some(element),
};
(layout_id, state)
@@ -311,23 +313,25 @@ impl Element for AnyView {
return;
}
if let Some(cache_key) = state.cache_key.as_mut() {
if cache_key.bounds == bounds
&& cache_key.content_mask == cx.content_mask()
&& cache_key.stacking_order == *cx.stacking_order()
&& cache_key.text_style == cx.text_style()
if let Some(cache_state) = state.cache_state.as_mut() {
if cache_state.bounds == bounds
&& cache_state.content_mask == cx.content_mask()
&& cache_state.stacking_order == *cx.stacking_order()
&& cache_state.text_style == cx.text_style()
{
cx.reuse_view(state.next_stacking_order_id);
cx.reuse_view(cache_state.subframe_range.clone());
return;
}
}
let subframe_start = cx.window.next_frame.current_index();
if let Some(mut element) = state.element.take() {
element.paint(cx);
} else {
let mut element = (self.request_layout)(self, cx).1;
element.draw(bounds.origin, bounds.size.into(), cx);
}
let subframe_end = cx.window.next_frame.current_index();
state.next_stacking_order_id = cx
.window
@@ -336,11 +340,12 @@ impl Element for AnyView {
.last()
.copied()
.unwrap();
state.cache_key = Some(ViewCacheKey {
state.cache_state = Some(ViewCacheState {
bounds,
stacking_order: cx.stacking_order().clone(),
content_mask: cx.content_mask(),
text_style: cx.text_style(),
subframe_range: subframe_start..subframe_end,
});
})
}

View File

@@ -1,8 +1,8 @@
use crate::{
px, size, transparent_black, Action, AnyDrag, AnyView, AppContext, Arena, AsyncWindowContext,
AvailableSpace, Bounds, Context, Corners, CursorStyle, DispatchActionListener, DispatchNodeId,
DispatchTree, DisplayId, Edges, Effect, Entity, EntityId, EventEmitter, FileDropEvent, Flatten,
Global, GlobalElementId, Hsla, KeyBinding, KeyContext, KeyDownEvent, KeyMatch, KeymatchResult,
frame::ActionListener, px, size, transparent_black, Action, AnyDrag, AnyView, AppContext,
Arena, AsyncWindowContext, AvailableSpace, Bounds, Context, Corners, CursorStyle, DisplayId,
Edges, Effect, Entity, EntityId, EventEmitter, FileDropEvent, Flatten, Frame, Global,
GlobalElementId, Hsla, KeyBinding, KeyContext, KeyDownEvent, KeyMatch, KeymatchResult,
Keystroke, KeystrokeEvent, Model, ModelContext, Modifiers, MouseButton, MouseMoveEvent,
MouseUpEvent, Pixels, PlatformAtlas, PlatformDisplay, PlatformInput, PlatformWindow, Point,
PromptLevel, Render, ScaledPixels, SharedString, Size, SubscriberSet, Subscription,
@@ -126,10 +126,7 @@ impl FocusId {
/// Obtains whether this handle contains the given handle in the most recently rendered frame.
pub(crate) fn contains(&self, other: Self, cx: &WindowContext) -> bool {
cx.window
.rendered_frame
.dispatch_tree
.focus_contains(*self, other)
cx.window.rendered_frame.focus_contains(*self, other)
}
}
@@ -314,13 +311,6 @@ impl PendingInput {
}
}
pub(crate) struct ElementStateBox {
pub(crate) inner: Box<dyn Any>,
pub(crate) parent_view_id: EntityId,
#[cfg(debug_assertions)]
pub(crate) type_name: &'static str,
}
impl Window {
pub(crate) fn new(
handle: AnyWindowHandle,
@@ -449,8 +439,8 @@ impl Window {
layout_engine: Some(TaffyLayoutEngine::new()),
root_view: None,
element_id_stack: GlobalElementId::default(),
rendered_frame: Frame::new(DispatchTree::new(cx.keymap.clone(), cx.actions.clone())),
next_frame: Frame::new(DispatchTree::new(cx.keymap.clone(), cx.actions.clone())),
rendered_frame: Frame::new(cx.keymap.clone(), cx.actions.clone()),
next_frame: Frame::new(cx.keymap.clone(), cx.actions.clone()),
next_frame_callbacks,
dirty_views: FxHashSet::default(),
focus_handles: Arc::new(RwLock::new(SlotMap::with_key())),
@@ -561,10 +551,7 @@ impl<'a> WindowContext<'a> {
}
self.window.focus = Some(handle.id);
self.window
.rendered_frame
.dispatch_tree
.clear_pending_keystrokes();
self.window.rendered_frame.clear_pending_keystrokes();
self.refresh();
}
@@ -591,20 +578,10 @@ impl<'a> WindowContext<'a> {
/// Dispatch the given action on the currently focused element.
pub fn dispatch_action(&mut self, action: Box<dyn Action>) {
let focus_handle = self.focused();
let focus_id = self.window.focus;
self.defer(move |cx| {
let node_id = focus_handle
.and_then(|handle| {
cx.window
.rendered_frame
.dispatch_tree
.focusable_node_id(handle.id)
})
.unwrap_or_else(|| cx.window.rendered_frame.dispatch_tree.root_node_id());
cx.propagate_event = true;
cx.dispatch_action_on_node(node_id, action);
cx.dispatch_action_on(focus_id, action);
})
}
@@ -632,14 +609,8 @@ impl<'a> WindowContext<'a> {
}
pub(crate) fn clear_pending_keystrokes(&mut self) {
self.window
.rendered_frame
.dispatch_tree
.clear_pending_keystrokes();
self.window
.next_frame
.dispatch_tree
.clear_pending_keystrokes();
self.window.rendered_frame.clear_pending_keystrokes();
self.window.next_frame.clear_pending_keystrokes();
}
/// Schedules the given function to be run at the end of the current effect cycle, allowing entities
@@ -834,19 +805,9 @@ impl<'a> WindowContext<'a> {
/// Determine whether the given action is available along the dispatch path to the currently focused element.
pub fn is_action_available(&self, action: &dyn Action) -> bool {
let target = self
.focused()
.and_then(|focused_handle| {
self.window
.rendered_frame
.dispatch_tree
.focusable_node_id(focused_handle.id)
})
.unwrap_or_else(|| self.window.rendered_frame.dispatch_tree.root_node_id());
self.window
.rendered_frame
.dispatch_tree
.is_action_available(action, target)
.is_action_available(action, self.window.focus)
}
/// The position of the mouse relative to the window.
@@ -863,36 +824,38 @@ impl<'a> WindowContext<'a> {
/// on top of the given level. Layers who are extensions of the queried layer
/// are not considered to be on top of queried layer.
pub fn was_top_layer(&self, point: &Point<Pixels>, layer: &StackingOrder) -> bool {
// Precondition: the depth map is ordered from topmost to bottomost.
todo!()
for (opaque_layer, _, bounds) in self.window.rendered_frame.depth_map.iter() {
if layer >= opaque_layer {
// The queried layer is either above or is the same as the this opaque layer.
// Anything after this point is guaranteed to be below the queried layer.
return true;
}
// // Precondition: the depth map is ordered from topmost to bottomost.
if !bounds.contains(point) {
// This opaque layer is above the queried layer but it doesn't contain
// the given position, so we can ignore it even if it's above.
continue;
}
// for (opaque_layer, _, bounds) in self.window.rendered_frame.depth_map.iter() {
// if layer >= opaque_layer {
// // The queried layer is either above or is the same as the this opaque layer.
// // Anything after this point is guaranteed to be below the queried layer.
// return true;
// }
// At this point, we've established that this opaque layer is on top of the queried layer
// and contains the position:
// If neither the opaque layer or the queried layer is an extension of the other then
// we know they are on different stacking orders, and return false.
let is_on_same_layer = opaque_layer
.iter()
.zip(layer.iter())
.all(|(a, b)| a.z_index == b.z_index);
// if !bounds.contains(point) {
// // This opaque layer is above the queried layer but it doesn't contain
// // the given position, so we can ignore it even if it's above.
// continue;
// }
if !is_on_same_layer {
return false;
}
}
// // At this point, we've established that this opaque layer is on top of the queried layer
// // and contains the position:
// // If neither the opaque layer or the queried layer is an extension of the other then
// // we know they are on different stacking orders, and return false.
// let is_on_same_layer = opaque_layer
// .iter()
// .zip(layer.iter())
// .all(|(a, b)| a.z_index == b.z_index);
true
// if !is_on_same_layer {
// return false;
// }
// }
// true
}
pub(crate) fn was_top_layer_under_active_drag(
@@ -900,52 +863,53 @@ impl<'a> WindowContext<'a> {
point: &Point<Pixels>,
layer: &StackingOrder,
) -> bool {
todo!()
// Precondition: the depth map is ordered from topmost to bottomost.
for (opaque_layer, _, bounds) in self.window.rendered_frame.depth_map.iter() {
if layer >= opaque_layer {
// The queried layer is either above or is the same as the this opaque layer.
// Anything after this point is guaranteed to be below the queried layer.
return true;
}
// for (opaque_layer, _, bounds) in self.window.rendered_frame.depth_map.iter() {
// if layer >= opaque_layer {
// // The queried layer is either above or is the same as the this opaque layer.
// // Anything after this point is guaranteed to be below the queried layer.
// return true;
// }
if !bounds.contains(point) {
// This opaque layer is above the queried layer but it doesn't contain
// the given position, so we can ignore it even if it's above.
continue;
}
// if !bounds.contains(point) {
// // This opaque layer is above the queried layer but it doesn't contain
// // the given position, so we can ignore it even if it's above.
// continue;
// }
// All normal content is rendered with a base z-index of 0, we know that if the root of this opaque layer
// equals `ACTIVE_DRAG_Z_INDEX` then it must be the drag layer and we can ignore it as we are
// looking to see if the queried layer was the topmost underneath the drag layer.
if opaque_layer
.first()
.map(|c| c.z_index == ACTIVE_DRAG_Z_INDEX)
.unwrap_or(false)
{
continue;
}
// // All normal content is rendered with a base z-index of 0, we know that if the root of this opaque layer
// // equals `ACTIVE_DRAG_Z_INDEX` then it must be the drag layer and we can ignore it as we are
// // looking to see if the queried layer was the topmost underneath the drag layer.
// if opaque_layer
// .first()
// .map(|c| c.z_index == ACTIVE_DRAG_Z_INDEX)
// .unwrap_or(false)
// {
// continue;
// }
// At this point, we've established that this opaque layer is on top of the queried layer
// and contains the position:
// If neither the opaque layer or the queried layer is an extension of the other then
// we know they are on different stacking orders, and return false.
let is_on_same_layer = opaque_layer
.iter()
.zip(layer.iter())
.all(|(a, b)| a.z_index == b.z_index);
// // At this point, we've established that this opaque layer is on top of the queried layer
// // and contains the position:
// // If neither the opaque layer or the queried layer is an extension of the other then
// // we know they are on different stacking orders, and return false.
// let is_on_same_layer = opaque_layer
// .iter()
// .zip(layer.iter())
// .all(|(a, b)| a.z_index == b.z_index);
if !is_on_same_layer {
return false;
}
}
// if !is_on_same_layer {
// return false;
// }
// }
true
// true
}
/// Called during painting to get the current stacking order.
pub fn stacking_order(&self) -> &StackingOrder {
&self.window.next_frame.z_index_stack
todo!()
}
/// Produces a new frame and assigns it to `rendered_frame`. To actually show
@@ -954,12 +918,6 @@ impl<'a> WindowContext<'a> {
self.window.dirty.set(false);
self.window.drawing = true;
if let Some(requested_handler) = self.window.rendered_frame.requested_input_handler.as_mut()
{
let input_handler = self.window.platform_window.take_input_handler();
requested_handler.handler = input_handler;
}
let root_view = self.window.root_view.take().unwrap();
self.with_element_context(|cx| {
cx.with_z_index(0, |cx| {
@@ -967,7 +925,7 @@ impl<'a> WindowContext<'a> {
// We need to use cx.cx here so we can utilize borrow splitting
for (action_type, action_listeners) in &cx.cx.app.global_action_listeners {
for action_listener in action_listeners.iter().cloned() {
cx.cx.window.next_frame.dispatch_tree.on_action(
cx.cx.window.next_frame.on_action(
*action_type,
Rc::new(
move |action: &dyn Any, phase, cx: &mut WindowContext<'_>| {
@@ -1010,15 +968,14 @@ impl<'a> WindowContext<'a> {
}
self.window.dirty_views.clear();
self.window.next_frame.preserve_pending_keystrokes(
&mut self.window.rendered_frame.dispatch_tree,
self.window.focus,
);
self.window.next_frame.set_focus(self.window.focus);
self.window
.next_frame
.dispatch_tree
.preserve_pending_keystrokes(
&mut self.window.rendered_frame.dispatch_tree,
self.window.focus,
);
self.window.next_frame.focus = self.window.focus;
self.window.next_frame.window_active = self.window.active.get();
.set_window_active(self.window.active.get());
self.window.root_view = Some(root_view);
// Set the cursor only if we're the active window.
@@ -1042,9 +999,10 @@ impl<'a> WindowContext<'a> {
self.window.layout_engine.as_mut().unwrap().clear();
self.text_system()
.finish_frame(&self.window.next_frame.reused_views);
self.window
.next_frame
.finish(&mut self.window.rendered_frame);
// todo!()
// self.window
// .next_frame
// .finish(&mut self.window.rendered_frame);
ELEMENT_ARENA.with_borrow_mut(|element_arena| {
let percentage = (element_arena.len() as f32 / element_arena.capacity() as f32) * 100.;
if percentage >= 80. {
@@ -1226,56 +1184,54 @@ impl<'a> WindowContext<'a> {
}
fn dispatch_mouse_event(&mut self, event: &dyn Any) {
if let Some(mut handlers) = self
.window
.rendered_frame
.mouse_listeners
.remove(&event.type_id())
{
// Because handlers may add other handlers, we sort every time.
handlers.sort_by(|(a, _, _), (b, _, _)| a.cmp(b));
todo!()
// if let Some(mut handlers) = self
// .window
// .rendered_frame
// .mouse_listeners
// .remove(&event.type_id())
// {
// // Capture phase, events bubble from back to front. Handlers for this phase are used for
// // special purposes, such as detecting events outside of a given Bounds.
// for (_, _, handler) in &mut handlers {
// self.with_element_context(|cx| {
// handler(event, DispatchPhase::Capture, cx);
// });
// if !self.app.propagate_event {
// break;
// }
// }
// Capture phase, events bubble from back to front. Handlers for this phase are used for
// special purposes, such as detecting events outside of a given Bounds.
for (_, _, handler) in &mut handlers {
self.with_element_context(|cx| {
handler(event, DispatchPhase::Capture, cx);
});
if !self.app.propagate_event {
break;
}
}
// // Bubble phase, where most normal handlers do their work.
// if self.app.propagate_event {
// for (_, _, handler) in handlers.iter_mut().rev() {
// self.with_element_context(|cx| {
// handler(event, DispatchPhase::Bubble, cx);
// });
// if !self.app.propagate_event {
// break;
// }
// }
// }
// Bubble phase, where most normal handlers do their work.
if self.app.propagate_event {
for (_, _, handler) in handlers.iter_mut().rev() {
self.with_element_context(|cx| {
handler(event, DispatchPhase::Bubble, cx);
});
if !self.app.propagate_event {
break;
}
}
}
// self.window
// .rendered_frame
// .mouse_listeners
// .insert(event.type_id(), handlers);
// }
self.window
.rendered_frame
.mouse_listeners
.insert(event.type_id(), handlers);
}
if self.app.propagate_event && self.has_active_drag() {
if event.is::<MouseMoveEvent>() {
// If this was a mouse move event, redraw the window so that the
// active drag can follow the mouse cursor.
self.refresh();
} else if event.is::<MouseUpEvent>() {
// If this was a mouse up event, cancel the active drag and redraw
// the window.
self.active_drag = None;
self.refresh();
}
}
// if self.app.propagate_event && self.has_active_drag() {
// if event.is::<MouseMoveEvent>() {
// // If this was a mouse move event, redraw the window so that the
// // active drag can follow the mouse cursor.
// self.refresh();
// } else if event.is::<MouseUpEvent>() {
// // If this was a mouse up event, cancel the active drag and redraw
// // the window.
// self.active_drag = None;
// self.refresh();
// }
// }
}
fn dispatch_key_event(&mut self, event: &dyn Any) {
@@ -1283,29 +1239,14 @@ impl<'a> WindowContext<'a> {
self.draw();
}
let node_id = self
.window
.focus
.and_then(|focus_id| {
self.window
.rendered_frame
.dispatch_tree
.focusable_node_id(focus_id)
})
.unwrap_or_else(|| self.window.rendered_frame.dispatch_tree.root_node_id());
let dispatch_path = self
.window
.rendered_frame
.dispatch_tree
.dispatch_path(node_id);
let focus_id = self.window.focus;
let dispatch_path = self.window.rendered_frame.key_dispatch_path(focus_id);
if let Some(key_down_event) = event.downcast_ref::<KeyDownEvent>() {
let KeymatchResult { bindings, pending } = self
.window
.rendered_frame
.dispatch_tree
.dispatch_key(&key_down_event.keystroke, &dispatch_path);
.match_keystroke(&key_down_event.keystroke, focus_id);
if pending {
let mut currently_pending = self.window.pending_input.take().unwrap_or_default();
@@ -1335,8 +1276,11 @@ impl<'a> WindowContext<'a> {
self.window.pending_input = Some(currently_pending);
self.propagate_event = false;
return;
} else if let Some(currently_pending) = self.window.pending_input.take() {
}
if let Some(currently_pending) = self.window.pending_input.take() {
if bindings
.iter()
.all(|binding| !currently_pending.used_by_binding(binding))
@@ -1351,7 +1295,7 @@ impl<'a> WindowContext<'a> {
self.propagate_event = true;
for binding in bindings {
self.dispatch_action_on_node(node_id, binding.action.boxed_clone());
self.dispatch_action_on(focus_id, binding.action.boxed_clone());
if !self.propagate_event {
self.dispatch_keystroke_observers(event, Some(binding.action));
return;
@@ -1359,7 +1303,7 @@ impl<'a> WindowContext<'a> {
}
}
self.dispatch_key_down_up_event(event, &dispatch_path);
self.dispatch_key_down_up_event(event, focus_id);
if !self.propagate_event {
return;
}
@@ -1367,61 +1311,37 @@ impl<'a> WindowContext<'a> {
self.dispatch_keystroke_observers(event, None);
}
fn dispatch_key_down_up_event(
&mut self,
event: &dyn Any,
dispatch_path: &SmallVec<[DispatchNodeId; 32]>,
) {
fn dispatch_key_down_up_event(&mut self, event: &dyn Any, focus_id: Option<FocusId>) {
// Capture phase
for node_id in dispatch_path {
let node = self.window.rendered_frame.dispatch_tree.node(*node_id);
for key_listener in node.key_listeners.clone() {
self.with_element_context(|cx| {
key_listener(event, DispatchPhase::Capture, cx);
});
if !self.propagate_event {
return;
}
let key_dispatch_path = self.window.rendered_frame.key_dispatch_path(focus_id);
for key_listener in &key_dispatch_path {
self.with_element_context(|cx| {
key_listener(event, DispatchPhase::Capture, cx);
});
if !self.propagate_event {
return;
}
}
// Bubble phase
for node_id in dispatch_path.iter().rev() {
// Handle low level key events
let node = self.window.rendered_frame.dispatch_tree.node(*node_id);
for key_listener in node.key_listeners.clone() {
self.with_element_context(|cx| {
key_listener(event, DispatchPhase::Bubble, cx);
});
if !self.propagate_event {
return;
}
for key_listener in key_dispatch_path.iter().rev() {
self.with_element_context(|cx| {
key_listener(event, DispatchPhase::Bubble, cx);
});
if !self.propagate_event {
return;
}
}
}
/// Determine whether a potential multi-stroke key binding is in progress on this window.
pub fn has_pending_keystrokes(&self) -> bool {
self.window
.rendered_frame
.dispatch_tree
.has_pending_keystrokes()
self.window.rendered_frame.has_pending_keystrokes()
}
fn replay_pending_input(&mut self, currently_pending: PendingInput) {
let node_id = self
.window
.focus
.and_then(|focus_id| {
self.window
.rendered_frame
.dispatch_tree
.focusable_node_id(focus_id)
})
.unwrap_or_else(|| self.window.rendered_frame.dispatch_tree.root_node_id());
if self.window.focus != currently_pending.focus {
let focus_id = self.window.focus;
if focus_id != currently_pending.focus {
return;
}
@@ -1429,25 +1349,19 @@ impl<'a> WindowContext<'a> {
self.propagate_event = true;
for binding in currently_pending.bindings {
self.dispatch_action_on_node(node_id, binding.action.boxed_clone());
self.dispatch_action_on(focus_id, binding.action.boxed_clone());
if !self.propagate_event {
return;
}
}
let dispatch_path = self
.window
.rendered_frame
.dispatch_tree
.dispatch_path(node_id);
for keystroke in currently_pending.keystrokes {
let event = KeyDownEvent {
keystroke,
is_held: false,
};
self.dispatch_key_down_up_event(&event, &dispatch_path);
self.dispatch_key_down_up_event(&event, focus_id);
if !self.propagate_event {
return;
}
@@ -1461,52 +1375,43 @@ impl<'a> WindowContext<'a> {
}
}
fn dispatch_action_on_node(&mut self, node_id: DispatchNodeId, action: Box<dyn Action>) {
let dispatch_path = self
.window
.rendered_frame
.dispatch_tree
.dispatch_path(node_id);
fn dispatch_action_on(&mut self, focus_id: Option<FocusId>, action: Box<dyn Action>) {
let dispatch_path = self.window.rendered_frame.action_dispatch_path(focus_id);
// Capture phase
for node_id in &dispatch_path {
let node = self.window.rendered_frame.dispatch_tree.node(*node_id);
for DispatchActionListener {
action_type,
listener,
} in node.action_listeners.clone()
{
let any_action = action.as_any();
if action_type == any_action.type_id() {
self.with_element_context(|cx| {
listener(any_action, DispatchPhase::Capture, cx);
});
for ActionListener {
action_type,
listener,
} in &dispatch_path
{
let any_action = action.as_any();
if *action_type == any_action.type_id() {
self.with_element_context(|cx| {
listener(any_action, DispatchPhase::Capture, cx);
});
if !self.propagate_event {
return;
}
if !self.propagate_event {
return;
}
}
}
// Bubble phase
for node_id in dispatch_path.iter().rev() {
let node = self.window.rendered_frame.dispatch_tree.node(*node_id);
for DispatchActionListener {
action_type,
listener,
} in node.action_listeners.clone()
{
let any_action = action.as_any();
if action_type == any_action.type_id() {
self.propagate_event = false; // Actions stop propagation by default during the bubble phase
for ActionListener {
action_type,
listener,
} in dispatch_path.iter().rev()
{
let any_action = action.as_any();
if *action_type == any_action.type_id() {
self.propagate_event = false; // Actions stop propagation by default during the bubble phase
self.with_element_context(|cx| {
listener(any_action, DispatchPhase::Bubble, cx);
});
self.with_element_context(|cx| {
listener(any_action, DispatchPhase::Bubble, cx);
});
if !self.propagate_event {
return;
}
if !self.propagate_event {
return;
}
}
}
@@ -1567,32 +1472,16 @@ impl<'a> WindowContext<'a> {
/// Returns all available actions for the focused element.
pub fn available_actions(&self) -> Vec<Box<dyn Action>> {
let node_id = self
.window
.focus
.and_then(|focus_id| {
self.window
.rendered_frame
.dispatch_tree
.focusable_node_id(focus_id)
})
.unwrap_or_else(|| self.window.rendered_frame.dispatch_tree.root_node_id());
self.window
.rendered_frame
.dispatch_tree
.available_actions(node_id)
.available_actions(self.window.focus)
}
/// Returns key bindings that invoke the given action on the currently focused element.
pub fn bindings_for_action(&self, action: &dyn Action) -> Vec<KeyBinding> {
self.window
.rendered_frame
.dispatch_tree
.bindings_for_action(
action,
&self.window.rendered_frame.dispatch_tree.context_stack,
)
.bindings_for_action(action, self.window.focus)
}
/// Returns any bindings that would invoke the given action on the given focus handle if it were focused.
@@ -1601,17 +1490,9 @@ impl<'a> WindowContext<'a> {
action: &dyn Action,
focus_handle: &FocusHandle,
) -> Vec<KeyBinding> {
let dispatch_tree = &self.window.rendered_frame.dispatch_tree;
let Some(node_id) = dispatch_tree.focusable_node_id(focus_handle.id) else {
return vec![];
};
let context_stack: Vec<_> = dispatch_tree
.dispatch_path(node_id)
.into_iter()
.filter_map(|node_id| dispatch_tree.node(node_id).context.clone())
.collect();
dispatch_tree.bindings_for_action(action, &context_stack)
self.window
.rendered_frame
.bindings_for_action(action, Some(focus_handle.id))
}
/// Returns a generic event listener that invokes the given listener with the view and context associated with the given view handle.
@@ -1647,15 +1528,6 @@ impl<'a> WindowContext<'a> {
.on_should_close(Box::new(move || this.update(|cx| f(cx)).unwrap_or(true)))
}
pub(crate) fn parent_view_id(&self) -> EntityId {
*self
.window
.next_frame
.view_stack
.last()
.expect("a view should always be on the stack while drawing")
}
/// Register an action listener on the window for the next frame. The type of action
/// is determined by the first parameter of the given listener. When the next frame is rendered
/// the listener will be cleared.
@@ -1669,7 +1541,6 @@ impl<'a> WindowContext<'a> {
) {
self.window
.next_frame
.dispatch_tree
.on_action(action_type, Rc::new(listener));
}
}
@@ -2081,7 +1952,6 @@ impl<'a, V: 'static> ViewContext<'a, V> {
for view_id in self
.window
.rendered_frame
.dispatch_tree
.view_path(self.view.entity_id())
.into_iter()
.rev()

View File

@@ -16,12 +16,13 @@ use std::{
any::{Any, TypeId},
borrow::{Borrow, BorrowMut, Cow},
mem,
ops::Range,
rc::Rc,
sync::Arc,
};
use anyhow::Result;
use collections::{FxHashMap, FxHashSet};
use collections::FxHashMap;
use derive_more::{Deref, DerefMut};
#[cfg(target_os = "macos")]
use media::core_video::CVImageBuffer;
@@ -34,132 +35,135 @@ use crate::{
EntityId, FocusHandle, FocusId, FontId, GlobalElementId, GlyphId, Hsla, ImageData,
InputHandler, IsZero, KeyContext, KeyEvent, LayoutId, MonochromeSprite, MouseEvent, PaintQuad,
Path, Pixels, PlatformInputHandler, Point, PolychromeSprite, Quad, RenderGlyphParams,
RenderImageParams, RenderSvgParams, Scene, Shadow, SharedString, Size, StackingContext,
StackingOrder, StrikethroughStyle, Style, TextStyleRefinement, Underline, UnderlineStyle,
Window, WindowContext, SUBPIXEL_VARIANTS,
RenderImageParams, RenderSvgParams, Scene, SceneIndex, Shadow, SharedString, Size,
StackingContext, StackingOrder, StrikethroughStyle, Style, TextStyleRefinement, Underline,
UnderlineStyle, Window, WindowContext, SUBPIXEL_VARIANTS,
};
type AnyMouseListener = Box<dyn FnMut(&dyn Any, DispatchPhase, &mut ElementContext) + 'static>;
pub(crate) struct RequestedInputHandler {
pub(crate) view_id: EntityId,
pub(crate) handler: Option<PlatformInputHandler>,
}
pub(crate) struct TooltipRequest {
pub(crate) view_id: EntityId,
pub(crate) tooltip: AnyTooltip,
}
pub(crate) struct Frame {
pub(crate) focus: Option<FocusId>,
pub(crate) window_active: bool,
pub(crate) element_states: FxHashMap<GlobalElementId, ElementStateBox>,
pub(crate) mouse_listeners: FxHashMap<TypeId, Vec<(StackingOrder, EntityId, AnyMouseListener)>>,
pub(crate) dispatch_tree: DispatchTree,
pub(crate) scene: Scene,
pub(crate) depth_map: Vec<(StackingOrder, EntityId, Bounds<Pixels>)>,
pub(crate) z_index_stack: StackingOrder,
pub(crate) next_stacking_order_ids: Vec<u16>,
pub(crate) next_root_z_index: u16,
pub(crate) content_mask_stack: Vec<ContentMask<Pixels>>,
pub(crate) element_offset_stack: Vec<Point<Pixels>>,
pub(crate) requested_input_handler: Option<RequestedInputHandler>,
pub(crate) tooltip_request: Option<TooltipRequest>,
pub(crate) cursor_styles: FxHashMap<EntityId, CursorStyle>,
pub(crate) requested_cursor_style: Option<CursorStyle>,
pub(crate) view_stack: Vec<EntityId>,
pub(crate) reused_views: FxHashSet<EntityId>,
#[cfg(any(test, feature = "test-support"))]
pub(crate) debug_bounds: FxHashMap<String, Bounds<Pixels>>,
/// Identifies a moment in time during construction of a frame. Used for reusing cached subsets of a previous frame.
#[derive(Clone)]
pub(crate) struct FrameIndex {
mouse_listeners: usize,
dispatch_nodes: usize,
scene_index: SceneIndex,
}
impl Frame {
pub(crate) fn new(dispatch_tree: DispatchTree) -> Self {
Frame {
focus: None,
window_active: false,
element_states: FxHashMap::default(),
mouse_listeners: FxHashMap::default(),
dispatch_tree,
scene: Scene::default(),
depth_map: Vec::new(),
z_index_stack: StackingOrder::default(),
next_stacking_order_ids: vec![0],
next_root_z_index: 0,
content_mask_stack: Vec::new(),
element_offset_stack: Vec::new(),
requested_input_handler: None,
tooltip_request: None,
cursor_styles: FxHashMap::default(),
requested_cursor_style: None,
view_stack: Vec::new(),
reused_views: FxHashSet::default(),
// pub(crate) struct Frame {
// pub(crate) focus: Option<FocusId>,
// pub(crate) window_active: bool,
// pub(crate) element_states: FxHashMap<GlobalElementId, ElementStateBox>,
// pub(crate) mouse_listeners: FxHashMap<TypeId, Vec<(StackingOrder, EntityId, AnyMouseListener)>>,
// pub(crate) input_handlers: Vec<PlatformInputHandler>,
// pub(crate) dispatch_tree: DispatchTree,
// pub(crate) scene: Scene,
// pub(crate) depth_map: Vec<(StackingOrder, EntityId, Bounds<Pixels>)>,
// pub(crate) z_index_stack: StackingOrder,
// pub(crate) next_stacking_order_ids: Vec<u16>,
// pub(crate) next_root_z_index: u16,
// pub(crate) content_mask_stack: Vec<ContentMask<Pixels>>,
// pub(crate) element_offset_stack: Vec<Point<Pixels>>,
// pub(crate) tooltip_request: Option<TooltipRequest>,
// pub(crate) cursor_styles: FxHashMap<EntityId, CursorStyle>,
// pub(crate) requested_cursor_style: Option<CursorStyle>,
// pub(crate) view_stack: Vec<EntityId>,
#[cfg(any(test, feature = "test-support"))]
debug_bounds: FxHashMap::default(),
}
}
// #[cfg(any(test, feature = "test-support"))]
// pub(crate) debug_bounds: FxHashMap<String, Bounds<Pixels>>,
// }
pub(crate) fn clear(&mut self) {
self.element_states.clear();
self.mouse_listeners.values_mut().for_each(Vec::clear);
self.dispatch_tree.clear();
self.depth_map.clear();
self.next_stacking_order_ids = vec![0];
self.next_root_z_index = 0;
self.reused_views.clear();
self.scene.clear();
self.requested_input_handler.take();
self.tooltip_request.take();
self.cursor_styles.clear();
self.requested_cursor_style.take();
debug_assert_eq!(self.view_stack.len(), 0);
}
// impl Frame {
// pub(crate) fn new(dispatch_tree: DispatchTree) -> Self {
// Frame {
// focus: None,
// window_active: false,
// element_states: FxHashMap::default(),
// mouse_listeners: FxHashMap::default(),
// input_handlers: Vec::new(),
// dispatch_tree,
// scene: Scene::default(),
// depth_map: Vec::new(),
// z_index_stack: StackingOrder::default(),
// next_stacking_order_ids: vec![0],
// next_root_z_index: 0,
// content_mask_stack: Vec::new(),
// element_offset_stack: Vec::new(),
// tooltip_request: None,
// cursor_styles: FxHashMap::default(),
// requested_cursor_style: None,
// view_stack: Vec::new(),
pub(crate) fn focus_path(&self) -> SmallVec<[FocusId; 8]> {
self.focus
.map(|focus_id| self.dispatch_tree.focus_path(focus_id))
.unwrap_or_default()
}
// #[cfg(any(test, feature = "test-support"))]
// debug_bounds: FxHashMap::default(),
// }
// }
pub(crate) fn finish(&mut self, prev_frame: &mut Self) {
// Reuse mouse listeners that didn't change since the last frame.
for (type_id, listeners) in &mut prev_frame.mouse_listeners {
let next_listeners = self.mouse_listeners.entry(*type_id).or_default();
for (order, view_id, listener) in listeners.drain(..) {
if self.reused_views.contains(&view_id) {
next_listeners.push((order, view_id, listener));
}
}
}
// pub(crate) fn clear(&mut self) {
// self.element_states.clear();
// self.mouse_listeners.values_mut().for_each(Vec::clear);
// self.input_handlers.clear();
// self.dispatch_tree.clear();
// self.depth_map.clear();
// self.next_stacking_order_ids = vec![0];
// self.next_root_z_index = 0;
// self.scene.clear();
// self.tooltip_request.take();
// self.cursor_styles.clear();
// self.requested_cursor_style.take();
// debug_assert_eq!(self.view_stack.len(), 0);
// }
// Reuse entries in the depth map that didn't change since the last frame.
for (order, view_id, bounds) in prev_frame.depth_map.drain(..) {
if self.reused_views.contains(&view_id) {
match self
.depth_map
.binary_search_by(|(level, _, _)| order.cmp(level))
{
Ok(i) | Err(i) => self.depth_map.insert(i, (order, view_id, bounds)),
}
}
}
// pub(crate) fn focus_path(&self) -> SmallVec<[FocusId; 8]> {
// self.focus
// .map(|focus_id| self.dispatch_tree.focus_path(focus_id))
// .unwrap_or_default()
// }
// Retain element states for views that didn't change since the last frame.
for (element_id, state) in prev_frame.element_states.drain() {
if self.reused_views.contains(&state.parent_view_id) {
self.element_states.entry(element_id).or_insert(state);
}
}
// pub(crate) fn current_index(&self) -> FrameIndex {
// FrameIndex {
// scene_index: self.scene.current_index(),
// mouse_listeners: self.mouse_listeners.len(),
// dispatch_nodes: self.dispatch_tree.len(),
// }
// }
// Reuse geometry that didn't change since the last frame.
self.scene
.reuse_views(&self.reused_views, &mut prev_frame.scene);
self.scene.finish();
}
}
// pub(crate) fn finish(&mut self, prev_frame: &mut Self) {
// // Reuse mouse listeners that didn't change since the last frame.
// for (type_id, listeners) in &mut prev_frame.mouse_listeners {
// let next_listeners = self.mouse_listeners.entry(*type_id).or_default();
// for (order, view_id, listener) in listeners.drain(..) {
// if self.reused_views.contains(&view_id) {
// next_listeners.push((order, view_id, listener));
// }
// }
// }
// // Reuse entries in the depth map that didn't change since the last frame.
// for (order, view_id, bounds) in prev_frame.depth_map.drain(..) {
// if self.reused_views.contains(&view_id) {
// match self
// .depth_map
// .binary_search_by(|(level, _, _)| order.cmp(level))
// {
// Ok(i) | Err(i) => self.depth_map.insert(i, (order, view_id, bounds)),
// }
// }
// }
// // Retain element states for views that didn't change since the last frame.
// for (element_id, state) in prev_frame.element_states.drain() {
// if self.reused_views.contains(&state.parent_view_id) {
// self.element_states.entry(element_id).or_insert(state);
// }
// }
// }
// }
/// This context is used for assisting in the implementation of the element trait
#[derive(Deref, DerefMut)]
@@ -310,8 +314,9 @@ impl<'a> VisualContext for ElementContext<'a> {
}
impl<'a> ElementContext<'a> {
pub(crate) fn reuse_view(&mut self, next_stacking_order_id: u16) {
pub(crate) fn reuse_view(&mut self, subframe_range: Range<FrameIndex>) {
let view_id = self.parent_view_id();
let grafted_view_ids = self
.cx
.window
@@ -651,6 +656,7 @@ impl<'a> ElementContext<'a> {
}
})
}
/// Paint one or more drop shadows into the scene for the next frame at the current z-index.
pub fn paint_shadows(
&mut self,
@@ -666,20 +672,18 @@ impl<'a> ElementContext<'a> {
let mut shadow_bounds = bounds;
shadow_bounds.origin += shadow.offset;
shadow_bounds.dilate(shadow.spread_radius);
window.next_frame.scene.insert(
&window.next_frame.z_index_stack,
Shadow {
view_id: view_id.into(),
layer_id: 0,
order: 0,
window
.next_frame
.scene
.paint_primitive(|draw_order| Shadow {
draw_order,
bounds: shadow_bounds.scale(scale_factor),
content_mask: content_mask.scale(scale_factor),
corner_radii: corner_radii.scale(scale_factor),
color: shadow.color,
blur_radius: shadow.blur_radius.scale(scale_factor),
pad: 0,
},
);
});
}
}
@@ -692,20 +696,15 @@ impl<'a> ElementContext<'a> {
let view_id = self.parent_view_id();
let window = &mut *self.window;
window.next_frame.scene.insert(
&window.next_frame.z_index_stack,
Quad {
view_id: view_id.into(),
layer_id: 0,
order: 0,
bounds: quad.bounds.scale(scale_factor),
content_mask: content_mask.scale(scale_factor),
background: quad.background,
border_color: quad.border_color,
corner_radii: quad.corner_radii.scale(scale_factor),
border_widths: quad.border_widths.scale(scale_factor),
},
);
window.next_frame.scene.paint_primitive(|draw_order| Quad {
draw_order,
bounds: quad.bounds.scale(scale_factor),
content_mask: content_mask.scale(scale_factor),
background: quad.background,
border_color: quad.border_color,
corner_radii: quad.corner_radii.scale(scale_factor),
border_widths: quad.border_widths.scale(scale_factor),
});
}
/// Paint the given `Path` into the scene for the next frame at the current z-index.
@@ -716,12 +715,11 @@ impl<'a> ElementContext<'a> {
path.content_mask = content_mask;
path.color = color.into();
path.view_id = view_id.into();
let window = &mut *self.window;
window
.next_frame
.scene
.insert(&window.next_frame.z_index_stack, path.scale(scale_factor));
window.next_frame.scene.paint_primitive(|draw_order| {
path.draw_order = draw_order;
path.scale(scale_factor)
});
}
/// Paint an underline into the scene for the next frame at the current z-index.
@@ -745,19 +743,17 @@ impl<'a> ElementContext<'a> {
let view_id = self.parent_view_id();
let window = &mut *self.window;
window.next_frame.scene.insert(
&window.next_frame.z_index_stack,
Underline {
view_id: view_id.into(),
layer_id: 0,
order: 0,
window
.next_frame
.scene
.paint_primitive(|draw_order| Underline {
draw_order,
bounds: bounds.scale(scale_factor),
content_mask: content_mask.scale(scale_factor),
color: style.color.unwrap_or_default(),
thickness: style.thickness.scale(scale_factor),
wavy: style.wavy,
},
);
});
}
/// Paint a strikethrough into the scene for the next frame at the current z-index.
@@ -777,19 +773,17 @@ impl<'a> ElementContext<'a> {
let view_id = self.parent_view_id();
let window = &mut *self.window;
window.next_frame.scene.insert(
&window.next_frame.z_index_stack,
Underline {
view_id: view_id.into(),
layer_id: 0,
order: 0,
window
.next_frame
.scene
.paint_primitive(|draw_order| Underline {
draw_order,
bounds: bounds.scale(scale_factor),
content_mask: content_mask.scale(scale_factor),
thickness: style.thickness.scale(scale_factor),
color: style.color.unwrap_or_default(),
wavy: false,
},
);
});
}
/// Paints a monochrome (non-emoji) glyph into the scene for the next frame at the current z-index.
@@ -837,18 +831,16 @@ impl<'a> ElementContext<'a> {
let content_mask = self.content_mask().scale(scale_factor);
let view_id = self.parent_view_id();
let window = &mut *self.window;
window.next_frame.scene.insert(
&window.next_frame.z_index_stack,
MonochromeSprite {
view_id: view_id.into(),
layer_id: 0,
order: 0,
window
.next_frame
.scene
.paint_primitive(|draw_order| MonochromeSprite {
draw_order,
bounds,
content_mask,
color,
tile,
},
);
});
}
Ok(())
}
@@ -895,20 +887,18 @@ impl<'a> ElementContext<'a> {
let view_id = self.parent_view_id();
let window = &mut *self.window;
window.next_frame.scene.insert(
&window.next_frame.z_index_stack,
PolychromeSprite {
view_id: view_id.into(),
layer_id: 0,
order: 0,
window
.next_frame
.scene
.paint_primitive(|draw_order| PolychromeSprite {
draw_order,
bounds,
corner_radii: Default::default(),
content_mask,
tile,
grayscale: false,
pad: 0,
},
);
});
}
Ok(())
}
@@ -941,18 +931,16 @@ impl<'a> ElementContext<'a> {
let view_id = self.parent_view_id();
let window = &mut *self.window;
window.next_frame.scene.insert(
&window.next_frame.z_index_stack,
MonochromeSprite {
view_id: view_id.into(),
layer_id: 0,
order: 0,
window
.next_frame
.scene
.paint_primitive(|draw_order| MonochromeSprite {
draw_order,
bounds,
content_mask,
color,
tile,
},
);
});
Ok(())
}
@@ -980,20 +968,18 @@ impl<'a> ElementContext<'a> {
let view_id = self.parent_view_id();
let window = &mut *self.window;
window.next_frame.scene.insert(
&window.next_frame.z_index_stack,
PolychromeSprite {
view_id: view_id.into(),
layer_id: 0,
order: 0,
window
.next_frame
.scene
.paint_primitive(|draw_order| PolychromeSprite {
draw_order,
bounds,
content_mask,
corner_radii,
tile,
grayscale,
pad: 0,
},
);
});
Ok(())
}
@@ -1005,17 +991,15 @@ impl<'a> ElementContext<'a> {
let content_mask = self.content_mask().scale(scale_factor);
let view_id = self.parent_view_id();
let window = &mut *self.window;
window.next_frame.scene.insert(
&window.next_frame.z_index_stack,
crate::Surface {
view_id: view_id.into(),
layer_id: 0,
order: 0,
window
.next_frame
.scene
.paint_primitive(|draw_order| crate::Surface {
draw_order,
bounds,
content_mask,
image_buffer,
},
);
});
}
#[must_use]