bevy_picking/
events.rs

1//! This module defines a stateful set of interaction events driven by the `PointerInput` stream
2//! and the hover state of each Pointer.
3//!
4//! # Usage
5//!
6//! To receive events from this module, you must use an [`Observer`]
7//! The simplest example, registering a callback when an entity is hovered over by a pointer, looks like this:
8//!
9//! ```rust
10//! # use bevy_ecs::prelude::*;
11//! # use bevy_picking::prelude::*;
12//! # let mut world = World::default();
13//! world.spawn_empty()
14//!     .observe(|trigger: Trigger<Pointer<Over>>| {
15//!         println!("I am being hovered over");
16//!     });
17//! ```
18//!
19//! Observers give us three important properties:
20//! 1. They allow for attaching event handlers to specific entities,
21//! 2. they allow events to bubble up the entity hierarchy,
22//! 3. and they allow events of different types to be called in a specific order.
23//!
24//! The order in which interaction events are received is extremely important, and you can read more
25//! about it on the docs for the dispatcher system: [`pointer_events`]. This system runs in
26//! [`PreUpdate`](bevy_app::PreUpdate) in [`PickSet::Focus`](crate::PickSet::Focus). All pointer-event
27//! observers resolve during the sync point between [`pointer_events`] and
28//! [`update_interactions`](crate::focus::update_interactions).
29//!
30//! # Events Types
31//!
32//! The events this module defines fall into a few broad categories:
33//! + Hovering and movement: [`Over`], [`Move`], and [`Out`].
34//! + Clicking and pressing: [`Down`], [`Up`], and [`Click`].
35//! + Dragging and dropping: [`DragStart`], [`Drag`], [`DragEnd`], [`DragEnter`], [`DragOver`], [`DragDrop`], [`DragLeave`].
36//!
37//! When received by an observer, these events will always be wrapped by the [`Pointer`] type, which contains
38//! general metadata about the pointer and it's location.
39
40use core::fmt::Debug;
41
42use bevy_ecs::{prelude::*, system::SystemParam};
43use bevy_hierarchy::Parent;
44use bevy_math::Vec2;
45use bevy_reflect::prelude::*;
46use bevy_utils::{tracing::debug, Duration, HashMap, Instant};
47
48use crate::{
49    backend::{prelude::PointerLocation, HitData},
50    focus::{HoverMap, PreviousHoverMap},
51    pointer::{
52        Location, PointerAction, PointerButton, PointerId, PointerInput, PointerMap, PressDirection,
53    },
54};
55
56/// Stores the common data needed for all pointer events.
57///
58/// The documentation for the [`pointer_events`] explains the events this module exposes and
59/// the order in which they fire.
60#[derive(Clone, PartialEq, Debug, Reflect, Component)]
61#[reflect(Component, Debug)]
62pub struct Pointer<E: Debug + Clone + Reflect> {
63    /// The original target of this picking event, before bubbling
64    pub target: Entity,
65    /// The pointer that triggered this event
66    pub pointer_id: PointerId,
67    /// The location of the pointer during this event
68    pub pointer_location: Location,
69    /// Additional event-specific data. [`DragDrop`] for example, has an additional field to describe
70    /// the `Entity` that is being dropped on the target.
71    pub event: E,
72}
73
74impl<E> Event for Pointer<E>
75where
76    E: Debug + Clone + Reflect,
77{
78    type Traversal = &'static Parent;
79
80    const AUTO_PROPAGATE: bool = true;
81}
82
83impl<E: Debug + Clone + Reflect> core::fmt::Display for Pointer<E> {
84    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
85        f.write_fmt(format_args!(
86            "{:?}, {:.1?}, {:.1?}",
87            self.pointer_id, self.pointer_location.position, self.event
88        ))
89    }
90}
91
92impl<E: Debug + Clone + Reflect> core::ops::Deref for Pointer<E> {
93    type Target = E;
94
95    fn deref(&self) -> &Self::Target {
96        &self.event
97    }
98}
99
100impl<E: Debug + Clone + Reflect> Pointer<E> {
101    /// Construct a new `Pointer<E>` event.
102    pub fn new(target: Entity, id: PointerId, location: Location, event: E) -> Self {
103        Self {
104            target,
105            pointer_id: id,
106            pointer_location: location,
107            event,
108        }
109    }
110}
111
112/// Fires when a pointer is canceled, and it's current interaction state is dropped.
113#[derive(Clone, PartialEq, Debug, Reflect)]
114pub struct Cancel {
115    /// Information about the picking intersection.
116    pub hit: HitData,
117}
118
119/// Fires when a the pointer crosses into the bounds of the `target` entity.
120#[derive(Clone, PartialEq, Debug, Reflect)]
121pub struct Over {
122    /// Information about the picking intersection.
123    pub hit: HitData,
124}
125
126/// Fires when a the pointer crosses out of the bounds of the `target` entity.
127#[derive(Clone, PartialEq, Debug, Reflect)]
128pub struct Out {
129    /// Information about the latest prior picking intersection.
130    pub hit: HitData,
131}
132
133/// Fires when a pointer button is pressed over the `target` entity.
134#[derive(Clone, PartialEq, Debug, Reflect)]
135pub struct Down {
136    /// Pointer button pressed to trigger this event.
137    pub button: PointerButton,
138    /// Information about the picking intersection.
139    pub hit: HitData,
140}
141
142/// Fires when a pointer button is released over the `target` entity.
143#[derive(Clone, PartialEq, Debug, Reflect)]
144pub struct Up {
145    /// Pointer button lifted to trigger this event.
146    pub button: PointerButton,
147    /// Information about the picking intersection.
148    pub hit: HitData,
149}
150
151/// Fires when a pointer sends a pointer down event followed by a pointer up event, with the same
152/// `target` entity for both events.
153#[derive(Clone, PartialEq, Debug, Reflect)]
154pub struct Click {
155    /// Pointer button pressed and lifted to trigger this event.
156    pub button: PointerButton,
157    /// Information about the picking intersection.
158    pub hit: HitData,
159    /// Duration between the pointer pressed and lifted for this click
160    pub duration: Duration,
161}
162
163/// Fires while a pointer is moving over the `target` entity.
164#[derive(Clone, PartialEq, Debug, Reflect)]
165pub struct Move {
166    /// Information about the picking intersection.
167    pub hit: HitData,
168    /// The change in position since the last move event.
169    pub delta: Vec2,
170}
171
172/// Fires when the `target` entity receives a pointer down event followed by a pointer move event.
173#[derive(Clone, PartialEq, Debug, Reflect)]
174pub struct DragStart {
175    /// Pointer button pressed and moved to trigger this event.
176    pub button: PointerButton,
177    /// Information about the picking intersection.
178    pub hit: HitData,
179}
180
181/// Fires while the `target` entity is being dragged.
182#[derive(Clone, PartialEq, Debug, Reflect)]
183pub struct Drag {
184    /// Pointer button pressed and moved to trigger this event.
185    pub button: PointerButton,
186    /// The total distance vector of a drag, measured from drag start to the current position.
187    pub distance: Vec2,
188    /// The change in position since the last drag event.
189    pub delta: Vec2,
190}
191
192/// Fires when a pointer is dragging the `target` entity and a pointer up event is received.
193#[derive(Clone, PartialEq, Debug, Reflect)]
194pub struct DragEnd {
195    /// Pointer button pressed, moved, and lifted to trigger this event.
196    pub button: PointerButton,
197    /// The vector of drag movement measured from start to final pointer position.
198    pub distance: Vec2,
199}
200
201/// Fires when a pointer dragging the `dragged` entity enters the `target` entity.
202#[derive(Clone, PartialEq, Debug, Reflect)]
203pub struct DragEnter {
204    /// Pointer button pressed to enter drag.
205    pub button: PointerButton,
206    /// The entity that was being dragged when the pointer entered the `target` entity.
207    pub dragged: Entity,
208    /// Information about the picking intersection.
209    pub hit: HitData,
210}
211
212/// Fires while the `dragged` entity is being dragged over the `target` entity.
213#[derive(Clone, PartialEq, Debug, Reflect)]
214pub struct DragOver {
215    /// Pointer button pressed while dragging over.
216    pub button: PointerButton,
217    /// The entity that was being dragged when the pointer was over the `target` entity.
218    pub dragged: Entity,
219    /// Information about the picking intersection.
220    pub hit: HitData,
221}
222
223/// Fires when a pointer dragging the `dragged` entity leaves the `target` entity.
224#[derive(Clone, PartialEq, Debug, Reflect)]
225pub struct DragLeave {
226    /// Pointer button pressed while leaving drag.
227    pub button: PointerButton,
228    /// The entity that was being dragged when the pointer left the `target` entity.
229    pub dragged: Entity,
230    /// Information about the latest prior picking intersection.
231    pub hit: HitData,
232}
233
234/// Fires when a pointer drops the `dropped` entity onto the `target` entity.
235#[derive(Clone, PartialEq, Debug, Reflect)]
236pub struct DragDrop {
237    /// Pointer button lifted to drop.
238    pub button: PointerButton,
239    /// The entity that was dropped onto the `target` entity.
240    pub dropped: Entity,
241    /// Information about the picking intersection.
242    pub hit: HitData,
243}
244
245/// Dragging state.
246#[derive(Debug, Clone)]
247pub struct DragEntry {
248    /// The position of the pointer at drag start.
249    pub start_pos: Vec2,
250    /// The latest position of the pointer during this drag, used to compute deltas.
251    pub latest_pos: Vec2,
252}
253
254/// An entry in the cache that drives the `pointer_events` system, storing additional data
255/// about pointer button presses.
256#[derive(Debug, Clone, Default)]
257pub struct PointerButtonState {
258    /// Stores the press location and start time for each button currently being pressed by the pointer.
259    pub pressing: HashMap<Entity, (Location, Instant, HitData)>,
260    /// Stores the starting and current locations for each entity currently being dragged by the pointer.
261    pub dragging: HashMap<Entity, DragEntry>,
262    /// Stores  the hit data for each entity currently being dragged over by the pointer.
263    pub dragging_over: HashMap<Entity, HitData>,
264}
265
266/// State for all pointers.
267#[derive(Debug, Clone, Default, Resource)]
268pub struct PointerState {
269    /// Pressing and dragging state, organized by pointer and button.
270    pub pointer_buttons: HashMap<(PointerId, PointerButton), PointerButtonState>,
271}
272
273impl PointerState {
274    /// Retrieves the current state for a specific pointer and button, if it has been created.
275    pub fn get(&self, pointer_id: PointerId, button: PointerButton) -> Option<&PointerButtonState> {
276        self.pointer_buttons.get(&(pointer_id, button))
277    }
278
279    /// Provides write access to the state of a pointer and button, creating it if it does not yet exist.
280    pub fn get_mut(
281        &mut self,
282        pointer_id: PointerId,
283        button: PointerButton,
284    ) -> &mut PointerButtonState {
285        self.pointer_buttons
286            .entry((pointer_id, button))
287            .or_default()
288    }
289
290    /// Clears all the data assoceated with all of the buttons on a pointer. Does not free the underlying memory.
291    pub fn clear(&mut self, pointer_id: PointerId) {
292        for button in PointerButton::iter() {
293            if let Some(state) = self.pointer_buttons.get_mut(&(pointer_id, button)) {
294                state.pressing.clear();
295                state.dragging.clear();
296                state.dragging_over.clear();
297            }
298        }
299    }
300}
301
302/// A helper system param for accessing the picking event writers.
303#[derive(SystemParam)]
304pub struct PickingEventWriters<'w> {
305    cancel_events: EventWriter<'w, Pointer<Cancel>>,
306    click_events: EventWriter<'w, Pointer<Click>>,
307    down_events: EventWriter<'w, Pointer<Down>>,
308    drag_drop_events: EventWriter<'w, Pointer<DragDrop>>,
309    drag_end_events: EventWriter<'w, Pointer<DragEnd>>,
310    drag_enter_events: EventWriter<'w, Pointer<DragEnter>>,
311    drag_events: EventWriter<'w, Pointer<Drag>>,
312    drag_leave_events: EventWriter<'w, Pointer<DragLeave>>,
313    drag_over_events: EventWriter<'w, Pointer<DragOver>>,
314    drag_start_events: EventWriter<'w, Pointer<DragStart>>,
315    move_events: EventWriter<'w, Pointer<Move>>,
316    out_events: EventWriter<'w, Pointer<Out>>,
317    over_events: EventWriter<'w, Pointer<Over>>,
318    up_events: EventWriter<'w, Pointer<Up>>,
319}
320
321/// Dispatches interaction events to the target entities.
322///
323/// Within a single frame, events are dispatched in the following order:
324/// + [`Out`] → [`DragLeave`].
325/// + [`DragEnter`] → [`Over`].
326/// + Any number of any of the following:
327///   + For each movement: [`DragStart`] → [`Drag`] → [`DragOver`] → [`Move`].
328///   + For each button press: [`Down`] or [`Click`] → [`Up`] → [`DragDrop`] → [`DragEnd`] → [`DragLeave`].
329///   + For each pointer cancellation: [`Cancel`].
330///
331/// Additionally, across multiple frames, the following are also strictly
332/// ordered by the interaction state machine:
333/// + When a pointer moves over the target:
334///   [`Over`], [`Move`], [`Out`].
335/// + When a pointer presses buttons on the target:
336///   [`Down`], [`Click`], [`Up`].
337/// + When a pointer drags the target:
338///   [`DragStart`], [`Drag`], [`DragEnd`].
339/// + When a pointer drags something over the target:
340///   [`DragEnter`], [`DragOver`], [`DragDrop`], [`DragLeave`].
341/// + When a pointer is canceled:
342///   No other events will follow the [`Cancel`] event for that pointer.
343///
344/// Two events -- [`Over`] and [`Out`] -- are driven only by the [`HoverMap`].
345/// The rest rely on additional data from the [`PointerInput`] event stream. To
346/// receive these events for a custom pointer, you must add [`PointerInput`]
347/// events.
348///
349/// When the pointer goes from hovering entity A to entity B, entity A will
350/// receive [`Out`] and then entity B will receive [`Over`]. No entity will ever
351/// receive both an [`Over`] and and a [`Out`] event during the same frame.
352///
353/// When we account for event bubbling, this is no longer true. When focus shifts
354/// between children, parent entities may receive redundant [`Out`] → [`Over`] pairs.
355/// In the context of UI, this is especially problematic. Additional hierarchy-aware
356/// events will be added in a future release.
357///
358/// Both [`Click`] and [`Up`] target the entity hovered in the *previous frame*,
359/// rather than the current frame. This is because touch pointers hover nothing
360/// on the frame they are released. The end effect is that these two events can
361/// be received sequentally after an [`Out`] event (but always on the same frame
362/// as the [`Out`] event).
363///
364/// Note: Though it is common for the [`PointerInput`] stream may contain
365/// multiple pointer movements and presses each frame, the hover state is
366/// determined only by the pointer's *final position*. Since the hover state
367/// ultimately determines which entities receive events, this may mean that an
368/// entity can receive events from before or after it was actually hovered.
369#[allow(clippy::too_many_arguments)]
370pub fn pointer_events(
371    // Input
372    mut input_events: EventReader<PointerInput>,
373    // ECS State
374    pointers: Query<&PointerLocation>,
375    pointer_map: Res<PointerMap>,
376    hover_map: Res<HoverMap>,
377    previous_hover_map: Res<PreviousHoverMap>,
378    mut pointer_state: ResMut<PointerState>,
379    // Output
380    mut commands: Commands,
381    mut event_writers: PickingEventWriters,
382) {
383    // Setup utilities
384    let now = Instant::now();
385    let pointer_location = |pointer_id: PointerId| {
386        pointer_map
387            .get_entity(pointer_id)
388            .and_then(|entity| pointers.get(entity).ok())
389            .and_then(|pointer| pointer.location.clone())
390    };
391
392    // If the entity was hovered by a specific pointer last frame...
393    for (pointer_id, hovered_entity, hit) in previous_hover_map
394        .iter()
395        .flat_map(|(id, hashmap)| hashmap.iter().map(|data| (*id, *data.0, data.1.clone())))
396    {
397        // ...but is now not being hovered by that same pointer...
398        if !hover_map
399            .get(&pointer_id)
400            .iter()
401            .any(|e| e.contains_key(&hovered_entity))
402        {
403            let Some(location) = pointer_location(pointer_id) else {
404                debug!(
405                    "Unable to get location for pointer {:?} during pointer out",
406                    pointer_id
407                );
408                continue;
409            };
410
411            // Always send Out events
412            let out_event = Pointer::new(
413                hovered_entity,
414                pointer_id,
415                location.clone(),
416                Out { hit: hit.clone() },
417            );
418            commands.trigger_targets(out_event.clone(), hovered_entity);
419            event_writers.out_events.send(out_event);
420
421            // Possibly send DragLeave events
422            for button in PointerButton::iter() {
423                let state = pointer_state.get_mut(pointer_id, button);
424                state.dragging_over.remove(&hovered_entity);
425                for drag_target in state.dragging.keys() {
426                    let drag_leave_event = Pointer::new(
427                        hovered_entity,
428                        pointer_id,
429                        location.clone(),
430                        DragLeave {
431                            button,
432                            dragged: *drag_target,
433                            hit: hit.clone(),
434                        },
435                    );
436                    commands.trigger_targets(drag_leave_event.clone(), hovered_entity);
437                    event_writers.drag_leave_events.send(drag_leave_event);
438                }
439            }
440        }
441    }
442
443    // If the entity is hovered...
444    for (pointer_id, hovered_entity, hit) in hover_map
445        .iter()
446        .flat_map(|(id, hashmap)| hashmap.iter().map(|data| (*id, *data.0, data.1.clone())))
447    {
448        // ...but was not hovered last frame...
449        if !previous_hover_map
450            .get(&pointer_id)
451            .iter()
452            .any(|e| e.contains_key(&hovered_entity))
453        {
454            let Some(location) = pointer_location(pointer_id) else {
455                debug!(
456                    "Unable to get location for pointer {:?} during pointer over",
457                    pointer_id
458                );
459                continue;
460            };
461
462            // Possibly send DragEnter events
463            for button in PointerButton::iter() {
464                let state = pointer_state.get_mut(pointer_id, button);
465
466                for drag_target in state
467                    .dragging
468                    .keys()
469                    .filter(|&&drag_target| hovered_entity != drag_target)
470                {
471                    state.dragging_over.insert(hovered_entity, hit.clone());
472                    let drag_enter_event = Pointer::new(
473                        hovered_entity,
474                        pointer_id,
475                        location.clone(),
476                        DragEnter {
477                            button,
478                            dragged: *drag_target,
479                            hit: hit.clone(),
480                        },
481                    );
482                    commands.trigger_targets(drag_enter_event.clone(), hovered_entity);
483                    event_writers.drag_enter_events.send(drag_enter_event);
484                }
485            }
486
487            // Always send Over events
488            let over_event = Pointer::new(
489                hovered_entity,
490                pointer_id,
491                location.clone(),
492                Over { hit: hit.clone() },
493            );
494            commands.trigger_targets(over_event.clone(), hovered_entity);
495            event_writers.over_events.send(over_event);
496        }
497    }
498
499    // Dispatch input events...
500    for PointerInput {
501        pointer_id,
502        location,
503        action,
504    } in input_events.read().cloned()
505    {
506        match action {
507            // Pressed Button
508            PointerAction::Pressed { direction, button } => {
509                let state = pointer_state.get_mut(pointer_id, button);
510
511                // The sequence of events emitted depends on if this is a press or a release
512                match direction {
513                    PressDirection::Down => {
514                        // If it's a press, emit a Down event and mark the hovered entities as pressed
515                        for (hovered_entity, hit) in hover_map
516                            .get(&pointer_id)
517                            .iter()
518                            .flat_map(|h| h.iter().map(|(entity, data)| (*entity, data.clone())))
519                        {
520                            let down_event = Pointer::new(
521                                hovered_entity,
522                                pointer_id,
523                                location.clone(),
524                                Down {
525                                    button,
526                                    hit: hit.clone(),
527                                },
528                            );
529                            commands.trigger_targets(down_event.clone(), hovered_entity);
530                            event_writers.down_events.send(down_event);
531                            // Also insert the press into the state
532                            state
533                                .pressing
534                                .insert(hovered_entity, (location.clone(), now, hit));
535                        }
536                    }
537                    PressDirection::Up => {
538                        // Emit Click and Up events on all the previously hovered entities.
539                        for (hovered_entity, hit) in previous_hover_map
540                            .get(&pointer_id)
541                            .iter()
542                            .flat_map(|h| h.iter().map(|(entity, data)| (*entity, data.clone())))
543                        {
544                            // If this pointer previously pressed the hovered entity, emit a Click event
545                            if let Some((_, press_instant, _)) = state.pressing.get(&hovered_entity)
546                            {
547                                let click_event = Pointer::new(
548                                    hovered_entity,
549                                    pointer_id,
550                                    location.clone(),
551                                    Click {
552                                        button,
553                                        hit: hit.clone(),
554                                        duration: now - *press_instant,
555                                    },
556                                );
557                                commands.trigger_targets(click_event.clone(), hovered_entity);
558                                event_writers.click_events.send(click_event);
559                            }
560                            // Always send the Up event
561                            let up_event = Pointer::new(
562                                hovered_entity,
563                                pointer_id,
564                                location.clone(),
565                                Up {
566                                    button,
567                                    hit: hit.clone(),
568                                },
569                            );
570                            commands.trigger_targets(up_event.clone(), hovered_entity);
571                            event_writers.up_events.send(up_event);
572                        }
573
574                        // Then emit the drop events.
575                        for (drag_target, drag) in state.dragging.drain() {
576                            // Emit DragDrop
577                            for (dragged_over, hit) in state.dragging_over.iter() {
578                                let drag_drop_event = Pointer::new(
579                                    *dragged_over,
580                                    pointer_id,
581                                    location.clone(),
582                                    DragDrop {
583                                        button,
584                                        dropped: drag_target,
585                                        hit: hit.clone(),
586                                    },
587                                );
588                                commands.trigger_targets(drag_drop_event.clone(), *dragged_over);
589                                event_writers.drag_drop_events.send(drag_drop_event);
590                            }
591                            // Emit DragEnd
592                            let drag_end_event = Pointer::new(
593                                drag_target,
594                                pointer_id,
595                                location.clone(),
596                                DragEnd {
597                                    button,
598                                    distance: drag.latest_pos - drag.start_pos,
599                                },
600                            );
601                            commands.trigger_targets(drag_end_event.clone(), drag_target);
602                            event_writers.drag_end_events.send(drag_end_event);
603                            // Emit DragLeave
604                            for (dragged_over, hit) in state.dragging_over.iter() {
605                                let drag_leave_event = Pointer::new(
606                                    *dragged_over,
607                                    pointer_id,
608                                    location.clone(),
609                                    DragLeave {
610                                        button,
611                                        dragged: drag_target,
612                                        hit: hit.clone(),
613                                    },
614                                );
615                                commands.trigger_targets(drag_leave_event.clone(), *dragged_over);
616                                event_writers.drag_leave_events.send(drag_leave_event);
617                            }
618                        }
619
620                        // Finally, we can clear the state of everything relating to presses or drags.
621                        state.pressing.clear();
622                        state.dragging.clear();
623                        state.dragging_over.clear();
624                    }
625                }
626            }
627            // Moved
628            PointerAction::Moved { delta } => {
629                // Triggers during movement even if not over an entity
630                for button in PointerButton::iter() {
631                    let state = pointer_state.get_mut(pointer_id, button);
632
633                    // Emit DragEntry and DragStart the first time we move while pressing an entity
634                    for (press_target, (location, _, hit)) in state.pressing.iter() {
635                        if state.dragging.contains_key(press_target) {
636                            continue; // This entity is already logged as being dragged
637                        }
638                        state.dragging.insert(
639                            *press_target,
640                            DragEntry {
641                                start_pos: location.position,
642                                latest_pos: location.position,
643                            },
644                        );
645                        let drag_start_event = Pointer::new(
646                            *press_target,
647                            pointer_id,
648                            location.clone(),
649                            DragStart {
650                                button,
651                                hit: hit.clone(),
652                            },
653                        );
654                        commands.trigger_targets(drag_start_event.clone(), *press_target);
655                        event_writers.drag_start_events.send(drag_start_event);
656                    }
657
658                    // Emit Drag events to the entities we are dragging
659                    for (drag_target, drag) in state.dragging.iter_mut() {
660                        let delta = location.position - drag.latest_pos;
661                        if delta == Vec2::ZERO {
662                            continue; // No need to emit a Drag event if there is no movement
663                        }
664                        let drag_event = Pointer::new(
665                            *drag_target,
666                            pointer_id,
667                            location.clone(),
668                            Drag {
669                                button,
670                                distance: location.position - drag.start_pos,
671                                delta,
672                            },
673                        );
674                        commands.trigger_targets(drag_event.clone(), *drag_target);
675                        event_writers.drag_events.send(drag_event);
676
677                        // Update drag position
678                        drag.latest_pos = location.position;
679
680                        // Emit corresponding DragOver to the hovered entities
681                        for (hovered_entity, hit) in hover_map
682                            .get(&pointer_id)
683                            .iter()
684                            .flat_map(|h| h.iter().map(|(entity, data)| (*entity, data.to_owned())))
685                            .filter(|(hovered_entity, _)| *hovered_entity != *drag_target)
686                        {
687                            let drag_over_event = Pointer::new(
688                                hovered_entity,
689                                pointer_id,
690                                location.clone(),
691                                DragOver {
692                                    button,
693                                    dragged: *drag_target,
694                                    hit: hit.clone(),
695                                },
696                            );
697                            commands.trigger_targets(drag_over_event.clone(), hovered_entity);
698                            event_writers.drag_over_events.send(drag_over_event);
699                        }
700                    }
701                }
702
703                for (hovered_entity, hit) in hover_map
704                    .get(&pointer_id)
705                    .iter()
706                    .flat_map(|h| h.iter().map(|(entity, data)| (*entity, data.to_owned())))
707                {
708                    // Emit Move events to the entities we are hovering
709                    let move_event = Pointer::new(
710                        hovered_entity,
711                        pointer_id,
712                        location.clone(),
713                        Move {
714                            hit: hit.clone(),
715                            delta,
716                        },
717                    );
718                    commands.trigger_targets(move_event.clone(), hovered_entity);
719                    event_writers.move_events.send(move_event);
720                }
721            }
722            // Canceled
723            PointerAction::Canceled => {
724                // Emit a Cancel to the hovered entity.
725                for (hovered_entity, hit) in hover_map
726                    .get(&pointer_id)
727                    .iter()
728                    .flat_map(|h| h.iter().map(|(entity, data)| (*entity, data.to_owned())))
729                {
730                    let cancel_event =
731                        Pointer::new(hovered_entity, pointer_id, location.clone(), Cancel { hit });
732                    commands.trigger_targets(cancel_event.clone(), hovered_entity);
733                    event_writers.cancel_events.send(cancel_event);
734                }
735                // Clear the state for the canceled pointer
736                pointer_state.clear(pointer_id);
737            }
738        }
739    }
740}