diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/PopupControlService.cs b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/PopupControlService.cs index 952fa101ade..1d51ae30aa3 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/PopupControlService.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/PopupControlService.cs @@ -330,7 +330,7 @@ private void BeginShowToolTip(DependencyObject o, ToolTipService.TriggerAction t switch (triggerAction) { case ToolTipService.TriggerAction.Mouse: - if (SafeArea != null) + if (HasValidSafeArea) { // the mouse has moved over a tooltip owner o, while still // within the safe area of the current tooltip (which must be from mouse). @@ -909,8 +909,8 @@ private void SetSafeArea(ToolTip tooltip) private bool MouseHasLeftSafeArea() { - // if there is no SafeArea, the mouse didn't leave it - if (SafeArea == null) + // if there is no valid SafeArea, the mouse didn't leave it + if (!HasValidSafeArea) return false; // if the current tooltip's owner is no longer being displayed, the safe area is no longer valid @@ -926,6 +926,17 @@ private bool MouseHasLeftSafeArea() private ConvexHull SafeArea { get; set; } + private bool HasValidSafeArea + { + get + { + // There are plenty of Watsons which indicate that source might get disposed + // (i.e. underlying HWND gets destroyed) while we are still holding on it. + // If such a case treat it as if there is no valid safe area. + return SafeArea != null && SafeArea.IsValid; + } + } + #endregion #endregion @@ -1374,6 +1385,8 @@ internal ConvexHull(PresentationSource source, List rects) } } + internal bool IsValid => !_source.IsDisposed; + // sort by y (and by x among equal y's) private void SortPoints(PointList points) {