From 78bf9f3acb8d88c8a39f9f2cd8bcacb65c90db3e Mon Sep 17 00:00:00 2001 From: Simon Cropp Date: Sat, 22 Aug 2026 23:37:21 +1000 Subject: [PATCH] Clear the queue tooltip when it is forgotten Forget reset the row and left the caption registered. Every caller of it - the cursor leaving the canvas, and a redraw, which renumbers the rows under a cursor that has not moved - is followed by the cursor being somewhere that has no tip, which arrives as row -1. That is the row Forget just set, so Apply returned with nothing to do and the last hovered row's text stayed registered on the whole canvas: resting anywhere brought it back, over the diff panes. Which is the bug this type was written to prevent, reached from the other side. Forget clears the text as well now, and takes the control it is clearing it on. --- .../QueueTipsTests.cs | 37 ++++++++++++++++++- src/DiffEngineViewer.Windows/QueueTips.cs | 12 +++++- src/DiffEngineViewer.Windows/ViewerCanvas.cs | 4 +- 3 files changed, 49 insertions(+), 4 deletions(-) diff --git a/src/DiffEngineViewer.Windows.Tests/QueueTipsTests.cs b/src/DiffEngineViewer.Windows.Tests/QueueTipsTests.cs index d064dbc9..eb43de79 100644 --- a/src/DiffEngineViewer.Windows.Tests/QueueTipsTests.cs +++ b/src/DiffEngineViewer.Windows.Tests/QueueTipsTests.cs @@ -68,8 +68,43 @@ public async Task ForgettingLetsTheSameRowChange() using var tips = new QueueTips(); tips.Apply(owner, 3, "before"); - tips.Forget(); + tips.Forget(owner); tips.Apply(owner, 3, null); await Assert.That(tips.Current(owner)).IsEmpty(); } + + /// + /// The reported bug reached the other way round: the cursor leaves the queue column for the + /// diff panes, which is a Forget - from the mouse leaving, or from the screen being redrawn - + /// followed by a row of -1. + /// + /// Both set the row to -1, so Apply had nothing to do and returned, and the caption for the + /// row last hovered stayed registered on the whole canvas. Resting anywhere brought it back, + /// over the panes. + /// + /// + [Test] + public async Task ForgettingBeforeLeavingTheColumnLeavesNothingRegistered() + { + using var owner = new Control(); + using var tips = new QueueTips(); + + tips.Apply(owner, 2, "SolutionA/Tests/ATests.cs:6"); + tips.Forget(owner); + tips.Apply(owner, -1, null); + + await Assert.That(tips.Current(owner)).IsEmpty(); + } + + [Test] + public async Task ForgettingClearsTheText() + { + using var owner = new Control(); + using var tips = new QueueTips(); + + tips.Apply(owner, 2, "SolutionA/Tests/ATests.cs:6"); + tips.Forget(owner); + + await Assert.That(tips.Current(owner)).IsEmpty(); + } } diff --git a/src/DiffEngineViewer.Windows/QueueTips.cs b/src/DiffEngineViewer.Windows/QueueTips.cs index 6cd420c4..f1533f64 100644 --- a/src/DiffEngineViewer.Windows/QueueTips.cs +++ b/src/DiffEngineViewer.Windows/QueueTips.cs @@ -58,9 +58,19 @@ public void Apply(Control owner, int queueRow, string? text) /// /// Forgets which row is described, so the next move re-applies. For a new screen, which /// renumbers the rows under a cursor that has not moved, and for the cursor leaving. + /// + /// The caption goes with it. Resetting only the row left the last row's text registered on the + /// whole canvas, and 's own early return then kept it there: a cursor on + /// the canvas but not on a queue row arrives as row -1, which is the row this just set. So the + /// tip popped up over the diff panes, which is the thing this type exists to prevent. + /// /// - public void Forget() => + public void Forget(Control owner) + { row = -1; + tip.Hide(owner); + tip.SetToolTip(owner, null); + } /// /// What would be shown, which is what the tests assert on: the bug this type exists to prevent diff --git a/src/DiffEngineViewer.Windows/ViewerCanvas.cs b/src/DiffEngineViewer.Windows/ViewerCanvas.cs index 2b4e8742..70fb4fe7 100644 --- a/src/DiffEngineViewer.Windows/ViewerCanvas.cs +++ b/src/DiffEngineViewer.Windows/ViewerCanvas.cs @@ -102,7 +102,7 @@ public void Draw(Screen value) { screen = value; // A new screen renumbers the rows, so a kept index would describe a different entry. - tips.Forget(); + tips.Forget(this); Invalidate(); } @@ -498,7 +498,7 @@ protected override void OnMouseLeave(EventArgs e) Cursor = Cursors.Default; } - tips.Forget(); + tips.Forget(this); } protected override void OnMouseWheel(MouseEventArgs e)