Struct InputRouter

Source
pub struct InputRouter {
    pub hit_test: HitTestEngine,
    pub focus: FocusManager,
    /* private fields */
}
Expand description

Per-window input state: hit-test, hover, press, focus, and event dispatch.

Pointer states are isolated by [PointerId] in deterministic key order. Mouse convenience methods use [PointerId::MOUSE]. The router owns no platform handles and remains provider-neutral; callbacks execute synchronously on the UI thread.

§Examples

use ailloli_ui_runtime::input::InputRouter;
let router = InputRouter::default();
assert!(router.hovered().is_none() && router.focused().is_none());

Fields§

§hit_test: HitTestEngine

Stateless rectangle hit-test helper.

§focus: FocusManager

Low-level strict keyboard-focus store.

Implementations§

Source§

impl InputRouter

Focus, semantic-role, pointer, popup, and event-routing operations.

Source

pub fn hovered(&self) -> Option<ElementId>

Returns the mouse hover target, or None.

§Examples
use ailloli_ui_runtime::input::InputRouter;
assert_eq!(InputRouter::default().hovered(), None);
Source

pub fn hovered_for(&self, pointer_id: PointerId) -> Option<ElementId>

Returns one pointer’s hover target, or None for unknown/idle IDs.

§Examples
use ailloli_ui_core::event::PointerId;
use ailloli_ui_runtime::input::InputRouter;
assert_eq!(InputRouter::default().hovered_for(PointerId::MOUSE), None);
Source

pub fn focused(&self) -> Option<ElementId>

Returns the strict keyboard-focus owner.

§Examples
use ailloli_ui_runtime::input::InputRouter;
assert_eq!(InputRouter::default().focused(), None);
Source

pub fn snapshot(&self) -> InputSnapshot

Returns focus plus mouse hover/press strict targets.

§Examples
use ailloli_ui_runtime::input::{InputRouter, InputSnapshot};
assert_eq!(InputRouter::default().snapshot(), InputSnapshot::default());
Source

pub fn snapshot_for(&self, pointer_id: PointerId) -> InputSnapshot

Returns focus plus strict targets for one pointer ID.

Unknown pointer IDs still include global focus and use None for hover and press.

§Examples
use ailloli_ui_core::event::PointerId;
use ailloli_ui_runtime::input::{InputRouter, InputSnapshot};
assert_eq!(InputRouter::default().snapshot_for(PointerId::MOUSE), InputSnapshot::default());
Source

pub fn active_pointer_ids(&self) -> impl Iterator<Item = PointerId> + '_

Iterates pointer IDs with retained nonempty state in sorted order.

The iterator borrows the router and allocates nothing.

§Examples
use ailloli_ui_runtime::input::InputRouter;
assert_eq!(InputRouter::default().active_pointer_ids().count(), 0);
Source

pub fn clear_pointer_state(&mut self) -> bool

Clears every pointer’s hover/press/capture/consumed-gesture state.

Returns whether any retained pointer state was nonempty. Focus is not changed and no widget events are dispatched. Use Self::cancel_pointer_state when capture owners must end gestures.

§Examples
use ailloli_ui_runtime::input::InputRouter;
assert!(!InputRouter::default().clear_pointer_state());
Source

pub fn clear_focus(&mut self) -> bool

Clears focus and cached focus metadata without dispatching blur.

Returns whether a focus ID was present. Hosts preserving widget event contracts should use Self::blur_tree.

§Examples
use ailloli_ui_core::ElementId;
use ailloli_ui_runtime::input::InputRouter;
let mut router = InputRouter::default();
router.focus.set_focused(Some(ElementId(3)));
assert!(router.clear_focus());
assert_eq!(router.focused(), None);
Source

pub fn blur_tree<A: 'static>( &mut self, tree: &ElementTree<A>, runtime: RuntimeHandle<A>, ) -> bool

Clears focus from a host-owned tree and dispatches its matching blur.

Unlike Self::clear_focus, this method preserves the widget event contract. Hosts use it when focus ownership moves between retained trees, for example between the main tree and a popup overlay. Returns true only when focus changed. A stale focus ID is cleared but receives no blur because it is absent from tree.

§Examples
use ailloli_ui_core::ElementId;
use ailloli_ui_runtime::app::RuntimeHandle;
use ailloli_ui_runtime::element::ElementTree;
use ailloli_ui_runtime::input::InputRouter;
let mut router = InputRouter::default();
router.focus.set_focused(Some(ElementId(9)));
assert!(router.blur_tree(&ElementTree::<()>::new(), RuntimeHandle::new()));
Source

