Example #1
0
        protected internal override void PostDispatch(IPanel panel)
        {
            if (PointerType.IsDirectManipulationDevice(pointerType))
            {
                panel.ReleasePointer(pointerId);
                BaseVisualElementPanel basePanel = panel as BaseVisualElementPanel;
                basePanel?.ClearCachedElementUnderPointer(this);
            }

            if (panel.ShouldSendCompatibilityMouseEvents(this))
            {
                using (var evt = MouseUpEvent.GetPooled(this))
                {
                    evt.target = target;
                    target.SendEvent(evt);
                }
            }

            base.PostDispatch(panel);
        }
        static bool SendEventToIMGUIContainer(EventBase evt, BaseVisualElementPanel panel)
        {
            if (evt.imguiEvent == null)
                return false;

            // Root IMGUI is the container that handles all the GUIView/DockArea logic for EditorWindows.
            var rootIMGUI = panel.rootIMGUIContainer;
            if (rootIMGUI == null)
                return false;

            // If root IMGUI doesn't use event, send it to other IMGUIs down the line.
            if (evt.propagateToIMGUI ||
                evt.eventTypeId == MouseEnterWindowEvent.TypeId() ||
                evt.eventTypeId == MouseLeaveWindowEvent.TypeId())
            {
                evt.skipElements.Add(evt.target);
                EventDispatchUtilities.PropagateToIMGUIContainer(panel.visualTree, evt);
            }

            return IsDone(evt);
        }
        static void SetBestTargetForEvent(EventBase evt, BaseVisualElementPanel panel)
        {
            UpdateElementUnderMouse(evt, panel, out VisualElement elementUnderMouse);

            if (evt.target != null)
            {
                evt.propagateToIMGUI = false;
            }
            else if (elementUnderMouse != null)
            {
                evt.propagateToIMGUI = false;
                evt.target = elementUnderMouse;
            }
            else
            {
                // Event occured outside the window.
                // Send event to visual tree root and
                // don't modify evt.propagateToIMGUI.
                evt.target = panel?.visualTree;
            }
        }
        static bool SendEventToIMGUIContainer(EventBase evt, BaseVisualElementPanel panel)
        {
            if (evt.imguiEvent == null)
            {
                return(false);
            }

            // Root IMGUI is the container that handles all the GUIView/DockArea logic for EditorWindows.
            var rootIMGUI = panel.rootIMGUIContainer;

            if (rootIMGUI == null)
            {
                return(false);
            }

            // If root IMGUI doesn't use event, send it to other IMGUIs down the line.
            if (evt.propagateToIMGUI ||
                evt.eventTypeId == MouseEnterWindowEvent.TypeId() ||
                evt.eventTypeId == MouseLeaveWindowEvent.TypeId() ||
                evt.target == rootIMGUI
                )
            {
                evt.skipElements.Add(evt.target);
                EventDispatchUtilities.PropagateToIMGUIContainer(panel.visualTree, evt);
            }
            // If non-root element doesn't use event, send it to root IMGUI.
            // This is necessary for some behaviors like dropdown menus in IMGUI.
            // See case : https://fogbugz.unity3d.com/f/cases/1223087/
            else
            {
                evt.skipElements.Add(evt.target);
                if (!evt.Skip(rootIMGUI))
                {
                    bool canAffectFocus = evt.target is Focusable f && !f.focusable && f.isIMGUIContainer;
                    rootIMGUI.SendEventToIMGUI(evt, canAffectFocus);
                }
            }

            return(IsDone(evt));
        }
 void OnPanelChanged(BaseVisualElementPanel obj)
 {
     DisposeRenderChain();
     if (panel != null)
     {
         renderChain = CreateRenderChain();
         if (panel.visualTree != null)
         {
             renderChain.UIEOnChildAdded(panel.visualTree.hierarchy.parent, panel.visualTree,
                                         panel.visualTree.hierarchy.parent == null ? 0 : panel.visualTree.hierarchy.parent.IndexOf(panel.visualTree));
             renderChain.UIEOnVisualsChanged(panel.visualTree, true);
         }
         panel.standardShaderChanged           += OnPanelStandardShaderChanged;
         panel.standardWorldSpaceShaderChanged += OnPanelStandardWorldSpaceShaderChanged;
         panel.hierarchyChanged += OnPanelHierarchyChanged;
         OnPanelStandardShaderChanged();
         if (panel.contextType == ContextType.Player)
         {
             OnPanelStandardWorldSpaceShaderChanged();
         }
     }
 }
