From d2521f217a21019fc7455af0320d3db2f088e815 Mon Sep 17 00:00:00 2001 From: Lehonti Ramos <17771375+Lehonti@users.noreply.github.com> Date: Sun, 8 Mar 2026 00:05:15 +0100 Subject: [PATCH 1/4] Fix for #2009 --- Pinta.Tools/Tools/SelectTool.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Pinta.Tools/Tools/SelectTool.cs b/Pinta.Tools/Tools/SelectTool.cs index 577121d9f8..65b6015f2e 100644 --- a/Pinta.Tools/Tools/SelectTool.cs +++ b/Pinta.Tools/Tools/SelectTool.cs @@ -105,7 +105,10 @@ protected override void OnMouseMove (Document document, ToolMouseEventArgs e) protected override void OnMouseUp (Document document, ToolMouseEventArgs e) { - if (handle.HasDragged (e.PointDouble)) { + double x = Math.Round (Math.Clamp (e.PointDouble.X, 0, document.ImageSize.Width)); + double y = Math.Round (Math.Clamp (e.PointDouble.Y, 0, document.ImageSize.Height)); + PointD roundedCoordinates = new (x, y); + if (handle.HasDragged (roundedCoordinates)) { ReDraw (document); SelectionModeHandler.PerformSelectionMode (document, combine_mode, document.Selection.SelectionPolygons); From 7e82c090bea860176665662a6ed6848baeeb288a Mon Sep 17 00:00:00 2001 From: Lehonti Ramos <17771375+Lehonti@users.noreply.github.com> Date: Mon, 9 Mar 2026 16:01:18 +0100 Subject: [PATCH 2/4] Common method for adjusting (rounding) mouse coordinates --- Pinta.Tools/Tools/SelectTool.cs | 38 +++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/Pinta.Tools/Tools/SelectTool.cs b/Pinta.Tools/Tools/SelectTool.cs index 65b6015f2e..e0836d6836 100644 --- a/Pinta.Tools/Tools/SelectTool.cs +++ b/Pinta.Tools/Tools/SelectTool.cs @@ -64,6 +64,13 @@ protected override void OnBuildToolBar (Gtk.Box tb) workspace.SelectionHandler.BuildToolbar (tb, Settings); } + private static PointD AdjustMousePosition (Document document, in PointD position) + { + double x = Math.Round (Math.Clamp (position.X, 0, document.ImageSize.Width)); + double y = Math.Round (Math.Clamp (position.Y, 0, document.ImageSize.Height)); + return new (x, y); + } + protected override void OnMouseDown (Document document, ToolMouseEventArgs e) { // Ignore extra button clicks while drawing @@ -73,20 +80,20 @@ protected override void OnMouseDown (Document document, ToolMouseEventArgs e) hist = new SelectionHistoryItem (workspace, Icon, Name); hist.TakeSnapshot (); - if (!handle.BeginDrag (e.PointDouble, document.ImageSize)) { - // Start drawing a new rectangle. - combine_mode = PintaCore.Workspace.SelectionHandler.DetermineCombineMode (e); + if (handle.BeginDrag (e.PointDouble, document.ImageSize)) + return; - double x = Math.Round (Math.Clamp (e.PointDouble.X, 0, document.ImageSize.Width)); - double y = Math.Round (Math.Clamp (e.PointDouble.Y, 0, document.ImageSize.Height)); - handle.Rectangle = new (x, y, 0.0, 0.0); + // Start drawing a new rectangle. + combine_mode = PintaCore.Workspace.SelectionHandler.DetermineCombineMode (e); - document.PreviousSelection = document.Selection.Clone (); - document.Selection.SelectionPolygons.Clear (); + PointD adjusted = AdjustMousePosition (document, e.PointDouble); + handle.Rectangle = new (adjusted.X, adjusted.Y, 0.0, 0.0); - if (!handle.BeginDrag (new PointD (x, y), document.ImageSize)) - throw new InvalidOperationException ("Should be able to start drawing a new rectangle!"); - } + document.PreviousSelection = document.Selection.Clone (); + document.Selection.SelectionPolygons.Clear (); + + if (!handle.BeginDrag (adjusted, document.ImageSize)) + throw new InvalidOperationException ("Should be able to start drawing a new rectangle!"); } protected override void OnMouseMove (Document document, ToolMouseEventArgs e) @@ -96,7 +103,8 @@ protected override void OnMouseMove (Document document, ToolMouseEventArgs e) return; } - handle.UpdateDrag (e.PointDouble, e.IsShiftPressed); + PointD adjusted = AdjustMousePosition (document, e.PointDouble); + handle.UpdateDrag (adjusted, e.IsShiftPressed); ReDraw (document); @@ -105,10 +113,8 @@ protected override void OnMouseMove (Document document, ToolMouseEventArgs e) protected override void OnMouseUp (Document document, ToolMouseEventArgs e) { - double x = Math.Round (Math.Clamp (e.PointDouble.X, 0, document.ImageSize.Width)); - double y = Math.Round (Math.Clamp (e.PointDouble.Y, 0, document.ImageSize.Height)); - PointD roundedCoordinates = new (x, y); - if (handle.HasDragged (roundedCoordinates)) { + PointD adjusted = AdjustMousePosition (document, e.PointDouble); + if (handle.HasDragged (adjusted)) { ReDraw (document); SelectionModeHandler.PerformSelectionMode (document, combine_mode, document.Selection.SelectionPolygons); From 87e01f7fd510cfecb0524710e8bc3a481d974e17 Mon Sep 17 00:00:00 2001 From: Lehonti Ramos <17771375+Lehonti@users.noreply.github.com> Date: Fri, 11 Sep 2026 02:06:57 +0200 Subject: [PATCH 3/4] Added extra check to prevent committing zero-sized selections --- Pinta.Tools/Tools/SelectTool.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/Pinta.Tools/Tools/SelectTool.cs b/Pinta.Tools/Tools/SelectTool.cs index 8736941686..5a835bb6dc 100644 --- a/Pinta.Tools/Tools/SelectTool.cs +++ b/Pinta.Tools/Tools/SelectTool.cs @@ -26,9 +26,6 @@ using System; using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; -using Gtk; using Pinta.Core; namespace Pinta.Tools; @@ -40,7 +37,7 @@ public abstract class SelectTool : BaseTool private SelectionHistoryItem? hist = default; private CombineMode combine_mode = default; - private Separator? mode_sep; + private Gtk.Separator? mode_sep; private ToolBarDropDownButton? auto_scroll_button; public override Gdk.Key ShortcutKey => new (Gdk.Constants.KEY_S); @@ -145,7 +142,7 @@ protected override void OnMouseMove (Document document, ToolMouseEventArgs e) protected override void OnMouseUp (Document document, ToolMouseEventArgs e) { PointD adjusted = AdjustMousePosition (document, e.PointDouble); - if (handle.HasDragged (adjusted)) { + if (handle.HasDragged (adjusted) && handle.Rectangle.Width > 0 && handle.Rectangle.Height > 0) { ReDraw (document); SelectionModeHandler.PerformSelectionMode (document, combine_mode, document.Selection.SelectionPolygons); @@ -256,7 +253,7 @@ private void LoadFromDocument (Document document) ShowHandles (document.Selection.Visible && tools.CurrentTool == this); } - private Separator Separator => mode_sep ??= GtkExtensions.CreateToolBarSeparator (); + private Gtk.Separator Separator => mode_sep ??= GtkExtensions.CreateToolBarSeparator (); private ToolBarDropDownButton AutoScrollButton { get { From 563d0ed546364deed6cd61021f4008a2eb2ac093 Mon Sep 17 00:00:00 2001 From: Lehonti Ramos <17771375+Lehonti@users.noreply.github.com> Date: Fri, 11 Sep 2026 02:17:45 +0200 Subject: [PATCH 4/4] Sealed `RectangleHandle` --- Pinta.Tools/Handles/RectangleHandle.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Pinta.Tools/Handles/RectangleHandle.cs b/Pinta.Tools/Handles/RectangleHandle.cs index 7468fac47a..e2a7df99dc 100644 --- a/Pinta.Tools/Handles/RectangleHandle.cs +++ b/Pinta.Tools/Handles/RectangleHandle.cs @@ -20,7 +20,7 @@ enum HandlePoint /// /// A handle for specifying a rectangular region. /// -public class RectangleHandle : IToolHandle +public sealed class RectangleHandle : IToolHandle { private readonly IWorkspaceService workspace;