From 9c54ee41e5d4e5edc0acd9c6c34ba9dbd4ee120d Mon Sep 17 00:00:00 2001 From: Thomas Nind <31306100+tznind@users.noreply.github.com> Date: Sun, 18 May 2025 23:47:16 +0100 Subject: [PATCH] Fixes 4088 mouse released flag cannot be combined safely with report position (#4091) --- .../UICatalog/Properties/launchSettings.json | 2 +- .../ConsoleDrivers/V2/ConsoleDriverFacade.cs | 7 +++++- .../V2/WindowsInputProcessor.cs | 8 +++++++ .../V2/WindowsInputProcessorTests.cs | 22 +++++++++---------- 4 files changed, 26 insertions(+), 13 deletions(-) diff --git a/Examples/UICatalog/Properties/launchSettings.json b/Examples/UICatalog/Properties/launchSettings.json index 858308a30..609e7cedb 100644 --- a/Examples/UICatalog/Properties/launchSettings.json +++ b/Examples/UICatalog/Properties/launchSettings.json @@ -13,7 +13,7 @@ }, "UICatalog --driver v2win": { "commandName": "Project", - "commandLineArgs": "--driver v2win" + "commandLineArgs": "--driver v2win -dl Trace" }, "UICatalog --driver v2net": { "commandName": "Project", diff --git a/Terminal.Gui/ConsoleDrivers/V2/ConsoleDriverFacade.cs b/Terminal.Gui/ConsoleDrivers/V2/ConsoleDriverFacade.cs index 2cebd145d..2cabb1e56 100644 --- a/Terminal.Gui/ConsoleDrivers/V2/ConsoleDriverFacade.cs +++ b/Terminal.Gui/ConsoleDrivers/V2/ConsoleDriverFacade.cs @@ -1,4 +1,5 @@ using System.Runtime.InteropServices; +using Microsoft.Extensions.Logging; namespace Terminal.Gui; @@ -29,7 +30,11 @@ internal class ConsoleDriverFacade : IConsoleDriver, IConsoleDriverFacade InputProcessor.KeyDown += (s, e) => KeyDown?.Invoke (s, e); InputProcessor.KeyUp += (s, e) => KeyUp?.Invoke (s, e); - InputProcessor.MouseEvent += (s, e) => MouseEvent?.Invoke (s, e); + InputProcessor.MouseEvent += (s, e) => + { + //Logging.Logger.LogTrace ($"Mouse {e.Flags} at x={e.ScreenPosition.X} y={e.ScreenPosition.Y}"); + MouseEvent?.Invoke (s, e); + }; windowSizeMonitor.SizeChanging += (_, e) => SizeChanged?.Invoke (this, e); diff --git a/Terminal.Gui/ConsoleDrivers/V2/WindowsInputProcessor.cs b/Terminal.Gui/ConsoleDrivers/V2/WindowsInputProcessor.cs index da1e81887..b5b588ff8 100644 --- a/Terminal.Gui/ConsoleDrivers/V2/WindowsInputProcessor.cs +++ b/Terminal.Gui/ConsoleDrivers/V2/WindowsInputProcessor.cs @@ -87,6 +87,7 @@ internal class WindowsInputProcessor : InputProcessor mouseFlags = UpdateMouseFlags (mouseFlags, e.ButtonState, ButtonState.Button2Pressed, MouseFlags.Button2Pressed, MouseFlags.Button2Released, 1); mouseFlags = UpdateMouseFlags (mouseFlags, e.ButtonState, ButtonState.Button4Pressed, MouseFlags.Button4Pressed, MouseFlags.Button4Released, 3); + // Deal with button 3 separately because it is considered same as 'rightmost button' if (e.ButtonState.HasFlag (ButtonState.Button3Pressed) || e.ButtonState.HasFlag (ButtonState.RightmostButtonPressed)) { @@ -98,6 +99,10 @@ internal class WindowsInputProcessor : InputProcessor if (_lastWasPressed [2]) { mouseFlags |= MouseFlags.Button3Released; + + // Removes the moved flag when raising released flags (see https://github.com/gui-cs/Terminal.Gui/issues/4088) + mouseFlags &= ~MouseFlags.ReportMousePosition; + _lastWasPressed [2] = false; } } @@ -148,6 +153,9 @@ internal class WindowsInputProcessor : InputProcessor if (_lastWasPressed [buttonIndex]) { current |= releasedFlag; + + // Removes the moved flag when raising released flags (see https://github.com/gui-cs/Terminal.Gui/issues/4088) + current &= ~MouseFlags.ReportMousePosition; _lastWasPressed [buttonIndex] = false; } } diff --git a/Tests/UnitTests/ConsoleDrivers/V2/WindowsInputProcessorTests.cs b/Tests/UnitTests/ConsoleDrivers/V2/WindowsInputProcessorTests.cs index 4103ff4ce..35ba8d615 100644 --- a/Tests/UnitTests/ConsoleDrivers/V2/WindowsInputProcessorTests.cs +++ b/Tests/UnitTests/ConsoleDrivers/V2/WindowsInputProcessorTests.cs @@ -200,7 +200,7 @@ public class WindowsInputProcessorTests new [] { Tuple.Create (ButtonState.Button1Pressed, MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition), - Tuple.Create (ButtonState.NoButtonPressed, MouseFlags.Button1Released | MouseFlags.ReportMousePosition), + Tuple.Create (ButtonState.NoButtonPressed, MouseFlags.Button1Released), Tuple.Create (ButtonState.NoButtonPressed, MouseFlags.ReportMousePosition | MouseFlags.ReportMousePosition) } }; @@ -210,7 +210,7 @@ public class WindowsInputProcessorTests new [] { Tuple.Create (ButtonState.Button2Pressed, MouseFlags.Button2Pressed | MouseFlags.ReportMousePosition), - Tuple.Create (ButtonState.NoButtonPressed, MouseFlags.Button2Released | MouseFlags.ReportMousePosition), + Tuple.Create (ButtonState.NoButtonPressed, MouseFlags.Button2Released), Tuple.Create (ButtonState.NoButtonPressed, MouseFlags.ReportMousePosition | MouseFlags.ReportMousePosition) } }; @@ -220,7 +220,7 @@ public class WindowsInputProcessorTests new [] { Tuple.Create (ButtonState.Button3Pressed, MouseFlags.Button3Pressed | MouseFlags.ReportMousePosition), - Tuple.Create (ButtonState.NoButtonPressed, MouseFlags.Button3Released | MouseFlags.ReportMousePosition), + Tuple.Create (ButtonState.NoButtonPressed, MouseFlags.Button3Released), Tuple.Create (ButtonState.NoButtonPressed, MouseFlags.ReportMousePosition | MouseFlags.ReportMousePosition) } }; @@ -230,7 +230,7 @@ public class WindowsInputProcessorTests new [] { Tuple.Create (ButtonState.Button4Pressed, MouseFlags.Button4Pressed | MouseFlags.ReportMousePosition), - Tuple.Create (ButtonState.NoButtonPressed, MouseFlags.Button4Released | MouseFlags.ReportMousePosition), + Tuple.Create (ButtonState.NoButtonPressed, MouseFlags.Button4Released), Tuple.Create (ButtonState.NoButtonPressed, MouseFlags.ReportMousePosition | MouseFlags.ReportMousePosition) } }; @@ -240,7 +240,7 @@ public class WindowsInputProcessorTests new [] { Tuple.Create (ButtonState.RightmostButtonPressed, MouseFlags.Button3Pressed | MouseFlags.ReportMousePosition), - Tuple.Create (ButtonState.NoButtonPressed, MouseFlags.Button3Released | MouseFlags.ReportMousePosition), + Tuple.Create (ButtonState.NoButtonPressed, MouseFlags.Button3Released), Tuple.Create (ButtonState.NoButtonPressed, MouseFlags.ReportMousePosition | MouseFlags.ReportMousePosition) } }; @@ -253,8 +253,8 @@ public class WindowsInputProcessorTests Tuple.Create ( ButtonState.Button1Pressed | ButtonState.Button2Pressed, MouseFlags.Button1Pressed | MouseFlags.Button2Pressed | MouseFlags.ReportMousePosition), - Tuple.Create (ButtonState.Button1Pressed, MouseFlags.Button1Pressed | MouseFlags.Button2Released | MouseFlags.ReportMousePosition), - Tuple.Create (ButtonState.NoButtonPressed, MouseFlags.Button1Released | MouseFlags.ReportMousePosition), + Tuple.Create (ButtonState.Button1Pressed, MouseFlags.Button1Pressed | MouseFlags.Button2Released), + Tuple.Create (ButtonState.NoButtonPressed, MouseFlags.Button1Released), Tuple.Create (ButtonState.NoButtonPressed, MouseFlags.ReportMousePosition) } }; @@ -266,8 +266,8 @@ public class WindowsInputProcessorTests Tuple.Create ( ButtonState.Button3Pressed | ButtonState.Button4Pressed, MouseFlags.Button3Pressed | MouseFlags.Button4Pressed | MouseFlags.ReportMousePosition), - Tuple.Create (ButtonState.Button3Pressed, MouseFlags.Button3Pressed | MouseFlags.Button4Released | MouseFlags.ReportMousePosition), - Tuple.Create (ButtonState.NoButtonPressed, MouseFlags.Button3Released | MouseFlags.ReportMousePosition), + Tuple.Create (ButtonState.Button3Pressed, MouseFlags.Button3Pressed | MouseFlags.Button4Released), + Tuple.Create (ButtonState.NoButtonPressed, MouseFlags.Button3Released), Tuple.Create (ButtonState.NoButtonPressed, MouseFlags.ReportMousePosition) } }; @@ -280,7 +280,7 @@ public class WindowsInputProcessorTests Tuple.Create ( ButtonState.Button1Pressed | ButtonState.Button2Pressed, MouseFlags.Button1Pressed | MouseFlags.Button2Pressed | MouseFlags.ReportMousePosition), - Tuple.Create (ButtonState.NoButtonPressed, MouseFlags.Button1Released | MouseFlags.Button2Released | MouseFlags.ReportMousePosition), + Tuple.Create (ButtonState.NoButtonPressed, MouseFlags.Button1Released | MouseFlags.Button2Released), Tuple.Create (ButtonState.NoButtonPressed, MouseFlags.ReportMousePosition) } }; @@ -297,7 +297,7 @@ public class WindowsInputProcessorTests Tuple.Create (ButtonState.RightmostButtonPressed, MouseFlags.Button3Pressed | MouseFlags.ReportMousePosition), // Now with neither we get released - Tuple.Create (ButtonState.NoButtonPressed, MouseFlags.Button3Released | MouseFlags.ReportMousePosition), + Tuple.Create (ButtonState.NoButtonPressed, MouseFlags.Button3Released), Tuple.Create (ButtonState.NoButtonPressed, MouseFlags.ReportMousePosition) } };