pub fn cycle_focus_descendant<A: 'static>( &mut self, tree: &ElementTree<A>, runtime: RuntimeHandle<A>, reverse: bool, wrap: bool, ) -> bool

Moves focus through one retained tree in deterministic depth-first order.

reverse selects the Shift+Tab direction. At either boundary, wrap selects the opposite end; otherwise focus remains unchanged. The root participates when it is focusable, which keeps leaf-only popup trees keyboard reachable. Missing/malformed child IDs are skipped by focus-policy lookup, but a cyclic child graph can recurse indefinitely.

§Examples
use ailloli_ui_runtime::app::RuntimeHandle;
use ailloli_ui_runtime::element::ElementTree;
use ailloli_ui_runtime::input::InputRouter;
let mut router = InputRouter::default();
assert!(!router.cycle_focus_descendant(&ElementTree::<()>::new(), RuntimeHandle::new(), false, true));
Source

pub fn focused_input_role<A: 'static>(&self, tree: &ElementTree<A>) -> InputRole

Returns the current focused widget’s semantic input role.

Missing, empty, component, or unfocused targets return InputRole::None.

§Examples
use ailloli_ui_runtime::element::ElementTree;
use ailloli_ui_runtime::input::{InputRole, InputRouter};
assert_eq!(InputRouter::default().focused_input_role(&ElementTree::<()>::new()), InputRole::None);
Source

pub fn hovered_input_role<A: 'static>(&self, tree: &ElementTree<A>) -> InputRole

Returns the mouse-hovered widget’s semantic input role.

§Examples
use ailloli_ui_runtime::element::ElementTree;
use ailloli_ui_runtime::input::{InputRole, InputRouter};
assert_eq!(InputRouter::default().hovered_input_role(&ElementTree::<()>::new()), InputRole::None);
Source

pub fn hovered_cursor_role<A: 'static>( &self, tree: &ElementTree<A>, ) -> HoverCursorRole

Resolves the mouse-hover cursor role without positional specialization.

Inherit walks parents; no hovered target or reaching the root resolves to Default. A malformed parent cycle can loop indefinitely.

§Examples
use ailloli_ui_runtime::element::ElementTree;
use ailloli_ui_runtime::input::{HoverCursorRole, InputRouter};
assert_eq!(InputRouter::default().hovered_cursor_role(&ElementTree::<()>::new()), HoverCursorRole::Default);
Source

pub fn hovered_cursor_role_at<A: 'static>( &self, tree: &ElementTree<A>, pos: Point, ) -> HoverCursorRole

Resolves the mouse-hover cursor role at a window-space logical point.

Widgets can choose contextual resize/text roles from absolute bounds and cached layout. Missing layout on a hovered widget behaves as Inherit.

§Examples
use ailloli_ui_core::Point;
use ailloli_ui_runtime::element::ElementTree;
use ailloli_ui_runtime::input::{HoverCursorRole, InputRouter};
assert_eq!(InputRouter::default().hovered_cursor_role_at(&ElementTree::<()>::new(), Point::new(1.0, 2.0)), HoverCursorRole::Default);
Source

pub fn focused_ime_cursor_rect<A: 'static>( &self, tree: &ElementTree<A>, ) -> Option<Rect>

Returns the focused widget’s absolute logical IME cursor rectangle.

Returns None without focus, for stale/non-widget targets, without a cached layout, or when the widget declines to expose a rectangle.

§Examples
use ailloli_ui_runtime::element::ElementTree;
use ailloli_ui_runtime::input::InputRouter;
assert_eq!(InputRouter::default().focused_ime_cursor_rect(&ElementTree::<()>::new()), None);
Source

pub fn route_event<A: 'static>( &mut self, tree: &ElementTree<A>, runtime: RuntimeHandle<A>, event: &Event, ) -> RouteOutcome

Routes a metadata-free legacy event through hit test/focus/popup authority.

Pointer events use the mouse ID, popup work uses the headless presentation sentinel, and widget super::EventCtx::event_meta returns None. Routing also prunes stale targets and popup owners, applies focus-key and popup intents, and may synchronously invoke arbitrary widget code. Window focus loss dispatches pointer cancellation to every capture owner before clearing pointer state.

§Examples
use ailloli_ui_core::event::{Event, FocusEvent};
use ailloli_ui_runtime::app::RuntimeHandle;
use ailloli_ui_runtime::element::ElementTree;
use ailloli_ui_runtime::input::{InputRouter, RouteOutcome};
let outcome = InputRouter::default().route_event(
    &ElementTree::<()>::new(), RuntimeHandle::new(), &Event::Focus(FocusEvent::new(true)),
);
assert_eq!(outcome, RouteOutcome::default());
Source

