Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 35 additions & 2 deletions Terminal.Gui/Core/Application.cs
Original file line number Diff line number Diff line change
Expand Up @@ -581,7 +581,22 @@ static View FindTopFromView (View view)
return top;
}

internal static View mouseGrabView;
static View mouseGrabView;

/// <summary>
/// The view that grabbed the mouse, to where will be routed all the mouse events.
/// </summary>
public static View MouseGrabView => mouseGrabView;

/// <summary>
/// Event to be invoked when a view grab the mouse.
/// </summary>
public static event Action<View> GrabbedMouse;

/// <summary>
/// Event to be invoked when a view ungrab the mouse.
/// </summary>
public static event Action<View> UnGrabbedMouse;

/// <summary>
/// Grabs the mouse, forcing all mouse events to be routed to the specified view until UngrabMouse is called.
Expand All @@ -592,6 +607,7 @@ public static void GrabMouse (View view)
{
if (view == null)
return;
OnGrabbedMouse (view);
mouseGrabView = view;
Driver.UncookMouse ();
}
Expand All @@ -601,10 +617,27 @@ public static void GrabMouse (View view)
/// </summary>
public static void UngrabMouse ()
{
if (mouseGrabView == null)
return;
OnUnGrabbedMouse (mouseGrabView);
mouseGrabView = null;
Driver.CookMouse ();
}

static void OnGrabbedMouse (View view)
{
if (view == null)
return;
GrabbedMouse?.Invoke (view);
}

static void OnUnGrabbedMouse (View view)
{
if (view == null)
return;
UnGrabbedMouse?.Invoke (view);
}

/// <summary>
/// Merely a debugging aid to see the raw mouse events
/// </summary>
Expand Down Expand Up @@ -656,7 +689,7 @@ static void ProcessMouseEvent (MouseEvent me)
lastMouseOwnerView?.OnMouseLeave (me);
}
// System.Diagnostics.Debug.WriteLine ($"{nme.Flags};{nme.X};{nme.Y};{mouseGrabView}");
if (mouseGrabView != null && mouseGrabView.OnMouseEvent (nme)) {
if (mouseGrabView?.OnMouseEvent (nme) == true) {
return;
}
}
Expand Down
12 changes: 6 additions & 6 deletions Terminal.Gui/Views/Menu.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1816,7 +1816,7 @@ public override bool MouseEvent (MouseEvent me)

