From 1bb39edf977a25624325831f6bbf2bf0b419287b Mon Sep 17 00:00:00 2001
From: Curtis Wensley <curtis.wensley@gmail.com>
Date: Wed, 7 Jun 2023 11:35:48 -0700
Subject: [PATCH] Wpf/WinForms: Release capture if MouseUp event is handled by
 user code

---
 src/Eto.WinForms/Forms/ApplicationHandler.cs | 6 +++++-
 src/Eto.WinForms/Forms/WindowsControl.cs     | 6 +++++-
 src/Eto.Wpf/Forms/WpfFrameworkElement.cs     | 5 +++++
 3 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/src/Eto.WinForms/Forms/ApplicationHandler.cs b/src/Eto.WinForms/Forms/ApplicationHandler.cs
index b23487201e..8d6b97126a 100644
--- a/src/Eto.WinForms/Forms/ApplicationHandler.cs
+++ b/src/Eto.WinForms/Forms/ApplicationHandler.cs
@@ -172,12 +172,16 @@ void SetOptions()
 				}, null, Win32.WM.LBUTTONDBLCLK, Win32.WM.RBUTTONDBLCLK, Win32.WM.MBUTTONDBLCLK);
 				void OnMouseUpHandler(Control c, Control.ICallback cb, MouseEventArgs e)
 				{
-					if (c.Handler is IWindowsControl handler && handler.MouseCaptured)
+					var handler = c.Handler as IWindowsControl;
+					if (handler != null && handler.MouseCaptured)
 					{
 						handler.MouseCaptured = false;
 						handler.ContainerControl.Capture = false;
 					}
 					cb.OnMouseUp(c, e);
+
+					if (handler != null && e.Handled && handler.ContainerControl.Capture)
+						handler.ContainerControl.Capture = false;
 				}
 				
 				bubble.AddBubbleMouseEvent(OnMouseUpHandler, false, Win32.WM.LBUTTONUP, b => MouseButtons.Primary);
diff --git a/src/Eto.WinForms/Forms/WindowsControl.cs b/src/Eto.WinForms/Forms/WindowsControl.cs
index d591971f0f..39591f6445 100644
--- a/src/Eto.WinForms/Forms/WindowsControl.cs
+++ b/src/Eto.WinForms/Forms/WindowsControl.cs
@@ -534,7 +534,11 @@ void HandleMouseUp(Object sender, swf.MouseEventArgs e)
 				MouseCaptured = false;
 				Control.Capture = false;
 			}
-			Callback.OnMouseUp(Widget, e.ToEto(Control));
+			var args = e.ToEto(Control);
+			Callback.OnMouseUp(Widget, args);
+			
+			if (args.Handled && Control.Capture)
+				Control.Capture = false;
 		}
 
 		void HandleMouseMove(Object sender, swf.MouseEventArgs e)
diff --git a/src/Eto.Wpf/Forms/WpfFrameworkElement.cs b/src/Eto.Wpf/Forms/WpfFrameworkElement.cs
index 7a605b96ee..fd2c414ec3 100755
--- a/src/Eto.Wpf/Forms/WpfFrameworkElement.cs
+++ b/src/Eto.Wpf/Forms/WpfFrameworkElement.cs
@@ -821,6 +821,11 @@ protected virtual void HandleMouseUp(object sender, swi.MouseButtonEventArgs e)
 
 			Callback.OnMouseUp(Widget, args);
 			e.Handled = args.Handled;
+			
+			// If the mouse was captured intrinsically we need to release capture otherwise it hangs the app
+			// since the caller is overriding default behaviour.
+			if (e.Handled && Control.IsMouseCaptured)
+				Control.ReleaseMouseCapture();
 		}
 
 		void HandleMouseDoubleClick(object sender, swi.MouseButtonEventArgs e)