4217 lines · 149.6 KB · Rust
RawDownload
use crate::{    Action, AnyDrag, AnyElement, AnyTooltip, AnyView, App, AppContext, Arena, Asset,    AsyncWindowContext, AvailableSpace, Background, BorderStyle, Bounds, BoxShadow, Context,    Corners, CursorStyle, Decorations, DevicePixels, DispatchActionListener, DispatchNodeId,    DispatchTree, DisplayId, Edges, Effect, Entity, EntityId, EventEmitter, FileDropEvent, FontId,    Global, GlobalElementId, GlyphId, GpuSpecs, Hsla, InputHandler, IsZero, KeyBinding, KeyContext,    KeyDownEvent, KeyEvent, Keystroke, KeystrokeEvent, LayoutId, LineLayoutIndex, 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, SMOOTH_SVG_SCALE_FACTOR,    SUBPIXEL_VARIANTS, ScaledPixels, Scene, Shadow, SharedString, Size, StrikethroughStyle, Style,    SubscriberSet, Subscription, TaffyLayoutEngine, Task, TextStyle, TextStyleRefinement,    TransformationMatrix, Underline, UnderlineStyle, WindowAppearance, WindowBackgroundAppearance,    WindowBounds, WindowControls, WindowDecorations, WindowOptions, WindowParams, WindowTextSystem,    point, prelude::*, px, size, transparent_black,};use anyhow::{Context as _, Result, anyhow};use collections::{FxHashMap, FxHashSet};#[cfg(target_os = "macos")]use core_video::pixel_buffer::CVPixelBuffer;use derive_more::{Deref, DerefMut};use futures::FutureExt;use futures::channel::oneshot;use parking_lot::RwLock;use raw_window_handle::{HandleError, HasWindowHandle};use refineable::Refineable;use slotmap::SlotMap;use smallvec::SmallVec;use std::{    any::{Any, TypeId},    borrow::Cow,    cell::{Cell, RefCell},    cmp,    fmt::{Debug, Display},    hash::{Hash, Hasher},    marker::PhantomData,    mem,    ops::{DerefMut, Range},    rc::Rc,    sync::{        Arc, Weak,        atomic::{AtomicUsize, Ordering::SeqCst},    },    time::{Duration, Instant},};use util::post_inc;use util::{ResultExt, measure};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    }} struct WindowInvalidatorInner {    pub dirty: bool,    pub draw_phase: DrawPhase,    pub dirty_views: FxHashSet<EntityId>,} #[derive(Clone)]pub(crate) struct WindowInvalidator {    inner: Rc<RefCell<WindowInvalidatorInner>>,} impl WindowInvalidator {    pub fn new() -> Self {        WindowInvalidator {            inner: Rc::new(RefCell::new(WindowInvalidatorInner {                dirty: true,                draw_phase: DrawPhase::None,                dirty_views: FxHashSet::default(),            })),        }    }     pub fn invalidate_view(&self, entity: EntityId, cx: &mut App) -> bool {        let mut inner = self.inner.borrow_mut();        inner.dirty_views.insert(entity);        if inner.draw_phase == DrawPhase::None {            inner.dirty = true;            cx.push_effect(Effect::Notify { emitter: entity });            true        } else {            false        }    }     pub fn is_dirty(&self) -> bool {        self.inner.borrow().dirty    }     pub fn set_dirty(&self, dirty: bool) {        self.inner.borrow_mut().dirty = dirty    }     pub fn set_phase(&self, phase: DrawPhase) {        self.inner.borrow_mut().draw_phase = phase    }     pub fn take_views(&self) -> FxHashSet<EntityId> {        mem::take(&mut self.inner.borrow_mut().dirty_views)    }     pub fn replace_views(&self, views: FxHashSet<EntityId>) {        self.inner.borrow_mut().dirty_views = views;    }     pub fn not_drawing(&self) -> bool {        self.inner.borrow().draw_phase == DrawPhase::None    }     #[track_caller]    pub fn debug_assert_paint(&self) {        debug_assert!(            matches!(self.inner.borrow().draw_phase, DrawPhase::Paint),            "this method can only be called during paint"        );    }     #[track_caller]    pub fn debug_assert_prepaint(&self) {        debug_assert!(            matches!(self.inner.borrow().draw_phase, DrawPhase::Prepaint),            "this method can only be called during request_layout, or prepaint"        );    }     #[track_caller]    pub fn debug_assert_paint_or_prepaint(&self) {        debug_assert!(            matches!(                self.inner.borrow().draw_phase,                DrawPhase::Paint | DrawPhase::Prepaint            ),            "this method can only be called during request_layout, prepaint, or paint"        );    }} type AnyObserver = Box<dyn FnMut(&mut Window, &mut App) -> bool + 'static>; pub(crate) type AnyWindowFocusListener =    Box<dyn FnMut(&WindowFocusEvent, &mut Window, &mut App) -> bool + 'static>; pub(crate) struct WindowFocusEvent {    pub(crate) previous_focus_path: SmallVec<[FocusId; 8]>,    pub(crate) 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 `Context::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));} pub(crate) type FocusMap = RwLock<SlotMap<FocusId, AtomicUsize>>; impl FocusId {    /// Obtains whether the element associated with this handle is currently focused.    pub fn is_focused(&self, window: &Window) -> bool {        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, window: &Window, cx: &App) -> bool {        window            .focused(cx)            .map_or(false, |focused| self.contains(focused.id, window))    }     /// Obtains whether the element associated with this handle is contained within the    /// focused element or is itself focused.    pub fn within_focused(&self, window: &Window, cx: &App) -> bool {        let focused = window.focused(cx);        focused.map_or(false, |focused| focused.id.contains(*self, window))    }     /// Obtains whether this handle contains the given handle in the most recently rendered frame.    pub(crate) fn contains(&self, other: Self, window: &Window) -> bool {        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<FocusMap>,} 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<FocusMap>) -> Self {        let id = handles.write().insert(AtomicUsize::new(1));        Self {            id,            handles: handles.clone(),        }    }     pub(crate) fn for_id(id: FocusId, handles: &Arc<FocusMap>) -> 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, window: &mut Window) {        window.focus(self)    }     /// Obtains whether the element associated with this handle is currently focused.    pub fn is_focused(&self, window: &Window) -> bool {        self.id.is_focused(window)    }     /// Obtains whether the element associated with this handle contains the focused    /// element or is itself focused.    pub fn contains_focused(&self, window: &Window, cx: &App) -> bool {        self.id.contains_focused(window, cx)    }     /// Obtains whether the element associated with this handle is contained within the    /// focused element or is itself focused.    pub fn within_focused(&self, window: &Window, cx: &mut App) -> bool {        self.id.within_focused(window, cx)    }     /// Obtains whether this handle contains the given handle in the most recently rendered frame.    pub fn contains(&self, other: &Self, window: &Window) -> bool {        self.id.contains(other.id, window)    }     /// Dispatch an action on the element that rendered this focus handle    pub fn dispatch_action(&self, action: &dyn Action, window: &mut Window, cx: &mut App) {        if let Some(node_id) = window            .rendered_frame            .dispatch_tree            .focusable_node_id(self.id)        {            window.dispatch_action_on_node(node_id, action, cx)        }    }} 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,    pub(crate) handles: Weak<FocusMap>,} 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    }} /// Focusable allows users of your view to easily/// focus it (using window.focus_view(cx, view))pub trait Focusable: 'static {    /// Returns the focus handle associated with this view.    fn focus_handle(&self, cx: &App) -> FocusHandle;} impl<V: Focusable> Focusable for Entity<V> {    fn focus_handle(&self, cx: &App) -> FocusHandle {        self.read(cx).focus_handle(cx)    }} /// ManagedView is a view (like a Modal, Popover, Menu, etc.)/// where the lifecycle of the view is handled by another view.pub trait ManagedView: Focusable + EventEmitter<DismissEvent> + Render {} impl<M: Focusable + EventEmitter<DismissEvent> + Render> 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 Window, &mut App)>; pub(crate) type AnyMouseListener =    Box<dyn FnMut(&dyn Any, DispatchPhase, &mut Window, &mut App) + 'static>; #[derive(Clone)]pub(crate) struct CursorStyleRequest {    pub(crate) hitbox_id: Option<HitboxId>, // None represents whole window    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, window: &Window) -> bool {        window.mouse_hit_test.0.contains(self)    }} /// A rectangular region that potentially blocks hitboxes inserted prior./// See [Window::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, window: &Window) -> bool {        self.id.is_hovered(window)    }} #[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, window: &Window) -> bool {        window            .tooltip_bounds            .as_ref()            .map_or(false, |tooltip_bounds| {                tooltip_bounds.id == *self                    && tooltip_bounds.bounds.contains(&window.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 {    current_view: EntityId,    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>>,

Lines 1–500 of 4217.