Browse Source

Merge branch 'master' into AppVeyorZipArtifacts

pull/780/head
danwalmsley 10 years ago
committed by GitHub
parent
commit
5a508a4e8f
  1. 43
      Avalonia.sln
  2. 14
      samples/RenderTest/App.config
  3. 6
      samples/RenderTest/App.xaml
  4. 16
      samples/RenderTest/App.xaml.cs
  5. 3
      samples/RenderTest/MainWindow.xaml
  6. 82
      samples/RenderTest/MainWindow.xaml.cs
  7. 35
      samples/RenderTest/Program.cs
  8. 36
      samples/RenderTest/Properties/AssemblyInfo.cs
  9. 192
      samples/RenderTest/RenderTest.csproj
  10. 26
      samples/RenderTest/RenderTest.v2.ncrunchproject
  11. 10
      samples/RenderTest/packages.config
  12. 5
      src/Android/Avalonia.Android/AndroidPlatform.cs
  13. 1
      src/Android/Avalonia.Android/Avalonia.Android.csproj
  14. 59
      src/Android/Avalonia.Android/Platform/AndroidTopLevelRenderer.cs
  15. 1
      src/Avalonia.Base/Platform/IPlatformThreadingInterface.cs
  16. 3
      src/Avalonia.Controls/Application.cs
  17. 1
      src/Avalonia.Controls/Avalonia.Controls.csproj
  18. 66
      src/Avalonia.Controls/Platform/ITopLevelRenderer.cs
  19. 7
      src/Avalonia.Controls/Platform/PlatformManager.cs
  20. 31
      src/Avalonia.Controls/TopLevel.cs
  21. 2
      src/Avalonia.Controls/WrapPanel.cs
  22. 9
      src/Avalonia.SceneGraph/Avalonia.SceneGraph.csproj
  23. 2
      src/Avalonia.SceneGraph/Platform/IPlatformRenderInterface.cs
  24. 103
      src/Avalonia.SceneGraph/Rendering/DefaultRenderLoop.cs
  25. 19
      src/Avalonia.SceneGraph/Rendering/IRenderLoop.cs
  26. 31
      src/Avalonia.SceneGraph/Rendering/IRenderQueueManager.cs
  27. 25
      src/Avalonia.SceneGraph/Rendering/IRenderRoot.cs
  28. 15
      src/Avalonia.SceneGraph/Rendering/IRenderer.cs
  29. 18
      src/Avalonia.SceneGraph/Rendering/IRendererFactory.cs
  30. 51
      src/Avalonia.SceneGraph/Rendering/RenderQueueManager.cs
  31. 67
      src/Avalonia.SceneGraph/Rendering/Renderer.cs
  32. 4
      src/Avalonia.SceneGraph/Rendering/RendererMixin.cs
  33. 2
      src/Avalonia.SceneGraph/Visual.cs
  34. 2
      src/Gtk/Avalonia.Cairo/CairoPlatform.cs
  35. 10
      src/Gtk/Avalonia.Gtk/GtkPlatform.cs
  36. 2
      src/Skia/Avalonia.Skia.Android/SkiaRenderView.cs
  37. 2
      src/Skia/Avalonia.Skia.iOS.TestApp/MainView.cs
  38. 2
      src/Skia/Avalonia.Skia/PlatformRenderInterface.cs
  39. 11
      src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs
  40. 1
      src/Windows/Avalonia.Win32/Avalonia.Win32.csproj
  41. 10
      src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs
  42. 35
      src/Windows/Avalonia.Win32/RenderLoop.cs
  43. 2
      src/Windows/Avalonia.Win32/Win32Platform.cs
  44. 19
      src/Windows/Avalonia.Win32/WindowImpl.cs
  45. 14
      tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization.cs
  46. 14
      tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization_Simple.cs
  47. 1
      tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs
  48. 2
      tests/Avalonia.Input.UnitTests/InputElement_HitTesting.cs
  49. 2
      tests/Avalonia.Layout.UnitTests/FullLayoutTests.cs
  50. 25
      tests/Avalonia.LeakTests/ControlTests.cs
  51. 13
      tests/Avalonia.SceneGraph.UnitTests/TestRoot.cs
  52. 2
      tests/Avalonia.SceneGraph.UnitTests/VisualTree/MockRenderInterface.cs
  53. 12
      tests/Avalonia.UnitTests/TestRoot.cs
  54. 16
      tests/Avalonia.UnitTests/TestServices.cs
  55. 12
      tests/Avalonia.UnitTests/TestTemplatedRoot.cs
  56. 3
      tests/Avalonia.UnitTests/UnitTestApplication.cs

43
Avalonia.sln

