Fixes #1999. Prevents the mouseGrabView being executed with a null view. (#2000)

* Unit test that will fail without the fix.

* ScrollView must return true after ungrab the mouse to allow the View property run after returned.

* Fixes #1999. Prevents the mouseGrabView being executed with a null view.

* Added one more assert null check.
This commit is contained in:
BDisp
2022-09-15 01:18:00 +00:00
committed by GitHub
parent c983c2e65a
commit 75c0160d96
4 changed files with 125 additions and 2 deletions

View File

@@ -638,6 +638,11 @@ namespace Terminal.Gui {
}
RootMouseEvent?.Invoke (me);
if (mouseGrabView != null) {
if (view == null) {
UngrabMouse ();
return;
}
var newxy = mouseGrabView.ScreenToView (me.X, me.Y);
var nme = new MouseEvent () {
X = newxy.X,
@@ -653,7 +658,9 @@ namespace Terminal.Gui {
// System.Diagnostics.Debug.WriteLine ($"{nme.Flags};{nme.X};{nme.Y};{mouseGrabView}");
if (mouseGrabView != null) {
mouseGrabView.OnMouseEvent (nme);
return;
if (mouseGrabView != null) {
return;
}
}
}

View File

@@ -517,7 +517,6 @@ namespace Terminal.Gui {
horizontal.MouseEvent (me);
} else if (IsOverridden (me.View)) {
Application.UngrabMouse ();
return false;
}
return true;
}

View File

@@ -1408,5 +1408,87 @@ namespace Terminal.Gui.Core {
Application.Shutdown ();
}
[Fact, AutoInitShutdown]
public void MouseGrabView_WithNullMouseEventView ()
{
var tf = new TextField () { Width = 10 };
var sv = new ScrollView () {
Width = Dim.Fill (),
Height = Dim.Fill (),
ContentSize = new Size (100, 100)
};
sv.Add (tf);
Application.Top.Add (sv);
var iterations = -1;
Application.Iteration = () => {
iterations++;
if (iterations == 0) {
Assert.True (tf.HasFocus);
Assert.Null (Application.mouseGrabView);
ReflectionTools.InvokePrivate (
typeof (Application),
"ProcessMouseEvent",
new MouseEvent () {
X = 5,
Y = 5,
Flags = MouseFlags.ReportMousePosition
});
Assert.Equal (sv, Application.mouseGrabView);
MessageBox.Query ("Title", "Test", "Ok");
Assert.Null (Application.mouseGrabView);
} else if (iterations == 1) {
Assert.Equal (sv, Application.mouseGrabView);
ReflectionTools.InvokePrivate (
typeof (Application),
"ProcessMouseEvent",
new MouseEvent () {
X = 5,
Y = 5,
Flags = MouseFlags.ReportMousePosition
});
Assert.Null (Application.mouseGrabView);
ReflectionTools.InvokePrivate (
typeof (Application),
"ProcessMouseEvent",
new MouseEvent () {
X = 40,
Y = 12,
Flags = MouseFlags.ReportMousePosition
});
Assert.Null (Application.mouseGrabView);
ReflectionTools.InvokePrivate (
typeof (Application),
"ProcessMouseEvent",
new MouseEvent () {
X = 0,
Y = 0,
Flags = MouseFlags.Button1Pressed
});
Assert.Null (Application.mouseGrabView);
Application.RequestStop ();
} else if (iterations == 2) {
Assert.Null (Application.mouseGrabView);
Application.RequestStop ();
}
};
Application.Run ();
}
}
}

View File

@@ -0,0 +1,35 @@
using System;
using System.Reflection;
public static class ReflectionTools {
// If the class is non-static
public static Object InvokePrivate (Object objectUnderTest, string method, params object [] args)
{
Type t = objectUnderTest.GetType ();
return t.InvokeMember (method,
BindingFlags.InvokeMethod |
BindingFlags.NonPublic |
BindingFlags.Instance |
BindingFlags.Static,
null,
objectUnderTest,
args);
}
// if the class is static
public static Object InvokePrivate (Type typeOfObjectUnderTest, string method, params object [] args)
{
MemberInfo [] members = typeOfObjectUnderTest.GetMembers (BindingFlags.NonPublic | BindingFlags.Static);
foreach (var member in members) {
if (member.Name == method) {
return typeOfObjectUnderTest.InvokeMember (method,
BindingFlags.NonPublic |
BindingFlags.Static |
BindingFlags.InvokeMethod,
null,
typeOfObjectUnderTest,
args);
}
}
return null;
}
}