Skip to content

Commit

Permalink
Merge pull request #3383 from tig/v2_3344-Fullscreen-Moveable
Browse files Browse the repository at this point in the history
  • Loading branch information
tig authored Apr 3, 2024
2 parents 43e4a83 + f68adf7 commit 9937771
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 99 deletions.
94 changes: 0 additions & 94 deletions Terminal.Gui/View/Adornment/Adornment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ public Adornment ()
/// <param name="parent"></param>
public Adornment (View parent)
{
Application.GrabbingMouse += Application_GrabbingMouse;
Application.UnGrabbingMouse += Application_UnGrabbingMouse;
CanFocus = true;
Parent = parent;
}
Expand Down Expand Up @@ -209,9 +207,6 @@ public override bool Contains (int x, int y)
return Thickness.Contains (frame, x, y);
}

private Point? _dragPosition;
private Point _startGrabPoint;

/// <inheritdoc/>
protected internal override bool OnMouseEnter (MouseEvent mouseEvent)
{
Expand Down Expand Up @@ -257,70 +252,6 @@ protected internal override bool OnMouseEvent (MouseEvent mouseEvent)
return OnMouseClick (args);
}

if (!Parent.CanFocus || !Parent.Arrangement.HasFlag (ViewArrangement.Movable))
{
return true;
}

// BUGBUG: See https://github.com/gui-cs/Terminal.Gui/issues/3312
if (!_dragPosition.HasValue && mouseEvent.Flags.HasFlag (MouseFlags.Button1Pressed))
{
Parent.SetFocus ();
Application.BringOverlappedTopToFront ();

// Only start grabbing if the user clicks in the Thickness area
// Adornment.Contains takes Parent SuperView=relative coords.
if (Contains (mouseEvent.X + Parent.Frame.X + Frame.X, mouseEvent.Y+ Parent.Frame.Y + Frame.Y))
{
// Set the start grab point to the Frame coords
_startGrabPoint = new (mouseEvent.X + Frame.X, mouseEvent.Y + Frame.Y);
_dragPosition = new (mouseEvent.X, mouseEvent.Y);
Application.GrabMouse (this);
}

return true;
}

if (mouseEvent.Flags is (MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition))
{
if (Application.MouseGrabView == this && _dragPosition.HasValue)
{
if (Parent.SuperView is null)
{
// Redraw the entire app window.
Application.Top.SetNeedsDisplay ();
}
else
{
Parent.SuperView.SetNeedsDisplay ();
}

_dragPosition = new Point (mouseEvent.X, mouseEvent.Y);

Point parentLoc = Parent.SuperView?.ScreenToBounds (mouseEvent.ScreenPosition.X, mouseEvent.ScreenPosition.Y) ?? mouseEvent.ScreenPosition;

GetLocationEnsuringFullVisibility (
Parent,
parentLoc.X - _startGrabPoint.X,
parentLoc.Y - _startGrabPoint.Y,
out int nx,
out int ny,
out _
);

Parent.X = nx;
Parent.Y = ny;

return true;
}
}

if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Released) && _dragPosition.HasValue)
{
_dragPosition = null;
Application.UngrabMouse ();
}

return false;
}

Expand All @@ -340,30 +271,5 @@ protected internal override bool OnMouseLeave (MouseEvent mouseEvent)
return base.OnMouseLeave (mouseEvent);
}

/// <inheritdoc/>
protected override void Dispose (bool disposing)
{
Application.GrabbingMouse -= Application_GrabbingMouse;
Application.UnGrabbingMouse -= Application_UnGrabbingMouse;

_dragPosition = null;
base.Dispose (disposing);
}

private void Application_GrabbingMouse (object sender, GrabMouseEventArgs e)
{
if (Application.MouseGrabView == this && _dragPosition.HasValue)
{
e.Cancel = true;
}
}

private void Application_UnGrabbingMouse (object sender, GrabMouseEventArgs e)
{
if (Application.MouseGrabView == this && _dragPosition.HasValue)
{
e.Cancel = true;
}
}
#endregion Mouse Support
}
118 changes: 118 additions & 0 deletions Terminal.Gui/View/Adornment/Border.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ public Border (View parent) : base (parent)
{
/* Do nothing; View.CreateAdornment requires a constructor that takes a parent */
Parent = parent;
Application.GrabbingMouse += Application_GrabbingMouse;
Application.UnGrabbingMouse += Application_UnGrabbingMouse;
}

#if SUBVIEW_BASED_BORDER
Expand Down Expand Up @@ -183,6 +185,122 @@ public LineStyle LineStyle
set => _lineStyle = value;
}

#region Mouse Support

private Point? _dragPosition;
private Point _startGrabPoint;

