4681 lines · 162.1 KB · Rust
RawDownload
use crate::{    hash, point, prelude::*, px, size, transparent_black, Action, AnyDrag, AnyElement, AnyTooltip,    AnyView, AppContext, Arena, Asset, AsyncWindowContext, AvailableSpace, Bounds, BoxShadow,    Context, Corners, CursorStyle, DevicePixels, DispatchActionListener, DispatchNodeId,    DispatchTree, DisplayId, Edges, Effect, Entity, EntityId, EventEmitter, FileDropEvent, Flatten,    FontId, Global, GlobalElementId, GlyphId, Hsla, ImageData, InputHandler, IsZero, KeyBinding,    KeyContext, KeyDownEvent, KeyEvent, KeyMatch, KeymatchResult, Keystroke, KeystrokeEvent,    LayoutId, LineLayoutIndex, Model, ModelContext, Modifiers, ModifiersChangedEvent,    MonochromeSprite, MouseButton, MouseEvent, MouseMoveEvent, MouseUpEvent, Path, Pixels,    PlatformAtlas, PlatformDisplay, PlatformInput, PlatformInputHandler, PlatformWindow, Point,    PolychromeSprite, PromptLevel, Quad, Render, RenderGlyphParams, RenderImageParams,    RenderSvgParams, ScaledPixels, Scene, Shadow, SharedString, Size, StrikethroughStyle, Style,    SubscriberSet, Subscription, TaffyLayoutEngine, Task, TextStyle, TextStyleRefinement,    TransformationMatrix, Underline, UnderlineStyle, View, VisualContext, WeakView,    WindowAppearance, WindowBackgroundAppearance, WindowBounds, 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::{future::Shared, 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}; mod prompts; pub use prompts::*; pub(crate) const DEFAULT_WINDOW_SIZE: Size<DevicePixels> =    size(DevicePixels(1024), DevicePixels(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(&FocusEvent, &mut WindowContext) -> bool + 'static>; struct FocusEvent {    previous_focus_path: SmallVec<[FocusId; 8]>,    current_focus_path: SmallVec<[FocusId; 8]>,} 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();    }     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();    }} // Holds the state for a specific window.#[doc(hidden)]pub struct Window {    pub(crate) handle: AnyWindowHandle,    pub(crate) removed: bool,    pub(crate) platform_window: Box<dyn PlatformWindow>,    display_id: DisplayId,    sprite_atlas: Arc<dyn PlatformAtlas>,    text_system: Arc<WindowTextSystem>,    rem_size: Pixels,    /// The stack of override values for the window's rem size.    ///    /// This is used by `with_rem_size` to allow rendering an element tree with    /// a given rem size.    rem_size_override_stack: SmallVec<[Pixels; 8]>,    pub(crate) viewport_size: Size<Pixels>,    layout_engine: Option<TaffyLayoutEngine>,

Lines 1–500 of 4681.