Browse Source

Merge branch 'master' into t/lindexi

pull/1396/head
Steven Kirk 9 years ago
committed by GitHub
parent
commit
e6c976b117
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 55
      Avalonia.sln
  2. 1
      build/Rx.props
  3. 5
      build/System.Drawing.Common.props
  4. 7
      packages.cake
  5. 2
      parameters.cake
  6. 36
      readme.md
  7. 5
      samples/ControlCatalog.iOS/ControlCatalog.iOS.csproj
  8. 26
      src/Avalonia.Base/Collections/AvaloniaListExtensions.cs
  9. 127
      src/Avalonia.Base/Collections/NotifyCollectionChangedExtensions.cs
  10. 2
      src/Avalonia.Base/Threading/Dispatcher.cs
  11. 12
      src/Avalonia.Controls/ItemsControl.cs
  12. 2
      src/Avalonia.Controls/Screens.cs
  13. 40
      src/Avalonia.Controls/Window.cs
  14. 19
      src/Avalonia.Controls/WindowBase.cs
  15. 23
      src/Avalonia.Controls/WindowStartupLocation.cs
  16. 4
      src/Avalonia.DesignerSupport/DesignWindowLoader.cs
  17. 3
      src/Avalonia.DotNetCoreRuntime/AppBuilder.cs
  18. 2
      src/Avalonia.DotNetCoreRuntime/Avalonia.DotNetCoreRuntime.csproj
  19. 3
      src/OSX/Avalonia.MonoMac/Avalonia.MonoMac.csproj
  20. 31
      src/OSX/Avalonia.MonoMac/ClipboardImpl.cs
  21. 2
      src/OSX/Avalonia.MonoMac/MonoMacPlatform.cs
  22. 6
      src/Shared/SharedAssemblyInfo.cs
  23. 4
      src/Windows/Avalonia.Win32.Interop/Avalonia.Win32.Interop.csproj
  24. 1
      src/Windows/Avalonia.Win32.Interop/WinForms/WinFormsAvaloniaControlHost.cs
  25. 49
      src/Windows/Avalonia.Win32.NetStandard/Avalonia.Win32.NetStandard.csproj
  26. 197
      src/Windows/Avalonia.Win32.NetStandard/ComStreamWrapper.cs
  27. 128
      src/Windows/Avalonia.Win32.NetStandard/Gdip.cs
  28. 45
      src/Windows/Avalonia.Win32.NetStandard/IconImpl.cs
  29. 30
      src/Windows/Avalonia.Win32.NetStandard/NativeWin32Platform.cs
  30. 12
      src/Windows/Avalonia.Win32.NetStandard/Win32Exception.cs
  31. 35
      src/Windows/Avalonia.Win32/Avalonia.Win32.Shared.projitems
  32. 110
      src/Windows/Avalonia.Win32/Avalonia.Win32.csproj
  33. 2
      src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs
  34. 2
      src/Windows/Avalonia.Win32/Properties/AssemblyInfo.cs
  35. 4
      src/Windows/Avalonia.Win32/ScreenImpl.cs
  36. 184
      src/Windows/Avalonia.Win32/Settings.StyleCop
  37. 38
      src/Windows/Avalonia.Win32/Win32Platform.cs
  38. 47
      src/Windows/Avalonia.Win32/WinFormsWin32Platform.cs
  39. 15
      src/Windows/Avalonia.Win32/WindowImpl.cs
  40. 9
      src/iOS/Avalonia.iOS/EmulatedFramebuffer.cs
  41. 83
      tests/Avalonia.Controls.UnitTests/WindowTests.cs

55
Avalonia.sln

