Skip to content

Commit

Permalink
Fixes gui-cs#2954. Modal view is always refreshing only by moving the…
Browse files Browse the repository at this point in the history
… mouse. (gui-cs#2958)

* Fixes gui-cs#2954. Modal view is always refreshing only by moving the mouse.

* Fixes invisible topLevel to be cleaned up which should be a drawing task.

* Forcing Shutdown.
  • Loading branch information
BDisp authored Nov 7, 2023
1 parent 7b46b1d commit e16205a
Show file tree
Hide file tree
Showing 3 changed files with 179 additions and 10 deletions.
7 changes: 1 addition & 6 deletions Terminal.Gui/Application.cs
Original file line number Diff line number Diff line change
Expand Up @@ -665,8 +665,6 @@ public static void RunIteration (ref RunState state, ref bool firstIteration)
OverlappedTop?.OnActivate (state.Toplevel);
Top.SetSubViewNeedsDisplay ();
Refresh ();
} else if (Current.SuperView == null && Current?.Modal == true) {
Refresh ();
}
}

Expand All @@ -675,13 +673,11 @@ public static void RunIteration (ref RunState state, ref bool firstIteration)
if (state.Toplevel != Top &&
(Top.NeedsDisplay || Top.SubViewNeedsDisplay || Top.LayoutNeeded)) {
state.Toplevel.SetNeedsDisplay (state.Toplevel.Frame);
Top.Clear ();
Top.Draw ();
foreach (var top in _topLevels.Reverse ()) {
if (top != Top && top != state.Toplevel) {
top.SetNeedsDisplay ();
top.SetSubViewNeedsDisplay ();
top.Clear ();
top.Draw ();
}
}
Expand All @@ -690,14 +686,13 @@ public static void RunIteration (ref RunState state, ref bool firstIteration)
&& (Driver.Cols != state.Toplevel.Frame.Width || Driver.Rows != state.Toplevel.Frame.Height)
&& (state.Toplevel.NeedsDisplay || state.Toplevel.SubViewNeedsDisplay || state.Toplevel.LayoutNeeded)) {

state.Toplevel.Clear ();
state.Toplevel.Clear (new Rect (Point.Empty, new Size (Driver.Cols, Driver.Rows)));
}