@ -171,6 +171,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GtkInteropDemo", "samples\i
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.DotNetFrameworkRuntime", "src\Avalonia.DotNetFrameworkRuntime\Avalonia.DotNetFrameworkRuntime.csproj", "{4A1ABB09-9047-4BD5-A4AD-A055E52C5EE0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RenderTest", "samples\RenderTest\RenderTest.csproj", "{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCatalog.Android", "samples\ControlCatalog.Android\ControlCatalog.Android.csproj", "{29132311-1848-4FD6-AE0C-4FF841151BD3}"
EndProject
Global
@ -2363,6 +2365,46 @@ Global
{4A1ABB09-9047-4BD5-A4AD-A055E52C5EE0}.Release|Mono.Build.0 = Release|Any CPU
{4A1ABB09-9047-4BD5-A4AD-A055E52C5EE0}.Release|x86.ActiveCfg = Release|Any CPU
{4A1ABB09-9047-4BD5-A4AD-A055E52C5EE0}.Release|x86.Build.0 = Release|Any CPU
{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU
{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU
{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}.Ad-Hoc|Mono.ActiveCfg = Release|Any CPU
{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}.Ad-Hoc|Mono.Build.0 = Release|Any CPU
{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU
{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}.Ad-Hoc|x86.Build.0 = Release|Any CPU
{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}.AppStore|Any CPU.Build.0 = Release|Any CPU
{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}.AppStore|iPhone.ActiveCfg = Release|Any CPU
{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}.AppStore|iPhone.Build.0 = Release|Any CPU
{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU
{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}.AppStore|Mono.ActiveCfg = Release|Any CPU
{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}.AppStore|Mono.Build.0 = Release|Any CPU
{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}.AppStore|x86.ActiveCfg = Release|Any CPU
{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}.AppStore|x86.Build.0 = Release|Any CPU
{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}.Debug|iPhone.Build.0 = Debug|Any CPU
{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}.Debug|Mono.ActiveCfg = Debug|Any CPU
{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}.Debug|Mono.Build.0 = Debug|Any CPU
{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}.Debug|x86.ActiveCfg = Debug|Any CPU
{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}.Debug|x86.Build.0 = Debug|Any CPU
{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}.Release|Any CPU.Build.0 = Release|Any CPU
{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}.Release|iPhone.ActiveCfg = Release|Any CPU
{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}.Release|iPhone.Build.0 = Release|Any CPU
{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}.Release|Mono.ActiveCfg = Release|Any CPU
{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}.Release|Mono.Build.0 = Release|Any CPU
{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}.Release|x86.ActiveCfg = Release|Any CPU
{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}.Release|x86.Build.0 = Release|Any CPU
{29132311-1848-4FD6-AE0C-4FF841151BD3}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
{29132311-1848-4FD6-AE0C-4FF841151BD3}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
{29132311-1848-4FD6-AE0C-4FF841151BD3}.Ad-Hoc|Any CPU.Deploy.0 = Release|Any CPU
@ -2474,6 +2516,7 @@ Global
{A0CC0258-D18C-4AB3-854F-7101680FC3F9} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{C7A69145-60B6-4882-97D6-A3921DD43978} = {A0CC0258-D18C-4AB3-854F-7101680FC3F9}
{BD7F352C-6DC1-4740-BAF2-2D34A038728C} = {A0CC0258-D18C-4AB3-854F-7101680FC3F9}
{F1FDC5B0-4654-416F-AE69-E3E9BBD87801} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{29132311-1848-4FD6-AE0C-4FF841151BD3} = {9B9E3891-2366-4253-A952-D08BCEB71098}
EndGlobalSection
EndGlobal

14
samples/RenderTest/App.config

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Mono.Cairo" publicKeyToken="0738eb9f132ed756" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

6
samples/RenderTest/App.xaml

@ -0,0 +1,6 @@
<Application xmlns="https://github.com/avaloniaui">
<Application.Styles>
<StyleInclude Source="resm:Avalonia.Themes.Default.DefaultTheme.xaml?assembly=Avalonia.Themes.Default"/>
<StyleInclude Source="resm:Avalonia.Themes.Default.Accents.BaseLight.xaml?assembly=Avalonia.Themes.Default"/>
</Application.Styles>
</Application>

16
samples/RenderTest/App.xaml.cs

@ -0,0 +1,16 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using Avalonia;
using Avalonia.Markup.Xaml;
namespace RenderTest
{
public class App : Application
{
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
}
}
}

3
samples/RenderTest/MainWindow.xaml

@ -0,0 +1,3 @@
<Window xmlns="https://github.com/avaloniaui"
Title="Avalonia Render Test">
</Window>

82
samples/RenderTest/MainWindow.xaml.cs

@ -0,0 +1,82 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using System.Reactive.Linq;
using Avalonia;
using Avalonia.Animation;
using Avalonia.Controls;
using Avalonia.Controls.Shapes;
using Avalonia.Data;
using Avalonia.Layout;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
using Avalonia.Rendering;
namespace RenderTest
{
public class MainWindow : Window
{
public MainWindow()
{
this.InitializeComponent();
this.CreateAnimations();
this.AttachDevTools();
RendererMixin.DrawFpsCounter = true;
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
private void CreateAnimations()
{
const int Count = 100;
var panel = new WrapPanel();
for (var i = 0; i < Count; ++i)
{
var element = new Panel
{
Children =
{
new Ellipse
{
Width = 100,
Height = 100,
Fill = Brushes.Blue,
},
new Path
{
Data = StreamGeometry.Parse(
"F1 M 16.6309,18.6563C 17.1309,8.15625 29.8809,14.1563 29.8809,14.1563C 30.8809,11.1563 34.1308,11.4063 34.1308,11.4063C 33.5,12 34.6309,13.1563 34.6309,13.1563C 32.1309,13.1562 31.1309,14.9062 31.1309,14.9062C 41.1309,23.9062 32.6309,27.9063 32.6309,27.9062C 24.6309,24.9063 21.1309,22.1562 16.6309,18.6563 Z M 16.6309,19.9063C 21.6309,24.1563 25.1309,26.1562 31.6309,28.6562C 31.6309,28.6562 26.3809,39.1562 18.3809,36.1563C 18.3809,36.1563 18,38 16.3809,36.9063C 15,36 16.3809,34.9063 16.3809,34.9063C 16.3809,34.9063 10.1309,30.9062 16.6309,19.9063 Z"),
Fill = Brushes.Green,
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center,
RenderTransform = new ScaleTransform(2, 2),
}
},
Margin = new Thickness(4),
RenderTransform = new ScaleTransform(),
};
var start = Animate.Stopwatch.Elapsed;
var index = i;
var degrees = Animate.Timer
.Select(x => (x - start).TotalSeconds)
.Where(x => (x % Count) >= index && (x % Count) < index + 1)
.Select(x => (x % 1) / 1);
element.RenderTransform.Bind(
ScaleTransform.ScaleXProperty,
degrees,
BindingPriority.Animation);
panel.Children.Add(element);
}
Content = panel;
}
}
}

35
samples/RenderTest/Program.cs

@ -0,0 +1,35 @@
using System;
using System.Linq;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Logging.Serilog;
using Avalonia.Platform;
using Serilog;
namespace RenderTest
{
internal class Program
{
static void Main(string[] args)
{
InitializeLogging();
// TODO: Make this work with GTK/Skia/Cairo depending on command-line args
// again.
AppBuilder.Configure<App>()
.UsePlatformDetect()
.Start<MainWindow>();
}
// This will be made into a runtime configuration extension soon!
private static void InitializeLogging()
{
#if DEBUG
SerilogLogger.Initialize(new LoggerConfiguration()
.MinimumLevel.Warning()
.WriteTo.Trace(outputTemplate: "{Area}: {Message}")
.CreateLogger());
#endif
}
}
}

36
samples/RenderTest/Properties/AssemblyInfo.cs

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("RenderTest")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("RenderTest")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("f1fdc5b0-4654-416f-ae69-e3e9bbd87801")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

192
samples/RenderTest/RenderTest.csproj

@ -0,0 +1,192 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}</ProjectGuid>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>RenderTest</RootNamespace>
<AssemblyName>RenderTest</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<StartupObject />
</PropertyGroup>
<ItemGroup>
<Reference Include="Serilog, Version=1.5.0.0, Culture=neutral, PublicKeyToken=24c2f752a8e58a10, processorArchitecture=MSIL">
<HintPath>..\..\packages\Serilog.1.5.14\lib\net45\Serilog.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Serilog.FullNetFx, Version=1.5.0.0, Culture=neutral, PublicKeyToken=24c2f752a8e58a10, processorArchitecture=MSIL">
<HintPath>..\..\packages\Serilog.1.5.14\lib\net45\Serilog.FullNetFx.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Reactive.Core, Version=3.0.0.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Reactive.Core.3.0.0\lib\net45\System.Reactive.Core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Reactive.Interfaces, Version=3.0.0.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Reactive.Interfaces.3.0.0\lib\net45\System.Reactive.Interfaces.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Reactive.Linq, Version=3.0.0.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Reactive.Linq.3.0.0\lib\net45\System.Reactive.Linq.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Reactive.PlatformServices, Version=3.0.0.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Reactive.PlatformServices.3.0.0\lib\net45\System.Reactive.PlatformServices.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Reactive.Windows.Threading, Version=3.0.0.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Reactive.Windows.Threading.3.0.0\lib\net45\System.Reactive.Windows.Threading.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
<Reference Include="WindowsBase" />
</ItemGroup>
<ItemGroup>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="MainWindow.xaml.cs">
<DependentUpon>MainWindow.xaml</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="App.xaml">
<SubType>Designer</SubType>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Avalonia.Animation\Avalonia.Animation.csproj">
<Project>{d211e587-d8bc-45b9-95a4-f297c8fa5200}</Project>
<Name>Avalonia.Animation</Name>
</ProjectReference>
<ProjectReference Include="..\..\src\Avalonia.Base\Avalonia.Base.csproj">
<Project>{b09b78d8-9b26-48b0-9149-d64a2f120f3f}</Project>
<Name>Avalonia.Base</Name>
</ProjectReference>
<ProjectReference Include="..\..\src\Avalonia.Controls\Avalonia.Controls.csproj">
<Project>{d2221c82-4a25-4583-9b43-d791e3f6820c}</Project>
<Name>Avalonia.Controls</Name>
</ProjectReference>
<ProjectReference Include="..\..\src\Avalonia.DesignerSupport\Avalonia.DesignerSupport.csproj">
<Project>{799a7bb5-3c2c-48b6-85a7-406a12c420da}</Project>
<Name>Avalonia.DesignerSupport</Name>
</ProjectReference>
<ProjectReference Include="..\..\src\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj">
<Project>{7062ae20-5dcc-4442-9645-8195bdece63e}</Project>
<Name>Avalonia.Diagnostics</Name>
</ProjectReference>
<ProjectReference Include="..\..\src\Avalonia.DotNetFrameworkRuntime\Avalonia.DotNetFrameworkRuntime.csproj">
<Project>{4a1abb09-9047-4bd5-a4ad-a055e52c5ee0}</Project>
<Name>Avalonia.DotNetFrameworkRuntime</Name>
</ProjectReference>
<ProjectReference Include="..\..\src\Avalonia.Input\Avalonia.Input.csproj">
<Project>{62024b2d-53eb-4638-b26b-85eeaa54866e}</Project>
<Name>Avalonia.Input</Name>
</ProjectReference>
<ProjectReference Include="..\..\src\Avalonia.Interactivity\Avalonia.Interactivity.csproj">
<Project>{6b0ed19d-a08b-461c-a9d9-a9ee40b0c06b}</Project>
<Name>Avalonia.Interactivity</Name>
</ProjectReference>
<ProjectReference Include="..\..\src\Avalonia.Layout\Avalonia.Layout.csproj">
<Project>{42472427-4774-4c81-8aff-9f27b8e31721}</Project>
<Name>Avalonia.Layout</Name>
</ProjectReference>
<ProjectReference Include="..\..\src\Avalonia.Logging.Serilog\Avalonia.Logging.Serilog.csproj">
<Project>{b61b66a3-b82d-4875-8001-89d3394fe0c9}</Project>
<Name>Avalonia.Logging.Serilog</Name>
</ProjectReference>
<ProjectReference Include="..\..\src\Avalonia.ReactiveUI\Avalonia.ReactiveUI.csproj">
<Project>{6417b24e-49c2-4985-8db2-3ab9d898ec91}</Project>
<Name>Avalonia.ReactiveUI</Name>
</ProjectReference>
<ProjectReference Include="..\..\src\Avalonia.SceneGraph\Avalonia.SceneGraph.csproj">
<Project>{eb582467-6abb-43a1-b052-e981ba910e3a}</Project>
<Name>Avalonia.SceneGraph</Name>
</ProjectReference>
<ProjectReference Include="..\..\src\Avalonia.Styling\Avalonia.Styling.csproj">
<Project>{f1baa01a-f176-4c6a-b39d-5b40bb1b148f}</Project>
<Name>Avalonia.Styling</Name>
</ProjectReference>
<ProjectReference Include="..\..\src\Avalonia.Themes.Default\Avalonia.Themes.Default.csproj">
<Project>{3e10a5fa-e8da-48b1-ad44-6a5b6cb7750f}</Project>
<Name>Avalonia.Themes.Default</Name>
</ProjectReference>
<ProjectReference Include="..\..\src\Gtk\Avalonia.Cairo\Avalonia.Cairo.csproj">
<Project>{fb05ac90-89ba-4f2f-a924-f37875fb547c}</Project>
<Name>Avalonia.Cairo</Name>
</ProjectReference>
<ProjectReference Include="..\..\src\Gtk\Avalonia.Gtk\Avalonia.Gtk.csproj">
<Project>{54f237d5-a70a-4752-9656-0c70b1a7b047}</Project>
<Name>Avalonia.Gtk</Name>
</ProjectReference>
<ProjectReference Include="..\..\src\Markup\Avalonia.Markup.Xaml\Avalonia.Markup.Xaml.csproj">
<Project>{3e53a01a-b331-47f3-b828-4a5717e77a24}</Project>
<Name>Avalonia.Markup.Xaml</Name>
</ProjectReference>
<ProjectReference Include="..\..\src\Markup\Avalonia.Markup\Avalonia.Markup.csproj">
<Project>{6417e941-21bc-467b-a771-0de389353ce6}</Project>
<Name>Avalonia.Markup</Name>
</ProjectReference>
<ProjectReference Include="..\..\src\Windows\Avalonia.Direct2D1\Avalonia.Direct2D1.csproj">
<Project>{3e908f67-5543-4879-a1dc-08eace79b3cd}</Project>
<Name>Avalonia.Direct2D1</Name>
</ProjectReference>
<ProjectReference Include="..\..\src\Windows\Avalonia.Win32\Avalonia.Win32.csproj">
<Project>{811a76cf-1cf6-440f-963b-bbe31bd72a82}</Project>
<Name>Avalonia.Win32</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="MainWindow.xaml">
<SubType>Designer</SubType>
</EmbeddedResource>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

26
samples/RenderTest/RenderTest.v2.ncrunchproject

@ -0,0 +1,26 @@
<ProjectConfiguration>
<AutoDetectNugetBuildDependencies>true</AutoDetectNugetBuildDependencies>
<BuildPriority>1000</BuildPriority>
<CopyReferencedAssembliesToWorkspace>false</CopyReferencedAssembliesToWorkspace>
<ConsiderInconclusiveTestsAsPassing>false</ConsiderInconclusiveTestsAsPassing>
<PreloadReferencedAssemblies>false</PreloadReferencedAssemblies>
<AllowDynamicCodeContractChecking>true</AllowDynamicCodeContractChecking>
<AllowStaticCodeContractChecking>false</AllowStaticCodeContractChecking>
<AllowCodeAnalysis>false</AllowCodeAnalysis>
<IgnoreThisComponentCompletely>false</IgnoreThisComponentCompletely>
<RunPreBuildEvents>false</RunPreBuildEvents>
<RunPostBuildEvents>false</RunPostBuildEvents>
<PreviouslyBuiltSuccessfully>true</PreviouslyBuiltSuccessfully>
<InstrumentAssembly>true</InstrumentAssembly>
<PreventSigningOfAssembly>false</PreventSigningOfAssembly>
<AnalyseExecutionTimes>true</AnalyseExecutionTimes>
<DetectStackOverflow>true</DetectStackOverflow>
<IncludeStaticReferencesInWorkspace>true</IncludeStaticReferencesInWorkspace>
<DefaultTestTimeout>60000</DefaultTestTimeout>
<UseBuildConfiguration />
<UseBuildPlatform />
<ProxyProcessPath />
<UseCPUArchitecture>AutoDetect</UseCPUArchitecture>
<MSTestThreadApartmentState>STA</MSTestThreadApartmentState>
<BuildProcessArchitecture>x86</BuildProcessArchitecture>
</ProjectConfiguration>

10
samples/RenderTest/packages.config

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Serilog" version="1.5.14" targetFramework="net45" />
<package id="System.Reactive" version="3.0.0" targetFramework="net45" />
<package id="System.Reactive.Core" version="3.0.0" targetFramework="net45" />
<package id="System.Reactive.Interfaces" version="3.0.0" targetFramework="net45" />
<package id="System.Reactive.Linq" version="3.0.0" targetFramework="net45" />
<package id="System.Reactive.PlatformServices" version="3.0.0" targetFramework="net45" />
<package id="System.Reactive.Windows.Threading" version="3.0.0" targetFramework="net45" />
</packages>

5
src/Android/Avalonia.Android/AndroidPlatform.cs

@ -1,6 +1,5 @@
using System;
using System.IO;
using Avalonia.Android.CanvasRendering;
using Avalonia.Android.Platform;
using Avalonia.Android.Platform.Input;
using Avalonia.Android.Platform.SkiaPlatform;
@ -10,6 +9,7 @@ using Avalonia.Input;
using Avalonia.Input.Platform;
using Avalonia.Platform;
using Avalonia.Shared.PlatformSupport;
using Avalonia.Skia;
namespace Avalonia
{
@ -50,8 +50,9 @@ namespace Avalonia.Android
.Bind<IPlatformSettings>().ToConstant(Instance)
.Bind<IPlatformThreadingInterface>().ToConstant(new AndroidThreadingInterface())
.Bind<ISystemDialogImpl>().ToTransient<SystemDialogImpl>()
.Bind<ITopLevelRenderer>().ToTransient<AndroidTopLevelRenderer>()
.Bind<IWindowingPlatform>().ToConstant(Instance);
SkiaPlatform.Initialize();
}
public void Init(Type applicationType)

1
src/Android/Avalonia.Android/Avalonia.Android.csproj

@ -74,7 +74,6 @@
<Compile Include="Platform\Specific\AvaloniaActivity.cs" />
<Compile Include="Platform\Specific\Helpers\AndroidTouchEventsHelper.cs" />
<Compile Include="Platform\Specific\Helpers\AndroidKeyboardEventsHelper.cs" />
<Compile Include="Platform\AndroidTopLevelRenderer.cs" />
<Compile Include="Resources\Resource.Designer.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RuntimeInfo.cs" />

59
src/Android/Avalonia.Android/Platform/AndroidTopLevelRenderer.cs

@ -1,59 +0,0 @@
using Avalonia.Controls;
using Avalonia.Controls.Platform;
using Avalonia.Platform;
using Avalonia.Rendering;
using Avalonia.Threading;
using System;
using System.Collections.Generic;
namespace Avalonia.Android.CanvasRendering
{
internal class AndroidTopLevelRenderer : ITopLevelRenderer
{
public void Attach(TopLevel topLevel)
{
var resources = new List<IDisposable>();
var initialClientSize = topLevel.PlatformImpl.ClientSize;
var queueManager = ((IRenderRoot)topLevel).RenderQueueManager;
if (queueManager == null)
return;
var viewport = PlatformManager.CreateRenderTarget(topLevel.PlatformImpl);
resources.Add(viewport);
//resources.Add(queueManager.RenderNeeded.Subscribe(_
// =>
// Dispatcher.UIThread.InvokeAsync(() => topLevel.PlatformImpl.Invalidate(new Rect(topLevel.ClientSize)))));
Action pendingInvalidation = null;
resources.Add(queueManager.RenderNeeded.Subscribe(_ =>
{
if (pendingInvalidation == null)
{
pendingInvalidation = () =>
{
topLevel.PlatformImpl.Invalidate(new Rect(topLevel.ClientSize));
pendingInvalidation = null;
};
Dispatcher.UIThread.InvokeAsync(pendingInvalidation);
}
}
));
topLevel.PlatformImpl.Paint = rect =>
{
viewport.Render(topLevel);
queueManager.RenderFinished();
};
topLevel.Closed += delegate
{
foreach (var disposable in resources)
disposable.Dispose();
resources.Clear();
};
}
}
}

1
src/Avalonia.Base/Platform/IPlatformThreadingInterface.cs

@ -26,6 +26,5 @@ namespace Avalonia.Platform
bool CurrentThreadIsLoopThread { get; }
event Action Signaled;
}
}

3
src/Avalonia.Controls/Application.cs

@ -2,10 +2,8 @@
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using System.Reflection;
using System.Threading;
using Avalonia.Controls;
using Avalonia.Controls.Platform;
using Avalonia.Controls.Templates;
using Avalonia.Input;
using Avalonia.Input.Platform;
@ -177,7 +175,6 @@ namespace Avalonia
.Bind<IKeyboardNavigationHandler>().ToTransient<KeyboardNavigationHandler>()
.Bind<IStyler>().ToConstant(_styler)
.Bind<ILayoutManager>().ToSingleton<LayoutManager>()
.Bind<IRenderQueueManager>().ToTransient<RenderQueueManager>()
.Bind<IApplicationLifecycle>().ToConstant(this);
}
}

1
src/Avalonia.Controls/Avalonia.Controls.csproj

@ -73,7 +73,6 @@
<Compile Include="Mixins\ContentControlMixin.cs" />
<Compile Include="Platform\IWindowIconImpl.cs" />
<Compile Include="Platform\IPlatformIconLoader.cs" />
<Compile Include="Platform\ITopLevelRenderer.cs" />
<Compile Include="Platform\IWindowingPlatform.cs" />
<Compile Include="Platform\PlatformManager.cs" />
<Compile Include="Presenters\IContentPresenterHost.cs" />

66
src/Avalonia.Controls/Platform/ITopLevelRenderer.cs

@ -1,66 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Avalonia.Platform;
using Avalonia.Rendering;
using Avalonia.Threading;
namespace Avalonia.Controls.Platform
{
public interface ITopLevelRenderer
{
void Attach(TopLevel topLevel);
}
class DefaultTopLevelRenderer : ITopLevelRenderer
{
public void Attach(TopLevel topLevel)
{
var resources = new List<IDisposable>();
var initialClientSize = topLevel.PlatformImpl.ClientSize;
var queueManager = ((IRenderRoot)topLevel).RenderQueueManager;
if (queueManager == null)
return;
var viewport = PlatformManager.CreateRenderTarget(topLevel.PlatformImpl);
resources.Add(viewport);
resources.Add(queueManager.RenderNeeded.Subscribe(_
=>
Dispatcher.UIThread.InvokeAsync(() => topLevel.PlatformImpl.Invalidate(new Rect(topLevel.ClientSize)))));
topLevel.PlatformImpl.Paint = rect =>
{
try
{
viewport.Render(topLevel);
}
catch (RenderTargetCorruptedException ex)
{
Logging.Logger.Error("Renderer", this, "Render target was corrupted. Exception: {0}", ex);
viewport.Dispose();
resources.Remove(viewport);
viewport = PlatformManager.CreateRenderTarget(topLevel.PlatformImpl);
resources.Add(viewport);
topLevel.PlatformImpl.Paint(rect); // Retry painting
}
queueManager.RenderFinished();
};
topLevel.Closed += delegate
{
foreach (var disposable in resources)
disposable.Dispose();
resources.Clear();
};
}
}
}

7
src/Avalonia.Controls/Platform/PlatformManager.cs

@ -12,13 +12,6 @@ namespace Avalonia.Controls.Platform
static bool s_designerMode;
public static IRenderTarget CreateRenderTarget(ITopLevelImpl window)
{
return AvaloniaLocator.Current
.GetService<IPlatformRenderInterface>()
.CreateRenderer(window.Handle);
}
public static IDisposable DesignerMode()
{
s_designerMode = true;

31
src/Avalonia.Controls/TopLevel.cs

@ -45,11 +45,11 @@ namespace Avalonia.Controls
public static readonly StyledProperty<IInputElement> PointerOverElementProperty =
AvaloniaProperty.Register<TopLevel, IInputElement>(nameof(IInputRoot.PointerOverElement));
private readonly IRenderQueueManager _renderQueueManager;
private readonly IInputManager _inputManager;
private readonly IAccessKeyHandler _accessKeyHandler;
private readonly IKeyboardNavigationHandler _keyboardNavigationHandler;
private readonly IApplicationLifecycle _applicationLifecycle;
private readonly IPlatformRenderInterface _renderInterface;
private Size _clientSize;
private bool _isActive;
@ -86,22 +86,25 @@ namespace Avalonia.Controls
}
PlatformImpl = impl;
dependencyResolver = dependencyResolver ?? AvaloniaLocator.Current;
var styler = TryGetService<IStyler>(dependencyResolver);
_accessKeyHandler = TryGetService<IAccessKeyHandler>(dependencyResolver);
_inputManager = TryGetService<IInputManager>(dependencyResolver);
_keyboardNavigationHandler = TryGetService<IKeyboardNavigationHandler>(dependencyResolver);
_renderQueueManager = TryGetService<IRenderQueueManager>(dependencyResolver);
_applicationLifecycle = TryGetService<IApplicationLifecycle>(dependencyResolver);
_renderInterface = TryGetService<IPlatformRenderInterface>(dependencyResolver);
(dependencyResolver.GetService<ITopLevelRenderer>() ?? new DefaultTopLevelRenderer()).Attach(this);
var renderLoop = TryGetService<IRenderLoop>(dependencyResolver);
var rendererFactory = TryGetService<IRendererFactory>(dependencyResolver);
Renderer = rendererFactory?.CreateRenderer(this, renderLoop);
PlatformImpl.SetInputRoot(this);
PlatformImpl.Activated = HandleActivated;
PlatformImpl.Deactivated = HandleDeactivated;
PlatformImpl.Closed = HandleClosed;
PlatformImpl.Input = HandleInput;
PlatformImpl.Paint = Renderer != null ? (Action<Rect>)Renderer.Render : null;
PlatformImpl.Resized = HandleResized;
PlatformImpl.ScalingChanged = HandleScalingChanged;
PlatformImpl.PositionChanged = HandlePositionChanged;
@ -179,9 +182,9 @@ namespace Avalonia.Controls
}
/// <summary>
/// Gets the window render manager.
/// Gets the renderer for the window.
/// </summary>
IRenderQueueManager IRenderRoot.RenderQueueManager => _renderQueueManager;
public IRenderer Renderer { get; }
/// <summary>
/// Gets the access key handler for the window.
@ -231,6 +234,18 @@ namespace Avalonia.Controls
private set;
}
/// <inheritdoc/>
IRenderTarget IRenderRoot.CreateRenderTarget()
{
return _renderInterface.CreateRenderTarget(PlatformImpl.Handle);
}
/// <inheritdoc/>
void IRenderRoot.Invalidate(Rect rect)
{
PlatformImpl.Invalidate(rect);
}
/// <inheritdoc/>
Point IRenderRoot.PointToClient(Point p)
{
@ -321,8 +336,8 @@ namespace Avalonia.Controls
}
/// <summary>
/// Tries to get a service from an <see cref="IAvaloniaDependencyResolver"/>, throwing an
/// exception if not found.
/// Tries to get a service from an <see cref="IAvaloniaDependencyResolver"/>, logging a
/// warning if not found.
/// </summary>
/// <typeparam name="T">The service type.</typeparam>
/// <param name="resolver">The resolver.</param>

