Skip to content

Commit da3dd51

Browse files
committed
Fix window activation and rendering bugs
Fixed several bugs related to window z-order and rendering: WindowStateService.cs: - BringToFront now activates window (matches standard windowing behavior) - SendToBack updated to activate next window if current was active - Improved documentation for z-order methods RenderCoordinator.cs: - Clear coverage cache when z-indices change between frames - Prevents stale occlusion data from previous frame WindowPositioningManager.cs: - Use SetPositionDirect instead of SetPosition in CenterOnScreen - Prevents recursion when centering windows
1 parent 048216e commit da3dd51

3 files changed

Lines changed: 41 additions & 8 deletions

File tree

SharpConsoleUI/Core/WindowStateService.cs

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -618,7 +618,8 @@ public void EndResize()
618618
#region Z-Order Management
619619

620620
/// <summary>
621-
/// Brings a window to the front (highest Z-index).
621+
/// Brings a window to the front (highest Z-index) and activates it.
622+
/// This matches typical windowing system behavior where bringing a window to front makes it active.
622623
/// </summary>
623624
/// <param name="window">The window to bring to front.</param>
624625
public void BringToFront(Window window)
@@ -628,19 +629,17 @@ public void BringToFront(Window window)
628629

629630
lock (_lock)
630631
{
631-
window.ZIndex = GetMaxZIndex() + 1;
632-
UpdateStateInternal(CreateStateSnapshot());
633-
634-
// Invalidate window when z-order changes because visibleRegions change
635-
// Window may now have more visible area and needs to repaint with new clipRect
636-
window.Invalidate(true);
632+
// Activate window (which also brings it to front with highest Z-index)
633+
// This ensures the window is both visually on top and receives input
634+
ActivateWindow(window);
637635

638636
FireWindowEvent(window, WindowEventType.ZOrderChanged);
639637
}
640638
}
641639

642640
/// <summary>
643641
/// Sends a window to the back (lowest Z-index).
642+
/// If the window was active, activates the next available window.
644643
/// </summary>
645644
/// <param name="window">The window to send to back.</param>
646645
public void SendToBack(Window window)
@@ -650,6 +649,8 @@ public void SendToBack(Window window)
650649

651650
lock (_lock)
652651
{
652+
var wasActive = _currentState.ActiveWindow == window;
653+
653654
var minZIndex = _windows.Count > 0 ? _windows.Values.Min(w => w.ZIndex) : 0;
654655
window.ZIndex = minZIndex - 1;
655656
UpdateStateInternal(CreateStateSnapshot());
@@ -658,6 +659,13 @@ public void SendToBack(Window window)
658659
// Window may now have less visible area and needs to repaint with new clipRect
659660
window.Invalidate(true);
660661

662+
// If this was the active window, activate the next one
663+
if (wasActive)
664+
{
665+
var nextWindow = FindNextActiveWindow(window);
666+
ActivateWindow(nextWindow);
667+
}
668+
661669
FireWindowEvent(window, WindowEventType.ZOrderChanged);
662670
}
663671
}
@@ -827,6 +835,28 @@ private void FireInteractionChanged(InteractionState previousState, InteractionS
827835
});
828836
}
829837

838+
/// <summary>
839+
/// Invalidates all windows that overlap with the specified window.
840+
/// Used after z-order changes to ensure proper rendering of affected windows.
841+
/// </summary>
842+
private void InvalidateOverlappingWindows(Window window)
843+
{
844+
if (window == null) return;
845+
846+
var windowRect = new System.Drawing.Rectangle(window.Left, window.Top, window.Width, window.Height);
847+
848+
foreach (var other in _windows.Values)
849+
{
850+
if (other == window) continue;
851+
852+
// Invalidate any window that overlaps with the moved window
853+
if (Helpers.GeometryHelpers.DoesRectangleOverlapWindow(windowRect, other))
854+
{
855+
other.Invalidate(true);
856+
}
857+
}
858+
}
859+
830860
#endregion
831861

832862
#region IDisposable

SharpConsoleUI/Rendering/RenderCoordinator.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,9 @@ private void RenderWindows()
334334
// Reuse cached HashSet to avoid allocation
335335
_windowsToRender.Clear();
336336

337+
// Clear coverage cache - Z-indices may have changed since last frame
338+
_coverageCache.Clear();
339+
337340
// Build sorted window list for rendering (avoid LINQ allocations)
338341
_sortedWindows.Clear();
339342
_sortedWindows.AddRange(_windowSystemContext.Windows.Values);

SharpConsoleUI/Windows/WindowPositioningManager.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public void MoveWindowTo(Window window, int newLeft, int newTop)
5858
var oldBounds = new Rectangle(window.Left, window.Top, window.Width, window.Height);
5959

6060
_renderCoordinator.AddPendingDesktopClear(oldBounds);
61-
window.SetPosition(new Point(newLeft, newTop));
61+
window.SetPositionDirect(new Point(newLeft, newTop)); // Use direct setter to avoid recursion
6262
window.Invalidate(true);
6363

6464
// Invalidate windows that were underneath (now exposed)

0 commit comments

Comments
 (0)