static void UpdateElementUnderMouse(EventBase evt, BaseVisualElementPanel panel, out VisualElement elementUnderMouse)
        {
            bool shouldRecomputeTopElementUnderMouse = (evt as IMouseEventInternal)?.recomputeTopElementUnderMouse ?? true;

            elementUnderMouse = shouldRecomputeTopElementUnderMouse
                ? panel.Pick(((IMouseEvent)evt).mousePosition)
                : panel.GetTopElementUnderPointer(PointerId.mousePointerId);

            // If mouse leaves the window, make sure element under mouse is null.
            // However, if pressed button != 0, we are getting a MouseLeaveWindowEvent as part of
            // of a drag and drop operation, at the very beginning of the drag. Since
            // we are not really exiting the window, we do not want to set the element
            // under mouse to null in this case.
            if (evt.eventTypeId == MouseLeaveWindowEvent.TypeId() &&
                (evt as MouseLeaveWindowEvent).pressedButtons == 0)
            {
                panel.SetElementUnderPointer(null, evt);
            }
            else if (shouldRecomputeTopElementUnderMouse)
            {
                panel.SetElementUnderPointer(elementUnderMouse, evt);
            }
        }
        public void DispatchEvent(EventBase evt, IPanel panel)
        {
            EventBehavior captureBehavior = EventBehavior.None;

            IEventHandler capturingElement = panel?.GetCapturingElement(PointerId.mousePointerId);

            if (capturingElement == null)
            {
                return;
            }

            // Release mouse capture if capture element is not in a panel.
            VisualElement captureVE = capturingElement as VisualElement;

            if (evt.eventTypeId != MouseCaptureOutEvent.TypeId() && captureVE != null && captureVE.panel == null)
            {
                captureVE.ReleaseMouse();
                return;
            }

            if (panel != null && captureVE != null && captureVE.panel.contextType != panel.contextType)
            {
                return;
            }

            IMouseEvent mouseEvent = evt as IMouseEvent;

            if (mouseEvent != null && (evt.target == null || evt.target == capturingElement))
            {
                // Exclusive processing by capturing element.
                captureBehavior  = EventBehavior.IsCapturable;
                captureBehavior |= EventBehavior.IsSentExclusivelyToCapturingElement;
            }
            else if (evt.imguiEvent != null && evt.target == null)
            {
                // Non exclusive processing by capturing element.
                captureBehavior = EventBehavior.IsCapturable;
            }

            if (evt.eventTypeId == MouseEnterWindowEvent.TypeId() ||
                evt.eventTypeId == MouseLeaveWindowEvent.TypeId() ||
                evt.eventTypeId == WheelEvent.TypeId())
            {
                captureBehavior = EventBehavior.None;
            }

            if ((captureBehavior & EventBehavior.IsCapturable) == EventBehavior.IsCapturable)
            {
                BaseVisualElementPanel basePanel = panel as BaseVisualElementPanel;

                if (mouseEvent != null && basePanel != null)
                {
                    bool shouldRecomputeTopElementUnderMouse = true;
                    if ((IMouseEventInternal)mouseEvent != null)
                    {
                        shouldRecomputeTopElementUnderMouse =
                            ((IMouseEventInternal)mouseEvent).recomputeTopElementUnderMouse;
                    }
                    VisualElement elementUnderMouse = shouldRecomputeTopElementUnderMouse ?
                                                      basePanel.Pick(mouseEvent.mousePosition) :
                                                      basePanel.GetTopElementUnderPointer(PointerId.mousePointerId);

                    basePanel.SetElementUnderPointer(elementUnderMouse, evt);
                }

                evt.dispatch      = true;
                evt.target        = capturingElement;
                evt.currentTarget = capturingElement;
                (capturingElement as CallbackEventHandler)?.HandleEventAtTargetPhase(evt);
                // Do further processing with a target computed the usual way.
                // However, if IsSentExclusivelyToCapturingElement, the only thing remaining to do is ExecuteDefaultAction,
                // which should be done with mouseCapture as the target.
                if ((captureBehavior & EventBehavior.IsSentExclusivelyToCapturingElement) != EventBehavior.IsSentExclusivelyToCapturingElement)
                {
                    evt.target = null;
                }

                evt.currentTarget    = null;
                evt.propagationPhase = PropagationPhase.None;
                evt.dispatch         = false;

                // Do not call HandleEvent again for this element.
                evt.skipElements.Add(capturingElement);

                evt.stopDispatch     = (captureBehavior & EventBehavior.IsSentExclusivelyToCapturingElement) == EventBehavior.IsSentExclusivelyToCapturingElement;
                evt.propagateToIMGUI = false;
            }
        }
示例#3
0
        public virtual void DispatchEvent(EventBase evt, IPanel panel)
        {
            IMouseEvent mouseEvent = evt as IMouseEvent;

            // FIXME: we should not change hover state when capture is true.
            // However, when doing drag and drop, drop target should be highlighted.

            // TODO when EditorWindow is docked MouseLeaveWindow is not always sent
            // this is a problem in itself but it could leave some elements as "hover"

            BaseVisualElementPanel basePanel = panel as BaseVisualElementPanel;

            if (basePanel != null && (evt.eventTypeId == MouseLeaveWindowEvent.TypeId() || evt.eventTypeId == DragExitedEvent.TypeId()))
            {
                basePanel.SetElementUnderMouse(null, evt);
            }
            else
            {
                // update element under mouse and fire necessary events
                if (basePanel != null)
                {
                    bool shouldRecomputeTopElementUnderMouse = true;
                    if ((IMouseEventInternal)mouseEvent != null)
                    {
                        shouldRecomputeTopElementUnderMouse =
                            ((IMouseEventInternal)mouseEvent).recomputeTopElementUnderMouse;
                    }

                    VisualElement elementUnderMouse = shouldRecomputeTopElementUnderMouse ?
                                                      basePanel.Pick(mouseEvent.mousePosition) :
                                                      basePanel.topElementUnderMouse;

                    if (evt.target == null)
                    {
                        evt.target = elementUnderMouse;
                    }

                    // Because events are queued, we can set the element under mouse
                    // right now, instead of waiting after the PropagateEvent() as we
                    // did before.
                    basePanel.SetElementUnderMouse(elementUnderMouse, evt);
                }

                if (evt.target != null)
                {
                    evt.propagateToIMGUI = false;
                    EventDispatchUtilities.PropagateEvent(evt);
                }
            }

            if (!evt.isPropagationStopped && panel != null)
            {
                if (evt.propagateToIMGUI ||
                    evt.eventTypeId == MouseEnterWindowEvent.TypeId() ||
                    evt.eventTypeId == MouseLeaveWindowEvent.TypeId()
                    )
                {
                    EventDispatchUtilities.PropagateToIMGUIContainer(panel.visualTree, evt);
                }
            }

            evt.stopDispatch = true;
        }