Merge pull request #2070 from BDisp/view-keydown-keyup-fix

Fixes #2069. Enable KeyDown and KeyUp events to be canceled (like KeyPress)
This commit is contained in:
Tig Kindel
2022-09-29 11:17:50 -07:00
committed by GitHub
3 changed files with 160 additions and 11 deletions

View File

@@ -370,12 +370,14 @@ namespace Terminal.Gui {
return keyMod != Key.Null ? keyMod | key : key;
}
Action<KeyEvent> keyDownHandler;
Action<KeyEvent> keyHandler;
Action<KeyEvent> keyUpHandler;
private CursorVisibility savedCursorVisibility;
public override void PrepareToRun (MainLoop mainLoop, Action<KeyEvent> keyHandler, Action<KeyEvent> keyDownHandler, Action<KeyEvent> keyUpHandler, Action<MouseEvent> mouseHandler)
{
this.keyDownHandler = keyDownHandler;
this.keyHandler = keyHandler;
this.keyUpHandler = keyUpHandler;
@@ -386,20 +388,25 @@ namespace Terminal.Gui {
void ProcessInput (ConsoleKeyInfo consoleKey)
{
keyModifiers = new KeyModifiers ();
var map = MapKey (consoleKey);
if (map == (Key)0xffffffff)
return;
if (consoleKey.Modifiers.HasFlag (ConsoleModifiers.Alt)) {
keyModifiers.Alt = true;
}
if (consoleKey.Modifiers.HasFlag (ConsoleModifiers.Shift)) {
keyModifiers.Shift = true;
}
if (consoleKey.Modifiers.HasFlag (ConsoleModifiers.Alt)) {
keyModifiers.Alt = true;
}
if (consoleKey.Modifiers.HasFlag (ConsoleModifiers.Control)) {
keyModifiers.Ctrl = true;
}
var map = MapKey (consoleKey);
if (map == (Key)0xffffffff) {
if ((consoleKey.Modifiers & (ConsoleModifiers.Shift | ConsoleModifiers.Alt | ConsoleModifiers.Control)) != 0) {
keyDownHandler (new KeyEvent (map, keyModifiers));
keyUpHandler (new KeyEvent (map, keyModifiers));
}
return;
}
keyDownHandler (new KeyEvent (map, keyModifiers));
keyHandler (new KeyEvent (map, keyModifiers));
keyUpHandler (new KeyEvent (map, keyModifiers));
}

View File

@@ -1932,8 +1932,14 @@ namespace Terminal.Gui {
if (args.Handled) {
return true;
}
if (Focused?.Enabled == true && Focused?.OnKeyDown (keyEvent) == true) {
return true;
if (Focused?.Enabled == true) {
Focused.KeyDown?.Invoke (args);
if (args.Handled) {
return true;
}
if (Focused?.OnKeyDown (keyEvent) == true) {
return true;
}
}
return false;
@@ -1956,8 +1962,14 @@ namespace Terminal.Gui {
if (args.Handled) {
return true;
}
if (Focused?.Enabled == true && Focused?.OnKeyUp (keyEvent) == true) {
return true;
if (Focused?.Enabled == true) {
Focused.KeyUp?.Invoke (args);
if (args.Handled) {
return true;
}
if (Focused?.OnKeyUp (keyEvent) == true) {
return true;
}
}
return false;

View File

@@ -3910,5 +3910,135 @@ This is a tes
Assert.True (viewCalled);
Assert.True (tvCalled);
}
[Fact, AutoInitShutdown]
public void KeyDown_And_KeyUp_Events_Must_Called_Before_OnKeyDown_And_OnKeyUp ()
{
var keyDown = false;
var keyPress = false;
var keyUp = false;
var view = new DerivedView ();
view.KeyDown += (e) => {
Assert.Equal (Key.a, e.KeyEvent.Key);
Assert.False (keyDown);
Assert.False (view.IsKeyDown);
e.Handled = true;
keyDown = true;
};
view.KeyPress += (e) => {
Assert.Equal (Key.a, e.KeyEvent.Key);
Assert.False (keyPress);
Assert.False (view.IsKeyPress);
e.Handled = true;
keyPress = true;
};
view.KeyUp += (e) => {
Assert.Equal (Key.a, e.KeyEvent.Key);
Assert.False (keyUp);
Assert.False (view.IsKeyUp);
e.Handled = true;
keyUp = true;
};
Application.Top.Add (view);
Console.MockKeyPresses.Push (new ConsoleKeyInfo ('a', ConsoleKey.A, false, false, false));
Application.Iteration += () => Application.RequestStop ();
Assert.True (view.CanFocus);
Application.Run ();
Application.Shutdown ();
Assert.True (keyDown);
Assert.True (keyPress);
Assert.True (keyUp);
Assert.False (view.IsKeyDown);
Assert.False (view.IsKeyPress);
Assert.False (view.IsKeyUp);
}
public class DerivedView : View {
public DerivedView ()
{
CanFocus = true;
}
public bool IsKeyDown { get; set; }
public bool IsKeyPress { get; set; }
public bool IsKeyUp { get; set; }
public override bool OnKeyDown (KeyEvent keyEvent)
{
IsKeyDown = true;
return true;
}
public override bool ProcessKey (KeyEvent keyEvent)
{
IsKeyPress = true;
return true;
}
public override bool OnKeyUp (KeyEvent keyEvent)
{
IsKeyUp = true;
return true;
}
}
[Theory, AutoInitShutdown]
[InlineData (true, false, false)]
[InlineData (true, true, false)]
[InlineData (true, true, true)]
public void KeyDown_And_KeyUp_Events_With_Only_Key_Modifiers (bool shift, bool alt, bool control)
{
var keyDown = false;
var keyPress = false;
var keyUp = false;
var view = new DerivedView ();
view.KeyDown += (e) => {
Assert.Equal (-1, e.KeyEvent.KeyValue);
Assert.Equal (shift, e.KeyEvent.IsShift);
Assert.Equal (alt, e.KeyEvent.IsAlt);
Assert.Equal (control, e.KeyEvent.IsCtrl);
Assert.False (keyDown);
Assert.False (view.IsKeyDown);
keyDown = true;
};
view.KeyPress += (e) => {
keyPress = true;
};
view.KeyUp += (e) => {
Assert.Equal (-1, e.KeyEvent.KeyValue);
Assert.Equal (shift, e.KeyEvent.IsShift);
Assert.Equal (alt, e.KeyEvent.IsAlt);
Assert.Equal (control, e.KeyEvent.IsCtrl);
Assert.False (keyUp);
Assert.False (view.IsKeyUp);
keyUp = true;
};
Application.Top.Add (view);
Console.MockKeyPresses.Push (new ConsoleKeyInfo ('\0', (ConsoleKey)'\0', shift, alt, control));
Application.Iteration += () => Application.RequestStop ();
Assert.True (view.CanFocus);
Application.Run ();
Application.Shutdown ();
Assert.True (keyDown);
Assert.False (keyPress);
Assert.True (keyUp);
Assert.True (view.IsKeyDown);
Assert.False (view.IsKeyPress);
Assert.True (view.IsKeyUp);
}
}
}