diff --git a/src/Avalonia.Controls/Primitives/Popup.cs b/src/Avalonia.Controls/Primitives/Popup.cs index f6d54b9546..6de5b1ea78 100644 --- a/src/Avalonia.Controls/Primitives/Popup.cs +++ b/src/Avalonia.Controls/Primitives/Popup.cs @@ -536,6 +536,16 @@ namespace Avalonia.Controls.Primitives (x, handler) => x.Closed -= handler).DisposeWith(handlerCleanup); } } + else if (topLevel is { } wtl && wtl.PlatformImpl is IWindowBaseImpl wimpl) + { + SubscribeToEventHandler(wimpl, TopLevelLostPlatformFocus, + (x, handler) => x.LostFocus += handler, + (x, handler) => x.LostFocus -= handler).DisposeWith(handlerCleanup); + + SubscribeToEventHandler(wimpl, WindowBaseDeactivated, + (x, handler) => x.Deactivated += handler, + (x, handler) => x.Deactivated -= handler).DisposeWith(handlerCleanup); + } else if (topLevel is { } tl && tl.PlatformImpl is ITopLevelImpl pimpl) { SubscribeToEventHandler(pimpl, TopLevelLostPlatformFocus, @@ -987,6 +997,14 @@ namespace Avalonia.Controls.Primitives } } + private void WindowBaseDeactivated() + { + if (IsLightDismissEnabled) + { + Close(); + } + } + private void ParentClosed(object? sender, EventArgs e) { if (IsLightDismissEnabled) diff --git a/src/Windows/Avalonia.Win32.Interoperability/WinForms/WinFormsAvaloniaControlHost.cs b/src/Windows/Avalonia.Win32.Interoperability/WinForms/WinFormsAvaloniaControlHost.cs index 44e9c85d2e..38d0b134f1 100644 --- a/src/Windows/Avalonia.Win32.Interoperability/WinForms/WinFormsAvaloniaControlHost.cs +++ b/src/Windows/Avalonia.Win32.Interoperability/WinForms/WinFormsAvaloniaControlHost.cs @@ -14,7 +14,7 @@ namespace Avalonia.Win32.Interoperability; /// An element that allows you to host a Avalonia control on a Windows Forms page. /// [ToolboxItem(true)] -public class WinFormsAvaloniaControlHost : WinFormsControl +public class WinFormsAvaloniaControlHost : WinFormsControl, IMessageFilter { private AvControl? _content; private EmbeddableControlRoot? _root; @@ -66,11 +66,14 @@ public class WinFormsAvaloniaControlHost : WinFormsControl } base.OnHandleCreated(e); + + System.Windows.Forms.Application.AddMessageFilter(this); } /// protected override void OnHandleDestroyed(EventArgs e) { + System.Windows.Forms.Application.RemoveMessageFilter(this); _root?.StopRendering(); _root?.Dispose(); _root = null; @@ -135,4 +138,26 @@ public class WinFormsAvaloniaControlHost : WinFormsControl e.Graphics.DrawString(message, Font, SystemBrushes.ControlText, messageArea); } } + + public bool PreFilterMessage(ref Message m) + { + var message = (UnmanagedMethods.WindowsMessage)m.Msg; + + switch (message) + { + case UnmanagedMethods.WindowsMessage.WM_LBUTTONDOWN: + case UnmanagedMethods.WindowsMessage.WM_MBUTTONDOWN: + case UnmanagedMethods.WindowsMessage.WM_RBUTTONDOWN: + case UnmanagedMethods.WindowsMessage.WM_NCLBUTTONDOWN: + case UnmanagedMethods.WindowsMessage.WM_NCMBUTTONDOWN: + case UnmanagedMethods.WindowsMessage.WM_NCRBUTTONDOWN: + if (_root?.PlatformImpl is WindowImpl impl && !impl.IsOurWindow(m.HWnd)) + { + impl.Deactivated?.Invoke(); + } + break; + } + + return false; + } } diff --git a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs index 662f07623e..4e2872b387 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs @@ -900,7 +900,7 @@ namespace Avalonia.Win32 return DefWindowProc(hWnd, msg, wParam, lParam); } - private bool IsOurWindow(IntPtr hwnd) + internal bool IsOurWindow(IntPtr hwnd) { if (hwnd == IntPtr.Zero) return false;