瀏覽代碼

Merge pull request #1094 from BDisp/netdriver-virtual-terminal-sequences

Fixes #1093. NetDriver is reading badly sometimes the virtual terminal sequences.
Charlie Kindel 4 年之前
父節點
當前提交
45d5e997e1
共有 1 個文件被更改,包括 165 次插入42 次删除
  1. 165 42
      Terminal.Gui/ConsoleDrivers/NetDriver.cs

+ 165 - 42
Terminal.Gui/ConsoleDrivers/NetDriver.cs

@@ -290,16 +290,18 @@ namespace Terminal.Gui {
 			int curCSI = 0;
 			int curCSI = 0;
 			char previousKChar = '\0';
 			char previousKChar = '\0';
 			if (nCSI > 1) {
 			if (nCSI > 1) {
-				foreach (var ck in cki) {
+				for (int i = 0; i < cki.Length; i++) {
+					var ck = cki [i];
 					if (NumberOfCSI > 0 && nCSI - curCSI > NumberOfCSI) {
 					if (NumberOfCSI > 0 && nCSI - curCSI > NumberOfCSI) {
-						if (ck.KeyChar == '\x1b'
-							|| (ck.KeyChar == '[' && previousKChar != '\x1b')) {
+						if (cki [i + 1].KeyChar == '\x1b' && previousKChar != '\0') {
 							curCSI++;
 							curCSI++;
+							previousKChar = '\0';
+						} else {
+							previousKChar = ck.KeyChar;
 						}
 						}
-						previousKChar = ck.KeyChar;
 						continue;
 						continue;
 					}
 					}
-					if (ck.KeyChar == '\x1b' || (ck.KeyChar == '[' && previousKChar != '\x1b')) {
+					if (ck.KeyChar == '\x1b') {
 						if (ck.KeyChar == 'R') {
 						if (ck.KeyChar == 'R') {
 							ResizeArray (ck);
 							ResizeArray (ck);
 						}
 						}
@@ -310,7 +312,9 @@ namespace Terminal.Gui {
 						length = 0;
 						length = 0;
 					}
 					}
 					ResizeArray (ck);
 					ResizeArray (ck);
-					previousKChar = ck.KeyChar;
+					if (i == cki.Length - 1 && splitedCki.Length > 0) {
+						DecodeCSI (ref inputResult, ref newConsoleKeyInfo, ref key, ref mouseEvent, splitedCki, ref mod);
+					}
 				}
 				}
 			} else {
 			} else {
 				DecodeCSI (ref inputResult, ref newConsoleKeyInfo, ref key, ref mouseEvent, cki, ref mod);
 				DecodeCSI (ref inputResult, ref newConsoleKeyInfo, ref key, ref mouseEvent, cki, ref mod);
@@ -493,6 +497,7 @@ namespace Terminal.Gui {
 		bool isButtonDoubleClicked;
 		bool isButtonDoubleClicked;
 		bool isButtonTripleClicked;
 		bool isButtonTripleClicked;
 		bool isProcContBtnPressedRuning;
 		bool isProcContBtnPressedRuning;
+		bool isButtonReleased;
 
 
 		void GetMouseEvent (ConsoleKeyInfo [] cki)
 		void GetMouseEvent (ConsoleKeyInfo [] cki)
 		{
 		{
@@ -525,39 +530,64 @@ namespace Terminal.Gui {
 				} else if (c == 'm' || c == 'M') {
 				} else if (c == 'm' || c == 'M') {
 					point.Y = int.Parse (value) + Console.WindowTop - 1;
 					point.Y = int.Parse (value) + Console.WindowTop - 1;
 
 
-					if (c == 'M') {
-						isButtonPressed = true;
-					} else if (c == 'm') {
-						isButtonPressed = false;
-					}
+					//if (c == 'M') {
+					//	isButtonPressed = true;
+					//} else if (c == 'm') {
+					//	isButtonPressed = false;
+					//}
 
 
 					switch (buttonCode) {
 					switch (buttonCode) {
 					case 0:
 					case 0:
 					case 8:
 					case 8:
 					case 16:
 					case 16:
+					case 24:
 					case 32:
 					case 32:
+					case 36:
 					case 40:
 					case 40:
+					case 48:
+					case 56:
 						buttonState = c == 'M' ? MouseButtonState.Button1Pressed
 						buttonState = c == 'M' ? MouseButtonState.Button1Pressed
 							: MouseButtonState.Button1Released;
 							: MouseButtonState.Button1Released;
 						break;
 						break;
 					case 1:
 					case 1:
 					case 9:
 					case 9:
 					case 17:
 					case 17:
+					case 25:
 					case 33:
 					case 33:
+					case 37:
 					case 41:
 					case 41:
+					case 45:
+					case 49:
+					case 53:
+					case 57:
+					case 61:
 						buttonState = c == 'M' ? MouseButtonState.Button2Pressed
 						buttonState = c == 'M' ? MouseButtonState.Button2Pressed
 							: MouseButtonState.Button2Released;
 							: MouseButtonState.Button2Released;
 						break;
 						break;
 					case 2:
 					case 2:
 					case 10:
 					case 10:
+					case 14:
 					case 18:
 					case 18:
+					case 22:
+					case 26:
+					case 30:
 					case 34:
 					case 34:
 					case 42:
 					case 42:
+					case 46:
+					case 50:
+					case 54:
+					case 58:
+					case 62:
 						buttonState = c == 'M' ? MouseButtonState.Button3Pressed
 						buttonState = c == 'M' ? MouseButtonState.Button3Pressed
 							: MouseButtonState.Button3Released;
 							: MouseButtonState.Button3Released;
 						break;
 						break;
 					case 35:
 					case 35:
+					case 39:
 					case 43:
 					case 43:
+					case 47:
+					case 55:
+					case 59:
+					case 63:
 						buttonState = MouseButtonState.ReportMousePosition;
 						buttonState = MouseButtonState.ReportMousePosition;
 						break;
 						break;
 					case 64:
 					case 64:
@@ -566,11 +596,15 @@ namespace Terminal.Gui {
 					case 65:
 					case 65:
 						buttonState = MouseButtonState.ButtonWheeledDown;
 						buttonState = MouseButtonState.ButtonWheeledDown;
 						break;
 						break;
+					case 68:
 					case 72:
 					case 72:
-						buttonState = MouseButtonState.ButtonWheeledLeft;       // Ctrl+ButtonWheeledUp
+					case 80:
+						buttonState = MouseButtonState.ButtonWheeledLeft;       // Shift/Ctrl+ButtonWheeledUp
 						break;
 						break;
+					case 69:
 					case 73:
 					case 73:
-						buttonState = MouseButtonState.ButtonWheeledRight;      // Ctrl+ButtonWheeledDown
+					case 81:
+						buttonState = MouseButtonState.ButtonWheeledRight;      // Shift/Ctrl+ButtonWheeledDown
 						break;
 						break;
 					}
 					}
 					// Modifiers.
 					// Modifiers.
@@ -578,17 +612,74 @@ namespace Terminal.Gui {
 					case 8:
 					case 8:
 					case 9:
 					case 9:
 					case 10:
 					case 10:
+					case 43:
+						buttonState |= MouseButtonState.ButtonAlt;
+						break;
+					case 14:
+					case 47:
+						buttonState |= MouseButtonState.ButtonAlt | MouseButtonState.ButtonShift;
+						break;
 					case 16:
 					case 16:
 					case 17:
 					case 17:
 					case 18:
 					case 18:
-					case 43:
+					case 51:
 						buttonState |= MouseButtonState.ButtonCtrl;
 						buttonState |= MouseButtonState.ButtonCtrl;
 						break;
 						break;
+					case 22:
+					case 55:
+						buttonState |= MouseButtonState.ButtonCtrl | MouseButtonState.ButtonShift;
+						break;
+					case 24:
+					case 25:
+					case 26:
+					case 59:
+						buttonState |= MouseButtonState.ButtonAlt | MouseButtonState.ButtonCtrl;
+						break;
+					case 30:
+					case 63:
+						buttonState |= MouseButtonState.ButtonCtrl | MouseButtonState.ButtonShift | MouseButtonState.ButtonAlt;
+						break;
 					case 32:
 					case 32:
 					case 33:
 					case 33:
 					case 34:
 					case 34:
 						buttonState |= MouseButtonState.ReportMousePosition;
 						buttonState |= MouseButtonState.ReportMousePosition;
 						break;
 						break;
+					case 36:
+					case 37:
+						buttonState |= MouseButtonState.ReportMousePosition | MouseButtonState.ButtonShift;
+						break;
+					case 39:
+					case 68:
+					case 69:
+						buttonState |= MouseButtonState.ButtonShift;
+						break;
+					case 40:
+					case 41:
+					case 42:
+						buttonState |= MouseButtonState.ReportMousePosition | MouseButtonState.ButtonAlt;
+						break;
+					case 45:
+					case 46:
+						buttonState |= MouseButtonState.ReportMousePosition | MouseButtonState.ButtonAlt | MouseButtonState.ButtonShift;
+						break;
+					case 48:
+					case 49:
+					case 50:
+						buttonState |= MouseButtonState.ReportMousePosition | MouseButtonState.ButtonCtrl;
+						break;
+					case 53:
+					case 54:
+						buttonState |= MouseButtonState.ReportMousePosition | MouseButtonState.ButtonCtrl | MouseButtonState.ButtonShift;
+						break;
+					case 56:
+					case 57:
+					case 58:
+						buttonState |= MouseButtonState.ReportMousePosition | MouseButtonState.ButtonCtrl | MouseButtonState.ButtonAlt;
+						break;
+					case 61:
+					case 62:
+						buttonState |= MouseButtonState.ReportMousePosition | MouseButtonState.ButtonCtrl | MouseButtonState.ButtonShift | MouseButtonState.ButtonAlt;
+						break;
 					}
 					}
 				}
 				}
 			}
 			}
@@ -596,6 +687,14 @@ namespace Terminal.Gui {
 			mouseEvent.Position.Y = point.Y;
 			mouseEvent.Position.Y = point.Y;
 			mouseEvent.ButtonState = buttonState;
 			mouseEvent.ButtonState = buttonState;
 
 
+			if ((buttonState & MouseButtonState.Button1Pressed) != 0
+				|| (buttonState & MouseButtonState.Button2Pressed) != 0
+				|| (buttonState & MouseButtonState.Button3Pressed) != 0) {
+				isButtonPressed = true;
+			} else {
+				isButtonPressed = false;
+			}
+
 			if ((isButtonClicked || isButtonDoubleClicked || isButtonTripleClicked)
 			if ((isButtonClicked || isButtonDoubleClicked || isButtonTripleClicked)
 				&& ((buttonState & MouseButtonState.Button1Released) != 0
 				&& ((buttonState & MouseButtonState.Button1Released) != 0
 				|| (buttonState & MouseButtonState.Button2Released) != 0
 				|| (buttonState & MouseButtonState.Button2Released) != 0
@@ -630,6 +729,16 @@ namespace Terminal.Gui {
 				return;
 				return;
 			}
 			}
 
 
+			if (!isButtonPressed && !isButtonClicked && !isButtonDoubleClicked && !isButtonTripleClicked
+				&& !isButtonReleased
+				&& ((buttonState & MouseButtonState.Button1Released) == 0
+				&& (buttonState & MouseButtonState.Button2Released) == 0
+				&& (buttonState & MouseButtonState.Button3Released) == 0)) {
+				ProcessButtonReleased (lastMouseEvent);
+				inputReady.Set ();
+				return;
+			}
+
 			inputResultQueue.Enqueue (new InputResult () {
 			inputResultQueue.Enqueue (new InputResult () {
 				EventType = EventType.Mouse,
 				EventType = EventType.Mouse,
 				MouseEvent = mouseEvent
 				MouseEvent = mouseEvent
@@ -654,6 +763,7 @@ namespace Terminal.Gui {
 
 
 			lastMouseEvent = mouseEvent;
 			lastMouseEvent = mouseEvent;
 			if (isButtonPressed && !isButtonClicked && !isButtonDoubleClicked && !isButtonTripleClicked && !isProcContBtnPressedRuning) {
 			if (isButtonPressed && !isButtonClicked && !isButtonDoubleClicked && !isButtonTripleClicked && !isProcContBtnPressedRuning) {
+				isButtonReleased = false;
 				Application.MainLoop.AddIdle (() => {
 				Application.MainLoop.AddIdle (() => {
 					ProcessContinuousButtonPressedAsync ().ConfigureAwait (false);
 					ProcessContinuousButtonPressedAsync ().ConfigureAwait (false);
 					return false;
 					return false;
@@ -669,22 +779,18 @@ namespace Terminal.Gui {
 				Position = mouseEvent.Position,
 				Position = mouseEvent.Position,
 				ButtonState = mouseEvent.ButtonState
 				ButtonState = mouseEvent.ButtonState
 			};
 			};
-			switch (mouseEvent.ButtonState) {
-			case MouseButtonState.Button1Released:
+			if ((mouseEvent.ButtonState & MouseButtonState.Button1Released) != 0) {
 				me.ButtonState &= ~MouseButtonState.Button1Released;
 				me.ButtonState &= ~MouseButtonState.Button1Released;
 				me.ButtonState |= MouseButtonState.Button1Clicked;
 				me.ButtonState |= MouseButtonState.Button1Clicked;
-				break;
-			case MouseButtonState.Button2Released:
+			} else if ((mouseEvent.ButtonState & MouseButtonState.Button2Released) != 0) {
 				me.ButtonState &= ~MouseButtonState.Button2Released;
 				me.ButtonState &= ~MouseButtonState.Button2Released;
 				me.ButtonState |= MouseButtonState.Button2Clicked;
 				me.ButtonState |= MouseButtonState.Button2Clicked;
-				break;
-			case MouseButtonState.Button3Released:
+			} else if ((mouseEvent.ButtonState & MouseButtonState.Button3Released) != 0) {
 				me.ButtonState &= ~MouseButtonState.Button3Released;
 				me.ButtonState &= ~MouseButtonState.Button3Released;
 				me.ButtonState |= MouseButtonState.Button3Clicked;
 				me.ButtonState |= MouseButtonState.Button3Clicked;
-				break;
-			default:
-				return;
 			}
 			}
+			isButtonReleased = true;
+
 			inputResultQueue.Enqueue (new InputResult () {
 			inputResultQueue.Enqueue (new InputResult () {
 				EventType = EventType.Mouse,
 				EventType = EventType.Mouse,
 				MouseEvent = me
 				MouseEvent = me
@@ -697,22 +803,18 @@ namespace Terminal.Gui {
 				Position = mouseEvent.Position,
 				Position = mouseEvent.Position,
 				ButtonState = mouseEvent.ButtonState
 				ButtonState = mouseEvent.ButtonState
 			};
 			};
-			switch (mouseEvent.ButtonState) {
-			case MouseButtonState.Button1Pressed:
+			if ((mouseEvent.ButtonState & MouseButtonState.Button1Pressed) != 0) {
 				me.ButtonState &= ~MouseButtonState.Button1Pressed;
 				me.ButtonState &= ~MouseButtonState.Button1Pressed;
 				me.ButtonState |= MouseButtonState.Button1DoubleClicked;
 				me.ButtonState |= MouseButtonState.Button1DoubleClicked;
-				break;
-			case MouseButtonState.Button2Pressed:
+			} else if ((mouseEvent.ButtonState & MouseButtonState.Button2Pressed) != 0) {
 				me.ButtonState &= ~MouseButtonState.Button2Pressed;
 				me.ButtonState &= ~MouseButtonState.Button2Pressed;
 				me.ButtonState |= MouseButtonState.Button2DoubleClicked;
 				me.ButtonState |= MouseButtonState.Button2DoubleClicked;
-				break;
-			case MouseButtonState.Button3Pressed:
+			} else if ((mouseEvent.ButtonState & MouseButtonState.Button3Pressed) != 0) {
 				me.ButtonState &= ~MouseButtonState.Button3Pressed;
 				me.ButtonState &= ~MouseButtonState.Button3Pressed;
 				me.ButtonState |= MouseButtonState.Button3DoubleClicked;
 				me.ButtonState |= MouseButtonState.Button3DoubleClicked;
-				break;
-			default:
-				return;
 			}
 			}
+			isButtonReleased = true;
+
 			inputResultQueue.Enqueue (new InputResult () {
 			inputResultQueue.Enqueue (new InputResult () {
 				EventType = EventType.Mouse,
 				EventType = EventType.Mouse,
 				MouseEvent = me
 				MouseEvent = me
@@ -725,22 +827,18 @@ namespace Terminal.Gui {
 				Position = mouseEvent.Position,
 				Position = mouseEvent.Position,
 				ButtonState = mouseEvent.ButtonState
 				ButtonState = mouseEvent.ButtonState
 			};
 			};
-			switch (mouseEvent.ButtonState) {
-			case MouseButtonState.Button1Pressed:
+			if ((mouseEvent.ButtonState & MouseButtonState.Button1Pressed) != 0) {
 				me.ButtonState &= ~MouseButtonState.Button1Pressed;
 				me.ButtonState &= ~MouseButtonState.Button1Pressed;
 				me.ButtonState |= MouseButtonState.Button1TripleClicked;
 				me.ButtonState |= MouseButtonState.Button1TripleClicked;
-				break;
-			case MouseButtonState.Button2Pressed:
+			} else if ((mouseEvent.ButtonState & MouseButtonState.Button2Pressed) != 0) {
 				me.ButtonState &= ~MouseButtonState.Button2Pressed;
 				me.ButtonState &= ~MouseButtonState.Button2Pressed;
 				me.ButtonState |= MouseButtonState.Button2TrippleClicked;
 				me.ButtonState |= MouseButtonState.Button2TrippleClicked;
-				break;
-			case MouseButtonState.Button3Pressed:
+			} else if ((mouseEvent.ButtonState & MouseButtonState.Button3Pressed) != 0) {
 				me.ButtonState &= ~MouseButtonState.Button3Pressed;
 				me.ButtonState &= ~MouseButtonState.Button3Pressed;
 				me.ButtonState |= MouseButtonState.Button3TripleClicked;
 				me.ButtonState |= MouseButtonState.Button3TripleClicked;
-				break;
-			default:
-				return;
 			}
 			}
+			isButtonReleased = true;
+
 			inputResultQueue.Enqueue (new InputResult () {
 			inputResultQueue.Enqueue (new InputResult () {
 				EventType = EventType.Mouse,
 				EventType = EventType.Mouse,
 				MouseEvent = me
 				MouseEvent = me
@@ -768,7 +866,32 @@ namespace Terminal.Gui {
 				}
 				}
 			}
 			}
 			isProcContBtnPressedRuning = false;
 			isProcContBtnPressedRuning = false;
-			isButtonPressed = false;
+			//isButtonPressed = false;
+		}
+
+		void ProcessButtonReleased (MouseEvent mouseEvent)
+		{
+			var me = new MouseEvent () {
+				Position = mouseEvent.Position,
+				ButtonState = mouseEvent.ButtonState
+			};
+			if ((mouseEvent.ButtonState & MouseButtonState.Button1Pressed) != 0) {
+				me.ButtonState &= ~(MouseButtonState.Button1Pressed | MouseButtonState.ReportMousePosition);
+				me.ButtonState |= MouseButtonState.Button1Released;
+			} else if ((mouseEvent.ButtonState & MouseButtonState.Button2Pressed) != 0) {
+				me.ButtonState &= ~(MouseButtonState.Button2Pressed | MouseButtonState.ReportMousePosition);
+				me.ButtonState |= MouseButtonState.Button2Released;
+			} else if ((mouseEvent.ButtonState & MouseButtonState.Button3Pressed) != 0) {
+				me.ButtonState &= ~(MouseButtonState.Button3Pressed | MouseButtonState.ReportMousePosition);
+				me.ButtonState |= MouseButtonState.Button3Released;
+			}
+			isButtonReleased = true;
+			lastMouseEvent = me;
+
+			inputResultQueue.Enqueue (new InputResult () {
+				EventType = EventType.Mouse,
+				MouseEvent = me
+			});
 		}
 		}
 
 
 		ConsoleModifiers GetConsoleModifiers (uint keyChar)
 		ConsoleModifiers GetConsoleModifiers (uint keyChar)