pub fn route_envelope<A: 'static>( &mut self, tree: &ElementTree<A>, runtime: RuntimeHandle<A>, envelope: &EventEnvelope, ) -> RouteOutcome

Routes a provider-neutral event envelope while preserving its metadata in super::EventCtx and isolating pointer state by [PointerId].

Presentation metadata scopes popup pruning/dismissal and pointer metadata selects the independent pointer state. Metadata is not validated against the enclosed event variant. Window focus loss cancels each captured pointer with its last envelope metadata before clearing pointer state.

§Examples
use std::time::Duration;
use ailloli_ui_core::event::{Event, FocusEvent};
use ailloli_ui_runtime::app::{PresentationGeneration, RuntimeHandle};
use ailloli_ui_runtime::element::ElementTree;
use ailloli_ui_runtime::input::{EventEnvelope, EventId, EventMeta, EventTimestamp, InputRouter};
let meta = EventMeta::new(EventId::new(1), EventTimestamp::new(Duration::ZERO), "main", PresentationGeneration::INITIAL);
let envelope = EventEnvelope::new(meta, Event::Focus(FocusEvent::new(true)));
assert!(!InputRouter::default().route_envelope(&ElementTree::<()>::new(), RuntimeHandle::new(), &envelope).event_dispatched);
Source

pub fn apply_pending_focus_request<A: 'static>( &mut self, tree: &ElementTree<A>, runtime: RuntimeHandle<A>, ) -> bool

Applies a programmatic focus-key request after the tree has been laid out.

The request is consumed even when the key is missing/duplicate or resolves to no focusable target. Returns whether strict focus changed.

§Examples
use ailloli_ui_runtime::app::RuntimeHandle;
use ailloli_ui_runtime::element::ElementTree;
use ailloli_ui_runtime::input::InputRouter;
let runtime = RuntimeHandle::<()>::new();
runtime.request_focus_key("missing");
assert!(!InputRouter::default().apply_pending_focus_request(&ElementTree::new(), runtime.clone()));
assert!(runtime.take_focus_key_request().is_none());
Source

pub fn apply_pending_popup_intents_for_presentation<A: 'static>( &mut self, tree: &ElementTree<A>, runtime: RuntimeHandle<A>, logical_window_id: &LogicalWindowId, presentation_generation: PresentationGeneration, ) -> bool

Applies queued popup focus/presentation effects belonging to one exact retained tree and presentation.

Hosts call this after a retained popup subtree consumes an event, and once per redraw for programmatic popup changes emitted outside input dispatch. Intents owned by sibling windows or popup trees remain queued.

Returns true for present/dismiss intents, retained-overlay focus delegation, or an actual owner-tree focus change. Missing/stale popup requests are consumed and skipped.

§Examples
use ailloli_ui_core::LogicalWindowId;
use ailloli_ui_runtime::app::{PresentationGeneration, RuntimeHandle};
use ailloli_ui_runtime::element::ElementTree;
use ailloli_ui_runtime::input::InputRouter;
let mut router = InputRouter::default();
assert!(!router.apply_pending_popup_intents_for_presentation(
    &ElementTree::<()>::new(), RuntimeHandle::new(), &LogicalWindowId::new("main"), PresentationGeneration::INITIAL,
));
Source

pub fn cancel_pointer_state<A: 'static>( &mut self, tree: &ElementTree<A>, runtime: RuntimeHandle<A>, ) -> RouteOutcome

Cancels every pressed/captured pointer before clearing pointer state.

Capture owners synchronously receive [PointerEvent::Cancelled] with the last known position, modifiers, and pointer metadata when available. Hosts should use this before detaching or suspending a presentation; the lower-level Self::clear_pointer_state intentionally dispatches no widget events.

§Examples
use ailloli_ui_runtime::{
    app::RuntimeHandle,
    element::ElementTree,
    input::{InputRouter, RouteOutcome},
};
let mut router = InputRouter::default();
let outcome = router.cancel_pointer_state(
    &ElementTree::<()>::new(),
    RuntimeHandle::new(),
);
assert_eq!(outcome, RouteOutcome::default());

Trait Implementations§

Source§

impl Clone for InputRouter

Source§

fn clone(&self) -> InputRouter

Returns a copy of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for InputRouter

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for InputRouter

Source§

fn default() -> InputRouter

Returns the “default value” for a type. Read more

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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. 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<A> IntoClickAction<A> for A
where A: Clone + 'static,

Source§

fn into_click_action(self) -> ClickAction<A>

Implements the into_click_action helper used by this module.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
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,

Source§

impl<T> Props for T
where T: Clone + 'static,