mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2026-01-02 01:03:29 +01:00
Change WindowsDriver to send down/up on key down and ignore key up events from win 32 api
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 [];
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user