/// <inheritdoc />
protected internal override bool OnMouseEvent (MouseEvent mouseEvent)
{
if (base.OnMouseEvent (mouseEvent))
{
return true;
}

if (!Parent.CanFocus)
{
return false;
}

if (!Parent.Arrangement.HasFlag (ViewArrangement.Movable))
{
return false;
}

// BUGBUG: See https://github.com/gui-cs/Terminal.Gui/issues/3312
if (!_dragPosition.HasValue && mouseEvent.Flags.HasFlag (MouseFlags.Button1Pressed))
{
Parent.SetFocus ();
Application.BringOverlappedTopToFront ();

// Only start grabbing if the user clicks in the Thickness area
// Adornment.Contains takes Parent SuperView=relative coords.
if (Contains (mouseEvent.X + Parent.Frame.X + Frame.X, mouseEvent.Y + Parent.Frame.Y + Frame.Y))
{
// Set the start grab point to the Frame coords
_startGrabPoint = new (mouseEvent.X + Frame.X, mouseEvent.Y + Frame.Y);
_dragPosition = new (mouseEvent.X, mouseEvent.Y);
Application.GrabMouse (this);
}

return true;
}

if (mouseEvent.Flags is (MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition))
{
if (Application.MouseGrabView == this && _dragPosition.HasValue)
{
if (Parent.SuperView is null)
{
// Redraw the entire app window.
Application.Top.SetNeedsDisplay ();
}
else
{
Parent.SuperView.SetNeedsDisplay ();
}

_dragPosition = new Point (mouseEvent.X, mouseEvent.Y);

Point parentLoc = Parent.SuperView?.ScreenToBounds (mouseEvent.ScreenPosition.X, mouseEvent.ScreenPosition.Y) ?? mouseEvent.ScreenPosition;

GetLocationEnsuringFullVisibility (
Parent,
parentLoc.X - _startGrabPoint.X,
parentLoc.Y - _startGrabPoint.Y,
out int nx,
out int ny,
out _
);

Parent.X = nx;
Parent.Y = ny;

return true;
}
}

if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Released) && _dragPosition.HasValue)
{
_dragPosition = null;
Application.UngrabMouse ();

return true;
}

return false;
}


/// <inheritdoc/>
protected override void Dispose (bool disposing)
{
Application.GrabbingMouse -= Application_GrabbingMouse;
Application.UnGrabbingMouse -= Application_UnGrabbingMouse;

_dragPosition = null;
base.Dispose (disposing);
}

private void Application_GrabbingMouse (object sender, GrabMouseEventArgs e)
{
if (Application.MouseGrabView == this && _dragPosition.HasValue)
{
e.Cancel = true;
}
}

private void Application_UnGrabbingMouse (object sender, GrabMouseEventArgs e)
{
if (Application.MouseGrabView == this && _dragPosition.HasValue)
{
e.Cancel = true;
}
}

#endregion Mouse Support

/// <inheritdoc/>
public override void OnDrawContent (Rectangle contentArea)
{
Expand Down
2 changes: 1 addition & 1 deletion Terminal.Gui/View/Layout/ViewLayout.cs
Original file line number Diff line number Diff line change
Expand Up @@ -975,7 +975,7 @@ internal void OnResizeNeeded ()
// First try SuperView.Bounds, then Application.Top, then Driver.Bounds.
// Finally, if none of those are valid, use int.MaxValue (for Unit tests).
Rectangle relativeBounds = SuperView is { IsInitialized: true } ? SuperView.Bounds :
Application.Top is { } && Application.Top.IsInitialized ? Application.Top.Bounds :
Application.Top is { } && Application.Top != this && Application.Top.IsInitialized ? Application.Top.Bounds :
Application.Driver?.Bounds ?? new Rectangle (0, 0, int.MaxValue, int.MaxValue);
SetRelativeLayout (relativeBounds);

Expand Down
8 changes: 4 additions & 4 deletions UnitTests/View/MouseTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,22 +38,22 @@ public void MouseClick_SetsFocus_If_CanFocus (bool canFocus, bool setFocus, bool
[Theory]
[InlineData (0, 0, 0, 0, false)]
[InlineData (0, 0, 0, 4, false)]
[InlineData (1, 0, 0, 4, true)]
[InlineData (1, 0, 0, 4, false)]
[InlineData (0, 1, 0, 4, true)]
[InlineData (0, 0, 1, 4, false)]

[InlineData (1, 1, 0, 3, false)]
[InlineData (1, 1, 0, 4, true)]
[InlineData (1, 1, 0, 4, false)]
[InlineData (1, 1, 0, 5, true)]
[InlineData (1, 1, 0, 6, false)]


[InlineData (1, 1, 0, 11, false)]
[InlineData (1, 1, 0, 12, true)]
[InlineData (1, 1, 0, 13, true)]
[InlineData (1, 1, 0, 13, false)]
[InlineData (1, 1, 0, 14, false)]
[AutoInitShutdown]
public void ButtonPressed_In_Margin_Or_Border_Starts_Drag (int marginThickness, int borderThickness, int paddingThickness, int xy, bool expectedMoved)
public void ButtonPressed_In_Border_Starts_Drag (int marginThickness, int borderThickness, int paddingThickness, int xy, bool expectedMoved)
{
var testView = new View
{
Expand Down

0 comments on commit 9937771

Please sign in to comment.