Merge pull request #3334 from BDisp/v2_mousegrabview-fix_3333

Fixes #3333. Application.UnGrabbedMouse event doesn't allow grab another view after exit.
This commit is contained in:
Tig
2024-03-18 08:42:20 -07:00
committed by GitHub
4 changed files with 75 additions and 40 deletions

View File

@@ -1316,8 +1316,9 @@ public static partial class Application
if (!OnUnGrabbingMouse (MouseGrabView))
{
OnUnGrabbedMouse (MouseGrabView);
var view = MouseGrabView;
MouseGrabView = null;
OnUnGrabbedMouse (view);
}
}

View File

@@ -78,6 +78,8 @@ public class ScrollView : View
_contentView.MouseEnter += View_MouseEnter;
_contentView.MouseLeave += View_MouseLeave;
Application.UnGrabbedMouse += Application_UnGrabbedMouse;
// Things this view knows how to do
AddCommand (Command.ScrollUp, () => ScrollUp (1));
AddCommand (Command.ScrollDown, () => ScrollDown (1));
@@ -134,6 +136,28 @@ public class ScrollView : View
};
}
private void Application_UnGrabbedMouse (object sender, ViewEventArgs e)
{
var parent = e.View is Adornment adornment ? adornment.Parent : e.View;
if (parent is { })
{
var supView = parent.SuperView;
while (supView is { })
{
if (supView == _contentView)
{
Application.GrabMouse (this);
break;
}
supView = supView.SuperView;
}
}
}
/// <summary>If true the vertical/horizontal scroll bars won't be showed if it's not needed.</summary>
public bool AutoHideScrollBars
{
@@ -536,6 +560,8 @@ public class ScrollView : View
_horizontal?.Dispose ();
}
Application.UnGrabbedMouse -= Application_UnGrabbedMouse;
base.Dispose (disposing);
}
@@ -719,7 +745,7 @@ public class ScrollView : View
private void View_MouseLeave (object sender, MouseEventEventArgs e)
{
if (Application.MouseGrabView is { } && Application.MouseGrabView != _vertical && Application.MouseGrabView != _horizontal)
if (Application.MouseGrabView is { } && Application.MouseGrabView != this && Application.MouseGrabView != _vertical && Application.MouseGrabView != _horizontal)
{
Application.UngrabMouse ();
}

View File

@@ -316,8 +316,9 @@ public class MouseTests
View grabView = null;
var count = 0;
var view1 = new View ();
var view2 = new View ();
var view1 = new View { Id = "view1" };
var view2 = new View { Id = "view2" };
var view3 = new View { Id = "view3" };
Application.GrabbedMouse += Application_GrabbedMouse;
Application.UnGrabbedMouse += Application_UnGrabbedMouse;
@@ -343,6 +344,8 @@ public class MouseTests
Application.UngrabMouse ();
Assert.Equal (2, count);
Assert.Equal (grabView, view2);
Assert.Equal (view3, Application.MouseGrabView);
Application.UngrabMouse ();
Assert.Null (Application.MouseGrabView);
void Application_GrabbedMouse (object sender, ViewEventArgs e)
@@ -376,6 +379,12 @@ public class MouseTests
count++;
if (count > 1)
{
// It's possible to grab another view after the previous was ungrabbed
Application.GrabMouse (view3);
}
Application.UnGrabbedMouse -= Application_UnGrabbedMouse;
}
}

View File

@@ -1366,7 +1366,6 @@ public class ToplevelTests
Assert.Equal (new (0, 0, 10, 5), view._needsDisplayRect);
}
// BUGBUG: Broke this test with #2483 - @bdisp I need your help figuring out why
[Fact]
[AutoInitShutdown]
public void Toplevel_Inside_ScrollView_MouseGrabView ()
@@ -1471,44 +1470,44 @@ public class ToplevelTests
Assert.Equal (win.Border, Application.MouseGrabView);
top.SetNeedsLayout ();
top.LayoutSubviews ();
// BUGBUG: tig broke this in #3273
// Assert.Equal (new Rectangle (2, 2, 195, 95), win.Frame);
// Application.Refresh ();
Assert.Equal (new Rectangle (2, 2, 195, 95), win.Frame);
Application.Refresh ();
// TestHelpers.AssertDriverContentsWithFrameAre (
// @"
//
//
// ┌────────────────────────────────────│
// │ ┴
// │ ░
// │ ░
// │ ░
// │ ░
// │ ░
// │ ░
// │ ░
// │ ░
// │ ░
// │ ░
// │ ▼
//◄├──────┤░░░░░░░░░░░░░░░░░░░░░░░░░░░░░► ",
// _output
// );
TestHelpers.AssertDriverContentsWithFrameAre (
@"
┌────────────────────────────────────│
│ ┴
│ ░
│ ░
│ ░
│ ░
│ ░
│ ░
│ ░
│ ░
│ ░
│ ░
│ ▼
◄├──────┤░░░░░░░░░░░░░░░░░░░░░░░░░░░░░► ",
_output
);
// Application.OnMouseEvent (
// new MouseEventEventArgs (
// new MouseEvent { X = 5, Y = 5, Flags = MouseFlags.Button1Released }
// )
// );
// Assert.Null (Application.MouseGrabView);
Application.OnMouseEvent (
new MouseEventEventArgs (
new MouseEvent { X = 5, Y = 5, Flags = MouseFlags.Button1Released }
)
);
// ScrollView always grab the mouse when the container's subview OnMouseEnter don't want grab the mouse
Assert.Equal (scrollView, Application.MouseGrabView);
// Application.OnMouseEvent (
// new MouseEventEventArgs (
// new MouseEvent { X = 4, Y = 4, Flags = MouseFlags.ReportMousePosition }
// )
// );
// Assert.Equal (scrollView, Application.MouseGrabView);
Application.OnMouseEvent (
new MouseEventEventArgs (
new MouseEvent { X = 4, Y = 4, Flags = MouseFlags.ReportMousePosition }
)
);
Assert.Equal (scrollView, Application.MouseGrabView);
}
[Fact]