Skip to content

Fixes #3312. Mouse API makes it way too hard to track button pressed. #3393

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 19 commits into
base: v2_develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 10 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
53 changes: 47 additions & 6 deletions Terminal.Gui/Application.cs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,9 @@ internal static void ResetState ()

// Mouse
_mouseEnteredView = null;
_lastViewButtonPressed = null;
_canProcessClickedEvent = true;
_isMouseDown = false;
WantContinuousButtonPressedView = null;
MouseEvent = null;
GrabbedMouse = null;
Expand Down Expand Up @@ -1550,6 +1553,9 @@ private static void OnUnGrabbedMouse (View view)

// Used by OnMouseEvent to track the last view that was clicked on.
internal static View? _mouseEnteredView;
internal static View? _lastViewButtonPressed;
internal static bool _canProcessClickedEvent = true;
internal static bool? _isMouseDown;

/// <summary>Event fired when a mouse move or click occurs. Coordinates are screen relative.</summary>
/// <remarks>
Expand Down Expand Up @@ -1578,6 +1584,38 @@ internal static void OnMouseEvent (MouseEvent mouseEvent)
mouseEvent.View = view;
}

if (_lastViewButtonPressed is null && mouseEvent.Flags is MouseFlags.Button1Pressed or MouseFlags.Button2Pressed or MouseFlags.Button3Pressed or MouseFlags.Button4Pressed)
{
_lastViewButtonPressed = view;
_isMouseDown = true;
}
else if (_lastViewButtonPressed is { } && mouseEvent.Flags is MouseFlags.Button1Released or MouseFlags.Button2Released or MouseFlags.Button3Released or MouseFlags.Button4Released)
{
if (_lastViewButtonPressed != view)
{
_canProcessClickedEvent = false;
}

_lastViewButtonPressed = null;
_isMouseDown = false;
}
else if (!_canProcessClickedEvent && mouseEvent.Flags is MouseFlags.Button1Clicked or MouseFlags.Button2Clicked or MouseFlags.Button3Clicked or MouseFlags.Button4Clicked)
{
_canProcessClickedEvent = true;
_isMouseDown = null;

return;
}
else if (!mouseEvent.Flags.HasFlag(MouseFlags.ReportMousePosition))
{
_lastViewButtonPressed = null;
_isMouseDown = null;
}
else
{
_isMouseDown = null;
}

MouseEvent?.Invoke (null, mouseEvent);

if (mouseEvent.Handled)
Expand All @@ -1597,7 +1635,8 @@ internal static void OnMouseEvent (MouseEvent mouseEvent)
Y = frameLoc.Y,
Flags = mouseEvent.Flags,
ScreenPosition = new (mouseEvent.X, mouseEvent.Y),
View = MouseGrabView
View = view ?? MouseGrabView,
IsMouseDown = _isMouseDown
};

if ((MouseGrabView.Viewport with { Location = Point.Empty }).Contains (viewRelativeMouseEvent.X, viewRelativeMouseEvent.Y) is false)
Expand All @@ -1606,8 +1645,8 @@ internal static void OnMouseEvent (MouseEvent mouseEvent)
_mouseEnteredView?.NewMouseLeaveEvent (mouseEvent);
}

//System.Diagnostics.Debug.WriteLine ($"{nme.Flags};{nme.X};{nme.Y};{mouseGrabView}");
if (MouseGrabView?.NewMouseEvent (viewRelativeMouseEvent) == true)
if ((MouseGrabView?.WantMousePositionReports == true || MouseGrabView?.WantContinuousButtonPressed == true)
&& MouseGrabView?.NewMouseEvent (viewRelativeMouseEvent) == true)
{
return;
}
Expand All @@ -1622,7 +1661,6 @@ internal static void OnMouseEvent (MouseEvent mouseEvent)
WantContinuousButtonPressedView = null;
}


if (view is not Adornment)
{
if ((view is null || view == OverlappedTop)
Expand Down Expand Up @@ -1660,7 +1698,8 @@ internal static void OnMouseEvent (MouseEvent mouseEvent)
Y = frameLoc.Y,
Flags = mouseEvent.Flags,
ScreenPosition = new (mouseEvent.X, mouseEvent.Y),
View = view
View = view,
IsMouseDown = _isMouseDown
};
}
else if (view.ViewportToScreen (Rectangle.Empty with { Size = view.Viewport.Size }).Contains (mouseEvent.X, mouseEvent.Y))
Expand All @@ -1673,7 +1712,8 @@ internal static void OnMouseEvent (MouseEvent mouseEvent)
Y = viewportLocation.Y,
Flags = mouseEvent.Flags,
ScreenPosition = new (mouseEvent.X, mouseEvent.Y),
View = view
View = view,
IsMouseDown = _isMouseDown
};
}

Expand Down Expand Up @@ -1738,6 +1778,7 @@ internal static void OnMouseEvent (MouseEvent mouseEvent)

BringOverlappedTopToFront ();
}

#nullable restore

#endregion Mouse handling
Expand Down
5 changes: 5 additions & 0 deletions Terminal.Gui/Input/Mouse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,11 @@ public class MouseEvent
/// </remarks>
public Point ScreenPosition { get; set; }

/// <summary>
/// Indicates if the current mouse event has first pressed <see langword="true"/>, latest released <see langword="false"/> or none <see langword="null"/>.
/// </summary>
public bool? IsMouseDown { get; set; }

/// <summary>Returns a <see cref="T:System.String"/> that represents the current <see cref="MouseEvent"/>.</summary>
/// <returns>A <see cref="T:System.String"/> that represents the current <see cref="MouseEvent"/>.</returns>
public override string ToString () { return $"({X},{Y}):{Flags}"; }
Expand Down
1 change: 1 addition & 0 deletions Terminal.Gui/View/Adornment/Border.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ public Border (View parent) : base (parent)

HighlightStyle |= HighlightStyle.Pressed;
Highlight += Border_Highlight;
WantMousePositionReports = true;
}

#if SUBVIEW_BASED_BORDER
Expand Down
Loading