瀏覽代碼

Merge pull request #2218 from BDisp/toplevel-drag-fix-2162

Fixes #2162. Toplevel dragging wasn't moving well.
Tig 2 年之前
父節點
當前提交
9afdc4df3b
共有 4 個文件被更改,包括 179 次插入19 次删除
  1. 5 6
      Terminal.Gui/Core/Application.cs
  2. 9 12
      Terminal.Gui/Core/Toplevel.cs
  3. 1 1
      UnitTests/ApplicationTests.cs
  4. 164 0
      UnitTests/ToplevelTests.cs

+ 5 - 6
Terminal.Gui/Core/Application.cs

@@ -414,7 +414,7 @@ namespace Terminal.Gui {
 				// In this case, we want to throw a more specific exception.
 				throw new InvalidOperationException ("Unable to initialize the console. This can happen if the console is already in use by another process or in unit tests.", ex);
 			}
-			
+
 			SynchronizationContext.SetSynchronizationContext (new MainLoopSyncContext (MainLoop));
 
 			Top = topLevelFactory ();
@@ -757,8 +757,7 @@ namespace Terminal.Gui {
 
 			if (mouseGrabView != null) {
 				if (view == null) {
-					UngrabMouse ();
-					return;
+					view = mouseGrabView;
 				}
 
 				var newxy = mouseGrabView.ScreenToView (me.X, me.Y);
@@ -773,7 +772,7 @@ namespace Terminal.Gui {
 				if (OutsideFrame (new Point (nme.X, nme.Y), mouseGrabView.Frame)) {
 					lastMouseOwnerView?.OnMouseLeave (me);
 				}
-				// System.Diagnostics.Debug.WriteLine ($"{nme.Flags};{nme.X};{nme.Y};{mouseGrabView}");
+				//System.Diagnostics.Debug.WriteLine ($"{nme.Flags};{nme.X};{nme.Y};{mouseGrabView}");
 				if (mouseGrabView?.OnMouseEvent (nme) == true) {
 					return;
 				}
@@ -901,7 +900,7 @@ namespace Terminal.Gui {
 			}
 
 			var rs = new RunState (toplevel);
-			
+
 			if (toplevel is ISupportInitializeNotification initializableNotification &&
 			    !initializableNotification.IsInitialized) {
 				initializableNotification.BeginInit ();
@@ -915,7 +914,7 @@ namespace Terminal.Gui {
 				// If Top was already initialized with Init, and Begin has never been called
 				// Top was not added to the toplevels Stack. It will thus never get disposed.
 				// Clean it up here:
-				if (Top != null && toplevel != Top && !toplevels.Contains(Top)) {
+				if (Top != null && toplevel != Top && !toplevels.Contains (Top)) {
 					Top.Dispose ();
 					Top = null;
 				}

+ 9 - 12
Terminal.Gui/Core/Toplevel.cs

@@ -775,6 +775,8 @@ namespace Terminal.Gui {
 				return true;
 			}
 
+			//System.Diagnostics.Debug.WriteLine ($"dragPosition before: {dragPosition.HasValue}");
+
 			int nx, ny;
 			if (!dragPosition.HasValue && (mouseEvent.Flags == MouseFlags.Button1Pressed
 				|| mouseEvent.Flags == MouseFlags.Button2Pressed
@@ -809,32 +811,27 @@ namespace Terminal.Gui {
 						SuperView.SetNeedsDisplay ();
 					}
 					EnsureVisibleBounds (this, mouseEvent.X + (SuperView == null ? mouseEvent.OfX - start.X : Frame.X - start.X),
-						mouseEvent.Y + (SuperView == null ? mouseEvent.OfY : Frame.Y),
+						mouseEvent.Y + (SuperView == null ? mouseEvent.OfY - start.Y : Frame.Y - start.Y),
 						out nx, out ny, out _, out _);
 
 					dragPosition = new Point (nx, ny);
-					LayoutSubviews ();
-					Frame = new Rect (nx, ny, Frame.Width, Frame.Height);
-					if (X == null || X is Pos.PosAbsolute) {
-						X = nx;
-					}
-					if (Y == null || Y is Pos.PosAbsolute) {
-						Y = ny;
-					}
-					//System.Diagnostics.Debug.WriteLine ($"nx:{nx},ny:{ny}");
+					X = nx;
+					Y = ny;
+					//System.Diagnostics.Debug.WriteLine ($"Drag: nx:{nx},ny:{ny}");
 
 					SetNeedsDisplay ();
 					return true;
 				}
 			}
 
-			if (mouseEvent.Flags == MouseFlags.Button1Released && dragPosition.HasValue) {
+			if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Released) && dragPosition.HasValue) {
 				Application.UngrabMouse ();
 				Driver.UncookMouse ();
 				dragPosition = null;
 			}
 
-			//System.Diagnostics.Debug.WriteLine (mouseEvent.ToString ());
+			//System.Diagnostics.Debug.WriteLine ($"dragPosition after: {dragPosition.HasValue}");
+			//System.Diagnostics.Debug.WriteLine ($"Toplevel: {mouseEvent}");
 			return false;
 		}
 

+ 1 - 1
UnitTests/ApplicationTests.cs

@@ -905,7 +905,7 @@ namespace Terminal.Gui.Core {
 							Flags = MouseFlags.ReportMousePosition
 						});
 
-					Assert.Null (Application.MouseGrabView);
+					Assert.Equal (sv, Application.MouseGrabView);
 
 					ReflectionTools.InvokePrivate (
 						typeof (Application),

+ 164 - 0
UnitTests/ToplevelTests.cs

@@ -1,8 +1,16 @@
 using System;
 using Xunit;
+using Xunit.Abstractions;
 
 namespace Terminal.Gui.Core {
 	public class ToplevelTests {
+		readonly ITestOutputHelper output;
+
+		public ToplevelTests (ITestOutputHelper output)
+		{
+			this.output = output;
+		}
+
 		[Fact]
 		[AutoInitShutdown]
 		public void Constructor_Default ()
@@ -661,5 +669,161 @@ namespace Terminal.Gui.Core {
 				Application.Run (fd);
 			}
 		}
+
+		[Fact, AutoInitShutdown]
+		public void Mouse_Drag ()
+		{
+			var menu = new MenuBar (new MenuBarItem [] {
+				new MenuBarItem("File", new MenuItem [] {
+					new MenuItem("New", "", null)
+				})
+			});
+
+			var sbar = new StatusBar (new StatusItem [] {
+				new StatusItem(Key.N, "~CTRL-N~ New", null)
+			});
+
+			var win = new Window ("Window");
+			var top = Application.Top;
+			top.Add (menu, sbar, win);
+
+			var iterations = -1;
+
+			Application.Iteration = () => {
+				iterations++;
+				if (iterations == 0) {
+					((FakeDriver)Application.Driver).SetBufferSize (40, 15);
+					MessageBox.Query ("About", "Hello Word", "Ok");
+
+				} else if (iterations == 1) {
+					TestHelpers.AssertDriverContentsWithFrameAre (@"
+ File                                   
+┌ Window ──────────────────────────────┐
+│                                      │
+│                                      │
+│                                      │
+│       ┌ About ───────────────┐       │
+│       │      Hello Word      │       │
+│       │                      │       │
+│       │       [◦ Ok ◦]       │       │
+│       └──────────────────────┘       │
+│                                      │
+│                                      │
+│                                      │
+└──────────────────────────────────────┘
+ CTRL-N New                             ", output);
+
+				} else if (iterations == 2) {
+					Assert.Null (Application.MouseGrabView);
+					// Grab the mouse
+					ReflectionTools.InvokePrivate (
+						typeof (Application),
+						"ProcessMouseEvent",
+						new MouseEvent () {
+							X = 8,
+							Y = 5,
+							Flags = MouseFlags.Button1Pressed
+						});
+
+					Assert.Equal (Application.Current, Application.MouseGrabView);
+					Assert.Equal (new Rect (8, 5, 24, 5), Application.MouseGrabView.Frame);
+
+				} else if (iterations == 3) {
+					Assert.Equal (Application.Current, Application.MouseGrabView);
+					// Grab to left
+					ReflectionTools.InvokePrivate (
+						typeof (Application),
+						"ProcessMouseEvent",
+						new MouseEvent () {
+							X = 7,
+							Y = 5,
+							Flags = MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition
+						});
+
+					Assert.Equal (Application.Current, Application.MouseGrabView);
+					Assert.Equal (new Rect (7, 5, 24, 5), Application.MouseGrabView.Frame);
+
+				} else if (iterations == 4) {
+					Assert.Equal (Application.Current, Application.MouseGrabView);
+
+					TestHelpers.AssertDriverContentsWithFrameAre (@"
+ File                                   
+┌ Window ──────────────────────────────┐
+│                                      │
+│                                      │
+│                                      │
+│      ┌ About ───────────────┐        │
+│      │      Hello Word      │        │
+│      │                      │        │
+│      │       [◦ Ok ◦]       │        │
+│      └──────────────────────┘        │
+│                                      │
+│                                      │
+│                                      │
+└──────────────────────────────────────┘
+ CTRL-N New                             ", output);
+
+					Assert.Equal (Application.Current, Application.MouseGrabView);
+				} else if (iterations == 5) {
+					Assert.Equal (Application.Current, Application.MouseGrabView);
+					// Grab to top
+					ReflectionTools.InvokePrivate (
+						typeof (Application),
+						"ProcessMouseEvent",
+						new MouseEvent () {
+							X = 7,
+							Y = 4,
+							Flags = MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition
+						});
+
+					Assert.Equal (Application.Current, Application.MouseGrabView);
+					Assert.Equal (new Rect (7, 4, 24, 5), Application.MouseGrabView.Frame);
+
+				} else if (iterations == 6) {
+					Assert.Equal (Application.Current, Application.MouseGrabView);
+
+					TestHelpers.AssertDriverContentsWithFrameAre (@"
+ File                                   
+┌ Window ──────────────────────────────┐
+│                                      │
+│                                      │
+│      ┌ About ───────────────┐        │
+│      │      Hello Word      │        │
+│      │                      │        │
+│      │       [◦ Ok ◦]       │        │
+│      └──────────────────────┘        │
+│                                      │
+│                                      │
+│                                      │
+│                                      │
+└──────────────────────────────────────┘
+ CTRL-N New                             ", output);
+
+					Assert.Equal (Application.Current, Application.MouseGrabView);
+					Assert.Equal (new Rect (7, 4, 24, 5), Application.MouseGrabView.Frame);
+
+				} else if (iterations == 7) {
+					Assert.Equal (Application.Current, Application.MouseGrabView);
+					// Ungrab the mouse
+					ReflectionTools.InvokePrivate (
+						typeof (Application),
+						"ProcessMouseEvent",
+						new MouseEvent () {
+							X = 7,
+							Y = 4,
+							Flags = MouseFlags.Button1Released
+						});
+
+					Assert.Null (Application.MouseGrabView);
+
+				} else if (iterations == 8) {
+					Application.RequestStop ();
+				} else if (iterations == 9) {
+					Application.RequestStop ();
+				}
+			};
+
+			Application.Run ();
+		}
 	}
 }