Przeglądaj źródła

fix(Win32): PopupImpl memory leak (#16890)

* fix: PopupImpl memory leak

* fix: Address review

* fix: Address review

---------

Co-authored-by: Max Katz <[email protected]>
workgroupengineering 1 rok temu
rodzic
commit
182e3f9cfd

+ 1 - 2
src/Avalonia.Controls/TopLevel.cs

@@ -23,7 +23,6 @@ using Avalonia.Utilities;
 using Avalonia.Input.Platform;
 using System.Linq;
 using System.Threading.Tasks;
-using Avalonia.Metadata;
 using Avalonia.Rendering.Composition;
 using Avalonia.Threading;
 
@@ -220,7 +219,7 @@ namespace Avalonia.Controls
             _globalStyles = TryGetService<IGlobalStyles>(dependencyResolver);
             _applicationThemeHost = TryGetService<IThemeVariantHost>(dependencyResolver);
 
-            Renderer = new CompositingRenderer(this, impl.Compositor, () => impl.Surfaces);
+            Renderer = new CompositingRenderer(this, impl.Compositor, () => PlatformImpl.Surfaces ?? []);
             Renderer.SceneInvalidated += SceneInvalidated;
 
             impl.SetInputRoot(this);

+ 8 - 1
src/Windows/Avalonia.Win32/Input/WindowsInputPane.cs

@@ -18,9 +18,10 @@ internal unsafe class WindowsInputPane : InputPaneBase, IDisposable
     // GUID: 5752238B-24F0-495A-82F1-2FD593056796
     private static readonly Guid SID_IFrameworkInputPane  = new(0x5752238B, 0x24F0, 0x495A, 0x82, 0xF1, 0x2F, 0xD5, 0x93, 0x05, 0x67, 0x96);
 
-    private readonly WindowImpl _windowImpl;
+    private WindowImpl _windowImpl;
     private IFrameworkInputPane? _inputPane;
     private readonly uint _cookie;
+    private bool _disposed;
 
     private WindowsInputPane(WindowImpl windowImpl)
     {
@@ -72,6 +73,10 @@ internal unsafe class WindowsInputPane : InputPaneBase, IDisposable
 
     public void Dispose()
     {
+        if (_disposed)
+            return; 
+        _disposed = true;
+        _windowImpl = null!;
         if (_inputPane is not null)
         {
             if (_cookie != 0)
@@ -82,6 +87,8 @@ internal unsafe class WindowsInputPane : InputPaneBase, IDisposable
             _inputPane.Dispose();
             _inputPane = null;
         }
+        // Suppress finalization.
+        GC.SuppressFinalize(this);
     }
 
     private class Handler : CallbackBase, IFrameworkInputPaneHandler

+ 3 - 4
src/Windows/Avalonia.Win32/WindowImpl.cs

@@ -20,13 +20,10 @@ using Avalonia.Win32.Input;
 using Avalonia.Win32.Interop;
 using Avalonia.Win32.OpenGl;
 using Avalonia.Win32.OpenGl.Angle;
-using Avalonia.Win32.WinRT;
 using Avalonia.Win32.WinRT.Composition;
 using static Avalonia.Win32.Interop.UnmanagedMethods;
-using System.Diagnostics;
 using Avalonia.Platform.Storage.FileIO;
 using Avalonia.Threading;
-using static Avalonia.Controls.Platform.IWin32OptionsTopLevelImpl;
 using static Avalonia.Controls.Win32Properties;
 using Avalonia.Logging;
 
@@ -83,7 +80,7 @@ namespace Avalonia.Win32
 
         private readonly Win32NativeControlHost _nativeControlHost;
         private readonly IStorageProvider _storageProvider;
-        private readonly WindowsInputPane? _inputPane;
+        private WindowsInputPane? _inputPane;
         private WndProc _wndProcDelegate;
         private string? _className;
         private IntPtr _hwnd;
@@ -613,6 +610,8 @@ namespace Avalonia.Win32
 
         public void Dispose()
         {
+            _inputPane?.Dispose();
+            _inputPane = null;
             if (_hwnd != IntPtr.Zero)
             {
                 // Detect if we are being closed programmatically - this would mean that WM_CLOSE was not called