From a6ff5629b4ebe1e4ad21dca945eb344c459bdeb9 Mon Sep 17 00:00:00 2001 From: Tig Date: Tue, 9 Apr 2024 23:39:27 -0400 Subject: [PATCH] Rewrote FindDeepestView to be clearer and more performant --- Terminal.Gui/View/Layout/ViewLayout.cs | 78 +++++++++++++++----------- 1 file changed, 44 insertions(+), 34 deletions(-) diff --git a/Terminal.Gui/View/Layout/ViewLayout.cs b/Terminal.Gui/View/Layout/ViewLayout.cs index 0090b353dc..03bc864efa 100644 --- a/Terminal.Gui/View/Layout/ViewLayout.cs +++ b/Terminal.Gui/View/Layout/ViewLayout.cs @@ -605,53 +605,63 @@ public LayoutStyle LayoutStyle // CONCURRENCY: This method is not thread-safe. Undefined behavior and likely program crashes are exposed by unsynchronized access to InternalSubviews. internal static View? FindDeepestView (View? start, int x, int y) { - if (start is null || !start.Visible || !start.Contains (x, y)) + while (start is { Visible: true } && start.Contains (x, y)) { - return null; - } - - Adornment? found = null; + Adornment? found = null; - if (start.Margin.Contains (x, y)) - { - found = start.Margin; - } - else if (start.Border.Contains (x, y)) - { - found = start.Border; - } - else if (start.Padding.Contains (x, y)) - { - found = start.Padding; - } + if (start.Margin.Contains (x, y)) + { + found = start.Margin; + } + else if (start.Border.Contains (x, y)) + { + found = start.Border; + } + else if (start.Padding.Contains (x, y)) + { + found = start.Padding; + } - Point viewportOffset = start.GetViewportOffsetFromFrame (); + Point viewportOffset = start.GetViewportOffsetFromFrame (); - if (found is { }) - { - start = found; - viewportOffset = found.Parent.Frame.Location; - } - - if (start.InternalSubviews is { Count: > 0 }) - { - int startOffsetX = x - (start.Frame.X + viewportOffset.X); - int startOffsetY = y - (start.Frame.Y + viewportOffset.Y); + if (found is { }) + { + start = found; + viewportOffset = found.Parent.Frame.Location; + } - for (int i = start.InternalSubviews.Count - 1; i >= 0; i--) + if (start.InternalSubviews is { Count: > 0 }) { - View nextStart = start.InternalSubviews [i]; + int startOffsetX = x - (start.Frame.X + viewportOffset.X); + int startOffsetY = y - (start.Frame.Y + viewportOffset.Y); - if (nextStart.Visible && nextStart.Contains (startOffsetX + start.Viewport.X, startOffsetY + start.Viewport.Y)) + for (int i = start.InternalSubviews.Count - 1; i >= 0; i--) { - // TODO: Remove recursion - return FindDeepestView (nextStart, startOffsetX + start.Viewport.X, startOffsetY + start.Viewport.Y) ?? nextStart; + View nextStart = start.InternalSubviews [i]; + + if (nextStart.Visible && nextStart.Contains (startOffsetX + start.Viewport.X, startOffsetY + start.Viewport.Y)) + { + start = nextStart; + x = startOffsetX + start.Viewport.X; + y = startOffsetY + start.Viewport.Y; + break; + } + + if (i == 0) + { + return start; // If no visible subview is found, return the current start view + } } } + else + { + return start; + } } - return start; + return null; } + #nullable restore ///