Browse Source

Merge branch 'master' into feature/ApplicationExitMode

pull/1662/head
Benedikt Schroeder 8 years ago
committed by GitHub
parent
commit
5158993db3
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      Avalonia.sln
  2. 261
      build.cake
  3. 17
      build/XUnit.props
  4. 15
      cake.config
  5. 2
      parameters.cake
  6. 9
      samples/ControlCatalog.Android/Resources/Resource.Designer.cs
  7. 1
      samples/interop/Direct3DInteropSample/MainWindow.cs
  8. 5
      src/Android/Avalonia.Android/Platform/SkiaPlatform/PopupImpl.cs
  9. 2
      src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidTouchEventsHelper.cs
  10. 7
      src/Android/Avalonia.Android/Resources/Resource.Designer.cs
  11. 9
      src/Android/Avalonia.AndroidTestApplication/Resources/Resource.Designer.cs
  12. 2
      src/Avalonia.Animation/AnimatorKeyFrame.cs
  13. 6
      src/Avalonia.Base/Data/Core/ExpressionNode.cs
  14. 4
      src/Avalonia.Base/Data/Core/ExpressionObserver.cs
  15. 15
      src/Avalonia.Base/Data/Core/ISettableNode.cs
  16. 6
      src/Avalonia.Base/Data/Core/IndexerNode.cs
  17. 17
      src/Avalonia.Base/Data/Core/PropertyAccessorNode.cs
  18. 38
      src/Avalonia.Base/Data/Core/SettableNode.cs
  19. 4
      src/Avalonia.Controls/AppBuilderBase.cs
  20. 5
      src/Avalonia.Controls/Platform/IWindowBaseImpl.cs
  21. 2
      src/Avalonia.Controls/Platform/InProcessDragSource.cs
  22. 20
      src/Avalonia.Controls/Presenters/CarouselPresenter.cs
  23. 16
      src/Avalonia.Controls/Primitives/Popup.cs
  24. 37
      src/Avalonia.Controls/Primitives/ScrollBar.cs
  25. 53
      src/Avalonia.Controls/Primitives/ScrollEventType.cs
  26. 3
      src/Avalonia.Controls/ToolTip.cs
  27. 14
      src/Avalonia.Controls/WindowBase.cs
  28. 6
      src/Avalonia.DesignerSupport/Remote/DetachableTransportConnection.cs
  29. 10
      src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs
  30. 6
      src/Avalonia.DesignerSupport/Remote/RemoteDesignerEntryPoint.cs
  31. 4
      src/Avalonia.DesignerSupport/Remote/Stubs.cs
  32. 24
      src/Avalonia.Input/DragDropDevice.cs
  33. 5
      src/Avalonia.Input/DragEventArgs.cs
  34. 4
      src/Avalonia.Input/Raw/RawDragEvent.cs
  35. 4
      src/Avalonia.Remote.Protocol/TcpTransportBase.cs
  36. 2
      src/Avalonia.Visuals/Media/DrawingContext.cs
  37. 6
      src/Avalonia.Visuals/Media/Fonts/FontFamilyKey.cs
  38. 20
      src/Avalonia.Visuals/Rendering/IRendererFactory.cs
  39. 5
      src/Gtk/Avalonia.Gtk3/Interop/GlibTimeout.cs
  40. 9
      src/Gtk/Avalonia.Gtk3/Interop/Native.cs
  41. 2
      src/Gtk/Avalonia.Gtk3/WindowBaseImpl.cs
  42. 2
      src/Gtk/Avalonia.Gtk3/WindowImpl.cs
  43. 6
      src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs
  44. 14
      src/Markup/Avalonia.Markup.Xaml/PortableXaml/TypeDescriptorExtensions.cs
  45. 6
      src/Markup/Avalonia.Markup.Xaml/Styling/StyleInclude.cs
  46. 3
      src/OSX/Avalonia.MonoMac/ClipboardImpl.cs
  47. 9
      src/OSX/Avalonia.MonoMac/SystemDialogsImpl.cs
  48. 3
      src/OSX/Avalonia.MonoMac/TopLevelImpl.cs
  49. 1
      src/OSX/Avalonia.MonoMac/WindowBaseImpl.cs
  50. 54
      src/Skia/Avalonia.Skia/FormattedTextImpl.cs
  51. 1
      src/Windows/Avalonia.Direct2D1/Media/Imaging/D2DBitmapImpl.cs
  52. 1
      src/Windows/Avalonia.Direct2D1/Media/TransformedGeometryImpl.cs
  53. 18
      src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs
  54. 9
      src/Windows/Avalonia.Win32/OleDragSource.cs
  55. 43
      src/Windows/Avalonia.Win32/OleDropTarget.cs
  56. 28
      src/Windows/Avalonia.Win32/WindowImpl.cs
  57. 2
      src/iOS/Avalonia.iOS/DisplayLinkRenderLoop.cs
  58. 6
      src/iOS/Avalonia.iOS/EmbeddableImpl.cs
  59. 3
      src/iOS/Avalonia.iOS/TopLevelImpl.cs
  60. 49
      tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Binding.cs
  61. 2
      tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Threading.cs
  62. 5
      tests/Avalonia.Controls.UnitTests/AppBuilderTests.cs
  63. 35
      tests/Avalonia.Controls.UnitTests/CarouselTests.cs
  64. 59
      tests/Avalonia.Controls.UnitTests/Primitives/ScrollBarTests.cs
  65. 2
      tests/Avalonia.DesignerSupport.TestApp/Avalonia.DesignerSupport.TestApp.csproj
  66. 8
      tests/Avalonia.DesignerSupport.Tests/DesignerSupportTests.cs
  67. 2
      tests/Avalonia.Interactivity.UnitTests/InteractiveTests.cs
  68. 1
      tests/Avalonia.Layout.UnitTests/FullLayoutTests.cs
  69. 9
      tests/Avalonia.LeakTests/Avalonia.LeakTests.csproj
  70. 8
      tests/Avalonia.LeakTests/Properties/AssemblyInfo.cs
  71. 11
      tests/Avalonia.LeakTests/toolproject/tool.csproj
  72. 2
      tests/Avalonia.RenderTests/TestBase.cs
  73. 22
      tests/Avalonia.UnitTests/Avalonia.UnitTests.csproj
  74. 16
      tests/Avalonia.UnitTests/RuntimeInfo.cs
  75. 14
      tests/Avalonia.UnitTests/TestServices.cs
  76. 11
      tests/Avalonia.UnitTests/app.config
  77. 2
      tools/packages.config

5
Avalonia.sln

