Change WindowsDriver to send down/up on key down and ignore key up events from win 32 api

This commit is contained in:
tznind
2024-10-13 10:42:34 +01:00
parent 204d640f0b
commit 67b28925cc
3 changed files with 14 additions and 109 deletions

View File

@@ -246,7 +246,7 @@ namespace Terminal.Gui;
public IEnumerable<Tuple<char, T>> Release ()
{
foreach (var h in held)
foreach (var h in held.ToArray ())
{
yield return h;
}

View File

@@ -1458,7 +1458,7 @@ internal class WindowsDriver : ConsoleDriver
/// How long after Esc has been pressed before we give up on getting an Ansi escape sequence
/// </summary>
private TimeSpan _escTimeout = TimeSpan.FromMilliseconds (50);
public AnsiResponseParser<WindowsConsole.InputRecord []> Parser { get; set; } = new ();
public AnsiResponseParser<WindowsConsole.InputRecord> Parser { get; set; } = new ();
internal void ProcessInput (WindowsConsole.InputRecord inputEvent)
{
@@ -1493,15 +1493,9 @@ internal class WindowsDriver : ConsoleDriver
break;
}
if (inputEvent.KeyEvent.bKeyDown)
{
// Avoid sending repeat key down events
OnKeyDown (new Key (map));
}
else
{
OnKeyUp (new Key (map));
}
// This follows convention in NetDriver
OnKeyDown (new Key (map));
OnKeyUp (new Key (map));
break;
@@ -1543,7 +1537,6 @@ internal class WindowsDriver : ConsoleDriver
}
}
private WindowsDriverKeyPairer pairer = new WindowsDriverKeyPairer ();
private IEnumerable<WindowsConsole.InputRecord> Parse (WindowsConsole.InputRecord inputEvent)
{
if (inputEvent.EventType != WindowsConsole.EventType.Key)
@@ -1552,36 +1545,22 @@ internal class WindowsDriver : ConsoleDriver
yield break;
}
var pair = pairer.ProcessInput (inputEvent).ToArray ();
// Swallow key up events - they are unreliable
if (!inputEvent.KeyEvent.bKeyDown)
{
yield break;
}
foreach (var i in ShouldRelease ())
{
yield return i;
}
foreach (var p in pair)
foreach (Tuple<char, WindowsConsole.InputRecord> output in
Parser.ProcessInput (Tuple.Create (inputEvent.KeyEvent.UnicodeChar, inputEvent)))
{
// may be down/up
if (p.Length == 2)
{
var c = p [0].KeyEvent.UnicodeChar;
foreach (Tuple<char, WindowsConsole.InputRecord []> output in
Parser.ProcessInput (Tuple.Create(c,p)))
{
foreach (var r in output.Item2)
{
yield return r;
}
}
}
else
{
// environment doesn't support down/up
// TODO: what we do in this situation?
}
yield return output.Item2;
}
}
public IEnumerable<WindowsConsole.InputRecord> ShouldRelease ()
@@ -1590,7 +1569,7 @@ internal class WindowsDriver : ConsoleDriver
if (Parser.State == ParserState.ExpectingBracket &&
DateTime.Now - Parser.StateChangedAt > _escTimeout)
{
return Parser.Release ().SelectMany (o => o.Item2);
return Parser.Release ().Select (o => o.Item2);
}
return [];

View File

@@ -1,74 +0,0 @@
using static Terminal.Gui.WindowsConsole;
namespace Terminal.Gui.ConsoleDrivers;
class WindowsDriverKeyPairer
{
private InputRecord? _heldDownEvent = null; // To hold the "down" event
// Process a single input record at a time
public IEnumerable<InputRecord []> ProcessInput (InputRecord record)
{
// If it's a "down" event, store it as a held event
if (IsKeyDown (record))
{
return HandleKeyDown (record);
}
// If it's an "up" event, try to match it with the held "down" event
else if (IsKeyUp (record))
{
return HandleKeyUp (record);
}
else
{
// If it's not a key event, just pass it through
return new [] { new [] { record } };
}
}
private IEnumerable<InputRecord []> HandleKeyDown (InputRecord record)
{
// If we already have a held "down" event, release it (unmatched)
if (_heldDownEvent != null)
{
// Release the previous "down" event since there's a new "down"
var previousDown = _heldDownEvent.Value;
_heldDownEvent = record; // Hold the new "down" event
return new [] { new [] { previousDown } };
}
// Hold the new "down" event
_heldDownEvent = record;
return Enumerable.Empty<InputRecord []> ();
}
private IEnumerable<InputRecord []> HandleKeyUp (InputRecord record)
{
// If we have a held "down" event that matches this "up" event, release both
if (_heldDownEvent != null && IsMatchingKey (record, _heldDownEvent.Value))
{
var downEvent = _heldDownEvent.Value;
_heldDownEvent = null; // Clear the held event
return new [] { new [] { downEvent, record } };
}
else
{
// No match, release the "up" event by itself
return new [] { new [] { record } };
}
}
private bool IsKeyDown (InputRecord record)
{
return record.KeyEvent.bKeyDown;
}
private bool IsKeyUp (InputRecord record)
{
return !record.KeyEvent.bKeyDown;
}
private bool IsMatchingKey (InputRecord upEvent, InputRecord downEvent)
{
return upEvent.KeyEvent.UnicodeChar == downEvent.KeyEvent.UnicodeChar;
}
}