Merge remote-tracking branch 'origin/main' into cancel-clicks-on-drag
This commit is contained in:
+30
-32
@@ -2,13 +2,13 @@ use std::{
|
||||
alloc,
|
||||
cell::Cell,
|
||||
ops::{Deref, DerefMut},
|
||||
ptr::{self, NonNull},
|
||||
ptr,
|
||||
rc::Rc,
|
||||
};
|
||||
|
||||
struct ArenaElement {
|
||||
value: NonNull<u8>,
|
||||
drop: unsafe fn(NonNull<u8>),
|
||||
value: *mut u8,
|
||||
drop: unsafe fn(*mut u8),
|
||||
}
|
||||
|
||||
impl Drop for ArenaElement {
|
||||
@@ -21,8 +21,9 @@ impl Drop for ArenaElement {
|
||||
}
|
||||
|
||||
pub struct Arena {
|
||||
start: NonNull<u8>,
|
||||
offset: usize,
|
||||
start: *mut u8,
|
||||
end: *mut u8,
|
||||
offset: *mut u8,
|
||||
elements: Vec<ArenaElement>,
|
||||
valid: Rc<Cell<bool>>,
|
||||
}
|
||||
@@ -31,10 +32,12 @@ impl Arena {
|
||||
pub fn new(size_in_bytes: usize) -> Self {
|
||||
unsafe {
|
||||
let layout = alloc::Layout::from_size_align(size_in_bytes, 1).unwrap();
|
||||
let ptr = alloc::alloc(layout);
|
||||
let start = alloc::alloc(layout);
|
||||
let end = start.add(size_in_bytes);
|
||||
Self {
|
||||
start: NonNull::new_unchecked(ptr),
|
||||
offset: 0,
|
||||
start,
|
||||
end,
|
||||
offset: start,
|
||||
elements: Vec::new(),
|
||||
valid: Rc::new(Cell::new(true)),
|
||||
}
|
||||
@@ -45,7 +48,7 @@ impl Arena {
|
||||
self.valid.set(false);
|
||||
self.valid = Rc::new(Cell::new(true));
|
||||
self.elements.clear();
|
||||
self.offset = 0;
|
||||
self.offset = self.start;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
@@ -58,24 +61,28 @@ impl Arena {
|
||||
ptr::write(ptr, f());
|
||||
}
|
||||
|
||||
unsafe fn drop<T>(ptr: NonNull<u8>) {
|
||||
std::ptr::drop_in_place(ptr.cast::<T>().as_ptr());
|
||||
unsafe fn drop<T>(ptr: *mut u8) {
|
||||
std::ptr::drop_in_place(ptr.cast::<T>());
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let layout = alloc::Layout::new::<T>().pad_to_align();
|
||||
let ptr = NonNull::new_unchecked(self.start.as_ptr().add(self.offset).cast::<T>());
|
||||
inner_writer(ptr.as_ptr(), f);
|
||||
let next_offset = self.offset.add(layout.size());
|
||||
assert!(next_offset <= self.end);
|
||||
|
||||
let result = ArenaRef {
|
||||
ptr: self.offset.cast(),
|
||||
valid: self.valid.clone(),
|
||||
};
|
||||
|
||||
inner_writer(result.ptr, f);
|
||||
self.elements.push(ArenaElement {
|
||||
value: ptr.cast(),
|
||||
value: self.offset,
|
||||
drop: drop::<T>,
|
||||
});
|
||||
self.offset += layout.size();
|
||||
ArenaRef {
|
||||
ptr,
|
||||
valid: self.valid.clone(),
|
||||
}
|
||||
self.offset = next_offset;
|
||||
|
||||
result
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -87,24 +94,15 @@ impl Drop for Arena {
|
||||
}
|
||||
|
||||
pub struct ArenaRef<T: ?Sized> {
|
||||
ptr: NonNull<T>,
|
||||
ptr: *mut T,
|
||||
valid: Rc<Cell<bool>>,
|
||||
}
|
||||
|
||||
impl<T: ?Sized> Clone for ArenaRef<T> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
ptr: self.ptr,
|
||||
valid: self.valid.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> ArenaRef<T> {
|
||||
#[inline(always)]
|
||||
pub fn map<U: ?Sized>(mut self, f: impl FnOnce(&mut T) -> &mut U) -> ArenaRef<U> {
|
||||
ArenaRef {
|
||||
ptr: unsafe { NonNull::new_unchecked(f(&mut *self)) },
|
||||
ptr: f(&mut self),
|
||||
valid: self.valid,
|
||||
}
|
||||
}
|
||||
@@ -123,7 +121,7 @@ impl<T: ?Sized> Deref for ArenaRef<T> {
|
||||
#[inline(always)]
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.validate();
|
||||
unsafe { self.ptr.as_ref() }
|
||||
unsafe { &*self.ptr }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,7 +129,7 @@ impl<T: ?Sized> DerefMut for ArenaRef<T> {
|
||||
#[inline(always)]
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
self.validate();
|
||||
unsafe { self.ptr.as_mut() }
|
||||
unsafe { &mut *self.ptr }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1105,11 +1105,14 @@ impl Interactivity {
|
||||
stacking_order: cx.stacking_order().clone(),
|
||||
};
|
||||
|
||||
if let Some(mouse_cursor) = style.mouse_cursor {
|
||||
let mouse_position = &cx.mouse_position();
|
||||
let hovered = interactive_bounds.visibly_contains(mouse_position, cx);
|
||||
if hovered {
|
||||
cx.set_cursor_style(mouse_cursor);
|
||||
if !cx.has_active_drag() {
|
||||
if let Some(mouse_cursor) = style.mouse_cursor {
|
||||
let mouse_position = &cx.mouse_position();
|
||||
let hovered =
|
||||
interactive_bounds.visibly_contains(mouse_position, cx);
|
||||
if hovered {
|
||||
cx.set_cursor_style(mouse_cursor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1334,8 +1337,8 @@ impl Interactivity {
|
||||
}
|
||||
let is_hovered = interactive_bounds
|
||||
.visibly_contains(&event.position, cx)
|
||||
&& !cx.has_active_drag()
|
||||
&& has_mouse_down.borrow().is_none();
|
||||
&& has_mouse_down.borrow().is_none()
|
||||
&& !cx.has_active_drag();
|
||||
let mut was_hovered = was_hovered.borrow_mut();
|
||||
|
||||
if is_hovered != was_hovered.clone() {
|
||||
@@ -1420,14 +1423,14 @@ impl Interactivity {
|
||||
}
|
||||
}
|
||||
|
||||
let clicked_state = element_state
|
||||
let active_state = element_state
|
||||
.clicked_state
|
||||
.get_or_insert_with(Default::default)
|
||||
.clone();
|
||||
if clicked_state.borrow().is_clicked() {
|
||||
if active_state.borrow().is_clicked() {
|
||||
cx.on_mouse_event(move |_: &MouseUpEvent, phase, cx| {
|
||||
if phase == DispatchPhase::Capture {
|
||||
*clicked_state.borrow_mut() = ElementClickedState::default();
|
||||
*active_state.borrow_mut() = ElementClickedState::default();
|
||||
cx.notify();
|
||||
}
|
||||
});
|
||||
@@ -1444,7 +1447,7 @@ impl Interactivity {
|
||||
let element =
|
||||
interactive_bounds.visibly_contains(&down.position, cx);
|
||||
if group || element {
|
||||
*clicked_state.borrow_mut() =
|
||||
*active_state.borrow_mut() =
|
||||
ElementClickedState { group, element };
|
||||
cx.notify();
|
||||
}
|
||||
@@ -1465,7 +1468,6 @@ impl Interactivity {
|
||||
let line_height = cx.line_height();
|
||||
let scroll_max = (content_size - bounds.size).max(&Size::default());
|
||||
let interactive_bounds = interactive_bounds.clone();
|
||||
|
||||
cx.on_mouse_event(move |event: &ScrollWheelEvent, phase, cx| {
|
||||
if phase == DispatchPhase::Bubble
|
||||
&& interactive_bounds.visibly_contains(&event.position, cx)
|
||||
@@ -1524,7 +1526,15 @@ impl Interactivity {
|
||||
cx.on_action(action_type, listener)
|
||||
}
|
||||
|
||||
f(&style, scroll_offset.unwrap_or_default(), cx)
|
||||
cx.with_z_index(style.z_index.unwrap_or(0), |cx| {
|
||||
if style.background.as_ref().is_some_and(|fill| {
|
||||
fill.color().is_some_and(|color| !color.is_transparent())
|
||||
}) {
|
||||
cx.add_opaque_layer(bounds)
|
||||
}
|
||||
|
||||
f(&style, scroll_offset.unwrap_or_default(), cx)
|
||||
})
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
@@ -91,6 +91,14 @@ impl UniformListScrollHandle {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn scroll_top(&self) -> Pixels {
|
||||
if let Some(state) = &*self.0.borrow() {
|
||||
-state.scroll_offset.borrow().y
|
||||
} else {
|
||||
Pixels::ZERO
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Styled for UniformList {
|
||||
@@ -135,6 +143,7 @@ impl Element for UniformList {
|
||||
item_size.width
|
||||
}
|
||||
});
|
||||
|
||||
let height = match available_space.height {
|
||||
AvailableSpace::Definite(height) => desired_height.min(height),
|
||||
AvailableSpace::MinContent | AvailableSpace::MaxContent => {
|
||||
|
||||
@@ -35,7 +35,6 @@ pub(crate) struct DispatchNode {
|
||||
|
||||
type KeyListener = ArenaRef<dyn Fn(&dyn Any, DispatchPhase, &mut WindowContext)>;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct DispatchActionListener {
|
||||
pub(crate) action_type: TypeId,
|
||||
pub(crate) listener: ArenaRef<dyn Fn(&dyn Any, DispatchPhase, &mut WindowContext)>,
|
||||
@@ -267,6 +266,10 @@ impl DispatchTree {
|
||||
&self.nodes[node_id.0]
|
||||
}
|
||||
|
||||
pub fn node_mut(&mut self, node_id: DispatchNodeId) -> &mut DispatchNode {
|
||||
&mut self.nodes[node_id.0]
|
||||
}
|
||||
|
||||
fn active_node(&mut self) -> &mut DispatchNode {
|
||||
let active_node_id = self.active_node_id();
|
||||
&mut self.nodes[active_node_id.0]
|
||||
|
||||
@@ -104,6 +104,15 @@ impl SceneBuilder {
|
||||
);
|
||||
}
|
||||
|
||||
for (ix, surface) in self.surfaces.iter().enumerate() {
|
||||
let z = layer_z_values[surface.order as LayerId as usize];
|
||||
self.splitter.add(
|
||||
surface
|
||||
.bounds
|
||||
.to_bsp_polygon(z, (PrimitiveKind::Surface, ix)),
|
||||
);
|
||||
}
|
||||
|
||||
// Sort all polygons, then reassign the order field of each primitive to `draw_order`
|
||||
// We need primitives to be repr(C), hence the weird reuse of the order field for two different types.
|
||||
for (draw_order, polygon) in self
|
||||
|
||||
+52
-15
@@ -1572,30 +1572,43 @@ impl<'a> WindowContext<'a> {
|
||||
self.propagate_event = true;
|
||||
|
||||
for node_id in &dispatch_path {
|
||||
let node = self.window.rendered_frame.dispatch_tree.node(*node_id);
|
||||
|
||||
let node = self.window.rendered_frame.dispatch_tree.node_mut(*node_id);
|
||||
if let Some(context) = node.context.clone() {
|
||||
context_stack.push(context);
|
||||
}
|
||||
|
||||
for key_listener in node.key_listeners.clone() {
|
||||
let key_listeners = mem::take(&mut node.key_listeners);
|
||||
for key_listener in &key_listeners {
|
||||
key_listener(event, DispatchPhase::Capture, self);
|
||||
if !self.propagate_event {
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
let node = self.window.rendered_frame.dispatch_tree.node_mut(*node_id);
|
||||
node.key_listeners = key_listeners;
|
||||
|
||||
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() {
|
||||
let node = self.window.rendered_frame.dispatch_tree.node_mut(*node_id);
|
||||
let key_listeners = mem::take(&mut node.key_listeners);
|
||||
for key_listener in &key_listeners {
|
||||
key_listener(event, DispatchPhase::Bubble, self);
|
||||
if !self.propagate_event {
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
let node = self.window.rendered_frame.dispatch_tree.node_mut(*node_id);
|
||||
node.key_listeners = key_listeners;
|
||||
|
||||
if !self.propagate_event {
|
||||
return;
|
||||
}
|
||||
|
||||
// Match keystrokes
|
||||
let node = self.window.rendered_frame.dispatch_tree.node(*node_id);
|
||||
@@ -1639,38 +1652,52 @@ impl<'a> WindowContext<'a> {
|
||||
|
||||
// Capture phase
|
||||
for node_id in &dispatch_path {
|
||||
let node = self.window.rendered_frame.dispatch_tree.node(*node_id);
|
||||
let node = self.window.rendered_frame.dispatch_tree.node_mut(*node_id);
|
||||
let action_listeners = mem::take(&mut node.action_listeners);
|
||||
for DispatchActionListener {
|
||||
action_type,
|
||||
listener,
|
||||
} in node.action_listeners.clone()
|
||||
} in &action_listeners
|
||||
{
|
||||
let any_action = action.as_any();
|
||||
if action_type == any_action.type_id() {
|
||||
if *action_type == any_action.type_id() {
|
||||
listener(any_action, DispatchPhase::Capture, self);
|
||||
if !self.propagate_event {
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
let node = self.window.rendered_frame.dispatch_tree.node_mut(*node_id);
|
||||
node.action_listeners = action_listeners;
|
||||
|
||||
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);
|
||||
let node = self.window.rendered_frame.dispatch_tree.node_mut(*node_id);
|
||||
let action_listeners = mem::take(&mut node.action_listeners);
|
||||
for DispatchActionListener {
|
||||
action_type,
|
||||
listener,
|
||||
} in node.action_listeners.clone()
|
||||
} in &action_listeners
|
||||
{
|
||||
let any_action = action.as_any();
|
||||
if action_type == any_action.type_id() {
|
||||
if *action_type == any_action.type_id() {
|
||||
self.propagate_event = false; // Actions stop propagation by default during the bubble phase
|
||||
listener(any_action, DispatchPhase::Bubble, self);
|
||||
if !self.propagate_event {
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let node = self.window.rendered_frame.dispatch_tree.node_mut(*node_id);
|
||||
node.action_listeners = action_listeners;
|
||||
if !self.propagate_event {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2057,9 +2084,14 @@ pub trait BorrowWindow: BorrowMut<Window> + BorrowMut<AppContext> {
|
||||
size: self.window().viewport_size,
|
||||
},
|
||||
};
|
||||
let new_stacking_order_id =
|
||||
post_inc(&mut self.window_mut().next_frame.next_stacking_order_id);
|
||||
let old_stacking_order = mem::take(&mut self.window_mut().next_frame.z_index_stack);
|
||||
self.window_mut().next_frame.z_index_stack.id = new_stacking_order_id;
|
||||
self.window_mut().next_frame.content_mask_stack.push(mask);
|
||||
let result = f(self);
|
||||
self.window_mut().next_frame.content_mask_stack.pop();
|
||||
self.window_mut().next_frame.z_index_stack = old_stacking_order;
|
||||
result
|
||||
}
|
||||
|
||||
@@ -2068,9 +2100,14 @@ pub trait BorrowWindow: BorrowMut<Window> + BorrowMut<AppContext> {
|
||||
fn with_z_index<R>(&mut self, z_index: u8, f: impl FnOnce(&mut Self) -> R) -> R {
|
||||
let new_stacking_order_id =
|
||||
post_inc(&mut self.window_mut().next_frame.next_stacking_order_id);
|
||||
let old_stacking_order_id = mem::replace(
|
||||
&mut self.window_mut().next_frame.z_index_stack.id,
|
||||
new_stacking_order_id,
|
||||
);
|
||||
self.window_mut().next_frame.z_index_stack.id = new_stacking_order_id;
|
||||
self.window_mut().next_frame.z_index_stack.push(z_index);
|
||||
let result = f(self);
|
||||
self.window_mut().next_frame.z_index_stack.id = old_stacking_order_id;
|
||||
self.window_mut().next_frame.z_index_stack.pop();
|
||||
result
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user