@ -105,9 +105,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlCatalog.Desktop", "s
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCatalog.iOS", "samples\ControlCatalog.iOS\ControlCatalog.iOS.csproj", "{57E0455D-D565-44BB-B069-EE1AA20F8337}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.DesignerSupport.Tests", "tests\Avalonia.DesignerSupport.Tests\Avalonia.DesignerSupport.Tests.csproj", "{52F55355-D120-42AC-8116-8410A7D602FA}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.DesignerSupport.Tests", "tests\Avalonia.DesignerSupport.Tests\Avalonia.DesignerSupport.Tests.csproj", "{52F55355-D120-42AC-8116-8410A7D602FA}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.DesignerSupport.TestApp", "tests\Avalonia.DesignerSupport.TestApp\Avalonia.DesignerSupport.TestApp.csproj", "{F1381F98-4D24-409A-A6C5-1C5B1E08BB08}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.DesignerSupport.TestApp", "tests\Avalonia.DesignerSupport.TestApp\Avalonia.DesignerSupport.TestApp.csproj", "{F1381F98-4D24-409A-A6C5-1C5B1E08BB08}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VirtualizationTest", "samples\VirtualizationTest\VirtualizationTest.csproj", "{FBCAF3D0-2808-4934-8E96-3F607594517B}"
EndProject
@ -141,7 +141,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Props", "Props", "{F3AC8BC1
build\Microsoft.Reactive.Testing.props = build\Microsoft.Reactive.Testing.props
build\Moq.props = build\Moq.props
build\NetCore.props = build\NetCore.props
build\NetFX.props = build\NetFX.props
build\ReactiveUI.props = build\ReactiveUI.props
build\Rx.props = build\Rx.props
build\SampleApp.props = build\SampleApp.props

261
build.cake

@ -10,7 +10,8 @@
// TOOLS
///////////////////////////////////////////////////////////////////////////////
#tool "nuget:?package=xunit.runner.console&version=2.3.0-beta5-build3769"
#tool "nuget:?package=xunit.runner.console&version=2.3.1"
#tool "nuget:?package=JetBrains.dotMemoryUnit&version=3.0.20171219.105559"
///////////////////////////////////////////////////////////////////////////////
// USINGS
@ -34,20 +35,31 @@ using NuGet;
// PARAMETERS
//////////////////////////////////////////////////////////////////////
Parameters parameters = new Parameters(Context);
Packages packages = new Packages(Context, parameters);
class AvaloniaBuildData
{
public AvaloniaBuildData(Parameters parameters, Packages packages)
{
Parameters = parameters;
Packages = packages;
}
public Parameters Parameters { get; }
public Packages Packages { get; }
}
///////////////////////////////////////////////////////////////////////////////
// SETUP
///////////////////////////////////////////////////////////////////////////////
Setup(context =>
Setup<AvaloniaBuildData>(context =>
{
Information("Building version {0} of Avalonia ({1}, {2}, {3}) using version {4} of Cake.",
var parameters = new Parameters(context);
var buildContext = new AvaloniaBuildData(parameters, new Packages(context, parameters));
Information("Building version {0} of Avalonia ({1}, {2}) using version {3} of Cake.",
parameters.Version,
parameters.Platform,
parameters.Configuration,
parameters.Target,
typeof(ICakeContext).Assembly.GetName().Version.ToString());
if (parameters.IsRunningOnAppVeyor)
@ -55,8 +67,7 @@ Setup(context =>
Information("Repository Name: " + BuildSystem.AppVeyor.Environment.Repository.Name);
Information("Repository Branch: " + BuildSystem.AppVeyor.Environment.Repository.Branch);
}
Information("Target: " + parameters.Target);
Information("Target:" + context.TargetTask.Name);
Information("Platform: " + parameters.Platform);
Information("Configuration: " + parameters.Configuration);
Information("IsLocalBuild: " + parameters.IsLocalBuild);
@ -70,13 +81,15 @@ Setup(context =>
Information("IsReleasable: " + parameters.IsReleasable);
Information("IsMyGetRelease: " + parameters.IsMyGetRelease);
Information("IsNuGetRelease: " + parameters.IsNuGetRelease);
return buildContext;
});
///////////////////////////////////////////////////////////////////////////////
// TEARDOWN
///////////////////////////////////////////////////////////////////////////////
Teardown(context =>
Teardown<AvaloniaBuildData>((context, buildContext) =>
{
Information("Finished running tasks.");
});
@ -86,19 +99,19 @@ Teardown(context =>
///////////////////////////////////////////////////////////////////////////////
Task("Clean")
.Does(() =>
.Does<AvaloniaBuildData>(data =>
{
CleanDirectories(parameters.BuildDirs);
CleanDirectory(parameters.ArtifactsDir);
CleanDirectory(parameters.NugetRoot);
CleanDirectory(parameters.ZipRoot);
CleanDirectory(parameters.BinRoot);
CleanDirectories(data.Parameters.BuildDirs);
CleanDirectory(data.Parameters.ArtifactsDir);
CleanDirectory(data.Parameters.NugetRoot);
CleanDirectory(data.Parameters.ZipRoot);
CleanDirectory(data.Parameters.BinRoot);
});
Task("Restore-NuGet-Packages")
.IsDependentOn("Clean")
.WithCriteria(parameters.IsRunningOnWindows)
.Does(() =>
.WithCriteria<AvaloniaBuildData>((context, data) => data.Parameters.IsRunningOnWindows)
.Does<AvaloniaBuildData>(data =>
{
var maxRetryCount = 5;
var toolTimeout = 2d;
@ -115,13 +128,13 @@ Task("Restore-NuGet-Packages")
toolTimeout+=0.5;
}})
.Execute(()=> {
NuGetRestore(parameters.MSBuildSolution, new NuGetRestoreSettings {
NuGetRestore(data.Parameters.MSBuildSolution, new NuGetRestoreSettings {
ToolTimeout = TimeSpan.FromMinutes(toolTimeout)
});
});
});
void DotNetCoreBuild()
void DotNetCoreBuild(Parameters parameters)
{
var settings = new DotNetCoreBuildSettings
{
@ -137,23 +150,24 @@ void DotNetCoreBuild()
Task("Build")
.IsDependentOn("Restore-NuGet-Packages")
.Does(() =>
.Does<AvaloniaBuildData>(data =>
{
if(parameters.IsRunningOnWindows)
if(data.Parameters.IsRunningOnWindows)
{
MSBuild(parameters.MSBuildSolution, settings => {
settings.SetConfiguration(parameters.Configuration);
MSBuild(data.Parameters.MSBuildSolution, settings => {
settings.SetConfiguration(data.Parameters.Configuration);
settings.SetVerbosity(Verbosity.Minimal);
settings.WithProperty("Platform", "\"" + parameters.Platform + "\"");
settings.WithProperty("Platform", "\"" + data.Parameters.Platform + "\"");
settings.WithProperty("UseRoslynPathHack", "true");
settings.UseToolVersion(MSBuildToolVersion.VS2017);
settings.WithProperty("Windows", "True");
settings.SetNodeReuse(false);
settings.SetMaxCpuCount(0);
});
}
else
{
DotNetCoreBuild();
DotNetCoreBuild(data.Parameters);
}
});
@ -182,68 +196,94 @@ void RunCoreTest(string project, Parameters parameters, bool coreOnly = false)
Task("Run-Unit-Tests")
.IsDependentOn("Build")
.IsDependentOn("Run-Designer-Tests")
.IsDependentOn("Run-Render-Tests")
.WithCriteria(() => !parameters.SkipTests)
.Does(() => {
RunCoreTest("./tests/Avalonia.Base.UnitTests", parameters, false);
RunCoreTest("./tests/Avalonia.Controls.UnitTests", parameters, false);
RunCoreTest("./tests/Avalonia.Input.UnitTests", parameters, false);
RunCoreTest("./tests/Avalonia.Interactivity.UnitTests", parameters, false);
RunCoreTest("./tests/Avalonia.Layout.UnitTests", parameters, false);
RunCoreTest("./tests/Avalonia.Markup.UnitTests", parameters, false);
RunCoreTest("./tests/Avalonia.Markup.Xaml.UnitTests", parameters, false);
RunCoreTest("./tests/Avalonia.Styling.UnitTests", parameters, false);
RunCoreTest("./tests/Avalonia.Visuals.UnitTests", parameters, false);
if (parameters.IsRunningOnWindows)
.WithCriteria<AvaloniaBuildData>((context, data) => !data.Parameters.SkipTests)
.Does<AvaloniaBuildData>(data => {
RunCoreTest("./tests/Avalonia.Base.UnitTests", data.Parameters, false);
RunCoreTest("./tests/Avalonia.Controls.UnitTests", data.Parameters, false);
RunCoreTest("./tests/Avalonia.Input.UnitTests", data.Parameters, false);
RunCoreTest("./tests/Avalonia.Interactivity.UnitTests", data.Parameters, false);
RunCoreTest("./tests/Avalonia.Layout.UnitTests", data.Parameters, false);
RunCoreTest("./tests/Avalonia.Markup.UnitTests", data.Parameters, false);
RunCoreTest("./tests/Avalonia.Markup.Xaml.UnitTests", data.Parameters, false);
RunCoreTest("./tests/Avalonia.Styling.UnitTests", data.Parameters, false);
RunCoreTest("./tests/Avalonia.Visuals.UnitTests", data.Parameters, false);
if (data.Parameters.IsRunningOnWindows)
{
RunCoreTest("./tests/Avalonia.Direct2D1.UnitTests", parameters, true);
RunCoreTest("./tests/Avalonia.Direct2D1.UnitTests", data.Parameters, true);
}
});
Task("Run-Designer-Tests")
.IsDependentOn("Build")
.WithCriteria(() => !parameters.SkipTests)
.Does(() => {
RunCoreTest("./tests/Avalonia.DesignerSupport.Tests", parameters, false);
.WithCriteria<AvaloniaBuildData>((context, data) => !data.Parameters.SkipTests)
.Does<AvaloniaBuildData>(data => {
RunCoreTest("./tests/Avalonia.DesignerSupport.Tests", data.Parameters, false);
});
Task("Run-Render-Tests")
.IsDependentOn("Build")
.WithCriteria(() => !parameters.SkipTests && parameters.IsRunningOnWindows)
.Does(() => {
RunCoreTest("./tests/Avalonia.Skia.RenderTests/Avalonia.Skia.RenderTests.csproj", parameters, true);
RunCoreTest("./tests/Avalonia.Direct2D1.RenderTests/Avalonia.Direct2D1.RenderTests.csproj", parameters, true);
.WithCriteria<AvaloniaBuildData>((context, data) => !data.Parameters.SkipTests && data.Parameters.IsRunningOnWindows)
.Does<AvaloniaBuildData>(data => {
RunCoreTest("./tests/Avalonia.Skia.RenderTests/Avalonia.Skia.RenderTests.csproj", data.Parameters, true);
RunCoreTest("./tests/Avalonia.Direct2D1.RenderTests/Avalonia.Direct2D1.RenderTests.csproj", data.Parameters, true);
});
Task("Copy-Files")
.IsDependentOn("Run-Unit-Tests")
Task("Run-Leak-Tests")
.WithCriteria<AvaloniaBuildData>((context, data) => !data.Parameters.SkipTests && data.Parameters.IsRunningOnWindows)
.IsDependentOn("Build")
.Does(() =>
{
var dotMemoryUnit = Context.Tools.Resolve("dotMemoryUnit.exe");
var leakTestsExitCode = StartProcess(dotMemoryUnit, new ProcessSettings
{
Arguments = new ProcessArgumentBuilder()
.Append(Context.Tools.Resolve("xunit.console.x86.exe").FullPath)
.Append("--propagate-exit-code")
.Append("--")
.Append("tests\\Avalonia.LeakTests\\bin\\Release\\net461\\Avalonia.LeakTests.dll"),
Timeout = 120000
});
if (leakTestsExitCode != 0)
{
throw new Exception("Leak Tests failed");
}
});
Task("Run-Tests")
.IsDependentOn("Run-Unit-Tests")
.IsDependentOn("Run-Render-Tests")
.IsDependentOn("Run-Designer-Tests")
.IsDependentOn("Run-Leak-Tests");
Task("Copy-Files")
.IsDependentOn("Run-Tests")
.Does<AvaloniaBuildData>(data =>
{
CopyFiles(packages.BinFiles, parameters.BinRoot);
CopyFiles(data.Packages.BinFiles, data.Parameters.BinRoot);
});
Task("Zip-Files")
.IsDependentOn("Copy-Files")
.Does(() =>
.Does<AvaloniaBuildData>(data =>
{
Zip(parameters.BinRoot, parameters.ZipCoreArtifacts);
Zip(parameters.ZipSourceControlCatalogDesktopDirs,
parameters.ZipTargetControlCatalogDesktopDirs,
GetFiles(parameters.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.dll") +
GetFiles(parameters.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.config") +
GetFiles(parameters.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.so") +
GetFiles(parameters.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.dylib") +
GetFiles(parameters.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.exe"));
Zip(data.Parameters.BinRoot, data.Parameters.ZipCoreArtifacts);
Zip(data.Parameters.ZipSourceControlCatalogDesktopDirs,
data.Parameters.ZipTargetControlCatalogDesktopDirs,
GetFiles(data.Parameters.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.dll") +
GetFiles(data.Parameters.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.config") +
GetFiles(data.Parameters.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.so") +
GetFiles(data.Parameters.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.dylib") +
GetFiles(data.Parameters.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.exe"));
});
Task("Create-NuGet-Packages")
.IsDependentOn("Run-Unit-Tests")
.IsDependentOn("Run-Tests")
.IsDependentOn("Inspect")
.Does(() =>
.Does<AvaloniaBuildData>(data =>
{
foreach(var nuspec in packages.NuspecNuGetSettings)
foreach(var nuspec in data.Packages.NuspecNuGetSettings)
{
NuGetPack(nuspec);
}
@ -251,12 +291,12 @@ Task("Create-NuGet-Packages")
Task("Publish-MyGet")
.IsDependentOn("Create-NuGet-Packages")
.WithCriteria(() => !parameters.IsLocalBuild)
.WithCriteria(() => !parameters.IsPullRequest)
.WithCriteria(() => parameters.IsMainRepo)
.WithCriteria(() => parameters.IsMasterBranch)
.WithCriteria(() => parameters.IsMyGetRelease)
.Does(() =>
.WithCriteria<AvaloniaBuildData>((context, data) => !data.Parameters.IsLocalBuild)
.WithCriteria<AvaloniaBuildData>((context, data) => !data.Parameters.IsPullRequest)
.WithCriteria<AvaloniaBuildData>((context, data) => data.Parameters.IsMainRepo)
.WithCriteria<AvaloniaBuildData>((context, data) => data.Parameters.IsMasterBranch)
.WithCriteria<AvaloniaBuildData>((context, data) => data.Parameters.IsMyGetRelease)
.Does<AvaloniaBuildData>(data =>
{
var apiKey = EnvironmentVariable("MYGET_API_KEY");
if(string.IsNullOrEmpty(apiKey))
@ -270,7 +310,7 @@ Task("Publish-MyGet")
throw new InvalidOperationException("Could not resolve MyGet API url.");
}
foreach(var nupkg in packages.NugetPackages)
foreach(var nupkg in data.Packages.NugetPackages)
{
NuGetPush(nupkg, new NuGetPushSettings {
Source = apiUrl,
@ -285,11 +325,11 @@ Task("Publish-MyGet")
Task("Publish-NuGet")
.IsDependentOn("Create-NuGet-Packages")
.WithCriteria(() => !parameters.IsLocalBuild)
.WithCriteria(() => !parameters.IsPullRequest)
.WithCriteria(() => parameters.IsMainRepo)
.WithCriteria(() => parameters.IsNuGetRelease)
.Does(() =>
.WithCriteria<AvaloniaBuildData>((context, data) => !data.Parameters.IsLocalBuild)
.WithCriteria<AvaloniaBuildData>((context, data) => !data.Parameters.IsPullRequest)
.WithCriteria<AvaloniaBuildData>((context, data) => data.Parameters.IsMainRepo)
.WithCriteria<AvaloniaBuildData>((context, data) => data.Parameters.IsNuGetRelease)
.Does<AvaloniaBuildData>(data =>
{
var apiKey = EnvironmentVariable("NUGET_API_KEY");
if(string.IsNullOrEmpty(apiKey))
@ -303,7 +343,7 @@ Task("Publish-NuGet")
throw new InvalidOperationException("Could not resolve NuGet API url.");
}
foreach(var nupkg in packages.NugetPackages)
foreach(var nupkg in data.Packages.NugetPackages)
{
NuGetPush(nupkg, new NuGetPushSettings {
ApiKey = apiKey,
@ -316,48 +356,8 @@ Task("Publish-NuGet")
Information("Publish-NuGet Task failed, but continuing with next Task...");
});
Task("Run-Leak-Tests")
.WithCriteria(parameters.IsRunningOnWindows)
.IsDependentOn("Build")
.Does(() =>
{
DotNetCoreRestore("tests\\Avalonia.LeakTests\\toolproject\\tool.csproj");
DotNetBuild("tests\\Avalonia.LeakTests\\toolproject\\tool.csproj", settings => settings.SetConfiguration("Release"));
var report = "tests\\Avalonia.LeakTests\\bin\\Release\\report.xml";
if(System.IO.File.Exists(report))
System.IO.File.Delete(report);
var toolXunitConsoleX86 = Context.Tools.Resolve("xunit.console.x86.exe").FullPath;
var proc = System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo
{
FileName="tests\\Avalonia.LeakTests\\toolproject\\bin\\dotMemoryUnit.exe",
Arguments="-targetExecutable=\"" + toolXunitConsoleX86 + "\" -returnTargetExitCode -- tests\\Avalonia.LeakTests\\bin\\Release\\Avalonia.LeakTests.dll -xml tests\\Avalonia.LeakTests\\bin\\Release\\report.xml ",
UseShellExecute = false,
});
var st = System.Diagnostics.Stopwatch.StartNew();
while(!proc.HasExited && !System.IO.File.Exists(report))
{
if(st.Elapsed.TotalSeconds>60)
{
Error("Timed out, probably a bug in dotMemoryUnit");
proc.Kill();
throw new Exception("dotMemory issue");
}
proc.WaitForExit(100);
}
try{
proc.Kill();
}catch{}
var doc = System.Xml.Linq.XDocument.Load(report);
if(doc.Root.Descendants("assembly").Any(x=>x.Attribute("failed").Value.ToString() != "0"))
{
throw new Exception("Tests failed");
}
});
Task("Inspect")
.WithCriteria(parameters.IsRunningOnWindows)
.WithCriteria<AvaloniaBuildData>((context, data) => data.Parameters.IsRunningOnWindows)
.IsDependentOn("Restore-NuGet-Packages")
.Does(() =>
{
@ -366,8 +366,13 @@ Task("Inspect")
"src\\markup\\avalonia.markup.xaml\\portablexaml\\portable.xaml.github"};
Information("Running code inspections");
StartProcess(Context.Tools.Resolve("inspectcode.exe"),
new ProcessSettings{ Arguments = "--output=artifacts\\inspectcode.xml --profile=Avalonia.sln.DotSettings Avalonia.sln" });
var exitCode = StartProcess(Context.Tools.Resolve("inspectcode.exe"),
new ProcessSettings
{
Arguments = "--output=artifacts\\inspectcode.xml --profile=Avalonia.sln.DotSettings Avalonia.sln",
RedirectStandardOutput = true
});
Information("Analyzing report");
var doc = XDocument.Parse(System.IO.File.ReadAllText("artifacts\\inspectcode.xml"));
var failBuild = false;
@ -395,23 +400,23 @@ Task("Inspect")
Task("Package")
.IsDependentOn("Create-NuGet-Packages");
Task("Default").Does(() =>
{
if(parameters.IsRunningOnWindows)
RunTarget("Package");
else
RunTarget("Run-Unit-Tests");
});
Task("AppVeyor")
.IsDependentOn("Zip-Files")
.IsDependentOn("Publish-MyGet")
.IsDependentOn("Publish-NuGet");
Task("Travis")
.IsDependentOn("Run-Unit-Tests");
.IsDependentOn("Run-Tests");
///////////////////////////////////////////////////////////////////////////////
// EXECUTE
///////////////////////////////////////////////////////////////////////////////
RunTarget(parameters.Target);
var target = Context.Argument("target", "Default");
if (target == "Default")
{
target = Context.IsRunningOnWindows() ? "Package" : "Run-Tests";
}
RunTarget(target);

17
build/XUnit.props

@ -9,21 +9,6 @@
<PackageReference Include="xunit.runner.console" Version="2.3.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.0" />
<PackageReference Include="Xunit.SkippableFact" Version="1.3.6" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp2.0'">
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" />
</ItemGroup>
<PropertyGroup>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
</PropertyGroup>
<Target Name="ForceGenerationOfBindingRedirects"
AfterTargets="ResolveAssemblyReferences"
BeforeTargets="GenerateBindingRedirects"
Condition="'$(AutoGenerateBindingRedirects)' == 'true'">
<PropertyGroup>
<!-- Needs to be set in a target because it has to be set after the initial evaluation in the common targets -->
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
</PropertyGroup>
</Target>
<Import Project="$(MSBuildThisFileDirectory)\NetFX.props" />
</Project>

15
cake.config

@ -0,0 +1,15 @@
; This is the default configuration file for Cake.
; This file was downloaded from https://github.com/cake-build/resources
[Nuget]
Source=https://api.nuget.org/v3/index.json
UseInProcessClient=true
LoadDependencies=false
[Paths]
Tools=./tools
Addins=./tools/Addins
Modules=./tools/Modules
[Settings]
SkipVerification=false

2
parameters.cake

@ -1,6 +1,5 @@
public class Parameters
{
public string Target { get; private set; }
public string Platform { get; private set; }
public string Configuration { get; private set; }
public bool SkipTests { get; private set; }
@ -43,7 +42,6 @@ public class Parameters
var buildSystem = context.BuildSystem();
// ARGUMENTS
Target = context.Argument("target", "Default");
Platform = context.Argument("platform", "Any CPU");
Configuration = context.Argument("configuration", "Release");
SkipTests = context.HasArgument("skip-tests");

9
samples/ControlCatalog.Android/Resources/Resource.Designer.cs

@ -28,8 +28,6 @@ namespace ControlCatalog.Android
{
global::Avalonia.Android.Resource.String.ApplicationName = global::ControlCatalog.Android.Resource.String.ApplicationName;
global::Avalonia.Android.Resource.String.Hello = global::ControlCatalog.Android.Resource.String.Hello;
global::Avalonia.Android.Resource.String.library_name = global::ControlCatalog.Android.Resource.String.library_name;
global::Splat.Resource.String.library_name = global::ControlCatalog.Android.Resource.String.library_name;
}
public partial class Attribute
@ -96,14 +94,11 @@ namespace ControlCatalog.Android
public partial class String
{
// aapt resource value: 0x7f040002
public const int ApplicationName = 2130968578;
// aapt resource value: 0x7f040001
public const int Hello = 2130968577;
public const int ApplicationName = 2130968577;
// aapt resource value: 0x7f040000
public const int library_name = 2130968576;
public const int Hello = 2130968576;
static String()
{

1
samples/interop/Direct3DInteropSample/MainWindow.cs

@ -88,7 +88,6 @@ namespace Direct3DInteropSample
context.ClearDepthStencilView(depthView, DepthStencilClearFlags.Depth, 1.0f, 0);
context.ClearRenderTargetView(renderView, Color.White);
var time = 50;
// Update WorldViewProj Matrix
var worldViewProj = Matrix.RotationX((float) _model.RotationX) * Matrix.RotationY((float) _model.RotationY) *
Matrix.RotationZ((float) _model.RotationZ)

5
src/Android/Avalonia.Android/Platform/SkiaPlatform/PopupImpl.cs

@ -110,7 +110,10 @@ namespace Avalonia.Android.Platform.SkiaPlatform
{
//Not supported
}
public void SetTopmost(bool value)
{
//Not supported
}
}
}

2
src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidTouchEventsHelper.cs

@ -126,8 +126,6 @@ namespace Avalonia.Android.Platform.Specific.Helpers
return e.Action != MotionEventActions.Up;
}
private Paint _paint;
public void Dispose()
{
HandleEvents = false;

7
src/Android/Avalonia.Android/Resources/Resource.Designer.cs

@ -40,14 +40,11 @@ namespace Avalonia.Android
public partial class String
{
// aapt resource value: 0x7f020002
public static int ApplicationName = 2130837506;
// aapt resource value: 0x7f020001
public static int Hello = 2130837505;
public static int ApplicationName = 2130837505;
// aapt resource value: 0x7f020000
public static int library_name = 2130837504;
public static int Hello = 2130837504;
static String()
{

9
src/Android/Avalonia.AndroidTestApplication/Resources/Resource.Designer.cs

@ -28,8 +28,6 @@ namespace Avalonia.AndroidTestApplication
{
global::Avalonia.Android.Resource.String.ApplicationName = global::Avalonia.AndroidTestApplication.Resource.String.ApplicationName;
global::Avalonia.Android.Resource.String.Hello = global::Avalonia.AndroidTestApplication.Resource.String.Hello;
global::Avalonia.Android.Resource.String.library_name = global::Avalonia.AndroidTestApplication.Resource.String.library_name;
global::Splat.Resource.String.library_name = global::Avalonia.AndroidTestApplication.Resource.String.library_name;
}
public partial class Attribute
@ -64,14 +62,11 @@ namespace Avalonia.AndroidTestApplication
public partial class String
{
// aapt resource value: 0x7f030002
public const int ApplicationName = 2130903042;
// aapt resource value: 0x7f030001
public const int Hello = 2130903041;
public const int ApplicationName = 2130903041;
// aapt resource value: 0x7f030000
public const int library_name = 2130903040;
public const int Hello = 2130903040;
static String()
{

2
src/Avalonia.Animation/AnimatorKeyFrame.cs

@ -9,7 +9,7 @@ namespace Avalonia.Animation
{
/// <summary>
/// Defines a KeyFrame that is used for
/// <see cref="Animators"/> objects.
/// <see cref="Animator{T}"/> objects.
/// </summary>
public class AnimatorKeyFrame
{

6
src/Avalonia.Base/Data/Core/ExpressionNode.cs

@ -11,6 +11,7 @@ namespace Avalonia.Data.Core
{
internal abstract class ExpressionNode : ISubject<object>
{
private static readonly object CacheInvalid = new object();
protected static readonly WeakReference UnsetReference =
new WeakReference(AvaloniaProperty.UnsetValue);
@ -18,6 +19,8 @@ namespace Avalonia.Data.Core
private IDisposable _valueSubscription;
private IObserver<object> _observer;
protected WeakReference LastValue { get; private set; }
public abstract string Description { get; }
public ExpressionNode Next { get; set; }
@ -61,6 +64,7 @@ namespace Avalonia.Data.Core
{
_valueSubscription?.Dispose();
_valueSubscription = null;
LastValue = null;
nextSubscription?.Dispose();
_observer = null;
});
@ -120,6 +124,7 @@ namespace Avalonia.Data.Core
if (notification == null)
{
LastValue = new WeakReference(value);
if (Next != null)
{
Next.Target = new WeakReference(value);
@ -131,6 +136,7 @@ namespace Avalonia.Data.Core
}
else
{
LastValue = new WeakReference(notification.Value);
if (Next != null)
{
Next.Target = new WeakReference(notification.Value);

4
src/Avalonia.Base/Data/Core/ExpressionObserver.cs

@ -154,7 +154,7 @@ namespace Avalonia.Data.Core
/// </returns>
public bool SetValue(object value, BindingPriority priority = BindingPriority.LocalValue)
{
if (Leaf is ISettableNode settable)
if (Leaf is SettableNode settable)
{
var node = _node;
while (node != null)
@ -188,7 +188,7 @@ namespace Avalonia.Data.Core
/// Gets the type of the expression result or null if the expression could not be
/// evaluated.
/// </summary>
public Type ResultType => (Leaf as ISettableNode)?.PropertyType;
public Type ResultType => (Leaf as SettableNode)?.PropertyType;
/// <summary>
/// Gets the leaf node.

15
src/Avalonia.Base/Data/Core/ISettableNode.cs

@ -1,15 +0,0 @@
using Avalonia.Data;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Avalonia.Data.Core
{
interface ISettableNode
{
bool SetTargetValue(object value, BindingPriority priority);
Type PropertyType { get; }
}
}

6
src/Avalonia.Base/Data/Core/IndexerNode.cs

@ -15,7 +15,7 @@ using Avalonia.Data;
namespace Avalonia.Data.Core
{
internal class IndexerNode : ExpressionNode, ISettableNode
internal class IndexerNode : SettableNode
{
public IndexerNode(IList<string> arguments)
{
@ -52,7 +52,7 @@ namespace Avalonia.Data.Core
return Observable.Merge(inputs).StartWith(GetValue(target));
}
public bool SetTargetValue(object value, BindingPriority priority)
protected override bool SetTargetValueCore(object value, BindingPriority priority)
{
var typeInfo = Target.Target.GetType().GetTypeInfo();
var list = Target.Target as IList;
@ -154,7 +154,7 @@ namespace Avalonia.Data.Core
public IList<string> Arguments { get; }
public Type PropertyType => GetIndexer(Target.Target.GetType().GetTypeInfo())?.PropertyType;
public override Type PropertyType => GetIndexer(Target.Target.GetType().GetTypeInfo())?.PropertyType;
private object GetValue(object target)
{

17
src/Avalonia.Base/Data/Core/PropertyAccessorNode.cs

@ -10,7 +10,7 @@ using Avalonia.Data.Core.Plugins;
namespace Avalonia.Data.Core
{
internal class PropertyAccessorNode : ExpressionNode, ISettableNode
internal class PropertyAccessorNode : SettableNode
{
private readonly bool _enableValidation;
private IPropertyAccessor _accessor;
@ -23,13 +23,17 @@ namespace Avalonia.Data.Core
public override string Description => PropertyName;
public string PropertyName { get; }
public Type PropertyType => _accessor?.PropertyType;
public override Type PropertyType => _accessor?.PropertyType;
public bool SetTargetValue(object value, BindingPriority priority)
protected override bool SetTargetValueCore(object value, BindingPriority priority)
{
if (_accessor != null)
{
try { return _accessor.SetValue(value, priority); } catch { }
try
{
return _accessor.SetValue(value, priority);
}
catch { }
}
return false;
@ -56,7 +60,10 @@ namespace Avalonia.Data.Core
() =>
{
_accessor = accessor;
return Disposable.Create(() => _accessor = null);
return Disposable.Create(() =>
{
_accessor = null;
});
},
_ => accessor);
}

38
src/Avalonia.Base/Data/Core/SettableNode.cs

@ -0,0 +1,38 @@
using Avalonia.Data;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Avalonia.Data.Core
{
internal abstract class SettableNode : ExpressionNode
{
public bool SetTargetValue(object value, BindingPriority priority)
{
if (ShouldNotSet(value))
{
return true;
}
return SetTargetValueCore(value, priority);
}
private bool ShouldNotSet(object value)
{
if (PropertyType == null)
{
return false;
}
if (PropertyType.IsValueType)
{
return LastValue?.Target != null && LastValue.Target.Equals(value);
}
return LastValue != null && Object.ReferenceEquals(LastValue?.Target, value);
}
protected abstract bool SetTargetValueCore(object value, BindingPriority priority);
public abstract Type PropertyType { get; }
}
}

4
src/Avalonia.Controls/AppBuilderBase.cs

@ -216,7 +216,7 @@ namespace Avalonia.Controls
{
Instance.ExitMode = exitMode;
return Self;
}
}
private bool CheckSetup { get; set; } = true;
@ -229,6 +229,8 @@ namespace Avalonia.Controls
return Self;
}
protected virtual bool CheckSetup => true;
private void SetupAvaloniaModules()
{
var moduleInitializers = from assembly in AvaloniaLocator.Current.GetService<IRuntimePlatform>().GetLoadedAssemblies()

5
src/Avalonia.Controls/Platform/IWindowBaseImpl.cs

@ -72,6 +72,11 @@ namespace Avalonia.Platform
///
void SetMinMaxSize(Size minSize, Size maxSize);
/// <summary>
/// Sets whether this window appears on top of all other windows
/// </summary>
void SetTopmost(bool value);
/// <summary>
/// Gets platform specific display information
/// </summary>

2
src/Avalonia.Controls/Platform/InProcessDragSource.cs

@ -60,7 +60,7 @@ namespace Avalonia.Platform
{
_lastPosition = pt;
RawDragEvent rawEvent = new RawDragEvent(_dragDrop, type, root, pt, _draggedData, _allowedEffects);
RawDragEvent rawEvent = new RawDragEvent(_dragDrop, type, root, pt, _draggedData, _allowedEffects, modifiers);
var tl = root.GetSelfAndVisualAncestors().OfType<TopLevel>().FirstOrDefault();
tl.PlatformImpl?.Input(rawEvent);

20
src/Avalonia.Controls/Presenters/CarouselPresenter.cs

@ -115,7 +115,9 @@ namespace Avalonia.Controls.Presenters
var containers = generator.RemoveRange(e.OldStartingIndex, e.OldItems.Count);
Panel.Children.RemoveAll(containers.Select(x => x.ContainerControl));
#pragma warning disable 4014
MoveToPage(-1, SelectedIndex);
#pragma warning restore 4014
}
break;
@ -126,7 +128,23 @@ namespace Avalonia.Controls.Presenters
generator.Clear();
Panel.Children.RemoveAll(containers.Select(x => x.ContainerControl));
MoveToPage(-1, SelectedIndex >= 0 ? SelectedIndex : 0);
#pragma warning disable 4014
var newIndex = SelectedIndex;
if(SelectedIndex < 0)
{
if(Items != null && Items.Count() > 0)
{
newIndex = 0;
}
else
{
newIndex = -1;
}
}
MoveToPage(-1, newIndex);
#pragma warning restore 4014
}
break;
}

16
src/Avalonia.Controls/Primitives/Popup.cs

@ -70,6 +70,12 @@ namespace Avalonia.Controls.Primitives
public static readonly StyledProperty<bool> StaysOpenProperty =
AvaloniaProperty.Register<Popup, bool>(nameof(StaysOpen), true);
/// <summary>
/// Defines the <see cref="Topmost"/> property.
/// </summary>
public static readonly StyledProperty<bool> TopmostProperty =
AvaloniaProperty.Register<Popup, bool>(nameof(Topmost));
private bool _isOpen;
private PopupRoot _popupRoot;
private TopLevel _topLevel;
@ -84,6 +90,7 @@ namespace Avalonia.Controls.Primitives
IsHitTestVisibleProperty.OverrideDefaultValue<Popup>(false);
ChildProperty.Changed.AddClassHandler<Popup>(x => x.ChildChanged);
IsOpenProperty.Changed.AddClassHandler<Popup>(x => x.IsOpenChanged);
TopmostProperty.Changed.AddClassHandler<Popup>((p, e) => p.PopupRoot.Topmost = (bool)e.NewValue);
}
/// <summary>
@ -194,6 +201,15 @@ namespace Avalonia.Controls.Primitives
set { SetValue(StaysOpenProperty, value); }
}
/// <summary>
/// Gets or sets whether this popup appears on top of all other windows
/// </summary>
public bool Topmost
{
get { return GetValue(TopmostProperty); }
set { SetValue(TopmostProperty, value); }
}
/// <summary>
/// Gets the root of the popup window.
/// </summary>

37
src/Avalonia.Controls/Primitives/ScrollBar.cs

@ -6,9 +6,21 @@ using System.Reactive;
using System.Reactive.Linq;
using Avalonia.Data;
using Avalonia.Interactivity;
using Avalonia.Input;
namespace Avalonia.Controls.Primitives
{
public class ScrollEventArgs : EventArgs
{
public ScrollEventArgs(ScrollEventType eventType, double newValue)
{
ScrollEventType = eventType;
NewValue = newValue;
}
public double NewValue { get; private set; }
public ScrollEventType ScrollEventType { get; private set; }
}
/// <summary>
/// A scrollbar control.
/// </summary>
@ -44,6 +56,9 @@ namespace Avalonia.Controls.Primitives
{
PseudoClass(OrientationProperty, o => o == Orientation.Vertical, ":vertical");
PseudoClass(OrientationProperty, o => o == Orientation.Horizontal, ":horizontal");
Thumb.DragDeltaEvent.AddClassHandler<ScrollBar>(o => o.OnThumbDragDelta, RoutingStrategies.Bubble);
Thumb.DragCompletedEvent.AddClassHandler<ScrollBar>(o => o.OnThumbDragComplete, RoutingStrategies.Bubble);
}
/// <summary>
@ -88,6 +103,8 @@ namespace Avalonia.Controls.Primitives
set { SetValue(OrientationProperty, value); }
}
public event EventHandler<ScrollEventArgs> Scroll;
/// <summary>
/// Calculates whether the scrollbar should be visible.
/// </summary>
@ -140,6 +157,8 @@ namespace Avalonia.Controls.Primitives
_pageUpButton = e.NameScope.Find<Button>("PART_PageUpButton");
_pageDownButton = e.NameScope.Find<Button>("PART_PageDownButton");
if (_lineUpButton != null)
{
_lineUpButton.Click += LineUpClick;
@ -184,21 +203,39 @@ namespace Avalonia.Controls.Primitives
private void SmallDecrement()
{
Value = Math.Max(Value - SmallChange * ViewportSize, Minimum);
OnScroll(ScrollEventType.SmallDecrement);
}
private void SmallIncrement()
{
Value = Math.Min(Value + SmallChange * ViewportSize, Maximum);
OnScroll(ScrollEventType.SmallIncrement);
}
private void LargeDecrement()
{
Value = Math.Max(Value - LargeChange * ViewportSize, Minimum);
OnScroll(ScrollEventType.LargeDecrement);
}
private void LargeIncrement()
{
Value = Math.Min(Value + LargeChange * ViewportSize, Maximum);
OnScroll(ScrollEventType.LargeIncrement);
}
private void OnThumbDragDelta(VectorEventArgs e)
{
OnScroll(ScrollEventType.ThumbTrack);
}
private void OnThumbDragComplete(VectorEventArgs e)
{
OnScroll(ScrollEventType.EndScroll);
}
protected void OnScroll(ScrollEventType scrollEventType)
{
Scroll?.Invoke(this, new ScrollEventArgs(scrollEventType, Value));
}
}
}

53
src/Avalonia.Controls/Primitives/ScrollEventType.cs

@ -0,0 +1,53 @@
// 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.
namespace Avalonia.Controls.Primitives
{
/// <summary>
/// Specifies the type of Avalonia.Controls.Primitives.ScrollBar.Scroll event
/// that occurred.
/// </summary>
public enum ScrollEventType
{
/// <summary>
/// Specifies that the Avalonia.Controls.Primitives.Thumb moved a specified
/// distance, as determined by the value of Avalonia.Controls.Primitives.RangeBase.SmallChange.
/// The Avalonia.Controls.Primitives.Thumb moved to the left for a horizontal
/// Avalonia.Controls.Primitives.ScrollBar or upward for a vertical Avalonia.Controls.Primitives.ScrollBar.
/// </summary>
SmallDecrement = 0,
/// <summary>
/// Specifies that the Avalonia.Controls.Primitives.Thumb moved a specified
/// distance, as determined by the value of Avalonia.Controls.Primitives.RangeBase.SmallChange.
/// The Avalonia.Controls.Primitives.Thumb moved to the right for a horizontal
/// Avalonia.Controls.Primitives.ScrollBar or downward for a vertical Avalonia.Controls.Primitives.ScrollBar.
/// </summary>
SmallIncrement = 1,
/// <summary>
/// Specifies that the Avalonia.Controls.Primitives.Thumb moved a specified
/// distance, as determined by the value of Avalonia.Controls.Primitives.RangeBase.LargeChange.
/// The Avalonia.Controls.Primitives.Thumb moved to the left for a horizontal
/// Avalonia.Controls.Primitives.ScrollBar or upward for a vertical Avalonia.Controls.Primitives.ScrollBar.
/// </summary>
LargeDecrement = 2,
/// <summary>
/// Specifies that the Avalonia.Controls.Primitives.Thumb moved a specified
/// distance, as determined by the value of Avalonia.Controls.Primitives.RangeBase.LargeChange.
/// The Avalonia.Controls.Primitives.Thumb moved to the right for a horizontal
/// Avalonia.Controls.Primitives.ScrollBar or downward for a vertical Avalonia.Controls.Primitives.ScrollBar.
/// </summary>
LargeIncrement = 3,
/// <summary>
/// The Avalonia.Controls.Primitives.Thumb was dragged and caused a Avalonia.UIElement.MouseMove
/// event. A Avalonia.Controls.Primitives.ScrollBar.Scroll event of this Avalonia.Controls.Primitives.ScrollEventType
/// may occur more than one time when the Avalonia.Controls.Primitives.Thumb
/// is dragged in the Avalonia.Controls.Primitives.ScrollBar.
/// </summary>
ThumbTrack = 4,
/// <summary>
/// Specifies that the Avalonia.Controls.Primitives.Thumb was dragged to a
/// new position and is now no longer being dragged by the user.
/// </summary>
EndScroll = 5
}
}

3
src/Avalonia.Controls/ToolTip.cs

@ -234,11 +234,12 @@ namespace Avalonia.Controls
{
Close();
_popup = new PopupRoot { Content = this };
_popup = new PopupRoot { Content = this, };
((ISetLogicalParent)_popup).SetParent(control);
_popup.Position = Popup.GetPosition(control, GetPlacement(control), _popup,
GetHorizontalOffset(control), GetVerticalOffset(control));
_popup.Show();
_popup.SnapInsideScreenEdges();
}
private void Close()

14
src/Avalonia.Controls/WindowBase.cs

@ -38,6 +38,9 @@ namespace Avalonia.Controls
o => o.Owner,
(o, v) => o.Owner = v);
public static readonly StyledProperty<bool> TopmostProperty =
AvaloniaProperty.Register<WindowBase, bool>(nameof(Topmost));
private bool _hasExecutedInitialLayoutPass;
private bool _isActive;
private bool _ignoreVisibilityChange;
@ -52,6 +55,8 @@ namespace Avalonia.Controls
MinHeightProperty.Changed.AddClassHandler<WindowBase>((w, e) => w.PlatformImpl?.SetMinMaxSize(new Size(w.MinWidth, (double)e.NewValue), new Size(w.MaxWidth, w.MaxHeight)));
MaxWidthProperty.Changed.AddClassHandler<WindowBase>((w, e) => w.PlatformImpl?.SetMinMaxSize(new Size(w.MinWidth, w.MinHeight), new Size((double)e.NewValue, w.MaxHeight)));
MaxHeightProperty.Changed.AddClassHandler<WindowBase>((w, e) => w.PlatformImpl?.SetMinMaxSize(new Size(w.MinWidth, w.MinHeight), new Size(w.MaxWidth, (double)e.NewValue)));
TopmostProperty.Changed.AddClassHandler<WindowBase>((w, e) => w.PlatformImpl?.SetTopmost((bool)e.NewValue));
}
public WindowBase(IWindowBaseImpl impl) : this(impl, AvaloniaLocator.Current)
@ -124,6 +129,15 @@ namespace Avalonia.Controls
set { SetAndRaise(OwnerProperty, ref _owner, value); }
}
/// <summary>
/// Gets or sets whether this window appears on top of all other windows
/// </summary>
public bool Topmost
{
get { return GetValue(TopmostProperty); }
set { SetValue(TopmostProperty, value); }
}
/// <summary>
/// Activates the window.
/// </summary>

6
src/Avalonia.DesignerSupport/Remote/DetachableTransportConnection.cs

@ -30,6 +30,10 @@ namespace Avalonia.DesignerSupport.Remote
public event Action<IAvaloniaRemoteTransportConnection, object> OnMessage;
public event Action<IAvaloniaRemoteTransportConnection, Exception> OnException;
public event Action<IAvaloniaRemoteTransportConnection, Exception> OnException
{
add {}
remove {}
}
}
}

10
src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs

@ -44,7 +44,11 @@ namespace Avalonia.DesignerSupport.Remote
public WindowState WindowState { get; set; }
public Action<WindowState> WindowStateChanged { get; set; }
public Size MaxClientSize { get; } = new Size(4096, 4096);
public event Action LostFocus;
public event Action LostFocus
{
add {}
remove {}
}
protected override void OnMessage(IAvaloniaRemoteTransportConnection transport, object obj)
{
@ -102,5 +106,9 @@ namespace Avalonia.DesignerSupport.Remote
public void CanResize(bool value)
{
}
public void SetTopmost(bool value)
{
}
}
}

6
src/Avalonia.DesignerSupport/Remote/RemoteDesignerEntryPoint.cs

@ -125,7 +125,11 @@ namespace Avalonia.DesignerSupport.Remote
class NeverClose : ICloseable
{
public event EventHandler Closed;
public event EventHandler Closed
{
add {}
remove {}
}
}
public static void Main(string[] cmdline)

4
src/Avalonia.DesignerSupport/Remote/Stubs.cs

@ -104,6 +104,10 @@ namespace Avalonia.DesignerSupport.Remote
public void CanResize(bool value)
{
}
public void SetTopmost(bool value)
{
}
}
class ClipboardStub : IClipboard

24
src/Avalonia.Input/DragDropDevice.cs

@ -19,11 +19,11 @@ namespace Avalonia.Input
return null;
}
private DragDropEffects RaiseDragEvent(Interactive target, IInputElement inputRoot, Point point, RoutedEvent<DragEventArgs> routedEvent, DragDropEffects operation, IDataObject data)
private DragDropEffects RaiseDragEvent(Interactive target, IInputElement inputRoot, Point point, RoutedEvent<DragEventArgs> routedEvent, DragDropEffects operation, IDataObject data, InputModifiers modifiers)
{
if (target == null)
return DragDropEffects.None;
var args = new DragEventArgs(routedEvent, data, target, inputRoot.TranslatePoint(point, target))
var args = new DragEventArgs(routedEvent, data, target, inputRoot.TranslatePoint(point, target), modifiers)
{
RoutedEvent = routedEvent,
DragEffects = operation
@ -32,24 +32,24 @@ namespace Avalonia.Input
return args.DragEffects;
}
private DragDropEffects DragEnter(IInputElement inputRoot, Point point, IDataObject data, DragDropEffects effects)
private DragDropEffects DragEnter(IInputElement inputRoot, Point point, IDataObject data, DragDropEffects effects, InputModifiers modifiers)
{
_lastTarget = GetTarget(inputRoot, point);
return RaiseDragEvent(_lastTarget, inputRoot, point, DragDrop.DragEnterEvent, effects, data);
return RaiseDragEvent(_lastTarget, inputRoot, point, DragDrop.DragEnterEvent, effects, data, modifiers);
}
private DragDropEffects DragOver(IInputElement inputRoot, Point point, IDataObject data, DragDropEffects effects)
private DragDropEffects DragOver(IInputElement inputRoot, Point point, IDataObject data, DragDropEffects effects, InputModifiers modifiers)
{
var target = GetTarget(inputRoot, point);
if (target == _lastTarget)
return RaiseDragEvent(target, inputRoot, point, DragDrop.DragOverEvent, effects, data);
return RaiseDragEvent(target, inputRoot, point, DragDrop.DragOverEvent, effects, data, modifiers);
try
{
if (_lastTarget != null)
_lastTarget.RaiseEvent(new RoutedEventArgs(DragDrop.DragLeaveEvent));
return RaiseDragEvent(target, inputRoot, point, DragDrop.DragEnterEvent, effects, data);
return RaiseDragEvent(target, inputRoot, point, DragDrop.DragEnterEvent, effects, data, modifiers);
}
finally
{
@ -71,11 +71,11 @@ namespace Avalonia.Input
}
}
private DragDropEffects Drop(IInputElement inputRoot, Point point, IDataObject data, DragDropEffects effects)
private DragDropEffects Drop(IInputElement inputRoot, Point point, IDataObject data, DragDropEffects effects, InputModifiers modifiers)
{
try
{
return RaiseDragEvent(_lastTarget, inputRoot, point, DragDrop.DropEvent, effects, data);
return RaiseDragEvent(_lastTarget, inputRoot, point, DragDrop.DropEvent, effects, data, modifiers);
}
finally
{
@ -94,16 +94,16 @@ namespace Avalonia.Input
switch (e.Type)
{
case RawDragEventType.DragEnter:
e.Effects = DragEnter(e.InputRoot, e.Location, e.Data, e.Effects);
e.Effects = DragEnter(e.InputRoot, e.Location, e.Data, e.Effects, e.Modifiers);
break;
case RawDragEventType.DragOver:
e.Effects = DragOver(e.InputRoot, e.Location, e.Data, e.Effects);
e.Effects = DragOver(e.InputRoot, e.Location, e.Data, e.Effects, e.Modifiers);
break;
case RawDragEventType.DragLeave:
DragLeave(e.InputRoot);
break;
case RawDragEventType.Drop:
e.Effects = Drop(e.InputRoot, e.Location, e.Data, e.Effects);
e.Effects = Drop(e.InputRoot, e.Location, e.Data, e.Effects, e.Modifiers);
break;
}
}

5
src/Avalonia.Input/DragEventArgs.cs

@ -13,6 +13,8 @@ namespace Avalonia.Input
public IDataObject Data { get; private set; }
public InputModifiers Modifiers { get; private set; }
public Point GetPosition(IVisual relativeTo)
{
var point = new Point(0, 0);
@ -29,12 +31,13 @@ namespace Avalonia.Input
return point;
}
public DragEventArgs(RoutedEvent<DragEventArgs> routedEvent, IDataObject data, Interactive target, Point targetLocation)
public DragEventArgs(RoutedEvent<DragEventArgs> routedEvent, IDataObject data, Interactive target, Point targetLocation, InputModifiers modifiers)
: base(routedEvent)
{
this.Data = data;
this._target = target;
this._targetLocation = targetLocation;
this.Modifiers = modifiers;
}
}

4
src/Avalonia.Input/Raw/RawDragEvent.cs

@ -11,9 +11,10 @@ namespace Avalonia.Input.Raw
public IDataObject Data { get; }
public DragDropEffects Effects { get; set; }
public RawDragEventType Type { get; }
public InputModifiers Modifiers { get; }
public RawDragEvent(IDragDropDevice inputDevice, RawDragEventType type,
IInputElement inputRoot, Point location, IDataObject data, DragDropEffects effects)
IInputElement inputRoot, Point location, IDataObject data, DragDropEffects effects, InputModifiers modifiers)
:base(inputDevice, 0)
{
Type = type;
@ -21,6 +22,7 @@ namespace Avalonia.Input.Raw
Location = location;
Data = data;
Effects = effects;
Modifiers = modifiers;
}
}
}

4
src/Avalonia.Remote.Protocol/TcpTransportBase.cs

@ -48,14 +48,12 @@ namespace Avalonia.Remote.Protocol
{
var cl = await server.AcceptTcpClientAsync();
AcceptNew();
Task.Run(async () =>
await Task.Run(async () =>
{
var tcs = new TaskCompletionSource<int>();
var t = CreateTransport(_resolver, cl.GetStream(), () => tcs.TrySetResult(0));
cb(t);
await tcs.Task;
});
}
catch

2
src/Avalonia.Visuals/Media/DrawingContext.cs

@ -59,7 +59,7 @@ namespace Avalonia.Media
//HACK: This is a temporary hack that is used in the render loop
//to update TransformedBounds property
[Obsolete("HACK for render loop, don't use")]
internal Matrix CurrentContainerTransform => _currentContainerTransform;
public Matrix CurrentContainerTransform => _currentContainerTransform;
/// <summary>
/// Draws a bitmap image.

6
src/Avalonia.Visuals/Media/Fonts/FontFamilyKey.cs

@ -7,7 +7,7 @@ using System.Linq;
namespace Avalonia.Media.Fonts
{
/// <summary>
/// Represents an identifier for a <see cref="IFontFamily"/>
/// Represents an identifier for a <see cref="FontFamily"/>
/// </summary>
public class FontFamilyKey
{
@ -33,12 +33,12 @@ namespace Avalonia.Media.Fonts
}
/// <summary>
/// Location of stored font asset that belongs to a <see cref="IFontFamily"/>
/// Location of stored font asset that belongs to a <see cref="FontFamily"/>
/// </summary>
public Uri Location { get; }
/// <summary>
/// Optional filename for a font asset that belongs to a <see cref="IFontFamily"/>
/// Optional filename for a font asset that belongs to a <see cref="FontFamily"/>
/// </summary>
public string FileName { get; }

20
src/Avalonia.Visuals/Rendering/IRendererFactory.cs

@ -0,0 +1,20 @@
// 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;
namespace Avalonia.Rendering
{
/// <summary>
/// Defines the interface for a renderer factory.
/// </summary>
public interface IRendererFactory
{
/// <summary>
/// Creates a renderer.
/// </summary>
/// <param name="root">The root visual.</param>
/// <param name="renderLoop">The render loop.</param>
IRenderer Create(IRenderRoot root, IRenderLoop renderLoop);
}
}

5
src/Gtk/Avalonia.Gtk3/Interop/GlibTimeout.cs

@ -21,20 +21,17 @@ namespace Avalonia.Gtk3.Interop
}
return true;
}
private static readonly GCHandle PinnedHandle;
private static readonly Native.D.timeout_callback PinnedHandler;
static GlibTimeout()
{
PinnedHandler = Handler;
}
public static void Add(int priority, uint interval, Func<bool> callback)
{
var handle = GCHandle.Alloc(callback);
//Native.GTimeoutAdd(interval, PinnedHandler, GCHandle.ToIntPtr(handle));
Native.GTimeoutAddFull(priority, interval, PinnedHandler, GCHandle.ToIntPtr(handle), IntPtr.Zero);
}

9
src/Gtk/Avalonia.Gtk3/Interop/Native.cs

@ -1,4 +1,5 @@
using System;
#pragma warning disable 649
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
@ -261,10 +262,13 @@ namespace Avalonia.Gtk3.Interop
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate void gtk_window_unmaximize(GtkWindow window);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate void gtk_window_close(GtkWindow window);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate void gtk_window_set_keep_above(GtkWindow gtkWindow, bool setting);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate void gtk_window_set_geometry_hints(GtkWindow window, IntPtr geometry_widget, ref GdkGeometry geometry, GdkWindowHints geom_mask);
@ -472,6 +476,7 @@ namespace Avalonia.Gtk3.Interop
public static D.gtk_window_maximize GtkWindowMaximize;
public static D.gtk_window_unmaximize GtkWindowUnmaximize;
public static D.gtk_window_close GtkWindowClose;
public static D.gtk_window_set_keep_above GtkWindowSetKeepAbove;
public static D.gdk_window_begin_move_drag GdkWindowBeginMoveDrag;
public static D.gdk_window_begin_resize_drag GdkWindowBeginResizeDrag;
public static D.gdk_event_request_motions GdkEventRequestMotions;

2
src/Gtk/Avalonia.Gtk3/WindowBaseImpl.cs

@ -416,6 +416,8 @@ namespace Avalonia.Gtk3
public void Hide() => Native.GtkWidgetHide(GtkWidget);
public void SetTopmost(bool value) => Native.GtkWindowSetKeepAbove(GtkWidget, value);
void GetGlobalPointer(out int x, out int y)
{
int mask;

2
src/Gtk/Avalonia.Gtk3/WindowImpl.cs

@ -81,7 +81,7 @@ namespace Avalonia.Gtk3
public void ShowTaskbarIcon(bool value) => Native.GtkWindowSetSkipTaskbarHint(GtkWidget, !value);
public void CanResize(bool value) => Native.GtkWindowSetResizable(GtkWidget, value);
class EmptyDisposable : IDisposable
{

6
src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs

@ -70,6 +70,10 @@ namespace Avalonia.LinuxFramebuffer
public Action<Size> Resized { get; set; }
public Action<double> ScalingChanged { get; set; }
public Action Closed { get; set; }
public event Action LostFocus;
public event Action LostFocus
{
add {}
remove {}
}
}
}

14
src/Markup/Avalonia.Markup.Xaml/PortableXaml/TypeDescriptorExtensions.cs

@ -14,13 +14,13 @@ namespace Portable.Xaml.ComponentModel
/// Gets the service from ITypeDescriptorContext
/// usually in TypeConverter in xaml reader context
/// examples:
/// context.GetService<IXamlTypeResolver>()
/// context.GetService<IXamlNamespaceResolver>()
/// context.GetService<IXamlNameProvider>()
/// context.GetService<INamespacePrefixLookup>()
/// context.GetService<IXamlSchemaContextProvider>()
/// context.GetService<IRootObjectProvider>()
/// context.GetService<IProvideValueTarget>()
/// context.GetService&lt;IXamlTypeResolver&gt;()
/// context.GetService&lt;IXamlNamespaceResolver&gt;()
/// context.GetService&lt;IXamlNameProvider&gt;()
/// context.GetService&lt;INamespacePrefixLookup&gt;()
/// context.GetService&lt;IXamlSchemaContextProvider&gt;()
/// context.GetService&lt;IRootObjectProvider&gt;()
/// context.GetService&lt;IProvideValueTarget&gt;()
/// </summary>
/// <typeparam name="T">Service Type</typeparam>
/// <param name="ctx">The TypeDescriptor context.</param>

6
src/Markup/Avalonia.Markup.Xaml/Styling/StyleInclude.cs

@ -26,7 +26,11 @@ namespace Avalonia.Markup.Xaml.Styling
}
/// <inheritdoc/>
public event EventHandler<ResourcesChangedEventArgs> ResourcesChanged;
public event EventHandler<ResourcesChangedEventArgs> ResourcesChanged
{
add {}
remove {}
}
/// <summary>
/// Gets or sets the source URL.

3
src/OSX/Avalonia.MonoMac/ClipboardImpl.cs

@ -22,9 +22,10 @@ namespace Avalonia.MonoMac
return Task.CompletedTask;
}
public async Task ClearAsync()
public Task ClearAsync()
{
NSPasteboard.GeneralPasteboard.ClearContents();
return Task.CompletedTask;
}
}
}

9
src/OSX/Avalonia.MonoMac/SystemDialogsImpl.cs

@ -7,6 +7,7 @@ using Avalonia.Controls;
using Avalonia.Controls.Platform;
using Avalonia.Platform;
using MonoMac.AppKit;
using MonoMac.Foundation;
namespace Avalonia.MonoMac
{
@ -24,9 +25,9 @@ namespace Avalonia.MonoMac
else
{
if (panel is NSOpenPanel openPanel)
tcs.SetResult(openPanel.Filenames);
tcs.SetResult(openPanel.Urls.Select(url => url.AbsoluteString).ToArray());
else
tcs.SetResult(new[] { panel.Filename });
tcs.SetResult(new[] { panel.Url.AbsoluteString });
}
panel.OrderOut(panel);
keyWindow?.MakeKeyAndOrderFront(keyWindow);
@ -62,7 +63,7 @@ namespace Avalonia.MonoMac
panel = new NSSavePanel();
panel.Title = panel.Title;
if (dialog.InitialDirectory != null)
panel.Directory = dialog.InitialDirectory;
panel.DirectoryUrl = new NSUrl(dialog.InitialDirectory);
if (dialog.InitialFileName != null)
panel.NameFieldStringValue = dialog.InitialFileName;
if (dialog.Filters?.Count > 0)
@ -84,7 +85,7 @@ namespace Avalonia.MonoMac
CanChooseFiles = false
};
if (dialog.DefaultDirectory != null)
panel.Directory = dialog.DefaultDirectory;
panel.DirectoryUrl = new NSUrl(dialog.DefaultDirectory);
return (await RunPanel(panel, parent))?.FirstOrDefault();
}
}

3
src/OSX/Avalonia.MonoMac/TopLevelImpl.cs

@ -164,8 +164,9 @@ namespace Avalonia.MonoMac
var dragOp = DraggingInfo.ConvertDragOperation(sender.DraggingSourceOperationMask);
DraggingInfo info = new DraggingInfo(sender);
var pt = TranslateLocalPoint(info.Location);
var args = new RawDragEvent(dragDevice, type, root, pt, info, dragOp);
var args = new RawDragEvent(dragDevice, type, root, pt, info, dragOp, GetModifiers(NSEvent.CurrentModifierFlags));
input(args);
return DraggingInfo.ConvertDragOperation(args.Effects);
}

1
src/OSX/Avalonia.MonoMac/WindowBaseImpl.cs

@ -123,6 +123,7 @@ namespace Avalonia.MonoMac
public void Hide() => Window?.OrderOut(Window);
public void SetTopmost(bool value) => Window.Level = value ? NSWindowLevel.Floating : NSWindowLevel.Normal;
public void BeginMoveDrag()
{

54
src/Skia/Avalonia.Skia/FormattedTextImpl.cs

@ -250,7 +250,26 @@ namespace Avalonia.Skia
{
float currX = x;
string subStr;
float measure;
int len;
float factor;
switch (paint.TextAlign)
{
case SKTextAlign.Left:
factor = 0;
break;
case SKTextAlign.Center:
factor = 0.5f;
break;
case SKTextAlign.Right:
factor = 1;
break;
default:
throw new ArgumentOutOfRangeException();
}
var textLine = Text.Substring(line.Start, line.Length);
currX -= paint.MeasureText(textLine) * factor;
for (int i = line.Start; i < line.Start + line.Length;)
{
@ -268,13 +287,15 @@ namespace Avalonia.Skia
}
subStr = Text.Substring(i, len);
measure = paint.MeasureText(subStr);
currX += measure * factor;
ApplyWrapperTo(ref currentPaint, currentWrapper, ref currd, paint, canUseLcdRendering);
canvas.DrawText(subStr, currX, origin.Y + line.Top + _lineOffset, paint);
i += len;
currX += paint.MeasureText(subStr);
currX += measure * (1 - factor);
}
}
}
@ -560,13 +581,11 @@ namespace Avalonia.Skia
}
measured = LineBreak(Text, curOff, length, _paint, constraint, out trailingnumber);
AvaloniaFormattedTextLine line = new AvaloniaFormattedTextLine();
line.Start = curOff;
line.TextLength = measured;
subString = Text.Substring(line.Start, line.TextLength);
lineWidth = _paint.MeasureText(subString);
line.Start = curOff;
line.Length = measured - trailingnumber;
line.Width = lineWidth;
line.Height = _lineHeight;
@ -575,10 +594,33 @@ namespace Avalonia.Skia
_skiaLines.Add(line);
curY += _lineHeight;
curY += mLeading;
curOff += measured;
//if this is the last line and there are trailing newline characters then
//insert a additional line
if (curOff >= length)
{
var subStringMinusNewlines = subString.TrimEnd('\n', '\r');
var lengthDiff = subString.Length - subStringMinusNewlines.Length;
if (lengthDiff > 0)
{
AvaloniaFormattedTextLine lastLine = new AvaloniaFormattedTextLine();
lastLine.TextLength = lengthDiff;
lastLine.Start = curOff - lengthDiff;
var lastLineSubString = Text.Substring(line.Start, line.TextLength);
var lastLineWidth = _paint.MeasureText(lastLineSubString);
lastLine.Length = 0;
lastLine.Width = lastLineWidth;
lastLine.Height = _lineHeight;
lastLine.Top = curY;
_skiaLines.Add(lastLine);
curY += _lineHeight;
curY += mLeading;
}
}
}
// Now convert to Avalonia data formats

1
src/Windows/Avalonia.Direct2D1/Media/Imaging/D2DBitmapImpl.cs

@ -19,6 +19,7 @@ namespace Avalonia.Direct2D1.Media
/// Initialize a new instance of the <see cref="BitmapImpl"/> class
/// with a bitmap backed by GPU memory.
/// </summary>
/// <param name="imagingFactory">The image factory to use when saving out this bitmap.</param>
/// <param name="d2DBitmap">The GPU bitmap.</param>
/// <remarks>
/// This bitmap must be either from the same render target,

1
src/Windows/Avalonia.Direct2D1/Media/TransformedGeometryImpl.cs

@ -11,6 +11,7 @@ namespace Avalonia.Direct2D1.Media
/// <summary>
/// Initializes a new instance of the <see cref="StreamGeometryImpl"/> class.
/// </summary>
/// <param name="source">The source geometry.</param>
/// <param name="geometry">An existing Direct2D <see cref="TransformedGeometry"/>.</param>
public TransformedGeometryImpl(TransformedGeometry geometry, GeometryImpl source)
: base(geometry)

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

@ -78,6 +78,14 @@ namespace Avalonia.Win32.Interop
SWP_RESIZE = SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER
}
public static class WindowPosZOrder
{
public static readonly IntPtr HWND_BOTTOM = new IntPtr(1);
public static readonly IntPtr HWND_TOP = new IntPtr(0);
public static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
public static readonly IntPtr HWND_NOTOPMOST = new IntPtr(-2);
}
public enum SizeCommand
{
Restored,
@ -218,6 +226,8 @@ namespace Avalonia.Win32.Interop
MK_SHIFT = 0x0004,
MK_ALT = 0x0020,
MK_XBUTTON1 = 0x0020,
MK_XBUTTON2 = 0x0040
@ -998,7 +1008,7 @@ namespace Avalonia.Win32.Interop
public static extern int DragQueryFile(IntPtr hDrop, int iFile, StringBuilder lpszFile, int cch);
[DllImport("ole32.dll", CharSet = CharSet.Auto, ExactSpelling = true, PreserveSig = false)]
public static extern void DoDragDrop(IOleDataObject dataObject, IDropSource dropSource, int allowedEffects, int[] finalEffect);
internal static extern void DoDragDrop(IOleDataObject dataObject, IDropSource dropSource, int allowedEffects, int[] finalEffect);
@ -1375,9 +1385,7 @@ namespace Avalonia.Win32.Interop
Link = 4,
Scroll = -2147483648,
}
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("00000122-0000-0000-C000-000000000046")]
@ -1408,7 +1416,7 @@ namespace Avalonia.Win32.Interop
[ComImport]
[Guid("0000010E-0000-0000-C000-000000000046")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IOleDataObject
internal interface IOleDataObject
{
void GetData([In] ref FORMATETC format, out STGMEDIUM medium);
void GetDataHere([In] ref FORMATETC format, ref STGMEDIUM medium);

9
src/Windows/Avalonia.Win32/OleDragSource.cs

@ -11,10 +11,11 @@ namespace Avalonia.Win32
private const int DRAGDROP_S_DROP = 0x00040100;
private const int DRAGDROP_S_CANCEL = 0x00040101;
private const int KEYSTATE_LEFTMB = 1;
private const int KEYSTATE_MIDDLEMB = 16;
private const int KEYSTATE_RIGHTMB = 2;
private static readonly int[] MOUSE_BUTTONS = new int[] { KEYSTATE_LEFTMB, KEYSTATE_MIDDLEMB, KEYSTATE_RIGHTMB };
private static readonly int[] MOUSE_BUTTONS = new int[] {
(int)UnmanagedMethods.ModifierKeys.MK_LBUTTON,
(int)UnmanagedMethods.ModifierKeys.MK_MBUTTON,
(int)UnmanagedMethods.ModifierKeys.MK_RBUTTON
};
public int QueryContinueDrag(int fEscapePressed, int grfKeyState)
{

43
src/Windows/Avalonia.Win32/OleDropTarget.cs

@ -45,6 +45,26 @@ namespace Avalonia.Win32
return result;
}
private static InputModifiers ConvertKeyState(int grfKeyState)
{
InputModifiers modifiers = InputModifiers.None;
var state = (UnmanagedMethods.ModifierKeys)grfKeyState;
if (state.HasFlag(UnmanagedMethods.ModifierKeys.MK_LBUTTON))
modifiers |= InputModifiers.LeftMouseButton;
if (state.HasFlag(UnmanagedMethods.ModifierKeys.MK_MBUTTON))
modifiers |= InputModifiers.MiddleMouseButton;
if (state.HasFlag(UnmanagedMethods.ModifierKeys.MK_RBUTTON))
modifiers |= InputModifiers.RightMouseButton;
if (state.HasFlag(UnmanagedMethods.ModifierKeys.MK_SHIFT))
modifiers |= InputModifiers.Shift;
if (state.HasFlag(UnmanagedMethods.ModifierKeys.MK_CONTROL))
modifiers |= InputModifiers.Control;
if (state.HasFlag(UnmanagedMethods.ModifierKeys.MK_ALT))
modifiers |= InputModifiers.Alt;
return modifiers;
}
UnmanagedMethods.HRESULT IDropTarget.DragEnter(IOleDataObject pDataObj, int grfKeyState, long pt, ref DropEffect pdwEffect)
{
var dispatch = _tl?.Input;
@ -56,13 +76,15 @@ namespace Avalonia.Win32
_currentDrag = pDataObj as IDataObject;
if (_currentDrag == null)
_currentDrag = new OleDataObject(pDataObj);
var args = new RawDragEvent(
_dragDevice,
RawDragEventType.DragEnter,
_target,
GetDragLocation(pt),
_currentDrag,
ConvertDropEffect(pdwEffect)
ConvertDropEffect(pdwEffect),
ConvertKeyState(grfKeyState)
);
dispatch(args);
pdwEffect = ConvertDropEffect(args.Effects);
@ -85,7 +107,8 @@ namespace Avalonia.Win32
_target,
GetDragLocation(pt),
_currentDrag,
ConvertDropEffect(pdwEffect)
ConvertDropEffect(pdwEffect),
ConvertKeyState(grfKeyState)
);
dispatch(args);
pdwEffect = ConvertDropEffect(args.Effects);
@ -98,12 +121,13 @@ namespace Avalonia.Win32
try
{
_tl?.Input(new RawDragEvent(
_dragDevice,
RawDragEventType.DragLeave,
_target,
default(Point),
null,
DragDropEffects.None
_dragDevice,
RawDragEventType.DragLeave,
_target,
default(Point),
null,
DragDropEffects.None,
InputModifiers.None
));
return UnmanagedMethods.HRESULT.S_OK;
}
@ -134,7 +158,8 @@ namespace Avalonia.Win32
_target,
GetDragLocation(pt),
_currentDrag,
ConvertDropEffect(pdwEffect)
ConvertDropEffect(pdwEffect),
ConvertKeyState(grfKeyState)
);
dispatch(args);
pdwEffect = ConvertDropEffect(args.Effects);

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

@ -32,6 +32,7 @@ namespace Avalonia.Win32
private bool _trackingMouse;
private bool _decorated = true;
private bool _resizable = true;
private bool _topmost = false;
private double _scaling = 1;
private WindowState _showWindowState;
private WindowState _lastWindowState;
@ -124,9 +125,12 @@ namespace Avalonia.Win32
public IRenderer CreateRenderer(IRenderRoot root)
{
var loop = AvaloniaLocator.Current.GetService<IRenderLoop>();
return Win32Platform.UseDeferredRendering ?
(IRenderer)new DeferredRenderer(root, loop) :
new ImmediateRenderer(root);
var customRendererFactory = AvaloniaLocator.Current.GetService<IRendererFactory>();
if (customRendererFactory != null)
return customRendererFactory.Create(root, loop);
return Win32Platform.UseDeferredRendering ? (IRenderer)new DeferredRenderer(root, loop) : new ImmediateRenderer(root);
}
public void Resize(Size value)
@ -838,7 +842,7 @@ namespace Avalonia.Win32
var cx = Math.Abs(monitorInfo.rcWork.right - x);
var cy = Math.Abs(monitorInfo.rcWork.bottom - y);
SetWindowPos(_hwnd, new IntPtr(-2), x, y, cx, cy, SetWindowPosFlags.SWP_SHOWWINDOW);
SetWindowPos(_hwnd, WindowPosZOrder.HWND_NOTOPMOST, x, y, cx, cy, SetWindowPosFlags.SWP_SHOWWINDOW);
}
}
}
@ -901,5 +905,21 @@ namespace Avalonia.Win32
_resizable = value;
}
public void SetTopmost(bool value)
{
if (value == _topmost)
{
return;
}
IntPtr hWndInsertAfter = value ? WindowPosZOrder.HWND_TOPMOST : WindowPosZOrder.HWND_NOTOPMOST;
UnmanagedMethods.SetWindowPos(_hwnd,
hWndInsertAfter,
0, 0, 0, 0,
SetWindowPosFlags.SWP_NOMOVE | SetWindowPosFlags.SWP_NOSIZE | SetWindowPosFlags.SWP_NOACTIVATE);
_topmost = value;
}
}
}

2
src/iOS/Avalonia.iOS/DisplayLinkRenderLoop.cs

@ -26,7 +26,7 @@ namespace Avalonia.iOS
{
Tick?.Invoke(this, new EventArgs());
}
catch (Exception e)
catch (Exception)
{
//TODO: log
}

6
src/iOS/Avalonia.iOS/EmbeddableImpl.cs

@ -27,6 +27,10 @@ namespace Avalonia.iOS
{
}
public event Action LostFocus;
public event Action LostFocus
{
add {}
remove {}
}
}
}

3
src/iOS/Avalonia.iOS/TopLevelImpl.cs

@ -26,7 +26,6 @@ namespace Avalonia.iOS
{
private IInputRoot _inputRoot;
private readonly KeyboardEventsHelper<TopLevelImpl> _keyboardHelper;
private Point _position;
public TopLevelImpl()
{
@ -52,7 +51,7 @@ namespace Avalonia.iOS
public Action<Size> Resized { get; set; }
public Action<double> ScalingChanged { get; set; }
public IPlatformHandle Handle => null;
public new IPlatformHandle Handle => null;
public double Scaling => UIScreen.MainScreen.Scale;

49
tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Binding.cs

@ -457,6 +457,28 @@ namespace Avalonia.Base.UnitTests
Assert.True(target.IsAnimating(Class1.FooProperty));
}
[Fact]
public void TwoWay_Binding_Should_Not_Call_Setter_On_Creation()
{
var target = new Class1();
var source = new TestTwoWayBindingViewModel();
target.Bind(Class1.DoubleValueProperty, new Binding(nameof(source.Value), BindingMode.TwoWay) { Source = source });
Assert.False(source.SetterCalled);
}
[Fact]
public void TwoWay_Binding_Should_Not_Call_Setter_On_Creation_Indexer()
{
var target = new Class1();
var source = new TestTwoWayBindingViewModel();
target.Bind(Class1.DoubleValueProperty, new Binding("[0]", BindingMode.TwoWay) { Source = source });
Assert.False(source.SetterCalled);
}
/// <summary>
/// Returns an observable that returns a single value but does not complete.
/// </summary>
@ -545,5 +567,32 @@ namespace Avalonia.Base.UnitTests
}
}
}
private class TestTwoWayBindingViewModel
{
private double _value;
public double Value
{
get => _value;
set
{
_value = value;
SetterCalled = true;
}
}
public double this[int index]
{
get => _value;
set
{
_value = value;
SetterCalled = true;
}
}
public bool SetterCalled { get; private set; }
}
}
}

2
tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Threading.cs

@ -160,7 +160,9 @@ namespace Avalonia.Base.UnitTests
public bool CurrentThreadIsLoopThread { get; set; }
#pragma warning disable 67
public event Action<DispatcherPriority?> Signaled;
#pragma warning restore 67
public void RunLoop(CancellationToken cancellationToken)
{

5
tests/Avalonia.Controls.UnitTests/AppBuilderTests.cs

@ -6,6 +6,7 @@ using System.Threading.Tasks;
using Xunit;
using Avalonia.Controls.UnitTests;
using Avalonia.Platform;
using Avalonia.UnitTests;
[assembly: ExportAvaloniaModule("DefaultModule", typeof(AppBuilderTests.DefaultModule))]
[assembly: ExportAvaloniaModule("RenderingModule", typeof(AppBuilderTests.Direct2DModule), ForRenderingSubsystem = "Direct2D1")]
@ -65,7 +66,6 @@ namespace Avalonia.Controls.UnitTests
{
ResetModuleLoadStates();
AppBuilder.Configure<App>()
.IgnoreSetupCheck()
.UseWindowingSubsystem(() => { })
.UseRenderingSubsystem(() => { })
.UseAvaloniaModules()
@ -82,7 +82,6 @@ namespace Avalonia.Controls.UnitTests
{
ResetModuleLoadStates();
var builder = AppBuilder.Configure<App>()
.IgnoreSetupCheck()
.UseWindowingSubsystem(() => { })
.UseRenderingSubsystem(() => { }, "Direct2D1");
builder.UseAvaloniaModules().SetupWithoutStarting();
@ -92,7 +91,6 @@ namespace Avalonia.Controls.UnitTests
ResetModuleLoadStates();
builder = AppBuilder.Configure<App>()
.IgnoreSetupCheck()
.UseWindowingSubsystem(() => { })
.UseRenderingSubsystem(() => { }, "Skia");
builder.UseAvaloniaModules().SetupWithoutStarting();
@ -109,7 +107,6 @@ namespace Avalonia.Controls.UnitTests
{
ResetModuleLoadStates();
var builder = AppBuilder.Configure<App>()
.IgnoreSetupCheck()
.UseWindowingSubsystem(() => { })
.UseRenderingSubsystem(() => { }, "TBD");
builder.UseAvaloniaModules().SetupWithoutStarting();

35
tests/Avalonia.Controls.UnitTests/CarouselTests.cs

@ -170,6 +170,41 @@ namespace Avalonia.Controls.UnitTests
Assert.Equal("Bar", ((TextBlock)child).Text);
}
[Fact]
public void Selected_Index_Changes_To_When_Items_Assigned_Null()
{
var items = new ObservableCollection<string>
{
"Foo",
"Bar",
"FooBar"
};
var target = new Carousel
{
Template = new FuncControlTemplate<Carousel>(CreateTemplate),
Items = items,
IsVirtualized = false
};
target.ApplyTemplate();
target.Presenter.ApplyTemplate();
Assert.Single(target.GetLogicalChildren());
var child = target.GetLogicalChildren().Single();
Assert.IsType<TextBlock>(child);
Assert.Equal("Foo", ((TextBlock)child).Text);
target.Items = null;
var numChildren = target.GetLogicalChildren().Count();
Assert.Equal(0, numChildren);
Assert.Equal(-1, target.SelectedIndex);
}
[Fact]
public void Selected_Index_Is_Maintained_Carousel_Created_With_Non_Zero_SelectedIndex()
{

59
tests/Avalonia.Controls.UnitTests/Primitives/ScrollBarTests.cs

@ -5,6 +5,7 @@ using System;
using System.Linq;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates;
using Avalonia.Input;
using Avalonia.Media;
using Xunit;
@ -59,6 +60,64 @@ namespace Avalonia.Controls.UnitTests.Primitives
Assert.Equal(50, target.Value);
}
[Fact]
public void Thumb_DragDelta_Event_Should_Raise_Scroll_Event()
{
var target = new ScrollBar
{
Template = new FuncControlTemplate<ScrollBar>(Template),
};
target.ApplyTemplate();
var track = (Track)target.GetTemplateChildren().First(x => x.Name == "track");
var raisedEvent = Assert.Raises<ScrollEventArgs>(
handler => target.Scroll += handler,
handler => target.Scroll -= handler,
() =>
{
var ev = new VectorEventArgs
{
RoutedEvent = Thumb.DragDeltaEvent,
Vector = new Vector(0, 0)
};
track.Thumb.RaiseEvent(ev);
});
Assert.Equal(ScrollEventType.ThumbTrack, raisedEvent.Arguments.ScrollEventType);
}
[Fact]
public void Thumb_DragComplete_Event_Should_Raise_Scroll_Event()
{
var target = new ScrollBar
{
Template = new FuncControlTemplate<ScrollBar>(Template),
};
target.ApplyTemplate();
var track = (Track)target.GetTemplateChildren().First(x => x.Name == "track");
var raisedEvent = Assert.Raises<ScrollEventArgs>(
handler => target.Scroll += handler,
handler => target.Scroll -= handler,
() =>
{
var ev = new VectorEventArgs
{
RoutedEvent = Thumb.DragCompletedEvent,
Vector = new Vector(0, 0)
};
track.Thumb.RaiseEvent(ev);
});
Assert.Equal(ScrollEventType.EndScroll, raisedEvent.Arguments.ScrollEventType);
}
[Fact]
public void ScrollBar_Can_AutoHide()
{

2
tests/Avalonia.DesignerSupport.TestApp/Avalonia.DesignerSupport.TestApp.csproj

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Update="**\*.xaml.cs">

8
tests/Avalonia.DesignerSupport.Tests/DesignerSupportTests.cs

@ -19,6 +19,12 @@ namespace Avalonia.DesignerSupport.Tests
public class DesignerSupportTests
{
private const string DesignerAppPath = "../../../../../src/tools/Avalonia.Designer.HostApp/bin/$BUILD/netcoreapp2.0/Avalonia.Designer.HostApp.dll";
private readonly Xunit.Abstractions.ITestOutputHelper outputHelper;
public DesignerSupportTests(Xunit.Abstractions.ITestOutputHelper outputHelper)
{
this.outputHelper = outputHelper;
}
[SkippableTheory,
InlineData(
@ -73,6 +79,8 @@ namespace Avalonia.DesignerSupport.Tests
}
else if (msg is UpdateXamlResultMessage result)
{
if (result.Error != null)
outputHelper.WriteLine(result.Error);
handle = result.Handle != null ? long.Parse(result.Handle) : 0;
resultMessageReceivedToken.Cancel();
conn.Dispose();

2
tests/Avalonia.Interactivity.UnitTests/InteractiveTests.cs

@ -403,7 +403,7 @@ namespace Avalonia.Interactivity.UnitTests
private class TestInteractive : Interactive
{
public bool ClassHandlerInvoked { get; private set; }
public string Name { get; set; }
public new string Name { get; set; }
public IEnumerable<IVisual> Children
{

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

@ -21,6 +21,7 @@ using Xunit;
using Avalonia.Media;
using System;
using System.Collections.Generic;
using Avalonia.UnitTests;
namespace Avalonia.Layout.UnitTests
{

9
tests/Avalonia.LeakTests/Avalonia.LeakTests.csproj

@ -1,13 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netcoreapp2.0</TargetFrameworks>
<TargetFrameworks>net461</TargetFrameworks>
</PropertyGroup>
<Import Project="..\..\build\JetBrains.dotMemoryUnit.props" />
<Import Project="..\..\build\Moq.props" />
<Import Project="..\..\build\Rx.props" />
<Import Project="..\..\build\XUnit.props" />
<Import Project="..\..\build\NetFX.props" />
<ItemGroup>
<ProjectReference Include="..\..\src\Avalonia.DotNetCoreRuntime\Avalonia.DotNetCoreRuntime.csproj" />
<ProjectReference Include="..\..\src\Markup\Avalonia.Markup.Xaml\Avalonia.Markup.Xaml.csproj" />
<ProjectReference Include="..\..\src\Markup\Avalonia.Markup\Avalonia.Markup.csproj" />
<ProjectReference Include="..\..\src\Avalonia.Animation\Avalonia.Animation.csproj" />
@ -19,13 +19,10 @@
<ProjectReference Include="..\..\src\Avalonia.Visuals\Avalonia.Visuals.csproj" />
<ProjectReference Include="..\..\src\Avalonia.Styling\Avalonia.Styling.csproj" />
<ProjectReference Include="..\..\src\Avalonia.Themes.Default\Avalonia.Themes.Default.csproj" />
<ProjectReference Include="..\Avalonia.Controls.UnitTests\Avalonia.Controls.UnitTests.csproj" />
<ProjectReference Include="..\Avalonia.UnitTests\Avalonia.UnitTests.csproj" />
<Compile Remove="testproject/**/*.cs" />
</ItemGroup>
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
</Project>

8
tests/Avalonia.LeakTests/Properties/AssemblyInfo.cs

@ -0,0 +1,8 @@
// 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.Reflection;
using Xunit;
// Don't run tests in parallel.
[assembly: CollectionBehavior(DisableTestParallelization = true)]

11
tests/Avalonia.LeakTests/toolproject/tool.csproj

@ -1,11 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
<PropertyGroup>
<OutputPath>$(MSBuildThisFileDirectory)\bin</OutputPath>
<OutDir>$(OutputPath)</OutDir>
<TargetFrameworks>net461</TargetFrameworks>
<OutputType>Library</OutputType>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="JetBrains.dotMemory.Unit" Version="109.0.20170720.104130-eap09" />
</ItemGroup>
</Project>

2
tests/Avalonia.RenderTests/TestBase.cs

@ -161,7 +161,9 @@ namespace Avalonia.Direct2D1.RenderTests
public Thread MainThread { get; set; }
#pragma warning disable 67
public event Action<DispatcherPriority?> Signaled;
#pragma warning restore 67
public void RunLoop(CancellationToken cancellationToken)
{

22
tests/Avalonia.UnitTests/Avalonia.UnitTests.csproj

@ -1,22 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netcoreapp2.0</TargetFrameworks>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<OutputType>Library</OutputType>
</PropertyGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net461'">
<Reference Include="System" />
<Reference Include="System.Core" />
<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" />
</ItemGroup>
<ItemGroup>
<ProjectReference Condition="'$(TargetFramework)' == 'net461'" Include="..\..\src\Avalonia.DotNetFrameworkRuntime\Avalonia.DotNetFrameworkRuntime.csproj" />
<ProjectReference Condition="'$(TargetFramework)' == 'netcoreapp2.0'" Include="..\..\src\Avalonia.DotNetCoreRuntime\Avalonia.DotNetCoreRuntime.csproj" />
<ProjectReference Include="..\..\src\Markup\Avalonia.Markup.Xaml\Avalonia.Markup.Xaml.csproj" />
<ProjectReference Include="..\..\src\Markup\Avalonia.Markup\Avalonia.Markup.csproj" />
<ProjectReference Include="..\..\src\Avalonia.Animation\Avalonia.Animation.csproj" />
@ -29,13 +17,7 @@
<ProjectReference Include="..\..\src\Avalonia.Styling\Avalonia.Styling.csproj" />
<ProjectReference Include="..\..\src\Avalonia.Themes.Default\Avalonia.Themes.Default.csproj" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
</ItemGroup>
<Import Project="..\..\build\Moq.props" />
<Import Project="..\..\build\Rx.props" />
<Import Project="..\..\build\XUnit.props" />
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp2.0'">
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" />
</ItemGroup>
<Import Project="..\..\src\Shared\PlatformSupport\PlatformSupport.projitems" Label="Shared" />
</Project>

16
tests/Avalonia.UnitTests/RuntimeInfo.cs

@ -0,0 +1,16 @@
using Avalonia.Platform;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
namespace Avalonia.Shared.PlatformSupport
{
internal partial class StandardRuntimePlatform : IRuntimePlatform
{
public RuntimePlatformInfo GetRuntimeInfo()
{
return new RuntimePlatformInfo();
}
}
}

14
tests/Avalonia.UnitTests/TestServices.cs

@ -14,6 +14,8 @@ using Avalonia.Themes.Default;
using Avalonia.Rendering;
using System.Reactive.Concurrency;
using System.Collections.Generic;
using Avalonia.Controls;
using System.Reflection;
namespace Avalonia.UnitTests
{
@ -178,4 +180,16 @@ namespace Avalonia.UnitTests
y => y.Open() == Mock.Of<IStreamGeometryContextImpl>()));
}
}
public class AppBuilder : AppBuilderBase<AppBuilder>
{
public AppBuilder()
: base(new StandardRuntimePlatform(),
builder => StandardRuntimePlatformServices.Register(builder.Instance?.GetType()
?.GetTypeInfo().Assembly))
{
}
protected override bool CheckSetup => false;
}
}

11
tests/Avalonia.UnitTests/app.config

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Moq" publicKeyToken="69f491c39445e920" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.1510.2205" newVersion="4.2.1510.2205" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

2
tools/packages.config

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Cake" version="0.25.0" />
<package id="Cake" version="0.28.0" />
</packages>

Loading…
Cancel
Save