use crate::{ point, prelude::*, px, size, transparent_black, Action, AnyDrag, AnyElement, AnyTooltip, AnyView, AppContext, Arena, Asset, AsyncWindowContext, AvailableSpace, Background, Bounds, BoxShadow, Context, Corners, CursorStyle, Decorations, DevicePixels, DispatchActionListener, DispatchNodeId, DispatchTree, DisplayId, Edges, Effect, Entity, EntityId, EventEmitter, FileDropEvent, Flatten, FontId, Global, GlobalElementId, GlyphId, GpuSpecs, Hsla, InputHandler, IsZero, KeyBinding, KeyContext, KeyDownEvent, KeyEvent, Keystroke, KeystrokeEvent, KeystrokeObserver, LayoutId, LineLayoutIndex, Model, ModelContext, Modifiers, ModifiersChangedEvent, MonochromeSprite, MouseButton, MouseEvent, MouseMoveEvent, MouseUpEvent, Path, Pixels, PlatformAtlas, PlatformDisplay, PlatformInput, PlatformInputHandler, PlatformWindow, Point, PolychromeSprite, PromptLevel, Quad, Render, RenderGlyphParams, RenderImage, RenderImageParams, RenderSvgParams, Replay, ResizeEdge, ScaledPixels, Scene, Shadow, SharedString, Size, StrikethroughStyle, Style, SubscriberSet, Subscription, TaffyLayoutEngine, Task, TextStyle, TextStyleRefinement, TransformationMatrix, Underline, UnderlineStyle, View, VisualContext, WeakView, WindowAppearance, WindowBackgroundAppearance, WindowBounds, WindowControls, WindowDecorations, WindowOptions, WindowParams, WindowTextSystem, SUBPIXEL_VARIANTS,};use anyhow::{anyhow, Context as _, Result};use collections::{FxHashMap, FxHashSet};use derive_more::{Deref, DerefMut};use futures::channel::oneshot;use futures::FutureExt;#[cfg(target_os = "macos")]use media::core_video::CVImageBuffer;use parking_lot::RwLock;use refineable::Refineable;use slotmap::SlotMap;use smallvec::SmallVec;use std::{ any::{Any, TypeId}, borrow::{Borrow, BorrowMut, Cow}, cell::{Cell, RefCell}, cmp, fmt::{Debug, Display}, future::Future, hash::{Hash, Hasher}, marker::PhantomData, mem, ops::Range, rc::Rc, sync::{ atomic::{AtomicUsize, Ordering::SeqCst}, Arc, Weak, }, time::{Duration, Instant},};use util::post_inc;use util::{measure, ResultExt};use uuid::Uuid; mod prompts; pub use prompts::*; pub(crate) const DEFAULT_WINDOW_SIZE: Size<Pixels> = size(px(1024.), px(700.)); /// Represents the two different phases when dispatching events.#[derive(Default, Copy, Clone, Debug, Eq, PartialEq)]pub enum DispatchPhase { /// After the capture phase comes the bubble phase, in which mouse event listeners are /// invoked front to back and keyboard event listeners are invoked from the focused element /// to the root of the element tree. This is the phase you'll most commonly want to use when /// registering event listeners. #[default] Bubble, /// During the initial capture phase, mouse event listeners are invoked back to front, and keyboard /// listeners are invoked from the root of the tree downward toward the focused element. This phase /// is used for special purposes such as clearing the "pressed" state for click events. If /// you stop event propagation during this phase, you need to know what you're doing. Handlers /// outside of the immediate region may rely on detecting non-local events during this phase. Capture,} impl DispatchPhase { /// Returns true if this represents the "bubble" phase. pub fn bubble(self) -> bool { self == DispatchPhase::Bubble } /// Returns true if this represents the "capture" phase. pub fn capture(self) -> bool { self == DispatchPhase::Capture }} type AnyObserver = Box<dyn FnMut(&mut WindowContext) -> bool + 'static>; type AnyWindowFocusListener = Box<dyn FnMut(&WindowFocusEvent, &mut WindowContext) -> bool + 'static>; struct WindowFocusEvent { previous_focus_path: SmallVec<[FocusId; 8]>, current_focus_path: SmallVec<[FocusId; 8]>,} impl WindowFocusEvent { pub fn is_focus_in(&self, focus_id: FocusId) -> bool { !self.previous_focus_path.contains(&focus_id) && self.current_focus_path.contains(&focus_id) } pub fn is_focus_out(&self, focus_id: FocusId) -> bool { self.previous_focus_path.contains(&focus_id) && !self.current_focus_path.contains(&focus_id) }} /// This is provided when subscribing for `ViewContext::on_focus_out` events.pub struct FocusOutEvent { /// A weak focus handle representing what was blurred. pub blurred: WeakFocusHandle,} slotmap::new_key_type! { /// A globally unique identifier for a focusable element. pub struct FocusId;} thread_local! { /// 8MB wasn't quite enough... pub(crate) static ELEMENT_ARENA: RefCell<Arena> = RefCell::new(Arena::new(32 * 1024 * 1024));} impl FocusId { /// Obtains whether the element associated with this handle is currently focused. pub fn is_focused(&self, cx: &WindowContext) -> bool { cx.window.focus == Some(*self) } /// Obtains whether the element associated with this handle contains the focused /// element or is itself focused. pub fn contains_focused(&self, cx: &WindowContext) -> bool { cx.focused() .map_or(false, |focused| self.contains(focused.id, cx)) } /// Obtains whether the element associated with this handle is contained within the /// focused element or is itself focused. pub fn within_focused(&self, cx: &WindowContext) -> bool { let focused = cx.focused(); focused.map_or(false, |focused| focused.id.contains(*self, cx)) } /// 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) }} /// A handle which can be used to track and manipulate the focused element in a window.pub struct FocusHandle { pub(crate) id: FocusId, handles: Arc<RwLock<SlotMap<FocusId, AtomicUsize>>>,} impl std::fmt::Debug for FocusHandle { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.write_fmt(format_args!("FocusHandle({:?})", self.id)) }} impl FocusHandle { pub(crate) fn new(handles: &Arc<RwLock<SlotMap<FocusId, AtomicUsize>>>) -> Self { let id = handles.write().insert(AtomicUsize::new(1)); Self { id, handles: handles.clone(), } } pub(crate) fn for_id( id: FocusId, handles: &Arc<RwLock<SlotMap<FocusId, AtomicUsize>>>, ) -> Option<Self> { let lock = handles.read(); let ref_count = lock.get(id)?; if ref_count.load(SeqCst) == 0 { None } else { ref_count.fetch_add(1, SeqCst); Some(Self { id, handles: handles.clone(), }) } } /// Converts this focus handle into a weak variant, which does not prevent it from being released. pub fn downgrade(&self) -> WeakFocusHandle { WeakFocusHandle { id: self.id, handles: Arc::downgrade(&self.handles), } } /// Moves the focus to the element associated with this handle. pub fn focus(&self, cx: &mut WindowContext) { cx.focus(self) } /// Obtains whether the element associated with this handle is currently focused. pub fn is_focused(&self, cx: &WindowContext) -> bool { self.id.is_focused(cx) } /// Obtains whether the element associated with this handle contains the focused /// element or is itself focused. pub fn contains_focused(&self, cx: &WindowContext) -> bool { self.id.contains_focused(cx) } /// Obtains whether the element associated with this handle is contained within the /// focused element or is itself focused. pub fn within_focused(&self, cx: &WindowContext) -> bool { self.id.within_focused(cx) } /// Obtains whether this handle contains the given handle in the most recently rendered frame. pub fn contains(&self, other: &Self, cx: &WindowContext) -> bool { self.id.contains(other.id, cx) } /// Dispatch an action on the element that rendered this focus handle pub fn dispatch_action(&self, action: &dyn Action, cx: &mut WindowContext) { if let Some(node_id) = cx .window .rendered_frame .dispatch_tree .focusable_node_id(self.id) { cx.dispatch_action_on_node(node_id, action) } }} impl Clone for FocusHandle { fn clone(&self) -> Self { Self::for_id(self.id, &self.handles).unwrap() }} impl PartialEq for FocusHandle { fn eq(&self, other: &Self) -> bool { self.id == other.id }} impl Eq for FocusHandle {} impl Drop for FocusHandle { fn drop(&mut self) { self.handles .read() .get(self.id) .unwrap() .fetch_sub(1, SeqCst); }} /// A weak reference to a focus handle.#[derive(Clone, Debug)]pub struct WeakFocusHandle { pub(crate) id: FocusId, handles: Weak<RwLock<SlotMap<FocusId, AtomicUsize>>>,} impl WeakFocusHandle { /// Attempts to upgrade the [WeakFocusHandle] to a [FocusHandle]. pub fn upgrade(&self) -> Option<FocusHandle> { let handles = self.handles.upgrade()?; FocusHandle::for_id(self.id, &handles) }} impl PartialEq for WeakFocusHandle { fn eq(&self, other: &WeakFocusHandle) -> bool { self.id == other.id }} impl Eq for WeakFocusHandle {} impl PartialEq<FocusHandle> for WeakFocusHandle { fn eq(&self, other: &FocusHandle) -> bool { self.id == other.id }} impl PartialEq<WeakFocusHandle> for FocusHandle { fn eq(&self, other: &WeakFocusHandle) -> bool { self.id == other.id }} /// FocusableView allows users of your view to easily/// focus it (using cx.focus_view(view))pub trait FocusableView: 'static + Render { /// Returns the focus handle associated with this view. fn focus_handle(&self, cx: &AppContext) -> FocusHandle;} /// ManagedView is a view (like a Modal, Popover, Menu, etc.)/// where the lifecycle of the view is handled by another view.pub trait ManagedView: FocusableView + EventEmitter<DismissEvent> {} impl<M: FocusableView + EventEmitter<DismissEvent>> ManagedView for M {} /// Emitted by implementers of [`ManagedView`] to indicate the view should be dismissed, such as when a view is presented as a modal.pub struct DismissEvent; type FrameCallback = Box<dyn FnOnce(&mut WindowContext)>; pub(crate) type AnyMouseListener = Box<dyn FnMut(&dyn Any, DispatchPhase, &mut WindowContext) + 'static>; #[derive(Clone)]pub(crate) struct CursorStyleRequest { pub(crate) hitbox_id: HitboxId, pub(crate) style: CursorStyle,} /// An identifier for a [Hitbox].#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]pub struct HitboxId(usize); impl HitboxId { /// Checks if the hitbox with this id is currently hovered. pub fn is_hovered(&self, cx: &WindowContext) -> bool { cx.window.mouse_hit_test.0.contains(self) }} /// A rectangular region that potentially blocks hitboxes inserted prior./// See [WindowContext::insert_hitbox] for more details.#[derive(Clone, Debug, Deref)]pub struct Hitbox { /// A unique identifier for the hitbox. pub id: HitboxId, /// The bounds of the hitbox. #[deref] pub bounds: Bounds<Pixels>, /// The content mask when the hitbox was inserted. pub content_mask: ContentMask<Pixels>, /// Whether the hitbox occludes other hitboxes inserted prior. pub opaque: bool,} impl Hitbox { /// Checks if the hitbox is currently hovered. pub fn is_hovered(&self, cx: &WindowContext) -> bool { self.id.is_hovered(cx) }} #[derive(Default, Eq, PartialEq)]pub(crate) struct HitTest(SmallVec<[HitboxId; 8]>); /// An identifier for a tooltip.#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]pub struct TooltipId(usize); impl TooltipId { /// Checks if the tooltip is currently hovered. pub fn is_hovered(&self, cx: &WindowContext) -> bool { cx.window .tooltip_bounds .as_ref() .map_or(false, |tooltip_bounds| { tooltip_bounds.id == *self && tooltip_bounds.bounds.contains(&cx.mouse_position()) }) }} pub(crate) struct TooltipBounds { id: TooltipId, bounds: Bounds<Pixels>,} #[derive(Clone)]pub(crate) struct TooltipRequest { id: TooltipId, tooltip: AnyTooltip,} pub(crate) struct DeferredDraw { priority: usize, parent_node: DispatchNodeId, element_id_stack: SmallVec<[ElementId; 32]>, text_style_stack: Vec<TextStyleRefinement>, element: Option<AnyElement>, absolute_offset: Point<Pixels>, prepaint_range: Range<PrepaintStateIndex>, paint_range: Range<PaintIndex>,} pub(crate) struct Frame { pub(crate) focus: Option<FocusId>, pub(crate) window_active: bool, pub(crate) element_states: FxHashMap<(GlobalElementId, TypeId), ElementStateBox>, accessed_element_states: Vec<(GlobalElementId, TypeId)>, pub(crate) mouse_listeners: Vec<Option<AnyMouseListener>>, pub(crate) dispatch_tree: DispatchTree, pub(crate) scene: Scene, pub(crate) hitboxes: Vec<Hitbox>, pub(crate) deferred_draws: Vec<DeferredDraw>, pub(crate) input_handlers: Vec<Option<PlatformInputHandler>>, pub(crate) tooltip_requests: Vec<Option<TooltipRequest>>, pub(crate) cursor_styles: Vec<CursorStyleRequest>, #[cfg(any(test, feature = "test-support"))] pub(crate) debug_bounds: FxHashMap<String, Bounds<Pixels>>,} #[derive(Clone, Default)]pub(crate) struct PrepaintStateIndex { hitboxes_index: usize, tooltips_index: usize, deferred_draws_index: usize, dispatch_tree_index: usize, accessed_element_states_index: usize, line_layout_index: LineLayoutIndex,} #[derive(Clone, Default)]pub(crate) struct PaintIndex { scene_index: usize, mouse_listeners_index: usize, input_handlers_index: usize, cursor_styles_index: usize, accessed_element_states_index: usize, line_layout_index: LineLayoutIndex,} impl Frame { pub(crate) fn new(dispatch_tree: DispatchTree) -> Self { Frame { focus: None, window_active: false, element_states: FxHashMap::default(), accessed_element_states: Vec::new(), mouse_listeners: Vec::new(), dispatch_tree, scene: Scene::default(), hitboxes: Vec::new(), deferred_draws: Vec::new(), input_handlers: Vec::new(), tooltip_requests: Vec::new(), cursor_styles: Vec::new(), #[cfg(any(test, feature = "test-support"))] debug_bounds: FxHashMap::default(), } } pub(crate) fn clear(&mut self) { self.element_states.clear(); self.accessed_element_states.clear(); self.mouse_listeners.clear(); self.dispatch_tree.clear(); self.scene.clear(); self.input_handlers.clear(); self.tooltip_requests.clear(); self.cursor_styles.clear(); self.hitboxes.clear(); self.deferred_draws.clear(); self.focus = None; } pub(crate) fn hit_test(&self, position: Point<Pixels>) -> HitTest { let mut hit_test = HitTest::default(); for hitbox in self.hitboxes.iter().rev() { let bounds = hitbox.bounds.intersect(&hitbox.content_mask.bounds); if bounds.contains(&position) { hit_test.0.push(hitbox.id); if hitbox.opaque { break; } } } hit_test } pub(crate) fn focus_path(&self) -> SmallVec<[FocusId; 8]> { self.focus .map(|focus_id| self.dispatch_tree.focus_path(focus_id)) .unwrap_or_default() } pub(crate) fn finish(&mut self, prev_frame: &mut Self) { for element_state_key in &self.accessed_element_states { if let Some((element_state_key, element_state)) = prev_frame.element_states.remove_entry(element_state_key) { self.element_states.insert(element_state_key, element_state); } } self.scene.finish(); }Lines 1–500 of 5089. Load more
use crate::{ point, prelude::*, px, size, transparent_black, Action, AnyDrag, AnyElement, AnyTooltip, AnyView, AppContext, Arena, Asset, AsyncWindowContext, AvailableSpace, Background, Bounds, BoxShadow, Context, Corners, CursorStyle, Decorations, DevicePixels, DispatchActionListener, DispatchNodeId, DispatchTree, DisplayId, Edges, Effect, Entity, EntityId, EventEmitter, FileDropEvent, Flatten, FontId, Global, GlobalElementId, GlyphId, GpuSpecs, Hsla, InputHandler, IsZero, KeyBinding, KeyContext, KeyDownEvent, KeyEvent, Keystroke, KeystrokeEvent, KeystrokeObserver, LayoutId, LineLayoutIndex, Model, ModelContext, Modifiers, ModifiersChangedEvent, MonochromeSprite, MouseButton, MouseEvent, MouseMoveEvent, MouseUpEvent, Path, Pixels, PlatformAtlas, PlatformDisplay, PlatformInput, PlatformInputHandler, PlatformWindow, Point, PolychromeSprite, PromptLevel, Quad, Render, RenderGlyphParams, RenderImage, RenderImageParams, RenderSvgParams, Replay, ResizeEdge, ScaledPixels, Scene, Shadow, SharedString, Size, StrikethroughStyle, Style, SubscriberSet, Subscription, TaffyLayoutEngine, Task, TextStyle, TextStyleRefinement, TransformationMatrix, Underline, UnderlineStyle, View, VisualContext, WeakView, WindowAppearance, WindowBackgroundAppearance, WindowBounds, WindowControls, WindowDecorations, WindowOptions, WindowParams, WindowTextSystem, SUBPIXEL_VARIANTS, }; use anyhow::{anyhow, Context as _, Result}; use collections::{FxHashMap, FxHashSet}; use derive_more::{Deref, DerefMut}; use futures::channel::oneshot; use futures::FutureExt; #[cfg(target_os = "macos")] use media::core_video::CVImageBuffer; use parking_lot::RwLock; use refineable::Refineable; use slotmap::SlotMap; use smallvec::SmallVec; use std::{ any::{Any, TypeId}, borrow::{Borrow, BorrowMut, Cow}, cell::{Cell, RefCell}, cmp, fmt::{Debug, Display}, future::Future, hash::{Hash, Hasher}, marker::PhantomData, mem, ops::Range, rc::Rc, sync::{ atomic::{AtomicUsize, Ordering::SeqCst}, Arc, Weak, }, time::{Duration, Instant}, }; use util::post_inc; use util::{measure, ResultExt}; use uuid::Uuid; mod prompts; pub use prompts::*; pub(crate) const DEFAULT_WINDOW_SIZE: Size<Pixels> = size(px(1024.), px(700.)); /// Represents the two different phases when dispatching events. #[derive(Default, Copy, Clone, Debug, Eq, PartialEq)] pub enum DispatchPhase { /// After the capture phase comes the bubble phase, in which mouse event listeners are /// invoked front to back and keyboard event listeners are invoked from the focused element /// to the root of the element tree. This is the phase you'll most commonly want to use when /// registering event listeners. #[default] Bubble, /// During the initial capture phase, mouse event listeners are invoked back to front, and keyboard /// listeners are invoked from the root of the tree downward toward the focused element. This phase /// is used for special purposes such as clearing the "pressed" state for click events. If /// you stop event propagation during this phase, you need to know what you're doing. Handlers /// outside of the immediate region may rely on detecting non-local events during this phase. Capture, } impl DispatchPhase { /// Returns true if this represents the "bubble" phase. pub fn bubble(self) -> bool { self == DispatchPhase::Bubble } /// Returns true if this represents the "capture" phase. pub fn capture(self) -> bool { self == DispatchPhase::Capture } } type AnyObserver = Box<dyn FnMut(&mut WindowContext) -> bool + 'static>; type AnyWindowFocusListener = Box<dyn FnMut(&WindowFocusEvent, &mut WindowContext) -> bool + 'static>; struct WindowFocusEvent { previous_focus_path: SmallVec<[FocusId; 8]>, current_focus_path: SmallVec<[FocusId; 8]>, } impl WindowFocusEvent { pub fn is_focus_in(&self, focus_id: FocusId) -> bool { !self.previous_focus_path.contains(&focus_id) && self.current_focus_path.contains(&focus_id) } pub fn is_focus_out(&self, focus_id: FocusId) -> bool { self.previous_focus_path.contains(&focus_id) && !self.current_focus_path.contains(&focus_id) } } /// This is provided when subscribing for `ViewContext::on_focus_out` events. pub struct FocusOutEvent { /// A weak focus handle representing what was blurred. pub blurred: WeakFocusHandle, } slotmap::new_key_type! { /// A globally unique identifier for a focusable element. pub struct FocusId; } thread_local! { /// 8MB wasn't quite enough... pub(crate) static ELEMENT_ARENA: RefCell<Arena> = RefCell::new(Arena::new(32 * 1024 * 1024)); } impl FocusId { /// Obtains whether the element associated with this handle is currently focused. pub fn is_focused(&self, cx: &WindowContext) -> bool { cx.window.focus == Some(*self) } /// Obtains whether the element associated with this handle contains the focused /// element or is itself focused. pub fn contains_focused(&self, cx: &WindowContext) -> bool { cx.focused() .map_or(false, |focused| self.contains(focused.id, cx)) } /// Obtains whether the element associated with this handle is contained within the /// focused element or is itself focused. pub fn within_focused(&self, cx: &WindowContext) -> bool { let focused = cx.focused(); focused.map_or(false, |focused| focused.id.contains(*self, cx)) } /// 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) } } /// A handle which can be used to track and manipulate the focused element in a window. pub struct FocusHandle { pub(crate) id: FocusId, handles: Arc<RwLock<SlotMap<FocusId, AtomicUsize>>>, } impl std::fmt::Debug for FocusHandle { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.write_fmt(format_args!("FocusHandle({:?})", self.id)) } } impl FocusHandle { pub(crate) fn new(handles: &Arc<RwLock<SlotMap<FocusId, AtomicUsize>>>) -> Self { let id = handles.write().insert(AtomicUsize::new(1)); Self { id, handles: handles.clone(), } } pub(crate) fn for_id( id: FocusId, handles: &Arc<RwLock<SlotMap<FocusId, AtomicUsize>>>, ) -> Option<Self> { let lock = handles.read(); let ref_count = lock.get(id)?; if ref_count.load(SeqCst) == 0 { None } else { ref_count.fetch_add(1, SeqCst); Some(Self { id, handles: handles.clone(), }) } } /// Converts this focus handle into a weak variant, which does not prevent it from being released. pub fn downgrade(&self) -> WeakFocusHandle { WeakFocusHandle { id: self.id, handles: Arc::downgrade(&self.handles), } } /// Moves the focus to the element associated with this handle. pub fn focus(&self, cx: &mut WindowContext) { cx.focus(self) } /// Obtains whether the element associated with this handle is currently focused. pub fn is_focused(&self, cx: &WindowContext) -> bool { self.id.is_focused(cx) } /// Obtains whether the element associated with this handle contains the focused /// element or is itself focused. pub fn contains_focused(&self, cx: &WindowContext) -> bool { self.id.contains_focused(cx) } /// Obtains whether the element associated with this handle is contained within the /// focused element or is itself focused. pub fn within_focused(&self, cx: &WindowContext) -> bool { self.id.within_focused(cx) } /// Obtains whether this handle contains the given handle in the most recently rendered frame. pub fn contains(&self, other: &Self, cx: &WindowContext) -> bool { self.id.contains(other.id, cx) } /// Dispatch an action on the element that rendered this focus handle pub fn dispatch_action(&self, action: &dyn Action, cx: &mut WindowContext) { if let Some(node_id) = cx .window .rendered_frame .dispatch_tree .focusable_node_id(self.id) { cx.dispatch_action_on_node(node_id, action) } } } impl Clone for FocusHandle { fn clone(&self) -> Self { Self::for_id(self.id, &self.handles).unwrap() } } impl PartialEq for FocusHandle { fn eq(&self, other: &Self) -> bool { self.id == other.id } } impl Eq for FocusHandle {} impl Drop for FocusHandle { fn drop(&mut self) { self.handles .read() .get(self.id) .unwrap() .fetch_sub(1, SeqCst); } } /// A weak reference to a focus handle. #[derive(Clone, Debug)] pub struct WeakFocusHandle { pub(crate) id: FocusId, handles: Weak<RwLock<SlotMap<FocusId, AtomicUsize>>>, } impl WeakFocusHandle { /// Attempts to upgrade the [WeakFocusHandle] to a [FocusHandle]. pub fn upgrade(&self) -> Option<FocusHandle> { let handles = self.handles.upgrade()?; FocusHandle::for_id(self.id, &handles) } } impl PartialEq for WeakFocusHandle { fn eq(&self, other: &WeakFocusHandle) -> bool { self.id == other.id } } impl Eq for WeakFocusHandle {} impl PartialEq<FocusHandle> for WeakFocusHandle { fn eq(&self, other: &FocusHandle) -> bool { self.id == other.id } } impl PartialEq<WeakFocusHandle> for FocusHandle { fn eq(&self, other: &WeakFocusHandle) -> bool { self.id == other.id } } /// FocusableView allows users of your view to easily /// focus it (using cx.focus_view(view)) pub trait FocusableView: 'static + Render { /// Returns the focus handle associated with this view. fn focus_handle(&self, cx: &AppContext) -> FocusHandle; } /// ManagedView is a view (like a Modal, Popover, Menu, etc.) /// where the lifecycle of the view is handled by another view. pub trait ManagedView: FocusableView + EventEmitter<DismissEvent> {} impl<M: FocusableView + EventEmitter<DismissEvent>> ManagedView for M {} /// Emitted by implementers of [`ManagedView`] to indicate the view should be dismissed, such as when a view is presented as a modal. pub struct DismissEvent; type FrameCallback = Box<dyn FnOnce(&mut WindowContext)>; pub(crate) type AnyMouseListener = Box<dyn FnMut(&dyn Any, DispatchPhase, &mut WindowContext) + 'static>; #[derive(Clone)] pub(crate) struct CursorStyleRequest { pub(crate) hitbox_id: HitboxId, pub(crate) style: CursorStyle, } /// An identifier for a [Hitbox]. #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)] pub struct HitboxId(usize); impl HitboxId { /// Checks if the hitbox with this id is currently hovered. pub fn is_hovered(&self, cx: &WindowContext) -> bool { cx.window.mouse_hit_test.0.contains(self) } } /// A rectangular region that potentially blocks hitboxes inserted prior. /// See [WindowContext::insert_hitbox] for more details. #[derive(Clone, Debug, Deref)] pub struct Hitbox { /// A unique identifier for the hitbox. pub id: HitboxId, /// The bounds of the hitbox. #[deref] pub bounds: Bounds<Pixels>, /// The content mask when the hitbox was inserted. pub content_mask: ContentMask<Pixels>, /// Whether the hitbox occludes other hitboxes inserted prior. pub opaque: bool, } impl Hitbox { /// Checks if the hitbox is currently hovered. pub fn is_hovered(&self, cx: &WindowContext) -> bool { self.id.is_hovered(cx) } } #[derive(Default, Eq, PartialEq)] pub(crate) struct HitTest(SmallVec<[HitboxId; 8]>); /// An identifier for a tooltip. #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)] pub struct TooltipId(usize); impl TooltipId { /// Checks if the tooltip is currently hovered. pub fn is_hovered(&self, cx: &WindowContext) -> bool { cx.window .tooltip_bounds .as_ref() .map_or(false, |tooltip_bounds| { tooltip_bounds.id == *self && tooltip_bounds.bounds.contains(&cx.mouse_position()) }) } } pub(crate) struct TooltipBounds { id: TooltipId, bounds: Bounds<Pixels>, } #[derive(Clone)] pub(crate) struct TooltipRequest { id: TooltipId, tooltip: AnyTooltip, } pub(crate) struct DeferredDraw { priority: usize, parent_node: DispatchNodeId, element_id_stack: SmallVec<[ElementId; 32]>, text_style_stack: Vec<TextStyleRefinement>, element: Option<AnyElement>, absolute_offset: Point<Pixels>, prepaint_range: Range<PrepaintStateIndex>, paint_range: Range<PaintIndex>, } pub(crate) struct Frame { pub(crate) focus: Option<FocusId>, pub(crate) window_active: bool, pub(crate) element_states: FxHashMap<(GlobalElementId, TypeId), ElementStateBox>, accessed_element_states: Vec<(GlobalElementId, TypeId)>, pub(crate) mouse_listeners: Vec<Option<AnyMouseListener>>, pub(crate) dispatch_tree: DispatchTree, pub(crate) scene: Scene, pub(crate) hitboxes: Vec<Hitbox>, pub(crate) deferred_draws: Vec<DeferredDraw>, pub(crate) input_handlers: Vec<Option<PlatformInputHandler>>, pub(crate) tooltip_requests: Vec<Option<TooltipRequest>>, pub(crate) cursor_styles: Vec<CursorStyleRequest>, #[cfg(any(test, feature = "test-support"))] pub(crate) debug_bounds: FxHashMap<String, Bounds<Pixels>>, } #[derive(Clone, Default)] pub(crate) struct PrepaintStateIndex { hitboxes_index: usize, tooltips_index: usize, deferred_draws_index: usize, dispatch_tree_index: usize, accessed_element_states_index: usize, line_layout_index: LineLayoutIndex, } #[derive(Clone, Default)] pub(crate) struct PaintIndex { scene_index: usize, mouse_listeners_index: usize, input_handlers_index: usize, cursor_styles_index: usize, accessed_element_states_index: usize, line_layout_index: LineLayoutIndex, } impl Frame { pub(crate) fn new(dispatch_tree: DispatchTree) -> Self { Frame { focus: None, window_active: false, element_states: FxHashMap::default(), accessed_element_states: Vec::new(), mouse_listeners: Vec::new(), dispatch_tree, scene: Scene::default(), hitboxes: Vec::new(), deferred_draws: Vec::new(), input_handlers: Vec::new(), tooltip_requests: Vec::new(), cursor_styles: Vec::new(), #[cfg(any(test, feature = "test-support"))] debug_bounds: FxHashMap::default(), } } pub(crate) fn clear(&mut self) { self.element_states.clear(); self.accessed_element_states.clear(); self.mouse_listeners.clear(); self.dispatch_tree.clear(); self.scene.clear(); self.input_handlers.clear(); self.tooltip_requests.clear(); self.cursor_styles.clear(); self.hitboxes.clear(); self.deferred_draws.clear(); self.focus = None; } pub(crate) fn hit_test(&self, position: Point<Pixels>) -> HitTest { let mut hit_test = HitTest::default(); for hitbox in self.hitboxes.iter().rev() { let bounds = hitbox.bounds.intersect(&hitbox.content_mask.bounds); if bounds.contains(&position) { hit_test.0.push(hitbox.id); if hitbox.opaque { break; } } } hit_test } pub(crate) fn focus_path(&self) -> SmallVec<[FocusId; 8]> { self.focus .map(|focus_id| self.dispatch_tree.focus_path(focus_id)) .unwrap_or_default() } pub(crate) fn finish(&mut self, prev_frame: &mut Self) { for element_state_key in &self.accessed_element_states { if let Some((element_state_key, element_state)) = prev_frame.element_states.remove_entry(element_state_key) { self.element_states.insert(element_state_key, element_state); } } self.scene.finish(); }