5495 lines · 199.1 KB · Rust
RawDownload
#[cfg(any(feature = "inspector", debug_assertions))]use crate::Inspector;use crate::{    Action, AnyDrag, AnyElement, AnyImageCache, AnyTooltip, AnyView, App, AppContext, Arena, Asset,    AsyncWindowContext, AvailableSpace, Background, BorderStyle, Bounds, BoxShadow, Capslock,    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, Priority, PromptButton,    PromptLevel, Quad, Render, RenderGlyphParams, RenderImage, RenderImageParams, RenderSvgParams,    Replay, ResizeEdge, SMOOTH_SVG_SCALE_FACTOR, SUBPIXEL_VARIANTS_X, SUBPIXEL_VARIANTS_Y,    ScaledPixels, Scene, Shadow, SharedString, Size, StrikethroughStyle, Style, SubpixelSprite,    SubscriberSet, Subscription, SystemWindowTab, SystemWindowTabController, TabStopMap,    TaffyLayoutEngine, Task, TextRenderingMode, TextStyle, TextStyleRefinement, ThermalState,    TransformationMatrix, Underline, UnderlineStyle, WindowAppearance, WindowBackgroundAppearance,    WindowBounds, WindowControls, WindowDecorations, WindowOptions, WindowParams, WindowTextSystem,    point, prelude::*, px, rems, 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 itertools::FoldWhile::{Continue, Done};use itertools::Itertools;use parking_lot::RwLock;use raw_window_handle::{HandleError, HasDisplayHandle, 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; use crate::util::atomic_incr_if_not_zero;pub use prompts::*; pub(crate) const DEFAULT_WINDOW_SIZE: Size<Pixels> = size(px(1536.), px(864.)); /// A 6:5 aspect ratio minimum window size to be used for functional,/// additional-to-main-Zed windows, like the settings and rules library windows.pub const DEFAULT_ADDITIONAL_WINDOW_SIZE: Size<Pixels> = Size {    width: Pixels(900.),    height: Pixels(750.),}; /// 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.    #[inline]    pub fn bubble(self) -> bool {        self == DispatchPhase::Bubble    }     /// Returns true if this represents the "capture" phase.    #[inline]    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! {    /// Fallback arena used when no app-specific arena is active.    /// In production, each window draw sets CURRENT_ELEMENT_ARENA to the app's arena.    pub(crate) static ELEMENT_ARENA: RefCell<Arena> = RefCell::new(Arena::new(1024 * 1024));     /// Points to the current App's element arena during draw operations.    /// This allows multiple test Apps to have isolated arenas, preventing    /// cross-session corruption when the scheduler interleaves their tasks.    static CURRENT_ELEMENT_ARENA: Cell<Option<*const RefCell<Arena>>> = const { Cell::new(None) };} /// Allocates an element in the current arena. Uses the app-specific arena if one/// is active (during draw), otherwise falls back to the thread-local ELEMENT_ARENA.pub(crate) fn with_element_arena<R>(f: impl FnOnce(&mut Arena) -> R) -> R {    CURRENT_ELEMENT_ARENA.with(|current| {        if let Some(arena_ptr) = current.get() {            // SAFETY: The pointer is valid for the duration of the draw operation            // that set it, and we're being called during that same draw.            let arena_cell = unsafe { &*arena_ptr };            f(&mut arena_cell.borrow_mut())        } else {            ELEMENT_ARENA.with_borrow_mut(f)        }    })} /// RAII guard that sets CURRENT_ELEMENT_ARENA for the duration of a draw operation./// When dropped, restores the previous arena (supporting nested draws).pub(crate) struct ElementArenaScope {    previous: Option<*const RefCell<Arena>>,} impl ElementArenaScope {    /// Enter a scope where element allocations use the given arena.    pub(crate) fn enter(arena: &RefCell<Arena>) -> Self {        let previous = CURRENT_ELEMENT_ARENA.with(|current| {            let prev = current.get();            current.set(Some(arena as *const RefCell<Arena>));            prev        });        Self { previous }    }} impl Drop for ElementArenaScope {    fn drop(&mut self) {        CURRENT_ELEMENT_ARENA.with(|current| {            current.set(self.previous);        });    }} /// Returned when the element arena has been used and so must be cleared before the next draw.#[must_use]pub struct ArenaClearNeeded {    arena: *const RefCell<Arena>,} impl ArenaClearNeeded {    /// Create a new ArenaClearNeeded that will clear the given arena.    pub(crate) fn new(arena: &RefCell<Arena>) -> Self {        Self {            arena: arena as *const RefCell<Arena>,        }    }     /// Clear the element arena.    pub fn clear(self) {        // SAFETY: The arena pointer is valid because ArenaClearNeeded is created        // at the end of draw() and must be cleared before the next draw.        let arena_cell = unsafe { &*self.arena };        arena_cell.borrow_mut().clear();    }} pub(crate) type FocusMap = RwLock<SlotMap<FocusId, FocusRef>>;pub(crate) struct FocusRef {    pub(crate) ref_count: AtomicUsize,    pub(crate) tab_index: isize,    pub(crate) tab_stop: bool,} 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)            .is_some_and(|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.is_some_and(|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>,    /// The index of this element in the tab order.    pub tab_index: isize,    /// Whether this element can be focused by tab navigation.    pub tab_stop: bool,} 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(FocusRef {            ref_count: AtomicUsize::new(1),            tab_index: 0,            tab_stop: false,        });         Self {            id,            tab_index: 0,            tab_stop: false,            handles: handles.clone(),        }    }     pub(crate) fn for_id(id: FocusId, handles: &Arc<FocusMap>) -> Option<Self> {        let lock = handles.read();        let focus = lock.get(id)?;        if atomic_incr_if_not_zero(&focus.ref_count) == 0 {            return None;        }        Some(Self {            id,            tab_index: focus.tab_index,            tab_stop: focus.tab_stop,            handles: handles.clone(),        })    }     /// Sets the tab index of the element associated with this handle.    pub fn tab_index(mut self, index: isize) -> Self {        self.tab_index = index;        if let Some(focus) = self.handles.write().get_mut(self.id) {            focus.tab_index = index;        }        self    }     /// Sets whether the element associated with this handle is a tab stop.    ///    /// When `false`, the element will not be included in the tab order.    pub fn tab_stop(mut self, tab_stop: bool) -> Self {        self.tab_stop = tab_stop;        if let Some(focus) = self.handles.write().get_mut(self.id) {            focus.tab_stop = tab_stop;        }        self    }     /// 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, cx: &mut App) {        window.focus(self, cx)    }     /// 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()            .ref_count            .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

Lines 1–500 of 5495.