Skip to main content

Interaction

Struct Interaction 

Source
pub struct Interaction<Id> { /* private fields */ }
Expand description

Ties Pointer, HitTester, and FocusRing together into the one piece of state a draw pass needs to make its widgets interactive.

§Frame lifecycle

interaction.begin_frame();                 // 1
for event in poll_events() {
    interaction.handle_event(&event);       // 2
}
draw(&mut term, &mut interaction, &state);  // 3: calls interaction.interact(...)
interaction.end_frame();                    // 4
  1. begin_frame snapshots which id (if any) is under the pointer, and whether it pressed/released/scrolled, using last frame’s hit registrations and pointer events: this frame’s registrations aren’t complete until step 3 finishes, and this frame’s events haven’t arrived yet (they’re step 2), so every Response in a given frame is one frame stale relative to what’s being drawn/fed in this frame: uniformly for hover, press, release, click, and scroll, all resolved from that one snapshot. At typical redraw rates this is imperceptible; it’s the same kind of trade-off ListState::ensure_visible documents for a different reason (only the caller knows the current viewport height), applied here because only the previous frame knows the full hit list and the pointer’s position as of the input that’s about to be processed. dragging and Response::held are exceptions: both re-check the pointer’s live position (via Pointer::pos/Pointer::is_down) rather than the frame-stale snapshot, because a drag-in-progress or a press-cancel needs to react the instant the pointer moves, not one frame later. Keyboard focus is the remaining exception: Response::focused and Enter/Space activation read FocusRing’s current live, since it’s plain level state with no hit-testing involved: no staleness to trade off.
  2. handle_event updates pointer position/buttons and, by default, cycles focus on Tab/Shift+Tab.
  3. Each widget calls interact with its rect, a caller-chosen id, and a Sense describing what it cares about; it gets back a Response and, as a side effect, registers itself for step 1 of the next frame.
  4. end_frame releases the active widget if step 1 saw the pointer go up.

One consequence worth knowing: a full press-then-release gesture that arrives as two events in the same handle_event batch (both fed in during step 2 of one frame, e.g. a synthetic test firing them back to back) takes an extra frame to resolve versus a realistic press and release arriving in separate frames, because step 1’s hover snapshot for that frame still reflects the pointer’s position from before those events. Real input rarely lands this way (a physical click’s down and up are milliseconds apart, i.e. several frames at typical redraw rates), so this only tends to show up in tests.

§Why Id is a type parameter, not a hash

Immediate-mode toolkits like egui derive a widget’s identity from its call-site source location (optionally salted with data) hashed down to an opaque integer, flexible, but it means two widgets can collide onto the same id at runtime with no compile-time signal, and the id carries no meaning a debugger can show you. Interaction<Id> instead asks the app for whatever id type it already has lying around: typically a small Copy enum like the hand-rolled hit-target enum an app would otherwise define anyway. Collisions become unrepresentable if the enum is exhaustive, and {:?}-printing an id tells you exactly which widget it is. The cost is one generic parameter; Id: Copy + PartialEq is all any of this module asks for.

Consistently with that: everything here holds its state in a plain, explicitly-owned struct threaded through &mut self, the same convention ListState uses, rather than the interior-mutability/global-context pattern egui’s Memory relies on to keep its implicit ids from needing to be threaded everywhere.

Implementations§

Source§

impl<Id> Interaction<Id>

Source

pub const fn new() -> Self

A fresh interaction context: nothing hovered, focused, or active.

Source

pub const fn with_drag_threshold(self, cells: u16) -> Self

Override how far (in cells) the pointer must move from its press origin before a Sense::DRAG widget reports Response::dragging rather than a click-in-progress. Defaults to DEFAULT_DRAG_THRESHOLD.

Source

pub const fn pointer(&self) -> &Pointer

Read access to the pointer’s current position/button/scroll state, e.g. to draw a custom cursor glyph.

Source

pub const fn focus(&self) -> &FocusRing<Id>

Read access to the focus ring, e.g. to render a “press Tab to begin” hint when nothing is focused yet.

Source

pub const fn focus_mut(&mut self) -> &mut FocusRing<Id>

Mutable access to the focus ring, e.g. to drive it from a gamepad shoulder button instead of (or in addition to) Tab/Shift+Tab.

Source§

impl<Id: Copy + PartialEq> Interaction<Id>

Source

pub fn begin_frame(&mut self)

Resolve hover/press against last frame’s registrations, finalize the focus order, and clear the hit registry for this frame’s interact calls. Call once per frame, before processing input or drawing.

Source

pub fn handle_event(&mut self, event: &Event)

Feed a raw input event: updates the pointer, and (by default) Tab cycles focus: see FocusRing::handle_event if you need to override that.

Source

pub fn interact(&mut self, rect: Rect, id: Id, sense: Sense) -> Response

Register id’s rect for whatever sense asks for, and report what happened to it, resolved from last frame’s input: see the Interaction docs for the frame lifecycle this implies.

Source

pub const fn end_frame(&mut self)

Release the active widget (both primary and secondary), e.g. so a later focus_mut-driven Tab handling starts clean. Call once per frame, after drawing.

Trait Implementations§

Source§

impl<Id: Clone> Clone for Interaction<Id>

Source§

fn clone(&self) -> Interaction<Id>

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

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

Performs copy-assignment from source. Read more
Source§

impl<Id: Debug> Debug for Interaction<Id>

Source§

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

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

impl<Id> Default for Interaction<Id>

Source§

fn default() -> Self

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

Auto Trait Implementations§

§

impl<Id> Freeze for Interaction<Id>
where Id: Freeze,

§

impl<Id> RefUnwindSafe for Interaction<Id>
where Id: RefUnwindSafe,

§

impl<Id> Send for Interaction<Id>
where Id: Send,

§

impl<Id> Sync for Interaction<Id>
where Id: Sync,

§

impl<Id> Unpin for Interaction<Id>
where Id: Unpin,

§

impl<Id> UnsafeUnpin for Interaction<Id>
where Id: UnsafeUnpin,

§

impl<Id> UnwindSafe for Interaction<Id>
where Id: UnwindSafe,

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<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.