if (state.Toplevel.NeedsDisplay ||
state.Toplevel.SubViewNeedsDisplay ||
state.Toplevel.LayoutNeeded ||
OverlappedChildNeedsDisplay ()) {
state.Toplevel.Clear ();
state.Toplevel.Draw ();
state.Toplevel.PositionCursor ();
Driver.Refresh ();
Expand Down
109 changes: 107 additions & 2 deletions UnitTests/Application/ApplicationTests.cs
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
using System;
using System;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using Xunit;
using Xunit.Abstractions;

// Alias Console to MockConsole so we don't accidentally use Console
using Console = Terminal.Gui.FakeConsole;

namespace Terminal.Gui.ApplicationTests;

public class ApplicationTests {
public ApplicationTests ()
readonly ITestOutputHelper output;

public ApplicationTests (ITestOutputHelper output)
{
this.output = output;
#if DEBUG_IDISPOSABLE
Responder.Instances.Clear ();
RunState.Instances.Clear ();
Expand Down Expand Up @@ -416,6 +420,107 @@ public void Run_Loaded_Ready_Unlodaded_Events ()
Assert.Equal (3, count);
}

[Fact]
public void Run_Toplevel_With_Modal_View_Does_Not_Refresh_If_Not_Dirty ()
{
Init ();
var count = 0;
Dialog d = null;
var top = Application.Top;
top.DrawContent += (s, a) => count++;
var iteration = -1;
Application.Iteration += (s, a) => {
iteration++;
if (iteration == 0) {
d = new Dialog ();
d.DrawContent += (s, a) => count++;
Application.Run (d);
} else if (iteration < 3) {
Application.OnMouseEvent (new (new () { X = 0, Y = 0, Flags = MouseFlags.ReportMousePosition }));
Assert.False (top.NeedsDisplay);
Assert.False (top.SubViewNeedsDisplay);
Assert.False (top.LayoutNeeded);
Assert.False (d.NeedsDisplay);
Assert.False (d.SubViewNeedsDisplay);
Assert.False (d.LayoutNeeded);
} else {
Application.RequestStop ();
}
};
Application.Run ();
Application.Shutdown ();
// 1 - First top load, 1 - Dialog load, 1 - Dialog unload, Total - 3.
Assert.Equal (3, count);
}

[Fact]
public void Run_A_Modal_Toplevel_Refresh_Background_On_Moving ()
{
Init ();
var d = new Dialog () { Width = 5, Height = 5 };
((FakeDriver)Application.Driver).SetBufferSize (10, 10);
var rs = Application.Begin (d);
TestHelpers.AssertDriverContentsWithFrameAre (@"
┌───┐
│ │
│ │
│ │
└───┘", output);

var attributes = new Attribute [] {
// 0
new Attribute (ColorName.White, ColorName.Black),
// 1
Colors.Dialog.Normal
};
TestHelpers.AssertDriverColorsAre (@"
0000000000
0000000000
0011111000
0011111000
0011111000
0011111000
0011111000
0000000000
0000000000
0000000000
", null, attributes);

Application.OnMouseEvent (new MouseEventEventArgs (new MouseEvent () { X = 2, Y = 2, Flags = MouseFlags.Button1Pressed }));
Assert.Equal (d, Application.MouseGrabView);

Application.OnMouseEvent (new MouseEventEventArgs (new MouseEvent () { X = 1, Y = 1, Flags = MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition }));
Application.Refresh ();
TestHelpers.AssertDriverContentsWithFrameAre (@"
┌───┐
│ │
│ │
│ │
└───┘", output);

attributes = new Attribute [] {
// 0
new Attribute (ColorName.White, ColorName.Black),
// 1
Colors.Dialog.Normal
};
TestHelpers.AssertDriverColorsAre (@"
0000000000
0111110000
0111110000
0111110000
0111110000
0111110000
0000000000
0000000000
0000000000
0000000000
", null, attributes);

Application.End (rs);
Application.Shutdown ();
}

// TODO: Add tests for Run that test errorHandler

#endregion
Expand Down
73 changes: 71 additions & 2 deletions UnitTests/Views/OverlappedTests.cs
Original file line number Diff line number Diff line change
@@ -1,21 +1,27 @@
using System;
using System;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Terminal.Gui;
using Xunit;
using Xunit.Abstractions;

// Alias Console to MockConsole so we don't accidentally use Console
using Console = Terminal.Gui.FakeConsole;

namespace Terminal.Gui.ViewsTests {
public class OverlappedTests {
public OverlappedTests ()
readonly ITestOutputHelper output;

public OverlappedTests (ITestOutputHelper output)
{
this.output = output;
#if DEBUG_IDISPOSABLE
Responder.Instances.Clear ();
RunState.Instances.Clear ();
this.output = output;

#endif
}

Expand Down Expand Up @@ -674,5 +680,68 @@ public void MoveToOverlappedChild_Throw_NullReferenceException_Passing_Null_Para
{
Assert.Throws<NullReferenceException> (delegate { Application.MoveToOverlappedChild (null); });
}


[Fact, AutoInitShutdown]
public void Visible_False_Does_Not_Clear ()
{
var overlapped = new Overlapped ();
var win1 = new Window () { Width = 5, Height = 5, Visible = false };
var win2 = new Window () { X = 1, Y = 1, Width = 5, Height = 5 };
((FakeDriver)Application.Driver).SetBufferSize (10, 10);
var rs = Application.Begin (overlapped);
Application.Begin (win1);
Application.Begin (win2);
Assert.Equal (win2, Application.Current);
var firstIteration = false;
Application.RunIteration (ref rs, ref firstIteration);
TestHelpers.AssertDriverContentsWithFrameAre (@"
┌───┐
│ │
│ │
│ │
└───┘", output);
var attributes = new Attribute [] {
// 0
Colors.TopLevel.Normal,
// 1
Colors.Base.Normal
};
TestHelpers.AssertDriverColorsAre (@"
0000000000
0111110000
0111110000
0111110000
0111110000
0111110000
0000000000
0000000000
0000000000
0000000000", null, attributes);

Application.OnMouseEvent (new MouseEventEventArgs (new MouseEvent () { X = 1, Y = 1, Flags = MouseFlags.Button1Pressed }));
Assert.Equal (win2, Application.MouseGrabView);
Application.OnMouseEvent (new MouseEventEventArgs (new MouseEvent () { X = 2, Y = 2, Flags = MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition }));
Application.RunIteration (ref rs, ref firstIteration);
TestHelpers.AssertDriverContentsWithFrameAre (@"
┌───┐
│ │
│ │
│ │
└───┘", output);
TestHelpers.AssertDriverColorsAre (@"
0000000000
0000000000
0011111000
0011111000
0011111000
0011111000
0011111000
0000000000
0000000000
0000000000", null, attributes);

Application.Shutdown ();
}
}
}

0 comments on commit e16205a

Please sign in to comment.