Struct PopupOverlayMounts

Source
pub struct PopupOverlayMounts<A> { /* private fields */ }
Expand description

Persistent retained popup trees for one logical window presentation.

Closed registrations remain cached, so reopening the same registered popup reconciles into the same tree and preserves component state. A mount is destroyed only when its registration disappears or its owner no longer belongs to the synchronized presentation. Pointer capture/hover and focus are isolated per popup tree, while z-order follows the shared portal. This value is UI-thread-local through its runtime handle and component state.

§Examples

use ailloli_ui_runtime::{app::RuntimeHandle, popup_mount::PopupOverlayMounts};
let mounts = PopupOverlayMounts::new(RuntimeHandle::<()>::new());
assert!(mounts.is_empty());

Implementations§

Source§

impl<A: 'static> PopupOverlayMounts<A>

Synchronization, frame stages, hit-testing, and event routing for overlays.

Source

pub fn new(runtime: RuntimeHandle<A>) -> Self

Creates an empty mount cache sharing runtime’s portal/application state.

No retained tree or presentation scope is allocated until synchronization observes a matching retained-overlay registration.

§Examples
use ailloli_ui_runtime::{app::RuntimeHandle, popup_mount::PopupOverlayMounts};
let mounts = PopupOverlayMounts::new(RuntimeHandle::<()>::new());
assert_eq!((mounts.len(), mounts.open_len()), (0, 0));
Source

pub fn len(&self) -> usize

Returns cached persistent popup-tree count, including closed entries.

§Examples
use ailloli_ui_runtime::{app::RuntimeHandle, popup_mount::PopupOverlayMounts};
assert_eq!(PopupOverlayMounts::new(RuntimeHandle::<()>::new()).len(), 0);
Source

pub fn is_empty(&self) -> bool

Reports whether no persistent popup tree is cached.

Closed cached mounts make this false even when Self::open_len is zero.

§Examples
use ailloli_ui_runtime::{app::RuntimeHandle, popup_mount::PopupOverlayMounts};
assert!(PopupOverlayMounts::new(RuntimeHandle::<()>::new()).is_empty());
Source

pub fn open_len(&self) -> usize

Returns the number of currently open matching retained overlays.

§Examples
use ailloli_ui_runtime::{app::RuntimeHandle, popup_mount::PopupOverlayMounts};
assert_eq!(PopupOverlayMounts::new(RuntimeHandle::<()>::new()).open_len(), 0);
Source

pub fn contains(&self, popup_id: PopupId) -> bool

Reports whether a persistent tree is cached for popup_id.

This is distinct from portal registration and open state.

§Examples
use ailloli_ui_runtime::{app::RuntimeHandle, popup::PopupId, popup_mount::PopupOverlayMounts};
assert!(!PopupOverlayMounts::new(RuntimeHandle::<()>::new()).contains(PopupId::new(1)));
Source

pub fn element_tree_id(&self, popup_id: PopupId) -> Option<ElementTreeId>

Returns a cached popup mount’s allocated retained-tree namespace.

None means the popup has no retained mount, even if a procedural or unsynchronized portal registration exists.

§Examples
use ailloli_ui_runtime::{app::RuntimeHandle, popup::PopupId, popup_mount::PopupOverlayMounts};
assert_eq!(PopupOverlayMounts::new(RuntimeHandle::<()>::new()).element_tree_id(PopupId::new(1)), None);
Source

pub fn owner(&self, popup_id: PopupId) -> Option<&PopupOwner>

Borrows the last synchronized owner of a cached mount.

None means no retained mount is cached. Owner liveness can change in the portal until the next synchronization.

§Examples
use ailloli_ui_runtime::{app::RuntimeHandle, popup::PopupId, popup_mount::PopupOverlayMounts};
assert!(PopupOverlayMounts::new(RuntimeHandle::<()>::new()).owner(PopupId::new(1)).is_none());
Source

pub fn focus_owner(&self) -> Option<PopupMountFocus>

Snapshots strict keyboard focus in the claimed popup tree.

None means no mounted popup currently owns a focused element or cached focus state became stale.

§Examples
use ailloli_ui_runtime::{app::RuntimeHandle, popup_mount::PopupOverlayMounts};
assert!(PopupOverlayMounts::new(RuntimeHandle::<()>::new()).focus_owner().is_none());
Source

pub fn has_focus(&self) -> bool

Whether keyboard focus currently belongs to a retained popup tree.

§Examples
use ailloli_ui_runtime::{app::RuntimeHandle, popup_mount::PopupOverlayMounts};
assert!(!PopupOverlayMounts::new(RuntimeHandle::<()>::new()).has_focus());
Source

pub fn focused_input_role(&self) -> InputRole

