Merge branch 'context_menu_focus_fixes' of https://github.com/GoaLitiuM/FlaxEngine into GoaLitiuM-context_menu_focus_fixes

This commit is contained in:
Wojtek Figat
2023-02-17 20:27:47 +01:00
3 changed files with 50 additions and 74 deletions

View File

@@ -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
}
/// <summary>
/// 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).
/// </summary>
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();
}
/// <inheritdoc />
@@ -405,18 +382,6 @@ namespace FlaxEditor.GUI.ContextMenu
}
}
/// <inheritdoc />
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();
}
}
/// <inheritdoc />
public override void Draw()
{

View File

@@ -700,6 +700,8 @@ namespace FlaxEditor.GUI.Tree
/// <inheritdoc />
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
/// <inheritdoc />
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
/// <inheritdoc />
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;
}
}
}
}
/// <inheritdoc />
public override void OnMouseLeave()
{

View File

@@ -179,6 +179,8 @@ namespace FlaxEngine.GUI
/// <param name="target">The target.</param>
public void OnMouseLeaveControl(Control target)
{
if (Visible)
Hide();
_lastTarget = null;
}