diff --git a/Source/Editor/GUI/ContextMenu/ContextMenuBase.cs b/Source/Editor/GUI/ContextMenu/ContextMenuBase.cs
index 8596ab83b..27d47345d 100644
--- a/Source/Editor/GUI/ContextMenu/ContextMenuBase.cs
+++ b/Source/Editor/GUI/ContextMenu/ContextMenuBase.cs
@@ -1,3 +1,7 @@
+#if PLATFORM_WINDOWS
+#define USE_IS_FOREGROUND
+#else
+#endif
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using System.Collections.Generic;
@@ -196,6 +200,7 @@ 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
@@ -325,6 +330,49 @@ namespace FlaxEditor.GUI.ContextMenu
// Nothing to do
}
+#if USE_IS_FOREGROUND
+ ///
+ /// 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)
@@ -332,11 +380,39 @@ namespace FlaxEditor.GUI.ContextMenu
return;
// 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))
+ {
+ _parentCM._window.Focus();
+ }
+ }
+ }
+#else
+ private void OnWindowGotFocus()
+ {
+ }
+
+ private void OnWindowLostFocus()
+ {
+ // Skip for parent menus (child should handle lost of focus)
+ if (_childCM != null)
+ return;
+
if (_parentCM != null)
{
if (IsMouseOver)
return;
+ // Check if any external popup is focused
+ foreach (var externalPopup in ExternalPopups)
+ {
+ if (externalPopup && externalPopup.IsFocused)
+ return;
+ }
+
// Check if mouse is over any of the parents
ContextMenuBase focusCM = null;
var cm = _parentCM;
@@ -360,8 +436,11 @@ namespace FlaxEditor.GUI.ContextMenu
}
}
else if (!IsMouseOver)
+ {
Hide();
+ }
}
+#endif
///
public override bool IsMouseOver
@@ -382,6 +461,20 @@ namespace FlaxEditor.GUI.ContextMenu
}
}
+#if USE_IS_FOREGROUND
+ ///
+ 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();
+ }
+ }
+#endif
+
///
public override void Draw()
{