Input role of the focused retained-popup element.

Returns InputRole::None when no popup/element owns focus or the mount disappeared.

§Examples
use ailloli_ui_runtime::{app::RuntimeHandle, input::InputRole, popup_mount::PopupOverlayMounts};
assert_eq!(PopupOverlayMounts::new(RuntimeHandle::<()>::new()).focused_input_role(), InputRole::None);
Source

pub fn focused_ime_cursor_rect_global(&self) -> Option<Rect>

IME caret rectangle translated from popup-local to window coordinates.

Returns None without focused popup input, non-empty bounds, committed layout, or a widget-provided caret. Dimensions remain logical pixels.

§Examples
use ailloli_ui_runtime::{app::RuntimeHandle, popup_mount::PopupOverlayMounts};
assert!(PopupOverlayMounts::new(RuntimeHandle::<()>::new()).focused_ime_cursor_rect_global().is_none());
Source

pub fn hovered_cursor_role_at_global( &self, point: Point, ) -> Option<HoverCursorRole>

Cursor role under a window-global point when a retained popup owns it.

Some(Default) deliberately masks the owner-tree cursor while the pointer rests on passive popup content. None means no retained popup occupies the point and lets the host query the owner tree instead. point and returned hit geometry use window-global logical pixels.

§Examples
use ailloli_ui_core::Point; use ailloli_ui_runtime::{app::RuntimeHandle, popup_mount::PopupOverlayMounts};
assert!(PopupOverlayMounts::new(RuntimeHandle::<()>::new()).hovered_cursor_role_at_global(Point::new(1.0, 1.0)).is_none());
Source

pub fn apply_pending_popup_intents(&mut self) -> bool

Applies queued popup focus effects to every mounted tree in z-order.

Hosts call this before applying the owner-tree effects so a nested popup can restore focus into its retained parent without leaking the intent into a sibling tree namespace. Returns whether any popup focus changed. Before the first sync there is no presentation and the method is a no-op returning false.

§Examples
use ailloli_ui_runtime::{app::RuntimeHandle, popup_mount::PopupOverlayMounts};
let mut mounts = PopupOverlayMounts::new(RuntimeHandle::<()>::new());
assert!(!mounts.apply_pending_popup_intents());
Source

pub fn sync( &mut self, logical_window_id: &LogicalWindowId, presentation_generation: PresentationGeneration, ) -> PopupMountSyncOutcome

Reconciles every open portal entry belonging to one exact presentation.

Calling this once per frame is intentional: retained reconciliation refreshes declarative props while component slots remain attached to the mount’s persistent element tree. Only RetainedOverlay registrations with exact logical-window/generation ownership participate. Existing closed matching registrations stay cached; removed/mismatched mounts are blurred and destroyed. New mounts are created only for open entries. The method also clears stale pointer and focus ownership. Portal factories/component builds run synchronously.

§Panics

Propagates content-factory/component reconciliation panics and panics on conflicting portal/runtime RefCell borrows.

§Examples
use ailloli_ui_core::LogicalWindowId; use ailloli_ui_runtime::{app::{PresentationGeneration, RuntimeHandle}, popup_mount::PopupOverlayMounts};
let mut mounts = PopupOverlayMounts::new(RuntimeHandle::<()>::new());
let outcome = mounts.sync(&LogicalWindowId::new("main"), PresentationGeneration::INITIAL);
assert_eq!((outcome.mounted(), outcome.removed(), outcome.open()), (0, 0, 0));
Source

pub fn resolve_and_sync( &mut self, logical_window_id: &LogicalWindowId, presentation_generation: PresentationGeneration, viewport: Rect, capabilities: PopupBackendCapabilities, ) -> PopupMountSyncOutcome

Resolves retained-overlay geometry for one host viewport, then syncs the persistent popup trees.

Requests that already carry backend-published bounds but omit the declarative anchor or desired size keep those explicit bounds. This preserves low-level hosts while allowing fully provider-neutral popup requests to flip and clamp through the shared resolver. Placement failures are intentionally ignored here; such entries retain previous explicit bounds (if any) and still synchronize. Successfully resolved bounds are recorded with viewport before Self::sync. All geometry uses global logical pixels.

§Examples
use ailloli_ui_core::{LogicalWindowId, Rect}; use ailloli_ui_runtime::{app::{PresentationGeneration, RuntimeHandle}, popup::PopupBackendCapabilities, popup_mount::PopupOverlayMounts};
let mut mounts = PopupOverlayMounts::new(RuntimeHandle::<()>::new());
let outcome = mounts.resolve_and_sync(&LogicalWindowId::new("main"), PresentationGeneration::INITIAL, Rect::new(0.0, 0.0, 800.0, 600.0), PopupBackendCapabilities::overlay_only());
assert_eq!(outcome.open(), 0);
Source

