From e7c11835629c497a1ca0ae13084c2910cb1d09a5 Mon Sep 17 00:00:00 2001 From: BDisp Date: Thu, 4 Apr 2024 14:32:00 +0100 Subject: [PATCH 1/3] Fixes #3380. WindowsDriver is sending mouse button pressed only on moving. --- Terminal.Gui/ConsoleDrivers/WindowsDriver.cs | 28 +++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs index 9742d2591..e1c18d791 100644 --- a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs @@ -1281,7 +1281,7 @@ internal class WindowsDriver : ConsoleDriver { #if HACK_CHECK_WINCHANGED - //_mainLoop.WinChanged -= ChangeWin; + _mainLoopDriver.WinChanged -= ChangeWin; #endif } @@ -1698,7 +1698,7 @@ internal class WindowsDriver : ConsoleDriver private async Task ProcessButtonDoubleClickedAsync () { - await Task.Delay (300); + await Task.Delay (200); _isButtonDoubleClicked = false; _isOneFingerDoubleClicked = false; @@ -2130,9 +2130,15 @@ internal class WindowsMainLoop : IMainLoopDriver void IMainLoopDriver.TearDown () { + _inputHandlerTokenSource?.Cancel (); + _inputHandlerTokenSource?.Dispose (); + _waitForProbe?.Dispose (); + // Eat any outstanding events. See # + // I don't recommend this because if there is no input + // this could being hang until some event occur //var records = - _winConsole.ReadConsoleInput (); + //_winConsole.ReadConsoleInput (); //if (records != null) //{ @@ -2143,21 +2149,16 @@ internal class WindowsMainLoop : IMainLoopDriver // } //} - _inputHandlerTokenSource?.Cancel (); - _inputHandlerTokenSource?.Dispose (); + _resultQueue?.Clear (); _eventReadyTokenSource?.Cancel (); _eventReadyTokenSource?.Dispose (); _eventReady?.Dispose (); - _resultQueue?.Clear (); - #if HACK_CHECK_WINCHANGED _winChange?.Dispose (); #endif - //_waitForProbe?.Dispose (); - _mainLoop = null; } @@ -2174,11 +2175,18 @@ internal class WindowsMainLoop : IMainLoopDriver } catch (OperationCanceledException) { + // Wakes the _waitForProbe if it's waiting + _waitForProbe.Set (); return; } finally { - _waitForProbe.Reset (); + // If IsCancellationRequested is true the code after + // the `finally` block will not be executed. + if (!_inputHandlerTokenSource.IsCancellationRequested) + { + _waitForProbe.Reset (); + } } if (_resultQueue?.Count == 0) From 4af0fd1c7e403f99646c39141b4328531c6169dc Mon Sep 17 00:00:00 2001 From: BDisp Date: Thu, 4 Apr 2024 21:43:12 +0100 Subject: [PATCH 2/3] Remove bad code that hangs unit tests on Windows. --- Terminal.Gui/ConsoleDrivers/WindowsDriver.cs | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs index e1c18d791..0ee91b19c 100644 --- a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs @@ -2134,21 +2134,6 @@ internal class WindowsMainLoop : IMainLoopDriver _inputHandlerTokenSource?.Dispose (); _waitForProbe?.Dispose (); - // Eat any outstanding events. See # - // I don't recommend this because if there is no input - // this could being hang until some event occur - //var records = - //_winConsole.ReadConsoleInput (); - - //if (records != null) - //{ - // foreach (var rec in records) - // { - // Debug.WriteLine ($"Teardown: {rec.ToString ()}"); - // //Debug.Assert (rec is not { EventType: WindowsConsole.EventType.Mouse, MouseEvent.ButtonState: WindowsConsole.ButtonState.Button1Pressed }); - // } - //} - _resultQueue?.Clear (); _eventReadyTokenSource?.Cancel (); From b59c5ea9e63b0d6fda7d163ecf514d49f639e740 Mon Sep 17 00:00:00 2001 From: BDisp Date: Fri, 5 Apr 2024 14:42:19 +0100 Subject: [PATCH 3/3] Using GetNumberOfConsoleInputEvents and FlushConsoleInputBuffer to clear input events. --- Terminal.Gui/ConsoleDrivers/WindowsDriver.cs | 35 ++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs index 0ee91b19c..e0f854dcf 100644 --- a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs @@ -838,6 +838,29 @@ internal class WindowsConsole [DllImport ("kernel32.dll", SetLastError = true)] private static extern bool GetNumberOfConsoleInputEvents (nint handle, out uint lpcNumberOfEvents); + internal uint GetNumberOfConsoleInputEvents () + { + if (!GetNumberOfConsoleInputEvents (_inputHandle, out uint numOfEvents)) + { + Console.WriteLine ($"Error: {Marshal.GetLastWin32Error ()}"); + + return 0; + } + + return numOfEvents; + } + + [DllImport ("kernel32.dll", SetLastError = true)] + private static extern bool FlushConsoleInputBuffer (nint handle); + + internal void FlushConsoleInputBuffer () + { + if (!FlushConsoleInputBuffer (_inputHandle)) + { + Console.WriteLine ($"Error: {Marshal.GetLastWin32Error ()}"); + } + } + public InputRecord [] ReadConsoleInput () { const int bufferSize = 1; @@ -2132,6 +2155,18 @@ internal class WindowsMainLoop : IMainLoopDriver { _inputHandlerTokenSource?.Cancel (); _inputHandlerTokenSource?.Dispose (); + + if (_winConsole is { }) + { + var numOfEvents = _winConsole.GetNumberOfConsoleInputEvents (); + + if (numOfEvents > 0) + { + _winConsole.FlushConsoleInputBuffer (); + //Debug.WriteLine ($"Flushed {numOfEvents} events."); + } + } + _waitForProbe?.Dispose (); _resultQueue?.Clear ();