@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27130.2024
VisualStudioVersion = 15.0.27130.2027
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Base", "src\Avalonia.Base\Avalonia.Base.csproj", "{B09B78D8-9B26-48B0-9149-D64A2F120F3F}"
EndProject
@ -11,7 +11,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Layout", "src\Aval
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Windows", "Windows", "{B39A8919-9F95-48FE-AD7B-76E08B509888}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Win32", "src\Windows\Avalonia.Win32\Avalonia.Win32.csproj", "{811A76CF-1CF6-440F-963B-BBE31BD72A82}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Win32", "src\Windows\Avalonia.Win32\Avalonia.Win32.csproj", "{811A76CF-1CF6-440F-963B-BBE31BD72A82}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Direct2D1", "src\Windows\Avalonia.Direct2D1\Avalonia.Direct2D1.csproj", "{3E908F67-5543-4879-A1DC-08EACE79B3CD}"
EndProject
@ -126,10 +126,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RenderTest", "samples\Rende
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCatalog.Android", "samples\ControlCatalog.Android\ControlCatalog.Android.csproj", "{29132311-1848-4FD6-AE0C-4FF841151BD3}"
EndProject
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Avalonia.Win32.Shared", "src\Windows\Avalonia.Win32\Avalonia.Win32.Shared.shproj", "{9DEFC6B7-845B-4D8F-AFC0-D32BF0032B8C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Win32.NetStandard", "src\Windows\Avalonia.Win32.NetStandard\Avalonia.Win32.NetStandard.csproj", "{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.DotNetCoreRuntime", "src\Avalonia.DotNetCoreRuntime\Avalonia.DotNetCoreRuntime.csproj", "{7863EA94-F0FB-4386-BF8C-E5BFA761560A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Skia", "src\Skia\Avalonia.Skia\Avalonia.Skia.csproj", "{7D2D3083-71DD-4CC9-8907-39A0D86FB322}"
@ -196,14 +192,11 @@ Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
src\Shared\RenderHelpers\RenderHelpers.projitems*{3c4c0cb4-0c0f-4450-a37b-148c84ff905f}*SharedItemsImports = 13
src\Shared\RenderHelpers\RenderHelpers.projitems*{3e908f67-5543-4879-a1dc-08eace79b3cd}*SharedItemsImports = 4
src\Windows\Avalonia.Win32\Avalonia.Win32.Shared.projitems*{40759a76-d0f2-464e-8000-6ff0f5c4bd7c}*SharedItemsImports = 4
src\Shared\PlatformSupport\PlatformSupport.projitems*{4488ad85-1495-4809-9aa4-ddfe0a48527e}*SharedItemsImports = 4
src\Shared\PlatformSupport\PlatformSupport.projitems*{4a1abb09-9047-4bd5-a4ad-a055e52c5ee0}*SharedItemsImports = 4
src\Shared\PlatformSupport\PlatformSupport.projitems*{7863ea94-f0fb-4386-bf8c-e5bfa761560a}*SharedItemsImports = 4
src\Shared\PlatformSupport\PlatformSupport.projitems*{7b92af71-6287-4693-9dcb-bd5b6e927e23}*SharedItemsImports = 4
src\Shared\RenderHelpers\RenderHelpers.projitems*{7d2d3083-71dd-4cc9-8907-39a0d86fb322}*SharedItemsImports = 4
src\Windows\Avalonia.Win32\Avalonia.Win32.Shared.projitems*{811a76cf-1cf6-440f-963b-bbe31bd72a82}*SharedItemsImports = 4
src\Windows\Avalonia.Win32\Avalonia.Win32.Shared.projitems*{9defc6b7-845b-4d8f-afc0-d32bf0032b8c}*SharedItemsImports = 13
tests\Avalonia.RenderTests\Avalonia.RenderTests.projitems*{dabfd304-d6a4-4752-8123-c2ccf7ac7831}*SharedItemsImports = 4
src\Shared\PlatformSupport\PlatformSupport.projitems*{e4d9629c-f168-4224-3f51-a5e482ffbc42}*SharedItemsImports = 13
EndGlobalSection
@ -369,6 +362,7 @@ Global
{811A76CF-1CF6-440F-963B-BBE31BD72A82}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{811A76CF-1CF6-440F-963B-BBE31BD72A82}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{811A76CF-1CF6-440F-963B-BBE31BD72A82}.Debug|NetCoreOnly.ActiveCfg = Debug|Any CPU
{811A76CF-1CF6-440F-963B-BBE31BD72A82}.Debug|NetCoreOnly.Build.0 = Debug|Any CPU
{811A76CF-1CF6-440F-963B-BBE31BD72A82}.Debug|x86.ActiveCfg = Debug|Any CPU
{811A76CF-1CF6-440F-963B-BBE31BD72A82}.Debug|x86.Build.0 = Debug|Any CPU
{811A76CF-1CF6-440F-963B-BBE31BD72A82}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -378,6 +372,7 @@ Global
{811A76CF-1CF6-440F-963B-BBE31BD72A82}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{811A76CF-1CF6-440F-963B-BBE31BD72A82}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{811A76CF-1CF6-440F-963B-BBE31BD72A82}.Release|NetCoreOnly.ActiveCfg = Release|Any CPU
{811A76CF-1CF6-440F-963B-BBE31BD72A82}.Release|NetCoreOnly.Build.0 = Release|Any CPU
{811A76CF-1CF6-440F-963B-BBE31BD72A82}.Release|x86.ActiveCfg = Release|Any CPU
{811A76CF-1CF6-440F-963B-BBE31BD72A82}.Release|x86.Build.0 = Release|Any CPU
{3E908F67-5543-4879-A1DC-08EACE79B3CD}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
@ -1994,46 +1989,6 @@ Global
{29132311-1848-4FD6-AE0C-4FF841151BD3}.Release|x86.ActiveCfg = Release|Any CPU
{29132311-1848-4FD6-AE0C-4FF841151BD3}.Release|x86.Build.0 = Release|Any CPU
{29132311-1848-4FD6-AE0C-4FF841151BD3}.Release|x86.Deploy.0 = Release|Any CPU
{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU
{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU
{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Ad-Hoc|NetCoreOnly.ActiveCfg = Release|Any CPU
{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Ad-Hoc|NetCoreOnly.Build.0 = Release|Any CPU
{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU
{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Ad-Hoc|x86.Build.0 = Release|Any CPU
{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.AppStore|Any CPU.Build.0 = Release|Any CPU
{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.AppStore|iPhone.ActiveCfg = Release|Any CPU
{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.AppStore|iPhone.Build.0 = Release|Any CPU
{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU
{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.AppStore|NetCoreOnly.ActiveCfg = Release|Any CPU
{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.AppStore|NetCoreOnly.Build.0 = Release|Any CPU
{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.AppStore|x86.ActiveCfg = Release|Any CPU
{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.AppStore|x86.Build.0 = Release|Any CPU
{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Debug|iPhone.Build.0 = Debug|Any CPU
{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Debug|NetCoreOnly.ActiveCfg = Debug|Any CPU
{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Debug|NetCoreOnly.Build.0 = Debug|Any CPU
{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Debug|x86.ActiveCfg = Debug|Any CPU
{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Debug|x86.Build.0 = Debug|Any CPU
{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Release|Any CPU.Build.0 = Release|Any CPU
{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Release|iPhone.ActiveCfg = Release|Any CPU
{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Release|iPhone.Build.0 = Release|Any CPU
{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Release|NetCoreOnly.ActiveCfg = Release|Any CPU
{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Release|NetCoreOnly.Build.0 = Release|Any CPU
{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Release|x86.ActiveCfg = Release|Any CPU
{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Release|x86.Build.0 = Release|Any CPU
{7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
{7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
{7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
@ -2623,8 +2578,6 @@ Global
{C7A69145-60B6-4882-97D6-A3921DD43978} = {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}
{9DEFC6B7-845B-4D8F-AFC0-D32BF0032B8C} = {B39A8919-9F95-48FE-AD7B-76E08B509888}
{40759A76-D0F2-464E-8000-6FF0F5C4BD7C} = {B39A8919-9F95-48FE-AD7B-76E08B509888}
{7D2D3083-71DD-4CC9-8907-39A0D86FB322} = {3743B0F2-CC41-4F14-A8C8-267F579BF91E}
{BB1F7BB5-6AD4-4776-94D9-C09D0A972658} = {B9894058-278A-46B5-B6ED-AD613FCC03B3}
{39D7B147-1A5B-47C2-9D01-21FB7C47C4B3} = {9B9E3891-2366-4253-A952-D08BCEB71098}

1
build/Rx.props

@ -5,6 +5,5 @@
<PackageReference Include="System.Reactive.Interfaces" Version="3.1.1" />
<PackageReference Include="System.Reactive.Linq" Version="3.1.1" />
<PackageReference Include="System.Reactive.PlatformServices" Version="3.1.1" />
<PackageReference Condition="$(TargetFramework.StartsWith('net4'))" Include="System.Reactive.Windows.Threading" Version="3.1.1" />
</ItemGroup>
</Project>

5
build/System.Drawing.Common.props

@ -0,0 +1,5 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<PackageReference Include="System.Drawing.Common" Version="4.5.0-preview1-25914-04" />
</ItemGroup>
</Project>

7
packages.cake

@ -370,14 +370,13 @@ public class Packages
new NuGetPackSettings()
{
Id = "Avalonia.Win32",
Dependencies = new []
Dependencies = new DependencyBuilder(this)
{
new NuSpecDependency() { Id = "Avalonia", Version = parameters.Version }
},
}.Deps(new string[]{null}, "System.Drawing.Common"),
Files = new []
{
new NuSpecContent { Source = "Avalonia.Win32/bin/" + parameters.DirSuffix + "/Avalonia.Win32.dll", Target = "lib/net45" },
new NuSpecContent { Source = "Avalonia.Win32.NetStandard/bin/" + parameters.DirSuffix + "/netstandard2.0/Avalonia.Win32.dll", Target = "lib/netstandard2.0" }
new NuSpecContent { Source = "Avalonia.Win32/bin/" + parameters.DirSuffix + "/netstandard2.0/Avalonia.Win32.dll", Target = "lib/netstandard2.0" }
},
BasePath = context.Directory("./src/Windows"),
OutputDirectory = parameters.NugetRoot

2
parameters.cake

@ -97,7 +97,7 @@ public class Parameters
else
{
// Use AssemblyVersion with Build as version
Version += "-build" + context.EnvironmentVariable("APPVEYOR_BUILD_NUMBER") + "-alpha";
Version += "-build" + context.EnvironmentVariable("APPVEYOR_BUILD_NUMBER") + "-beta";
}
}

36
readme.md

@ -2,9 +2,9 @@
# Avalonia
| Gitter Chat | Windows Build Status | Linux/Mac Build Status |
|---|---|---|
| [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/AvaloniaUI/Avalonia?utm_campaign=pr-badge&utm_content=badge&utm_medium=badge&utm_source=badge) | [![Build status](https://ci.appveyor.com/api/projects/status/hubk3k0w9idyibfg/branch/master?svg=true)](https://ci.appveyor.com/project/AvaloniaUI/Avalonia/branch/master) | [![Build Status](https://travis-ci.org/AvaloniaUI/Avalonia.svg?branch=master)](https://travis-ci.org/AvaloniaUI/Avalonia) |
| Gitter Chat | Windows Build Status | Linux/Mac Build Status | Open Collective |
|---|---|---|---|
| [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/AvaloniaUI/Avalonia?utm_campaign=pr-badge&utm_content=badge&utm_medium=badge&utm_source=badge) | [![Build status](https://ci.appveyor.com/api/projects/status/hubk3k0w9idyibfg/branch/master?svg=true)](https://ci.appveyor.com/project/AvaloniaUI/Avalonia/branch/master) | [![Build Status](https://travis-ci.org/AvaloniaUI/Avalonia.svg?branch=master)](https://travis-ci.org/AvaloniaUI/Avalonia) | [![Backers on Open Collective](https://opencollective.com/Avalonia/backers/badge.svg)](#backers) [![Sponsors on Open Collective](https://opencollective.com/Avalonia/sponsors/badge.svg)](#sponsors) |
## About
@ -48,3 +48,33 @@ See the [build instructions here](http://avaloniaui.net/contributing/build).
## Contributing
Please read the [contribution guidelines](http://avaloniaui.net/contributing/contributing) before submitting a pull request.
### Contributors
This project exists thanks to all the people who contribute. [[Contribute](http://avaloniaui.net/contributing/contributing)].
<a href="graphs/contributors"><img src="https://opencollective.com/Avalonia/contributors.svg?width=890&button=false" /></a>
### Backers
Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/Avalonia#backer)]
<a href="https://opencollective.com/Avalonia#backers" target="_blank"><img src="https://opencollective.com/Avalonia/backers.svg?width=890"></a>
### Sponsors
Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/Avalonia#sponsor)]
<a href="https://opencollective.com/Avalonia/sponsor/0/website" target="_blank"><img src="https://opencollective.com/Avalonia/sponsor/0/avatar.svg"></a>
<a href="https://opencollective.com/Avalonia/sponsor/1/website" target="_blank"><img src="https://opencollective.com/Avalonia/sponsor/1/avatar.svg"></a>
<a href="https://opencollective.com/Avalonia/sponsor/2/website" target="_blank"><img src="https://opencollective.com/Avalonia/sponsor/2/avatar.svg"></a>
<a href="https://opencollective.com/Avalonia/sponsor/3/website" target="_blank"><img src="https://opencollective.com/Avalonia/sponsor/3/avatar.svg"></a>
<a href="https://opencollective.com/Avalonia/sponsor/4/website" target="_blank"><img src="https://opencollective.com/Avalonia/sponsor/4/avatar.svg"></a>
<a href="https://opencollective.com/Avalonia/sponsor/5/website" target="_blank"><img src="https://opencollective.com/Avalonia/sponsor/5/avatar.svg"></a>
<a href="https://opencollective.com/Avalonia/sponsor/6/website" target="_blank"><img src="https://opencollective.com/Avalonia/sponsor/6/avatar.svg"></a>
<a href="https://opencollective.com/Avalonia/sponsor/7/website" target="_blank"><img src="https://opencollective.com/Avalonia/sponsor/7/avatar.svg"></a>
<a href="https://opencollective.com/Avalonia/sponsor/8/website" target="_blank"><img src="https://opencollective.com/Avalonia/sponsor/8/avatar.svg"></a>
<a href="https://opencollective.com/Avalonia/sponsor/9/website" target="_blank"><img src="https://opencollective.com/Avalonia/sponsor/9/avatar.svg"></a>

5
samples/ControlCatalog.iOS/ControlCatalog.iOS.csproj

@ -170,15 +170,14 @@
<Name>Avalonia.Themes.Default</Name>
</ProjectReference>
<ProjectReference Include="..\..\src\Skia\Avalonia.Skia\Avalonia.Skia.csproj">
<Project>{D2D3083-71DD-4CC9-8907-39A0D86FB322}</Project>
<Project>{7d2d3083-71dd-4cc9-8907-39a0d86fb322}</Project>
<Name>Avalonia.Skia</Name>
<IsAppExtension>false</IsAppExtension>
<IsWatchApp>false</IsWatchApp>
</ProjectReference>
<ProjectReference Include="..\ControlCatalog\ControlCatalog.csproj">
<Project>{d0a739b9-3c68-4ba6-a328-41606954b6bd}</Project>
<Name>ControlCatalog</Name>
</ProjectReference>
</ItemGroup>
<Import Project="..\..\build\Sprache.props" />
<Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" />
</Project>

26
src/Avalonia.Base/Collections/AvaloniaListExtensions.cs

@ -34,14 +34,18 @@ namespace Avalonia.Collections
/// <param name="reset">
/// An action called when the collection is reset.
/// </param>
/// <param name="weakSubscription">
/// Indicates if a weak subscription should be used to track changes to the collection.
/// </param>
/// <returns>A disposable used to terminate the subscription.</returns>
public static IDisposable ForEachItem<T>(
this IAvaloniaReadOnlyList<T> collection,
Action<T> added,
Action<T> removed,
Action reset)
Action reset,
bool weakSubscription = false)
{
return collection.ForEachItem((_, i) => added(i), (_, i) => removed(i), reset);
return collection.ForEachItem((_, i) => added(i), (_, i) => removed(i), reset, weakSubscription);
}
/// <summary>
@ -63,12 +67,16 @@ namespace Avalonia.Collections
/// An action called when the collection is reset. This will be followed by calls to
/// <paramref name="added"/> for each item present in the collection after the reset.
/// </param>
/// <param name="weakSubscription">
/// Indicates if a weak subscription should be used to track changes to the collection.
/// </param>
/// <returns>A disposable used to terminate the subscription.</returns>
public static IDisposable ForEachItem<T>(
this IAvaloniaReadOnlyList<T> collection,
Action<int, T> added,
Action<int, T> removed,
Action reset)
Action reset,
bool weakSubscription = false)
{
void Add(int index, IList items)
{
@ -118,9 +126,17 @@ namespace Avalonia.Collections
};
Add(0, (IList)collection);
collection.CollectionChanged += handler;
return Disposable.Create(() => collection.CollectionChanged -= handler);
if (weakSubscription)
{
return collection.WeakSubscribe(handler);
}
else
{
collection.CollectionChanged += handler;
return Disposable.Create(() => collection.CollectionChanged -= handler);
}
}
public static IAvaloniaReadOnlyList<TDerived> CreateDerivedList<TSource, TDerived>(

127
src/Avalonia.Base/Collections/NotifyCollectionChangedExtensions.cs

@ -0,0 +1,127 @@
// 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.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Reactive;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using Avalonia.Utilities;
namespace Avalonia.Collections
{
public static class NotifyCollectionChangedExtensions
{
/// <summary>
/// Gets a weak observable for the CollectionChanged event.
/// </summary>
/// <param name="collection">The collection.</param>
/// <returns>An observable.</returns>
public static IObservable<NotifyCollectionChangedEventArgs> GetWeakCollectionChangedObservable(
this INotifyCollectionChanged collection)
{
Contract.Requires<ArgumentNullException>(collection != null);
return new WeakCollectionChangedObservable(new WeakReference<INotifyCollectionChanged>(collection));
}
/// <summary>
/// Subcribes to the CollectionChanged event using a weak subscription.
/// </summary>
/// <param name="collection">The collection.</param>
/// <param name="handler">
/// An action called when the collection event is raised.
/// </param>
/// <returns>A disposable used to terminate the subscription.</returns>
public static IDisposable WeakSubscribe(
this INotifyCollectionChanged collection,
NotifyCollectionChangedEventHandler handler)
{
Contract.Requires<ArgumentNullException>(collection != null);
Contract.Requires<ArgumentNullException>(handler != null);
return
collection.GetWeakCollectionChangedObservable()
.Subscribe(e => handler.Invoke(collection, e));
}
/// <summary>
/// Subcribes to the CollectionChanged event using a weak subscription.
/// </summary>
/// <param name="collection">The collection.</param>
/// <param name="handler">
/// An action called when the collection event is raised.
/// </param>
/// <returns>A disposable used to terminate the subscription.</returns>
public static IDisposable WeakSubscribe(
this INotifyCollectionChanged collection,
Action<NotifyCollectionChangedEventArgs> handler)
{
Contract.Requires<ArgumentNullException>(collection != null);
Contract.Requires<ArgumentNullException>(handler != null);
return
collection.GetWeakCollectionChangedObservable()
.Subscribe(handler);
}
private class WeakCollectionChangedObservable : ObservableBase<NotifyCollectionChangedEventArgs>,
IWeakSubscriber<NotifyCollectionChangedEventArgs>
{
private WeakReference<INotifyCollectionChanged> _sourceReference;
private readonly Subject<NotifyCollectionChangedEventArgs> _changed = new Subject<NotifyCollectionChangedEventArgs>();
private int _count;
public WeakCollectionChangedObservable(WeakReference<INotifyCollectionChanged> source)
{
_sourceReference = source;
}
public void OnEvent(object sender, NotifyCollectionChangedEventArgs e)
{
_changed.OnNext(e);
}
protected override IDisposable SubscribeCore(IObserver<NotifyCollectionChangedEventArgs> observer)
{
if (_sourceReference.TryGetTarget(out INotifyCollectionChanged instance))
{
if (_count++ == 0)
{
WeakSubscriptionManager.Subscribe(
instance,
nameof(instance.CollectionChanged),
this);
}
return Observable.Using(() => Disposable.Create(DecrementCount), _ => _changed)
.Subscribe(observer);
}
else
{
_changed.OnCompleted();
observer.OnCompleted();
return Disposable.Empty;
}
}
private void DecrementCount()
{
if (--_count == 0)
{
if (_sourceReference.TryGetTarget(out INotifyCollectionChanged instance))
{
WeakSubscriptionManager.Unsubscribe(
instance,
nameof(instance.CollectionChanged),
this);
}
}
}
}
}
}

2
src/Avalonia.Base/Threading/Dispatcher.cs

@ -81,12 +81,14 @@ namespace Avalonia.Threading
/// <inheritdoc/>
public Task InvokeAsync(Action action, DispatcherPriority priority = DispatcherPriority.Normal)
{
Contract.Requires<ArgumentNullException>(action != null);
return _jobRunner?.InvokeAsync(action, priority);
}
/// <inheritdoc/>
public void Post(Action action, DispatcherPriority priority = DispatcherPriority.Normal)
{
Contract.Requires<ArgumentNullException>(action != null);
_jobRunner?.Post(action, priority);
}

12
src/Avalonia.Controls/ItemsControl.cs

@ -1,6 +1,7 @@
// 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.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
@ -54,6 +55,7 @@ namespace Avalonia.Controls
private IEnumerable _items = new AvaloniaList<object>();
private IItemContainerGenerator _itemContainerGenerator;
private IDisposable _itemsCollectionChangedSubscription;
/// <summary>
/// Initializes static members of the <see cref="ItemsControl"/> class.
@ -326,12 +328,8 @@ namespace Avalonia.Controls
/// <param name="e">The event args.</param>
protected virtual void ItemsChanged(AvaloniaPropertyChangedEventArgs e)
{
var incc = e.OldValue as INotifyCollectionChanged;
if (incc != null)
{
incc.CollectionChanged -= ItemsCollectionChanged;
}
_itemsCollectionChangedSubscription?.Dispose();
_itemsCollectionChangedSubscription = null;
var oldValue = e.OldValue as IEnumerable;
var newValue = e.NewValue as IEnumerable;
@ -428,7 +426,7 @@ namespace Avalonia.Controls
if (incc != null)
{
incc.CollectionChanged += ItemsCollectionChanged;
_itemsCollectionChangedSubscription = incc.WeakSubscribe(ItemsCollectionChanged);
}
}

2
src/Avalonia.Controls/Screens.cs

@ -39,7 +39,7 @@ namespace Avalonia.Controls
return currMaxScreen;
}
public Screen SceenFromPoint(Point point)
public Screen ScreenFromPoint(Point point)
{
return All.FirstOrDefault(x=>x.Bounds.Contains(point));
}

40
src/Avalonia.Controls/Window.cs

@ -85,9 +85,19 @@ namespace Avalonia.Controls
public static readonly StyledProperty<WindowIcon> IconProperty =
AvaloniaProperty.Register<Window, WindowIcon>(nameof(Icon));
/// <summary>
/// Defines the <see cref="WindowStartupLocation"/> proeprty.
/// </summary>
public static readonly DirectProperty<Window, WindowStartupLocation> WindowStartupLocationProperty =
AvaloniaProperty.RegisterDirect<Window, WindowStartupLocation>(
nameof(WindowStartupLocation),
o => o.WindowStartupLocation,
(o, v) => o.WindowStartupLocation = v);
private readonly NameScope _nameScope = new NameScope();
private object _dialogResult;
private readonly Size _maxPlatformClientSize;
private WindowStartupLocation _windowStartupLoction;
/// <summary>
/// Initializes static members of the <see cref="Window"/> class.
@ -205,6 +215,15 @@ namespace Avalonia.Controls
set { SetValue(IconProperty, value); }
}
/// <summary>
/// Gets or sets the startup location of the window.
/// </summary>
public WindowStartupLocation WindowStartupLocation
{
get { return _windowStartupLoction; }
set { SetAndRaise(WindowStartupLocationProperty, ref _windowStartupLoction, value); }
}
/// <inheritdoc/>
Size ILayoutRoot.MaxClientSize => _maxPlatformClientSize;
@ -274,6 +293,7 @@ namespace Avalonia.Controls
s_windows.Add(this);
EnsureInitialized();
SetWindowStartupLocation();
IsVisible = true;
LayoutManager.Instance.ExecuteInitialLayoutPass(this);
@ -314,6 +334,7 @@ namespace Avalonia.Controls
s_windows.Add(this);
EnsureInitialized();
SetWindowStartupLocation();
IsVisible = true;
LayoutManager.Instance.ExecuteInitialLayoutPass(this);
@ -352,6 +373,25 @@ namespace Avalonia.Controls
}
}
void SetWindowStartupLocation()
{
if (WindowStartupLocation == WindowStartupLocation.CenterScreen)
{
var screen = Screens.ScreenFromPoint(Bounds.Position);
if (screen != null)
Position = screen.WorkingArea.CenterRect(new Rect(ClientSize)).Position;
}
else if (WindowStartupLocation == WindowStartupLocation.CenterOwner)
{
if (Owner != null)
{
var positionAsSize = Owner.ClientSize / 2 - ClientSize / 2;
Position = Owner.Position + new Point(positionAsSize.Width, positionAsSize.Height);
}
}
}
/// <inheritdoc/>
void INameScope.Register(string name, object element)
{

19
src/Avalonia.Controls/WindowBase.cs

@ -29,9 +29,19 @@ namespace Avalonia.Controls
public static readonly DirectProperty<WindowBase, bool> IsActiveProperty =
AvaloniaProperty.RegisterDirect<WindowBase, bool>(nameof(IsActive), o => o.IsActive);
/// <summary>
/// Defines the <see cref="Owner"/> property.
/// </summary>
public static readonly DirectProperty<WindowBase, WindowBase> OwnerProperty =
AvaloniaProperty.RegisterDirect<WindowBase, WindowBase>(
nameof(Owner),
o => o.Owner,
(o, v) => o.Owner = v);
private bool _hasExecutedInitialLayoutPass;
private bool _isActive;
private bool _ignoreVisibilityChange;
private WindowBase _owner;
static WindowBase()
{
@ -100,6 +110,15 @@ namespace Avalonia.Controls
private set;
}
/// <summary>
/// Gets or sets the owner of the window.
/// </summary>
public WindowBase Owner
{
get { return _owner; }
set { SetAndRaise(OwnerProperty, ref _owner, value); }
}
/// <summary>
/// Activates the window.
/// </summary>

23
src/Avalonia.Controls/WindowStartupLocation.cs

@ -0,0 +1,23 @@
namespace Avalonia.Controls
{
/// <summary>
/// Determines the startup location of the window.
/// </summary>
public enum WindowStartupLocation
{
/// <summary>
/// The startup location is defined by the Position property.
/// </summary>
Manual,
/// <summary>
/// The startup location is the center of the screen.
/// </summary>
CenterScreen,
/// <summary>
/// The startup location is the center of the owner window. If the owner window is not specified, the startup location will be <see cref="Manual"/>.
/// </summary>
CenterOwner
}
}

4
src/Avalonia.DesignerSupport/DesignWindowLoader.cs

@ -54,7 +54,7 @@ namespace Avalonia.DesignerSupport
}
};
}
if (loaded is Application)
else if (loaded is Application)
control = new TextBlock {Text = "Application can't be previewed in design view"};
else
control = (Control) loaded;
@ -73,4 +73,4 @@ namespace Avalonia.DesignerSupport
return window;
}
}
}
}

3
src/Avalonia.DotNetCoreRuntime/AppBuilder.cs

@ -10,6 +10,9 @@ using Avalonia.Shared.PlatformSupport;
namespace Avalonia
{
/// <summary>
/// Initializes platform-specific services for an <see cref="Application"/>.
/// </summary>
public sealed class AppBuilder : AppBuilderBase<AppBuilder>
{
/// <summary>

2
src/Avalonia.DotNetCoreRuntime/Avalonia.DotNetCoreRuntime.csproj

@ -19,7 +19,7 @@
<ProjectReference Include="..\Gtk\Avalonia.Gtk3\Avalonia.Gtk3.csproj" />
<ProjectReference Include="..\OSX\Avalonia.MonoMac\Avalonia.MonoMac.csproj" />
<ProjectReference Include="..\Skia\Avalonia.Skia\Avalonia.Skia.csproj" />
<ProjectReference Include="..\Windows\Avalonia.Win32.NetStandard\Avalonia.Win32.NetStandard.csproj" />
<ProjectReference Include="..\Windows\Avalonia.Win32\Avalonia.Win32.csproj" />
</ItemGroup>
<Import Project="..\..\build\NetCore.props" />
<Import Project="..\Shared\PlatformSupport\PlatformSupport.projitems" />

3
src/OSX/Avalonia.MonoMac/Avalonia.MonoMac.csproj

@ -8,9 +8,6 @@
<Compile Include="..\..\Shared\SharedAssemblyInfo.cs" Link="SharedAssemblyInfo.cs" />
<Compile Include="..\..\Shared\WindowResizeDragHelper.cs" Link="WindowResizeDragHelper.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="MonoMac.NetStandard" Version="0.0.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Avalonia.Animation\Avalonia.Animation.csproj" />
<ProjectReference Include="..\..\Avalonia.Base\Avalonia.Base.csproj" />

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

@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Avalonia.Input.Platform;
using MonoMac.AppKit;
namespace Avalonia.MonoMac
{
class ClipboardImpl : IClipboard
{
public Task<string> GetTextAsync()
{
return Task.FromResult(NSPasteboard.GeneralPasteboard.GetStringForType(NSPasteboard.NSStringType));
}
public Task SetTextAsync(string text)
{
NSPasteboard.GeneralPasteboard.ClearContents();
if (text != null)
NSPasteboard.GeneralPasteboard.SetStringForType(text, NSPasteboard.NSStringType);
return Task.CompletedTask;
}
public async Task ClearAsync()
{
NSPasteboard.GeneralPasteboard.ClearContents();
}
}
}

2
src/OSX/Avalonia.MonoMac/MonoMacPlatform.cs

@ -3,6 +3,7 @@ using System.Threading;
using Avalonia.Controls;
using Avalonia.Controls.Platform;
using Avalonia.Input;
using Avalonia.Input.Platform;
using Avalonia.Platform;
using Avalonia.Rendering;
using MonoMac.AppKit;
@ -32,6 +33,7 @@ namespace Avalonia.MonoMac
.Bind<IPlatformSettings>().ToConstant(this)
.Bind<IWindowingPlatform>().ToConstant(this)
.Bind<ISystemDialogImpl>().ToSingleton<SystemDialogsImpl>()
.Bind<IClipboard>().ToSingleton<ClipboardImpl>()
.Bind<IRenderLoop>().ToConstant(s_renderLoop)
.Bind<IPlatformThreadingInterface>().ToConstant(PlatformThreadingInterface.Instance);
}

6
src/Shared/SharedAssemblyInfo.cs

@ -14,6 +14,6 @@ using System.Runtime.CompilerServices;
[assembly: AssemblyTrademark("")]
[assembly: NeutralResourcesLanguage("en")]
[assembly: AssemblyVersion("0.6.0")]
[assembly: AssemblyFileVersion("0.6.0")]
[assembly: AssemblyInformationalVersion("0.6.0")]
[assembly: AssemblyVersion("0.6.2")]
[assembly: AssemblyFileVersion("0.6.2")]
[assembly: AssemblyInformationalVersion("0.6.2")]

4
src/Windows/Avalonia.Win32.Interop/Avalonia.Win32.Interop.csproj

@ -34,6 +34,7 @@
<Reference Include="PresentationFramework" />
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xaml" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
@ -48,6 +49,9 @@
<Link>UnmanagedMethods.cs</Link>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="WinForms\WinFormsAvaloniaControlHost.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="Wpf\CursorShim.cs" />
<Compile Include="Wpf\Direct2DImageSurface.cs" />
<Compile Include="Wpf\IntSize.cs" />

1
src/Windows/Avalonia.Win32/Embedding/WinFormsAvaloniaControlHost.cs → src/Windows/Avalonia.Win32.Interop/WinForms/WinFormsAvaloniaControlHost.cs

@ -1,7 +1,6 @@
using System;
using System.ComponentModel;
using System.Windows.Forms;
using Avalonia.Controls;
using Avalonia.Controls.Embedding;
using Avalonia.Input;
using Avalonia.VisualTree;

49
src/Windows/Avalonia.Win32.NetStandard/Avalonia.Win32.NetStandard.csproj

@ -1,49 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<EnableDefaultCompileItems>False</EnableDefaultCompileItems>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<RootNamespace>Avalonia.Win32</RootNamespace>
<AssemblyName>Avalonia.Win32</AssemblyName>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;NETSTANDARD</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE;NETSTANDARD</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Avalonia.Animation\Avalonia.Animation.csproj" />
<ProjectReference Include="..\..\Avalonia.Base\Avalonia.Base.csproj" />
<ProjectReference Include="..\..\Avalonia.Controls\Avalonia.Controls.csproj" />
<ProjectReference Include="..\..\Avalonia.Input\Avalonia.Input.csproj" />
<ProjectReference Include="..\..\Avalonia.Interactivity\Avalonia.Interactivity.csproj" />
<ProjectReference Include="..\..\Avalonia.Layout\Avalonia.Layout.csproj" />
<ProjectReference Include="..\..\Avalonia.Styling\Avalonia.Styling.csproj" />
<ProjectReference Include="..\..\Avalonia.Visuals\Avalonia.Visuals.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Include="ComStreamWrapper.cs" />
<Compile Include="Gdip.cs" />
<Compile Include="IconImpl.cs" />
<Compile Include="NativeWin32Platform.cs" />
<Compile Include="Win32Exception.cs" />
</ItemGroup>
<Import Project="..\Avalonia.Win32\Avalonia.Win32.Shared.projitems" Label="Shared" />
</Project>

197
src/Windows/Avalonia.Win32.NetStandard/ComStreamWrapper.cs

@ -1,197 +0,0 @@
//
// System.Drawing.ComIStreamWrapper.cs
//
// Author:
// Kornél Pál <http://www.kornelpal.hu/>
//
// Copyright (C) 2005-2008 Kornél Pál
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using STATSTG = System.Runtime.InteropServices.ComTypes.STATSTG;
namespace Avalonia.Win32
{
// Stream to IStream wrapper for COM interop
internal sealed class ComIStreamWrapper : IStream
{
private const int STG_E_INVALIDFUNCTION = unchecked((int)0x80030001);
private readonly Stream baseStream;
private long position = -1;
internal ComIStreamWrapper(Stream stream)
{
baseStream = stream;
}
private void SetSizeToPosition()
{
if (position != -1)
{
if (position > baseStream.Length)
baseStream.SetLength(position);
baseStream.Position = position;
position = -1;
}
}
public void Read(byte[] pv, int cb, IntPtr pcbRead)
{
int read = 0;
if (cb != 0)
{
SetSizeToPosition();
read = baseStream.Read(pv, 0, cb);
}
if (pcbRead != IntPtr.Zero)
Marshal.WriteInt32(pcbRead, read);
}
public void Write(byte[] pv, int cb, IntPtr pcbWritten)
{
if (cb != 0)
{
SetSizeToPosition();
baseStream.Write(pv, 0, cb);
}
if (pcbWritten != IntPtr.Zero)
Marshal.WriteInt32(pcbWritten, cb);
}
public void Seek(long dlibMove, int dwOrigin, IntPtr plibNewPosition)
{
long length = baseStream.Length;
long newPosition;
switch ((SeekOrigin)dwOrigin)
{
case SeekOrigin.Begin:
newPosition = dlibMove;
break;
case SeekOrigin.Current:
if (position == -1)
newPosition = baseStream.Position + dlibMove;
else
newPosition = position + dlibMove;
break;
case SeekOrigin.End:
newPosition = length + dlibMove;
break;
default:
throw new COMException(null, STG_E_INVALIDFUNCTION);
}
if (newPosition > length)
position = newPosition;
else
{
baseStream.Position = newPosition;
position = -1;
}
if (plibNewPosition != IntPtr.Zero)
Marshal.WriteInt64(plibNewPosition, newPosition);
}
public void SetSize(long libNewSize)
{
baseStream.SetLength(libNewSize);
}
public void CopyTo(IStream pstm, long cb, IntPtr pcbRead, IntPtr pcbWritten)
{
byte[] buffer;
long written = 0;
int read;
int count;
if (cb != 0)
{
if (cb < 4096)
count = (int)cb;
else
count = 4096;
buffer = new byte[count];
SetSizeToPosition();
while (true)
{
if ((read = baseStream.Read(buffer, 0, count)) == 0)
break;
pstm.Write(buffer, read, IntPtr.Zero);
written += read;
if (written >= cb)
break;
if (cb - written < 4096)
count = (int)(cb - written);
}
}
if (pcbRead != IntPtr.Zero)
Marshal.WriteInt64(pcbRead, written);
if (pcbWritten != IntPtr.Zero)
Marshal.WriteInt64(pcbWritten, written);
}
public void Commit(int grfCommitFlags)
{
baseStream.Flush();
SetSizeToPosition();
}
public void Revert()
{
throw new COMException(null, STG_E_INVALIDFUNCTION);
}
public void LockRegion(long libOffset, long cb, int dwLockType)
{
throw new COMException(null, STG_E_INVALIDFUNCTION);
}
public void UnlockRegion(long libOffset, long cb, int dwLockType)
{
throw new COMException(null, STG_E_INVALIDFUNCTION);
}
public void Stat(out STATSTG pstatstg, int grfStatFlag)
{
pstatstg = new STATSTG();
pstatstg.cbSize = baseStream.Length;
}
public void Clone(out IStream ppstm)
{
ppstm = null;
throw new COMException(null, STG_E_INVALIDFUNCTION);
}
}
}

128
src/Windows/Avalonia.Win32.NetStandard/Gdip.cs

@ -1,128 +0,0 @@
//
// Code copy-pasted from from Mono / System.Drawing.*.cs
// Original license below:
//
// Authors:
// Alexandre Pigolkine (pigolkine@gmx.de)
// Jordi Mas (jordi@ximian.com)
// Sanjay Gupta (gsanjay@novell.com)
// Ravindra (rkumar@novell.com)
// Peter Dennis Bartok (pbartok@novell.com)
// Sebastien Pouliot <sebastien@ximian.com>
//
//
// Copyright (C) 2004, 2007 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Text;
using System.Threading.Tasks;
namespace Avalonia.Win32
{
static class Gdip
{
public enum Status
{
Ok = 0,
GenericError = 1,
InvalidParameter = 2,
OutOfMemory = 3,
ObjectBusy = 4,
InsufficientBuffer = 5,
NotImplemented = 6,
Win32Error = 7,
WrongState = 8,
Aborted = 9,
FileNotFound = 10,
ValueOverflow = 11,
AccessDenied = 12,
UnknownImageFormat = 13,
FontFamilyNotFound = 14,
FontStyleNotFound = 15,
NotTrueTypeFont = 16,
UnsupportedGdiplusVersion = 17,
GdiplusNotInitialized = 18,
PropertyNotFound = 19,
PropertyNotSupported = 20,
ProfileNotFound = 21
}
[StructLayout(LayoutKind.Sequential)]
internal struct GdiplusStartupInput
{
// internalted to silent compiler
internal uint GdiplusVersion;
internal IntPtr DebugEventCallback;
internal int SuppressBackgroundThread;
internal int SuppressExternalCodecs;
internal static GdiplusStartupInput MakeGdiplusStartupInput()
{
GdiplusStartupInput result = new GdiplusStartupInput();
result.GdiplusVersion = 1;
result.DebugEventCallback = IntPtr.Zero;
result.SuppressBackgroundThread = 0;
result.SuppressExternalCodecs = 0;
return result;
}
}
[StructLayout(LayoutKind.Sequential)]
internal struct GdiplusStartupOutput
{
internal IntPtr NotificationHook;
internal IntPtr NotificationUnhook;
internal static GdiplusStartupOutput MakeGdiplusStartupOutput()
{
GdiplusStartupOutput result = new GdiplusStartupOutput();
result.NotificationHook = result.NotificationUnhook = IntPtr.Zero;
return result;
}
}
[DllImport("gdiplus.dll")]
public static extern Status GdiplusStartup(ref ulong token, ref GdiplusStartupInput input, ref GdiplusStartupOutput output);
[DllImport("gdiplus.dll", ExactSpelling = true, CharSet = CharSet.Unicode)]
public static extern Status GdipLoadImageFromStream([MarshalAs(UnmanagedType.Interface, MarshalTypeRef = typeof(IStream))] IStream stream, out IntPtr image);
[DllImport("gdiplus.dll")]
public static extern Status GdipCreateHICONFromBitmap(IntPtr bmp, out IntPtr HandleIcon);
[DllImport("gdiplus.dll")]
internal static extern Status GdipDisposeImage(IntPtr image);
static Gdip()
{
ulong token = 0;
var input = GdiplusStartupInput.MakeGdiplusStartupInput();
var output = GdiplusStartupOutput.MakeGdiplusStartupOutput();
GdiplusStartup(ref token, ref input, ref output);
}
}
}

45
src/Windows/Avalonia.Win32.NetStandard/IconImpl.cs

@ -1,45 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Text;
using System.Threading.Tasks;
using Avalonia.Platform;
namespace Avalonia.Win32
{
public class IconImpl : IWindowIconImpl
{
private readonly MemoryStream _ms;
public IconImpl(Stream data)
{
_ms = new MemoryStream();
data.CopyTo(_ms);
_ms.Seek(0, SeekOrigin.Begin);
IntPtr bitmap;
var status = Gdip.GdipLoadImageFromStream(new ComIStreamWrapper(_ms), out bitmap);
if (status != Gdip.Status.Ok)
throw new Exception("Unable to load icon, gdip status: " + (int) status);
IntPtr icon;
status = Gdip.GdipCreateHICONFromBitmap(bitmap, out icon);
if (status != Gdip.Status.Ok)
throw new Exception("Unable to create HICON, gdip status: " + (int)status);
Gdip.GdipDisposeImage(bitmap);
HIcon = icon;
}
public IntPtr HIcon { get;}
public void Save(Stream outputStream)
{
lock (_ms)
{
_ms.Seek(0, SeekOrigin.Begin);
_ms.CopyTo(outputStream);
}
}
}
}

30
src/Windows/Avalonia.Win32.NetStandard/NativeWin32Platform.cs

@ -1,30 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Avalonia.Platform;
namespace Avalonia.Win32
{
partial class Win32Platform
{
//TODO: An actual implementation
public IWindowIconImpl LoadIcon(string fileName)
{
//No file IO for netstandard, still waiting for proper net core tooling
throw new NotSupportedException();
}
public IWindowIconImpl LoadIcon(Stream stream) => new IconImpl(stream);
public IWindowIconImpl LoadIcon(IBitmapImpl bitmap)
{
var ms = new MemoryStream();
bitmap.Save(ms);
ms.Seek(0, SeekOrigin.Begin);
return new IconImpl(ms);
}
}
}

12
src/Windows/Avalonia.Win32.NetStandard/Win32Exception.cs

@ -1,12 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Avalonia.Win32.NetStandard
{
class AvaloniaWin32Exception : Exception
{
}
}

35
src/Windows/Avalonia.Win32/Avalonia.Win32.Shared.projitems

@ -1,35 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
<HasSharedItems>true</HasSharedItems>
<SharedGUID>9defc6b7-845b-4d8f-afc0-d32bf0032b8c</SharedGUID>
</PropertyGroup>
<PropertyGroup Label="Configuration">
<Import_RootNamespace>Avalonia.Win32.Shared</Import_RootNamespace>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)ClipboardImpl.cs" />
<Compile Include="$(MSBuildThisFileDirectory)CursorFactory.cs" />
<Compile Include="$(MSBuildThisFileDirectory)EmbeddedWindowImpl.cs" />
<Compile Include="$(MSBuildThisFileDirectory)FramebufferManager.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Input\KeyInterop.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Input\WindowsKeyboardDevice.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Input\WindowsMouseDevice.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\UnmanagedMethods.cs" />
<Compile Include="$(MSBuildThisFileDirectory)PlatformConstants.cs" />
<Compile Include="$(MSBuildThisFileDirectory)PopupImpl.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Properties\AssemblyInfo.cs" />
<Compile Include="$(MSBuildThisFileDirectory)RenderLoop.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ScreenImpl.cs" />
<Compile Include="$(MSBuildThisFileDirectory)SystemDialogImpl.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Win32Platform.cs" />
<Compile Include="$(MSBuildThisFileDirectory)WindowFramebuffer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)WindowImpl.cs" />
<Compile Include="$(MSBuildThisFileDirectory)WinScreen.cs" />
<Compile Include="$(MSBuildThisFileDirectory)..\..\Shared\WindowResizeDragHelper.cs" />
<Compile Include="..\..\Shared\SharedAssemblyInfo.cs">
<Link>Properties\SharedAssemblyInfo.cs</Link>
</Compile>
</ItemGroup>
</Project>

110
src/Windows/Avalonia.Win32/Avalonia.Win32.csproj

@ -1,103 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.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')" />
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{811A76CF-1CF6-440F-963B-BBE31BD72A82}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Avalonia.Win32</RootNamespace>
<AssemblyName>Avalonia.Win32</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Debug\Avalonia.Win32.xml</DocumentationFile>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<NoWarn>CS1591</NoWarn>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Release\Avalonia.Win32.xml</DocumentationFile>
<TargetFramework>netstandard2.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<NoWarn>CS1591</NoWarn>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
<ItemGroup>
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Windows.Forms" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Xaml" />
<Reference Include="WindowsBase" />
<Reference Include="WindowsFormsIntegration" />
</ItemGroup>
<ItemGroup>
<Compile Include="Embedding\WinFormsAvaloniaControlHost.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="IconImpl.cs" />
<Compile Include="WinFormsWin32Platform.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Avalonia.Animation\Avalonia.Animation.csproj">
<Project>{D211E587-D8BC-45B9-95A4-F297C8FA5200}</Project>
<Name>Avalonia.Animation</Name>
</ProjectReference>
<ProjectReference Include="..\..\Avalonia.Base\Avalonia.Base.csproj">
<Project>{B09B78D8-9B26-48B0-9149-D64A2F120F3F}</Project>
<Name>Avalonia.Base</Name>
</ProjectReference>
<ProjectReference Include="..\..\Avalonia.Controls\Avalonia.Controls.csproj">
<Project>{D2221C82-4A25-4583-9B43-D791E3F6820C}</Project>
<Name>Avalonia.Controls</Name>
</ProjectReference>
<ProjectReference Include="..\..\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj">
<Project>{7062AE20-5DCC-4442-9645-8195BDECE63E}</Project>
<Name>Avalonia.Diagnostics</Name>
</ProjectReference>
<ProjectReference Include="..\..\Avalonia.Input\Avalonia.Input.csproj">
<Project>{62024B2D-53EB-4638-B26B-85EEAA54866E}</Project>
<Name>Avalonia.Input</Name>
</ProjectReference>
<ProjectReference Include="..\..\Avalonia.Interactivity\Avalonia.Interactivity.csproj">
<Project>{6B0ED19D-A08B-461C-A9D9-A9EE40B0C06B}</Project>
<Name>Avalonia.Interactivity</Name>
</ProjectReference>
<ProjectReference Include="..\..\Avalonia.Layout\Avalonia.Layout.csproj">
<Project>{42472427-4774-4C81-8AFF-9F27B8E31721}</Project>
<Name>Avalonia.Layout</Name>
</ProjectReference>
<ProjectReference Include="..\..\Avalonia.Visuals\Avalonia.Visuals.csproj">
<Project>{EB582467-6ABB-43A1-B052-E981BA910E3A}</Project>
<Name>Avalonia.Visuals</Name>
</ProjectReference>
<ProjectReference Include="..\..\Avalonia.Styling\Avalonia.Styling.csproj">
<Project>{F1BAA01A-F176-4C6A-B39D-5B40BB1B148F}</Project>
<Name>Avalonia.Styling</Name>
</ProjectReference>
<ProjectReference Include="..\..\Avalonia.Animation\Avalonia.Animation.csproj" />
<ProjectReference Include="..\..\Avalonia.Base\Avalonia.Base.csproj" />
<ProjectReference Include="..\..\Avalonia.Controls\Avalonia.Controls.csproj" />
<ProjectReference Include="..\..\Avalonia.Input\Avalonia.Input.csproj" />
<ProjectReference Include="..\..\Avalonia.Interactivity\Avalonia.Interactivity.csproj" />
<ProjectReference Include="..\..\Avalonia.Layout\Avalonia.Layout.csproj" />
<ProjectReference Include="..\..\Avalonia.Styling\Avalonia.Styling.csproj" />
<ProjectReference Include="..\..\Avalonia.Visuals\Avalonia.Visuals.csproj" />
</ItemGroup>
<Import Project="Avalonia.Win32.Shared.projitems" Label="Shared" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\..\..\build\Rx.props" />
</Project>
<Import Project="$(MSBuildThisFileDirectory)\..\..\..\build\System.Drawing.Common.props" />
</Project>

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

@ -1098,7 +1098,7 @@ namespace Avalonia.Win32.Interop
}
}
[StructLayout(LayoutKind.Sequential)]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct WNDCLASSEX
{
public int cbSize;

2
src/Windows/Avalonia.Win32/Properties/AssemblyInfo.cs

@ -3,7 +3,5 @@
using Avalonia.Platform;
using Avalonia.Win32;
using System.Reflection;
[assembly: AssemblyTitle("Avalonia.Win32")]
[assembly: ExportWindowingSubsystem(OperatingSystemType.WinNT, 1, "Win32", typeof(Win32Platform), nameof(Win32Platform.Initialize))]

4
src/Windows/Avalonia.Win32/ScreenImpl.cs

@ -41,8 +41,8 @@ namespace Avalonia.Win32
Rect avaloniaBounds = new Rect(bounds.left, bounds.top, bounds.right - bounds.left,
bounds.bottom - bounds.top);
Rect avaloniaWorkArea =
new Rect(workingArea.left, workingArea.top, workingArea.right - bounds.left,
workingArea.bottom - bounds.top);
new Rect(workingArea.left, workingArea.top, workingArea.right - workingArea.left,
workingArea.bottom - workingArea.top);
screens[index] =
new WinScreen(avaloniaBounds, avaloniaWorkArea, monitorInfo.dwFlags == 1,
monitor);

184
src/Windows/Avalonia.Win32/Settings.StyleCop

@ -1,184 +0,0 @@
<StyleCopSettings Version="105">
<Analyzers>
<Analyzer AnalyzerId="StyleCop.CSharp.DocumentationRules">
<Rules>
<Rule Name="ElementsMustBeDocumented">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="PartialElementsMustBeDocumented">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="EnumerationItemsMustBeDocumented">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="DocumentationMustContainValidXml">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="ElementDocumentationMustHaveSummary">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="PartialElementDocumentationMustHaveSummary">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="ElementDocumentationMustHaveSummaryText">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="PartialElementDocumentationMustHaveSummaryText">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="ElementDocumentationMustNotHaveDefaultSummary">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="ElementParametersMustBeDocumented">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="ElementParameterDocumentationMustMatchElementParameters">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="ElementParameterDocumentationMustDeclareParameterName">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="ElementParameterDocumentationMustHaveText">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="ElementReturnValueMustBeDocumented">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="ElementReturnValueDocumentationMustHaveText">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="VoidReturnValueMustNotBeDocumented">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="GenericTypeParametersMustBeDocumented">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="GenericTypeParametersMustBeDocumentedPartialClass">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="GenericTypeParameterDocumentationMustMatchTypeParameters">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="GenericTypeParameterDocumentationMustDeclareParameterName">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="GenericTypeParameterDocumentationMustHaveText">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="PropertySummaryDocumentationMustMatchAccessors">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="PropertySummaryDocumentationMustOmitSetAccessorWithRestrictedAccess">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="ElementDocumentationMustNotBeCopiedAndPasted">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="SingleLineCommentsMustNotUseDocumentationStyleSlashes">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="DocumentationTextMustNotBeEmpty">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="DocumentationTextMustContainWhitespace">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="DocumentationMustMeetCharacterPercentage">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="ConstructorSummaryDocumentationMustBeginWithStandardText">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="DestructorSummaryDocumentationMustBeginWithStandardText">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="DocumentationHeadersMustNotContainBlankLines">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="IncludedDocumentationXPathDoesNotExist">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="IncludeNodeDoesNotContainValidFileAndPath">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="InheritDocMustBeUsedWithInheritingClass">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="ElementDocumentationMustBeSpelledCorrectly">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
</Rules>
<AnalyzerSettings />
</Analyzer>
</Analyzers>
</StyleCopSettings>

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

@ -16,6 +16,7 @@ using Avalonia.Win32.Interop;
using Avalonia.Controls;
using Avalonia.Rendering;
using Avalonia.Threading;
using System.IO;
#if NETSTANDARD
using Win32Exception = Avalonia.Win32.NetStandard.AvaloniaWin32Exception;
#else
@ -40,7 +41,7 @@ namespace Avalonia
namespace Avalonia.Win32
{
partial class Win32Platform : IPlatformThreadingInterface, IPlatformSettings, IWindowingPlatform, IPlatformIconLoader
class Win32Platform : IPlatformThreadingInterface, IPlatformSettings, IWindowingPlatform, IPlatformIconLoader
{
private static readonly Win32Platform s_instance = new Win32Platform();
private static uint _uiThread;
@ -205,5 +206,40 @@ namespace Avalonia.Win32
{
return new PopupImpl();
}
public IWindowIconImpl LoadIcon(string fileName)
{
using (var stream = File.OpenRead(fileName))
{
return CreateIconImpl(stream);
}
}
public IWindowIconImpl LoadIcon(Stream stream)
{
return CreateIconImpl(stream);
}
public IWindowIconImpl LoadIcon(IBitmapImpl bitmap)
{
using (var memoryStream = new MemoryStream())
{
bitmap.Save(memoryStream);
return new IconImpl(new System.Drawing.Bitmap(memoryStream));
}
}
private static IconImpl CreateIconImpl(Stream stream)
{
try
{
return new IconImpl(new System.Drawing.Icon(stream));
}
catch (ArgumentException)
{
return new IconImpl(new System.Drawing.Bitmap(stream));
}
}
}
}

47
src/Windows/Avalonia.Win32/WinFormsWin32Platform.cs

@ -1,47 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Avalonia.Platform;
namespace Avalonia.Win32
{
partial class Win32Platform
{
public IWindowIconImpl LoadIcon(string fileName)
{
using (var stream = File.OpenRead(fileName))
{
return CreateImpl(stream);
}
}
public IWindowIconImpl LoadIcon(Stream stream)
{
return CreateImpl(stream);
}
public IWindowIconImpl LoadIcon(IBitmapImpl bitmap)
{
using (var memoryStream = new MemoryStream())
{
bitmap.Save(memoryStream);
return new IconImpl(new System.Drawing.Bitmap(memoryStream));
}
}
private static IconImpl CreateImpl(Stream stream)
{
try
{
return new IconImpl(new System.Drawing.Icon(stream));
}
catch (ArgumentException)
{
return new IconImpl(new System.Drawing.Bitmap(stream));
}
}
}
}

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

@ -1,29 +1,24 @@
// 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.Input;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reactive.Disposables;
using System.Runtime.InteropServices;
using Avalonia.Controls;
using System.Reactive.Disposables;
using Avalonia.Input;
using Avalonia.Input.Raw;
using Avalonia.Platform;
using Avalonia.Rendering;
using Avalonia.Win32.Input;
using Avalonia.Win32.Interop;
using static Avalonia.Win32.Interop.UnmanagedMethods;
using Avalonia.Rendering;
using Avalonia.Threading;
#if NETSTANDARD
using Win32Exception = Avalonia.Win32.NetStandard.AvaloniaWin32Exception;
#endif
namespace Avalonia.Win32
{
class WindowImpl : IWindowImpl
public class WindowImpl : IWindowImpl
{
private static readonly List<WindowImpl> s_instances = new List<WindowImpl>();
@ -646,7 +641,7 @@ namespace Avalonia.Win32
// Ensure that the delegate doesn't get garbage collected by storing it as a field.
_wndProcDelegate = new UnmanagedMethods.WndProc(WndProc);
_className = Guid.NewGuid().ToString();
_className = "Avalonia-" + Guid.NewGuid();
UnmanagedMethods.WNDCLASSEX wndClassEx = new UnmanagedMethods.WNDCLASSEX
{

9
src/iOS/Avalonia.iOS/EmulatedFramebuffer.cs

@ -16,11 +16,15 @@ namespace Avalonia.iOS
/// </summary>
class EmulatedFramebuffer : ILockedFramebuffer
{
private nfloat _viewWidth;
private nfloat _viewHeight;
public EmulatedFramebuffer(UIView view)
{
var factor = (int) UIScreen.MainScreen.Scale;
var frame = view.Frame;
_viewWidth = frame.Width;
_viewHeight = frame.Height;
Width = (int) frame.Width * factor;
Height = (int) frame.Height * factor;
RowBytes = Width * 4;
@ -41,9 +45,9 @@ namespace Avalonia.iOS
using (var context = UIGraphics.GetCurrentContext())
{
// flip the image for CGContext.DrawImage
context.TranslateCTM(0, Height);
context.TranslateCTM(0, _viewHeight);
context.ScaleCTM(1, -1);
context.DrawImage(new CGRect(0, 0, Width, Height), image);
context.DrawImage(new CGRect(0, 0, _viewWidth, _viewHeight), image);
}
Marshal.FreeHGlobal(Address);
Address = IntPtr.Zero;
@ -57,3 +61,4 @@ namespace Avalonia.iOS
public PixelFormat Format { get; }
}
}

83
tests/Avalonia.Controls.UnitTests/WindowTests.cs

@ -70,7 +70,7 @@ namespace Avalonia.Controls.UnitTests
}
[Fact]
public void IsVisible_Should_Be_False_Atfer_Hide()
public void IsVisible_Should_Be_False_After_Hide()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
@ -84,7 +84,7 @@ namespace Avalonia.Controls.UnitTests
}
[Fact]
public void IsVisible_Should_Be_False_Atfer_Close()
public void IsVisible_Should_Be_False_After_Close()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
@ -98,7 +98,7 @@ namespace Avalonia.Controls.UnitTests
}
[Fact]
public void IsVisible_Should_Be_False_Atfer_Impl_Signals_Close()
public void IsVisible_Should_Be_False_After_Impl_Signals_Close()
{
var windowImpl = new Mock<IWindowImpl>();
windowImpl.SetupProperty(x => x.Closed);
@ -238,6 +238,83 @@ namespace Avalonia.Controls.UnitTests
((IList<Window>)Window.OpenWindows).Clear();
}
[Fact]
public void Window_Should_Be_Centered_When_WindowStartupLocation_Is_CenterScreen()
{
var screen1 = new Mock<Screen>(new Rect(new Size(1920, 1080)), new Rect(new Size(1920, 1040)), true);
var screen2 = new Mock<Screen>(new Rect(new Size(1366, 768)), new Rect(new Size(1366, 728)), false);
var screens = new Mock<IScreenImpl>();
screens.Setup(x => x.AllScreens).Returns(new Screen[] { screen1.Object, screen2.Object });
var windowImpl = new Mock<IWindowImpl>();
windowImpl.SetupProperty(x => x.Position);
windowImpl.Setup(x => x.ClientSize).Returns(new Size(800, 480));
windowImpl.Setup(x => x.Scaling).Returns(1);
windowImpl.Setup(x => x.Screen).Returns(screens.Object);
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var window = new Window(windowImpl.Object);
window.WindowStartupLocation = WindowStartupLocation.CenterScreen;
window.Position = new Point(60, 40);
window.Show();
var expectedPosition = new Point(
screen1.Object.WorkingArea.Size.Width / 2 - window.ClientSize.Width / 2,
screen1.Object.WorkingArea.Size.Height / 2 - window.ClientSize.Height / 2);
Assert.Equal(window.Position, expectedPosition);
}
}
[Fact]
public void Window_Should_Be_Centered_Relative_To_Owner_When_WindowStartupLocation_Is_CenterOwner()
{
var parentWindowImpl = new Mock<IWindowImpl>();
parentWindowImpl.SetupProperty(x => x.Position);
parentWindowImpl.Setup(x => x.ClientSize).Returns(new Size(800, 480));
parentWindowImpl.Setup(x => x.MaxClientSize).Returns(new Size(1920, 1080));
parentWindowImpl.Setup(x => x.Scaling).Returns(1);
var windowImpl = new Mock<IWindowImpl>();
windowImpl.SetupProperty(x => x.Position);
windowImpl.Setup(x => x.ClientSize).Returns(new Size(320, 200));
windowImpl.Setup(x => x.MaxClientSize).Returns(new Size(1920, 1080));
windowImpl.Setup(x => x.Scaling).Returns(1);
var parentWindowServices = TestServices.StyledWindow.With(
windowingPlatform: new MockWindowingPlatform(() => parentWindowImpl.Object));
var windowServices = TestServices.StyledWindow.With(
windowingPlatform: new MockWindowingPlatform(() => windowImpl.Object));
using (UnitTestApplication.Start(parentWindowServices))
{
var parentWindow = new Window();
parentWindow.Position = new Point(60, 40);
parentWindow.Show();
using (UnitTestApplication.Start(windowServices))
{
var window = new Window();
window.WindowStartupLocation = WindowStartupLocation.CenterOwner;
window.Position = new Point(60, 40);
window.Owner = parentWindow;
window.Show();
var expectedPosition = new Point(
parentWindow.Position.X + parentWindow.ClientSize.Width / 2 - window.ClientSize.Width / 2,
parentWindow.Position.Y + parentWindow.ClientSize.Height / 2 - window.ClientSize.Height / 2);
Assert.Equal(window.Position, expectedPosition);
}
}
}
private IWindowImpl CreateImpl(Mock<IRenderer> renderer)
{
return Mock.Of<IWindowImpl>(x =>

Loading…
Cancel
Save