committed by
GitHub
60 changed files with 749 additions and 243 deletions
@ -1,13 +0,0 @@ |
|||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|
||||
<PropertyGroup> |
|
||||
<ApiContractPackageVersion>0.10.0</ApiContractPackageVersion> |
|
||||
<NugetPackageName Condition="'$(PackageId)' != ''">$(PackageId)</NugetPackageName> |
|
||||
<NugetPackageName Condition="'$(PackageId)' == ''">Avalonia</NugetPackageName> |
|
||||
<RunApiCompat Condition="'$(TargetFramework)' == 'net6.0'">false</RunApiCompat> |
|
||||
</PropertyGroup> |
|
||||
<ItemGroup> |
|
||||
<PackageDownload Include="$(NugetPackageName)" Version="[$(ApiContractPackageVersion)]" /> |
|
||||
<PackageReference Include="Microsoft.DotNet.ApiCompat" Version="5.0.0-beta.20372.2" PrivateAssets="All" /> |
|
||||
<ResolvedMatchingContract Include="$(NuGetPackageRoot)\$(NugetPackageName.ToLowerInvariant())\$(ApiContractPackageVersion)\lib\$(TargetFramework)\$(AssemblyName).dll" /> |
|
||||
</ItemGroup> |
|
||||
</Project> |
|
||||
@ -0,0 +1,33 @@ |
|||||
|
using System; |
||||
|
using Avalonia.Automation.Peers; |
||||
|
|
||||
|
namespace Avalonia.Automation.Provider |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Exposure methods and properties to support UI Automation client access to the root of an
|
||||
|
/// automation tree hosted by another UI framework.
|
||||
|
/// </summary>
|
||||
|
/// <remarks>
|
||||
|
/// This interface is implemented by the <see cref="AutomationPeer"/> class, and can be used
|
||||
|
/// to embed an automation tree from a 3rd party UI framework that wishes to use Avalonia's
|
||||
|
/// automation support.
|
||||
|
/// </remarks>
|
||||
|
public interface IEmbeddedRootProvider |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Gets the currently focused element.
|
||||
|
/// </summary>
|
||||
|
AutomationPeer? GetFocus(); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the element at the specified point, expressed in top-level coordinates.
|
||||
|
/// </summary>
|
||||
|
/// <param name="p">The point.</param>
|
||||
|
AutomationPeer? GetPeerFromPoint(Point p); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Raised by the automation peer when the focus changes.
|
||||
|
/// </summary>
|
||||
|
event EventHandler? FocusChanged; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,68 @@ |
|||||
|
using Avalonia.Controls; |
||||
|
using Avalonia.Media; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Avalonia.Base.UnitTests.Rendering; |
||||
|
/// <summary>
|
||||
|
/// Test class that verifies how clipping influences rendering in the compositor
|
||||
|
/// </summary>
|
||||
|
public class CompositorInvalidationClippingTests : CompositorTestsBase |
||||
|
{ |
||||
|
[Fact] |
||||
|
// Test case: When the ClipToBounds is false, all visuals should be rendered
|
||||
|
public void Siblings_Should_Be_Rendered_On_Invalidate_Without_ClipToBounds() |
||||
|
{ |
||||
|
AssertRenderedVisuals(clipToBounds: false, clipGeometry: false, expectedRenderedVisualsCount: 4); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
// Test case: When the ClipToBounds is true, only visuals within the clipped boundary should be rendered
|
||||
|
public void Siblings_Should_Not_Be_Rendered_On_Invalidate_With_ClipToBounds() |
||||
|
{ |
||||
|
AssertRenderedVisuals(clipToBounds: true, clipGeometry: false, expectedRenderedVisualsCount: 3); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
// Test case: When the Clip is used, only visuals within the clip geometry should be rendered
|
||||
|
public void Siblings_Should_Not_Be_Rendered_On_Invalidate_With_Clip() |
||||
|
{ |
||||
|
AssertRenderedVisuals(clipToBounds: false, clipGeometry: true, expectedRenderedVisualsCount: 3); |
||||
|
} |
||||
|
|
||||
|
private void AssertRenderedVisuals(bool clipToBounds, bool clipGeometry, int expectedRenderedVisualsCount) |
||||
|
{ |
||||
|
using (var s = new CompositorCanvas()) |
||||
|
{ |
||||
|
//#1 visual is top level
|
||||
|
//#2 visual is s.Canvas
|
||||
|
|
||||
|
//#3 visual is border1
|
||||
|
s.Canvas.Children.Add(new Border() |
||||
|
{ |
||||
|
[Canvas.LeftProperty] = 0, [Canvas.TopProperty] = 0, |
||||
|
Width = 20, Height = 10, |
||||
|
Background = Brushes.Red, |
||||
|
ClipToBounds = clipToBounds, |
||||
|
Clip = clipGeometry ? new RectangleGeometry(new Rect(new Size(20, 10))) : null |
||||
|
}); |
||||
|
|
||||
|
//#4 visual is border2
|
||||
|
s.Canvas.Children.Add(new Border() |
||||
|
{ |
||||
|
[Canvas.LeftProperty] = 30, [Canvas.TopProperty] = 50, |
||||
|
Width = 20, Height = 10, |
||||
|
Background = Brushes.Red, |
||||
|
ClipToBounds = clipToBounds, |
||||
|
Clip = clipGeometry ? new RectangleGeometry(new Rect(new Size(20, 10))) : null |
||||
|
}); |
||||
|
s.RunJobs(); |
||||
|
s.Events.Reset(); |
||||
|
|
||||
|
//invalidate border1
|
||||
|
s.Canvas.Children[0].IsVisible = false; |
||||
|
s.RunJobs(); |
||||
|
|
||||
|
s.AssertRenderedVisuals(expectedRenderedVisualsCount); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,70 @@ |
|||||
|
using System; |
||||
|
using Avalonia.Controls; |
||||
|
using Avalonia.Controls.ApplicationLifetimes; |
||||
|
using Avalonia.Reactive; |
||||
|
using Avalonia.Threading; |
||||
|
using Avalonia.UnitTests; |
||||
|
using JetBrains.dotMemoryUnit; |
||||
|
using Xunit; |
||||
|
using Xunit.Abstractions; |
||||
|
|
||||
|
namespace Avalonia.LeakTests; |
||||
|
|
||||
|
internal class ViewModelForDisposingTest |
||||
|
{ |
||||
|
~ViewModelForDisposingTest() { ; } |
||||
|
} |
||||
|
|
||||
|
[DotMemoryUnit(FailIfRunWithoutSupport = false)] |
||||
|
public class DataContextTests |
||||
|
{ |
||||
|
public DataContextTests(ITestOutputHelper atr) |
||||
|
{ |
||||
|
DotMemoryUnitTestOutput.SetOutputMethod(atr.WriteLine); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Window_DataContext_Disposed_After_Window_Close_With_Lifetime() |
||||
|
{ |
||||
|
static IDisposable Run() |
||||
|
{ |
||||
|
var unitTestApp = UnitTestApplication.Start(TestServices.StyledWindow); |
||||
|
var lifetime = new ClassicDesktopStyleApplicationLifetime(); |
||||
|
lifetime.ShutdownMode = ShutdownMode.OnExplicitShutdown; |
||||
|
var window = new Window { DataContext = new ViewModelForDisposingTest() }; |
||||
|
window.Show(); |
||||
|
window.Close(); |
||||
|
|
||||
|
return Disposable.Create(lifetime, lt => lt.Shutdown()) |
||||
|
.DisposeWith(new CompositeDisposable(lifetime, unitTestApp)); |
||||
|
} |
||||
|
|
||||
|
using var _ = Run(); |
||||
|
// Process all Loaded events to free control reference(s)
|
||||
|
Dispatcher.UIThread.RunJobs(DispatcherPriority.Loaded); |
||||
|
GC.Collect(); |
||||
|
|
||||
|
dotMemory.Check(m => Assert.Equal(0, |
||||
|
m.GetObjects(o => o.Type.Is<ViewModelForDisposingTest>()).ObjectsCount)); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Window_DataContext_Disposed_After_Window_Close_Without_Lifetime() |
||||
|
{ |
||||
|
static void Run() |
||||
|
{ |
||||
|
using var _ = UnitTestApplication.Start(TestServices.StyledWindow); |
||||
|
var window = new Window { DataContext = new ViewModelForDisposingTest() }; |
||||
|
window.Show(); |
||||
|
window.Close(); |
||||
|
} |
||||
|
|
||||
|
Run(); |
||||
|
// Process all Loaded events to free control reference(s)
|
||||
|
Dispatcher.UIThread.RunJobs(DispatcherPriority.Loaded); |
||||
|
GC.Collect(); |
||||
|
|
||||
|
dotMemory.Check(m => Assert.Equal(0, |
||||
|
m.GetObjects(o => o.Type.Is<ViewModelForDisposingTest>()).ObjectsCount)); |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue