From 98d56b3562ebf0aca513785a89fa379bc05b42df Mon Sep 17 00:00:00 2001 From: miguel Date: Mon, 9 Apr 2018 22:50:40 -0400 Subject: [PATCH] Improve current behavior on Windows, and prepare for building a real Windows driver --- Terminal.Gui/Core.cs | 2 +- Terminal.Gui/Driver.cs | 202 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 199 insertions(+), 5 deletions(-) diff --git a/Terminal.Gui/Core.cs b/Terminal.Gui/Core.cs index 71a1408a8..0789277bb 100644 --- a/Terminal.Gui/Core.cs +++ b/Terminal.Gui/Core.cs @@ -1616,4 +1616,4 @@ namespace Terminal.Gui { } } } -} \ No newline at end of file +} diff --git a/Terminal.Gui/Driver.cs b/Terminal.Gui/Driver.cs index 674173a97..4302e55c6 100644 --- a/Terminal.Gui/Driver.cs +++ b/Terminal.Gui/Driver.cs @@ -825,8 +825,9 @@ namespace Terminal.Gui { } internal class NetDriver : ConsoleDriver { - public override int Cols => Console.WindowWidth; - public override int Rows => Console.WindowHeight; + int cols, rows; + public override int Cols => cols; + public override int Rows => rows; // The format is rows, columns and 3 values on the last column: Rune, Attribute and Dirty Flag int [,,] contents; @@ -854,6 +855,8 @@ namespace Terminal.Gui { public NetDriver () { + cols = Console.WindowWidth; + rows = Console.WindowHeight - 1; UpdateOffscreen (); } @@ -881,8 +884,8 @@ namespace Terminal.Gui { { if (Clip.Contains (ccol, crow)) { if (needMove) { - Console.CursorLeft = ccol; - Console.CursorTop = crow; + //Console.CursorLeft = ccol; + //Console.CursorTop = crow; needMove = false; } contents [crow, ccol, 0] = (int)(uint)rune; @@ -965,6 +968,7 @@ namespace Terminal.Gui { Colors.Error.Focus = MakeColor (ConsoleColor.Black, ConsoleColor.Gray); Colors.Error.HotNormal = MakeColor (ConsoleColor.Yellow, ConsoleColor.Red); Colors.Error.HotFocus = Colors.Error.HotNormal; + Console.Clear (); } int redrawColor = -1; @@ -1129,5 +1133,195 @@ namespace Terminal.Gui { public override void UncookMouse () { } + + // + // These are for the .NET driver, but running natively on Windows, wont run + // on the Mono emulation + // + + + } + + internal class WindowsConsole { + public const int STD_OUTPUT_HANDLE = -11; + public const int STD_INPUT_HANDLE = -10; + public const int STD_ERROR_HANDLE = -12; + + [DllImport ("kernel32.dll", SetLastError = true)] + static extern IntPtr GetStdHandle (int nStdHandle); + + IntPtr inputHandle, outputHandle; + + public WindowsConsole () + { + inputHandle = GetStdHandle (STD_INPUT_HANDLE); + outputHandle = GetStdHandle (STD_OUTPUT_HANDLE); + } + + [StructLayout (LayoutKind.Explicit, CharSet = CharSet.Unicode)] + public struct KeyEventRecord { + [FieldOffset (0), MarshalAs (UnmanagedType.Bool)] + public bool bKeyDown; + [FieldOffset (4), MarshalAs (UnmanagedType.U2)] + public ushort wRepeatCount; + [FieldOffset (6), MarshalAs (UnmanagedType.U2)] + public ushort wVirtualKeyCode; + [FieldOffset (8), MarshalAs (UnmanagedType.U2)] + public ushort wVirtualScanCode; + [FieldOffset (10)] + public char UnicodeChar; + [FieldOffset (12), MarshalAs (UnmanagedType.U4)] + public ControlKeyState dwControlKeyState; + } + + [Flags] + public enum ButtonState { + Button1Pressed = 1, + Button2Pressed = 4, + Button3Pressed = 8, + Button4Pressed = 16, + RightmostButtonPressed = 2, + + } + + [Flags] + public enum ControlKeyState { + RightAltPressed = 1, + LeftAltPressed = 2, + RightControlPressed = 4, + LeftControlPressed = 8, + ShiftPressed = 16, + NumlockOn = 32, + ScrolllockOn = 64, + CapslockOn = 128, + EnhancedKey = 256 + } + + [Flags] + public enum EventFlags { + MouseMoved = 1, + DoubleClick = 2, + MouseWheeled = 4, + MouseHorizontalWheeled = 8 + } + + [StructLayout (LayoutKind.Explicit)] + public struct MouseEventRecord { + [FieldOffset (0)] + public Coordinate MousePosition; + [FieldOffset (4)] + public ButtonState ButtonState; + [FieldOffset (8)] + public ControlKeyState ControlKeyState; + [FieldOffset (12)] + public EventFlags EventFlags; + + public override string ToString () + { + return $"[Mouse({MousePosition},{ButtonState},{ControlKeyState},{EventFlags}"; + } + } + + [StructLayout (LayoutKind.Sequential)] + public struct Coordinate { + public short X; + public short Y; + + public Coordinate (short X, short Y) + { + this.X = X; + this.Y = Y; + } + + public override string ToString () => $"({X},{Y})"; + }; + + internal struct WindowBufferSizeRecord { + public Coordinate size; + + public WindowBufferSizeRecord (short x, short y) + { + this.size = new Coordinate (x, y); + } + + public override string ToString () => $"[WindowBufferSize{size}"; + } + + [StructLayout (LayoutKind.Sequential)] + public struct MenuEventRecord { + public uint dwCommandId; + } + + [StructLayout (LayoutKind.Sequential)] + public struct FocusEventRecord { + public uint bSetFocus; + } + + public enum EventType { + Focus = 0x10, + Key = 0x1, + Menu = 0x8, + Mouse = 2, + WindowBufferSize = 4 + } + + [StructLayout (LayoutKind.Explicit)] + public struct InputRecord { + [FieldOffset (0)] + public EventType EventType; + [FieldOffset (4)] + public KeyEventRecord KeyEvent; + [FieldOffset (4)] + public MouseEventRecord MouseEvent; + [FieldOffset (4)] + public WindowBufferSizeRecord WindowBufferSizeEvent; + [FieldOffset (4)] + public MenuEventRecord MenuEvent; + [FieldOffset (4)] + public FocusEventRecord FocusEvent; + + public override string ToString () + { + switch (EventType) { + case EventType.Focus: + return FocusEvent.ToString (); + case EventType.Key: + return KeyEvent.ToString (); + case EventType.Menu: + return MenuEvent.ToString (); + case EventType.Mouse: + return MouseEvent.ToString (); + case EventType.WindowBufferSize: + return WindowBufferSizeEvent.ToString (); + default: + return "Unknown event type: " + EventType; + } + } + }; + + [DllImport ("kernel32.dll", EntryPoint = "ReadConsoleInputW", CharSet = CharSet.Unicode)] + public static extern bool ReadConsoleInput ( + IntPtr hConsoleInput, + [Out] InputRecord [] lpBuffer, + uint nLength, + out uint lpNumberOfEventsRead); + + [DllImport ("kernel32.dll")] + static extern bool GetConsoleMode (IntPtr hConsoleHandle, out uint lpMode); + + [DllImport ("kernel32.dll")] + static extern bool SetConsoleMode (IntPtr hConsoleHandle, uint dwMode); + + public uint ConsoleMode { + get { + uint v; + GetConsoleMode (inputHandle, out v); + return v; + } + + set { + SetConsoleMode (inputHandle, value); + } + } } }