浏览代码

Improves mouse performance #386. Provides a better async call. Ensures all the cycles of a simple click (Pressed, Released and Clicked). Only clears selected text if other view than MenuBar get focus. (#404)

BDisp 5 年之前
父节点
当前提交
a9e62c0626
共有 4 个文件被更改,包括 46 次插入36 次删除
  1. 9 4
      Terminal.Gui/Drivers/WindowsDriver.cs
  2. 17 18
      Terminal.Gui/MonoCurses/mainloop.cs
  3. 19 13
      Terminal.Gui/Views/Menu.cs
  4. 1 1
      Terminal.Gui/Views/TextField.cs

+ 9 - 4
Terminal.Gui/Drivers/WindowsDriver.cs

@@ -594,6 +594,8 @@ namespace Terminal.Gui {
 
 			case WindowsConsole.EventType.Mouse:
 				mouseHandler (ToDriverMouse (inputEvent.MouseEvent));
+				if (IsButtonReleased)
+					mouseHandler (ToDriverMouse (inputEvent.MouseEvent));
 				break;
 
 			case WindowsConsole.EventType.WindowBufferSize:
@@ -635,7 +637,7 @@ namespace Terminal.Gui {
 
 			if ((mouseEvent.EventFlags == 0 && LastMouseButtonPressed == null && !IsButtonDoubleClicked) ||
 				(mouseEvent.EventFlags == WindowsConsole.EventFlags.MouseMoved &&
-				mouseEvent.ButtonState != 0 && !IsButtonDoubleClicked)) {
+				mouseEvent.ButtonState != 0 && !IsButtonReleased && !IsButtonDoubleClicked)) {
 				switch (mouseEvent.ButtonState) {
 				case WindowsConsole.ButtonState.Button1Pressed:
 					mouseFlag = MouseFlags.Button1Pressed;
@@ -653,6 +655,7 @@ namespace Terminal.Gui {
 				if (mouseEvent.EventFlags == WindowsConsole.EventFlags.MouseMoved) {
 					mouseFlag |= MouseFlags.ReportMousePosition;
 					point = new Point ();
+					IsButtonReleased = false;
 				} else {
 					point = new Point () {
 						X = mouseEvent.MousePosition.X,
@@ -660,8 +663,8 @@ namespace Terminal.Gui {
 					};
 				}
 				LastMouseButtonPressed = mouseEvent.ButtonState;
-			} else if (mouseEvent.EventFlags == 0 && LastMouseButtonPressed != null && !IsButtonReleased &&
-				!IsButtonDoubleClicked) {
+			} else if ((mouseEvent.EventFlags == 0 || mouseEvent.EventFlags == WindowsConsole.EventFlags.MouseMoved) &&
+				LastMouseButtonPressed != null && !IsButtonReleased && !IsButtonDoubleClicked) {
 				switch (LastMouseButtonPressed) {
 				case WindowsConsole.ButtonState.Button1Pressed:
 					mouseFlag = MouseFlags.Button1Released;
@@ -677,7 +680,7 @@ namespace Terminal.Gui {
 				}
 				IsButtonReleased = true;
 			} else if ((mouseEvent.EventFlags == 0 || mouseEvent.EventFlags == WindowsConsole.EventFlags.MouseMoved) &&
-				IsButtonReleased) {
+				  IsButtonReleased) {
 				var p = new Point () {
 					X = mouseEvent.MousePosition.X,
 					Y = mouseEvent.MousePosition.Y
@@ -696,6 +699,8 @@ namespace Terminal.Gui {
 						mouseFlag = MouseFlags.Button4Clicked;
 						break;
 					}
+				} else {
+					mouseFlag = 0;
 				}
 				LastMouseButtonPressed = null;
 				IsButtonReleased = false;

+ 17 - 18
Terminal.Gui/MonoCurses/mainloop.cs

@@ -13,10 +13,10 @@
 // distribute, sublicense, and/or sell copies of the Software, and to
 // permit persons to whom the Software is furnished to do so, subject to
 // the following conditions:
-// 
+//
 // The above copyright notice and this permission notice shall be
 // included in all copies or substantial portions of the Software.
-// 
+//
 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@@ -138,7 +138,7 @@ namespace Mono.Terminal {
 			AddWatch (wakeupPipes [0], Condition.PollIn, ml => {
 				read (wakeupPipes [0], ignore, (IntPtr)1);
 				return true;
-			});			
+			});
 		}
 
 		/// <summary>
@@ -192,7 +192,7 @@ namespace Mono.Terminal {
 			}
 		}
 
-		bool IMainLoopDriver.EventsPending (bool wait) 
+		bool IMainLoopDriver.EventsPending (bool wait)
 		{
 			long now = DateTime.UtcNow.Ticks;
 
@@ -214,10 +214,10 @@ namespace Mono.Terminal {
 			int ic;
 			lock (mainLoop.idleHandlers)
 				ic = mainLoop.idleHandlers.Count;
-			return n > 0 || mainLoop.timeouts.Count > 0 && ((mainLoop.timeouts.Keys [0] - DateTime.UtcNow.Ticks) < 0) || ic > 0;			
+			return n > 0 || mainLoop.timeouts.Count > 0 && ((mainLoop.timeouts.Keys [0] - DateTime.UtcNow.Ticks) < 0) || ic > 0;
 		}
 
-		void IMainLoopDriver.MainIteration () 
+		void IMainLoopDriver.MainIteration ()
 		{
 			if (pollmap != null) {
 				foreach (var p in pollmap) {
@@ -231,7 +231,7 @@ namespace Mono.Terminal {
 					if (!watch.Callback (this.mainLoop))
 						descriptorWatchers.Remove (p.fd);
 				}
-			}			
+			}
 		}
 	}
 
@@ -247,7 +247,7 @@ namespace Mono.Terminal {
 		public Action<ConsoleKeyInfo> WindowsKeyPressed;
 		MainLoop mainLoop;
 
-		public NetMainLoop () 
+		public NetMainLoop ()
 		{
 		}
 
@@ -258,16 +258,16 @@ namespace Mono.Terminal {
 				windowsKeyResult = Console.ReadKey (true);
 				keyReady.Set ();
 			}
-		}		
+		}
 
 		void IMainLoopDriver.Setup (MainLoop mainLoop)
 		{
 			this.mainLoop = mainLoop;
 			Thread readThread = new Thread (WindowsKeyReader);
-			readThread.Start ();			
+			readThread.Start ();
 		}
 
-		void IMainLoopDriver.Wakeup () 
+		void IMainLoopDriver.Wakeup ()
 		{
 		}
 
@@ -298,7 +298,7 @@ namespace Mono.Terminal {
 				if (WindowsKeyPressed!= null)
 					WindowsKeyPressed (windowsKeyResult.Value);
 				windowsKeyResult = null;
-			}			
+			}
 		}
 	}
 