internal bool HandleGrabView (MouseEvent me, View current)
{
if (Application.mouseGrabView != null) {
if (Application.MouseGrabView != null) {
if (me.View is MenuBar || me.View is Menu) {
var mbar = GetMouseGrabViewInstance (me.View);
if (mbar != null) {
Expand Down Expand Up @@ -1890,7 +1890,7 @@ internal bool HandleGrabView (MouseEvent me, View current)
//if (!(me.View is MenuBar) && !(me.View is Menu) && me.Flags != MouseFlags.Button1Pressed))
// return false;

//if (Application.mouseGrabView != null) {
//if (Application.MouseGrabView != null) {
// if (me.View is MenuBar || me.View is Menu) {
// me.X -= me.OfX;
// me.Y -= me.OfY;
Expand All @@ -1905,8 +1905,8 @@ internal bool HandleGrabView (MouseEvent me, View current)
// return true;
//}

//if (Application.mouseGrabView != null) {
// if (Application.mouseGrabView == me.View && me.View == current) {
//if (Application.MouseGrabView != null) {
// if (Application.MouseGrabView == me.View && me.View == current) {
// me.X -= me.OfX;
// me.Y -= me.OfY;
// } else if (me.View != current && me.View is MenuBar && me.View is Menu) {
Expand All @@ -1927,7 +1927,7 @@ internal bool HandleGrabView (MouseEvent me, View current)

MenuBar GetMouseGrabViewInstance (View view)
{
if (view == null || Application.mouseGrabView == null) {
if (view == null || Application.MouseGrabView == null) {
return null;
}

Expand All @@ -1938,7 +1938,7 @@ MenuBar GetMouseGrabViewInstance (View view)
hostView = ((Menu)view).host;
}

var grabView = Application.mouseGrabView;
var grabView = Application.MouseGrabView;
MenuBar hostGrabView = null;
if (grabView is MenuBar) {
hostGrabView = (MenuBar)grabView;
Expand Down
6 changes: 3 additions & 3 deletions Terminal.Gui/Views/ScrollBarView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ void ShowHideScrollBars (bool redraw = true)
} else if (otherScrollBarView != null && otherScrollBarView.contentBottomRightCorner != null) {
otherScrollBarView.contentBottomRightCorner.Visible = false;
}
if (Application.mouseGrabView != null && Application.mouseGrabView == this) {
if (Application.MouseGrabView != null && Application.MouseGrabView == this) {
Application.UngrabMouse ();
}
} else if (contentBottomRightCorner != null) {
Expand Down Expand Up @@ -638,9 +638,9 @@ public override bool MouseEvent (MouseEvent me)
var pos = Position;

if (me.Flags != MouseFlags.Button1Released
&& (Application.mouseGrabView == null || Application.mouseGrabView != this)) {
&& (Application.MouseGrabView == null || Application.MouseGrabView != this)) {
Application.GrabMouse (this);
} else if (me.Flags == MouseFlags.Button1Released && Application.mouseGrabView != null && Application.mouseGrabView == this) {
} else if (me.Flags == MouseFlags.Button1Released && Application.MouseGrabView != null && Application.MouseGrabView == this) {
lastLocation = -1;
Application.UngrabMouse ();
return true;
Expand Down
2 changes: 1 addition & 1 deletion Terminal.Gui/Views/ScrollView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ public override void Add (View view)

void View_MouseLeave (MouseEventArgs e)
{
if (Application.mouseGrabView != null && Application.mouseGrabView != vertical && Application.mouseGrabView != horizontal) {
if (Application.MouseGrabView != null && Application.MouseGrabView != vertical && Application.MouseGrabView != horizontal) {
Application.UngrabMouse ();
}
}
Expand Down
6 changes: 3 additions & 3 deletions Terminal.Gui/Views/TextField.cs
Original file line number Diff line number Diff line change
Expand Up @@ -249,9 +249,9 @@ void TextField_Initialized (object sender, EventArgs e)
///<inheritdoc/>
public override bool OnLeave (View view)
{
if (Application.mouseGrabView != null && Application.mouseGrabView == this)
if (Application.MouseGrabView != null && Application.MouseGrabView == this)
Application.UngrabMouse ();
//if (SelectedLength != 0 && !(Application.mouseGrabView is MenuBar))
//if (SelectedLength != 0 && !(Application.MouseGrabView is MenuBar))
// ClearAllSelection ();

return base.OnLeave (view);
Expand Down Expand Up @@ -1049,7 +1049,7 @@ public override bool MouseEvent (MouseEvent ev)
int x = PositionCursor (ev);
isButtonReleased = false;
PrepareSelection (x);
if (Application.mouseGrabView == null) {
if (Application.MouseGrabView == null) {
Application.GrabMouse (this);
}
} else if (ev.Flags == MouseFlags.Button1Released) {
Expand Down
4 changes: 2 additions & 2 deletions Terminal.Gui/Views/TextView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4328,7 +4328,7 @@ public override bool MouseEvent (MouseEvent ev)
}
lastWasKill = false;
columnTrack = currentColumn;
if (Application.mouseGrabView == null) {
if (Application.MouseGrabView == null) {
Application.GrabMouse (this);
}
} else if (ev.Flags.HasFlag (MouseFlags.Button1Released)) {
Expand Down Expand Up @@ -4407,7 +4407,7 @@ void ProcessMouseClick (MouseEvent ev, out List<Rune> line)
///<inheritdoc/>
public override bool OnLeave (View view)
{
if (Application.mouseGrabView != null && Application.mouseGrabView == this) {
if (Application.MouseGrabView != null && Application.MouseGrabView == this) {
Application.UngrabMouse ();
}

Expand Down
81 changes: 72 additions & 9 deletions UnitTests/ApplicationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1144,7 +1144,7 @@ public void Internal_Tests ()
Assert.NotNull (Application.Top);
var rs = Application.Begin (Application.Top);
Assert.Equal (Application.Top, rs.Toplevel);
Assert.Null (Application.mouseGrabView);
Assert.Null (Application.MouseGrabView);
Assert.Null (Application.WantContinuousButtonPressedView);
Assert.False (Application.DebugDrawBounds);
Assert.False (Application.ShowChild (Application.Top));
Expand Down Expand Up @@ -1428,7 +1428,7 @@ public void MouseGrabView_WithNullMouseEventView ()
iterations++;
if (iterations == 0) {
Assert.True (tf.HasFocus);
Assert.Null (Application.mouseGrabView);
Assert.Null (Application.MouseGrabView);

ReflectionTools.InvokePrivate (
typeof (Application),
Expand All @@ -1439,13 +1439,13 @@ public void MouseGrabView_WithNullMouseEventView ()
Flags = MouseFlags.ReportMousePosition
});

Assert.Equal (sv, Application.mouseGrabView);
Assert.Equal (sv, Application.MouseGrabView);

MessageBox.Query ("Title", "Test", "Ok");

Assert.Null (Application.mouseGrabView);
Assert.Null (Application.MouseGrabView);
} else if (iterations == 1) {
Assert.Equal (sv, Application.mouseGrabView);
Assert.Equal (sv, Application.MouseGrabView);

ReflectionTools.InvokePrivate (
typeof (Application),
Expand All @@ -1456,7 +1456,7 @@ public void MouseGrabView_WithNullMouseEventView ()
Flags = MouseFlags.ReportMousePosition
});

Assert.Null (Application.mouseGrabView);
Assert.Null (Application.MouseGrabView);

ReflectionTools.InvokePrivate (
typeof (Application),
Expand All @@ -1467,7 +1467,7 @@ public void MouseGrabView_WithNullMouseEventView ()
Flags = MouseFlags.ReportMousePosition
});

Assert.Null (Application.mouseGrabView);
Assert.Null (Application.MouseGrabView);

ReflectionTools.InvokePrivate (
typeof (Application),
Expand All @@ -1478,17 +1478,80 @@ public void MouseGrabView_WithNullMouseEventView ()
Flags = MouseFlags.Button1Pressed
});

Assert.Null (Application.mouseGrabView);
Assert.Null (Application.MouseGrabView);

Application.RequestStop ();
} else if (iterations == 2) {
Assert.Null (Application.mouseGrabView);
Assert.Null (Application.MouseGrabView);

Application.RequestStop ();
}
};

Application.Run ();
}

[Fact, AutoInitShutdown]
public void MouseGrabView_GrabbedMouse_UnGrabbedMouse ()
{
View grabView = null;
var count = 0;

var view1 = new View ();
var view2 = new View ();

Application.GrabbedMouse += Application_GrabbedMouse;
Application.UnGrabbedMouse += Application_UnGrabbedMouse;

Application.GrabMouse (view1);
Assert.Equal (0, count);
Assert.Equal (grabView, view1);
Assert.Equal (view1, Application.MouseGrabView);

Application.UngrabMouse ();
Assert.Equal (1, count);
Assert.Equal (grabView, view1);
Assert.Null (Application.MouseGrabView);

Application.GrabbedMouse += Application_GrabbedMouse;
Application.UnGrabbedMouse += Application_UnGrabbedMouse;

Application.GrabMouse (view2);
Assert.Equal (1, count);
Assert.Equal (grabView, view2);
Assert.Equal (view2, Application.MouseGrabView);

Application.UngrabMouse ();
Assert.Equal (2, count);
Assert.Equal (grabView, view2);
Assert.Null (Application.MouseGrabView);

void Application_GrabbedMouse (View obj)
{
if (count == 0) {
Assert.Equal (view1, obj);
grabView = view1;
} else {
Assert.Equal (view2, obj);
grabView = view2;
}

Application.GrabbedMouse -= Application_GrabbedMouse;
}

void Application_UnGrabbedMouse (View obj)
{
if (count == 0) {
Assert.Equal (view1, obj);
Assert.Equal (grabView, obj);
} else {
Assert.Equal (view2, obj);
Assert.Equal (grabView, obj);
}
count++;

Application.UnGrabbedMouse -= Application_UnGrabbedMouse;
}
}
}
}
16 changes: 8 additions & 8 deletions UnitTests/ContextMenuTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -519,38 +519,38 @@ public void ContextMenu_Is_Closed_If_Another_MenuBar_Is_Open_Or_Vice_Versa ()

Application.Top.Add (menu);

Assert.Null (Application.mouseGrabView);
Assert.Null (Application.MouseGrabView);

cm.Show ();
Assert.True (ContextMenu.IsShow);
Assert.Equal (cm.MenuBar, Application.mouseGrabView);
Assert.Equal (cm.MenuBar, Application.MouseGrabView);
Assert.False (menu.IsMenuOpen);
Assert.True (menu.ProcessHotKey (new KeyEvent (Key.F9, new KeyModifiers ())));
Assert.False (ContextMenu.IsShow);
Assert.Equal (menu, Application.mouseGrabView);
Assert.Equal (menu, Application.MouseGrabView);
Assert.True (menu.IsMenuOpen);

cm.Show ();
Assert.True (ContextMenu.IsShow);
Assert.Equal (cm.MenuBar, Application.mouseGrabView);
Assert.Equal (cm.MenuBar, Application.MouseGrabView);
Assert.False (menu.IsMenuOpen);
Assert.False (menu.OnKeyDown (new KeyEvent (Key.Null, new KeyModifiers () { Alt = true })));
Assert.True (menu.OnKeyUp (new KeyEvent (Key.Null, new KeyModifiers () { Alt = true })));
Assert.False (ContextMenu.IsShow);
Assert.Equal (menu, Application.mouseGrabView);
Assert.Equal (menu, Application.MouseGrabView);
Assert.True (menu.IsMenuOpen);

cm.Show ();
Assert.True (ContextMenu.IsShow);
Assert.Equal (cm.MenuBar, Application.mouseGrabView);
Assert.Equal (cm.MenuBar, Application.MouseGrabView);
Assert.False (menu.IsMenuOpen);
Assert.False (menu.MouseEvent (new MouseEvent () { X = 1, Flags = MouseFlags.ReportMousePosition, View = menu }));
Assert.True (ContextMenu.IsShow);
Assert.Equal (cm.MenuBar, Application.mouseGrabView);
Assert.Equal (cm.MenuBar, Application.MouseGrabView);
Assert.False (menu.IsMenuOpen);
Assert.True (menu.MouseEvent (new MouseEvent () { X = 1, Flags = MouseFlags.Button1Clicked, View = menu }));
Assert.False (ContextMenu.IsShow);
Assert.Equal (menu, Application.mouseGrabView);
Assert.Equal (menu, Application.MouseGrabView);
Assert.True (menu.IsMenuOpen);
}

Expand Down
4 changes: 2 additions & 2 deletions UnitTests/ScrollBarViewTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -947,7 +947,7 @@ This is a test
Flags = MouseFlags.Button1Clicked
});

Assert.Null (Application.mouseGrabView);
Assert.Null (Application.MouseGrabView);
Assert.True (clicked);

clicked = false;
Expand All @@ -974,7 +974,7 @@ This is a test
Flags = MouseFlags.Button1Clicked
});

Assert.Null (Application.mouseGrabView);
Assert.Null (Application.MouseGrabView);
Assert.True (clicked);
Assert.Equal (5, sbv.Size);
Assert.False (sbv.ShowScrollIndicator);
Expand Down