mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2025-12-26 15:57:56 +01:00
Fixes #4216. Legacy drivers aren't refreshing the screen correctly on view drag
This commit is contained in:
@@ -535,7 +535,7 @@ public static partial class Application // Run (Begin, Run, End, Stop)
|
||||
return firstIteration;
|
||||
}
|
||||
|
||||
LayoutAndDraw ();
|
||||
LayoutAndDraw (TopLevels.Any (v => v.NeedsLayout || v.NeedsDraw));
|
||||
|
||||
if (PositionCursor ())
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#nullable enable
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Terminal.Gui.ViewBase;
|
||||
|
||||
@@ -111,6 +112,26 @@ public partial class View // Drawing APIs
|
||||
Border?.AdvanceDrawIndicator ();
|
||||
|
||||
ClearNeedsDraw ();
|
||||
|
||||
if (this is not Adornment && SuperView is not Adornment)
|
||||
{
|
||||
// Parent
|
||||
Debug.Assert (Margin!.Parent == this);
|
||||
Debug.Assert (Border!.Parent == this);
|
||||
Debug.Assert (Padding!.Parent == this);
|
||||
|
||||
// SubViewNeedsDraw is set to false by ClearNeedsDraw.
|
||||
Debug.Assert (SubViewNeedsDraw == false);
|
||||
Debug.Assert (Margin!.SubViewNeedsDraw == false);
|
||||
Debug.Assert (Border!.SubViewNeedsDraw == false);
|
||||
Debug.Assert (Padding!.SubViewNeedsDraw == false);
|
||||
|
||||
// NeedsDraw is set to false by ClearNeedsDraw.
|
||||
Debug.Assert (NeedsDraw == false);
|
||||
Debug.Assert (Margin!.NeedsDraw == false);
|
||||
Debug.Assert (Border!.NeedsDraw == false);
|
||||
Debug.Assert (Padding!.NeedsDraw == false);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------
|
||||
@@ -131,6 +152,11 @@ public partial class View // Drawing APIs
|
||||
|
||||
private void DoDrawAdornmentsSubViews ()
|
||||
{
|
||||
if (Border?.NeedsLayout == true)
|
||||
{
|
||||
Border.Layout ();
|
||||
}
|
||||
|
||||
// NOTE: We do not support subviews of Margin?
|
||||
|
||||
if (Border?.SubViews is { } && Border.Thickness != Thickness.Empty)
|
||||
@@ -151,6 +177,11 @@ public partial class View // Drawing APIs
|
||||
SetClip (saved);
|
||||
}
|
||||
|
||||
if (Padding?.NeedsLayout == true)
|
||||
{
|
||||
Padding.Layout ();
|
||||
}
|
||||
|
||||
if (Padding?.SubViews is { } && Padding.Thickness != Thickness.Empty)
|
||||
{
|
||||
foreach (View subview in Padding.SubViews)
|
||||
@@ -720,8 +751,7 @@ public partial class View // Drawing APIs
|
||||
/// </remarks>
|
||||
public bool NeedsDraw
|
||||
{
|
||||
// TODO: Figure out if we can decouple NeedsDraw from NeedsLayout.
|
||||
get => Visible && (NeedsDrawRect != Rectangle.Empty || NeedsLayout);
|
||||
get => Visible && (NeedsDrawRect != Rectangle.Empty || Margin?.NeedsDraw == true || Border?.NeedsDraw == true || Padding?.NeedsDraw == true);
|
||||
set
|
||||
{
|
||||
if (value)
|
||||
@@ -807,7 +837,7 @@ public partial class View // Drawing APIs
|
||||
}
|
||||
|
||||
// There was multiple enumeration error here, so calling ToArray - probably a stop gap
|
||||
foreach (View subview in InternalSubViews)
|
||||
foreach (View subview in InternalSubViews.ToArray ())
|
||||
{
|
||||
if (subview.Frame.IntersectsWith (viewPortRelativeRegion))
|
||||
{
|
||||
@@ -846,17 +876,17 @@ public partial class View // Drawing APIs
|
||||
NeedsDrawRect = Rectangle.Empty;
|
||||
SubViewNeedsDraw = false;
|
||||
|
||||
if (Margin is { } && Margin.Thickness != Thickness.Empty)
|
||||
if (Margin is { } && (Margin.Thickness != Thickness.Empty || Margin.SubViewNeedsDraw || Margin.NeedsDraw))
|
||||
{
|
||||
Margin?.ClearNeedsDraw ();
|
||||
}
|
||||
|
||||
if (Border is { } && Border.Thickness != Thickness.Empty)
|
||||
if (Border is { } && (Border.Thickness != Thickness.Empty || Border.SubViewNeedsDraw || Border.NeedsDraw))
|
||||
{
|
||||
Border?.ClearNeedsDraw ();
|
||||
}
|
||||
|
||||
if (Padding is { } && Padding.Thickness != Thickness.Empty)
|
||||
if (Padding is { } && (Padding.Thickness != Thickness.Empty || Padding.SubViewNeedsDraw || Padding.NeedsDraw))
|
||||
{
|
||||
Padding?.ClearNeedsDraw ();
|
||||
}
|
||||
@@ -876,7 +906,6 @@ public partial class View // Drawing APIs
|
||||
{
|
||||
LineCanvas.Clear ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endregion NeedsDraw
|
||||
|
||||
@@ -419,7 +419,10 @@ public partial class View // Layout APIs
|
||||
{
|
||||
LayoutSubViews ();
|
||||
|
||||
// Debug.Assert(!NeedsLayout);
|
||||
// A layout was performed so a draw is needed
|
||||
// NeedsLayout may still be true if a dependent View still needs layout after SubViewsLaidOut event
|
||||
SetNeedsDraw ();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ public class NeedsDrawTests
|
||||
View view = new () { Width = 0, Height = 0 };
|
||||
view.BeginInit ();
|
||||
view.EndInit ();
|
||||
Assert.True (view.NeedsDraw);
|
||||
Assert.False (view.NeedsDraw);
|
||||
|
||||
//Assert.False (view.SubViewNeedsDraw);
|
||||
}
|
||||
@@ -70,14 +70,16 @@ public class NeedsDrawTests
|
||||
view.NeedsDraw = false;
|
||||
|
||||
view.BeginInit ();
|
||||
Assert.True (view.NeedsDraw); // Because layout is still needed
|
||||
Assert.False (view.NeedsDraw); // Because layout is still needed
|
||||
|
||||
view.Layout ();
|
||||
Assert.False (view.NeedsDraw);
|
||||
// NeedsDraw is true after layout and NeedsLayout is false if SubViewsLaidOut doesn't call SetNeedsLayout
|
||||
Assert.True (view.NeedsDraw);
|
||||
Assert.False (view.NeedsLayout);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NeedsDraw_False_After_EndInit ()
|
||||
public void NeedsDraw_True_After_EndInit_Where_Call_Layout ()
|
||||
{
|
||||
var view = new View { Width = 2, Height = 2, BorderStyle = LineStyle.Single };
|
||||
Assert.True (view.NeedsDraw);
|
||||
@@ -96,7 +98,7 @@ public class NeedsDrawTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NeedsDraw_After_SetLayoutNeeded ()
|
||||
public void NeedsDraw_After_SetLayoutNeeded_And_Layout ()
|
||||
{
|
||||
var view = new View { Width = 2, Height = 2 };
|
||||
Assert.True (view.NeedsDraw);
|
||||
@@ -107,8 +109,12 @@ public class NeedsDrawTests
|
||||
Assert.False (view.NeedsLayout);
|
||||
|
||||
view.SetNeedsLayout ();
|
||||
Assert.True (view.NeedsDraw);
|
||||
Assert.False (view.NeedsDraw);
|
||||
Assert.True (view.NeedsLayout);
|
||||
|
||||
view.Layout ();
|
||||
Assert.True (view.NeedsDraw);
|
||||
Assert.False (view.NeedsLayout);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -121,21 +127,27 @@ public class NeedsDrawTests
|
||||
Assert.False (view.NeedsDraw);
|
||||
Assert.False (view.NeedsLayout);
|
||||
|
||||
// SRL won't change anything since the view is Absolute
|
||||
// SRL won't change anything since the view frame wasn't changed
|
||||
view.SetRelativeLayout (Application.Screen.Size);
|
||||
Assert.False (view.NeedsDraw);
|
||||
|
||||
view.SetNeedsLayout ();
|
||||
|
||||
// SRL won't change anything since the view is Absolute
|
||||
// SRL won't change anything since the view frame wasn't changed
|
||||
// SRL doesn't depend on NeedsLayout, but LayoutSubViews does
|
||||
view.SetRelativeLayout (Application.Screen.Size);
|
||||
Assert.False (view.NeedsDraw);
|
||||
Assert.True (view.NeedsLayout);
|
||||
|
||||
view.Layout ();
|
||||
Assert.True (view.NeedsDraw);
|
||||
Assert.False (view.NeedsLayout);
|
||||
|
||||
view.NeedsDraw = false;
|
||||
|
||||
// SRL won't change anything since the view is Absolute. However, Layout has not been called
|
||||
// SRL won't change anything since the view frame wasn't changed. However, Layout has not been called
|
||||
view.SetRelativeLayout (new (10, 10));
|
||||
Assert.True (view.NeedsDraw);
|
||||
Assert.False (view.NeedsDraw);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -149,17 +161,20 @@ public class NeedsDrawTests
|
||||
Width = Dim.Fill (),
|
||||
Height = Dim.Fill ()
|
||||
};
|
||||
Assert.True (superView.NeedsDraw);
|
||||
|
||||
// A layout wasn't called yet, so NeedsDraw is still empty
|
||||
Assert.False (superView.NeedsDraw);
|
||||
|
||||
superView.Add (view);
|
||||
Assert.True (view.NeedsDraw);
|
||||
Assert.True (superView.NeedsDraw);
|
||||
// A layout wasn't called yet, so NeedsDraw is still empty
|
||||
Assert.False (view.NeedsDraw);
|
||||
Assert.False (superView.NeedsDraw);
|
||||
|
||||
superView.BeginInit ();
|
||||
Assert.True (view.NeedsDraw);
|
||||
Assert.True (superView.NeedsDraw);
|
||||
Assert.False (view.NeedsDraw);
|
||||
Assert.False (superView.NeedsDraw);
|
||||
|
||||
superView.EndInit ();
|
||||
superView.EndInit (); // Call Layout
|
||||
Assert.True (view.NeedsDraw);
|
||||
Assert.True (superView.NeedsDraw);
|
||||
|
||||
@@ -177,9 +192,10 @@ public class NeedsDrawTests
|
||||
Width = Dim.Fill (),
|
||||
Height = Dim.Fill ()
|
||||
};
|
||||
Assert.True (superView.NeedsDraw);
|
||||
Assert.False (superView.NeedsDraw);
|
||||
|
||||
superView.Layout ();
|
||||
Assert.True (superView.NeedsDraw);
|
||||
|
||||
superView.NeedsDraw = false;
|
||||
superView.SetRelativeLayout (new (10, 10));
|
||||
|
||||
Reference in New Issue
Block a user