@@ -346,7 +346,6 @@ namespace Mono.Terminal {
 				action ();
 				return false;
 			});
-			driver.Wakeup ();
 		}
 
 		/// <summary>
@@ -373,7 +372,7 @@ namespace Mono.Terminal {
 		{
 			timeouts.Add ((DateTime.UtcNow + time).Ticks, timeout);
 		}
-		
+
 		/// <summary>
 		///   Adds a timeout to the mainloop.
 		/// </summary>
@@ -440,9 +439,9 @@ namespace Mono.Terminal {
 						idleHandlers.Add (idle);
 			}
 		}
-		
+
 		bool running;
-		
+
 		/// <summary>
 		///   Stops the mainloop.
 		/// </summary>
@@ -458,7 +457,7 @@ namespace Mono.Terminal {
 		/// <remarks>
 		///   You can use this method if you want to probe if events are pending.
 		///   Typically used if you need to flush the input queue while still
-		///   running some of your own code in your main thread. 
+		///   running some of your own code in your main thread.
 		/// </remarks>
 		public bool EventsPending (bool wait = false)
 		{
@@ -486,7 +485,7 @@ namespace Mono.Terminal {
 					RunIdle();
 			}
 		}
-		
+
 		/// <summary>
 		///   Runs the mainloop.
 		/// </summary>

+ 19 - 13
Terminal.Gui/Views/Menu.cs

@@ -432,7 +432,7 @@ namespace Terminal.Gui {
 			}
 			host.handled = false;
 			bool disabled;
-			if (me.Flags == MouseFlags.Button1Pressed) {
+			if (me.Flags == MouseFlags.Button1Pressed || me.Flags == MouseFlags.Button1DoubleClicked) {
 				disabled = false;
 				if (me.Y < 1)
 					return true;
@@ -444,7 +444,8 @@ namespace Terminal.Gui {
 				if (item != null && !disabled)
 					Run (barItems.Children [meY].Action);
 				return true;
-			} else if (me.Flags == MouseFlags.Button1Pressed || me.Flags == MouseFlags.ReportMousePosition) {
+			} else if (me.Flags == MouseFlags.Button1Pressed || me.Flags == MouseFlags.Button1DoubleClicked ||
+				me.Flags == MouseFlags.ReportMousePosition) {
 				disabled = false;
 				if (me.Y < 1)
 					return true;
@@ -984,13 +985,14 @@ namespace Terminal.Gui {
 			}
 			handled = false;
 
-			if (me.Flags == MouseFlags.Button1Pressed ||
+			if (me.Flags == MouseFlags.Button1Pressed || me.Flags == MouseFlags.Button1DoubleClicked ||
 				(me.Flags == MouseFlags.ReportMousePosition && selected > -1)) {
 				int pos = 1;
 				int cx = me.X;
 				for (int i = 0; i < Menus.Length; i++) {
 					if (cx > pos && me.X < pos + 1 + Menus [i].TitleLength) {
-						if (selected == i && me.Flags == MouseFlags.Button1Pressed && !isMenuClosed) {
+						if (selected == i && (me.Flags == MouseFlags.Button1Pressed || me.Flags == MouseFlags.Button1DoubleClicked) &&
+							!isMenuClosed) {
 							Application.UngrabMouse ();
 							if (Menus [i].IsTopLevel) {
 								var menu = new Menu (this, i, 0, Menus [i]);
@@ -998,7 +1000,8 @@ namespace Terminal.Gui {
 							} else {
 								CloseMenu ();
 							}
-						} else if (me.Flags == MouseFlags.Button1Pressed && isMenuClosed) {
+						} else if ((me.Flags == MouseFlags.Button1Pressed || me.Flags == MouseFlags.Button1DoubleClicked) &&
+							isMenuClosed) {
 							if (Menus [i].IsTopLevel) {
 								var menu = new Menu (this, i, 0, Menus [i]);
 								menu.Run (Menus [i].Action);
@@ -1033,7 +1036,8 @@ namespace Terminal.Gui {
 						Application.GrabMouse (me.View);
 						me.View.MouseEvent (me);
 					}
-				} else if (!(me.View is MenuBar || me.View is Menu) && me.Flags.HasFlag (MouseFlags.Button1Pressed)) {
+				} else if (!(me.View is MenuBar || me.View is Menu) && (me.Flags.HasFlag (MouseFlags.Button1Pressed) ||
+					me.Flags == MouseFlags.Button1DoubleClicked)) {
 					Application.UngrabMouse ();
 					CloseAllMenus ();
 					handled = false;
@@ -1042,22 +1046,23 @@ namespace Terminal.Gui {
 					handled = false;
 					return false;
 				}
-			} else if (isMenuClosed && me.Flags.HasFlag (MouseFlags.Button1Pressed)) {
+			} else if (isMenuClosed && (me.Flags.HasFlag (MouseFlags.Button1Pressed) || me.Flags == MouseFlags.Button1DoubleClicked)) {
 				Application.GrabMouse (current);
 			} else {
 				handled = false;
 				return false;
 			}
-			//if (me.View != this && me.Flags != MouseFlags.Button1Pressed)
+			//if (me.View != this && (me.Flags != MouseFlags.Button1Pressed || me.Flags == MouseFlags.Button1DoubleClicked))
 			//	return true;
-			//else if (me.View != this && me.Flags == MouseFlags.Button1Pressed) {
+			//else if (me.View != this && (me.Flags == MouseFlags.Button1Pressed || me.Flags == MouseFlags.Button1DoubleClicked)) {
 			//	Application.UngrabMouse ();
 			//	host.CloseAllMenus ();
 			//	return true;
 			//}
 
 
-			//if (!(me.View is MenuBar) && !(me.View is Menu) && me.Flags != MouseFlags.Button1Pressed)
+			//if (!(me.View is MenuBar) && !(me.View is Menu) && (me.Flags != MouseFlags.Button1Pressed ||
+			// me.Flags != MouseFlags.Button1DoubleClicked))
 			//	return false;
 
 			//if (Application.mouseGrabView != null) {
@@ -1066,11 +1071,12 @@ namespace Terminal.Gui {
 			//		me.Y -= me.OfY;
 			//		me.View.MouseEvent (me);
 			//		return true;
-			//	} else if (!(me.View is MenuBar || me.View is Menu) && me.Flags == MouseFlags.Button1Pressed) {
+			//	} else if (!(me.View is MenuBar || me.View is Menu) && (me.Flags == MouseFlags.Button1Pressed ||
+			//		me.Flags == MouseFlags.Button1DoubleClicked)) {
 			//		Application.UngrabMouse ();
 			//		CloseAllMenus ();
 			//	}
-			//} else if (!isMenuClosed && selected == -1 && me.Flags == MouseFlags.Button1Pressed) {
+			//} else if (!isMenuClosed && selected == -1 && (me.Flags == MouseFlags.Button1Pressed || me.Flags == MouseFlags.Button1DoubleClicked)) {
 			//	Application.GrabMouse (this);
 			//	return true;
 			//}
@@ -1082,7 +1088,7 @@ namespace Terminal.Gui {
 			//	} else if (me.View != current && me.View is MenuBar && me.View is Menu) {
 			//		Application.UngrabMouse ();
 			//		Application.GrabMouse (me.View);
-			//	} else if (me.Flags == MouseFlags.Button1Pressed) {
+			//	} else if (me.Flags == MouseFlags.Button1Pressed || me.Flags == MouseFlags.Button1DoubleClicked) {
 			//		Application.UngrabMouse ();
 			//		CloseMenu ();
 			//	}

+ 1 - 1
Terminal.Gui/Views/TextField.cs

@@ -85,7 +85,7 @@ namespace Terminal.Gui {
 		{
 			if (Application.mouseGrabView != null && Application.mouseGrabView == this)
 				Application.UngrabMouse ();
-			if (SelectedLength != 0)
+			if (SelectedLength != 0 && !(Application.mouseGrabView is MenuBar))
 				ClearAllSelection ();
 		}