Procházet zdrojové kódy

Progress on the Windows driver

Miguel de Icaza před 7 roky
rodič
revize
4d1668549f
2 změnil soubory, kde provedl 124 přidání a 27 odebrání
  1. 61 2
      Terminal.Gui/Driver.cs
  2. 63 25
      Terminal.Gui/MonoCurses/mainloop.cs

+ 61 - 2
Terminal.Gui/Driver.cs

@@ -257,7 +257,7 @@ namespace Terminal.Gui {
 		/// </summary>
 		/// <param name="str">String.</param>
 		public abstract void AddStr (ustring str);
-		public abstract void PrepareToRun (MainLoop mainLoop, Action<KeyEvent> target, Action<MouseEvent> mouse);
+		public abstract void PrepareToRun (MainLoop mainLoop, Action<KeyEvent> keyHandler, Action<MouseEvent> mouseHandler);
 
 		/// <summary>
 		/// Updates the screen to reflect all the changes that have been done to the display buffer
@@ -996,8 +996,67 @@ namespace Terminal.Gui {
 			currentAttribute = c.value;
 		}
 
-		public override void PrepareToRun (MainLoop mainLoop, Action<KeyEvent> target, Action<MouseEvent> mouse)
+		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){
+			case ConsoleKey.Tab:
+				return Key.ControlT;
+			case ConsoleKey.Escape:
+				return Key.Esc;
+			case ConsoleKey.Home:
+				return Key.Home;
+			case ConsoleKey.End:
+				return Key.End;
+			case ConsoleKey.LeftArrow:
+				return Key.CursorLeft;
+			case ConsoleKey.RightArrow:
+				return Key.CursorRight;
+			case ConsoleKey.UpArrow:
+				return Key.CursorUp;
+			case ConsoleKey.DownArrow:
+				return Key.CursorDown;
+			case ConsoleKey.PageUp:
+				return Key.PageUp;
+			case ConsoleKey.PageDown:
+				return Key.PageDown;
+			case ConsoleKey.Enter:
+				return Key.Enter;
+			case ConsoleKey.Spacebar:
+				return Key.Space;
+			case ConsoleKey.Backspace:
+				return Key.Backspace;
+			case ConsoleKey.Delete:
+				return Key.Delete;
+			}
+			return (Key)(0xffffffff);
+		}
+
+		public override void PrepareToRun (MainLoop mainLoop, Action<KeyEvent> keyHandler, Action<MouseEvent> mouseHandler)
+		{
+			mainLoop.WindowsKeyPressed = delegate (ConsoleKeyInfo consoleKey) {
+				var map = MapKey (consoleKey);
+				if (map == (Key) 0xffffffff)
+					return;
+				keyHandler (new KeyEvent (map));
+			};
 		}
 
 		public override void SetColors (ConsoleColor foreground, ConsoleColor background)

+ 63 - 25
Terminal.Gui/MonoCurses/mainloop.cs

@@ -28,6 +28,7 @@
 using System.Collections.Generic;
 using System;
 using System.Runtime.InteropServices;
+using System.Threading;
 
 namespace Mono.Terminal {
 
@@ -36,6 +37,8 @@ namespace Mono.Terminal {
 	///   file descriptor, run timers and idle handlers.
 	/// </summary>
 	public class MainLoop {
+		static bool useUnix = true;
+
 		/// <summary>
 		///   Condition on which to wake up from file descriptor activity.  These match the Linux/BSD poll definitions.
 		/// </summary>
@@ -168,13 +171,20 @@ namespace Mono.Terminal {
 		{
 			if (callback == null)
 				throw new ArgumentNullException ("callback");
-
+			if (!useUnix)
+				throw new Exception ("AddWatch is only supported for Unix");
+			
 			var watch = new Watch () { Condition = condition, Callback = callback, File = fileDescriptor };
 			descriptorWatchers [fileDescriptor] = watch;
 			poll_dirty = true;
 			return watch;
 		}
 
+		/// <summary>
+		/// This event is raised when a key is pressed when using the Windows driver.
+		/// </summary>
+		public Action<ConsoleKeyInfo> WindowsKeyPressed;
+
 		/// <summary>
 		///   Removes an active watch from the mainloop.
 		/// </summary>
@@ -287,6 +297,18 @@ namespace Mono.Terminal {
 			Wakeup ();
 		}
 
+		AutoResetEvent keyReady = new AutoResetEvent (false);
+		AutoResetEvent waitForProbe = new AutoResetEvent (false);
+		ConsoleKeyInfo? windowsKeyResult = null;
+		void WindowsKeyReader ()
+		{
+			while (true) {
+				waitForProbe.WaitOne ();
+				var result = Console.ReadKey ();
+				keyReady.Set ();
+			}
+		}
+
 		/// <summary>
 		///   Determines whether there are pending events to be processed.
 		/// </summary>
@@ -298,22 +320,29 @@ namespace Mono.Terminal {
 		public bool EventsPending (bool wait = false)
 		{
 			long now = DateTime.UtcNow.Ticks;
-			int pollTimeout, n;
-			if (timeouts.Count > 0)
-				pollTimeout = (int) ((timeouts.Keys [0] - now) / TimeSpan.TicksPerMillisecond);
-			else
-				pollTimeout = -1;
-			
-			if (!wait)
-				pollTimeout = 0;
-			
-			UpdatePollMap ();
+			if (useUnix) {
+				int pollTimeout, n;
+				if (timeouts.Count > 0)
+					pollTimeout = (int)((timeouts.Keys [0] - now) / TimeSpan.TicksPerMillisecond);
+				else
+					pollTimeout = -1;
 
-			n = poll (pollmap, (uint) pollmap.Length, pollTimeout);
-			int ic;
-			lock (idleHandlers)
-				ic = idleHandlers.Count;
-			return n > 0 || timeouts.Count > 0 && ((timeouts.Keys [0] - DateTime.UtcNow.Ticks) < 0) || ic > 0;
+				if (!wait)
+					pollTimeout = 0;
+
+				UpdatePollMap ();
+
+				n = poll (pollmap, (uint)pollmap.Length, pollTimeout);
+				int ic;
+				lock (idleHandlers)
+					ic = idleHandlers.Count;
+				return n > 0 || timeouts.Count > 0 && ((timeouts.Keys [0] - DateTime.UtcNow.Ticks) < 0) || ic > 0;
+			} else {
+				windowsKeyResult = null;
+				waitForProbe.Set ();
+				keyReady.WaitOne ();
+				return false;
+			}
 		}
 
 		/// <summary>
@@ -329,18 +358,27 @@ namespace Mono.Terminal {
 		{
 			if (timeouts.Count > 0)
 				RunTimers ();
-			
-			foreach (var p in pollmap){
-				Watch watch;
 
-				if (p.revents == 0)
-					continue;
+			if (useUnix) {
+				foreach (var p in pollmap) {
+					Watch watch;
 
-				if (!descriptorWatchers.TryGetValue (p.fd, out watch))
-					continue;
-				if (!watch.Callback (this))
-					descriptorWatchers.Remove (p.fd);
+					if (p.revents == 0)
+						continue;
+
+					if (!descriptorWatchers.TryGetValue (p.fd, out watch))
+						continue;
+					if (!watch.Callback (this))
+						descriptorWatchers.Remove (p.fd);
+				}
+			} else {
+				if (windowsKeyResult.HasValue) {
+					if (WindowsKeyPressed != null)
+						WindowsKeyPressed (windowsKeyResult.Value);
+					windowsKeyResult = null;
+				}
 			}
+
 			if (idleHandlers.Count > 0)
 				RunIdle ();
 		}