From 92e067e0146559a592cc9ad43f013a9325e473e6 Mon Sep 17 00:00:00 2001 From: BDisp Date: Wed, 21 Aug 2024 22:15:17 +0100 Subject: [PATCH] Prevents continuous mouse button pressed from processing mouse event without slider completed the layout. --- Terminal.Gui/Views/Scroll/Scroll.cs | 27 ++++++++++++++++++----- Terminal.Gui/Views/Scroll/ScrollSlider.cs | 16 +++++++++++++- 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/Terminal.Gui/Views/Scroll/Scroll.cs b/Terminal.Gui/Views/Scroll/Scroll.cs index 9053fb4e1..19de2de1c 100644 --- a/Terminal.Gui/Views/Scroll/Scroll.cs +++ b/Terminal.Gui/Views/Scroll/Scroll.cs @@ -22,12 +22,12 @@ public class Scroll : View Height = Dim.Auto (DimAutoStyle.Content, 1); } + + internal bool _wasSliderLayoutComplete = true; + private readonly ScrollSlider _slider; - private Orientation _orientation; - private int _position; - private int _size; /// @@ -118,6 +118,12 @@ public class Scroll : View /// protected internal override bool OnMouseEvent (MouseEvent mouseEvent) { + if (!_wasSliderLayoutComplete) + { + // Do not process if slider layout wasn't yet completed + return base.OnMouseEvent (mouseEvent); + } + int location = Orientation == Orientation.Vertical ? mouseEvent.Position.Y : mouseEvent.Position.X; int barSize = Orientation == Orientation.Vertical ? GetContentSize ().Height : GetContentSize ().Width; @@ -125,11 +131,11 @@ public class Scroll : View ? new (_slider.Frame.Y, _slider.Frame.Bottom - 1) : new (_slider.Frame.X, _slider.Frame.Right - 1); - if (mouseEvent.Flags == MouseFlags.Button1Pressed && location < sliderPos.topLeft) + if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Pressed) && location < sliderPos.topLeft) { Position = Math.Max (Position - barSize, 0); } - else if (mouseEvent.Flags == MouseFlags.Button1Pressed && location > sliderPos.bottomRight) + else if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Pressed) && location > sliderPos.bottomRight) { Position = Math.Min (Position + barSize, Size - barSize); } @@ -150,10 +156,21 @@ public class Scroll : View return _slider.OnMouseEvent (mouseEvent); } } + // Flag as false until slider layout is completed + _wasSliderLayoutComplete = false; return base.OnMouseEvent (mouseEvent); } + /// + protected internal override bool OnMouseLeave (MouseEvent mouseEvent) + { + // If scroll isn't handling mouse then reset the flag + _wasSliderLayoutComplete = true; + + return base.OnMouseLeave (mouseEvent); + } + // TODO: Move this into "ScrollSlider" and override it there. Scroll can then subscribe to _slider.LayoutComplete and call AdjustSlider. // QUESTION: I've been meaning to add a "View.FrameChanged" event (fired from LayoutComplete only if Frame has changed). Should we do that as part of this PR? // QUESTION: Note I *did* add "View.ViewportChanged" in a previous PR. diff --git a/Terminal.Gui/Views/Scroll/ScrollSlider.cs b/Terminal.Gui/Views/Scroll/ScrollSlider.cs index aa4a641d4..075fa3c9e 100644 --- a/Terminal.Gui/Views/Scroll/ScrollSlider.cs +++ b/Terminal.Gui/Views/Scroll/ScrollSlider.cs @@ -73,11 +73,17 @@ internal class ScrollSlider : View /// protected internal override bool OnMouseEvent (MouseEvent mouseEvent) { + if (!_host._wasSliderLayoutComplete) + { + // Ensure not blocking scroll mouse event + _host._wasSliderLayoutComplete = true; + } + int location = _host.Orientation == Orientation.Vertical ? mouseEvent.Position.Y : mouseEvent.Position.X; int offset = _lastLocation > -1 ? location - _lastLocation : 0; int barSize = _host.Orientation == Orientation.Vertical ? _host.GetContentSize ().Height : _host.GetContentSize ().Width; - if (mouseEvent.Flags == MouseFlags.Button1Pressed) + if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Pressed) && _lastLocation == -1) { if (Application.MouseGrabView != this) { @@ -143,6 +149,14 @@ internal class ScrollSlider : View return base.OnMouseLeave (mouseEvent); } + /// + internal override void OnLayoutComplete (LayoutEventArgs args) + { + base.OnLayoutComplete (args); + + _host._wasSliderLayoutComplete = true; + } + private int GetPositionFromSliderLocation (int location) { if (_host.GetContentSize ().Height == 0 || _host.GetContentSize ().Width == 0)