From 1cca002393da3b3fbb87c6b53f6dfb051c61f755 Mon Sep 17 00:00:00 2001 From: Tig Date: Tue, 2 Apr 2024 08:45:28 -0600 Subject: [PATCH] Got new button fn working on WindowsDriver; Now debugging netdriver and curses --- Terminal.Gui/Application.cs | 24 +++---- .../CursesDriver/CursesDriver.cs | 6 ++ Terminal.Gui/ConsoleDrivers/NetDriver.cs | 4 +- Terminal.Gui/ConsoleDrivers/WindowsDriver.cs | 29 ++++++-- Terminal.Gui/Views/Button.cs | 70 +++++++++++-------- UICatalog/Scenarios/Buttons.cs | 15 +++- 6 files changed, 95 insertions(+), 53 deletions(-) diff --git a/Terminal.Gui/Application.cs b/Terminal.Gui/Application.cs index 660104f33..d5bac89d9 100644 --- a/Terminal.Gui/Application.cs +++ b/Terminal.Gui/Application.cs @@ -1456,15 +1456,6 @@ public static partial class Application // TODO: In PR #3273, FindDeepestView will return adornments. Update logic below to fix adornment mouse handling var view = View.FindDeepestView (Current, a.MouseEvent.X, a.MouseEvent.Y); - if (view is { WantContinuousButtonPressed: true }) - { - WantContinuousButtonPressedView = view; - } - else - { - WantContinuousButtonPressedView = null; - } - if (view is { }) { a.MouseEvent.View = view; @@ -1494,10 +1485,7 @@ public static partial class Application if (MouseGrabView.Bounds.Contains (viewRelativeMouseEvent.X, viewRelativeMouseEvent.Y) is false) { - // The mouse has moved outside the bounds of the view that - // grabbed the mouse, so we tell the view that last got - // OnMouseEnter the mouse is leaving - // BUGBUG: That sentence makes no sense. Either I'm missing something or this logic is flawed. + // The mouse has moved outside the bounds of the view that grabbed the mouse _mouseEnteredView?.OnMouseLeave (a.MouseEvent); } @@ -1508,6 +1496,16 @@ public static partial class Application } } + if (view is { WantContinuousButtonPressed: true }) + { + WantContinuousButtonPressedView = view; + } + else + { + WantContinuousButtonPressedView = null; + } + + if (view is not Adornment) { if ((view is null || view == OverlappedTop) diff --git a/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs b/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs index 7dcdd78a5..08457cc83 100644 --- a/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs @@ -2,6 +2,7 @@ // Driver.cs: Curses-based Driver // +using System.Diagnostics; using System.Runtime.InteropServices; using Terminal.Gui.ConsoleDrivers; using Unix.Terminal; @@ -798,6 +799,9 @@ internal class CursesDriver : ConsoleDriver || flag.HasFlag (MouseFlags.Button4DoubleClicked); } + Debug.WriteLine ($"CursesDriver: ({pos.X},{pos.Y}) - {mouseFlag}"); + + if ((WasButtonReleased (mouseFlag) && IsButtonNotPressed (_lastMouseFlags)) || (IsButtonClickedOrDoubleClicked (mouseFlag) && _lastMouseFlags == 0)) { return; @@ -806,6 +810,8 @@ internal class CursesDriver : ConsoleDriver _lastMouseFlags = mouseFlag; var me = new MouseEvent { Flags = mouseFlag, X = pos.X, Y = pos.Y }; + Debug.WriteLine ($"CursesDriver: ({me.X},{me.Y}) - {me.Flags}"); + OnMouseEvent (new MouseEventEventArgs (me)); } diff --git a/Terminal.Gui/ConsoleDrivers/NetDriver.cs b/Terminal.Gui/ConsoleDrivers/NetDriver.cs index 19e3667b6..cb22d288c 100644 --- a/Terminal.Gui/ConsoleDrivers/NetDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/NetDriver.cs @@ -1137,7 +1137,7 @@ internal class NetDriver : ConsoleDriver break; case EventType.Mouse: MouseEvent me = ToDriverMouse (inputEvent.MouseEvent); - //Debug.WriteLine ($"NetDriver: ({me.X},{me.Y}) - {me.Flags}"); + Debug.WriteLine ($"NetDriver: ({me.X},{me.Y}) - {me.Flags}"); OnMouseEvent (new MouseEventEventArgs (me)); break; @@ -1379,7 +1379,7 @@ internal class NetDriver : ConsoleDriver private MouseEvent ToDriverMouse (NetEvents.MouseEvent me) { - // System.Diagnostics.Debug.WriteLine ($"X: {me.Position.X}; Y: {me.Position.Y}; ButtonState: {me.ButtonState}"); + //System.Diagnostics.Debug.WriteLine ($"X: {me.Position.X}; Y: {me.Position.Y}; ButtonState: {me.ButtonState}"); MouseFlags mouseFlag = 0; diff --git a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs index 60989c586..24adb1ca3 100644 --- a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs @@ -1695,7 +1695,13 @@ internal class WindowsDriver : ConsoleDriver private async Task ProcessButtonDoubleClickedAsync () { - await Task.Delay (300); + // Only delay if there's not a view wanting continuous button presses + if (Application.WantContinuousButtonPressedView is null) + { + // QUESTION: Why 300ms? + await Task.Delay (300); + } + _isButtonDoubleClicked = false; _isOneFingerDoubleClicked = false; @@ -1704,10 +1710,16 @@ internal class WindowsDriver : ConsoleDriver private async Task ProcessContinuousButtonPressedAsync (MouseFlags mouseFlag) { + // When a user presses-and-holds, start generating pressed events every `startDelay` + // After `iterationsUntilFast` iterations, speed them up to `fastDelay` ms + const int startDelay = 500; + const int iterationsUntilFast = 4; + const int fastDelay = 50; + + int iterations = 0; + int delay = startDelay; while (_isButtonPressed) { - await Task.Delay (100); - var me = new MouseEvent { X = _pointMove.X, @@ -1715,13 +1727,18 @@ internal class WindowsDriver : ConsoleDriver Flags = mouseFlag }; - View view = Application.WantContinuousButtonPressedView; - - if (view is null) + if (Application.WantContinuousButtonPressedView is null) { break; } + if (iterations++ >= iterationsUntilFast) + { + delay = fastDelay; + } + await Task.Delay (delay); + + //Debug.WriteLine($"ProcessContinuousButtonPressedAsync: {view}"); if (_isButtonPressed && (mouseFlag & MouseFlags.ReportMousePosition) == 0) { Application.Invoke (() => OnMouseEvent (new MouseEventEventArgs (me))); diff --git a/Terminal.Gui/Views/Button.cs b/Terminal.Gui/Views/Button.cs index 5ceef8b9c..7cd32f1a0 100644 --- a/Terminal.Gui/Views/Button.cs +++ b/Terminal.Gui/Views/Button.cs @@ -67,52 +67,62 @@ public class Button : View private void Button_MouseEvent (object sender, MouseEventEventArgs e) { - if (e.MouseEvent.Flags.HasFlag(MouseFlags.Button1Clicked)) + // Default behavior is to invoke Accept (via HotKey) on clicked. + if (!WantContinuousButtonPressed && + Application.MouseGrabView != this && + e.MouseEvent.Flags.HasFlag (MouseFlags.Button1Clicked)) { + e.Handled = InvokeCommand (Command.HotKey) == true; + return; + } + + if (e.MouseEvent.Flags.HasFlag (MouseFlags.Button1Pressed)) + { + // If WantContinuousButtonPressed is true, and this is not the first pressed event, + // invoke Accept (via HotKey) + if (WantContinuousButtonPressed && Application.MouseGrabView == this) + { + e.Handled = InvokeCommand (Command.HotKey) == true; + return; + } + + // The first time we get pressed event, grab the mouse and invert the colors if (Application.MouseGrabView != this) { - e.Handled = InvokeCommand (Command.HotKey) == true; + Application.GrabMouse (this); + _savedColorScheme = ColorScheme; + var cs = new ColorScheme (new Attribute (ColorScheme.Normal.Background, ColorScheme.Normal.Foreground)); + ColorScheme = cs; - return; + // Set the focus, but don't invoke Accept + SetFocus (); } } - if (e.MouseEvent.Flags == MouseFlags.Button1Pressed) + if (e.MouseEvent.Flags.HasFlag (MouseFlags.Button1Released)) { + // When the mouse is released, if WantContinuousButtonPressed is set, invoke Accept one last time. + if (WantContinuousButtonPressed) + { + e.Handled = InvokeCommand (Command.HotKey) == true; + } + if (Application.MouseGrabView == this) { - e.Handled = InvokeCommand (Command.HotKey) == true; - return; + Application.UngrabMouse (); + if (_savedColorScheme is { }) + { + ColorScheme = _savedColorScheme; + _savedColorScheme = null; + } } - - SetFocus(); - Application.GrabMouse(this); - - _savedColorScheme = ColorScheme; - var cs = new ColorScheme (new Attribute (ColorScheme.Normal.Background, ColorScheme.Normal.Foreground)); - ColorScheme = cs; - } - - if (e.MouseEvent.Flags.HasFlag(MouseFlags.Button1Released)) - { - Application.UngrabMouse (); - - e.Handled = InvokeCommand (Command.HotKey) == true; - - if (_savedColorScheme is { }) - { - ColorScheme = _savedColorScheme; - } - - _savedColorScheme = null; } } /// - public override bool OnLeave (View view) + protected internal override bool OnMouseLeave (MouseEvent e) { - //Application.UngrabMouse(); - return base.OnLeave (view); + return base.OnMouseLeave (e); } private void Button_MouseClick (object sender, MouseEventEventArgs e) diff --git a/UICatalog/Scenarios/Buttons.cs b/UICatalog/Scenarios/Buttons.cs index e3c9b5ea2..8dd155385 100644 --- a/UICatalog/Scenarios/Buttons.cs +++ b/UICatalog/Scenarios/Buttons.cs @@ -396,7 +396,7 @@ public class Buttons : Scenario { X = Pos.Right (label) + 1, Y = Pos.Top (label), - Title = $"Accept Count (press-and-hold): {acceptCount}", + Title = $"Accept Count: {acceptCount}", WantContinuousButtonPressed = true, }; repeatButton.Accept += (s, e) => @@ -404,7 +404,18 @@ public class Buttons : Scenario repeatButton.Title = $"Accept Count: {++acceptCount}"; }; - main.Add(label, repeatButton); + var enableCB = new CheckBox () + { + X = Pos.Right (repeatButton) + 1, + Y = Pos.Top (repeatButton), + Title = "Enabled", + Checked = true, + }; + enableCB.Toggled += (s, e) => + { + repeatButton.Enabled = !repeatButton.Enabled; + }; + main.Add(label, repeatButton, enableCB); main.Ready += (s, e) => radioGroup.Refresh (); Application.Run (main);