2
src/Avalonia.Controls/WrapPanel.cs

@ -17,7 +17,7 @@ namespace Avalonia.Controls
/// Subsequent ordering happens sequentially from top to bottom or from right to left,
/// depending on the value of the Orientation property.
/// </summary>
internal class WrapPanel : Panel, INavigableContainer
public class WrapPanel : Panel, INavigableContainer
{
/// <summary>
/// Defines the <see cref="Orientation"/> property.

9
src/Avalonia.SceneGraph/Avalonia.SceneGraph.csproj

@ -102,6 +102,12 @@
<Compile Include="Media\Geometry.cs" />
<Compile Include="Media\IDrawingContext.cs" />
<Compile Include="Platform\ExportRenderingSubsystemAttribute.cs" />
<Compile Include="Rendering\IRenderer.cs" />
<Compile Include="Rendering\IRendererFactory.cs" />
<Compile Include="Rendering\IRenderLoop.cs" />
<Compile Include="Rendering\Renderer.cs" />
<Compile Include="Rendering\RendererMixin.cs" />
<Compile Include="Rendering\DefaultRenderLoop.cs" />
<Compile Include="RenderTargetCorruptedException.cs" />
<Compile Include="VisualTree\IVisual.cs" />
<Compile Include="Media\Imaging\Bitmap.cs" />
@ -139,9 +145,6 @@
<Compile Include="RelativeRect.cs" />
<Compile Include="Rect.cs" />
<Compile Include="Rendering\IRenderRoot.cs" />
<Compile Include="Rendering\IRenderQueueManager.cs" />
<Compile Include="Rendering\RendererMixin.cs" />
<Compile Include="Rendering\RenderQueueManager.cs" />
<Compile Include="Size.cs" />
<Compile Include="Thickness.cs" />
<Compile Include="Vector.cs" />

2
src/Avalonia.SceneGraph/Platform/IPlatformRenderInterface.cs

@ -42,7 +42,7 @@ namespace Avalonia.Platform
/// </summary>
/// <param name="handle">The platform handle for the renderer.</param>
/// <returns>An <see cref="IRenderTarget"/>.</returns>
IRenderTarget CreateRenderer(IPlatformHandle handle);
IRenderTarget CreateRenderTarget(IPlatformHandle handle);
/// <summary>
/// Creates a render target bitmap implementation.

103
src/Avalonia.SceneGraph/Rendering/DefaultRenderLoop.cs

@ -0,0 +1,103 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using Avalonia.Platform;
namespace Avalonia.Rendering
{
/// <summary>
/// Defines a default render loop that uses a standard timer.
/// </summary>
/// <remarks>
/// This class may be overridden by platform implementations to use a specialized timer
/// implementation.
/// </remarks>
public class DefaultRenderLoop : IRenderLoop
{
private IPlatformThreadingInterface _threading;
private int _subscriberCount;
private EventHandler<EventArgs> _tick;
private IDisposable _subscription;
/// <summary>
/// Initializes a new instance of the <see cref="DefaultRenderLoop"/> class.
/// </summary>
/// <param name="framesPerSecond">
/// The number of frames per second at which the loop should run.
/// </param>
public DefaultRenderLoop(int framesPerSecond)
{
FramesPerSecond = framesPerSecond;
}
/// <summary>
/// Gets the number of frames per second at which the loop runs.
/// </summary>
public int FramesPerSecond { get; }
/// <inheritdoc/>
public event EventHandler<EventArgs> Tick
{
add
{
if (_subscriberCount++ == 0)
{
Start();
}
_tick += value;
}
remove
{
if (--_subscriberCount == 0)
{
Stop();
}
_tick -= value;
}
}
/// <summary>
/// Starts the timer.
/// </summary>
protected void Start()
{
_subscription = StartCore(InternalTick);
}
/// <summary>
/// Provides the implementation of starting the timer.
/// </summary>
/// <param name="tick">The method to call on each tick.</param>
/// <remarks>
/// This can be overridden by platform implementations to use a specialized timer
/// implementation.
/// </remarks>
protected virtual IDisposable StartCore(Action tick)
{
if (_threading == null)
{
_threading = AvaloniaLocator.Current.GetService<IPlatformThreadingInterface>();
}
return _threading.StartTimer(TimeSpan.FromSeconds(1.0 / FramesPerSecond), tick);
}
/// <summary>
/// Stops the timer.
/// </summary>
protected void Stop()
{
_subscription.Dispose();
_subscription = null;
}
private void InternalTick()
{
_tick(this, EventArgs.Empty);
}
}
}

19
src/Avalonia.SceneGraph/Rendering/IRenderLoop.cs

@ -0,0 +1,19 @@
using System;
namespace Avalonia.Rendering
{
/// <summary>
/// Defines the interface implemented by an application render loop.
/// </summary>
public interface IRenderLoop
{
/// <summary>
/// Raised when the render loop ticks to signal a new frame should be drawn.
/// </summary>
/// <remarks>
/// This event can be raised on any thread; it is the responsibility of the subscriber to
/// switch execution to the right thread.
/// </remarks>
event EventHandler<EventArgs> Tick;
}
}

31
src/Avalonia.SceneGraph/Rendering/IRenderQueueManager.cs

@ -1,31 +0,0 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using System.Reactive;
using Avalonia.VisualTree;
namespace Avalonia.Rendering
{
/// <summary>
/// Defines the interface for a <see cref="RenderQueueManager"/>.
/// </summary>
public interface IRenderQueueManager
{
/// <summary>
/// Gets an observable that is fired whenever a render is required.
/// </summary>
IObservable<Unit> RenderNeeded { get; }
/// <summary>
/// Invalidates the render for the specified visual and raises <see cref="RenderNeeded"/>.
/// </summary>
/// <param name="visual">The visual.</param>
void InvalidateRender(IVisual visual);
/// <summary>
/// Called when rendering is finished.
/// </summary>
void RenderFinished();
}
}

25
src/Avalonia.SceneGraph/Rendering/IRenderRoot.cs

@ -1,19 +1,38 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using Avalonia.Platform;
using Avalonia.VisualTree;
namespace Avalonia.Rendering
{
/// <summary>
/// Represents the root of a renderable tree.
/// </summary>
public interface IRenderRoot
public interface IRenderRoot : IVisual
{
/// <summary>
/// Gets the render manager which schedules renders.
/// Gets the client size of the window.
/// </summary>
IRenderQueueManager RenderQueueManager { get; }
Size ClientSize { get; }
/// <summary>
/// Gets the renderer for the window.
/// </summary>
IRenderer Renderer { get; }
/// <summary>
/// Creates a render target for the window.
/// </summary>
/// <returns>An <see cref="IRenderTarget"/>.</returns>
IRenderTarget CreateRenderTarget();
/// <summary>
/// Adds a rectangle to the window's dirty region.
/// </summary>
/// <param name="rect">The rectangle.</param>
void Invalidate(Rect rect);
/// <summary>
/// Converts a point from screen to client coordinates.

15
src/Avalonia.SceneGraph/Rendering/IRenderer.cs

@ -0,0 +1,15 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using Avalonia.VisualTree;
namespace Avalonia.Rendering
{
public interface IRenderer : IDisposable
{
void AddDirty(IVisual visual);
void Render(Rect rect);
}
}

18
src/Avalonia.SceneGraph/Rendering/IRendererFactory.cs

@ -0,0 +1,18 @@
using System;
namespace Avalonia.Rendering
{
/// <summary>
/// Defines a factory for creating <see cref="IRenderer"/> instances.
/// </summary>
public interface IRendererFactory
{
/// <summary>
/// Creates a new renderer for the specified render root.
/// </summary>
/// <param name="root">The render root.</param>
/// <param name="renderLoop">The render loop.</param>
/// <returns>An instance of an <see cref="IRenderer"/>.</returns>
IRenderer CreateRenderer(IRenderRoot root, IRenderLoop renderLoop);
}
}

51
src/Avalonia.SceneGraph/Rendering/RenderQueueManager.cs

@ -1,51 +0,0 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using System.Reactive;
using System.Reactive.Subjects;
using Avalonia.VisualTree;
namespace Avalonia.Rendering
{
/// <summary>
/// Schedules the rendering of a tree.
/// </summary>
public class RenderQueueManager : IRenderQueueManager
{
private readonly Subject<Unit> _renderNeeded = new Subject<Unit>();
private bool _renderQueued;
/// <summary>
/// Gets an observable that is fired whenever a render is required.
/// </summary>
public IObservable<Unit> RenderNeeded => _renderNeeded;
/// <summary>
/// Gets a value indicating whether a render is queued.
/// </summary>
public bool RenderQueued => _renderQueued;
/// <summary>
/// Invalidates the render for the specified visual and raises <see cref="RenderNeeded"/>.
/// </summary>
/// <param name="visual">The visual.</param>
public void InvalidateRender(IVisual visual)
{
if (!_renderQueued)
{
_renderQueued = true;
_renderNeeded.OnNext(Unit.Default);
}
}
/// <summary>
/// Called when rendering is finished.
/// </summary>
public void RenderFinished()
{
_renderQueued = false;
}
}
}

67
src/Avalonia.SceneGraph/Rendering/Renderer.cs

@ -0,0 +1,67 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using Avalonia.Platform;
using Avalonia.VisualTree;
namespace Avalonia.Rendering
{
public class Renderer : IDisposable, IRenderer
{
private readonly IRenderLoop _renderLoop;
private readonly IRenderRoot _root;
private IRenderTarget _renderTarget;
private bool _dirty;
public Renderer(IRenderRoot root, IRenderLoop renderLoop)
{
Contract.Requires<ArgumentNullException>(root != null);
_root = root;
_renderLoop = renderLoop;
_renderLoop.Tick += OnRenderLoopTick;
}
public void AddDirty(IVisual visual)
{
_dirty = true;
}
public void Dispose()
{
_renderLoop.Tick -= OnRenderLoopTick;
}
public void Render(Rect rect)
{
if (_renderTarget == null)
{
_renderTarget = _root.CreateRenderTarget();
}
try
{
_renderTarget.Render(_root);
}
catch (RenderTargetCorruptedException ex)
{
Logging.Logger.Information("Renderer", this, "Render target was corrupted. Exception: {0}", ex);
_renderTarget.Dispose();
_renderTarget = null;
}
finally
{
_dirty = false;
}
}
private void OnRenderLoopTick(object sender, EventArgs e)
{
if (_dirty)
{
_root.Invalidate(new Rect(_root.ClientSize));
}
}
}
}

4
src/Avalonia.SceneGraph/Rendering/RendererMixin.cs

@ -1,4 +1,4 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
@ -51,7 +51,7 @@ namespace Avalonia.Rendering
s_currentFrames++;
var now = s_stopwatch.Elapsed;
var elapsed = now - s_lastMeasure;
if (elapsed.TotalSeconds > 0)
if (elapsed.TotalSeconds > 1)
{
s_fps = (int) (s_currentFrames/elapsed.TotalSeconds);
s_currentFrames = 0;

2
src/Avalonia.SceneGraph/Visual.cs

@ -259,7 +259,7 @@ namespace Avalonia
/// </summary>
public void InvalidateVisual()
{
VisualRoot?.RenderQueueManager?.InvalidateRender(this);
VisualRoot?.Renderer?.AddDirty(this);
}
/// <summary>

2
src/Gtk/Avalonia.Cairo/CairoPlatform.cs

@ -50,7 +50,7 @@ namespace Avalonia.Cairo
return new FormattedTextImpl(s_pangoContext, text, fontFamily, fontSize, fontStyle, textAlignment, fontWeight);
}
public IRenderTarget CreateRenderer(IPlatformHandle handle)
public IRenderTarget CreateRenderTarget(IPlatformHandle handle)
{
var window = handle as Gtk.Window;
if (window != null)

10
src/Gtk/Avalonia.Gtk/GtkPlatform.cs

@ -25,9 +25,10 @@ namespace Avalonia
namespace Avalonia.Gtk
{
using System.IO;
using Rendering;
using Gtk = global::Gtk;
public class GtkPlatform : IPlatformThreadingInterface, IPlatformSettings, IWindowingPlatform, IPlatformIconLoader
public class GtkPlatform : IPlatformThreadingInterface, IPlatformSettings, IWindowingPlatform, IPlatformIconLoader, IRendererFactory
{
private static readonly GtkPlatform s_instance = new GtkPlatform();
private static Thread _uiThread;
@ -53,6 +54,8 @@ namespace Avalonia.Gtk
.Bind<IMouseDevice>().ToConstant(GtkMouseDevice.Instance)
.Bind<IPlatformSettings>().ToConstant(s_instance)
.Bind<IPlatformThreadingInterface>().ToConstant(s_instance)
.Bind<IRendererFactory>().ToConstant(s_instance)
.Bind<IRenderLoop>().ToConstant(new DefaultRenderLoop(60))
.Bind<ISystemDialogImpl>().ToSingleton<SystemDialogImpl>()
.Bind<IPlatformIconLoader>().ToConstant(s_instance);
_uiThread = Thread.CurrentThread;
@ -110,6 +113,11 @@ namespace Avalonia.Gtk
return new PopupImpl();
}
public IRenderer CreateRenderer(IRenderRoot root, IRenderLoop renderLoop)
{
return new Renderer(root, renderLoop);
}
public IWindowIconImpl LoadIcon(string fileName)
{
return new IconImpl(new Gdk.Pixbuf(fileName));

2
src/Skia/Avalonia.Skia.Android/SkiaRenderView.cs

@ -22,7 +22,7 @@ namespace Avalonia.Skia.Android
{
_renderTarget =
AvaloniaLocator.Current.GetService<IPlatformRenderInterface>()
.CreateRenderer(this);
.CreateRenderTarget(this);
}
protected override void Draw()

2
src/Skia/Avalonia.Skia.iOS.TestApp/MainView.cs

@ -21,7 +21,7 @@ namespace Avalonia.Skia.iOS.TestApp
AutoresizingMask = UIViewAutoresizing.All;
SkiaPlatform.Initialize();
_target = AvaloniaLocator.Current.GetService<IPlatformRenderInterface>()
.CreateRenderer(AvaloniaPlatformHandle);
.CreateRenderTarget(AvaloniaPlatformHandle);
UpdateText(0);
}
double _radians = 0;

2
src/Skia/Avalonia.Skia/PlatformRenderInterface.cs

@ -58,7 +58,7 @@ namespace Avalonia.Skia
return new BitmapImpl(width, height);
}
public IRenderTarget CreateRenderer(IPlatformHandle handle)
public IRenderTarget CreateRenderTarget(IPlatformHandle handle)
{
return new WindowRenderTarget(handle);
}

11
src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs

@ -7,6 +7,7 @@ using Avalonia.Direct2D1.Media;
using Avalonia.Media;
using Avalonia.Platform;
using Avalonia.Controls;
using Avalonia.Rendering;
namespace Avalonia
{
@ -22,7 +23,7 @@ namespace Avalonia
namespace Avalonia.Direct2D1
{
public class Direct2D1Platform : IPlatformRenderInterface
public class Direct2D1Platform : IPlatformRenderInterface, IRendererFactory
{
private static readonly Direct2D1Platform s_instance = new Direct2D1Platform();
@ -38,6 +39,7 @@ namespace Avalonia.Direct2D1
public static void Initialize() => AvaloniaLocator.CurrentMutable
.Bind<IPlatformRenderInterface>().ToConstant(s_instance)
.Bind<IRendererFactory>().ToConstant(s_instance)
.BindToSelf(s_d2D1Factory)
.BindToSelf(s_dwfactory)
.BindToSelf(s_imagingFactory);
@ -59,7 +61,12 @@ namespace Avalonia.Direct2D1
return new FormattedTextImpl(text, fontFamily, fontSize, fontStyle, textAlignment, fontWeight, wrapping);
}
public IRenderTarget CreateRenderer(IPlatformHandle handle)
public IRenderer CreateRenderer(IRenderRoot root, IRenderLoop renderLoop)
{
return new Renderer(root, renderLoop);
}
public IRenderTarget CreateRenderTarget(IPlatformHandle handle)
{
if (handle.HandleDescriptor == "HWND")
{

1
src/Windows/Avalonia.Win32/Avalonia.Win32.csproj

@ -70,6 +70,7 @@
</Compile>
<Compile Include="Embedding\WpfAvaloniaControlHost.cs" />
<Compile Include="IconImpl.cs" />
<Compile Include="RenderLoop.cs" />
<Compile Include="SystemDialogImpl.cs" />
<Compile Include="CursorFactory.cs" />
<Compile Include="Input\KeyInterop.cs" />

10
src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs

@ -23,6 +23,8 @@ namespace Avalonia.Win32.Interop
public delegate void TimerProc(IntPtr hWnd, uint uMsg, IntPtr nIDEvent, uint dwTime);
public delegate void TimeCallback(uint uTimerID, uint uMsg, UIntPtr dwUser, UIntPtr dw1, UIntPtr dw2);
public delegate IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
public enum Cursor
@ -705,8 +707,6 @@ namespace Avalonia.Win32.Interop
[DllImport("user32.dll")]
public static extern IntPtr LoadCursor(IntPtr hInstance, IntPtr lpCursorName);
[DllImport("user32.dll")]
public static extern bool PeekMessage(out MSG lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax, uint wRemoveMsg);
@ -738,6 +738,12 @@ namespace Avalonia.Win32.Interop
[DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr hWnd, ShowWindowCommand nCmdShow);
[DllImport("Winmm.dll")]
public static extern uint timeKillEvent(uint uTimerID);
[DllImport("Winmm.dll")]
public static extern uint timeSetEvent(uint uDelay, uint uResolution, TimeCallback lpTimeProc, UIntPtr dwUser, uint fuEvent);
[DllImport("user32.dll")]
public static extern int ToUnicode(
uint virtualKeyCode,

35
src/Windows/Avalonia.Win32/RenderLoop.cs

@ -0,0 +1,35 @@
using System;
using System.Reactive.Disposables;
using Avalonia.Rendering;
using Avalonia.Win32.Interop;
namespace Avalonia.Win32
{
internal class RenderLoop : DefaultRenderLoop
{
private UnmanagedMethods.TimeCallback timerDelegate;
public RenderLoop(int framesPerSecond)
: base(framesPerSecond)
{
}
protected override IDisposable StartCore(Action tick)
{
timerDelegate = (id, uMsg, user, dw1, dw2) => tick();
var handle = UnmanagedMethods.timeSetEvent(
(uint)(1000 / FramesPerSecond),
0,
timerDelegate,
UIntPtr.Zero,
1);
return Disposable.Create(() =>
{
timerDelegate = null;
UnmanagedMethods.timeKillEvent(handle);
});
}
}
}

2
src/Windows/Avalonia.Win32/Win32Platform.cs

@ -16,6 +16,7 @@ using Avalonia.Win32.Input;
using Avalonia.Win32.Interop;
using Avalonia.Controls;
using System.IO;
using Avalonia.Rendering;
namespace Avalonia
{
@ -65,6 +66,7 @@ namespace Avalonia.Win32
.Bind<IMouseDevice>().ToConstant(WindowsMouseDevice.Instance)
.Bind<IPlatformSettings>().ToConstant(s_instance)
.Bind<IPlatformThreadingInterface>().ToConstant(s_instance)
.Bind<IRenderLoop>().ToConstant(new RenderLoop(60))
.Bind<ISystemDialogImpl>().ToSingleton<SystemDialogImpl>()
.Bind<IWindowingPlatform>().ToConstant(s_instance)
.Bind<IPlatformIconLoader>().ToConstant(s_instance);

19
src/Windows/Avalonia.Win32/WindowImpl.cs

@ -537,18 +537,15 @@ namespace Avalonia.Win32
break;
case UnmanagedMethods.WindowsMessage.WM_PAINT:
if (Paint != null)
{
UnmanagedMethods.PAINTSTRUCT ps;
UnmanagedMethods.PAINTSTRUCT ps;
if (UnmanagedMethods.BeginPaint(_hwnd, out ps) != IntPtr.Zero)
{
UnmanagedMethods.RECT r;
UnmanagedMethods.GetUpdateRect(_hwnd, out r, false);
var f = Scaling;
Paint(new Rect(r.left / f, r.top / f, (r.right - r.left) / f, (r.bottom - r.top) / f));
UnmanagedMethods.EndPaint(_hwnd, ref ps);
}
if (UnmanagedMethods.BeginPaint(_hwnd, out ps) != IntPtr.Zero)
{
UnmanagedMethods.RECT r;
UnmanagedMethods.GetUpdateRect(_hwnd, out r, false);
var f = Scaling;
Paint?.Invoke(new Rect(r.left / f, r.top / f, (r.right - r.left) / f, (r.bottom - r.top) / f));
UnmanagedMethods.EndPaint(_hwnd, ref ps);
}
return IntPtr.Zero;

14
tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization.cs

@ -10,6 +10,7 @@ using Avalonia.Controls.Presenters;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates;
using Avalonia.Layout;
using Avalonia.Platform;
using Avalonia.Rendering;
using Avalonia.UnitTests;
using Xunit;
@ -315,7 +316,18 @@ namespace Avalonia.Controls.UnitTests.Presenters
private class TestScroller : ScrollContentPresenter, IRenderRoot
{
public IRenderQueueManager RenderQueueManager { get; }
public IRenderer Renderer { get; }
public Size ClientSize { get; }
public IRenderTarget CreateRenderTarget()
{
throw new NotImplementedException();
}
public void Invalidate(Rect rect)
{
throw new NotImplementedException();
}
public Point PointToClient(Point point)
{

14
tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization_Simple.cs

@ -12,6 +12,7 @@ using Avalonia.Controls.Presenters;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates;
using Avalonia.Input;
using Avalonia.Platform;
using Avalonia.Rendering;
using Avalonia.UnitTests;
using Xunit;
@ -990,7 +991,18 @@ namespace Avalonia.Controls.UnitTests.Presenters
private class TestScroller : ScrollContentPresenter, IRenderRoot
{
public IRenderQueueManager RenderQueueManager { get; }
public IRenderer Renderer { get; }
public Size ClientSize { get; }
public IRenderTarget CreateRenderTarget()
{
throw new NotImplementedException();
}
public void Invalidate(Rect rect)
{
throw new NotImplementedException();
}
public Point PointToClient(Point point)
{

1
tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs

@ -268,7 +268,6 @@ namespace Avalonia.Controls.UnitTests.Primitives
globalStyles.Setup(x => x.Styles).Returns(styles);
var renderInterface = new Mock<IPlatformRenderInterface>();
renderInterface.Setup(x => x.CreateRenderer(It.IsAny<IPlatformHandle>())).Returns(() => new Mock<IRenderTarget>().Object);
AvaloniaLocator.CurrentMutable
.Bind<ILayoutManager>().ToTransient<LayoutManager>()

2
tests/Avalonia.Input.UnitTests/InputElement_HitTesting.cs

@ -340,7 +340,7 @@ namespace Avalonia.Input.UnitTests
throw new NotImplementedException();
}
public IRenderTarget CreateRenderer(IPlatformHandle handle)
public IRenderTarget CreateRenderTarget(IPlatformHandle handle)
{
throw new NotImplementedException();
}

2
tests/Avalonia.Layout.UnitTests/FullLayoutTests.cs

@ -137,7 +137,6 @@ namespace Avalonia.Layout.UnitTests
var formattedText = fixture.Create<IFormattedTextImpl>();
var globalStyles = new Mock<IGlobalStyles>();
var renderInterface = fixture.Create<IPlatformRenderInterface>();
var renderManager = fixture.Create<IRenderQueueManager>();
var windowImpl = new Mock<IWindowImpl>();
windowImpl.SetupProperty(x => x.ClientSize);
@ -151,7 +150,6 @@ namespace Avalonia.Layout.UnitTests
.Bind<ILayoutManager>().ToConstant(new LayoutManager())
.Bind<IRuntimePlatform>().ToConstant(new AppBuilder().RuntimePlatform)
.Bind<IPlatformRenderInterface>().ToConstant(renderInterface)
.Bind<IRenderQueueManager>().ToConstant(renderManager)
.Bind<IStyler>().ToConstant(new Styler())
.Bind<IWindowingPlatform>().ToConstant(new WindowingPlatformMock(() => windowImpl.Object));

25
tests/Avalonia.LeakTests/ControlTests.cs

@ -11,9 +11,11 @@ using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates;
using Avalonia.Diagnostics;
using Avalonia.Layout;
using Avalonia.Rendering;
using Avalonia.Styling;
using Avalonia.UnitTests;
using Avalonia.VisualTree;
using Moq;
using Xunit;
using Xunit.Abstractions;
@ -52,6 +54,7 @@ namespace Avalonia.LeakTests
};
var result = run();
PurgeMoqReferences();
dotMemory.Check(memory =>
Assert.Equal(0, memory.GetObjects(where => where.Type.Is<Canvas>()).ObjectsCount));
@ -87,6 +90,7 @@ namespace Avalonia.LeakTests
};
var result = run();
PurgeMoqReferences();
dotMemory.Check(memory =>
Assert.Equal(0, memory.GetObjects(where => where.Type.Is<Canvas>()).ObjectsCount));
@ -123,6 +127,7 @@ namespace Avalonia.LeakTests
};
var result = run();
PurgeMoqReferences();
dotMemory.Check(memory =>
Assert.Equal(0, memory.GetObjects(where => where.Type.Is<TextBox>()).ObjectsCount));
@ -158,6 +163,7 @@ namespace Avalonia.LeakTests
};
var result = run();
PurgeMoqReferences();
dotMemory.Check(memory =>
Assert.Equal(0, memory.GetObjects(where => where.Type.Is<TextBox>()).ObjectsCount));
@ -201,6 +207,7 @@ namespace Avalonia.LeakTests
};
var result = run();
PurgeMoqReferences();
dotMemory.Check(memory =>
Assert.Equal(0, memory.GetObjects(where => where.Type.Is<TextBox>()).ObjectsCount));
@ -287,25 +294,19 @@ namespace Avalonia.LeakTests
};
var result = run();
PurgeMoqReferences();
dotMemory.Check(memory =>
Assert.Equal(0, memory.GetObjects(where => where.Type.Is<TreeView>()).ObjectsCount));
}
}
private class TestTemplatedControl : TemplatedControl
private static void PurgeMoqReferences()
{
public static readonly StyledProperty<int> IsCanvasVisibleProperty =
AvaloniaProperty.Register<TestTemplatedControl, int>("IsCanvasVisible");
public TestTemplatedControl()
{
Template = new FuncControlTemplate<TestTemplatedControl>(parent =>
new Canvas
{
[~IsVisibleProperty] = parent[~IsCanvasVisibleProperty]
});
}
// Moq holds onto references in its mock of IRenderer in case we want to check if a method has been called;
// clear these.
var renderer = Mock.Get(AvaloniaLocator.Current.GetService<IRenderer>());
renderer.ResetCalls();
}
private class Node

13
tests/Avalonia.SceneGraph.UnitTests/TestRoot.cs

@ -9,12 +9,19 @@ namespace Avalonia.SceneGraph.UnitTests
{
public class TestRoot : TestVisual, IRenderRoot
{
public IRenderTarget RenderTarget
public Size ClientSize { get; }
public IRenderTarget CreateRenderTarget()
{
get { throw new NotImplementedException(); }
throw new NotImplementedException();
}
public void Invalidate(Rect rect)
{
throw new NotImplementedException();
}
public IRenderQueueManager RenderQueueManager
public IRenderer Renderer
{
get { throw new NotImplementedException(); }
}

2
tests/Avalonia.SceneGraph.UnitTests/VisualTree/MockRenderInterface.cs

@ -20,7 +20,7 @@ namespace Avalonia.SceneGraph.UnitTests.VisualTree
throw new NotImplementedException();
}
public IRenderTarget CreateRenderer(IPlatformHandle handle)
public IRenderTarget CreateRenderTarget(IPlatformHandle handle)
{
throw new NotImplementedException();
}

12
tests/Avalonia.UnitTests/TestRoot.cs

@ -41,7 +41,17 @@ namespace Avalonia.UnitTests
public IRenderTarget RenderTarget => null;
public IRenderQueueManager RenderQueueManager => null;
public IRenderer Renderer => null;
public IRenderTarget CreateRenderTarget()
{
throw new NotImplementedException();
}
public void Invalidate(Rect rect)
{
throw new NotImplementedException();
}
public Point PointToClient(Point p) => p;

16
tests/Avalonia.UnitTests/TestServices.cs

@ -11,6 +11,7 @@ using Avalonia.Platform;
using Avalonia.Shared.PlatformSupport;
using Avalonia.Styling;
using Avalonia.Themes.Default;
using Avalonia.Rendering;
namespace Avalonia.UnitTests
{
@ -20,7 +21,9 @@ namespace Avalonia.UnitTests
assetLoader: new AssetLoader(),
layoutManager: new LayoutManager(),
platform: new AppBuilder().RuntimePlatform,
renderer: Mock.Of<IRenderer>(),
renderInterface: CreateRenderInterfaceMock(),
renderLoop: Mock.Of<IRenderLoop>(),
standardCursorFactory: Mock.Of<IStandardCursorFactory>(),
styler: new Styler(),
theme: () => CreateDefaultTheme(),
@ -57,7 +60,9 @@ namespace Avalonia.UnitTests
Func<IKeyboardDevice> keyboardDevice = null,
ILayoutManager layoutManager = null,
IRuntimePlatform platform = null,
IRenderer renderer = null,
IPlatformRenderInterface renderInterface = null,
IRenderLoop renderLoop = null,
IStandardCursorFactory standardCursorFactory = null,
IStyler styler = null,
Func<Styles> theme = null,
@ -71,7 +76,9 @@ namespace Avalonia.UnitTests
KeyboardDevice = keyboardDevice;
LayoutManager = layoutManager;
Platform = platform;
Renderer = renderer;
RenderInterface = renderInterface;
RenderLoop = renderLoop;
StandardCursorFactory = standardCursorFactory;
Styler = styler;
Theme = theme;
@ -86,7 +93,9 @@ namespace Avalonia.UnitTests
public Func<IKeyboardDevice> KeyboardDevice { get; }
public ILayoutManager LayoutManager { get; }
public IRuntimePlatform Platform { get; }
public IRenderer Renderer { get; }
public IPlatformRenderInterface RenderInterface { get; }
public IRenderLoop RenderLoop { get; }
public IStandardCursorFactory StandardCursorFactory { get; }
public IStyler Styler { get; }
public Func<Styles> Theme { get; }
@ -101,7 +110,9 @@ namespace Avalonia.UnitTests
Func<IKeyboardDevice> keyboardDevice = null,
ILayoutManager layoutManager = null,
IRuntimePlatform platform = null,
IRenderer renderer = null,
IPlatformRenderInterface renderInterface = null,
IRenderLoop renderLoop = null,
IStandardCursorFactory standardCursorFactory = null,
IStyler styler = null,
Func<Styles> theme = null,
@ -116,7 +127,9 @@ namespace Avalonia.UnitTests
keyboardDevice: keyboardDevice ?? KeyboardDevice,
layoutManager: layoutManager ?? LayoutManager,
platform: platform ?? Platform,
renderer: renderer ?? Renderer,
renderInterface: renderInterface ?? RenderInterface,
renderLoop: renderLoop ?? RenderLoop,
standardCursorFactory: standardCursorFactory ?? StandardCursorFactory,
styler: styler ?? Styler,
theme: theme ?? Theme,
@ -152,8 +165,7 @@ namespace Avalonia.UnitTests
It.IsAny<FontWeight>(),
It.IsAny<TextWrapping>()) == Mock.Of<IFormattedTextImpl>() &&
x.CreateStreamGeometry() == Mock.Of<IStreamGeometryImpl>(
y => y.Open() == Mock.Of<IStreamGeometryContextImpl>()) &&
x.CreateRenderer(It.IsAny<IPlatformHandle>()) == Mock.Of<IRenderTarget>());
y => y.Open() == Mock.Of<IStreamGeometryContextImpl>()));
}
}
}

12
tests/Avalonia.UnitTests/TestTemplatedRoot.cs

@ -43,7 +43,17 @@ namespace Avalonia.UnitTests
public IRenderTarget RenderTarget => null;
public IRenderQueueManager RenderQueueManager => null;
public IRenderer Renderer => null;
public IRenderTarget CreateRenderTarget()
{
throw new NotImplementedException();
}
public void Invalidate(Rect rect)
{
throw new NotImplementedException();
}
public Point PointToClient(Point p) => p;

3
tests/Avalonia.UnitTests/UnitTestApplication.cs

@ -7,6 +7,7 @@ using Avalonia.Layout;
using Avalonia.Platform;
using Avalonia.Styling;
using Avalonia.Controls;
using Avalonia.Rendering;
namespace Avalonia.UnitTests
{
@ -42,7 +43,9 @@ namespace Avalonia.UnitTests
.Bind<IKeyboardDevice>().ToConstant(Services.KeyboardDevice?.Invoke())
.Bind<ILayoutManager>().ToConstant(Services.LayoutManager)
.Bind<IRuntimePlatform>().ToConstant(Services.Platform)
.Bind<IRenderer>().ToConstant(Services.Renderer)
.Bind<IPlatformRenderInterface>().ToConstant(Services.RenderInterface)
.Bind<IRenderLoop>().ToConstant(Services.RenderLoop)
.Bind<IPlatformThreadingInterface>().ToConstant(Services.ThreadingInterface)
.Bind<IStandardCursorFactory>().ToConstant(Services.StandardCursorFactory)
.Bind<IStyler>().ToConstant(Services.Styler)

Loading…
Cancel
Save