| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 | 
							- using System;
 
- using System.Collections.Generic;
 
- using System.Diagnostics;
 
- using Avalonia.Controls.Platform;
 
- using Avalonia.Platform;
 
- using Avalonia.Threading;
 
- using Avalonia.VisualTree;
 
- namespace Avalonia.Controls
 
- {
 
-     public class NativeControlHost : Control
 
-     {
 
-         private TopLevel? _currentRoot;
 
-         private INativeControlHostImpl? _currentHost;
 
-         private INativeControlHostControlTopLevelAttachment? _attachment;
 
-         private IPlatformHandle? _nativeControlHandle;
 
-         private bool _queuedForDestruction;
 
-         private bool _queuedForMoveResize;
 
-         private readonly List<Visual> _propertyChangedSubscriptions = new List<Visual>();
 
-         protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
 
-         {
 
-             _currentRoot = e.Root as TopLevel;
 
-             var visual = (Visual)this;
 
-             while (visual != null)
 
-             {
 
-                 if (visual is Visual v)
 
-                 {
 
-                     v.PropertyChanged += PropertyChangedHandler;
 
-                     _propertyChangedSubscriptions.Add(v);
 
-                 }
 
-                 visual = visual.GetVisualParent();
 
-             }
 
-             UpdateHost();
 
-         }
 
-         private void PropertyChangedHandler(object? sender, AvaloniaPropertyChangedEventArgs e)
 
-         {
 
-             if (e.IsEffectiveValueChange && (e.Property == BoundsProperty || e.Property == IsVisibleProperty))
 
-                 EnqueueForMoveResize();
 
-         }
 
-         protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
 
-         {
 
-             _currentRoot = null;
 
-             if (_propertyChangedSubscriptions != null)
 
-             {
 
-                 foreach (var v in _propertyChangedSubscriptions)
 
-                     v.PropertyChanged -= PropertyChangedHandler;
 
-                 _propertyChangedSubscriptions.Clear();
 
-             }
 
-             UpdateHost();
 
-         }
 
-         private void UpdateHost()
 
-         {
 
-             _queuedForMoveResize = false;
 
-             _currentHost = _currentRoot?.PlatformImpl?.TryGetFeature<INativeControlHostImpl>();
 
-             
 
-             if (_currentHost != null)
 
-             {
 
-                 // If there is an existing attachment, ensure that we are attached to the proper host or destroy the attachment
 
-                 if (_attachment != null && _attachment.AttachedTo != _currentHost)
 
-                 {
 
-                     if (_attachment != null)
 
-                     {
 
-                         if (_attachment.IsCompatibleWith(_currentHost))
 
-                         {
 
-                             _attachment.AttachedTo = _currentHost;
 
-                         }
 
-                         else
 
-                         {
 
-                             _attachment.Dispose();
 
-                             _attachment = null;
 
-                         }
 
-                     }
 
-                 }
 
-                 // If there is no attachment, but the control exists,
 
-                 // attempt to attach to to the current toplevel or destroy the control if it's incompatible
 
-                 if (_attachment == null && _nativeControlHandle != null)
 
-                 {
 
-                     if (_currentHost.IsCompatibleWith(_nativeControlHandle))
 
-                         _attachment = _currentHost.CreateNewAttachment(_nativeControlHandle);
 
-                     else
 
-                         DestroyNativeControl();
 
-                 }
 
-                 // There is no control handle an no attachment, create both
 
-                 if (_nativeControlHandle == null)
 
-                 {
 
-                     _attachment = _currentHost.CreateNewAttachment(parent =>
 
-                         _nativeControlHandle = CreateNativeControlCore(parent));
 
-                 }
 
-             }
 
-             else
 
-             {
 
-                 // Immediately detach the control from the current toplevel if there is an existing attachment
 
-                 if (_attachment != null)
 
-                     _attachment.AttachedTo = null;
 
-                 
 
-                 // Don't destroy the control immediately, it might be just being reparented to another TopLevel
 
-                 if (_nativeControlHandle != null && !_queuedForDestruction)
 
-                 {
 
-                     _queuedForDestruction = true;
 
-                     Dispatcher.UIThread.Post(CheckDestruction, DispatcherPriority.Background);
 
-                 }
 
-             }
 
-             if (_attachment?.AttachedTo != _currentHost)
 
-                 return;
 
-             TryUpdateNativeControlPosition();
 
-         }
 
-         
 
-         private Rect? GetAbsoluteBounds()
 
-         {
 
-             Debug.Assert(_currentRoot is not null);
 
-             var bounds = Bounds;
 
-             var position = this.TranslatePoint(default, _currentRoot);
 
-             if (position == null)
 
-                 return null;
 
-             return new Rect(position.Value, bounds.Size);
 
-         }
 
-         void EnqueueForMoveResize()
 
-         {
 
-             if(_queuedForMoveResize)
 
-                 return;
 
-             _queuedForMoveResize = true;
 
-             Dispatcher.UIThread.Post(UpdateHost, DispatcherPriority.Render);
 
-         }
 
-         public bool TryUpdateNativeControlPosition()
 
-         {
 
-             if (_currentHost == null)
 
-                 return false;
 
-             
 
-             var bounds = GetAbsoluteBounds();
 
-             if (IsEffectivelyVisible && bounds.HasValue)
 
-             {
 
-                 if (bounds.Value.IsDefault)
 
-                     return false;
 
-                 _attachment?.ShowInBounds(bounds.Value);
 
-             }
 
-             else
 
-                 _attachment?.HideWithSize(Bounds.Size);
 
-             return true;
 
-         }
 
-         private void CheckDestruction()
 
-         {
 
-             _queuedForDestruction = false;
 
-             if (_currentRoot == null)
 
-                 DestroyNativeControl();
 
-         }
 
-         
 
-         protected virtual IPlatformHandle CreateNativeControlCore(IPlatformHandle parent)
 
-         {
 
-             if (_currentHost == null)
 
-                 throw new InvalidOperationException();
 
-             return _currentHost.CreateDefaultChild(parent);
 
-         }
 
-         private void DestroyNativeControl()
 
-         {
 
-             if (_nativeControlHandle != null)
 
-             {
 
-                 _attachment?.Dispose();
 
-                 _attachment = null;
 
-                 
 
-                 DestroyNativeControlCore(_nativeControlHandle);
 
-                 _nativeControlHandle = null;
 
-             }
 
-         }
 
-         protected virtual void DestroyNativeControlCore(IPlatformHandle control)
 
-         {
 
-             ((INativeControlHostDestroyableControlHandle)control).Destroy();
 
-         }
 
-         
 
-     }
 
- }
 
 
  |