diff --git a/build/SourceLink.props b/build/SourceLink.props
index 1e007e01eb..9f05848881 100644
--- a/build/SourceLink.props
+++ b/build/SourceLink.props
@@ -3,7 +3,6 @@
true
false
true
- embedded
$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb
@@ -15,6 +14,10 @@
true
+
+ embedded
+
+
diff --git a/src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs b/src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs
index a2bdcd1ea8..18348571bf 100644
--- a/src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs
+++ b/src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs
@@ -101,7 +101,7 @@ namespace Avalonia.Controls.Platform
root.Deactivated -= WindowDeactivated;
}
- if (_root is TopLevel tl)
+ if (_root is TopLevel tl && tl.PlatformImpl != null)
tl.PlatformImpl.LostFocus -= TopLevelLostPlatformFocus;
_inputManagerSubscription?.Dispose();
diff --git a/src/Avalonia.Controls/Primitives/PopupRoot.cs b/src/Avalonia.Controls/Primitives/PopupRoot.cs
index 1a11778db2..c59c7c11d9 100644
--- a/src/Avalonia.Controls/Primitives/PopupRoot.cs
+++ b/src/Avalonia.Controls/Primitives/PopupRoot.cs
@@ -44,7 +44,7 @@ namespace Avalonia.Controls.Primitives
/// The dependency resolver to use. If null the default dependency resolver will be used.
///
public PopupRoot(TopLevel parent, IPopupImpl impl, IAvaloniaDependencyResolver dependencyResolver)
- : base(impl, dependencyResolver)
+ : base(ValidatingPopupImpl.Wrap(impl), dependencyResolver)
{
_parent = parent;
}
diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs
index eaee5bdb50..9eb35e0548 100644
--- a/src/Avalonia.Controls/TopLevel.cs
+++ b/src/Avalonia.Controls/TopLevel.cs
@@ -134,6 +134,8 @@ namespace Avalonia.Controls
"Could not create window implementation: maybe no windowing subsystem was initialized?");
}
+ impl = ValidatingToplevelImpl.Wrap(impl);
+
PlatformImpl = impl;
_actualTransparencyLevel = PlatformImpl.TransparencyLevel;
@@ -367,14 +369,15 @@ namespace Avalonia.Controls
Renderer?.Dispose();
Renderer = null;
+ (this as IInputRoot).MouseDevice?.TopLevelClosed(this);
+ PlatformImpl = null;
+
var logicalArgs = new LogicalTreeAttachmentEventArgs(this, this, null);
((ILogical)this).NotifyDetachedFromLogicalTree(logicalArgs);
var visualArgs = new VisualTreeAttachmentEventArgs(this, this);
OnDetachedFromVisualTreeCore(visualArgs);
-
- (this as IInputRoot).MouseDevice?.TopLevelClosed(this);
- PlatformImpl = null;
+
OnClosed(EventArgs.Empty);
LayoutManager?.Dispose();
diff --git a/src/Avalonia.Controls/ValidatingToplevel.cs b/src/Avalonia.Controls/ValidatingToplevel.cs
new file mode 100644
index 0000000000..97792a9c87
--- /dev/null
+++ b/src/Avalonia.Controls/ValidatingToplevel.cs
@@ -0,0 +1,326 @@
+using System;
+using System.Collections.Generic;
+using Avalonia.Controls.Platform;
+using Avalonia.Controls.Primitives.PopupPositioning;
+using Avalonia.Input;
+using Avalonia.Input.Raw;
+using Avalonia.Input.TextInput;
+using Avalonia.Platform;
+using Avalonia.Rendering;
+
+namespace Avalonia.Controls;
+
+internal class ValidatingToplevelImpl : ITopLevelImpl, ITopLevelImplWithNativeControlHost,
+ ITopLevelImplWithNativeMenuExporter, ITopLevelImplWithTextInputMethod
+{
+ private readonly ITopLevelImpl _impl;
+ private bool _disposed;
+
+ public ValidatingToplevelImpl(ITopLevelImpl impl)
+ {
+ _impl = impl ?? throw new InvalidOperationException(
+ "Could not create TopLevel implementation: maybe no windowing subsystem was initialized?");
+ }
+
+ public void Dispose()
+ {
+ _disposed = true;
+ _impl.Dispose();
+ }
+
+ protected void CheckDisposed()
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(_impl.GetType().FullName);
+ }
+
+ protected ITopLevelImpl Inner
+ {
+ get
+ {
+ CheckDisposed();
+ return _impl;
+ }
+ }
+
+ public static ITopLevelImpl Wrap(ITopLevelImpl impl)
+ {
+#if DEBUG
+ if (impl is ValidatingToplevelImpl)
+ return impl;
+ return new ValidatingToplevelImpl(impl);
+#else
+ return impl;
+#endif
+ }
+
+ public Size ClientSize => Inner.ClientSize;
+ public Size? FrameSize => Inner.FrameSize;
+ public double RenderScaling => Inner.RenderScaling;
+ public IEnumerable