pub fn layout(&mut self, scale: Scale, text_system: &mut TextSystem)

Lays out all open popup trees in their non-empty portal bounds.

Width/height become tight logical-pixel constraints; scale is physical pixels per logical pixel. Missing/zero-or-negative bounds are skipped. Pending focus-on-open is applied after successful layout and focus is made exclusive across mounts.

§Panics

Propagates widget layout/focus callback panics.

§Examples
use ailloli_ui_core::Scale; use ailloli_ui_runtime::{app::RuntimeHandle, popup_mount::PopupOverlayMounts}; use ailloli_ui_text::TextSystem;
let mut mounts = PopupOverlayMounts::new(RuntimeHandle::<()>::new());
mounts.layout(Scale::new(1.0), &mut TextSystem::new());
assert_eq!(mounts.open_len(), 0);
Source

pub fn paint(&self, text_system: &mut TextSystem, frame_time_ms: u128) -> Scene

Produces overlay layers in portal z-order, clipped to popup bounds.

Mounts without non-empty bounds/root are skipped. Painting translates popup-local geometry by the window-global bounds origin, forces every emitted layer to LayerKind::Overlay, and exposes frame_time_ms verbatim to widget paint callbacks.

§Examples
use ailloli_ui_runtime::{app::RuntimeHandle, popup_mount::PopupOverlayMounts}; use ailloli_ui_text::TextSystem;
let mounts = PopupOverlayMounts::new(RuntimeHandle::<()>::new());
assert!(mounts.paint(&mut TextSystem::new(), 16).layers.is_empty());
Source

pub fn append_to_scene( &self, scene: &mut Scene, text_system: &mut TextSystem, frame_time_ms: u128, )

Appends retained popup layers after the owner scene.

Existing layers retain their order and popup layers append in portal bottom-to-top order. No sorting or deduplication occurs.

§Examples
use ailloli_ui_runtime::{app::RuntimeHandle, popup_mount::PopupOverlayMounts, scene::Scene}; use ailloli_ui_text::TextSystem;
let mounts = PopupOverlayMounts::new(RuntimeHandle::<()>::new()); let mut scene = Scene::default();
mounts.append_to_scene(&mut scene, &mut TextSystem::new(), 0);
assert!(scene.layers.is_empty());
Source

pub fn hit_test(&self, point: Point) -> Option<PopupMountHit>

Hit-tests mounted content from topmost popup to bottommost.

point is window-global logical pixels. Portal bounds select a retained mount, then the point is translated to popup-local coordinates for tree hit-testing. Missing/non-positive bounds or non-widget hits yield None.

§Examples
use ailloli_ui_core::Point; use ailloli_ui_runtime::{app::RuntimeHandle, popup_mount::PopupOverlayMounts};
assert!(PopupOverlayMounts::new(RuntimeHandle::<()>::new()).hit_test(Point::new(1.0, 1.0)).is_none());
Source

pub fn route_envelope( &mut self, envelope: &EventEnvelope, ) -> PopupMountRouteOutcome

Applies portal authority once, then routes into a popup-local tree.

The caller should skip owner-tree dispatch when PopupMountRouteOutcome::consumed is true. Pointer coordinates are translated to the selected mount while all event correlation metadata is preserved. Envelopes outside the last synchronized logical window/generation are ignored. Pointer gesture consumption persists through matching release; Escape/outside press invoke portal authority before local dispatch; keyboard/IME route to the focused popup; window focus loss cancels every captured popup pointer before clearing interaction state.

§Examples
use std::time::Duration; use ailloli_ui_core::{event::{Event, FocusEvent}, LogicalWindowId};
use ailloli_ui_runtime::{app::{PresentationGeneration, RuntimeHandle}, input::{EventEnvelope, EventId, EventMeta, EventTimestamp}, popup_mount::PopupOverlayMounts};
let mut mounts = PopupOverlayMounts::new(RuntimeHandle::<()>::new()); let window = LogicalWindowId::new("main");
mounts.sync(&window, PresentationGeneration::INITIAL);
let envelope = EventEnvelope::new(EventMeta::new(EventId::new(1), EventTimestamp::new(Duration::ZERO), window, PresentationGeneration::INITIAL), Event::Focus(FocusEvent::new(true)));
assert!(!mounts.route_envelope(&envelope).consumed());

Trait Implementations§

Source§

impl<A> Drop for PopupOverlayMounts<A>

Clears every mounted tree’s presentation scope before child runtimes drop.

Source§

fn drop(&mut self)

Removes presentation-scoped pending effects for all cached mounts.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> ErasedDestructor for T
where T: 'static,