From 95db6a83b4e8c593b42aa603393330e78035bee5 Mon Sep 17 00:00:00 2001 From: Miguel de Icaza Date: Thu, 15 Feb 2018 22:19:14 -0500 Subject: [PATCH] Complete the Windows driver --- Terminal.Gui/Core.cs | 9 ++-- Terminal.Gui/Driver.cs | 68 +++++++++++++++++++---------- Terminal.Gui/MonoCurses/mainloop.cs | 58 +++++++++++++++++------- Terminal.Gui/Views/ListView.cs | 3 +- Terminal.Gui/Views/ScrollView.cs | 2 + 5 files changed, 96 insertions(+), 44 deletions(-) diff --git a/Terminal.Gui/Core.cs b/Terminal.Gui/Core.cs index 5adff8b13..92c03af42 100644 --- a/Terminal.Gui/Core.cs +++ b/Terminal.Gui/Core.cs @@ -1264,14 +1264,13 @@ namespace Terminal.Gui { if (p == PlatformID.Win32NT || p == PlatformID.Win32S || p == PlatformID.Win32Windows) UseSystemConsole = true; } - if (UseSystemConsole){ - Console.WriteLine ("WARNING: This version currently does not support data input yet, working on it"); - Console.ReadLine (); + UseSystemConsole = true; + if (UseSystemConsole) Driver = new NetDriver (); - } else + else Driver = new CursesDriver (); Driver.Init (TerminalResized); - MainLoop = new Mono.Terminal.MainLoop (); + MainLoop = new Mono.Terminal.MainLoop (Driver is CursesDriver); SynchronizationContext.SetSynchronizationContext (new MainLoopSyncContext (MainLoop)); Top = Toplevel.Create (); Current = Top; diff --git a/Terminal.Gui/Driver.cs b/Terminal.Gui/Driver.cs index b164cb476..f4e4c59e4 100644 --- a/Terminal.Gui/Driver.cs +++ b/Terminal.Gui/Driver.cs @@ -834,21 +834,40 @@ namespace Terminal.Gui { UpdateOffscreen (); } + bool needMove; // Current row, and current col, tracked by Move/AddCh only int ccol, crow; public override void Move (int col, int row) { ccol = col; crow = row; + + if (Clip.Contains (col, row)) { + Console.CursorTop = row; + Console.CursorLeft = col; + needMove = false; + } else { + Console.CursorTop = Clip.Y; + Console.CursorLeft = Clip.X; + needMove = true; + } + } public override void AddRune (Rune rune) { if (Clip.Contains (ccol, crow)) { - contents [crow, ccol, 0] = (int) (uint) rune; + if (needMove) { + Console.CursorLeft = ccol; + Console.CursorTop = crow; + needMove = false; + } + contents [crow, ccol, 0] = (int)(uint)rune; contents [crow, ccol, 1] = currentAttribute; contents [crow, ccol, 2] = 1; - } + dirtyLine [crow] = true; + } else + needMove = true; ccol++; if (ccol == Cols) { ccol = 0; @@ -956,6 +975,8 @@ namespace Terminal.Gui { int rows = Rows; int cols = Cols; + var savedRow = Console.CursorTop; + var savedCol = Console.CursorLeft; for (int row = 0; row < rows; row++) { if (!dirtyLine [row]) continue; @@ -976,6 +997,8 @@ namespace Terminal.Gui { } } } + Console.CursorTop = savedRow; + Console.CursorLeft = savedCol; } public override void StartReportingMouseMoves() @@ -998,27 +1021,9 @@ namespace Terminal.Gui { Key MapKey (ConsoleKeyInfo keyInfo) { - var key = keyInfo.Key; - if (key >= ConsoleKey.A && key <= ConsoleKey.Z){ - var delta = key - ConsoleKey.A; - if (keyInfo.Modifiers == ConsoleModifiers.Control) - return (Key)((uint)Key.ControlA + delta); - if (keyInfo.Modifiers == ConsoleModifiers.Alt) - return (Key) (((uint)Key.AltMask) | ((uint)'A' + delta)); - if (keyInfo.Modifiers == ConsoleModifiers.Shift) - return (Key)((uint)'A' + delta); - else - return (Key)((uint)'a' + delta); - } - if (key >= ConsoleKey.F1 && key <= ConsoleKey.F10) { - var delta = key - ConsoleKey.F1; - - return (Key)(ConsoleKey.F1 + delta); - } - - switch (keyInfo.Key){ + switch (keyInfo.Key) { case ConsoleKey.Tab: - return Key.ControlT; + return Key.Tab; case ConsoleKey.Escape: return Key.Esc; case ConsoleKey.Home: @@ -1046,6 +1051,25 @@ namespace Terminal.Gui { case ConsoleKey.Delete: return Key.Delete; } + + var key = keyInfo.Key; + if (key >= ConsoleKey.A && key <= ConsoleKey.Z){ + var delta = key - ConsoleKey.A; + if (keyInfo.Modifiers == ConsoleModifiers.Control) + return (Key)((uint)Key.ControlA + delta); + if (keyInfo.Modifiers == ConsoleModifiers.Alt) + return (Key) (((uint)Key.AltMask) | ((uint)'A' + delta)); + if (keyInfo.Modifiers == ConsoleModifiers.Shift) + return (Key)((uint)'A' + delta); + else + return (Key)((uint)'a' + delta); + } + if (key >= ConsoleKey.F1 && key <= ConsoleKey.F10) { + var delta = key - ConsoleKey.F1; + + return (Key)(ConsoleKey.F1 + delta); + } + return (Key)(0xffffffff); } diff --git a/Terminal.Gui/MonoCurses/mainloop.cs b/Terminal.Gui/MonoCurses/mainloop.cs index 5ebc63414..daa13231d 100644 --- a/Terminal.Gui/MonoCurses/mainloop.cs +++ b/Terminal.Gui/MonoCurses/mainloop.cs @@ -36,8 +36,12 @@ namespace Mono.Terminal { /// Simple main loop implementation that can be used to monitor /// file descriptor, run timers and idle handlers. /// + /// + /// Monitoring of file descriptors is only available on Unix, there + /// does not seem to be a way of supporting this on Windows. + /// public class MainLoop { - static bool useUnix = true; + bool useUnix = true; /// /// Condition on which to wake up from file descriptor activity. These match the Linux/BSD poll definitions. @@ -82,7 +86,7 @@ namespace Mono.Terminal { } Dictionary descriptorWatchers = new Dictionary(); - SortedList timeouts = new SortedList (); + SortedList timeouts = new SortedList (); List> idleHandlers = new List> (); [StructLayout(LayoutKind.Sequential)] @@ -107,17 +111,27 @@ namespace Mono.Terminal { bool poll_dirty = true; int [] wakeupPipes = new int [2]; static IntPtr ignore = Marshal.AllocHGlobal (1); - + /// /// Default constructor /// - public MainLoop () + public MainLoop () : this (useUnix: true) { - pipe (wakeupPipes); - AddWatch (wakeupPipes [0], Condition.PollIn, ml => { - read (wakeupPipes [0], ignore, (IntPtr) 1); - return true; - }); + } + + public MainLoop (bool useUnix) + { + this.useUnix = useUnix; + if (useUnix) { + pipe (wakeupPipes); + AddWatch (wakeupPipes [0], Condition.PollIn, ml => { + read (wakeupPipes [0], ignore, (IntPtr)1); + return true; + }); + } else { + Thread readThread = new Thread (WindowsKeyReader); + readThread.Start (); + } } void Wakeup () @@ -260,7 +274,7 @@ namespace Mono.Terminal { { long now = DateTime.UtcNow.Ticks; var copy = timeouts; - timeouts = new SortedList (); + timeouts = new SortedList (); foreach (var k in copy.Keys){ var timeout = copy [k]; if (k < now) { @@ -304,7 +318,7 @@ namespace Mono.Terminal { { while (true) { waitForProbe.WaitOne (); - var result = Console.ReadKey (); + windowsKeyResult = Console.ReadKey (); keyReady.Set (); } } @@ -322,9 +336,12 @@ namespace Mono.Terminal { long now = DateTime.UtcNow.Ticks; if (useUnix) { int pollTimeout, n; - if (timeouts.Count > 0) + if (timeouts.Count > 0){ pollTimeout = (int)((timeouts.Keys [0] - now) / TimeSpan.TicksPerMillisecond); - else + if (pollTimeout < 0) + return true; + + } else pollTimeout = -1; if (!wait) @@ -338,10 +355,21 @@ namespace Mono.Terminal { ic = idleHandlers.Count; return n > 0 || timeouts.Count > 0 && ((timeouts.Keys [0] - DateTime.UtcNow.Ticks) < 0) || ic > 0; } else { + int waitTimeout; + if (timeouts.Count > 0){ + waitTimeout = (int)((timeouts.Keys [0] - now) / TimeSpan.TicksPerMillisecond); + if (waitTimeout < 0) + return true; + } else + waitTimeout = -1; + + if (!wait) + waitTimeout = 0; + windowsKeyResult = null; waitForProbe.Set (); - keyReady.WaitOne (); - return false; + keyReady.WaitOne (waitTimeout); + return windowsKeyResult.HasValue; } } diff --git a/Terminal.Gui/Views/ListView.cs b/Terminal.Gui/Views/ListView.cs index 31172428f..5f67e6d62 100644 --- a/Terminal.Gui/Views/ListView.cs +++ b/Terminal.Gui/Views/ListView.cs @@ -282,7 +282,6 @@ namespace Terminal.Gui { Driver.AddRune (' '); else Source.Render (isSelected, item, 0, row, f.Width); - } } @@ -361,7 +360,7 @@ namespace Terminal.Gui { /// public override void PositionCursor() { - Driver.Move (0, selected); + Move (0, selected-top); } public override bool MouseEvent(MouseEvent me) diff --git a/Terminal.Gui/Views/ScrollView.cs b/Terminal.Gui/Views/ScrollView.cs index 7551cc756..99b239470 100644 --- a/Terminal.Gui/Views/ScrollView.cs +++ b/Terminal.Gui/Views/ScrollView.cs @@ -270,6 +270,7 @@ namespace Terminal.Gui { contentView.Frame = new Rect (contentOffset, value); vertical.Size = contentSize.Height; horizontal.Size = contentSize.Width; + SetNeedsDisplay (); } } @@ -286,6 +287,7 @@ namespace Terminal.Gui { contentView.Frame = new Rect (contentOffset, contentSize); vertical.Position = Math.Max (0, -contentOffset.Y); horizontal.Position = Math.Max (0, -contentOffset.X); + SetNeedsDisplay (); } }