Example #6
0
        private static bool DoDispatch(BaseVisualElementPanel panel)
        {
            bool result = false;
            bool flag   = UIElementsUtility.s_EventInstance.type == EventType.Repaint;

            if (flag)
            {
                using (UIElementsUtility.s_RepaintProfilerMarker.Auto())
                {
                    panel.Repaint(UIElementsUtility.s_EventInstance);
                }
                IPanelDebug expr_46 = panel.panelDebug;
                Panel       expr_57 = ((expr_46 != null) ? expr_46.debuggerOverlayPanel : null) as Panel;
                if (expr_57 != null)
                {
                    expr_57.Repaint(UIElementsUtility.s_EventInstance);
                }
                result = (panel.IMGUIContainersCount > 0);
            }
            else
            {
                panel.ValidateLayout();
                using (EventBase eventBase = UIElementsUtility.CreateEvent(UIElementsUtility.s_EventInstance))
                {
                    bool flag2 = UIElementsUtility.s_EventInstance.type == EventType.Used || UIElementsUtility.s_EventInstance.type == EventType.Layout || UIElementsUtility.s_EventInstance.type == EventType.ExecuteCommand || UIElementsUtility.s_EventInstance.type == EventType.ValidateCommand;
                    using (UIElementsUtility.s_EventProfilerMarker.Auto())
                    {
                        panel.SendEvent(eventBase, flag2 ? DispatchMode.Immediate : DispatchMode.Default);
                    }
                    bool isPropagationStopped = eventBase.isPropagationStopped;
                    if (isPropagationStopped)
                    {
                        panel.visualTree.IncrementVersion(VersionChangeType.Repaint);
                        result = true;
                    }
                }
            }
            return(result);
        }
        static bool DoDispatch(BaseVisualElementPanel panel)
        {
            bool usesEvent = false;

            if (s_EventInstance.type == EventType.Repaint)
            {
                panel.Repaint(s_EventInstance);

                // TODO get rid of this when we wrap every GUIView inside IMGUIContainers
                // here we pretend to use the repaint event
                // in order to suspend to suspend OnGUI() processing on the native side
                // since we've already run it if we have an IMGUIContainer
                usesEvent = panel.IMGUIContainersCount > 0;
            }
            else
            {
                panel.ValidateLayout();

                using (EventBase evt = CreateEvent(s_EventInstance))
                {
                    bool immediate = s_EventInstance.type == EventType.Used || s_EventInstance.type == EventType.Layout || s_EventInstance.type == EventType.ExecuteCommand || s_EventInstance.type == EventType.ValidateCommand;
                    panel.SendEvent(evt, immediate ? DispatchMode.Immediate : DispatchMode.Queued);

                    // The dispatcher should have finished processing the event,
                    // otherwise we cannot return a value for usesEvent.
                    // FIXME: this makes GUIPointWindowConversionOnMultipleWindow fails because the event sent in the OnGUI is put in the queue.
                    // Debug.Assert(evt.processed);

                    // FIXME: we dont always have to repaint if evt.isPropagationStopped.
                    if (evt.isPropagationStopped)
                    {
                        panel.visualTree.IncrementVersion(VersionChangeType.Repaint);
                        usesEvent = true;
                    }
                }
            }

            return(usesEvent);
        }
        static bool SendEventToIMGUIContainer(EventBase evt, BaseVisualElementPanel panel)
        {
            if (evt.propagateToIMGUI ||
                evt.eventTypeId == MouseEnterWindowEvent.TypeId() ||
                evt.eventTypeId == MouseLeaveWindowEvent.TypeId()
                )
            {
                EventDispatchUtilities.PropagateToIMGUIContainer(panel.visualTree, evt);
            }
            else
            {
                // Send the events to the GUIView container so that it can process them.
                // This is necessary for some behaviors like dropdown menus in IMGUI.
                // See case : https://fogbugz.unity3d.com/f/cases/1223087/
                var topLevelIMGUI = panel.rootIMGUIContainer;
                if (topLevelIMGUI != null && !evt.Skip(topLevelIMGUI) && evt.imguiEvent != null)
                {
                    topLevelIMGUI.SendEventToIMGUI(evt, false);
                }
            }

            return(IsDone(evt));
        }
        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);
            }
        }
