diff --git a/src/Avalonia.MicroCom/CallbackBase.cs b/src/Avalonia.MicroCom/CallbackBase.cs new file mode 100644 index 0000000000..6783ebe3dc --- /dev/null +++ b/src/Avalonia.MicroCom/CallbackBase.cs @@ -0,0 +1,53 @@ +namespace Avalonia.MicroCom +{ + public abstract class CallbackBase : IUnknown, IMicroComShadowContainer + { + private readonly object _lock = new object(); + private bool _referencedFromManaged = true; + private bool _referencedFromNative = false; + private bool _destroyed; + + public bool IsDestroyed => _destroyed; + + protected virtual void Destroyed() + { + + } + + public void Dispose() + { + lock (_lock) + { + _referencedFromManaged = false; + DestroyIfNeeded(); + } + } + + void DestroyIfNeeded() + { + if(_destroyed) + return; + if (_referencedFromManaged == false && _referencedFromNative == false) + { + _destroyed = true; + Destroyed(); + } + } + + public MicroComShadow Shadow { get; set; } + public void OnReferencedFromNative() + { + lock (_lock) + _referencedFromNative = true; + } + + public void OnUnreferencedFromNative() + { + lock (_lock) + { + _referencedFromNative = false; + DestroyIfNeeded(); + } + } + } +} diff --git a/src/Avalonia.Native/AvaloniaNativeApplicationPlatform.cs b/src/Avalonia.Native/AvaloniaNativeApplicationPlatform.cs index 8084e06d28..ae24d06bad 100644 --- a/src/Avalonia.Native/AvaloniaNativeApplicationPlatform.cs +++ b/src/Avalonia.Native/AvaloniaNativeApplicationPlatform.cs @@ -6,7 +6,7 @@ using Avalonia.Platform; namespace Avalonia.Native { - internal class AvaloniaNativeApplicationPlatform : CallbackBase, IAvnApplicationEvents, IPlatformLifetimeEventsImpl + internal class AvaloniaNativeApplicationPlatform : NativeCallbackBase, IAvnApplicationEvents, IPlatformLifetimeEventsImpl { public event EventHandler ShutdownRequested; diff --git a/src/Avalonia.Native/AvaloniaNativeDragSource.cs b/src/Avalonia.Native/AvaloniaNativeDragSource.cs index 80d54d8a10..f91a299b3b 100644 --- a/src/Avalonia.Native/AvaloniaNativeDragSource.cs +++ b/src/Avalonia.Native/AvaloniaNativeDragSource.cs @@ -30,7 +30,7 @@ namespace Avalonia.Native return visual.VisualRoot as TopLevel; } - class DndCallback : CallbackBase, IAvnDndResultCallback + class DndCallback : NativeCallbackBase, IAvnDndResultCallback { private TaskCompletionSource _tcs; diff --git a/src/Avalonia.Native/AvaloniaNativePlatform.cs b/src/Avalonia.Native/AvaloniaNativePlatform.cs index 1eadf70b13..4802fed554 100644 --- a/src/Avalonia.Native/AvaloniaNativePlatform.cs +++ b/src/Avalonia.Native/AvaloniaNativePlatform.cs @@ -79,7 +79,7 @@ namespace Avalonia.Native _factory = factory; } - class GCHandleDeallocator : CallbackBase, IAvnGCHandleDeallocatorCallback + class GCHandleDeallocator : NativeCallbackBase, IAvnGCHandleDeallocatorCallback { public void FreeGCHandle(IntPtr handle) { diff --git a/src/Avalonia.Native/CallbackBase.cs b/src/Avalonia.Native/CallbackBase.cs index 455ed4b159..56f9505cb4 100644 --- a/src/Avalonia.Native/CallbackBase.cs +++ b/src/Avalonia.Native/CallbackBase.cs @@ -5,19 +5,8 @@ using Avalonia.Platform; namespace Avalonia.Native { - public class CallbackBase : IUnknown, IMicroComShadowContainer, IMicroComExceptionCallback + public abstract class NativeCallbackBase : CallbackBase, IMicroComExceptionCallback { - private readonly object _lock = new object(); - private bool _referencedFromManaged = true; - private bool _referencedFromNative = false; - private bool _destroyed; - - - protected virtual void Destroyed() - { - - } - public void RaiseException(Exception e) { if (AvaloniaLocator.Current.GetService() is PlatformThreadingInterface threadingInterface) @@ -27,41 +16,5 @@ namespace Avalonia.Native threadingInterface.DispatchException(ExceptionDispatchInfo.Capture(e)); } } - - public void Dispose() - { - lock (_lock) - { - _referencedFromManaged = false; - DestroyIfNeeded(); - } - } - - void DestroyIfNeeded() - { - if(_destroyed) - return; - if (_referencedFromManaged == false && _referencedFromNative == false) - { - _destroyed = true; - Destroyed(); - } - } - - public MicroComShadow Shadow { get; set; } - public void OnReferencedFromNative() - { - lock (_lock) - _referencedFromNative = true; - } - - public void OnUnreferencedFromNative() - { - lock (_lock) - { - _referencedFromNative = false; - DestroyIfNeeded(); - } - } } } diff --git a/src/Avalonia.Native/DeferredFramebuffer.cs b/src/Avalonia.Native/DeferredFramebuffer.cs index 950b6a3197..4e0c037154 100644 --- a/src/Avalonia.Native/DeferredFramebuffer.cs +++ b/src/Avalonia.Native/DeferredFramebuffer.cs @@ -27,7 +27,7 @@ namespace Avalonia.Native public Vector Dpi { get; set; } public PixelFormat Format { get; set; } - class Disposer : CallbackBase + class Disposer : NativeCallbackBase { private IntPtr _ptr; diff --git a/src/Avalonia.Native/IAvnMenu.cs b/src/Avalonia.Native/IAvnMenu.cs index 0e6fdd2df0..e413023f6d 100644 --- a/src/Avalonia.Native/IAvnMenu.cs +++ b/src/Avalonia.Native/IAvnMenu.cs @@ -7,7 +7,7 @@ using Avalonia.Platform.Interop; namespace Avalonia.Native.Interop { - class MenuEvents : CallbackBase, IAvnMenuEvents + class MenuEvents : NativeCallbackBase, IAvnMenuEvents { private IAvnMenu _parent; diff --git a/src/Avalonia.Native/MenuActionCallback.cs b/src/Avalonia.Native/MenuActionCallback.cs index 5318195f30..3acbb9c19c 100644 --- a/src/Avalonia.Native/MenuActionCallback.cs +++ b/src/Avalonia.Native/MenuActionCallback.cs @@ -3,7 +3,7 @@ using Avalonia.Native.Interop; namespace Avalonia.Native { - public class MenuActionCallback : CallbackBase, IAvnActionCallback + public class MenuActionCallback : NativeCallbackBase, IAvnActionCallback { private Action _action; diff --git a/src/Avalonia.Native/PlatformThreadingInterface.cs b/src/Avalonia.Native/PlatformThreadingInterface.cs index 882d5a2ed3..99aa8a5850 100644 --- a/src/Avalonia.Native/PlatformThreadingInterface.cs +++ b/src/Avalonia.Native/PlatformThreadingInterface.cs @@ -9,7 +9,7 @@ namespace Avalonia.Native { internal class PlatformThreadingInterface : IPlatformThreadingInterface { - class TimerCallback : CallbackBase, IAvnActionCallback + class TimerCallback : NativeCallbackBase, IAvnActionCallback { readonly Action _tick; @@ -24,7 +24,7 @@ namespace Avalonia.Native } } - class SignaledCallback : CallbackBase, IAvnSignaledCallback + class SignaledCallback : NativeCallbackBase, IAvnSignaledCallback { readonly PlatformThreadingInterface _parent; diff --git a/src/Avalonia.Native/PredicateCallback.cs b/src/Avalonia.Native/PredicateCallback.cs index 19c470bcb3..dbb65791f0 100644 --- a/src/Avalonia.Native/PredicateCallback.cs +++ b/src/Avalonia.Native/PredicateCallback.cs @@ -3,7 +3,7 @@ using Avalonia.Native.Interop; namespace Avalonia.Native { - public class PredicateCallback : CallbackBase, IAvnPredicateCallback + public class PredicateCallback : NativeCallbackBase, IAvnPredicateCallback { private Func _predicate; diff --git a/src/Avalonia.Native/SystemDialogs.cs b/src/Avalonia.Native/SystemDialogs.cs index 8012813644..4372829df1 100644 --- a/src/Avalonia.Native/SystemDialogs.cs +++ b/src/Avalonia.Native/SystemDialogs.cs @@ -62,7 +62,7 @@ namespace Avalonia.Native } } - internal unsafe class SystemDialogEvents : CallbackBase, IAvnSystemDialogEvents + internal unsafe class SystemDialogEvents : NativeCallbackBase, IAvnSystemDialogEvents { private TaskCompletionSource _tcs; diff --git a/src/Avalonia.Native/WindowImplBase.cs b/src/Avalonia.Native/WindowImplBase.cs index 1917b1575d..eba58c2f85 100644 --- a/src/Avalonia.Native/WindowImplBase.cs +++ b/src/Avalonia.Native/WindowImplBase.cs @@ -151,7 +151,7 @@ namespace Avalonia.Native public IMouseDevice MouseDevice => _mouse; public abstract IPopupImpl CreatePopup(); - protected unsafe class WindowBaseEvents : CallbackBase, IAvnWindowBaseEvents + protected unsafe class WindowBaseEvents : NativeCallbackBase, IAvnWindowBaseEvents { private readonly WindowBaseImpl _parent; diff --git a/src/Windows/Avalonia.Win32/DataObject.cs b/src/Windows/Avalonia.Win32/DataObject.cs index ac603f60eb..69ef3d5e76 100644 --- a/src/Windows/Avalonia.Win32/DataObject.cs +++ b/src/Windows/Avalonia.Win32/DataObject.cs @@ -49,18 +49,16 @@ namespace Avalonia.Win32 } } - internal class DataObject : IDisposableDataObject, Win32Com.IAvnDataObject, IMicroComShadowContainer + internal class DataObject : CallbackBase, IDisposableDataObject, Win32Com.IAvnDataObject { // Compatibility with WinForms + WPF... internal static readonly byte[] SerializedObjectGUID = new Guid("FD9EA796-3B13-4370-A679-56106BB288FB").ToByteArray(); - class FormatEnumerator : Win32Com.IEnumFORMATETC, IMicroComShadowContainer + class FormatEnumerator : CallbackBase, Win32Com.IEnumFORMATETC { private FORMATETC[] _formats; private uint _current; - public MicroComShadow Shadow { get; set; } - private FormatEnumerator(FORMATETC[] formats, uint current) { _formats = formats; @@ -76,7 +74,7 @@ namespace Avalonia.Win32 private FORMATETC ConvertToFormatEtc(string aFormatName) { FORMATETC result = default(FORMATETC); - result.cfFormat = (ushort)ClipboardFormats.GetFormat(aFormatName); + result.cfFormat = ClipboardFormats.GetFormat(aFormatName); result.dwAspect = DVASPECT.DVASPECT_CONTENT; result.ptd = IntPtr.Zero; result.lindex = -1; @@ -123,18 +121,6 @@ namespace Avalonia.Win32 { return new FormatEnumerator(_formats, _current); } - - public void Dispose() - { - } - - public void OnReferencedFromNative() - { - } - - public void OnUnreferencedFromNative() - { - } } private const uint DV_E_TYMED = 0x80040069; @@ -149,8 +135,6 @@ namespace Avalonia.Win32 IDataObject _wrapped; - public MicroComShadow Shadow { get; set; } - public DataObject(IDataObject wrapped) { if (_wrapped is DataObject || _wrapped is OleDataObject) @@ -426,18 +410,10 @@ namespace Avalonia.Win32 } } - public void Dispose() - { - } - - public void OnReferencedFromNative() + protected override void Destroyed() { + base.Destroyed(); } - - public void OnUnreferencedFromNative() - { - } - #endregion } } diff --git a/src/Windows/Avalonia.Win32/OleDragSource.cs b/src/Windows/Avalonia.Win32/OleDragSource.cs index dc5c561226..30503339da 100644 --- a/src/Windows/Avalonia.Win32/OleDragSource.cs +++ b/src/Windows/Avalonia.Win32/OleDragSource.cs @@ -6,7 +6,7 @@ using Avalonia.Win32.Win32Com; namespace Avalonia.Win32 { - internal class OleDragSource : IDropSource, IMicroComShadowContainer + internal class OleDragSource : CallbackBase, IDropSource { private const int DRAGDROP_S_USEDEFAULTCURSORS = 0x00040102; private const int DRAGDROP_S_DROP = 0x00040100; @@ -18,8 +18,6 @@ namespace Avalonia.Win32 (int)UnmanagedMethods.ModifierKeys.MK_RBUTTON }; - public MicroComShadow Shadow { get; set; } - public int QueryContinueDrag(int fEscapePressed, int grfKeyState) { if (fEscapePressed != 0) @@ -39,17 +37,5 @@ namespace Avalonia.Win32 { return DRAGDROP_S_USEDEFAULTCURSORS; } - - public void Dispose() - { - } - - public void OnReferencedFromNative() - { - } - - public void OnUnreferencedFromNative() - { - } } } diff --git a/src/Windows/Avalonia.Win32/OleDropTarget.cs b/src/Windows/Avalonia.Win32/OleDropTarget.cs index e20877e87c..dbcac124ee 100644 --- a/src/Windows/Avalonia.Win32/OleDropTarget.cs +++ b/src/Windows/Avalonia.Win32/OleDropTarget.cs @@ -7,7 +7,7 @@ using DropEffect = Avalonia.Win32.Win32Com.DropEffect; namespace Avalonia.Win32 { - internal class OleDropTarget : Win32Com.IDropTarget, IMicroComShadowContainer + internal class OleDropTarget : CallbackBase, Win32Com.IDropTarget { private readonly IInputRoot _target; private readonly ITopLevelImpl _tl; @@ -15,8 +15,6 @@ namespace Avalonia.Win32 private IDisposableDataObject _currentDrag = null; - public MicroComShadow Shadow { get; set; } - public OleDropTarget(ITopLevelImpl tl, IInputRoot target) { _dragDevice = AvaloniaLocator.Current.GetService(); @@ -180,17 +178,9 @@ namespace Avalonia.Win32 return _target.PointToClient(screenPt); } - public void Dispose() + protected override void Destroyed() { _currentDrag?.Dispose(); } - - public void OnReferencedFromNative() - { - } - - public void OnUnreferencedFromNative() - { - } } }