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: HitTestEngineStateless rectangle hit-test helper.
focus: FocusManagerLow-level strict keyboard-focus store.
Implementations§
Source§impl InputRouter
Focus, semantic-role, pointer, popup, and event-routing operations.
impl InputRouter
Focus, semantic-role, pointer, popup, and event-routing operations.
Sourcepub fn hovered(&self) -> Option<ElementId>
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);Sourcepub fn hovered_for(&self, pointer_id: PointerId) -> Option<ElementId>
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);Sourcepub fn focused(&self) -> Option<ElementId>
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);Sourcepub fn snapshot(&self) -> InputSnapshot
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());Sourcepub fn snapshot_for(&self, pointer_id: PointerId) -> InputSnapshot
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());Sourcepub fn active_pointer_ids(&self) -> impl Iterator<Item = PointerId> + '_
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);Sourcepub fn clear_pointer_state(&mut self) -> bool
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());Sourcepub fn clear_focus(&mut self) -> bool
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);Sourcepub fn blur_tree<A: 'static>(
&mut self,
tree: &ElementTree<A>,
runtime: RuntimeHandle<A>,
) -> bool
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()));Sourcepub fn cycle_focus_descendant<A: 'static>(
&mut self,
tree: &ElementTree<A>,
runtime: RuntimeHandle<A>,
reverse: bool,
wrap: bool,
) -> bool
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));Sourcepub fn focused_input_role<A: 'static>(&self, tree: &ElementTree<A>) -> InputRole
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);Sourcepub fn hovered_input_role<A: 'static>(&self, tree: &ElementTree<A>) -> InputRole
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);Sourcepub fn hovered_cursor_role<A: 'static>(
&self,
tree: &ElementTree<A>,
) -> HoverCursorRole
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);Sourcepub fn hovered_cursor_role_at<A: 'static>(
&self,
tree: &ElementTree<A>,
pos: Point,
) -> HoverCursorRole
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);Sourcepub fn focused_ime_cursor_rect<A: 'static>(
&self,
tree: &ElementTree<A>,
) -> Option<Rect>
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);Sourcepub fn route_event<A: 'static>(
&mut self,
tree: &ElementTree<A>,
runtime: RuntimeHandle<A>,
event: &Event,
) -> RouteOutcome
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());Sourcepub fn route_envelope<A: 'static>(
&mut self,
tree: &ElementTree<A>,
runtime: RuntimeHandle<A>,
envelope: &EventEnvelope,
) -> RouteOutcome
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);Sourcepub fn apply_pending_focus_request<A: 'static>(
&mut self,
tree: &ElementTree<A>,
runtime: RuntimeHandle<A>,
) -> bool
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());Sourcepub 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
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,
));Sourcepub fn cancel_pointer_state<A: 'static>(
&mut self,
tree: &ElementTree<A>,
runtime: RuntimeHandle<A>,
) -> RouteOutcome
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
impl Clone for InputRouter
Source§fn clone(&self) -> InputRouter
fn clone(&self) -> InputRouter
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for InputRouter
impl Debug for InputRouter
Source§impl Default for InputRouter
impl Default for InputRouter
Source§fn default() -> InputRouter
fn default() -> InputRouter
Auto Trait Implementations§
impl Freeze for InputRouter
impl RefUnwindSafe for InputRouter
impl Send for InputRouter
impl Sync for InputRouter
impl Unpin for InputRouter
impl UnwindSafe for InputRouter
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<A> IntoClickAction<A> for Awhere
A: Clone + 'static,
impl<A> IntoClickAction<A> for Awhere
A: Clone + 'static,
Source§fn into_click_action(self) -> ClickAction<A>
fn into_click_action(self) -> ClickAction<A>
Implements the into_click_action helper used by this module.