diff --git a/Source/Editor/GUI/ContextMenu/ContextMenuBase.cs b/Source/Editor/GUI/ContextMenu/ContextMenuBase.cs index f93e31957..8596ab83b 100644 --- a/Source/Editor/GUI/ContextMenu/ContextMenuBase.cs +++ b/Source/Editor/GUI/ContextMenu/ContextMenuBase.cs @@ -196,7 +196,6 @@ namespace FlaxEditor.GUI.ContextMenu desc.HasSizingFrame = false; OnWindowCreating(ref desc); _window = Platform.CreateWindow(ref desc); - _window.GotFocus += OnWindowGotFocus; _window.LostFocus += OnWindowLostFocus; // Attach to the window @@ -326,48 +325,6 @@ namespace FlaxEditor.GUI.ContextMenu // Nothing to do } - /// - /// Returns true if context menu is in foreground (eg. context window or any child window has user focus or user opened additional popup within this context). - /// - protected virtual bool IsForeground - { - get - { - // Any external popup is focused - foreach (var externalPopup in ExternalPopups) - { - if (externalPopup && externalPopup.IsForegroundWindow) - return true; - } - - // Any context menu window is focused - var anyForeground = false; - var c = this; - while (!anyForeground && c != null) - { - if (c._window != null && c._window.IsForegroundWindow) - anyForeground = true; - c = c._childCM; - } - - return anyForeground; - } - } - - private void OnWindowGotFocus() - { - var child = _childCM; - if (child != null && _window && _window.IsForegroundWindow) - { - // Hide child if user clicked over parent (do it next frame to process other events before - eg. child windows focus loss) - FlaxEngine.Scripting.InvokeOnUpdate(() => - { - if (child == _childCM) - HideChild(); - }); - } - } - private void OnWindowLostFocus() { // Skip for parent menus (child should handle lost of focus) @@ -377,13 +334,33 @@ namespace FlaxEditor.GUI.ContextMenu // Check if user stopped using that popup menu if (_parentCM != null) { - // Focus parent if user clicked over the parent popup - var mouse = _parentCM.PointFromScreen(FlaxEngine.Input.MouseScreenPosition); - if (_parentCM.ContainsPoint(ref mouse)) + if (IsMouseOver) + return; + + // Check if mouse is over any of the parents + ContextMenuBase focusCM = null; + var cm = _parentCM; + while (cm != null) { - _parentCM._window.Focus(); + if (cm.IsMouseOver) + focusCM = cm; + cm = cm._parentCM; + } + + if (focusCM != null) + { + // Focus on the clicked parent and hide any open sub-menus + focusCM.HideChild(); + focusCM._window?.Focus(); + } + else + { + // User clicked outside the context menus, hide the whole context menu tree + TopmostCM.Hide(); } } + else if (!IsMouseOver) + Hide(); } /// @@ -405,18 +382,6 @@ namespace FlaxEditor.GUI.ContextMenu } } - /// - public override void Update(float deltaTime) - { - base.Update(deltaTime); - - // Let root context menu to check if none of the popup windows - if (_parentCM == null && !IsForeground) - { - Hide(); - } - } - /// public override void Draw() { diff --git a/Source/Editor/GUI/Tree/TreeNode.cs b/Source/Editor/GUI/Tree/TreeNode.cs index 54aeedb9a..f2c8e2d6a 100644 --- a/Source/Editor/GUI/Tree/TreeNode.cs +++ b/Source/Editor/GUI/Tree/TreeNode.cs @@ -700,6 +700,8 @@ namespace FlaxEditor.GUI.Tree /// public override bool OnMouseDown(Float2 location, MouseButton button) { + UpdateMouseOverFlags(location); + // Check if mouse hits bar and node isn't a root if (_mouseOverHeader) { @@ -728,6 +730,8 @@ namespace FlaxEditor.GUI.Tree /// public override bool OnMouseUp(Float2 location, MouseButton button) { + UpdateMouseOverFlags(location); + // Clear flag for left button if (button == MouseButton.Left) { @@ -815,21 +819,7 @@ namespace FlaxEditor.GUI.Tree /// public override void OnMouseMove(Float2 location) { - // Cache flags - _mouseOverArrow = HasAnyVisibleChild && ArrowRect.Contains(location); - _mouseOverHeader = new Rectangle(0, 0, Width, _headerHeight - 1).Contains(location); - if (_mouseOverHeader) - { - // Allow non-scrollable controls to stay on top of the header and override the mouse behaviour - for (int i = 0; i < Children.Count; i++) - { - if (!Children[i].IsScrollable && IntersectsChildContent(Children[i], location, out _)) - { - _mouseOverHeader = false; - break; - } - } - } + UpdateMouseOverFlags(location); // Check if start drag and drop if (_isMouseDown && Float2.Distance(_mouseDownPos, location) > 10.0f) @@ -852,6 +842,25 @@ namespace FlaxEditor.GUI.Tree } } + private void UpdateMouseOverFlags(Vector2 location) + { + // Cache flags + _mouseOverArrow = HasAnyVisibleChild && ArrowRect.Contains(location); + _mouseOverHeader = new Rectangle(0, 0, Width, _headerHeight - 1).Contains(location); + if (_mouseOverHeader) + { + // Allow non-scrollable controls to stay on top of the header and override the mouse behaviour + for (int i = 0; i < Children.Count; i++) + { + if (!Children[i].IsScrollable && IntersectsChildContent(Children[i], location, out _)) + { + _mouseOverHeader = false; + break; + } + } + } + } + /// public override void OnMouseLeave() { diff --git a/Source/Engine/UI/GUI/Tooltip.cs b/Source/Engine/UI/GUI/Tooltip.cs index 9180d6d58..5089e0211 100644 --- a/Source/Engine/UI/GUI/Tooltip.cs +++ b/Source/Engine/UI/GUI/Tooltip.cs @@ -179,6 +179,8 @@ namespace FlaxEngine.GUI /// The target. public void OnMouseLeaveControl(Control target) { + if (Visible) + Hide(); _lastTarget = null; }