Example #10
0
        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 = (mouseEvent as IMouseEventInternal)?.recomputeTopElementUnderMouse ?? true;

                    if (shouldRecomputeTopElementUnderMouse)
                    {
                        basePanel.RecomputeTopElementUnderPointer(mouseEvent.mousePosition, 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;

                if (evt.target is IMGUIContainer)
                {
                    evt.propagateToIMGUI = true;
                    evt.skipElements.Add(evt.target);
                }
                else
                {
                    evt.propagateToIMGUI = false;
                }
            }
        }
 public VisualTreeUpdater(BaseVisualElementPanel panel)
 {
     this.m_Panel        = panel;
     this.m_UpdaterArray = new VisualTreeUpdater.UpdaterArray();
     this.SetDefaultUpdaters();
 }
Example #12
0
        public void DispatchEvent(EventBase evt, IPanel panel)
        {
            MouseCaptureDispatchingStrategy.EventBehavior eventBehavior = MouseCaptureDispatchingStrategy.EventBehavior.None;
            IEventHandler eventHandler = (panel != null) ? panel.GetCapturingElement(PointerId.mousePointerId) : null;
            bool          flag         = eventHandler == null;

            if (!flag)
            {
                VisualElement visualElement = eventHandler as VisualElement;
                bool          flag2         = evt.eventTypeId != EventBase <MouseCaptureOutEvent> .TypeId() && visualElement != null && visualElement.panel == null;

                if (flag2)
                {
                    visualElement.ReleaseMouse();
                }
                else
                {
                    bool flag3 = panel != null && visualElement != null && visualElement.panel.contextType != panel.contextType;
                    if (!flag3)
                    {
                        IMouseEvent mouseEvent = evt as IMouseEvent;
                        bool        flag4      = mouseEvent != null && (evt.target == null || evt.target == eventHandler);
                        if (flag4)
                        {
                            eventBehavior  = MouseCaptureDispatchingStrategy.EventBehavior.IsCapturable;
                            eventBehavior |= MouseCaptureDispatchingStrategy.EventBehavior.IsSentExclusivelyToCapturingElement;
                        }
                        else
                        {
                            bool flag5 = evt.imguiEvent != null && evt.target == null;
                            if (flag5)
                            {
                                eventBehavior = MouseCaptureDispatchingStrategy.EventBehavior.IsCapturable;
                            }
                        }
                        bool flag6 = evt.eventTypeId == EventBase <MouseEnterWindowEvent> .TypeId() || evt.eventTypeId == EventBase <MouseLeaveWindowEvent> .TypeId() || evt.eventTypeId == EventBase <WheelEvent> .TypeId();

                        if (flag6)
                        {
                            eventBehavior = MouseCaptureDispatchingStrategy.EventBehavior.None;
                        }
                        bool flag7 = (eventBehavior & MouseCaptureDispatchingStrategy.EventBehavior.IsCapturable) == MouseCaptureDispatchingStrategy.EventBehavior.IsCapturable;
                        if (flag7)
                        {
                            BaseVisualElementPanel baseVisualElementPanel = panel as BaseVisualElementPanel;
                            bool flag8 = mouseEvent != null && baseVisualElementPanel != null;
                            if (flag8)
                            {
                                IMouseEventInternal expr_139 = mouseEvent as IMouseEventInternal;
                                bool flag9  = expr_139 == null || expr_139.recomputeTopElementUnderMouse;
                                bool flag10 = flag9;
                                if (flag10)
                                {
                                    baseVisualElementPanel.RecomputeTopElementUnderPointer(mouseEvent.mousePosition, evt);
                                }
                            }
                            evt.dispatch = true;
                            evt.target   = eventHandler;
                            CallbackEventHandler expr_175 = eventHandler as CallbackEventHandler;
                            if (expr_175 != null)
                            {
                                expr_175.HandleEventAtTargetPhase(evt);
                            }
                            bool flag11 = (eventBehavior & MouseCaptureDispatchingStrategy.EventBehavior.IsSentExclusivelyToCapturingElement) != MouseCaptureDispatchingStrategy.EventBehavior.IsSentExclusivelyToCapturingElement;
                            if (flag11)
                            {
                                evt.target = null;
                            }
                            evt.currentTarget    = null;
                            evt.propagationPhase = PropagationPhase.None;
                            evt.dispatch         = false;
                            evt.skipElements.Add(eventHandler);
                            evt.stopDispatch = ((eventBehavior & MouseCaptureDispatchingStrategy.EventBehavior.IsSentExclusivelyToCapturingElement) == MouseCaptureDispatchingStrategy.EventBehavior.IsSentExclusivelyToCapturingElement);
                            bool flag12 = evt.target is IMGUIContainer;
                            if (flag12)
                            {
                                evt.propagateToIMGUI = true;
                                evt.skipElements.Add(evt.target);
                            }
                            else
                            {
                                evt.propagateToIMGUI = false;
                            }
                        }
                    }
                }
            }
        }
 static bool SendEventToTarget(EventBase evt, BaseVisualElementPanel panel)
 {
     return SendEventToRegularTarget(evt, panel) ||
         SendEventToIMGUIContainer(evt, panel);
 }
        public void DispatchEvent(EventBase evt, IPanel panel)
        {
            EventBehavior captureBehavior = EventBehavior.None;

            if (MouseCaptureController.mouseCapture == null)
            {
                return;
            }

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

            if (evt.eventTypeId != MouseCaptureOutEvent.TypeId() && captureVE != null && captureVE.panel == null)
            {
                MouseCaptureController.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 == MouseCaptureController.mouseCapture))
            {
                // 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.topElementUnderMouse;

                    basePanel.SetElementUnderMouse(elementUnderMouse, evt);
                }

                IEventHandler originalCaptureElement = MouseCaptureController.mouseCapture;

                evt.dispatch         = true;
                evt.target           = MouseCaptureController.mouseCapture;
                evt.currentTarget    = MouseCaptureController.mouseCapture;
                evt.propagationPhase = PropagationPhase.AtTarget;
                MouseCaptureController.mouseCapture.HandleEvent(evt);

                // Do further processing with a target computed the usual way.
                // However, if mouseEventWasCaptured, 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(originalCaptureElement);

                evt.stopDispatch     = (captureBehavior & EventBehavior.IsSentExclusivelyToCapturingElement) == EventBehavior.IsSentExclusivelyToCapturingElement;
                evt.propagateToIMGUI = false;
            }
        }
 void OnPanelChanged(BaseVisualElementPanel obj)
 {
     DetachFromPanel();
     AttachToPanel();
 }
 private static bool SendEventToTarget(EventBase evt, BaseVisualElementPanel panel)
 {
     return(MouseEventDispatchingStrategy.SendEventToRegularTarget(evt, panel) || MouseEventDispatchingStrategy.SendEventToIMGUIContainer(evt, panel));
 }
        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;
            }

            // Case 1342115: mouse position is in local panel coordinates; sending event to a target from a different
            // panel will lead to a wrong position, so we don't allow it. Note that in general the mouse-down-move-up
            // sequence still works properly because the OS captures the mouse on the starting EditorWindow.
            if (panel != null && captureVE != null && captureVE.panel != panel)
            {
                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 = (mouseEvent as IMouseEventInternal)?.recomputeTopElementUnderMouse ?? true;

                    if (shouldRecomputeTopElementUnderMouse)
                    {
                        basePanel.RecomputeTopElementUnderPointer(PointerId.mousePointerId, mouseEvent.mousePosition, evt);
                    }
                }

                evt.dispatch = true;
                evt.target   = capturingElement;
                var skipDisabledElements = evt.skipDisabledElements;
                evt.skipDisabledElements = false;
                (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.skipDisabledElements = skipDisabledElements;
                }

                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;

                if (evt.target is IMGUIContainer)
                {
                    evt.propagateToIMGUI = true;
                    evt.skipElements.Add(evt.target);
                }
                else
                {
                    evt.propagateToIMGUI = false;
                }
            }
        }
Example #18
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;
        }
 static void OnPanelDestroyed(BaseVisualElementPanel panel)
 {
     s_GroupManagers.Remove(panel);
     panel.panelDisposed -= OnPanelDestroyed;
 }