#[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, 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, SubscriberSet, Subscription, SystemWindowTab, SystemWindowTabController, TabStopMap, TaffyLayoutEngine, Task, TextStyle, TextStyleRefinement, 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! { pub(crate) static ELEMENT_ARENA: RefCell<Arena> = RefCell::new(Arena::new(1024 * 1024));} /// Returned when the element arena has been used and so must be cleared before the next draw.#[must_use]pub struct ArenaClearNeeded; impl ArenaClearNeeded { /// Clear the element arena. pub fn clear(self) { ELEMENT_ARENA.with_borrow_mut(|element_arena| { element_arena.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) { 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() .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 }} /// 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>, pub(crate) style: CursorStyle,} #[derive(Default, Eq, PartialEq)]pub(crate) struct HitTest { pub(crate) ids: SmallVec<[HitboxId; 8]>, pub(crate) hover_hitbox_count: usize,} /// A type of window control area that corresponds to the platform window.#[derive(Clone, Copy, Debug, Eq, PartialEq)]pub enum WindowControlArea { /// An area that allows dragging of the platform window. Drag, /// An area that allows closing of the platform window. Close, /// An area that allows maximizing of the platform window. Max, /// An area that allows minimizing of the platform window. Min,} /// An identifier for a [Hitbox] which also includes [HitboxBehavior].#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]pub struct HitboxId(u64); Lines 1–500 of 5148. Load more
#[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, 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, SubscriberSet, Subscription, SystemWindowTab, SystemWindowTabController, TabStopMap, TaffyLayoutEngine, Task, TextStyle, TextStyleRefinement, 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! { pub(crate) static ELEMENT_ARENA: RefCell<Arena> = RefCell::new(Arena::new(1024 * 1024)); } /// Returned when the element arena has been used and so must be cleared before the next draw. #[must_use] pub struct ArenaClearNeeded; impl ArenaClearNeeded { /// Clear the element arena. pub fn clear(self) { ELEMENT_ARENA.with_borrow_mut(|element_arena| { element_arena.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) { 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() .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 } } /// 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>, pub(crate) style: CursorStyle, } #[derive(Default, Eq, PartialEq)] pub(crate) struct HitTest { pub(crate) ids: SmallVec<[HitboxId; 8]>, pub(crate) hover_hitbox_count: usize, } /// A type of window control area that corresponds to the platform window. #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum WindowControlArea { /// An area that allows dragging of the platform window. Drag, /// An area that allows closing of the platform window. Close, /// An area that allows maximizing of the platform window. Max, /// An area that allows minimizing of the platform window. Min, } /// An identifier for a [Hitbox] which also includes [HitboxBehavior]. #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] pub struct HitboxId(u64);