From e37ae64356e0a1134603a73365ee5bf5592879d0 Mon Sep 17 00:00:00 2001 From: Charlie Kindel Date: Tue, 14 Apr 2020 20:33:02 -0600 Subject: [PATCH] key down/up support --- Terminal.Gui/Core.cs | 76 +++++++++++++++++++++++++-- Terminal.Gui/Drivers/ConsoleDriver.cs | 2 +- Terminal.Gui/Drivers/CursesDriver.cs | 3 +- Terminal.Gui/Drivers/NetDriver.cs | 5 +- Terminal.Gui/Drivers/WindowsDriver.cs | 23 +++++++- 5 files changed, 99 insertions(+), 10 deletions(-) diff --git a/Terminal.Gui/Core.cs b/Terminal.Gui/Core.cs index d0477ef86..e4d2aedaf 100644 --- a/Terminal.Gui/Core.cs +++ b/Terminal.Gui/Core.cs @@ -119,8 +119,29 @@ namespace Terminal.Gui { public virtual bool ProcessColdKey (KeyEvent keyEvent) { return false; - } - + } + + /// + /// Method invoked when a key is pressed. + /// + /// Contains the details about the key that produced the event. + /// true if the event was handled + public virtual bool KeyDown (KeyEvent keyEvent) + { + return false; + } + + /// + /// Method invoked when a key is released. + /// + /// Contains the details about the key that produced the event. + /// true if the event was handled + public virtual bool KeyUp (KeyEvent keyEvent) + { + return false; + } + + /// /// Method invoked when a mouse event is generated /// @@ -1009,8 +1030,31 @@ namespace Terminal.Gui { if (view.ProcessColdKey (keyEvent)) return true; return false; - } + } + + /// Contains the details about the key that produced the event. + public override bool KeyDown (KeyEvent keyEvent) + { + if (subviews == null || subviews.Count == 0) + return false; + foreach (var view in subviews) + if (view.KeyDown (keyEvent)) + return true; + return false; + } + + /// Contains the details about the key that produced the event. + public override bool KeyUp (KeyEvent keyEvent) + { + if (subviews == null || subviews.Count == 0) + return false; + foreach (var view in subviews) + if (view.KeyUp (keyEvent)) + return true; + + return false; + } /// /// Finds the first view in the hierarchy that wants to get the focus if nothing is currently focused, otherwise, it does nothing. /// @@ -1943,6 +1987,7 @@ namespace Terminal.Gui { static void ProcessKeyEvent (KeyEvent ke) { + var chain = toplevels.ToList(); foreach (var topLevel in chain) { if (topLevel.ProcessHotKey (ke)) @@ -1965,6 +2010,29 @@ namespace Terminal.Gui { if (topLevel.Modal) break; } + } + + static void ProcessKeyDownEvent (KeyEvent ke) + { + var chain = toplevels.ToList (); + foreach (var topLevel in chain) { + if (topLevel.KeyDown (ke)) + return; + if (topLevel.Modal) + break; + } + } + + + static void ProcessKeyUpEvent (KeyEvent ke) + { + var chain = toplevels.ToList (); + foreach (var topLevel in chain) { + if (topLevel.KeyUp (ke)) + return; + if (topLevel.Modal) + break; + } } static View FindDeepestView (View start, int x, int y, out int resx, out int resy) @@ -2092,7 +2160,7 @@ namespace Terminal.Gui { } toplevels.Push (toplevel); Current = toplevel; - Driver.PrepareToRun (MainLoop, ProcessKeyEvent, ProcessMouseEvent); + Driver.PrepareToRun (MainLoop, ProcessKeyEvent, ProcessKeyDownEvent, ProcessKeyUpEvent, ProcessMouseEvent); if (toplevel.LayoutStyle == LayoutStyle.Computed) toplevel.RelativeLayout (new Rect (0, 0, Driver.Cols, Driver.Rows)); toplevel.LayoutSubviews (); diff --git a/Terminal.Gui/Drivers/ConsoleDriver.cs b/Terminal.Gui/Drivers/ConsoleDriver.cs index 19cdc4e48..9e9511e85 100644 --- a/Terminal.Gui/Drivers/ConsoleDriver.cs +++ b/Terminal.Gui/Drivers/ConsoleDriver.cs @@ -469,7 +469,7 @@ namespace Terminal.Gui { /// /// /// - public abstract void PrepareToRun (MainLoop mainLoop, Action keyHandler, Action mouseHandler); + public abstract void PrepareToRun (MainLoop mainLoop, Action keyHandler, Action keyDownHandler, Action keyUpHandler, Action mouseHandler); /// /// Updates the screen to reflect all the changes that have been done to the display buffer diff --git a/Terminal.Gui/Drivers/CursesDriver.cs b/Terminal.Gui/Drivers/CursesDriver.cs index 2508051db..c51b37b6f 100644 --- a/Terminal.Gui/Drivers/CursesDriver.cs +++ b/Terminal.Gui/Drivers/CursesDriver.cs @@ -203,8 +203,9 @@ namespace Terminal.Gui { keyHandler (new KeyEvent ((Key)wch)); } - public override void PrepareToRun (MainLoop mainLoop, Action keyHandler, Action mouseHandler) + public override void PrepareToRun (MainLoop mainLoop, Action keyHandler, Action keyDownHandler, Action keyUpHandler, Action mouseHandler) { + // Note: Curses doesn't support keydown/up events and thus any passed keyDown/UpHandlers will never be called Curses.timeout (-1); (mainLoop.Driver as Mono.Terminal.UnixMainLoop).AddWatch (0, Mono.Terminal.UnixMainLoop.Condition.PollIn, x => { diff --git a/Terminal.Gui/Drivers/NetDriver.cs b/Terminal.Gui/Drivers/NetDriver.cs index 0b5217910..8483182c4 100644 --- a/Terminal.Gui/Drivers/NetDriver.cs +++ b/Terminal.Gui/Drivers/NetDriver.cs @@ -320,8 +320,9 @@ namespace Terminal.Gui { return (Key)(0xffffffff); } - public override void PrepareToRun (MainLoop mainLoop, Action keyHandler, Action mouseHandler) - { + public override void PrepareToRun (MainLoop mainLoop, Action keyHandler, Action keyDownHandler, Action keyUpHandler, Action mouseHandler) + { + // Note: Net doesn't support keydown/up events and thus any passed keyDown/UpHandlers will never be called (mainLoop.Driver as NetMainLoop).WindowsKeyPressed = delegate (ConsoleKeyInfo consoleKey) { var map = MapKey (consoleKey); if (map == (Key)0xffffffff) diff --git a/Terminal.Gui/Drivers/WindowsDriver.cs b/Terminal.Gui/Drivers/WindowsDriver.cs index f48eb6418..f7d21c612 100644 --- a/Terminal.Gui/Drivers/WindowsDriver.cs +++ b/Terminal.Gui/Drivers/WindowsDriver.cs @@ -26,6 +26,7 @@ // SOFTWARE. // using System; +using System.CodeDom; using System.Diagnostics; using System.Runtime.InteropServices; using System.Threading; @@ -537,11 +538,15 @@ namespace Terminal.Gui { } Action keyHandler; + Action keyDownHandler; + Action keyUpHandler; Action mouseHandler; - public override void PrepareToRun (MainLoop mainLoop, Action keyHandler, Action mouseHandler) + public override void PrepareToRun (MainLoop mainLoop, Action keyHandler, Action keyDownHandler, Action keyUpHandler, Action mouseHandler) { this.keyHandler = keyHandler; + this.keyDownHandler = keyDownHandler; + this.keyUpHandler = keyUpHandler; this.mouseHandler = mouseHandler; } @@ -554,10 +559,14 @@ namespace Terminal.Gui { var inputEvent = result [0]; switch (inputEvent.EventType) { case WindowsConsole.EventType.Key: + // See how this relies on key up? if (inputEvent.KeyEvent.bKeyDown == false) return; var map = MapKey (ToConsoleKeyInfoEx (inputEvent.KeyEvent)); - if (inputEvent.KeyEvent.UnicodeChar == 0 && map == (Key)0xffffffff) + if (inputEvent.KeyEvent.UnicodeChar == 0) + keyDownHandler (new KeyEvent (map)); + + if (map == (Key)0xffffffff) return; keyHandler (new KeyEvent (map)); break; @@ -837,6 +846,16 @@ namespace Terminal.Gui { return (Key)((int)Key.F1 + delta); } + + //if (keyInfo.KeyChar == 0) { + // if (keyInfo.Modifiers == ConsoleModifiers.Control) + // return (Key)(uint)Key.CharMask; + // if (keyInfo.Modifiers == ConsoleModifiers.Alt) + // return (Key)(uint)Key.AltMask; + // if ((keyInfo.Modifiers & (ConsoleModifiers.Alt | ConsoleModifiers.Control)) != 0) { + // return (Key)(uint)(Key.AltMask | Key.CharMask); + // } + //} return (Key)(0xffffffff); }