diff --git a/.editorconfig b/.editorconfig
index f6bce9cb76..c7a381b730 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -156,6 +156,9 @@ indent_size = 2
[*.{props,targets,config,nuspec}]
indent_size = 2
+[*.json]
+indent_size = 2
+
# Shell scripts
[*.sh]
end_of_line = lf
diff --git a/.ncrunch/Avalonia.Build.Tasks.v3.ncrunchproject b/.ncrunch/Avalonia.Build.Tasks.v3.ncrunchproject
index 319cd523ce..95a483b433 100644
--- a/.ncrunch/Avalonia.Build.Tasks.v3.ncrunchproject
+++ b/.ncrunch/Avalonia.Build.Tasks.v3.ncrunchproject
@@ -1,5 +1,3 @@
-
- True
-
+
\ No newline at end of file
diff --git a/.ncrunch/Avalonia.MicroCom.v3.ncrunchproject b/.ncrunch/Avalonia.MicroCom.v3.ncrunchproject
new file mode 100644
index 0000000000..319cd523ce
--- /dev/null
+++ b/.ncrunch/Avalonia.MicroCom.v3.ncrunchproject
@@ -0,0 +1,5 @@
+
+
+ True
+
+
\ No newline at end of file
diff --git a/Avalonia.sln b/Avalonia.sln
index 34ad19b41d..75f1dd8407 100644
--- a/Avalonia.sln
+++ b/Avalonia.sln
@@ -226,6 +226,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.ReactiveUI.Events"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sandbox", "samples\Sandbox\Sandbox.csproj", "{11BE52AF-E2DD-4CF0-B19A-05285ACAF571}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MicroComGenerator", "src\tools\MicroComGenerator\MicroComGenerator.csproj", "{AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.MicroCom", "src\Avalonia.MicroCom\Avalonia.MicroCom.csproj", "{FE2F3E5E-1E34-4972-8DC1-5C2C588E5ECE}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MiniMvvm", "samples\MiniMvvm\MiniMvvm.csproj", "{BC594FD5-4AF2-409E-A1E6-04123F54D7C5}"
+EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
src\Shared\RenderHelpers\RenderHelpers.projitems*{3c4c0cb4-0c0f-4450-a37b-148c84ff905f}*SharedItemsImports = 13
@@ -2064,6 +2070,78 @@ Global
{11BE52AF-E2DD-4CF0-B19A-05285ACAF571}.Release|iPhone.Build.0 = Release|Any CPU
{11BE52AF-E2DD-4CF0-B19A-05285ACAF571}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{11BE52AF-E2DD-4CF0-B19A-05285ACAF571}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
+ {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
+ {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
+ {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
+ {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
+ {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.AppStore|Any CPU.Build.0 = Debug|Any CPU
+ {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
+ {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.AppStore|iPhone.Build.0 = Debug|Any CPU
+ {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Release|Any CPU.Build.0 = Release|Any CPU
+ {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Release|iPhone.Build.0 = Release|Any CPU
+ {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {FE2F3E5E-1E34-4972-8DC1-5C2C588E5ECE}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
+ {FE2F3E5E-1E34-4972-8DC1-5C2C588E5ECE}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
+ {FE2F3E5E-1E34-4972-8DC1-5C2C588E5ECE}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
+ {FE2F3E5E-1E34-4972-8DC1-5C2C588E5ECE}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
+ {FE2F3E5E-1E34-4972-8DC1-5C2C588E5ECE}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {FE2F3E5E-1E34-4972-8DC1-5C2C588E5ECE}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {FE2F3E5E-1E34-4972-8DC1-5C2C588E5ECE}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
+ {FE2F3E5E-1E34-4972-8DC1-5C2C588E5ECE}.AppStore|Any CPU.Build.0 = Debug|Any CPU
+ {FE2F3E5E-1E34-4972-8DC1-5C2C588E5ECE}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
+ {FE2F3E5E-1E34-4972-8DC1-5C2C588E5ECE}.AppStore|iPhone.Build.0 = Debug|Any CPU
+ {FE2F3E5E-1E34-4972-8DC1-5C2C588E5ECE}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {FE2F3E5E-1E34-4972-8DC1-5C2C588E5ECE}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {FE2F3E5E-1E34-4972-8DC1-5C2C588E5ECE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FE2F3E5E-1E34-4972-8DC1-5C2C588E5ECE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FE2F3E5E-1E34-4972-8DC1-5C2C588E5ECE}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {FE2F3E5E-1E34-4972-8DC1-5C2C588E5ECE}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {FE2F3E5E-1E34-4972-8DC1-5C2C588E5ECE}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {FE2F3E5E-1E34-4972-8DC1-5C2C588E5ECE}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {FE2F3E5E-1E34-4972-8DC1-5C2C588E5ECE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FE2F3E5E-1E34-4972-8DC1-5C2C588E5ECE}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FE2F3E5E-1E34-4972-8DC1-5C2C588E5ECE}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {FE2F3E5E-1E34-4972-8DC1-5C2C588E5ECE}.Release|iPhone.Build.0 = Release|Any CPU
+ {FE2F3E5E-1E34-4972-8DC1-5C2C588E5ECE}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {FE2F3E5E-1E34-4972-8DC1-5C2C588E5ECE}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {BC594FD5-4AF2-409E-A1E6-04123F54D7C5}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
+ {BC594FD5-4AF2-409E-A1E6-04123F54D7C5}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
+ {BC594FD5-4AF2-409E-A1E6-04123F54D7C5}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
+ {BC594FD5-4AF2-409E-A1E6-04123F54D7C5}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
+ {BC594FD5-4AF2-409E-A1E6-04123F54D7C5}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {BC594FD5-4AF2-409E-A1E6-04123F54D7C5}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {BC594FD5-4AF2-409E-A1E6-04123F54D7C5}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
+ {BC594FD5-4AF2-409E-A1E6-04123F54D7C5}.AppStore|Any CPU.Build.0 = Debug|Any CPU
+ {BC594FD5-4AF2-409E-A1E6-04123F54D7C5}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
+ {BC594FD5-4AF2-409E-A1E6-04123F54D7C5}.AppStore|iPhone.Build.0 = Debug|Any CPU
+ {BC594FD5-4AF2-409E-A1E6-04123F54D7C5}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {BC594FD5-4AF2-409E-A1E6-04123F54D7C5}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {BC594FD5-4AF2-409E-A1E6-04123F54D7C5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BC594FD5-4AF2-409E-A1E6-04123F54D7C5}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BC594FD5-4AF2-409E-A1E6-04123F54D7C5}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {BC594FD5-4AF2-409E-A1E6-04123F54D7C5}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {BC594FD5-4AF2-409E-A1E6-04123F54D7C5}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {BC594FD5-4AF2-409E-A1E6-04123F54D7C5}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {BC594FD5-4AF2-409E-A1E6-04123F54D7C5}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BC594FD5-4AF2-409E-A1E6-04123F54D7C5}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BC594FD5-4AF2-409E-A1E6-04123F54D7C5}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {BC594FD5-4AF2-409E-A1E6-04123F54D7C5}.Release|iPhone.Build.0 = Release|Any CPU
+ {BC594FD5-4AF2-409E-A1E6-04123F54D7C5}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {BC594FD5-4AF2-409E-A1E6-04123F54D7C5}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -2123,6 +2201,8 @@ Global
{3C84E04B-36CF-4D0D-B965-C26DD649D1F3} = {A0CC0258-D18C-4AB3-854F-7101680FC3F9}
{909A8CBD-7D0E-42FD-B841-022AD8925820} = {8B6A8209-894F-4BA1-B880-965FD453982C}
{11BE52AF-E2DD-4CF0-B19A-05285ACAF571} = {9B9E3891-2366-4253-A952-D08BCEB71098}
+ {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD} = {4ED8B739-6F4E-4CD4-B993-545E6B5CE637}
+ {BC594FD5-4AF2-409E-A1E6-04123F54D7C5} = {9B9E3891-2366-4253-A952-D08BCEB71098}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {87366D66-1391-4D90-8999-95A620AD786A}
diff --git a/Avalonia.sln.DotSettings b/Avalonia.sln.DotSettings
index 7060f4a62a..25d62b0494 100644
--- a/Avalonia.sln.DotSettings
+++ b/Avalonia.sln.DotSettings
@@ -37,4 +37,5 @@
<Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
<Policy Inspect="False" Prefix="T" Suffix="" Style="AaBb" />
<Policy Inspect="False" Prefix="" Suffix="" Style="AaBb" />
+ True
True
\ No newline at end of file
diff --git a/Avalonia.v3.ncrunchsolution b/Avalonia.v3.ncrunchsolution
index afce1018ec..b97a8e54f5 100644
--- a/Avalonia.v3.ncrunchsolution
+++ b/Avalonia.v3.ncrunchsolution
@@ -4,6 +4,8 @@
tests\TestFiles\**.*
src\Avalonia.Build.Tasks\bin\Debug\netstandard2.0\Avalonia.Build.Tasks.dll
src\Avalonia.Build.Tasks\bin\Debug\netstandard2.0\Mono.Cecil.dll
+ src\Avalonia.Build.Tasks\bin\Debug\netstandard2.0\Mono.Cecil.Rocks.dll
+ src\Avalonia.Build.Tasks\bin\Debug\netstandard2.0\Mono.Cecil.Pdb.dll
True
diff --git a/Directory.Build.props b/Directory.Build.props
index b41f8c488e..c6610695c4 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -2,5 +2,7 @@
$(MSBuildThisFileDirectory)build-intermediate/nuget
$(MSBuildThisFileDirectory)\src\tools\Avalonia.Designer.HostApp\bin\$(Configuration)\netcoreapp2.0\Avalonia.Designer.HostApp.dll
+
+ false
diff --git a/Documentation/build.md b/Documentation/build.md
index 8c2ef57b54..5f75290424 100644
--- a/Documentation/build.md
+++ b/Documentation/build.md
@@ -30,7 +30,7 @@ The build process needs [Xcode](https://developer.apple.com/xcode/) to build the
Linux operating systems ship with their own respective package managers however we will use [Homebrew](https://brew.sh/) to manage packages on macOS. To install follow the instructions [here](https://docs.brew.sh/Installation).
-### Install CastXML
+### Install CastXML (pre Nov 2020)
Avalonia requires [CastXML](https://github.com/CastXML/CastXML) for XML processing during the build process. The easiest way to install this is via the operating system's package managers, such as below.
@@ -60,14 +60,10 @@ git submodule update --init --recursive
### Build native libraries (macOS only)
-On macOS it is necessary to build and manually install the respective native libraries using [Xcode](https://developer.apple.com/xcode/). The steps to get this working correctly are:
-- Navigate to the Avalonia/native/Avalonia.Native/src/OSX folder and open the `Avalonia.Native.OSX.xcodeproj` project
-- Build the library via the Product->Build menu. This will generate binaries in your local path under ~/Library/Developer/Xcode/DerivedData/Avalonia.Native.OSX-*guid* where "guid" is uniquely generated every time you build.
-- Manually install the native library by copying it from the build artifacts folder into the shared dynamic library path:
+On macOS it is necessary to build and manually install the respective native libraries using [Xcode](https://developer.apple.com/xcode/). Execute the build script in the root project with the `CompileNative` task. It will build the headers, build the libraries, and place them in the appropriate place to allow .NET to find them at compilation and run time.
-```
-cd ~/Library/Developer/Xcode/DerivedData/Avalonia.Native.OSX-[guid]/Build/Products/Debug
-cp libAvalonia.Native.OSX.dylib /usr/local/lib/libAvaloniaNative.dylib
+```bash
+./build.sh CompileNative
```
### Build and Run Avalonia
diff --git a/NuGet.Config b/NuGet.Config
index 3abd236d42..7a1f28bea7 100644
--- a/NuGet.Config
+++ b/NuGet.Config
@@ -4,6 +4,6 @@
-
+
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 721a0415f4..ac1944b171 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -3,13 +3,6 @@ jobs:
pool:
vmImage: 'ubuntu-16.04'
steps:
- - task: CmdLine@2
- displayName: 'Install CastXML'
- inputs:
- script: |
- sudo apt-get update
- sudo apt-get install castxml
-
- task: CmdLine@2
displayName: 'Install Nuke'
inputs:
@@ -31,6 +24,8 @@ jobs:
condition: not(canceled())
- job: macOS
+ variables:
+ SolutionDir: '$(Build.SourcesDirectory)'
pool:
vmImage: 'macOS-10.14'
steps:
@@ -46,6 +41,12 @@ jobs:
curl -o ./mono.pkg https://download.mono-project.com/archive/5.18.0/macos-10-universal/MonoFramework-MDK-5.18.0.225.macos10.xamarin.universal.pkg
sudo installer -verbose -pkg ./mono.pkg -target /
+ - task: CmdLine@2
+ displayName: 'Generate avalonia-native'
+ inputs:
+ script: |
+ cd src/tools/MicroComGenerator; dotnet run -i ../../Avalonia.Native/avn.idl --cpp ../../../native/Avalonia.Native/inc/avalonia-native.h
+
- task: Xcode@5
inputs:
actions: 'build'
@@ -97,6 +98,8 @@ jobs:
- job: Windows
pool:
vmImage: 'windows-2019'
+ variables:
+ SolutionDir: '$(Build.SourcesDirectory)'
steps:
- task: UseDotNet@2
displayName: 'Use .NET Core SDK 3.1.401'
diff --git a/build.ps1 b/build.ps1
index 57e2f80075..985e8abcee 100644
--- a/build.ps1
+++ b/build.ps1
@@ -43,7 +43,7 @@ if (Test-Path $DotNetGlobalFile) {
}
# If dotnet is installed locally, and expected version is not set or installation matches the expected version
-if ((Get-Command "dotnet" -ErrorAction SilentlyContinue) -ne $null -and `
+if ($null -ne (Get-Command "dotnet" -ErrorAction SilentlyContinue) -and `
(!(Test-Path variable:DotNetVersion) -or $(& dotnet --version) -eq $DotNetVersion)) {
$env:DOTNET_EXE = (Get-Command "dotnet").Path
}
@@ -53,7 +53,7 @@ else {
# Download install script
$DotNetInstallFile = "$TempDirectory\dotnet-install.ps1"
- md -force $TempDirectory > $null
+ mkdir -force $TempDirectory > $null
(New-Object System.Net.WebClient).DownloadFile($DotNetInstallUrl, $DotNetInstallFile)
# Install by channel or version
@@ -62,6 +62,8 @@ else {
} else {
ExecSafe { & $DotNetInstallFile -InstallDir $DotNetDirectory -Version $DotNetVersion -NoPath }
}
+
+ $env:PATH="$DotNetDirectory;$env:PATH"
}
Write-Output "Microsoft (R) .NET Core SDK version $(& $env:DOTNET_EXE --version)"
diff --git a/build.sh b/build.sh
index a40e00f815..bd162fab9b 100755
--- a/build.sh
+++ b/build.sh
@@ -47,7 +47,7 @@ if [ -f "$DOTNET_GLOBAL_FILE" ]; then
fi
# If dotnet is installed locally, and expected version is not set or installation matches the expected version
-if [[ -x "$(command -v dotnet)" && (-z ${DOTNET_VERSION+x} || $(dotnet --version) == "$DOTNET_VERSION") ]]; then
+if [[ -x "$(command -v dotnet)" && (-z ${DOTNET_VERSION+x} || $(dotnet --version) == "$DOTNET_VERSION") || "$SKIP_DOTNET_DOWNLOAD" == "1" ]]; then
export DOTNET_EXE="$(command -v dotnet)"
else
DOTNET_DIRECTORY="$TEMP_DIRECTORY/dotnet-unix"
diff --git a/build/ApiDiff.props b/build/ApiDiff.props
index da82fbcc51..fb65ef6e87 100644
--- a/build/ApiDiff.props
+++ b/build/ApiDiff.props
@@ -1,12 +1,12 @@
- 0.10.0-preview3
+ 0.10.0-preview6
$(PackageId)
Avalonia
-
+
diff --git a/build/Assets/Icon.png b/build/Assets/Icon.png
new file mode 100644
index 0000000000..41a2a618fb
Binary files /dev/null and b/build/Assets/Icon.png differ
diff --git a/build/CoreLibraries.props b/build/CoreLibraries.props
index d17eec0135..fff00041c3 100644
--- a/build/CoreLibraries.props
+++ b/build/CoreLibraries.props
@@ -15,6 +15,7 @@
+
diff --git a/build/EmbedXaml.props b/build/EmbedXaml.props
index 7ce0366dea..0bb8da4f47 100644
--- a/build/EmbedXaml.props
+++ b/build/EmbedXaml.props
@@ -4,8 +4,9 @@
%(Filename)
+
Designer
-
\ No newline at end of file
+
diff --git a/build/MicroCom.targets b/build/MicroCom.targets
new file mode 100644
index 0000000000..b48e377fd4
--- /dev/null
+++ b/build/MicroCom.targets
@@ -0,0 +1,33 @@
+
+
+
+
+
+ false
+ all
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_AvaloniaPatchComInterop>true
+
+
+
diff --git a/build/ReactiveUI.props b/build/ReactiveUI.props
index d8e86e917e..f74ab07e31 100644
--- a/build/ReactiveUI.props
+++ b/build/ReactiveUI.props
@@ -1,5 +1,5 @@
-
+
diff --git a/build/Rx.props b/build/Rx.props
index 8a15ccd6a9..fde1f80ea1 100644
--- a/build/Rx.props
+++ b/build/Rx.props
@@ -1,5 +1,5 @@
-
+
diff --git a/build/SharedVersion.props b/build/SharedVersion.props
index d3cebef418..43ec995ed9 100644
--- a/build/SharedVersion.props
+++ b/build/SharedVersion.props
@@ -10,10 +10,17 @@
CS1591
latest
MIT
- https://avatars2.githubusercontent.com/u/14075148?s=200
+ Icon.png
Avalonia is a WPF/UWP-inspired cross-platform XAML-based UI framework providing a flexible styling system and supporting a wide range of Operating Systems such as Windows (.NET Framework, .NET Core), Linux (via Xorg), MacOS and with experimental support for Android and iOS.
avalonia;avaloniaui;mvvm;rx;reactive extensions;android;ios;mac;forms;wpf;net;netstandard;net461;uwp;xamarin
https://github.com/AvaloniaUI/Avalonia/releases
git
+ $(MSBuildThisFileDirectory)\avalonia.snk
+ true
+ $(DefineConstants);SIGNED_BUILD
+
+
+
+
diff --git a/build/SourceLink.props b/build/SourceLink.props
index 0c9b6a34f8..e27727c9e8 100644
--- a/build/SourceLink.props
+++ b/build/SourceLink.props
@@ -1,5 +1,5 @@
-
+
-
\ No newline at end of file
+
diff --git a/build/XUnit.props b/build/XUnit.props
index 079565d184..a75e1bac86 100644
--- a/build/XUnit.props
+++ b/build/XUnit.props
@@ -11,4 +11,8 @@
+
+ $(MSBuildThisFileDirectory)\avalonia.snk
+ False
+
diff --git a/build/avalonia.snk b/build/avalonia.snk
new file mode 100644
index 0000000000..10b49deb31
Binary files /dev/null and b/build/avalonia.snk differ
diff --git a/dirs.proj b/dirs.proj
index bf32abef72..594f2c22d3 100644
--- a/dirs.proj
+++ b/dirs.proj
@@ -21,6 +21,7 @@
+
diff --git a/native/Avalonia.Native/inc/.gitignore b/native/Avalonia.Native/inc/.gitignore
new file mode 100644
index 0000000000..e7aa7fc6a5
--- /dev/null
+++ b/native/Avalonia.Native/inc/.gitignore
@@ -0,0 +1 @@
+avalonia-native.h
diff --git a/native/Avalonia.Native/inc/avalonia-native.h b/native/Avalonia.Native/inc/avalonia-native.h
deleted file mode 100644
index 9ff6130e5f..0000000000
--- a/native/Avalonia.Native/inc/avalonia-native.h
+++ /dev/null
@@ -1,516 +0,0 @@
-#include "com.h"
-#include "key.h"
-#include "stddef.h"
-
-#define AVNCOM(name, id) COMINTERFACE(name, 2e2cda0a, 9ae5, 4f1b, 8e, 20, 08, 1a, 04, 27, 9f, id)
-
-struct IAvnWindowEvents;
-struct IAvnWindow;
-struct IAvnPopup;
-struct IAvnMacOptions;
-struct IAvnPlatformThreadingInterface;
-struct IAvnSystemDialogEvents;
-struct IAvnSystemDialogs;
-struct IAvnScreens;
-struct IAvnClipboard;
-struct IAvnCursor;
-struct IAvnCursorFactory;
-struct IAvnGlFeature;
-struct IAvnGlContext;
-struct IAvnGlDisplay;
-struct IAvnGlSurfaceRenderTarget;
-struct IAvnGlSurfaceRenderingSession;
-struct IAvnMenu;
-struct IAvnMenuItem;
-struct IAvnStringArray;
-struct IAvnDndResultCallback;
-struct IAvnGCHandleDeallocatorCallback;
-struct IAvnMenuEvents;
-struct IAvnNativeControlHost;
-struct IAvnNativeControlHostTopLevelAttachment;
-enum SystemDecorations {
- SystemDecorationsNone = 0,
- SystemDecorationsBorderOnly = 1,
- SystemDecorationsFull = 2,
-};
-
-struct AvnSize
-{
- double Width, Height;
-};
-
-struct AvnPixelSize
-{
- int Width, Height;
-};
-
-struct AvnRect
-{
- double X, Y, Width, Height;
-};
-
-struct AvnVector
-{
- double X, Y;
-};
-
-struct AvnPoint
-{
- double X, Y;
-};
-
-struct AvnScreen
-{
- AvnRect Bounds;
- AvnRect WorkingArea;
- float PixelDensity;
- bool Primary;
-};
-
-enum AvnPixelFormat
-{
- kAvnRgb565,
- kAvnRgba8888,
- kAvnBgra8888
-};
-
-struct AvnFramebuffer
-{
- void* Data;
- int Width;
- int Height;
- int Stride;
- AvnVector Dpi;
- AvnPixelFormat PixelFormat;
-};
-
-struct AvnColor
-{
- unsigned char Alpha;
- unsigned char Red;
- unsigned char Green;
- unsigned char Blue;
-};
-
-enum AvnRawMouseEventType
-{
- LeaveWindow,
- LeftButtonDown,
- LeftButtonUp,
- RightButtonDown,
- RightButtonUp,
- MiddleButtonDown,
- MiddleButtonUp,
- XButton1Down,
- XButton1Up,
- XButton2Down,
- XButton2Up,
- Move,
- Wheel,
- NonClientLeftButtonDown,
- TouchBegin,
- TouchUpdate,
- TouchEnd,
- TouchCancel
-};
-
-enum AvnRawKeyEventType
-{
- KeyDown,
- KeyUp
-};
-
-enum AvnInputModifiers
-{
- AvnInputModifiersNone = 0,
- Alt = 1,
- Control = 2,
- Shift = 4,
- Windows = 8,
- LeftMouseButton = 16,
- RightMouseButton = 32,
- MiddleMouseButton = 64,
- XButton1MouseButton = 128,
- XButton2MouseButton = 256
-};
-
-enum class AvnDragDropEffects
-{
- None = 0,
- Copy = 1,
- Move = 2,
- Link = 4,
-};
-
-enum class AvnDragEventType
-{
- Enter,
- Over,
- Leave,
- Drop
-};
-
-enum AvnWindowState
-{
- Normal,
- Minimized,
- Maximized,
- FullScreen,
-};
-
-enum AvnStandardCursorType
-{
- CursorArrow,
- CursorIbeam,
- CursorWait,
- CursorCross,
- CursorUpArrow,
- CursorSizeWestEast,
- CursorSizeNorthSouth,
- CursorSizeAll,
- CursorNo,
- CursorHand,
- CursorAppStarting,
- CursorHelp,
- CursorTopSide,
- CursorBottomSize,
- CursorLeftSide,
- CursorRightSide,
- CursorTopLeftCorner,
- CursorTopRightCorner,
- CursorBottomLeftCorner,
- CursorBottomRightCorner,
- CursorDragMove,
- CursorDragCopy,
- CursorDragLink,
- CursorNone
-};
-
-enum AvnWindowEdge
-{
- WindowEdgeNorthWest,
- WindowEdgeNorth,
- WindowEdgeNorthEast,
- WindowEdgeWest,
- WindowEdgeEast,
- WindowEdgeSouthWest,
- WindowEdgeSouth,
- WindowEdgeSouthEast
-};
-
-enum AvnMenuItemToggleType
-{
- None,
- CheckMark,
- Radio
-};
-
-enum AvnExtendClientAreaChromeHints
-{
- AvnNoChrome = 0,
- AvnSystemChrome = 0x01,
- AvnPreferSystemChrome = 0x02,
- AvnOSXThickTitleBar = 0x08,
- AvnDefaultChrome = AvnSystemChrome,
-};
-
-AVNCOM(IAvaloniaNativeFactory, 01) : IUnknown
-{
-public:
- virtual HRESULT Initialize(IAvnGCHandleDeallocatorCallback* deallocator) = 0;
- virtual IAvnMacOptions* GetMacOptions() = 0;
- virtual HRESULT CreateWindow(IAvnWindowEvents* cb, IAvnGlContext* gl, IAvnWindow** ppv) = 0;
- virtual HRESULT CreatePopup (IAvnWindowEvents* cb, IAvnGlContext* gl, IAvnPopup** ppv) = 0;
- virtual HRESULT CreatePlatformThreadingInterface(IAvnPlatformThreadingInterface** ppv) = 0;
- virtual HRESULT CreateSystemDialogs (IAvnSystemDialogs** ppv) = 0;
- virtual HRESULT CreateScreens (IAvnScreens** ppv) = 0;
- virtual HRESULT CreateClipboard(IAvnClipboard** ppv) = 0;
- virtual HRESULT CreateDndClipboard(IAvnClipboard** ppv) = 0;
- virtual HRESULT CreateCursorFactory(IAvnCursorFactory** ppv) = 0;
- virtual HRESULT ObtainGlDisplay(IAvnGlDisplay** ppv) = 0;
- virtual HRESULT SetAppMenu(IAvnMenu* menu) = 0;
- virtual HRESULT CreateMenu (IAvnMenuEvents* cb, IAvnMenu** ppv) = 0;
- virtual HRESULT CreateMenuItem (IAvnMenuItem** ppv) = 0;
- virtual HRESULT CreateMenuItemSeperator (IAvnMenuItem** ppv) = 0;
-};
-
-AVNCOM(IAvnString, 17) : IUnknown
-{
- virtual HRESULT Pointer(void**retOut) = 0;
- virtual HRESULT Length(int*ret) = 0;
-};
-
-AVNCOM(IAvnWindowBase, 02) : IUnknown
-{
- virtual HRESULT Show() = 0;
- virtual HRESULT Hide () = 0;
- virtual HRESULT Close() = 0;
- virtual HRESULT Activate () = 0;
- virtual HRESULT GetClientSize(AvnSize*ret) = 0;
- virtual HRESULT GetScaling(double*ret)=0;
- virtual HRESULT SetMinMaxSize(AvnSize minSize, AvnSize maxSize) = 0;
- virtual HRESULT Resize(double width, double height) = 0;
- virtual HRESULT Invalidate (AvnRect rect) = 0;
- virtual HRESULT BeginMoveDrag () = 0;
- virtual HRESULT BeginResizeDrag (AvnWindowEdge edge) = 0;
- virtual HRESULT GetPosition (AvnPoint*ret) = 0;
- virtual HRESULT SetPosition (AvnPoint point) = 0;
- virtual HRESULT PointToClient (AvnPoint point, AvnPoint*ret) = 0;
- virtual HRESULT PointToScreen (AvnPoint point, AvnPoint*ret) = 0;
- virtual HRESULT ThreadSafeSetSwRenderedFrame(AvnFramebuffer* fb, IUnknown* dispose) = 0;
- virtual HRESULT SetTopMost (bool value) = 0;
- virtual HRESULT SetCursor(IAvnCursor* cursor) = 0;
- virtual HRESULT CreateGlRenderTarget(IAvnGlSurfaceRenderTarget** ret) = 0;
- virtual HRESULT SetMainMenu(IAvnMenu* menu) = 0;
- virtual HRESULT ObtainNSWindowHandle(void** retOut) = 0;
- virtual HRESULT ObtainNSWindowHandleRetained(void** retOut) = 0;
- virtual HRESULT ObtainNSViewHandle(void** retOut) = 0;
- virtual HRESULT ObtainNSViewHandleRetained(void** retOut) = 0;
- virtual HRESULT CreateNativeControlHost(IAvnNativeControlHost** retOut) = 0;
- virtual HRESULT BeginDragAndDropOperation(AvnDragDropEffects effects, AvnPoint point,
- IAvnClipboard* clipboard, IAvnDndResultCallback* cb, void* sourceHandle) = 0;
- virtual HRESULT SetBlurEnabled (bool enable) = 0;
-};
-
-AVNCOM(IAvnPopup, 03) : virtual IAvnWindowBase
-{
-
-};
-
-AVNCOM(IAvnWindow, 04) : virtual IAvnWindowBase
-{
- virtual HRESULT SetEnabled (bool enable) = 0;
- virtual HRESULT SetParent (IAvnWindow* parent) = 0;
- virtual HRESULT SetCanResize(bool value) = 0;
- virtual HRESULT SetDecorations(SystemDecorations value) = 0;
- virtual HRESULT SetTitle (void* utf8Title) = 0;
- virtual HRESULT SetTitleBarColor (AvnColor color) = 0;
- virtual HRESULT SetWindowState(AvnWindowState state) = 0;
- virtual HRESULT GetWindowState(AvnWindowState*ret) = 0;
- virtual HRESULT TakeFocusFromChildren() = 0;
- virtual HRESULT SetExtendClientArea (bool enable) = 0;
- virtual HRESULT SetExtendClientAreaHints (AvnExtendClientAreaChromeHints hints) = 0;
- virtual HRESULT GetExtendTitleBarHeight (double*ret) = 0;
- virtual HRESULT SetExtendTitleBarHeight (double value) = 0;
-};
-
-AVNCOM(IAvnWindowBaseEvents, 05) : IUnknown
-{
- virtual HRESULT Paint() = 0;
- virtual void Closed() = 0;
- virtual void Activated() = 0;
- virtual void Deactivated() = 0;
- virtual void Resized(const AvnSize& size) = 0;
- virtual void PositionChanged (AvnPoint position) = 0;
- virtual void RawMouseEvent (AvnRawMouseEventType type,
- unsigned int timeStamp,
- AvnInputModifiers modifiers,
- AvnPoint point,
- AvnVector delta) = 0;
- virtual bool RawKeyEvent (AvnRawKeyEventType type, unsigned int timeStamp, AvnInputModifiers modifiers, unsigned int key) = 0;
- virtual bool RawTextInputEvent (unsigned int timeStamp, const char* text) = 0;
- virtual void ScalingChanged(double scaling) = 0;
- virtual void RunRenderPriorityJobs() = 0;
- virtual void LostFocus() = 0;
- virtual AvnDragDropEffects DragEvent(AvnDragEventType type, AvnPoint position,
- AvnInputModifiers modifiers, AvnDragDropEffects effects,
- IAvnClipboard* clipboard, void* dataObjectHandle) = 0;
-};
-
-
-AVNCOM(IAvnWindowEvents, 06) : IAvnWindowBaseEvents
-{
- /**
- * Closing Event
- * Called when the user presses the OS window close button.
- * return true to allow the close, return false to prevent close.
- */
- virtual bool Closing () = 0;
-
- virtual void WindowStateChanged (AvnWindowState state) = 0;
-
- virtual void GotInputWhenDisabled () = 0;
-};
-
-AVNCOM(IAvnMacOptions, 07) : IUnknown
-{
- virtual HRESULT SetShowInDock(int show) = 0;
- virtual HRESULT SetApplicationTitle (void* utf8string) = 0;
-};
-
-AVNCOM(IAvnActionCallback, 08) : IUnknown
-{
- virtual void Run() = 0;
-};
-
-AVNCOM(IAvnSignaledCallback, 09) : IUnknown
-{
- virtual void Signaled(int priority, bool priorityContainsMeaningfulValue) = 0;
-};
-
-AVNCOM(IAvnLoopCancellation, 0a) : IUnknown
-{
- virtual void Cancel() = 0;
-};
-
-AVNCOM(IAvnPlatformThreadingInterface, 0b) : IUnknown
-{
- virtual bool GetCurrentThreadIsLoopThread() = 0;
- virtual void SetSignaledCallback(IAvnSignaledCallback* cb) = 0;
- virtual IAvnLoopCancellation* CreateLoopCancellation() = 0;
- virtual HRESULT RunLoop(IAvnLoopCancellation* cancel) = 0;
- // Can't pass int* to sharpgentools for some reason
- virtual void Signal(int priority) = 0;
- virtual IUnknown* StartTimer(int priority, int ms, IAvnActionCallback* callback) = 0;
-};
-
-AVNCOM(IAvnSystemDialogEvents, 0c) : IUnknown
-{
- virtual void OnCompleted (int numResults, void* ptrFirstResult) = 0;
-};
-
-AVNCOM(IAvnSystemDialogs, 0d) : IUnknown
-{
- virtual void SelectFolderDialog (IAvnWindow* parentWindowHandle,
- IAvnSystemDialogEvents* events,
- const char* title,
- const char* initialPath) = 0;
-
- virtual void OpenFileDialog (IAvnWindow* parentWindowHandle,
- IAvnSystemDialogEvents* events,
- bool allowMultiple,
- const char* title,
- const char* initialDirectory,
- const char* initialFile,
- const char* filters) = 0;
-
- virtual void SaveFileDialog (IAvnWindow* parentWindowHandle,
- IAvnSystemDialogEvents* events,
- const char* title,
- const char* initialDirectory,
- const char* initialFile,
- const char* filters) = 0;
-};
-
-AVNCOM(IAvnScreens, 0e) : IUnknown
-{
- virtual HRESULT GetScreenCount (int* ret) = 0;
- virtual HRESULT GetScreen (int index, AvnScreen* ret) = 0;
-};
-
-AVNCOM(IAvnClipboard, 0f) : IUnknown
-{
- virtual HRESULT GetText (char* type, IAvnString**ppv) = 0;
- virtual HRESULT SetText (char* type, void* utf8Text) = 0;
- virtual HRESULT ObtainFormats(IAvnStringArray**ppv) = 0;
- virtual HRESULT GetStrings(char* type, IAvnStringArray**ppv) = 0;
- virtual HRESULT SetBytes(char* type, void* utf8Text, int len) = 0;
- virtual HRESULT GetBytes(char* type, IAvnString**ppv) = 0;
-
- virtual HRESULT Clear() = 0;
-};
-
-AVNCOM(IAvnCursor, 10) : IUnknown
-{
-};
-
-AVNCOM(IAvnCursorFactory, 11) : IUnknown
-{
- virtual HRESULT GetCursor (AvnStandardCursorType cursorType, IAvnCursor** retOut) = 0;
-};
-
-AVNCOM(IAvnGlDisplay, 13) : IUnknown
-{
- virtual HRESULT CreateContext(IAvnGlContext* share, IAvnGlContext**ppv) = 0;
- virtual void LegacyClearCurrentContext() = 0;
- virtual HRESULT WrapContext(void* native, IAvnGlContext**ppv) = 0;
- virtual void* GetProcAddress(char* proc) = 0;
-};
-
-AVNCOM(IAvnGlContext, 14) : IUnknown
-{
- virtual HRESULT MakeCurrent(IUnknown** ppv) = 0;
- virtual HRESULT LegacyMakeCurrent() = 0;
- virtual int GetSampleCount() = 0;
- virtual int GetStencilSize() = 0;
- virtual void* GetNativeHandle() = 0;
-};
-
-AVNCOM(IAvnGlSurfaceRenderTarget, 15) : IUnknown
-{
- virtual HRESULT BeginDrawing(IAvnGlSurfaceRenderingSession** ret) = 0;
-};
-
-AVNCOM(IAvnGlSurfaceRenderingSession, 16) : IUnknown
-{
- virtual HRESULT GetPixelSize(AvnPixelSize* ret) = 0;
- virtual HRESULT GetScaling(double* ret) = 0;
-};
-
-AVNCOM(IAvnMenu, 17) : IUnknown
-{
- virtual HRESULT InsertItem (int index, IAvnMenuItem* item) = 0;
- virtual HRESULT RemoveItem (IAvnMenuItem* item) = 0;
- virtual HRESULT SetTitle (void* utf8String) = 0;
- virtual HRESULT Clear () = 0;
-};
-
-AVNCOM(IAvnPredicateCallback, 18) : IUnknown
-{
- virtual bool Evaluate() = 0;
-};
-
-AVNCOM(IAvnMenuItem, 19) : IUnknown
-{
- virtual HRESULT SetSubMenu (IAvnMenu* menu) = 0;
- virtual HRESULT SetTitle (void* utf8String) = 0;
- virtual HRESULT SetGesture (void* utf8String, AvnInputModifiers modifiers) = 0;
- virtual HRESULT SetAction (IAvnPredicateCallback* predicate, IAvnActionCallback* callback) = 0;
- virtual HRESULT SetIsChecked (bool isChecked) = 0;
- virtual HRESULT SetToggleType (AvnMenuItemToggleType toggleType) = 0;
- virtual HRESULT SetIcon (void* data, size_t length) = 0;
-};
-
-AVNCOM(IAvnMenuEvents, 1A) : IUnknown
-{
- /**
- * NeedsUpdate
- */
- virtual void NeedsUpdate () = 0;
-};
-
-AVNCOM(IAvnStringArray, 20) : IUnknown
-{
- virtual unsigned int GetCount() = 0;
- virtual HRESULT Get(unsigned int index, IAvnString**ppv) = 0;
-};
-
-AVNCOM(IAvnDndResultCallback, 21) : IUnknown
-{
- virtual void OnDragAndDropComplete(AvnDragDropEffects effecct) = 0;
-};
-
-AVNCOM(IAvnGCHandleDeallocatorCallback, 22) : IUnknown
-{
- virtual void FreeGCHandle(void* handle) = 0;
-};
-
-AVNCOM(IAvnNativeControlHost, 20) : IUnknown
-{
- virtual HRESULT CreateDefaultChild(void* parent, void** retOut) = 0;
- virtual IAvnNativeControlHostTopLevelAttachment* CreateAttachment() = 0;
- virtual void DestroyDefaultChild(void* child) = 0;
-};
-
-AVNCOM(IAvnNativeControlHostTopLevelAttachment, 21) : IUnknown
-{
- virtual void* GetParentHandle() = 0;
- virtual HRESULT InitializeWithChildHandle(void* child) = 0;
- virtual HRESULT AttachTo(IAvnNativeControlHost* host) = 0;
- virtual void ShowInBounds(float x, float y, float width, float height) = 0;
- virtual void HideWithSize(float width, float height) = 0;
- virtual void ReleaseChild() = 0;
-};
-
-
-extern "C" IAvaloniaNativeFactory* CreateAvaloniaNative();
diff --git a/native/Avalonia.Native/inc/key.h b/native/Avalonia.Native/inc/key.h
deleted file mode 100644
index 12d283cc17..0000000000
--- a/native/Avalonia.Native/inc/key.h
+++ /dev/null
@@ -1,1020 +0,0 @@
-#ifndef _KEY_H_
-#define _KEY_H_
-
-///
-/// Defines the keys available on a keyboard.
-///
-enum AvnKey
-{
- ///
- /// No key pressed.
- ///
- AvnKeyNone = 0,
-
- ///
- /// The Cancel key.
- ///
- AvnKeyCancel = 1,
-
- ///
- /// The Back key.
- ///
- AvnKeyBack = 2,
-
- ///
- /// The Tab key.
- ///
- AvnKeyTab = 3,
-
- ///
- /// The Linefeed key.
- ///
- AvnKeyLineFeed = 4,
-
- ///
- /// The Clear key.
- ///
- AvnKeyClear = 5,
-
- ///
- /// The Return key.
- ///
- AvnKeyReturn = 6,
-
- ///
- /// The Enter key.
- ///
- AvnKeyEnter = 6,
-
- ///
- /// The Pause key.
- ///
- AvnKeyPause = 7,
-
- ///
- /// The Caps Lock key.
- ///
- AvnKeyCapsLock = 8,
-
- ///
- /// The Caps Lock key.
- ///
- AvnKeyCapital = 8,
-
- ///
- /// The IME Hangul mode key.
- ///
- AvnKeyHangulMode = 9,
-
- ///
- /// The IME Kana mode key.
- ///
- AvnKeyKanaMode = 9,
-
- ///
- /// The IME Junja mode key.
- ///
- AvnKeyJunjaMode = 10,
-
- ///
- /// The IME Final mode key.
- ///
- AvnKeyFinalMode = 11,
-
- ///
- /// The IME Kanji mode key.
- ///
- AvnKeyKanjiMode = 12,
-
- ///
- /// The IME Hanja mode key.
- ///
- HanjaMode = 12,
-
- ///
- /// The Escape key.
- ///
- Escape = 13,
-
- ///
- /// The IME Convert key.
- ///
- ImeConvert = 14,
-
- ///
- /// The IME NonConvert key.
- ///
- ImeNonConvert = 15,
-
- ///
- /// The IME Accept key.
- ///
- ImeAccept = 16,
-
- ///
- /// The IME Mode change key.
- ///
- ImeModeChange = 17,
-
- ///
- /// The space bar.
- ///
- Space = 18,
-
- ///
- /// The Page Up key.
- ///
- PageUp = 19,
-
- ///
- /// The Page Up key.
- ///
- Prior = 19,
-
- ///
- /// The Page Down key.
- ///
- PageDown = 20,
-
- ///
- /// The Page Down key.
- ///
- Next = 20,
-
- ///
- /// The End key.
- ///
- End = 21,
-
- ///
- /// The Home key.
- ///
- Home = 22,
-
- ///
- /// The Left arrow key.
- ///
- Left = 23,
-
- ///
- /// The Up arrow key.
- ///
- Up = 24,
-
- ///
- /// The Right arrow key.
- ///
- Right = 25,
-
- ///
- /// The Down arrow key.
- ///
- Down = 26,
-
- ///
- /// The Select key.
- ///
- Select = 27,
-
- ///
- /// The Print key.
- ///
- Print = 28,
-
- ///
- /// The Execute key.
- ///
- Execute = 29,
-
- ///
- /// The Print Screen key.
- ///
- Snapshot = 30,
-
- ///
- /// The Print Screen key.
- ///
- PrintScreen = 30,
-
- ///
- /// The Insert key.
- ///
- Insert = 31,
-
- ///
- /// The Delete key.
- ///
- Delete = 32,
-
- ///
- /// The Help key.
- ///
- Help = 33,
-
- ///
- /// The 0 key.
- ///
- D0 = 34,
-
- ///
- /// The 1 key.
- ///
- D1 = 35,
-
- ///
- /// The 2 key.
- ///
- D2 = 36,
-
- ///
- /// The 3 key.
- ///
- D3 = 37,
-
- ///
- /// The 4 key.
- ///
- D4 = 38,
-
- ///
- /// The 5 key.
- ///
- D5 = 39,
-
- ///
- /// The 6 key.
- ///
- D6 = 40,
-
- ///
- /// The 7 key.
- ///
- D7 = 41,
-
- ///
- /// The 8 key.
- ///
- D8 = 42,
-
- ///
- /// The 9 key.
- ///
- D9 = 43,
-
- ///
- /// The A key.
- ///
- A = 44,
-
- ///
- /// The B key.
- ///
- B = 45,
-
- ///
- /// The C key.
- ///
- C = 46,
-
- ///
- /// The D key.
- ///
- D = 47,
-
- ///
- /// The E key.
- ///
- E = 48,
-
- ///
- /// The F key.
- ///
- F = 49,
-
- ///
- /// The G key.
- ///
- G = 50,
-
- ///
- /// The H key.
- ///
- H = 51,
-
- ///
- /// The I key.
- ///
- I = 52,
-
- ///
- /// The J key.
- ///
- J = 53,
-
- ///
- /// The K key.
- ///
- AvnKeyK = 54,
-
- ///
- /// The L key.
- ///
- L = 55,
-
- ///
- /// The M key.
- ///
- M = 56,
-
- ///
- /// The N key.
- ///
- N = 57,
-
- ///
- /// The O key.
- ///
- O = 58,
-
- ///
- /// The P key.
- ///
- P = 59,
-
- ///
- /// The Q key.
- ///
- Q = 60,
-
- ///
- /// The R key.
- ///
- R = 61,
-
- ///
- /// The S key.
- ///
- S = 62,
-
- ///
- /// The T key.
- ///
- T = 63,
-
- ///
- /// The U key.
- ///
- U = 64,
-
- ///
- /// The V key.
- ///
- V = 65,
-
- ///
- /// The W key.
- ///
- W = 66,
-
- ///
- /// The X key.
- ///
- X = 67,
-
- ///
- /// The Y key.
- ///
- Y = 68,
-
- ///
- /// The Z key.
- ///
- Z = 69,
-
- ///
- /// The left Windows key.
- ///
- LWin = 70,
-
- ///
- /// The right Windows key.
- ///
- RWin = 71,
-
- ///
- /// The Application key.
- ///
- Apps = 72,
-
- ///
- /// The Sleep key.
- ///
- Sleep = 73,
-
- ///
- /// The 0 key on the numeric keypad.
- ///
- NumPad0 = 74,
-
- ///
- /// The 1 key on the numeric keypad.
- ///
- NumPad1 = 75,
-
- ///
- /// The 2 key on the numeric keypad.
- ///
- NumPad2 = 76,
-
- ///
- /// The 3 key on the numeric keypad.
- ///
- NumPad3 = 77,
-
- ///
- /// The 4 key on the numeric keypad.
- ///
- NumPad4 = 78,
-
- ///
- /// The 5 key on the numeric keypad.
- ///
- NumPad5 = 79,
-
- ///
- /// The 6 key on the numeric keypad.
- ///
- NumPad6 = 80,
-
- ///
- /// The 7 key on the numeric keypad.
- ///
- NumPad7 = 81,
-
- ///
- /// The 8 key on the numeric keypad.
- ///
- NumPad8 = 82,
-
- ///
- /// The 9 key on the numeric keypad.
- ///
- NumPad9 = 83,
-
- ///
- /// The Multiply key.
- ///
- Multiply = 84,
-
- ///
- /// The Add key.
- ///
- Add = 85,
-
- ///
- /// The Separator key.
- ///
- Separator = 86,
-
- ///
- /// The Subtract key.
- ///
- Subtract = 87,
-
- ///
- /// The Decimal key.
- ///
- Decimal = 88,
-
- ///
- /// The Divide key.
- ///
- Divide = 89,
-
- ///
- /// The F1 key.
- ///
- F1 = 90,
-
- ///
- /// The F2 key.
- ///
- F2 = 91,
-
- ///
- /// The F3 key.
- ///
- F3 = 92,
-
- ///
- /// The F4 key.
- ///
- F4 = 93,
-
- ///
- /// The F5 key.
- ///
- F5 = 94,
-
- ///
- /// The F6 key.
- ///
- F6 = 95,
-
- ///
- /// The F7 key.
- ///
- F7 = 96,
-
- ///
- /// The F8 key.
- ///
- F8 = 97,
-
- ///
- /// The F9 key.
- ///
- F9 = 98,
-
- ///
- /// The F10 key.
- ///
- F10 = 99,
-
- ///
- /// The F11 key.
- ///
- F11 = 100,
-
- ///
- /// The F12 key.
- ///
- F12 = 101,
-
- ///
- /// The F13 key.
- ///
- F13 = 102,
-
- ///
- /// The F14 key.
- ///
- F14 = 103,
-
- ///
- /// The F15 key.
- ///
- F15 = 104,
-
- ///
- /// The F16 key.
- ///
- F16 = 105,
-
- ///
- /// The F17 key.
- ///
- F17 = 106,
-
- ///
- /// The F18 key.
- ///
- F18 = 107,
-
- ///
- /// The F19 key.
- ///
- F19 = 108,
-
- ///
- /// The F20 key.
- ///
- F20 = 109,
-
- ///
- /// The F21 key.
- ///
- F21 = 110,
-
- ///
- /// The F22 key.
- ///
- F22 = 111,
-
- ///
- /// The F23 key.
- ///
- F23 = 112,
-
- ///
- /// The F24 key.
- ///
- F24 = 113,
-
- ///
- /// The Numlock key.
- ///
- NumLock = 114,
-
- ///
- /// The Scroll key.
- ///
- Scroll = 115,
-
- ///
- /// The left Shift key.
- ///
- LeftShift = 116,
-
- ///
- /// The right Shift key.
- ///
- RightShift = 117,
-
- ///
- /// The left Ctrl key.
- ///
- LeftCtrl = 118,
-
- ///
- /// The right Ctrl key.
- ///
- RightCtrl = 119,
-
- ///
- /// The left Alt key.
- ///
- LeftAlt = 120,
-
- ///
- /// The right Alt key.
- ///
- RightAlt = 121,
-
- ///
- /// The browser Back key.
- ///
- BrowserBack = 122,
-
- ///
- /// The browser Forward key.
- ///
- BrowserForward = 123,
-
- ///
- /// The browser Refresh key.
- ///
- BrowserRefresh = 124,
-
- ///
- /// The browser Stop key.
- ///
- BrowserStop = 125,
-
- ///
- /// The browser Search key.
- ///
- BrowserSearch = 126,
-
- ///
- /// The browser Favorites key.
- ///
- BrowserFavorites = 127,
-
- ///
- /// The browser Home key.
- ///
- BrowserHome = 128,
-
- ///
- /// The Volume Mute key.
- ///
- VolumeMute = 129,
-
- ///
- /// The Volume Down key.
- ///
- VolumeDown = 130,
-
- ///
- /// The Volume Up key.
- ///
- VolumeUp = 131,
-
- ///
- /// The media Next Track key.
- ///
- MediaNextTrack = 132,
-
- ///
- /// The media Previous Track key.
- ///
- MediaPreviousTrack = 133,
-
- ///
- /// The media Stop key.
- ///
- MediaStop = 134,
-
- ///
- /// The media Play/Pause key.
- ///
- MediaPlayPause = 135,
-
- ///
- /// The Launch Mail key.
- ///
- LaunchMail = 136,
-
- ///
- /// The Select Media key.
- ///
- SelectMedia = 137,
-
- ///
- /// The Launch Application 1 key.
- ///
- LaunchApplication1 = 138,
-
- ///
- /// The Launch Application 2 key.
- ///
- LaunchApplication2 = 139,
-
- ///
- /// The OEM Semicolon key.
- ///
- OemSemicolon = 140,
-
- ///
- /// The OEM 1 key.
- ///
- Oem1 = 140,
-
- ///
- /// The OEM Plus key.
- ///
- OemPlus = 141,
-
- ///
- /// The OEM Comma key.
- ///
- OemComma = 142,
-
- ///
- /// The OEM Minus key.
- ///
- OemMinus = 143,
-
- ///
- /// The OEM Period key.
- ///
- OemPeriod = 144,
-
- ///
- /// The OEM Question Mark key.
- ///
- OemQuestion = 145,
-
- ///
- /// The OEM 2 key.
- ///
- Oem2 = 145,
-
- ///
- /// The OEM Tilde key.
- ///
- OemTilde = 146,
-
- ///
- /// The OEM 3 key.
- ///
- Oem3 = 146,
-
- ///
- /// The ABNT_C1 (Brazilian) key.
- ///
- AbntC1 = 147,
-
- ///
- /// The ABNT_C2 (Brazilian) key.
- ///
- AbntC2 = 148,
-
- ///
- /// The OEM Open Brackets key.
- ///
- OemOpenBrackets = 149,
-
- ///
- /// The OEM 4 key.
- ///
- Oem4 = 149,
-
- ///
- /// The OEM Pipe key.
- ///
- OemPipe = 150,
-
- ///
- /// The OEM 5 key.
- ///
- Oem5 = 150,
-
- ///
- /// The OEM Close Brackets key.
- ///
- OemCloseBrackets = 151,
-
- ///
- /// The OEM 6 key.
- ///
- Oem6 = 151,
-
- ///
- /// The OEM Quotes key.
- ///
- OemQuotes = 152,
-
- ///
- /// The OEM 7 key.
- ///
- Oem7 = 152,
-
- ///
- /// The OEM 8 key.
- ///
- Oem8 = 153,
-
- ///
- /// The OEM Backslash key.
- ///
- OemBackslash = 154,
-
- ///
- /// The OEM 3 key.
- ///
- Oem102 = 154,
-
- ///
- /// A special key masking the real key being processed by an IME.
- ///
- ImeProcessed = 155,
-
- ///
- /// A special key masking the real key being processed as a system key.
- ///
- System = 156,
-
- ///
- /// The OEM ATTN key.
- ///
- OemAttn = 157,
-
- ///
- /// The DBE_ALPHANUMERIC key.
- ///
- DbeAlphanumeric = 157,
-
- ///
- /// The OEM Finish key.
- ///
- OemFinish = 158,
-
- ///
- /// The DBE_KATAKANA key.
- ///
- DbeKatakana = 158,
-
- ///
- /// The DBE_HIRAGANA key.
- ///
- DbeHiragana = 159,
-
- ///
- /// The OEM Copy key.
- ///
- OemCopy = 159,
-
- ///
- /// The DBE_SBCSCHAR key.
- ///
- DbeSbcsChar = 160,
-
- ///
- /// The OEM Auto key.
- ///
- OemAuto = 160,
-
- ///
- /// The DBE_DBCSCHAR key.
- ///
- DbeDbcsChar = 161,
-
- ///
- /// The OEM ENLW key.
- ///
- OemEnlw = 161,
-
- ///
- /// The OEM BackTab key.
- ///
- OemBackTab = 162,
-
- ///
- /// The DBE_ROMAN key.
- ///
- DbeRoman = 162,
-
- ///
- /// The DBE_NOROMAN key.
- ///
- DbeNoRoman = 163,
-
- ///
- /// The ATTN key.
- ///
- Attn = 163,
-
- ///
- /// The CRSEL key.
- ///
- CrSel = 164,
-
- ///
- /// The DBE_ENTERWORDREGISTERMODE key.
- ///
- DbeEnterWordRegisterMode = 164,
-
- ///
- /// The EXSEL key.
- ///
- ExSel = 165,
-
- ///
- /// The DBE_ENTERIMECONFIGMODE key.
- ///
- DbeEnterImeConfigureMode = 165,
-
- ///
- /// The ERASE EOF Key.
- ///
- EraseEof = 166,
-
- ///
- /// The DBE_FLUSHSTRING key.
- ///
- DbeFlushString = 166,
-
- ///
- /// The Play key.
- ///
- Play = 167,
-
- ///
- /// The DBE_CODEINPUT key.
- ///
- DbeCodeInput = 167,
-
- ///
- /// The DBE_NOCODEINPUT key.
- ///
- DbeNoCodeInput = 168,
-
- ///
- /// The Zoom key.
- ///
- Zoom = 168,
-
- ///
- /// Reserved for future use.
- ///
- NoName = 169,
-
- ///
- /// The DBE_DETERMINESTRING key.
- ///
- DbeDetermineString = 169,
-
- ///
- /// The DBE_ENTERDLGCONVERSIONMODE key.
- ///
- DbeEnterDialogConversionMode = 170,
-
- ///
- /// The PA1 key.
- ///
- Pa1 = 170,
-
- ///
- /// The OEM Clear key.
- ///
- OemClear = 171,
-
- ///
- /// The key is used with another key to create a single combined character.
- ///
- DeadCharProcessed = 172,
-};
-
-#endif
diff --git a/native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj b/native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj
index d5cad4d1ca..dba3ee6d31 100644
--- a/native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj
+++ b/native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj
@@ -8,19 +8,20 @@
/* Begin PBXBuildFile section */
1A002B9E232135EE00021753 /* app.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1A002B9D232135EE00021753 /* app.mm */; };
+ 1A1852DC23E05814008F0DED /* deadlock.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1A1852DB23E05814008F0DED /* deadlock.mm */; };
1A3E5EA823E9E83B00EDE661 /* rendertarget.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1A3E5EA723E9E83B00EDE661 /* rendertarget.mm */; };
1A3E5EAA23E9F26C00EDE661 /* IOSurface.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A3E5EA923E9F26C00EDE661 /* IOSurface.framework */; };
- 1A1852DC23E05814008F0DED /* deadlock.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1A1852DB23E05814008F0DED /* deadlock.mm */; };
- 1AFD334123E03C4F0042899B /* controlhost.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1AFD334023E03C4F0042899B /* controlhost.mm */; };
1A3E5EAE23E9FB1300EDE661 /* cgl.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1A3E5EAD23E9FB1300EDE661 /* cgl.mm */; };
1A3E5EB023E9FE8300EDE661 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A3E5EAF23E9FE8300EDE661 /* QuartzCore.framework */; };
1A465D10246AB61600C5858B /* dnd.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1A465D0F246AB61600C5858B /* dnd.mm */; };
+ 1AFD334123E03C4F0042899B /* controlhost.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1AFD334023E03C4F0042899B /* controlhost.mm */; };
37155CE4233C00EB0034DCE9 /* menu.h in Headers */ = {isa = PBXBuildFile; fileRef = 37155CE3233C00EB0034DCE9 /* menu.h */; };
37A517B32159597E00FBA241 /* Screens.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37A517B22159597E00FBA241 /* Screens.mm */; };
37C09D8821580FE4006A6758 /* SystemDialogs.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37C09D8721580FE4006A6758 /* SystemDialogs.mm */; };
37DDA9B0219330F8002E132B /* AvnString.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37DDA9AF219330F8002E132B /* AvnString.mm */; };
37E2330F21583241000CB7E2 /* KeyTransform.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37E2330E21583241000CB7E2 /* KeyTransform.mm */; };
520624B322973F4100C4DCEF /* menu.mm in Sources */ = {isa = PBXBuildFile; fileRef = 520624B222973F4100C4DCEF /* menu.mm */; };
+ 522D5959258159C1006F7F7A /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 522D5958258159C1006F7F7A /* Carbon.framework */; };
5B21A982216530F500CEE36E /* cursor.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5B21A981216530F500CEE36E /* cursor.mm */; };
5B8BD94F215BFEA6005ED2A7 /* clipboard.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5B8BD94E215BFEA6005ED2A7 /* clipboard.mm */; };
AB00E4F72147CA920032A60A /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB00E4F62147CA920032A60A /* main.mm */; };
@@ -32,13 +33,13 @@
/* Begin PBXFileReference section */
1A002B9D232135EE00021753 /* app.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = app.mm; sourceTree = ""; };
+ 1A1852DB23E05814008F0DED /* deadlock.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = deadlock.mm; sourceTree = ""; };
1A3E5EA723E9E83B00EDE661 /* rendertarget.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = rendertarget.mm; sourceTree = ""; };
1A3E5EA923E9F26C00EDE661 /* IOSurface.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOSurface.framework; path = System/Library/Frameworks/IOSurface.framework; sourceTree = SDKROOT; };
- 1A1852DB23E05814008F0DED /* deadlock.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = deadlock.mm; sourceTree = ""; };
- 1AFD334023E03C4F0042899B /* controlhost.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = controlhost.mm; sourceTree = ""; };
1A3E5EAD23E9FB1300EDE661 /* cgl.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = cgl.mm; sourceTree = ""; };
1A3E5EAF23E9FE8300EDE661 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
1A465D0F246AB61600C5858B /* dnd.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = dnd.mm; sourceTree = ""; };
+ 1AFD334023E03C4F0042899B /* controlhost.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = controlhost.mm; sourceTree = ""; };
37155CE3233C00EB0034DCE9 /* menu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = menu.h; sourceTree = ""; };
379860FE214DA0C000CD0246 /* KeyTransform.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KeyTransform.h; sourceTree = ""; };
37A4E71A2178846A00EACBCD /* headers */ = {isa = PBXFileReference; lastKnownFileType = folder; name = headers; path = ../../inc; sourceTree = ""; };
@@ -49,6 +50,7 @@
37DDA9B121933371002E132B /* AvnString.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AvnString.h; sourceTree = ""; };
37E2330E21583241000CB7E2 /* KeyTransform.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = KeyTransform.mm; sourceTree = ""; };
520624B222973F4100C4DCEF /* menu.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = menu.mm; sourceTree = ""; };
+ 522D5958258159C1006F7F7A /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = System/Library/Frameworks/Carbon.framework; sourceTree = SDKROOT; };
5B21A981216530F500CEE36E /* cursor.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = cursor.mm; sourceTree = ""; };
5B8BD94E215BFEA6005ED2A7 /* clipboard.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = clipboard.mm; sourceTree = ""; };
5BF943652167AD1D009CAE35 /* cursor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = cursor.h; sourceTree = ""; };
@@ -69,6 +71,7 @@
1A3E5EB023E9FE8300EDE661 /* QuartzCore.framework in Frameworks */,
1A3E5EAA23E9F26C00EDE661 /* IOSurface.framework in Frameworks */,
AB1E522C217613570091CD71 /* OpenGL.framework in Frameworks */,
+ 522D5959258159C1006F7F7A /* Carbon.framework in Frameworks */,
AB661C1E2148230F00291242 /* AppKit.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -79,6 +82,7 @@
AB661C1C2148230E00291242 /* Frameworks */ = {
isa = PBXGroup;
children = (
+ 522D5958258159C1006F7F7A /* Carbon.framework */,
1A3E5EAF23E9FE8300EDE661 /* QuartzCore.framework */,
1A3E5EA923E9F26C00EDE661 /* IOSurface.framework */,
AB1E522B217613570091CD71 /* OpenGL.framework */,
diff --git a/native/Avalonia.Native/src/OSX/KeyTransform.h b/native/Avalonia.Native/src/OSX/KeyTransform.h
index ea4fbecd5c..2f434570c9 100644
--- a/native/Avalonia.Native/src/OSX/KeyTransform.h
+++ b/native/Avalonia.Native/src/OSX/KeyTransform.h
@@ -1,9 +1,14 @@
#ifndef keytransform_h
#define keytransform_h
#include "common.h"
-#include "key.h"
#include
+
+
+
+
diff --git a/packages/Avalonia/Avalonia.csproj b/packages/Avalonia/Avalonia.csproj
index cd3ce9adcd..75ee4a05cb 100644
--- a/packages/Avalonia/Avalonia.csproj
+++ b/packages/Avalonia/Avalonia.csproj
@@ -5,9 +5,8 @@
-
+
-
@@ -15,9 +14,7 @@
-
+
<_PackageFiles Include="$(DesignerHostAppPath)/Avalonia.Designer.HostApp/bin/$(Configuration)/netcoreapp2.0/Avalonia.Designer.HostApp.dll">
diff --git a/packages/Avalonia/AvaloniaBuildTasks.targets b/packages/Avalonia/AvaloniaBuildTasks.targets
index 84a62bb5c0..45a7f1aa44 100644
--- a/packages/Avalonia/AvaloniaBuildTasks.targets
+++ b/packages/Avalonia/AvaloniaBuildTasks.targets
@@ -3,6 +3,8 @@
<_AvaloniaUseExternalMSBuild>$(AvaloniaUseExternalMSBuild)
<_AvaloniaUseExternalMSBuild Condition="'$(_AvaloniaForceInternalMSBuild)' == 'true'">false
low
+ <_AvaloniaPatchComInterop Condition="'$(_AvaloniaPatchComInterop)' == ''">false
+ <_AvaloniaSkipXamlCompilation Condition="'$(_AvaloniaSkipXamlCompilation)' == ''">false
@@ -87,6 +89,11 @@
ProjectDirectory="$(MSBuildProjectDirectory)"
VerifyIl="$(AvaloniaXamlIlVerifyIl)"
ReportImportance="$(AvaloniaXamlReportImportance)"
+ AssemblyOriginatorKeyFile="$(AssemblyOriginatorKeyFile)"
+ SignAssembly="$(SignAssembly)"
+ DelaySign="$(DelaySign)"
+ EnableComInteropPatching="$(_AvaloniaPatchComInterop)"
+ SkipXamlCompilation="$(_AvaloniaSkipXamlCompilation)"
/>
()
- .UsePlatformDetect()
- .UseReactiveUI()
- .LogToDebug()
- .Start();
+ if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
+ desktop.MainWindow = new MainWindow();
+ base.OnFrameworkInitializationCompleted();
}
+
+ public static int Main(string[] args)
+ => BuildAvaloniaApp().StartWithClassicDesktopLifetime(args);
+
+ public static AppBuilder BuildAvaloniaApp()
+ => AppBuilder.Configure()
+ .UsePlatformDetect()
+ .LogToTrace();
}
}
diff --git a/samples/BindingDemo/BindingDemo.csproj b/samples/BindingDemo/BindingDemo.csproj
index 817023fd71..d898b737a9 100644
--- a/samples/BindingDemo/BindingDemo.csproj
+++ b/samples/BindingDemo/BindingDemo.csproj
@@ -6,12 +6,11 @@
-
+
-
diff --git a/samples/BindingDemo/ViewModels/ExceptionErrorViewModel.cs b/samples/BindingDemo/ViewModels/ExceptionErrorViewModel.cs
index 0fe12a8ef7..7de083351e 100644
--- a/samples/BindingDemo/ViewModels/ExceptionErrorViewModel.cs
+++ b/samples/BindingDemo/ViewModels/ExceptionErrorViewModel.cs
@@ -1,9 +1,9 @@
-using ReactiveUI;
+using MiniMvvm;
using System;
namespace BindingDemo.ViewModels
{
- public class ExceptionErrorViewModel : ReactiveObject
+ public class ExceptionErrorViewModel : ViewModelBase
{
private int _lessThan10;
diff --git a/samples/BindingDemo/ViewModels/IndeiErrorViewModel.cs b/samples/BindingDemo/ViewModels/IndeiErrorViewModel.cs
index caf75c846c..9ae8d9558f 100644
--- a/samples/BindingDemo/ViewModels/IndeiErrorViewModel.cs
+++ b/samples/BindingDemo/ViewModels/IndeiErrorViewModel.cs
@@ -1,11 +1,11 @@
-using ReactiveUI;
+using MiniMvvm;
using System;
using System.ComponentModel;
using System.Collections;
namespace BindingDemo.ViewModels
{
- public class IndeiErrorViewModel : ReactiveObject, INotifyDataErrorInfo
+ public class IndeiErrorViewModel : ViewModelBase, INotifyDataErrorInfo
{
private int _maximum = 10;
private int _value;
diff --git a/samples/BindingDemo/ViewModels/MainWindowViewModel.cs b/samples/BindingDemo/ViewModels/MainWindowViewModel.cs
index f0241cad48..18a7a01a69 100644
--- a/samples/BindingDemo/ViewModels/MainWindowViewModel.cs
+++ b/samples/BindingDemo/ViewModels/MainWindowViewModel.cs
@@ -5,14 +5,14 @@ using System.Reactive;
using System.Reactive.Linq;
using System.Threading.Tasks;
using System.Threading;
-using ReactiveUI;
+using MiniMvvm;
using Avalonia.Controls;
using Avalonia.Metadata;
using Avalonia.Controls.Selection;
namespace BindingDemo.ViewModels
{
- public class MainWindowViewModel : ReactiveObject
+ public class MainWindowViewModel : ViewModelBase
{
private string _booleanString = "True";
private double _doubleValue = 5.0;
@@ -32,13 +32,13 @@ namespace BindingDemo.ViewModels
Selection = new SelectionModel { SingleSelect = false };
- ShuffleItems = ReactiveCommand.Create(() =>
+ ShuffleItems = MiniCommand.Create(() =>
{
var r = new Random();
Items.Move(r.Next(Items.Count), 1);
});
- StringValueCommand = ReactiveCommand.Create
diff --git a/samples/Previewer/Program.cs b/samples/Previewer/Program.cs
index 48363e27f2..b12b93974a 100644
--- a/samples/Previewer/Program.cs
+++ b/samples/Previewer/Program.cs
@@ -1,13 +1,14 @@
-using System;
-using Avalonia;
+using Avalonia;
namespace Previewer
{
class Program
{
- static void Main(string[] args)
- {
- AppBuilder.Configure().UsePlatformDetect().Start();
- }
+ public static AppBuilder BuildAvaloniaApp()
+ => AppBuilder.Configure()
+ .UsePlatformDetect();
+
+ public static int Main(string[] args)
+ => BuildAvaloniaApp().StartWithClassicDesktopLifetime(args);
}
-}
\ No newline at end of file
+}
diff --git a/samples/RenderDemo/App.xaml b/samples/RenderDemo/App.xaml
index 61e4d2385b..7cdcea2e1d 100644
--- a/samples/RenderDemo/App.xaml
+++ b/samples/RenderDemo/App.xaml
@@ -3,7 +3,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="RenderDemo.App">
-
+
diff --git a/samples/RenderDemo/App.xaml.cs b/samples/RenderDemo/App.xaml.cs
index 233160b025..8054b06964 100644
--- a/samples/RenderDemo/App.xaml.cs
+++ b/samples/RenderDemo/App.xaml.cs
@@ -1,6 +1,6 @@
using Avalonia;
+using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
-using Avalonia.ReactiveUI;
namespace RenderDemo
{
@@ -11,15 +11,26 @@ namespace RenderDemo
AvaloniaXamlLoader.Load(this);
}
+ public override void OnFrameworkInitializationCompleted()
+ {
+ if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
+ desktop.MainWindow = new MainWindow();
+ base.OnFrameworkInitializationCompleted();
+ }
+
// TODO: Make this work with GTK/Skia/Cairo depending on command-line args
// again.
- static void Main(string[] args) => BuildAvaloniaApp().Start();
+ static void Main(string[] args)
+ => BuildAvaloniaApp().StartWithClassicDesktopLifetime(args);
// App configuration, used by the entry point and previewer
static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure()
+ .With(new Win32PlatformOptions
+ {
+ OverlayPopups = true,
+ })
.UsePlatformDetect()
- .UseReactiveUI()
- .LogToDebug();
+ .LogToTrace();
}
}
diff --git a/samples/RenderDemo/MainWindow.xaml.cs b/samples/RenderDemo/MainWindow.xaml.cs
index b45a605e04..877eb8016a 100644
--- a/samples/RenderDemo/MainWindow.xaml.cs
+++ b/samples/RenderDemo/MainWindow.xaml.cs
@@ -3,7 +3,7 @@ using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using RenderDemo.ViewModels;
-using ReactiveUI;
+using MiniMvvm;
namespace RenderDemo
{
diff --git a/samples/RenderDemo/Pages/GlyphRunPage.xaml b/samples/RenderDemo/Pages/GlyphRunPage.xaml
index fb3e318a0e..c2914e8847 100644
--- a/samples/RenderDemo/Pages/GlyphRunPage.xaml
+++ b/samples/RenderDemo/Pages/GlyphRunPage.xaml
@@ -6,9 +6,9 @@
x:Class="RenderDemo.Pages.GlyphRunPage">
-
-
+
diff --git a/samples/RenderDemo/Pages/GlyphRunPage.xaml.cs b/samples/RenderDemo/Pages/GlyphRunPage.xaml.cs
index ddee880288..857358f6b2 100644
--- a/samples/RenderDemo/Pages/GlyphRunPage.xaml.cs
+++ b/samples/RenderDemo/Pages/GlyphRunPage.xaml.cs
@@ -9,7 +9,7 @@ namespace RenderDemo.Pages
{
public class GlyphRunPage : UserControl
{
- private DrawingPresenter _drawingPresenter;
+ private Image _imageControl;
private GlyphTypeface _glyphTypeface = Typeface.Default.GlyphTypeface;
private readonly Random _rand = new Random();
private ushort[] _glyphIndices = new ushort[1];
@@ -25,7 +25,8 @@ namespace RenderDemo.Pages
{
AvaloniaXamlLoader.Load(this);
- _drawingPresenter = this.FindControl("drawingPresenter");
+ _imageControl = this.FindControl("imageControl");
+ _imageControl.Source = new DrawingImage();
DispatcherTimer.Run(() =>
{
@@ -73,7 +74,7 @@ namespace RenderDemo.Pages
drawingGroup.Children.Add(geometryDrawing);
- _drawingPresenter.Drawing = drawingGroup;
+ (_imageControl.Source as DrawingImage).Drawing = drawingGroup;
}
}
}
diff --git a/samples/RenderDemo/RenderDemo.csproj b/samples/RenderDemo/RenderDemo.csproj
index d1654f4b54..0d33b4c111 100644
--- a/samples/RenderDemo/RenderDemo.csproj
+++ b/samples/RenderDemo/RenderDemo.csproj
@@ -9,12 +9,11 @@
-
+
-
diff --git a/samples/RenderDemo/ViewModels/AnimationsPageViewModel.cs b/samples/RenderDemo/ViewModels/AnimationsPageViewModel.cs
index 7b89b7944c..f8ba01f3d1 100644
--- a/samples/RenderDemo/ViewModels/AnimationsPageViewModel.cs
+++ b/samples/RenderDemo/ViewModels/AnimationsPageViewModel.cs
@@ -1,10 +1,10 @@
using System;
-using ReactiveUI;
+using MiniMvvm;
using Avalonia.Animation;
namespace RenderDemo.ViewModels
{
- public class AnimationsPageViewModel : ReactiveObject
+ public class AnimationsPageViewModel : ViewModelBase
{
private bool _isPlaying = true;
diff --git a/samples/RenderDemo/ViewModels/MainWindowViewModel.cs b/samples/RenderDemo/ViewModels/MainWindowViewModel.cs
index eda5e80530..19917c20df 100644
--- a/samples/RenderDemo/ViewModels/MainWindowViewModel.cs
+++ b/samples/RenderDemo/ViewModels/MainWindowViewModel.cs
@@ -1,11 +1,10 @@
using System.Reactive;
using System.Threading.Tasks;
-
-using ReactiveUI;
+using MiniMvvm;
namespace RenderDemo.ViewModels
{
- public class MainWindowViewModel : ReactiveObject
+ public class MainWindowViewModel : ViewModelBase
{
private bool drawDirtyRects = false;
private bool drawFps = true;
@@ -14,9 +13,9 @@ namespace RenderDemo.ViewModels
public MainWindowViewModel()
{
- ToggleDrawDirtyRects = ReactiveCommand.Create(() => DrawDirtyRects = !DrawDirtyRects);
- ToggleDrawFps = ReactiveCommand.Create(() => DrawFps = !DrawFps);
- ResizeWindow = ReactiveCommand.CreateFromTask(ResizeWindowAsync);
+ ToggleDrawDirtyRects = MiniCommand.Create(() => DrawDirtyRects = !DrawDirtyRects);
+ ToggleDrawFps = MiniCommand.Create(() => DrawFps = !DrawFps);
+ ResizeWindow = MiniCommand.CreateFromTask(ResizeWindowAsync);
}
public bool DrawDirtyRects
@@ -43,9 +42,9 @@ namespace RenderDemo.ViewModels
set => this.RaiseAndSetIfChanged(ref height, value);
}
- public ReactiveCommand ToggleDrawDirtyRects { get; }
- public ReactiveCommand ToggleDrawFps { get; }
- public ReactiveCommand ResizeWindow { get; }
+ public MiniCommand ToggleDrawDirtyRects { get; }
+ public MiniCommand ToggleDrawFps { get; }
+ public MiniCommand ResizeWindow { get; }
private async Task ResizeWindowAsync()
{
diff --git a/samples/Sandbox/App.axaml b/samples/Sandbox/App.axaml
index 699781eb94..f601f9f78f 100644
--- a/samples/Sandbox/App.axaml
+++ b/samples/Sandbox/App.axaml
@@ -3,6 +3,6 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Sandbox.App">
-
+
diff --git a/samples/Sandbox/MainWindow.axaml.cs b/samples/Sandbox/MainWindow.axaml.cs
index b7222e043d..3d54036d29 100644
--- a/samples/Sandbox/MainWindow.axaml.cs
+++ b/samples/Sandbox/MainWindow.axaml.cs
@@ -1,6 +1,7 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
+using Avalonia.Win32.WinRT.Composition;
namespace Sandbox
{
diff --git a/samples/Sandbox/Program.cs b/samples/Sandbox/Program.cs
index 4d7eda8d9f..1e74105196 100644
--- a/samples/Sandbox/Program.cs
+++ b/samples/Sandbox/Program.cs
@@ -1,5 +1,4 @@
using Avalonia;
-using Avalonia.ReactiveUI;
namespace Sandbox
{
@@ -9,8 +8,7 @@ namespace Sandbox
{
AppBuilder.Configure()
.UsePlatformDetect()
- .UseReactiveUI()
- .LogToDebug()
+ .LogToTrace()
.StartWithClassicDesktopLifetime(args);
}
}
diff --git a/samples/Sandbox/Sandbox.csproj b/samples/Sandbox/Sandbox.csproj
index 1a0a8a7ce5..0c19440a1e 100644
--- a/samples/Sandbox/Sandbox.csproj
+++ b/samples/Sandbox/Sandbox.csproj
@@ -8,7 +8,6 @@
-
diff --git a/samples/VirtualizationDemo/App.xaml.cs b/samples/VirtualizationDemo/App.xaml.cs
index 5990dd282c..81b80c1f40 100644
--- a/samples/VirtualizationDemo/App.xaml.cs
+++ b/samples/VirtualizationDemo/App.xaml.cs
@@ -1,4 +1,5 @@
using Avalonia;
+using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
namespace VirtualizationDemo
@@ -9,5 +10,12 @@ namespace VirtualizationDemo
{
AvaloniaXamlLoader.Load(this);
}
+
+ public override void OnFrameworkInitializationCompleted()
+ {
+ if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
+ desktop.MainWindow = new MainWindow();
+ base.OnFrameworkInitializationCompleted();
+ }
}
}
diff --git a/samples/VirtualizationDemo/Program.cs b/samples/VirtualizationDemo/Program.cs
index 93ea5e1b88..febda46450 100644
--- a/samples/VirtualizationDemo/Program.cs
+++ b/samples/VirtualizationDemo/Program.cs
@@ -1,19 +1,15 @@
-using System;
-using Avalonia;
-using Avalonia.Controls;
-using Avalonia.ReactiveUI;
+using Avalonia;
namespace VirtualizationDemo
{
class Program
{
- static void Main(string[] args)
- {
- AppBuilder.Configure()
- .UsePlatformDetect()
- .UseReactiveUI()
- .LogToDebug()
- .Start();
- }
+ public static AppBuilder BuildAvaloniaApp()
+ => AppBuilder.Configure()
+ .UsePlatformDetect()
+ .LogToTrace();
+
+ public static int Main(string[] args)
+ => BuildAvaloniaApp().StartWithClassicDesktopLifetime(args);
}
}
diff --git a/samples/VirtualizationDemo/ViewModels/ItemViewModel.cs b/samples/VirtualizationDemo/ViewModels/ItemViewModel.cs
index cf34980b40..9ba505ffe5 100644
--- a/samples/VirtualizationDemo/ViewModels/ItemViewModel.cs
+++ b/samples/VirtualizationDemo/ViewModels/ItemViewModel.cs
@@ -1,9 +1,9 @@
using System;
-using ReactiveUI;
+using MiniMvvm;
namespace VirtualizationDemo.ViewModels
{
- internal class ItemViewModel : ReactiveObject
+ internal class ItemViewModel : ViewModelBase
{
private string _prefix;
private int _index;
diff --git a/samples/VirtualizationDemo/ViewModels/MainWindowViewModel.cs b/samples/VirtualizationDemo/ViewModels/MainWindowViewModel.cs
index 852c01399f..514df691ae 100644
--- a/samples/VirtualizationDemo/ViewModels/MainWindowViewModel.cs
+++ b/samples/VirtualizationDemo/ViewModels/MainWindowViewModel.cs
@@ -5,13 +5,13 @@ using System.Reactive;
using Avalonia.Collections;
using Avalonia.Controls;
using Avalonia.Controls.Primitives;
-using ReactiveUI;
using Avalonia.Layout;
using Avalonia.Controls.Selection;
+using MiniMvvm;
namespace VirtualizationDemo.ViewModels
{
- internal class MainWindowViewModel : ReactiveObject
+ internal class MainWindowViewModel : ViewModelBase
{
private int _itemCount = 200;
private string _newItemString = "New Item";
@@ -26,15 +26,15 @@ namespace VirtualizationDemo.ViewModels
public MainWindowViewModel()
{
this.WhenAnyValue(x => x.ItemCount).Subscribe(ResizeItems);
- RecreateCommand = ReactiveCommand.Create(() => Recreate());
+ RecreateCommand = MiniCommand.Create(() => Recreate());
- AddItemCommand = ReactiveCommand.Create(() => AddItem());
+ AddItemCommand = MiniCommand.Create(() => AddItem());
- RemoveItemCommand = ReactiveCommand.Create(() => Remove());
+ RemoveItemCommand = MiniCommand.Create(() => Remove());
- SelectFirstCommand = ReactiveCommand.Create(() => SelectItem(0));
+ SelectFirstCommand = MiniCommand.Create(() => SelectItem(0));
- SelectLastCommand = ReactiveCommand.Create(() => SelectItem(Items.Count - 1));
+ SelectLastCommand = MiniCommand.Create(() => SelectItem(Items.Count - 1));
}
public string NewItemString
@@ -90,11 +90,11 @@ namespace VirtualizationDemo.ViewModels
public IEnumerable VirtualizationModes =>
Enum.GetValues(typeof(ItemVirtualizationMode)).Cast();
- public ReactiveCommand AddItemCommand { get; private set; }
- public ReactiveCommand RecreateCommand { get; private set; }
- public ReactiveCommand RemoveItemCommand { get; private set; }
- public ReactiveCommand SelectFirstCommand { get; private set; }
- public ReactiveCommand SelectLastCommand { get; private set; }
+ public MiniCommand AddItemCommand { get; private set; }
+ public MiniCommand RecreateCommand { get; private set; }
+ public MiniCommand RemoveItemCommand { get; private set; }
+ public MiniCommand SelectFirstCommand { get; private set; }
+ public MiniCommand SelectLastCommand { get; private set; }
public void RandomizeSize()
{
diff --git a/samples/VirtualizationDemo/VirtualizationDemo.csproj b/samples/VirtualizationDemo/VirtualizationDemo.csproj
index 817023fd71..d898b737a9 100644
--- a/samples/VirtualizationDemo/VirtualizationDemo.csproj
+++ b/samples/VirtualizationDemo/VirtualizationDemo.csproj
@@ -6,12 +6,11 @@
-
+
-
diff --git a/samples/interop/Direct3DInteropSample/App.paml.cs b/samples/interop/Direct3DInteropSample/App.paml.cs
index 1b6d5fd39c..29365decfe 100644
--- a/samples/interop/Direct3DInteropSample/App.paml.cs
+++ b/samples/interop/Direct3DInteropSample/App.paml.cs
@@ -1,4 +1,5 @@
using Avalonia;
+using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
namespace Direct3DInteropSample
@@ -9,5 +10,12 @@ namespace Direct3DInteropSample
{
AvaloniaXamlLoader.Load(this);
}
+
+ public override void OnFrameworkInitializationCompleted()
+ {
+ if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
+ desktop.MainWindow = new MainWindow();
+ base.OnFrameworkInitializationCompleted();
+ }
}
}
diff --git a/samples/interop/Direct3DInteropSample/Direct3DInteropSample.csproj b/samples/interop/Direct3DInteropSample/Direct3DInteropSample.csproj
index bd6b6f170f..cd9963a2e5 100644
--- a/samples/interop/Direct3DInteropSample/Direct3DInteropSample.csproj
+++ b/samples/interop/Direct3DInteropSample/Direct3DInteropSample.csproj
@@ -22,9 +22,9 @@
-
+
diff --git a/samples/interop/Direct3DInteropSample/MainWindowViewModel.cs b/samples/interop/Direct3DInteropSample/MainWindowViewModel.cs
index d39a21cd07..21679a99c5 100644
--- a/samples/interop/Direct3DInteropSample/MainWindowViewModel.cs
+++ b/samples/interop/Direct3DInteropSample/MainWindowViewModel.cs
@@ -3,11 +3,11 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
-using ReactiveUI;
+using MiniMvvm;
namespace Direct3DInteropSample
{
- public class MainWindowViewModel : ReactiveObject
+ public class MainWindowViewModel : ViewModelBase
{
private double _rotationX;
diff --git a/samples/interop/Direct3DInteropSample/Program.cs b/samples/interop/Direct3DInteropSample/Program.cs
index 21302fa68a..bf8e76d7e4 100644
--- a/samples/interop/Direct3DInteropSample/Program.cs
+++ b/samples/interop/Direct3DInteropSample/Program.cs
@@ -1,19 +1,16 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Avalonia;
+using Avalonia;
namespace Direct3DInteropSample
{
class Program
{
- static void Main(string[] args)
- {
- AppBuilder.Configure()
- .With(new Win32PlatformOptions {UseDeferredRendering = false})
- .UseWin32().UseDirect2D1().Start();
- }
+ public static AppBuilder BuildAvaloniaApp()
+ => AppBuilder.Configure()
+ .With(new Win32PlatformOptions { UseDeferredRendering = false })
+ .UseWin32()
+ .UseDirect2D1();
+
+ public static int Main(string[] args)
+ => BuildAvaloniaApp().StartWithClassicDesktopLifetime(args);
}
}
diff --git a/samples/interop/NativeEmbedSample/NativeEmbedSample.csproj b/samples/interop/NativeEmbedSample/NativeEmbedSample.csproj
index cc831ef8ae..c25442b52c 100644
--- a/samples/interop/NativeEmbedSample/NativeEmbedSample.csproj
+++ b/samples/interop/NativeEmbedSample/NativeEmbedSample.csproj
@@ -9,11 +9,10 @@
-
-
+
Designer
diff --git a/samples/interop/WindowsInteropTest/WindowsInteropTest.csproj b/samples/interop/WindowsInteropTest/WindowsInteropTest.csproj
index c067d38595..8394d7cb13 100644
--- a/samples/interop/WindowsInteropTest/WindowsInteropTest.csproj
+++ b/samples/interop/WindowsInteropTest/WindowsInteropTest.csproj
@@ -136,10 +136,6 @@
{42472427-4774-4c81-8aff-9f27b8e31721}
Avalonia.Layout
-
- {6417b24e-49c2-4985-8db2-3ab9d898ec91}
- Avalonia.ReactiveUI
-
{eb582467-6abb-43a1-b052-e981ba910e3a}
Avalonia.Visuals
@@ -190,4 +186,4 @@
-
\ No newline at end of file
+
diff --git a/src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj b/src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj
index b8697e0ca2..f880e48282 100644
--- a/src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj
+++ b/src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj
@@ -127,10 +127,6 @@
{42472427-4774-4c81-8aff-9f27b8e31721}
Avalonia.Layout
-
- {6417b24e-49c2-4985-8db2-3ab9d898ec91}
- Avalonia.ReactiveUI
-
{eb582467-6abb-43a1-b052-e981ba910e3a}
Avalonia.Visuals
diff --git a/src/Avalonia.Animation/Properties/AssemblyInfo.cs b/src/Avalonia.Animation/Properties/AssemblyInfo.cs
index d34fd06272..221b51e95a 100644
--- a/src/Avalonia.Animation/Properties/AssemblyInfo.cs
+++ b/src/Avalonia.Animation/Properties/AssemblyInfo.cs
@@ -6,5 +6,10 @@ using System.Runtime.CompilerServices;
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Animation.Easings")]
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Animation.Animators")]
+#if SIGNED_BUILD
+[assembly: InternalsVisibleTo("Avalonia.LeakTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")]
+[assembly: InternalsVisibleTo("Avalonia.Animation.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")]
+#else
[assembly: InternalsVisibleTo("Avalonia.LeakTests")]
[assembly: InternalsVisibleTo("Avalonia.Animation.UnitTests")]
+#endif
diff --git a/src/Avalonia.Base/ApiCompatBaseline.txt b/src/Avalonia.Base/ApiCompatBaseline.txt
index 4668a572c5..d17f25ec49 100644
--- a/src/Avalonia.Base/ApiCompatBaseline.txt
+++ b/src/Avalonia.Base/ApiCompatBaseline.txt
@@ -1,3 +1,4 @@
Compat issues with assembly Avalonia.Base:
-CannotAddAbstractMembers : Member 'protected System.IObservable Avalonia.AvaloniaProperty.GetChanged()' is abstract in the implementation but is missing in the contract.
-Total Issues: 1
+MembersMustExist : Member 'public void Avalonia.Threading.AvaloniaSynchronizationContext..ctor(Avalonia.Threading.AvaloniaSynchronizationContext.INonPumpingPlatformWaitProvider)' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'Avalonia.Threading.AvaloniaSynchronizationContext.INonPumpingPlatformWaitProvider' does not exist in the implementation but it does exist in the contract.
+Total Issues: 2
diff --git a/src/Avalonia.Base/AvaloniaLocator.cs b/src/Avalonia.Base/AvaloniaLocator.cs
index f9bbe38bec..3163d15c1b 100644
--- a/src/Avalonia.Base/AvaloniaLocator.cs
+++ b/src/Avalonia.Base/AvaloniaLocator.cs
@@ -54,6 +54,23 @@ namespace Avalonia
return _locator;
}
+ public AvaloniaLocator ToLazy(Func func) where TImlp : TService
+ {
+ var constructed = false;
+ TImlp instance = default;
+ _locator._registry[typeof (TService)] = () =>
+ {
+ if (!constructed)
+ {
+ instance = func();
+ constructed = true;
+ }
+
+ return instance;
+ };
+ return _locator;
+ }
+
public AvaloniaLocator ToSingleton() where TImpl : class, TService, new()
{
TImpl instance = null;
diff --git a/src/Avalonia.Base/Collections/AvaloniaList.cs b/src/Avalonia.Base/Collections/AvaloniaList.cs
index d43b4e04bb..5681214222 100644
--- a/src/Avalonia.Base/Collections/AvaloniaList.cs
+++ b/src/Avalonia.Base/Collections/AvaloniaList.cs
@@ -63,6 +63,15 @@ namespace Avalonia.Collections
_inner = new List();
}
+ ///
+ /// Initializes a new instance of the .
+ ///
+ /// Initial list capacity.
+ public AvaloniaList(int capacity)
+ {
+ _inner = new List(capacity);
+ }
+
///
/// Initializes a new instance of the class.
///
@@ -175,6 +184,15 @@ namespace Avalonia.Collections
set { this[index] = (T)value; }
}
+ ///
+ /// Gets or sets the total number of elements the internal data structure can hold without resizing.
+ ///
+ public int Capacity
+ {
+ get => _inner.Capacity;
+ set => _inner.Capacity = value;
+ }
+
///
/// Adds an item to the collection.
///
diff --git a/src/Avalonia.Base/Data/Core/Plugins/InpcPropertyAccessorPlugin.cs b/src/Avalonia.Base/Data/Core/Plugins/InpcPropertyAccessorPlugin.cs
index 8fc2a7b77c..3bf6842cd6 100644
--- a/src/Avalonia.Base/Data/Core/Plugins/InpcPropertyAccessorPlugin.cs
+++ b/src/Avalonia.Base/Data/Core/Plugins/InpcPropertyAccessorPlugin.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;
using Avalonia.Utilities;
@@ -11,8 +12,11 @@ namespace Avalonia.Data.Core.Plugins
///
public class InpcPropertyAccessorPlugin : IPropertyAccessorPlugin
{
+ private readonly Dictionary<(Type, string), PropertyInfo> _propertyLookup =
+ new Dictionary<(Type, string), PropertyInfo>();
+
///
- public bool Match(object obj, string propertyName) => GetPropertyWithName(obj.GetType(), propertyName) != null;
+ public bool Match(object obj, string propertyName) => GetFirstPropertyWithName(obj.GetType(), propertyName) != null;
///
/// Starts monitoring the value of a property on an object.
@@ -30,7 +34,7 @@ namespace Avalonia.Data.Core.Plugins
reference.TryGetTarget(out object instance);
- var p = GetPropertyWithName(instance.GetType(), propertyName);
+ var p = GetFirstPropertyWithName(instance.GetType(), propertyName);
if (p != null)
{
@@ -44,12 +48,40 @@ namespace Avalonia.Data.Core.Plugins
}
}
- private static PropertyInfo GetPropertyWithName(Type type, string propertyName)
+ private PropertyInfo GetFirstPropertyWithName(Type type, string propertyName)
{
- const BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.Public |
- BindingFlags.Static | BindingFlags.Instance;
+ var key = (type, propertyName);
+
+ if (!_propertyLookup.TryGetValue(key, out PropertyInfo propertyInfo))
+ {
+ propertyInfo = TryFindAndCacheProperty(type, propertyName);
+ }
+
+ return propertyInfo;
+ }
+
+ private PropertyInfo TryFindAndCacheProperty(Type type, string propertyName)
+ {
+ PropertyInfo found = null;
+
+ const BindingFlags bindingFlags =
+ BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance;
+
+ var properties = type.GetProperties(bindingFlags);
+
+ foreach (PropertyInfo propertyInfo in properties)
+ {
+ if (propertyInfo.Name == propertyName)
+ {
+ found = propertyInfo;
+
+ break;
+ }
+ }
+
+ _propertyLookup.Add((type, propertyName), found);
- return type.GetProperty(propertyName, bindingFlags);
+ return found;
}
private class Accessor : PropertyAccessorBase, IWeakSubscriber
diff --git a/src/Avalonia.Base/Data/Core/TypeCastNode.cs b/src/Avalonia.Base/Data/Core/TypeCastNode.cs
new file mode 100644
index 0000000000..476fd5527f
--- /dev/null
+++ b/src/Avalonia.Base/Data/Core/TypeCastNode.cs
@@ -0,0 +1,34 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Avalonia.Data.Core
+{
+ public class TypeCastNode : ExpressionNode
+ {
+ public override string Description => $"as {TargetType.FullName}";
+
+ public Type TargetType { get; }
+
+ public TypeCastNode(Type type)
+ {
+ TargetType = type;
+ }
+
+ protected virtual object Cast(object value)
+ {
+ return TargetType.IsInstanceOfType(value) ? value : null;
+ }
+
+ protected override void StartListeningCore(WeakReference reference)
+ {
+ if (reference.TryGetTarget(out object target))
+ {
+ target = Cast(target);
+ reference = target == null ? NullReference : new WeakReference(target);
+ }
+
+ base.StartListeningCore(reference);
+ }
+ }
+}
diff --git a/src/Avalonia.Base/Logging/LogArea.cs b/src/Avalonia.Base/Logging/LogArea.cs
index 3c19b47a05..2ad220dddd 100644
--- a/src/Avalonia.Base/Logging/LogArea.cs
+++ b/src/Avalonia.Base/Logging/LogArea.cs
@@ -34,5 +34,10 @@ namespace Avalonia.Logging
/// The log event comes from the control system.
///
public const string Control = "Control";
+
+ ///
+ /// The log event comes from Win32Platform.
+ ///
+ public const string Win32Platform = nameof(Win32Platform);
}
}
diff --git a/src/Avalonia.Base/Logging/DebugLogSink.cs b/src/Avalonia.Base/Logging/TraceLogSink.cs
similarity index 92%
rename from src/Avalonia.Base/Logging/DebugLogSink.cs
rename to src/Avalonia.Base/Logging/TraceLogSink.cs
index 3695afa860..f597844378 100644
--- a/src/Avalonia.Base/Logging/DebugLogSink.cs
+++ b/src/Avalonia.Base/Logging/TraceLogSink.cs
@@ -6,12 +6,12 @@ using Avalonia.Utilities;
namespace Avalonia.Logging
{
- public class DebugLogSink : ILogSink
+ public class TraceLogSink : ILogSink
{
private readonly LogEventLevel _level;
private readonly IList _areas;
- public DebugLogSink(
+ public TraceLogSink(
LogEventLevel minimumLevel,
IList areas = null)
{
@@ -28,7 +28,7 @@ namespace Avalonia.Logging
{
if (IsEnabled(level, area))
{
- Debug.WriteLine(Format(area, messageTemplate, source));
+ Trace.WriteLine(Format(area, messageTemplate, source));
}
}
@@ -36,7 +36,7 @@ namespace Avalonia.Logging
{
if (IsEnabled(level, area))
{
- Debug.WriteLine(Format(area, messageTemplate, source, propertyValue0));
+ Trace.WriteLine(Format(area, messageTemplate, source, propertyValue0));
}
}
@@ -44,7 +44,7 @@ namespace Avalonia.Logging
{
if (IsEnabled(level, area))
{
- Debug.WriteLine(Format(area, messageTemplate, source, propertyValue0, propertyValue1));
+ Trace.WriteLine(Format(area, messageTemplate, source, propertyValue0, propertyValue1));
}
}
@@ -52,7 +52,7 @@ namespace Avalonia.Logging
{
if (IsEnabled(level, area))
{
- Debug.WriteLine(Format(area, messageTemplate, source, propertyValue0, propertyValue1, propertyValue2));
+ Trace.WriteLine(Format(area, messageTemplate, source, propertyValue0, propertyValue1, propertyValue2));
}
}
@@ -60,7 +60,7 @@ namespace Avalonia.Logging
{
if (IsEnabled(level, area))
{
- Debug.WriteLine(Format(area, messageTemplate, source, propertyValues));
+ Trace.WriteLine(Format(area, messageTemplate, source, propertyValues));
}
}
diff --git a/src/Avalonia.Base/Metadata/XmlnsPrefixAttribute.cs b/src/Avalonia.Base/Metadata/XmlnsPrefixAttribute.cs
new file mode 100644
index 0000000000..ad017822e4
--- /dev/null
+++ b/src/Avalonia.Base/Metadata/XmlnsPrefixAttribute.cs
@@ -0,0 +1,39 @@
+using System;
+
+namespace Avalonia.Metadata
+{
+ ///
+ /// Use to predefine the prefix associated to an xml namespace in a xaml file
+ ///
+ ///
+ /// example:
+ /// [assembly: XmlnsPrefix("https://github.com/avaloniaui", "av")]
+ /// xaml:
+ /// xmlns:av="https://github.com/avaloniaui"
+ ///
+ [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
+ public sealed class XmlnsPrefixAttribute : Attribute
+ {
+ ///
+ /// Constructor
+ ///
+ /// XML namespce
+ /// recommended prefix
+ public XmlnsPrefixAttribute(string xmlNamespace, string prefix)
+ {
+ XmlNamespace = xmlNamespace ?? throw new ArgumentNullException(nameof(xmlNamespace));
+
+ Prefix = prefix ?? throw new ArgumentNullException(nameof(prefix));
+ }
+
+ ///
+ /// XML Namespace
+ ///
+ public string XmlNamespace { get; }
+
+ ///
+ /// New Xml Namespace
+ ///
+ public string Prefix { get; }
+ }
+}
diff --git a/src/Avalonia.Base/Properties/AssemblyInfo.cs b/src/Avalonia.Base/Properties/AssemblyInfo.cs
index 13b247de51..b054c186ae 100644
--- a/src/Avalonia.Base/Properties/AssemblyInfo.cs
+++ b/src/Avalonia.Base/Properties/AssemblyInfo.cs
@@ -5,8 +5,18 @@ using System.Runtime.CompilerServices;
using Avalonia.Metadata;
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Data.Converters")]
+#if SIGNED_BUILD
+[assembly: InternalsVisibleTo("Avalonia.Base.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")]
+[assembly: InternalsVisibleTo("Avalonia.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")]
+[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]
+[assembly: InternalsVisibleTo("Avalonia.Controls.DataGrid, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")]
+[assembly: InternalsVisibleTo("Avalonia.Markup.Xaml.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")]
+[assembly: InternalsVisibleTo("Avalonia.Visuals, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")]
+#else
[assembly: InternalsVisibleTo("Avalonia.Base.UnitTests")]
[assembly: InternalsVisibleTo("Avalonia.UnitTests")]
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
[assembly: InternalsVisibleTo("Avalonia.Controls.DataGrid")]
[assembly: InternalsVisibleTo("Avalonia.Markup.Xaml.UnitTests")]
+[assembly: InternalsVisibleTo("Avalonia.Visuals")]
+#endif
diff --git a/src/Avalonia.Base/Threading/AvaloniaSynchronizationContext.cs b/src/Avalonia.Base/Threading/AvaloniaSynchronizationContext.cs
index 40cf81358f..1a78792173 100644
--- a/src/Avalonia.Base/Threading/AvaloniaSynchronizationContext.cs
+++ b/src/Avalonia.Base/Threading/AvaloniaSynchronizationContext.cs
@@ -9,20 +9,6 @@ namespace Avalonia.Threading
///
public class AvaloniaSynchronizationContext : SynchronizationContext
{
- public interface INonPumpingPlatformWaitProvider
- {
- int Wait(IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout);
- }
-
- private readonly INonPumpingPlatformWaitProvider _waitProvider;
-
- public AvaloniaSynchronizationContext(INonPumpingPlatformWaitProvider waitProvider)
- {
- _waitProvider = waitProvider;
- if (_waitProvider != null)
- SetWaitNotificationRequired();
- }
-
///
/// Controls if SynchronizationContext should be installed in InstallIfNeeded. Used by Designer.
///
@@ -38,8 +24,7 @@ namespace Avalonia.Threading
return;
}
- SetSynchronizationContext(new AvaloniaSynchronizationContext(AvaloniaLocator.Current
- .GetService()));
+ SetSynchronizationContext(new AvaloniaSynchronizationContext());
}
///
@@ -57,12 +42,6 @@ namespace Avalonia.Threading
Dispatcher.UIThread.InvokeAsync(() => d(state), DispatcherPriority.Send).Wait();
}
- [PrePrepareMethod]
- public override int Wait(IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout)
- {
- if (_waitProvider != null)
- return _waitProvider.Wait(waitHandles, waitAll, millisecondsTimeout);
- return base.Wait(waitHandles, waitAll, millisecondsTimeout);
- }
+
}
}
diff --git a/src/Avalonia.Base/Utilities/AvaloniaPropertyValueStore.cs b/src/Avalonia.Base/Utilities/AvaloniaPropertyValueStore.cs
index 0238446892..6e52b6770a 100644
--- a/src/Avalonia.Base/Utilities/AvaloniaPropertyValueStore.cs
+++ b/src/Avalonia.Base/Utilities/AvaloniaPropertyValueStore.cs
@@ -1,5 +1,8 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+
+#nullable enable
namespace Avalonia.Utilities
{
@@ -9,12 +12,14 @@ namespace Avalonia.Utilities
/// Stored value type.
internal sealed class AvaloniaPropertyValueStore
{
+ // The last item in the list is always int.MaxValue.
+ private static readonly Entry[] s_emptyEntries = { new Entry { PropertyId = int.MaxValue, Value = default! } };
+
private Entry[] _entries;
public AvaloniaPropertyValueStore()
{
- // The last item in the list is always int.MaxValue
- _entries = new[] { new Entry { PropertyId = int.MaxValue, Value = default } };
+ _entries = s_emptyEntries;
}
private (int, bool) TryFindEntry(int propertyId)
@@ -86,7 +91,7 @@ namespace Avalonia.Utilities
return (0, false);
}
- public bool TryGetValue(AvaloniaProperty property, out TValue value)
+ public bool TryGetValue(AvaloniaProperty property, [MaybeNull] out TValue value)
{
(int index, bool found) = TryFindEntry(property.Id);
if (!found)
@@ -132,7 +137,18 @@ namespace Avalonia.Utilities
if (found)
{
- Entry[] entries = new Entry[_entries.Length - 1];
+ var newLength = _entries.Length - 1;
+
+ // Special case - one element left means that value store is empty so we can just reuse our "empty" array.
+ if (newLength == 1)
+ {
+ _entries = s_emptyEntries;
+
+ return;
+ }
+
+ var entries = new Entry[newLength];
+
int ix = 0;
for (int i = 0; i < _entries.Length; ++i)
diff --git a/src/Avalonia.Base/Utilities/MathUtilities.cs b/src/Avalonia.Base/Utilities/MathUtilities.cs
index 2a92e75f58..446b366dc8 100644
--- a/src/Avalonia.Base/Utilities/MathUtilities.cs
+++ b/src/Avalonia.Base/Utilities/MathUtilities.cs
@@ -5,7 +5,10 @@ namespace Avalonia.Utilities
///
/// Provides math utilities not provided in System.Math.
///
- public static class MathUtilities
+#if !BUILDTASK
+ public
+#endif
+ static class MathUtilities
{
// smallest such that 1.0+DoubleEpsilon != 1.0
internal static readonly double DoubleEpsilon = 2.2204460492503131e-016;
diff --git a/src/Avalonia.Base/Utilities/NonPumpingLockHelper.cs b/src/Avalonia.Base/Utilities/NonPumpingLockHelper.cs
new file mode 100644
index 0000000000..fd4e5d2ace
--- /dev/null
+++ b/src/Avalonia.Base/Utilities/NonPumpingLockHelper.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Avalonia.Utilities
+{
+ public class NonPumpingLockHelper
+ {
+ public interface IHelperImpl
+ {
+ IDisposable Use();
+ }
+
+ public static IDisposable Use() => AvaloniaLocator.Current.GetService()?.Use();
+ }
+}
diff --git a/src/Avalonia.Base/Utilities/StringTokenizer.cs b/src/Avalonia.Base/Utilities/StringTokenizer.cs
index a159bfb72e..24e99febb9 100644
--- a/src/Avalonia.Base/Utilities/StringTokenizer.cs
+++ b/src/Avalonia.Base/Utilities/StringTokenizer.cs
@@ -4,7 +4,10 @@ using static System.Char;
namespace Avalonia.Utilities
{
- public struct StringTokenizer : IDisposable
+#if !BUILDTASK
+ public
+#endif
+ struct StringTokenizer : IDisposable
{
private const char DefaultSeparatorChar = ',';
diff --git a/src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj b/src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj
index 490364c0d8..90f6abc873 100644
--- a/src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj
+++ b/src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj
@@ -1,7 +1,7 @@
netstandard2.0
- netstandard2.0;netcoreapp2.0
+ netstandard2.0;netcoreapp3.1
exe
false
tools
@@ -45,6 +45,12 @@
Markup/%(RecursiveDir)%(FileName)%(Extension)
+
+ Markup/%(RecursiveDir)%(FileName)%(Extension)
+
+
+ Markup/%(RecursiveDir)%(FileName)%(Extension)
+
Markup/%(RecursiveDir)%(FileName)%(Extension)
@@ -57,9 +63,36 @@
Markup/%(RecursiveDir)%(FileName)%(Extension)
+
+ Markup/%(RecursiveDir)%(FileName)%(Extension)
+
+
+ Markup/%(RecursiveDir)%(FileName)%(Extension)
+
+
+ Markup/%(RecursiveDir)%(FileName)%(Extension)
+
+
+ Markup/%(RecursiveDir)%(FileName)%(Extension)
+
+
+ Markup/%(RecursiveDir)%(FileName)%(Extension)
+
+
+ Markup/%(RecursiveDir)%(FileName)%(Extension)
+
+
+ Markup/%(RecursiveDir)%(FileName)%(Extension)
+
+
+ Markup/%(RecursiveDir)%(FileName)%(Extension)
+
+
+ Markup/%(RecursiveDir)%(FileName)%(Extension)
+
-
+
diff --git a/src/Avalonia.Build.Tasks/ComInteropHelper.cs b/src/Avalonia.Build.Tasks/ComInteropHelper.cs
new file mode 100644
index 0000000000..007231417d
--- /dev/null
+++ b/src/Avalonia.Build.Tasks/ComInteropHelper.cs
@@ -0,0 +1,130 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using Mono.Cecil;
+using Mono.Cecil.Cil;
+using XamlX.TypeSystem;
+using MethodAttributes = Mono.Cecil.MethodAttributes;
+
+namespace Avalonia.Build.Tasks
+{
+ static class ComInteropHelper
+ {
+ public static void PatchAssembly(AssemblyDefinition asm, CecilTypeSystem typeSystem)
+ {
+ var classToRemoveList = new List();
+ var initializers = new List();
+ foreach (var type in asm.MainModule.Types)
+ {
+ var i = type.Methods.FirstOrDefault(m => m.Name == "__MicroComModuleInit");
+ if (i != null)
+ initializers.Add(i);
+
+ PatchType(type, classToRemoveList);
+ }
+
+ // Remove All Interop classes
+ foreach (var type in classToRemoveList)
+ asm.MainModule.Types.Remove(type);
+
+
+ // Patch automatic registrations
+ if (initializers.Count != 0)
+ {
+ var moduleType = asm.MainModule.Types.First(x => x.Name == "");
+
+ // Needed for compatibility with upcoming .NET 5 feature, look for existing initializer first
+ var staticCtor = moduleType.Methods.FirstOrDefault(m => m.Name == ".cctor");
+ if (staticCtor == null)
+ {
+ // Create a new static ctor if none exists
+ staticCtor = new MethodDefinition(".cctor",
+ MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName |
+ MethodAttributes.Static | MethodAttributes.Private,
+ asm.MainModule.TypeSystem.Void);
+ staticCtor.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
+ moduleType.Methods.Add(staticCtor);
+ }
+
+ foreach (var i in initializers)
+ staticCtor.Body.Instructions.Insert(0, Instruction.Create(OpCodes.Call, i));
+ }
+
+ }
+
+
+
+ static void PatchMethod(MethodDefinition method)
+ {
+ if (method.HasBody)
+ {
+ var ilProcessor = method.Body.GetILProcessor();
+
+ var instructions = method.Body.Instructions;
+ for (int i = 0; i < instructions.Count; i++)
+ {
+ Instruction instruction = instructions[i];
+
+ if (instruction.OpCode == OpCodes.Call && instruction.Operand is MethodReference)
+ {
+ var methodDescription = (MethodReference)instruction.Operand;
+
+ if (methodDescription.Name.StartsWith("Calli") && methodDescription.DeclaringType.Name == "LocalInterop")
+ {
+ var callSite = new CallSite(methodDescription.ReturnType) { CallingConvention = MethodCallingConvention.StdCall };
+
+ if (methodDescription.Name.StartsWith("CalliCdecl"))
+ {
+ callSite.CallingConvention = MethodCallingConvention.C;
+ }
+ else if(methodDescription.Name.StartsWith("CalliThisCall"))
+ {
+ callSite.CallingConvention = MethodCallingConvention.ThisCall;
+ }
+ else if(methodDescription.Name.StartsWith("CalliStdCall"))
+ {
+ callSite.CallingConvention = MethodCallingConvention.StdCall;
+ }
+ else if(methodDescription.Name.StartsWith("CalliFastCall"))
+ {
+ callSite.CallingConvention = MethodCallingConvention.FastCall;
+ }
+
+ // Last parameter is the function ptr, so we don't add it as a parameter for calli
+ // as it is already an implicit parameter for calli
+ for (int j = 0; j < methodDescription.Parameters.Count - 1; j++)
+ {
+ var parameterDefinition = methodDescription.Parameters[j];
+ callSite.Parameters.Add(parameterDefinition);
+ }
+
+ // Create calli Instruction
+ var callIInstruction = ilProcessor.Create(OpCodes.Calli, callSite);
+
+ // Replace instruction
+ ilProcessor.Replace(instruction, callIInstruction);
+ }
+ }
+ }
+ }
+ }
+
+ ///
+ /// Patches the type.
+ ///
+ /// The type.
+ static void PatchType(TypeDefinition type, List classToRemoveList)
+ {
+ // Patch methods
+ foreach (var method in type.Methods)
+ PatchMethod(method);
+
+ if (type.Name == "LocalInterop")
+ classToRemoveList.Add(type);
+
+ // Patch nested types
+ foreach (var typeDefinition in type.NestedTypes)
+ PatchType(typeDefinition, classToRemoveList);
+ }
+ }
+}
diff --git a/src/Avalonia.Build.Tasks/CompileAvaloniaXamlTask.cs b/src/Avalonia.Build.Tasks/CompileAvaloniaXamlTask.cs
index 95e59dde2b..b85991fb77 100644
--- a/src/Avalonia.Build.Tasks/CompileAvaloniaXamlTask.cs
+++ b/src/Avalonia.Build.Tasks/CompileAvaloniaXamlTask.cs
@@ -39,7 +39,9 @@ namespace Avalonia.Build.Tasks
var res = XamlCompilerTaskExecutor.Compile(BuildEngine, input,
File.ReadAllLines(ReferencesFilePath).Where(l => !string.IsNullOrWhiteSpace(l)).ToArray(),
- ProjectDirectory, OutputPath, VerifyIl, outputImportance);
+ ProjectDirectory, OutputPath, VerifyIl, outputImportance,
+ (SignAssembly && !DelaySign) ? AssemblyOriginatorKeyFile : null,
+ EnableComInteropPatching, SkipXamlCompilation);
if (!res.Success)
return false;
if (!res.WrittenFile)
@@ -73,6 +75,13 @@ namespace Avalonia.Build.Tasks
public string OutputPath { get; set; }
public bool VerifyIl { get; set; }
+
+ public bool EnableComInteropPatching { get; set; }
+ public bool SkipXamlCompilation { get; set; }
+
+ public string AssemblyOriginatorKeyFile { get; set; }
+ public bool SignAssembly { get; set; }
+ public bool DelaySign { get; set; }
public string ReportImportance { get; set; }
diff --git a/src/Avalonia.Build.Tasks/Program.cs b/src/Avalonia.Build.Tasks/Program.cs
index 1909c4c6ec..b18c19cd63 100644
--- a/src/Avalonia.Build.Tasks/Program.cs
+++ b/src/Avalonia.Build.Tasks/Program.cs
@@ -29,7 +29,8 @@ namespace Avalonia.Build.Tasks
OutputPath = args[2],
BuildEngine = new ConsoleBuildEngine(),
ProjectDirectory = Directory.GetCurrentDirectory(),
- VerifyIl = true
+ VerifyIl = true,
+ EnableComInteropPatching = true
}.Execute() ?
0 :
2;
diff --git a/src/Avalonia.Build.Tasks/SpanCompat.cs b/src/Avalonia.Build.Tasks/SpanCompat.cs
index d5c406293e..f8960f56ec 100644
--- a/src/Avalonia.Build.Tasks/SpanCompat.cs
+++ b/src/Avalonia.Build.Tasks/SpanCompat.cs
@@ -1,3 +1,4 @@
+#if !NETCOREAPP3_1
namespace System
{
// This is a hack to enable our span code to work inside MSBuild task without referencing System.Memory
@@ -63,6 +64,8 @@ namespace System
}
public override string ToString() => _length == 0 ? string.Empty : _s.Substring(_start, _length);
+
+ public static implicit operator ReadOnlySpan(char[] arr) => new ReadOnlySpan(new string(arr));
}
static class SpanCompatExtensions
@@ -71,3 +74,4 @@ namespace System
}
}
+#endif
diff --git a/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs b/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs
index c9c9c562bd..6ef8a98fae 100644
--- a/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs
+++ b/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs
@@ -40,17 +40,50 @@ namespace Avalonia.Build.Tasks
WrittenFile = writtenFile;
}
}
+
+ public static CompileResult Compile(IBuildEngine engine, string input, string[] references,
+ string projectDirectory,
+ string output, bool verifyIl, MessageImportance logImportance, string strongNameKey, bool patchCom,
+ bool skipXamlCompilation)
+ {
+ var typeSystem = new CecilTypeSystem(references
+ .Where(r => !r.ToLowerInvariant().EndsWith("avalonia.build.tasks.dll"))
+ .Concat(new[] { input }), input);
+
+ var asm = typeSystem.TargetAssemblyDefinition;
+
+ if (!skipXamlCompilation)
+ {
+ var compileRes = CompileCore(engine, typeSystem, projectDirectory, verifyIl, logImportance);
+ if (compileRes == null && !patchCom)
+ return new CompileResult(true);
+ if (compileRes == false)
+ return new CompileResult(false);
+ }
+
+ if (patchCom)
+ ComInteropHelper.PatchAssembly(asm, typeSystem);
+
+ var writerParameters = new WriterParameters { WriteSymbols = asm.MainModule.HasSymbols };
+ if (!string.IsNullOrWhiteSpace(strongNameKey))
+ writerParameters.StrongNameKeyBlob = File.ReadAllBytes(strongNameKey);
+
+ asm.Write(output, writerParameters);
+
+ return new CompileResult(true, true);
+
+ }
- public static CompileResult Compile(IBuildEngine engine, string input, string[] references, string projectDirectory,
- string output, bool verifyIl, MessageImportance logImportance)
+ static bool? CompileCore(IBuildEngine engine, CecilTypeSystem typeSystem,
+ string projectDirectory, bool verifyIl,
+ MessageImportance logImportance)
{
- var typeSystem = new CecilTypeSystem(references.Concat(new[] {input}), input);
var asm = typeSystem.TargetAssemblyDefinition;
var emres = new EmbeddedResources(asm);
var avares = new AvaloniaResources(asm, projectDirectory);
if (avares.Resources.Count(CheckXamlName) == 0 && emres.Resources.Count(CheckXamlName) == 0)
// Nothing to do
- return new CompileResult(true);
+ return null;
var clrPropertiesDef = new TypeDefinition("CompiledAvaloniaXaml", "XamlIlHelpers",
TypeAttributes.Class, asm.MainModule.TypeSystem.Object);
@@ -345,28 +378,36 @@ namespace Avalonia.Build.Tasks
}
res.Remove();
}
+
+
+ // Technically that's a hack, but it fixes corert incompatibility caused by deterministic builds
+ int dupeCounter = 1;
+ foreach (var grp in typeDef.NestedTypes.GroupBy(x => x.Name))
+ {
+ if (grp.Count() > 1)
+ {
+ foreach (var dupe in grp)
+ dupe.Name += "_dup" + dupeCounter++;
+ }
+ }
+
+
return true;
}
if (emres.Resources.Count(CheckXamlName) != 0)
if (!CompileGroup(emres))
- return new CompileResult(false);
+ return false;
if (avares.Resources.Count(CheckXamlName) != 0)
{
if (!CompileGroup(avares))
- return new CompileResult(false);
+ return false;
avares.Save();
}
loaderDispatcherMethod.Body.Instructions.Add(Instruction.Create(OpCodes.Ldnull));
loaderDispatcherMethod.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
-
- asm.Write(output, new WriterParameters
- {
- WriteSymbols = asm.MainModule.HasSymbols
- });
-
- return new CompileResult(true, true);
+ return true;
}
}
diff --git a/src/Avalonia.Controls.DataGrid/ApiCompatBaseline.txt b/src/Avalonia.Controls.DataGrid/ApiCompatBaseline.txt
index 82472c505a..fcc74cf864 100644
--- a/src/Avalonia.Controls.DataGrid/ApiCompatBaseline.txt
+++ b/src/Avalonia.Controls.DataGrid/ApiCompatBaseline.txt
@@ -1,5 +1 @@
-Compat issues with assembly Avalonia.Controls.DataGrid:
-MembersMustExist : Member 'public Avalonia.StyledProperty Avalonia.StyledProperty Avalonia.Controls.DataGridTextColumn.FontFamilyProperty' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'public System.String Avalonia.Controls.DataGridTextColumn.FontFamily.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'public void Avalonia.Controls.DataGridTextColumn.FontFamily.set(System.String)' does not exist in the implementation but it does exist in the contract.
-Total Issues: 3
+Total Issues: 0
diff --git a/src/Avalonia.Controls.DataGrid/DataGridColumn.cs b/src/Avalonia.Controls.DataGrid/DataGridColumn.cs
index 23c4acdf6c..92ddd4e736 100644
--- a/src/Avalonia.Controls.DataGrid/DataGridColumn.cs
+++ b/src/Avalonia.Controls.DataGrid/DataGridColumn.cs
@@ -665,6 +665,7 @@ namespace Avalonia.Controls
///
/// The data item represented by the row that contains the intended cell.
///
+ /// When the method returns, contains the applied binding.
///
/// A new editing element that is bound to the column's property value.
///
diff --git a/src/Avalonia.Controls.DataGrid/DataGridColumnHeader.cs b/src/Avalonia.Controls.DataGrid/DataGridColumnHeader.cs
index 856d1f6566..7f8d205949 100644
--- a/src/Avalonia.Controls.DataGrid/DataGridColumnHeader.cs
+++ b/src/Avalonia.Controls.DataGrid/DataGridColumnHeader.cs
@@ -340,8 +340,6 @@ namespace Avalonia.Controls
if (OwningGrid != null && OwningGrid.ColumnHeaders != null)
{
- args.Pointer.Capture(this);
-
_dragMode = DragMode.MouseDown;
_frozenColumnsWidth = OwningGrid.ColumnsInternal.GetVisibleFrozenEdgedColumnsWidth();
_lastMousePositionHeaders = this.Translate(OwningGrid.ColumnHeaders, mousePosition);
@@ -413,8 +411,9 @@ namespace Avalonia.Controls
}
//TODO DragEvents
- internal void OnMouseMove(ref bool handled, Point mousePosition, Point mousePositionHeaders)
+ internal void OnMouseMove(PointerEventArgs args, Point mousePosition, Point mousePositionHeaders)
{
+ var handled = args.Handled;
if (handled || OwningGrid == null || OwningGrid.ColumnHeaders == null)
{
return;
@@ -438,7 +437,10 @@ namespace Avalonia.Controls
}
_lastMousePositionHeaders = mousePositionHeaders;
-
+
+ if (args.Pointer.Captured != this && _dragMode == DragMode.Drag)
+ args.Pointer.Capture(this);
+
SetDragCursor(mousePosition);
}
@@ -506,8 +508,7 @@ namespace Avalonia.Controls
Point mousePosition = e.GetPosition(this);
Point mousePositionHeaders = e.GetPosition(OwningGrid.ColumnHeaders);
- bool handled = false;
- OnMouseMove(ref handled, mousePosition, mousePositionHeaders);
+ OnMouseMove(e, mousePosition, mousePositionHeaders);
}
///
diff --git a/src/Avalonia.Controls.DataGrid/Properties/AssemblyInfo.cs b/src/Avalonia.Controls.DataGrid/Properties/AssemblyInfo.cs
index 82b01e99bb..1b122996d2 100644
--- a/src/Avalonia.Controls.DataGrid/Properties/AssemblyInfo.cs
+++ b/src/Avalonia.Controls.DataGrid/Properties/AssemblyInfo.cs
@@ -1,10 +1,13 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using Avalonia.Metadata;
-
+#if SIGNED_BUILD
+[assembly: InternalsVisibleTo("Avalonia.Controls.DataGrid.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")]
+[assembly: InternalsVisibleTo("Avalonia.DesignerSupport, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")]
+#else
[assembly: InternalsVisibleTo("Avalonia.Controls.DataGrid.UnitTests")]
[assembly: InternalsVisibleTo("Avalonia.DesignerSupport")]
-
+#endif
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Controls")]
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Controls.Collections")]
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Controls.Primitives")]
diff --git a/src/Avalonia.Controls.DataGrid/Themes/Default.xaml b/src/Avalonia.Controls.DataGrid/Themes/Default.xaml
index cf062e0920..09d19c8e43 100644
--- a/src/Avalonia.Controls.DataGrid/Themes/Default.xaml
+++ b/src/Avalonia.Controls.DataGrid/Themes/Default.xaml
@@ -137,12 +137,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Avalonia.Diagnostics/Diagnostics/Views/ControlDetailsView.xaml.cs b/src/Avalonia.Diagnostics/Diagnostics/Views/ControlDetailsView.xaml.cs
index c6bd5a18aa..c9568509f6 100644
--- a/src/Avalonia.Diagnostics/Diagnostics/Views/ControlDetailsView.xaml.cs
+++ b/src/Avalonia.Diagnostics/Diagnostics/Views/ControlDetailsView.xaml.cs
@@ -1,10 +1,24 @@
+using System;
using Avalonia.Controls;
+using Avalonia.Controls.Shapes;
using Avalonia.Markup.Xaml;
+using Avalonia.VisualTree;
namespace Avalonia.Diagnostics.Views
{
internal class ControlDetailsView : UserControl
{
+ private ThicknessEditor _borderArea;
+ private ThicknessEditor _paddingArea;
+ private Rectangle _horizontalSizeBegin;
+ private Rectangle _horizontalSizeEnd;
+ private Rectangle _verticalSizeBegin;
+ private Rectangle _verticalSizeEnd;
+ private Grid _layoutRoot;
+ private Border _horizontalSize;
+ private Border _verticalSize;
+ private Border _contentArea;
+
public ControlDetailsView()
{
InitializeComponent();
@@ -13,6 +27,101 @@ namespace Avalonia.Diagnostics.Views
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
+
+ _borderArea = this.FindControl("BorderArea");
+ _paddingArea = this.FindControl("PaddingArea");
+
+ _horizontalSizeBegin = this.FindControl("HorizontalSizeBegin");
+ _horizontalSizeEnd = this.FindControl("HorizontalSizeEnd");
+ _verticalSizeBegin = this.FindControl("VerticalSizeBegin");
+ _verticalSizeEnd = this.FindControl("VerticalSizeEnd");
+
+ _horizontalSize = this.FindControl("HorizontalSize");
+ _verticalSize = this.FindControl("VerticalSize");
+
+ _contentArea = this.FindControl("ContentArea");
+
+ _layoutRoot = this.FindControl("LayoutRoot");
+
+ void SubscribeToBounds(Visual visual)
+ {
+ visual.GetPropertyChangedObservable(TransformedBoundsProperty)
+ .Subscribe(UpdateSizeGuidelines);
+ }
+
+ SubscribeToBounds(_borderArea);
+ SubscribeToBounds(_paddingArea);
+ SubscribeToBounds(_contentArea);
+ }
+
+ private void UpdateSizeGuidelines(AvaloniaPropertyChangedEventArgs e)
+ {
+ void UpdateGuidelines(Visual area)
+ {
+ if (area.TransformedBounds is TransformedBounds bounds)
+ {
+ // Horizontal guideline
+ {
+ var sizeArea = TranslateToRoot((_horizontalSize.TransformedBounds ?? default).Bounds.BottomLeft,
+ _horizontalSize);
+
+ var start = TranslateToRoot(bounds.Bounds.BottomLeft, area);
+
+ SetPosition(_horizontalSizeBegin, start);
+
+ var end = TranslateToRoot(bounds.Bounds.BottomRight, area);
+
+ SetPosition(_horizontalSizeEnd, end.WithX(end.X - 1));
+
+ var height = sizeArea.Y - start.Y + 2;
+
+ _horizontalSizeBegin.Height = height;
+ _horizontalSizeEnd.Height = height;
+ }
+
+ // Vertical guideline
+ {
+ var sizeArea = TranslateToRoot((_verticalSize.TransformedBounds ?? default).Bounds.TopRight, _verticalSize);
+
+ var start = TranslateToRoot(bounds.Bounds.TopRight, area);
+
+ SetPosition(_verticalSizeBegin, start);
+
+ var end = TranslateToRoot(bounds.Bounds.BottomRight, area);
+
+ SetPosition(_verticalSizeEnd, end.WithY(end.Y - 1));
+
+ var width = sizeArea.X - start.X + 2;
+
+ _verticalSizeBegin.Width = width;
+ _verticalSizeEnd.Width = width;
+ }
+ }
+ }
+
+ Point TranslateToRoot(Point point, IVisual from)
+ {
+ return from.TranslatePoint(point, _layoutRoot) ?? default;
+ }
+
+ static void SetPosition(Rectangle rect, Point start)
+ {
+ Canvas.SetLeft(rect, start.X);
+ Canvas.SetTop(rect, start.Y);
+ }
+
+ if (_borderArea.IsPresent)
+ {
+ UpdateGuidelines(_borderArea);
+ }
+ else if (_paddingArea.IsPresent)
+ {
+ UpdateGuidelines(_paddingArea);
+ }
+ else
+ {
+ UpdateGuidelines(_contentArea);
+ }
}
}
}
diff --git a/src/Avalonia.Diagnostics/Diagnostics/Views/MainWindow.xaml.cs b/src/Avalonia.Diagnostics/Diagnostics/Views/MainWindow.xaml.cs
index 10861538ae..c4f9185728 100644
--- a/src/Avalonia.Diagnostics/Diagnostics/Views/MainWindow.xaml.cs
+++ b/src/Avalonia.Diagnostics/Diagnostics/Views/MainWindow.xaml.cs
@@ -76,7 +76,13 @@ namespace Avalonia.Diagnostics.Views
if (e.Modifiers == modifiers)
{
var point = (Root as IInputRoot)?.MouseDevice?.GetPosition(Root) ?? default;
- var control = Root.GetVisualsAt(point, x => (!(x is AdornerLayer) && x.IsVisible))
+
+ var control = Root.GetVisualsAt(point, x =>
+ {
+ if (x is AdornerLayer || !x.IsVisible) return false;
+ if (!(x is IInputElement ie)) return true;
+ return ie.IsHitTestVisible;
+ })
.FirstOrDefault();
if (control != null)
diff --git a/src/Avalonia.Diagnostics/Diagnostics/Views/ThicknessEditor.cs b/src/Avalonia.Diagnostics/Diagnostics/Views/ThicknessEditor.cs
new file mode 100644
index 0000000000..c7611c8c46
--- /dev/null
+++ b/src/Avalonia.Diagnostics/Diagnostics/Views/ThicknessEditor.cs
@@ -0,0 +1,130 @@
+using Avalonia.Controls;
+using Avalonia.Data;
+using Avalonia.Data.Converters;
+using Avalonia.Media;
+
+namespace Avalonia.Diagnostics.Views
+{
+ internal static class Converters
+ {
+ public static IValueConverter HasConstraintConverter =
+ new FuncValueConverter(ConvertToDecoration);
+
+ private static TextDecorationCollection ConvertToDecoration(object arg)
+ {
+ return arg != null ? TextDecorations.Underline : null;
+ }
+ }
+
+ internal class ThicknessEditor : ContentControl
+ {
+ public static readonly DirectProperty ThicknessProperty =
+ AvaloniaProperty.RegisterDirect(nameof(Thickness), o => o.Thickness,
+ (o, v) => o.Thickness = v, defaultBindingMode: BindingMode.TwoWay);
+
+ public static readonly DirectProperty HeaderProperty =
+ AvaloniaProperty.RegisterDirect(nameof(Header), o => o.Header,
+ (o, v) => o.Header = v);
+
+ public static readonly DirectProperty IsPresentProperty =
+ AvaloniaProperty.RegisterDirect(nameof(Header), o => o.IsPresent,
+ (o, v) => o.IsPresent = v);
+
+ public static readonly DirectProperty LeftProperty =
+ AvaloniaProperty.RegisterDirect(nameof(Left), o => o.Left, (o, v) => o.Left = v);
+
+ public static readonly DirectProperty TopProperty =
+ AvaloniaProperty.RegisterDirect(nameof(Top), o => o.Top, (o, v) => o.Top = v);
+
+ public static readonly DirectProperty RightProperty =
+ AvaloniaProperty.RegisterDirect(nameof(Right), o => o.Right,
+ (o, v) => o.Right = v);
+
+ public static readonly DirectProperty BottomProperty =
+ AvaloniaProperty.RegisterDirect(nameof(Bottom), o => o.Bottom,
+ (o, v) => o.Bottom = v);
+
+
+ private Thickness _thickness;
+ private string _header;
+ private bool _isPresent = true;
+ private double _left;
+ private double _top;
+ private double _right;
+ private double _bottom;
+
+ private bool _isUpdatingThickness;
+
+ public Thickness Thickness
+ {
+ get => _thickness;
+ set => SetAndRaise(ThicknessProperty, ref _thickness, value);
+ }
+
+ public string Header
+ {
+ get => _header;
+ set => SetAndRaise(HeaderProperty, ref _header, value);
+ }
+
+ public bool IsPresent
+ {
+ get => _isPresent;
+ set => SetAndRaise(IsPresentProperty, ref _isPresent, value);
+ }
+
+ public double Left
+ {
+ get => _left;
+ set => SetAndRaise(LeftProperty, ref _left, value);
+ }
+
+ public double Top
+ {
+ get => _top;
+ set => SetAndRaise(TopProperty, ref _top, value);
+ }
+
+ public double Right
+ {
+ get => _right;
+ set => SetAndRaise(RightProperty, ref _right, value);
+ }
+
+ public double Bottom
+ {
+ get => _bottom;
+ set => SetAndRaise(BottomProperty, ref _bottom, value);
+ }
+
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ {
+ base.OnPropertyChanged(change);
+
+ if (change.Property == ThicknessProperty)
+ {
+ try
+ {
+ _isUpdatingThickness = true;
+
+ var value = change.NewValue.GetValueOrDefault();
+
+ Left = value.Left;
+ Top = value.Top;
+ Right = value.Right;
+ Bottom = value.Bottom;
+ }
+ finally
+ {
+ _isUpdatingThickness = false;
+ }
+ }
+ else if (!_isUpdatingThickness &&
+ (change.Property == LeftProperty || change.Property == TopProperty ||
+ change.Property == RightProperty || change.Property == BottomProperty))
+ {
+ Thickness = new Thickness(Left, Top, Right, Bottom);
+ }
+ }
+ }
+}
diff --git a/src/Avalonia.Diagnostics/Diagnostics/Views/TreePageView.xaml b/src/Avalonia.Diagnostics/Diagnostics/Views/TreePageView.xaml
index a1e6ca7d37..86137dfc57 100644
--- a/src/Avalonia.Diagnostics/Diagnostics/Views/TreePageView.xaml
+++ b/src/Avalonia.Diagnostics/Diagnostics/Views/TreePageView.xaml
@@ -2,7 +2,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:Avalonia.Diagnostics.ViewModels"
x:Class="Avalonia.Diagnostics.Views.TreePageView">
-
+
+
diff --git a/src/Avalonia.Dialogs/ApiCompatBaseline.txt b/src/Avalonia.Dialogs/ApiCompatBaseline.txt
new file mode 100644
index 0000000000..fcc74cf864
--- /dev/null
+++ b/src/Avalonia.Dialogs/ApiCompatBaseline.txt
@@ -0,0 +1 @@
+Total Issues: 0
diff --git a/src/Avalonia.FreeDesktop/Avalonia.FreeDesktop.csproj b/src/Avalonia.FreeDesktop/Avalonia.FreeDesktop.csproj
index 260d7350d2..81af76dc20 100644
--- a/src/Avalonia.FreeDesktop/Avalonia.FreeDesktop.csproj
+++ b/src/Avalonia.FreeDesktop/Avalonia.FreeDesktop.csproj
@@ -6,9 +6,7 @@
+
-
-
-
diff --git a/src/Avalonia.FreeDesktop/DBusHelper.cs b/src/Avalonia.FreeDesktop/DBusHelper.cs
index 91c4c28995..b445f86613 100644
--- a/src/Avalonia.FreeDesktop/DBusHelper.cs
+++ b/src/Avalonia.FreeDesktop/DBusHelper.cs
@@ -43,7 +43,7 @@ namespace Avalonia.FreeDesktop
public void Initialized()
{
lock (_lock)
- _ctx = new AvaloniaSynchronizationContext(null);
+ _ctx = new AvaloniaSynchronizationContext();
}
}
public static Connection Connection { get; private set; }
diff --git a/src/Avalonia.Headless/HeadlessPlatformRenderInterface.cs b/src/Avalonia.Headless/HeadlessPlatformRenderInterface.cs
index 4f6af0a41b..6a78f4c6e7 100644
--- a/src/Avalonia.Headless/HeadlessPlatformRenderInterface.cs
+++ b/src/Avalonia.Headless/HeadlessPlatformRenderInterface.cs
@@ -238,7 +238,7 @@ namespace Avalonia.Headless
}
}
- class HeadlessBitmapStub : IBitmapImpl, IRenderTargetBitmapImpl, IWriteableBitmapImpl
+ class HeadlessBitmapStub : IBitmapImpl, IDrawingContextLayerImpl, IWriteableBitmapImpl
{
public Size Size { get; }
@@ -267,6 +267,13 @@ namespace Avalonia.Headless
return new HeadlessDrawingContextStub();
}
+ public void Blit(IDrawingContextImpl context)
+ {
+
+ }
+
+ public bool CanBlit => false;
+
public Vector Dpi { get; }
public PixelSize PixelSize { get; }
public int Version { get; set; }
@@ -307,7 +314,7 @@ namespace Avalonia.Headless
}
- public IRenderTargetBitmapImpl CreateLayer(Size size)
+ public IDrawingContextLayerImpl CreateLayer(Size size)
{
return new HeadlessBitmapStub(size, new Vector(96, 96));
}
diff --git a/src/Avalonia.Headless/HeadlessWindowImpl.cs b/src/Avalonia.Headless/HeadlessWindowImpl.cs
index 8f4fa5e304..3a1f3bdaf7 100644
--- a/src/Avalonia.Headless/HeadlessWindowImpl.cs
+++ b/src/Avalonia.Headless/HeadlessWindowImpl.cs
@@ -75,9 +75,10 @@ namespace Avalonia.Headless
public Action Closed { get; set; }
public IMouseDevice MouseDevice { get; }
- public void Show()
+ public void Show(bool activate)
{
- Dispatcher.UIThread.Post(() => Activated?.Invoke(), DispatcherPriority.Input);
+ if (activate)
+ Dispatcher.UIThread.Post(() => Activated?.Invoke(), DispatcherPriority.Input);
}
public void Hide()
@@ -148,7 +149,7 @@ namespace Avalonia.Headless
public void ShowDialog(IWindowImpl parent)
{
- Show();
+ Show(true);
}
public void SetSystemDecorations(bool enabled)
diff --git a/src/Avalonia.Input/ApiCompatBaseline.txt b/src/Avalonia.Input/ApiCompatBaseline.txt
new file mode 100644
index 0000000000..d960664c1b
--- /dev/null
+++ b/src/Avalonia.Input/ApiCompatBaseline.txt
@@ -0,0 +1,4 @@
+Compat issues with assembly Avalonia.Input:
+InterfacesShouldHaveSameMembers : Interface member 'public System.Boolean Avalonia.Input.IInputElement.IsKeyboardFocusWithin' is present in the implementation but not in the contract.
+InterfacesShouldHaveSameMembers : Interface member 'public System.Boolean Avalonia.Input.IInputElement.IsKeyboardFocusWithin.get()' is present in the implementation but not in the contract.
+Total Issues: 2
diff --git a/src/Avalonia.Input/ICommandSource.cs b/src/Avalonia.Input/ICommandSource.cs
new file mode 100644
index 0000000000..ba2e8eed4e
--- /dev/null
+++ b/src/Avalonia.Input/ICommandSource.cs
@@ -0,0 +1,36 @@
+using System.Windows.Input;
+
+namespace Avalonia.Input
+{
+ ///
+ /// An interface for classes that know how to invoke a Command.
+ ///
+ public interface ICommandSource
+ {
+ ///
+ /// The command that will be executed when the class is "invoked."
+ /// Classes that implement this interface should enable or disable based on the command's CanExecute return value.
+ /// The property may be implemented as read-write if desired.
+ ///
+ ICommand Command { get; }
+
+ ///
+ /// The parameter that will be passed to the command when executing the command.
+ /// The property may be implemented as read-write if desired.
+ ///
+ object CommandParameter { get; }
+
+
+ ///
+ /// Bor the bheavior CanExecuteChanged
+ ///
+ ///
+ ///
+ void CanExecuteChanged(object sender, System.EventArgs e);
+
+ ///
+ /// Gets a value indicating whether this control and all its parents are enabled.
+ ///
+ bool IsEffectivelyEnabled { get; }
+ }
+}
diff --git a/src/Avalonia.Input/IInputElement.cs b/src/Avalonia.Input/IInputElement.cs
index 12fec82368..7aa9c32bca 100644
--- a/src/Avalonia.Input/IInputElement.cs
+++ b/src/Avalonia.Input/IInputElement.cs
@@ -89,6 +89,11 @@ namespace Avalonia.Input
/// value of this control and its parent controls.
///
bool IsEffectivelyEnabled { get; }
+
+ ///
+ /// Gets a value indicating whether keyboard focus is anywhere within the element or its visual tree child elements.
+ ///
+ bool IsKeyboardFocusWithin { get; }
///
/// Gets a value indicating whether the control is focused.
diff --git a/src/Avalonia.Input/InputElement.cs b/src/Avalonia.Input/InputElement.cs
index 9ace7fd92d..66fb9cfb1c 100644
--- a/src/Avalonia.Input/InputElement.cs
+++ b/src/Avalonia.Input/InputElement.cs
@@ -42,6 +42,14 @@ namespace Avalonia.Input
public static readonly StyledProperty CursorProperty =
AvaloniaProperty.Register(nameof(Cursor), null, true);
+ ///
+ /// Defines the property.
+ ///
+ public static readonly DirectProperty IsKeyboardFocusWithinProperty =
+ AvaloniaProperty.RegisterDirect(
+ nameof(IsKeyboardFocusWithin),
+ o => o.IsKeyboardFocusWithin);
+
///
/// Defines the property.
///
@@ -160,6 +168,7 @@ namespace Avalonia.Input
private bool _isEffectivelyEnabled = true;
private bool _isFocused;
+ private bool _isKeyboardFocusWithin;
private bool _isFocusVisible;
private bool _isPointerOver;
private GestureRecognizerCollection? _gestureRecognizers;
@@ -343,6 +352,15 @@ namespace Avalonia.Input
get { return GetValue(CursorProperty); }
set { SetValue(CursorProperty, value); }
}
+
+ ///
+ /// Gets a value indicating whether keyboard focus is anywhere within the element or its visual tree child elements.
+ ///
+ public bool IsKeyboardFocusWithin
+ {
+ get => _isKeyboardFocusWithin;
+ internal set => SetAndRaise(IsKeyboardFocusWithinProperty, ref _isKeyboardFocusWithin, value);
+ }
///
/// Gets a value indicating whether the control is focused.
@@ -544,6 +562,10 @@ namespace Avalonia.Input
{
UpdatePseudoClasses(null, change.NewValue.GetValueOrDefault());
}
+ else if (change.Property == IsKeyboardFocusWithinProperty)
+ {
+ PseudoClasses.Set(":focus-within", _isKeyboardFocusWithin);
+ }
}
///
diff --git a/src/Avalonia.Input/KeyGesture.cs b/src/Avalonia.Input/KeyGesture.cs
index aa6fcc8bff..e155666631 100644
--- a/src/Avalonia.Input/KeyGesture.cs
+++ b/src/Avalonia.Input/KeyGesture.cs
@@ -144,7 +144,10 @@ namespace Avalonia.Input
return s.ToString();
}
- public bool Matches(KeyEventArgs keyEvent) => ResolveNumPadOperationKey(keyEvent.Key) == Key && keyEvent.KeyModifiers == KeyModifiers;
+ public bool Matches(KeyEventArgs keyEvent) =>
+ keyEvent != null &&
+ keyEvent.KeyModifiers == KeyModifiers &&
+ ResolveNumPadOperationKey(keyEvent.Key) == ResolveNumPadOperationKey(Key);
// TODO: Move that to external key parser
private static Key ParseKey(string key)
diff --git a/src/Avalonia.Input/KeyboardDevice.cs b/src/Avalonia.Input/KeyboardDevice.cs
index 187670a26b..6f4cb7a35c 100644
--- a/src/Avalonia.Input/KeyboardDevice.cs
+++ b/src/Avalonia.Input/KeyboardDevice.cs
@@ -9,6 +9,7 @@ namespace Avalonia.Input
public class KeyboardDevice : IKeyboardDevice, INotifyPropertyChanged
{
private IInputElement? _focusedElement;
+ private IInputRoot? _focusedRoot;
public event PropertyChangedEventHandler? PropertyChanged;
@@ -28,10 +29,115 @@ namespace Avalonia.Input
private set
{
_focusedElement = value;
+
+ if (_focusedElement != null && _focusedElement.IsAttachedToVisualTree)
+ {
+ _focusedRoot = _focusedElement.VisualRoot as IInputRoot;
+ }
+ else
+ {
+ _focusedRoot = null;
+ }
+
RaisePropertyChanged();
}
}
+ private void ClearFocusWithinAncestors(IInputElement? element)
+ {
+ var el = element;
+
+ while (el != null)
+ {
+ if (el is InputElement ie)
+ {
+ ie.IsKeyboardFocusWithin = false;
+ }
+
+ el = (IInputElement)el.VisualParent;
+ }
+ }
+
+ private void ClearFocusWithin(IInputElement element, bool clearRoot)
+ {
+ foreach (var visual in element.VisualChildren)
+ {
+ if (visual is IInputElement el && el.IsKeyboardFocusWithin)
+ {
+ ClearFocusWithin(el, true);
+ break;
+ }
+ }
+
+ if (clearRoot)
+ {
+ if (element is InputElement ie)
+ {
+ ie.IsKeyboardFocusWithin = false;
+ }
+ }
+ }
+
+ private void SetIsFocusWithin(IInputElement? oldElement, IInputElement? newElement)
+ {
+ if (newElement == null && oldElement != null)
+ {
+ ClearFocusWithinAncestors(oldElement);
+ return;
+ }
+
+ IInputElement? branch = null;
+
+ var el = newElement;
+
+ while (el != null)
+ {
+ if (el.IsKeyboardFocusWithin)
+ {
+ branch = el;
+ break;
+ }
+
+ el = el.VisualParent as IInputElement;
+ }
+
+ el = oldElement;
+
+ if (el != null && branch != null)
+ {
+ ClearFocusWithin(branch, false);
+ }
+
+ el = newElement;
+
+ while (el != null && el != branch)
+ {
+ if (el is InputElement ie)
+ {
+ ie.IsKeyboardFocusWithin = true;
+ }
+
+ el = el.VisualParent as IInputElement;
+ }
+ }
+
+ private void ClearChildrenFocusWithin(IInputElement element, bool clearRoot)
+ {
+ foreach (var visual in element.VisualChildren)
+ {
+ if (visual is IInputElement el && el.IsKeyboardFocusWithin)
+ {
+ ClearChildrenFocusWithin(el, true);
+ break;
+ }
+ }
+
+ if (clearRoot && element is InputElement ie)
+ {
+ ie.IsKeyboardFocusWithin = false;
+ }
+ }
+
public void SetFocusedElement(
IInputElement? element,
NavigationMethod method,
@@ -40,6 +146,17 @@ namespace Avalonia.Input
if (element != FocusedElement)
{
var interactive = FocusedElement as IInteractive;
+
+ if (FocusedElement != null &&
+ (!FocusedElement.IsAttachedToVisualTree ||
+ _focusedRoot != element?.VisualRoot as IInputRoot) &&
+ _focusedRoot != null)
+ {
+ ClearChildrenFocusWithin(_focusedRoot, true);
+ }
+
+ SetIsFocusWithin(FocusedElement, element);
+
FocusedElement = element;
interactive?.RaiseEvent(new RoutedEventArgs
diff --git a/src/Avalonia.Input/MouseDevice.cs b/src/Avalonia.Input/MouseDevice.cs
index cec5029c18..5c63546f5d 100644
--- a/src/Avalonia.Input/MouseDevice.cs
+++ b/src/Avalonia.Input/MouseDevice.cs
@@ -19,6 +19,7 @@ namespace Avalonia.Input
private readonly Pointer _pointer;
private bool _disposed;
+ private PixelPoint? _position;
public MouseDevice(Pointer? pointer = null)
{
@@ -39,10 +40,11 @@ namespace Avalonia.Input
///
/// Gets the mouse position, in screen coordinates.
///
+ [Obsolete("Use events instead")]
public PixelPoint Position
{
- get;
- protected set;
+ get => _position ?? new PixelPoint(-1, -1);
+ protected set => _position = value;
}
///
@@ -91,7 +93,16 @@ namespace Avalonia.Input
public void SceneInvalidated(IInputRoot root, Rect rect)
{
- var clientPoint = root.PointToClient(Position);
+ // Pointer is outside of the target area
+ if (_position == null )
+ {
+ if (root.PointerOverElement != null)
+ ClearPointerOver(this, 0, root, PointerPointProperties.None, KeyModifiers.None);
+ return;
+ }
+
+
+ var clientPoint = root.PointToClient(_position.Value);
if (rect.Contains(clientPoint))
{
@@ -132,7 +143,7 @@ namespace Avalonia.Input
if(mouse._disposed)
return;
- Position = e.Root.PointToScreen(e.Position);
+ _position = e.Root.PointToScreen(e.Position);
var props = CreateProperties(e);
var keyModifiers = KeyModifiersUtils.ConvertToKey(e.InputModifiers);
switch (e.Type)
@@ -176,6 +187,7 @@ namespace Avalonia.Input
device = device ?? throw new ArgumentNullException(nameof(device));
root = root ?? throw new ArgumentNullException(nameof(root));
+ _position = null;
ClearPointerOver(this, timestamp, root, properties, inputModifiers);
}
diff --git a/src/Avalonia.Input/NavigationDirection.cs b/src/Avalonia.Input/NavigationDirection.cs
index 9b9af0b0a6..9bd6a8bb42 100644
--- a/src/Avalonia.Input/NavigationDirection.cs
+++ b/src/Avalonia.Input/NavigationDirection.cs
@@ -83,7 +83,7 @@ namespace Avalonia.Input
///
public static bool IsDirectional(this NavigationDirection direction)
{
- return direction > NavigationDirection.Previous ||
+ return direction > NavigationDirection.Previous &&
direction <= NavigationDirection.PageDown;
}
diff --git a/src/Avalonia.Layout/LayoutContext.cs b/src/Avalonia.Layout/LayoutContext.cs
index 45a8048ea2..dadce58c0c 100644
--- a/src/Avalonia.Layout/LayoutContext.cs
+++ b/src/Avalonia.Layout/LayoutContext.cs
@@ -14,7 +14,11 @@ namespace Avalonia.Layout
///
/// Gets or sets an object that represents the state of a layout.
///
- public object LayoutState { get; set; }
+ public object LayoutState
+ {
+ get => LayoutStateCore;
+ set => LayoutStateCore = value;
+ }
///
/// Implements the behavior of in a derived or custom LayoutContext.
diff --git a/src/Avalonia.Layout/Properties/AssemblyInfo.cs b/src/Avalonia.Layout/Properties/AssemblyInfo.cs
index 0a6a32493a..63afaa8e3e 100644
--- a/src/Avalonia.Layout/Properties/AssemblyInfo.cs
+++ b/src/Avalonia.Layout/Properties/AssemblyInfo.cs
@@ -1,7 +1,9 @@
using System.Runtime.CompilerServices;
using Avalonia.Metadata;
-
+#if SIGNED_BUILD
+[assembly: InternalsVisibleTo("Avalonia.Layout.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")]
+#else
[assembly: InternalsVisibleTo("Avalonia.Layout.UnitTests")]
-
+#endif
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Layout")]
diff --git a/src/Avalonia.Layout/StackLayout.cs b/src/Avalonia.Layout/StackLayout.cs
index 909c7bc7eb..4a93c8344f 100644
--- a/src/Avalonia.Layout/StackLayout.cs
+++ b/src/Avalonia.Layout/StackLayout.cs
@@ -249,8 +249,8 @@ namespace Avalonia.Layout
realizationWindowOffsetInExtent + _orientation.MajorSize(realizationRect) >= 0 && realizationWindowOffsetInExtent <= majorSize)
{
anchorIndex = (int) (realizationWindowOffsetInExtent / averageElementSize);
- offset = anchorIndex* averageElementSize + _orientation.MajorStart(lastExtent);
anchorIndex = Math.Max(0, Math.Min(itemsCount - 1, anchorIndex));
+ offset = anchorIndex* averageElementSize + _orientation.MajorStart(lastExtent);
}
}
diff --git a/src/Avalonia.MicroCom/Avalonia.MicroCom.csproj b/src/Avalonia.MicroCom/Avalonia.MicroCom.csproj
new file mode 100644
index 0000000000..b796e173c4
--- /dev/null
+++ b/src/Avalonia.MicroCom/Avalonia.MicroCom.csproj
@@ -0,0 +1,16 @@
+
+
+ netstandard2.0
+ true
+
+
+ <_AvaloniaPatchComInterop>true
+
+
+
+ false
+ all
+
+
+
+
diff --git a/src/Avalonia.MicroCom/IMicroComExceptionCallback.cs b/src/Avalonia.MicroCom/IMicroComExceptionCallback.cs
new file mode 100644
index 0000000000..08f20339ec
--- /dev/null
+++ b/src/Avalonia.MicroCom/IMicroComExceptionCallback.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace Avalonia.MicroCom
+{
+ public interface IMicroComExceptionCallback
+ {
+ void RaiseException(Exception e);
+ }
+}
diff --git a/src/Avalonia.MicroCom/IMicroComShadowContainer.cs b/src/Avalonia.MicroCom/IMicroComShadowContainer.cs
new file mode 100644
index 0000000000..a33d3a9811
--- /dev/null
+++ b/src/Avalonia.MicroCom/IMicroComShadowContainer.cs
@@ -0,0 +1,9 @@
+namespace Avalonia.MicroCom
+{
+ public interface IMicroComShadowContainer
+ {
+ MicroComShadow Shadow { get; set; }
+ void OnReferencedFromNative();
+ void OnUnreferencedFromNative();
+ }
+}
diff --git a/src/Avalonia.MicroCom/IUnknown.cs b/src/Avalonia.MicroCom/IUnknown.cs
new file mode 100644
index 0000000000..0dc4106423
--- /dev/null
+++ b/src/Avalonia.MicroCom/IUnknown.cs
@@ -0,0 +1,8 @@
+using System;
+
+namespace Avalonia.MicroCom
+{
+ public interface IUnknown : IDisposable
+ {
+ }
+}
diff --git a/src/Avalonia.MicroCom/LocalInterop.cs b/src/Avalonia.MicroCom/LocalInterop.cs
new file mode 100644
index 0000000000..785f4e03a5
--- /dev/null
+++ b/src/Avalonia.MicroCom/LocalInterop.cs
@@ -0,0 +1,17 @@
+using System;
+
+namespace Avalonia.MicroCom
+{
+ unsafe class LocalInterop
+ {
+ public static unsafe void CalliStdCallvoid(void* thisObject, void* methodPtr)
+ {
+ throw null;
+ }
+
+ public static unsafe int CalliStdCallint(void* thisObject, Guid* guid, IntPtr* ppv, void* methodPtr)
+ {
+ throw null;
+ }
+ }
+}
diff --git a/src/Avalonia.MicroCom/MicroComProxyBase.cs b/src/Avalonia.MicroCom/MicroComProxyBase.cs
new file mode 100644
index 0000000000..140af3e4ef
--- /dev/null
+++ b/src/Avalonia.MicroCom/MicroComProxyBase.cs
@@ -0,0 +1,110 @@
+using System;
+using System.Runtime.ConstrainedExecution;
+using System.Runtime.InteropServices;
+using System.Threading;
+
+namespace Avalonia.MicroCom
+{
+ public unsafe class MicroComProxyBase : CriticalFinalizerObject, IUnknown
+ {
+ private IntPtr _nativePointer;
+ private bool _ownsHandle;
+ private SynchronizationContext _synchronizationContext;
+
+ public IntPtr NativePointer
+ {
+ get
+ {
+ if (_nativePointer == IntPtr.Zero)
+ throw new ObjectDisposedException(this.GetType().FullName);
+ return _nativePointer;
+ }
+ }
+
+ public void*** PPV => (void***)NativePointer;
+
+ public MicroComProxyBase(IntPtr nativePointer, bool ownsHandle)
+ {
+ _nativePointer = nativePointer;
+ _ownsHandle = ownsHandle;
+ _synchronizationContext = SynchronizationContext.Current;
+ if(!_ownsHandle)
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual int VTableSize => 3;
+
+ public void AddRef()
+ {
+ LocalInterop.CalliStdCallvoid(PPV, (*PPV)[1]);
+ }
+
+ public void Release()
+ {
+ LocalInterop.CalliStdCallvoid(PPV, (*PPV)[2]);
+ }
+
+ public int QueryInterface(Guid guid, out IntPtr ppv)
+ {
+ IntPtr r = default;
+ var rv = LocalInterop.CalliStdCallint(PPV, &guid, &r, (*PPV)[0]);
+ ppv = r;
+ return rv;
+ }
+
+ public T QueryInterface() where T : IUnknown
+ {
+ var guid = MicroComRuntime.GetGuidFor(typeof(T));
+ var rv = QueryInterface(guid, out var ppv);
+ if (rv == 0)
+ return (T)MicroComRuntime.CreateProxyFor(typeof(T), ppv, true);
+ throw new COMException("QueryInterface failed", rv);
+ }
+
+ public bool IsDisposed => _nativePointer == IntPtr.Zero;
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if(_nativePointer == null)
+ return;
+ if (_ownsHandle)
+ {
+ Release();
+ _ownsHandle = false;
+ }
+ _nativePointer = IntPtr.Zero;
+ GC.SuppressFinalize(this);
+ }
+
+ public void Dispose() => Dispose(true);
+
+ public bool OwnsHandle => _ownsHandle;
+
+ public void EnsureOwned()
+ {
+ if (!_ownsHandle)
+ {
+ GC.ReRegisterForFinalize(true);
+ AddRef();
+ _ownsHandle = true;
+ }
+ }
+
+ private static readonly SendOrPostCallback _disposeDelegate = DisposeOnContext;
+
+ private static void DisposeOnContext(object state)
+ {
+ (state as MicroComProxyBase)?.Dispose(false);
+ }
+
+ ~MicroComProxyBase()
+ {
+ if(!_ownsHandle)
+ return;
+ if (_synchronizationContext == null)
+ Dispose();
+ else
+ _synchronizationContext.Post(_disposeDelegate, this);
+ }
+ }
+}
diff --git a/src/Avalonia.MicroCom/MicroComRuntime.cs b/src/Avalonia.MicroCom/MicroComRuntime.cs
new file mode 100644
index 0000000000..85507674d2
--- /dev/null
+++ b/src/Avalonia.MicroCom/MicroComRuntime.cs
@@ -0,0 +1,122 @@
+using System;
+using System.Collections.Concurrent;
+using System.Runtime.InteropServices;
+
+namespace Avalonia.MicroCom
+{
+ public static unsafe class MicroComRuntime
+ {
+ private static ConcurrentDictionary _vtables = new ConcurrentDictionary();
+
+ private static ConcurrentDictionary> _factories =
+ new ConcurrentDictionary>();
+ private static ConcurrentDictionary _guids = new ConcurrentDictionary();
+ private static ConcurrentDictionary _guidsToTypes = new ConcurrentDictionary();
+
+ static MicroComRuntime()
+ {
+ Register(typeof(IUnknown), new Guid("00000000-0000-0000-C000-000000000046"),
+ (ppv, owns) => new MicroComProxyBase(ppv, owns));
+ RegisterVTable(typeof(IUnknown), MicroComVtblBase.Vtable);
+ }
+
+ public static void RegisterVTable(Type t, IntPtr vtable)
+ {
+ _vtables[t] = vtable;
+ }
+
+ public static void Register(Type t, Guid guid, Func proxyFactory)
+ {
+ _factories[t] = proxyFactory;
+ _guids[t] = guid;
+ _guidsToTypes[guid] = t;
+ }
+
+ public static Guid GetGuidFor(Type type) => _guids[type];
+
+ public static T CreateProxyFor(void* pObject, bool ownsHandle) => (T)CreateProxyFor(typeof(T), new IntPtr(pObject), ownsHandle);
+ public static T CreateProxyFor(IntPtr pObject, bool ownsHandle) => (T)CreateProxyFor(typeof(T), pObject, ownsHandle);
+
+ public static object CreateProxyFor(Type type, IntPtr pObject, bool ownsHandle) => _factories[type](pObject, ownsHandle);
+
+ public static IntPtr GetNativeIntPtr(this T obj, bool owned = false) where T : IUnknown
+ => new IntPtr(GetNativePointer(obj, owned));
+ public static void* GetNativePointer(T obj, bool owned = false) where T : IUnknown
+ {
+ if (obj == null)
+ return null;
+ if (obj is MicroComProxyBase proxy)
+ {
+ if(owned)
+ proxy.AddRef();
+ return (void*)proxy.NativePointer;
+ }
+
+ if (obj is IMicroComShadowContainer container)
+ {
+ container.Shadow ??= new MicroComShadow(container);
+ void* ptr = null;
+ var res = container.Shadow.GetOrCreateNativePointer(typeof(T), &ptr);
+ if (res != 0)
+ throw new COMException(
+ "Unable to create native callable wrapper for type " + typeof(T) + " for instance of type " +
+ obj.GetType(),
+ res);
+ if (owned)
+ container.Shadow.AddRef((Ccw*)ptr);
+ return ptr;
+ }
+ throw new ArgumentException("Unable to get a native pointer for " + obj);
+ }
+
+ public static object GetObjectFromCcw(IntPtr ccw)
+ {
+ var ptr = (Ccw*)ccw;
+ var shadow = (MicroComShadow)GCHandle.FromIntPtr(ptr->GcShadowHandle).Target;
+ return shadow.Target;
+ }
+
+ public static bool TryGetTypeForGuid(Guid guid, out Type t) => _guidsToTypes.TryGetValue(guid, out t);
+
+ public static bool GetVtableFor(Type type, out IntPtr ptr) => _vtables.TryGetValue(type, out ptr);
+
+ public static void UnhandledException(object target, Exception e)
+ {
+ if (target is IMicroComExceptionCallback cb)
+ {
+ try
+ {
+ cb.RaiseException(e);
+ }
+ catch
+ {
+ // We've tried
+ }
+ }
+
+ }
+
+ public static T CloneReference(this T iface) where T : IUnknown
+ {
+ var proxy = (MicroComProxyBase)(object)iface;
+ var ownedPointer = GetNativePointer(iface, true);
+ return CreateProxyFor(ownedPointer, true);
+ }
+
+ public static T QueryInterface(this IUnknown unknown) where T : IUnknown
+ {
+ var proxy = (MicroComProxyBase)unknown;
+ return proxy.QueryInterface();
+ }
+
+ public static void UnsafeAddRef(this IUnknown unknown)
+ {
+ ((MicroComProxyBase)unknown).AddRef();
+ }
+
+ public static void UnsafeRelease(this IUnknown unknown)
+ {
+ ((MicroComProxyBase)unknown).Release();
+ }
+ }
+}
diff --git a/src/Avalonia.MicroCom/MicroComShadow.cs b/src/Avalonia.MicroCom/MicroComShadow.cs
new file mode 100644
index 0000000000..a6a0fd519e
--- /dev/null
+++ b/src/Avalonia.MicroCom/MicroComShadow.cs
@@ -0,0 +1,171 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Threading;
+
+namespace Avalonia.MicroCom
+{
+ public unsafe class MicroComShadow : IDisposable
+ {
+ private readonly object _lock = new object();
+ private readonly Dictionary _shadows = new Dictionary();
+ private readonly Dictionary _backShadows = new Dictionary();
+ private GCHandle? _handle;
+ private volatile int _refCount;
+ internal IMicroComShadowContainer Target { get; }
+ internal MicroComShadow(IMicroComShadowContainer target)
+ {
+ Target = target;
+ Target.Shadow = this;
+ }
+
+ internal int QueryInterface(Ccw* ccw, Guid* guid, void** ppv)
+ {
+ if (MicroComRuntime.TryGetTypeForGuid(*guid, out var type))
+ return QueryInterface(type, ppv);
+ else
+ return unchecked((int)0x80004002u);
+ }
+
+ internal int QueryInterface(Type type, void** ppv)
+ {
+ if (!type.IsInstanceOfType(Target))
+ return unchecked((int)0x80004002u);
+
+ var rv = GetOrCreateNativePointer(type, ppv);
+ if (rv == 0)
+ AddRef((Ccw*)*ppv);
+ return rv;
+ }
+
+ internal int GetOrCreateNativePointer(Type type, void** ppv)
+ {
+ if (!MicroComRuntime.GetVtableFor(type, out var vtable))
+ return unchecked((int)0x80004002u);
+ lock (_lock)
+ {
+
+ if (_shadows.TryGetValue(type, out var shadow))
+ {
+ var targetCcw = (Ccw*)shadow;
+ AddRef(targetCcw);
+ *ppv = targetCcw;
+ return 0;
+ }
+ else
+ {
+ var intPtr = Marshal.AllocHGlobal(Marshal.SizeOf());
+ var targetCcw = (Ccw*)intPtr;
+ *targetCcw = default;
+ targetCcw->RefCount = 0;
+ targetCcw->VTable = vtable;
+ if (_handle == null)
+ _handle = GCHandle.Alloc(this);
+ targetCcw->GcShadowHandle = GCHandle.ToIntPtr(_handle.Value);
+ _shadows[type] = intPtr;
+ _backShadows[intPtr] = type;
+ *ppv = targetCcw;
+
+ return 0;
+ }
+ }
+ }
+
+ internal int AddRef(Ccw* ccw)
+ {
+ if (Interlocked.Increment(ref _refCount) == 1)
+ {
+ try
+ {
+ Target.OnReferencedFromNative();
+ }
+ catch (Exception e)
+ {
+ MicroComRuntime.UnhandledException(Target, e);
+ }
+ }
+
+ return Interlocked.Increment(ref ccw->RefCount);
+ }
+
+ internal int Release(Ccw* ccw)
+ {
+ Interlocked.Decrement(ref _refCount);
+ var cnt = Interlocked.Decrement(ref ccw->RefCount);
+ if (cnt == 0)
+ return FreeCcw(ccw);
+
+ return cnt;
+ }
+
+ int FreeCcw(Ccw* ccw)
+ {
+ lock (_lock)
+ {
+ // Shadow got resurrected by a call to QueryInterface from another thread
+ if (ccw->RefCount != 0)
+ return ccw->RefCount;
+
+ var intPtr = new IntPtr(ccw);
+ var type = _backShadows[intPtr];
+ _backShadows.Remove(intPtr);
+ _shadows.Remove(type);
+ Marshal.FreeHGlobal(intPtr);
+ if (_shadows.Count == 0)
+ {
+ _handle?.Free();
+ _handle = null;
+ try
+ {
+ Target.OnUnreferencedFromNative();
+ }
+ catch(Exception e)
+ {
+ MicroComRuntime.UnhandledException(Target, e);
+ }
+ }
+ }
+
+ return 0;
+ }
+
+ /*
+ Needs to be called to support the following scenario:
+ 1) Object created
+ 2) Object passed to native code, shadow is created, CCW is created
+ 3) Native side has never called AddRef
+
+ In that case the GC handle to the shadow object is still alive
+ */
+
+ public void Dispose()
+ {
+ lock (_lock)
+ {
+ List toRemove = null;
+ foreach (var kv in _backShadows)
+ {
+ var ccw = (Ccw*)kv.Key;
+ if (ccw->RefCount == 0)
+ {
+ toRemove ??= new List();
+ toRemove.Add(kv.Key);
+ }
+ }
+
+ if(toRemove != null)
+ foreach (var intPtr in toRemove)
+ FreeCcw((Ccw*)intPtr);
+ }
+ }
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ struct Ccw
+ {
+ public IntPtr VTable;
+ public IntPtr GcShadowHandle;
+ public volatile int RefCount;
+ public MicroComShadow GetShadow() => (MicroComShadow)GCHandle.FromIntPtr(GcShadowHandle).Target;
+ }
+}
diff --git a/src/Avalonia.MicroCom/MicroComVtblBase.cs b/src/Avalonia.MicroCom/MicroComVtblBase.cs
new file mode 100644
index 0000000000..2f0607c0a8
--- /dev/null
+++ b/src/Avalonia.MicroCom/MicroComVtblBase.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+
+namespace Avalonia.MicroCom
+{
+ public unsafe class MicroComVtblBase
+ {
+ private List _methods = new List();
+ [UnmanagedFunctionPointerAttribute(CallingConvention.StdCall)]
+ private delegate int AddRefDelegate(Ccw* ccw);
+
+ [UnmanagedFunctionPointerAttribute(CallingConvention.StdCall)]
+ private delegate int QueryInterfaceDelegate(Ccw* ccw, Guid* guid, void** ppv);
+
+ public static IntPtr Vtable { get; } = new MicroComVtblBase().CreateVTable();
+ public MicroComVtblBase()
+ {
+ AddMethod((QueryInterfaceDelegate)QueryInterface);
+ AddMethod((AddRefDelegate)AddRef);
+ AddMethod((AddRefDelegate)Release);
+ }
+
+ protected void AddMethod(Delegate d)
+ {
+ GCHandle.Alloc(d);
+ _methods.Add(Marshal.GetFunctionPointerForDelegate(d));
+ }
+
+ protected unsafe IntPtr CreateVTable()
+ {
+ var ptr = (IntPtr*)Marshal.AllocHGlobal((IntPtr.Size + 1) * _methods.Count);
+ for (var c = 0; c < _methods.Count; c++)
+ ptr[c] = _methods[c];
+ return new IntPtr(ptr);
+ }
+
+ static int QueryInterface(Ccw* ccw, Guid* guid, void** ppv) => ccw->GetShadow().QueryInterface(ccw, guid, ppv);
+ static int AddRef(Ccw* ccw) => ccw->GetShadow().AddRef(ccw);
+ static int Release(Ccw* ccw) => ccw->GetShadow().Release(ccw);
+ }
+}
diff --git a/src/Avalonia.Native/.gitignore b/src/Avalonia.Native/.gitignore
index b1153e777c..b270c05962 100644
--- a/src/Avalonia.Native/.gitignore
+++ b/src/Avalonia.Native/.gitignore
@@ -1 +1,2 @@
Generated/*.cs
+*.Generated.cs
diff --git a/src/Avalonia.Native/Avalonia.Native.csproj b/src/Avalonia.Native/Avalonia.Native.csproj
index 49bd578290..3913484431 100644
--- a/src/Avalonia.Native/Avalonia.Native.csproj
+++ b/src/Avalonia.Native/Avalonia.Native.csproj
@@ -5,10 +5,7 @@
$(PackAvaloniaNative)
true
netstandard2.0
- /usr/bin/castxml
- /usr/local/bin/castxml
true
- false
@@ -21,11 +18,9 @@
-
-
-
-
+
-
\ No newline at end of file
+
+
diff --git a/src/Avalonia.Native/AvaloniaNativeMenuExporter.cs b/src/Avalonia.Native/AvaloniaNativeMenuExporter.cs
index 6d1b95b997..2e3408eca5 100644
--- a/src/Avalonia.Native/AvaloniaNativeMenuExporter.cs
+++ b/src/Avalonia.Native/AvaloniaNativeMenuExporter.cs
@@ -4,6 +4,7 @@ using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Controls.Platform;
using Avalonia.Dialogs;
using Avalonia.Native.Interop;
+using Avalonia.Native.Interop.Impl;
using Avalonia.Threading;
namespace Avalonia.Native
@@ -15,7 +16,7 @@ namespace Avalonia.Native
private bool _exported = false;
private IAvnWindow _nativeWindow;
private NativeMenu _menu;
- private IAvnMenu _nativeMenu;
+ private __MicroComIAvnMenuProxy _nativeMenu;
public AvaloniaNativeMenuExporter(IAvnWindow nativeWindow, IAvaloniaNativeFactory factory)
{
@@ -59,7 +60,7 @@ namespace Avalonia.Native
Header = "About Avalonia",
};
- aboutItem.Clicked += async (sender, e) =>
+ aboutItem.Click += async (sender, e) =>
{
var dialog = new AboutAvaloniaDialog();
@@ -135,7 +136,7 @@ namespace Avalonia.Native
if (_nativeMenu is null)
{
- _nativeMenu = IAvnMenu.Create(_factory);
+ _nativeMenu = (__MicroComIAvnMenuProxy)__MicroComIAvnMenuProxy.Create(_factory);
_nativeMenu.Initialise(this, appMenuHolder, "");
@@ -156,7 +157,7 @@ namespace Avalonia.Native
if (_nativeMenu is null)
{
- _nativeMenu = IAvnMenu.Create(_factory);
+ _nativeMenu = __MicroComIAvnMenuProxy.Create(_factory);
_nativeMenu.Initialise(this, menu, "");
diff --git a/src/Avalonia.Native/AvaloniaNativePlatform.cs b/src/Avalonia.Native/AvaloniaNativePlatform.cs
index e8b2f065c7..6ce55e17b3 100644
--- a/src/Avalonia.Native/AvaloniaNativePlatform.cs
+++ b/src/Avalonia.Native/AvaloniaNativePlatform.cs
@@ -4,6 +4,7 @@ using System.Security.Cryptography;
using Avalonia.Controls.Platform;
using Avalonia.Input;
using Avalonia.Input.Platform;
+using Avalonia.MicroCom;
using Avalonia.Native.Interop;
using Avalonia.OpenGL;
using Avalonia.Platform;
@@ -29,7 +30,7 @@ namespace Avalonia.Native
public static AvaloniaNativePlatform Initialize(IntPtr factory, AvaloniaNativePlatformOptions options)
{
- var result = new AvaloniaNativePlatform(new IAvaloniaNativeFactory(factory));
+ var result = new AvaloniaNativePlatform(MicroComRuntime.CreateProxyFor(factory, true));
result.DoInitialize(options);
return result;
@@ -65,10 +66,7 @@ namespace Avalonia.Native
{
if(!string.IsNullOrWhiteSpace(Application.Current.Name))
{
- using (var buffer = new Utf8Buffer(Application.Current.Name))
- {
- _factory.MacOptions.SetApplicationTitle(buffer.DangerousGetHandle());
- }
+ _factory.MacOptions.SetApplicationTitle(Application.Current.Name);
}
}
@@ -93,7 +91,7 @@ namespace Avalonia.Native
{
var macOpts = AvaloniaLocator.Current.GetService();
- _factory.MacOptions.ShowInDock = macOpts?.ShowInDock != false ? 1 : 0;
+ _factory.MacOptions.SetShowInDock(macOpts?.ShowInDock != false ? 1 : 0);
}
AvaloniaLocator.CurrentMutable
@@ -153,7 +151,7 @@ namespace Avalonia.Native
set
{
_showInDock = value;
- _opts.ShowInDock = value ? 1 : 0;
+ _opts.SetShowInDock(value ? 1 : 0);
}
}
}
diff --git a/src/Avalonia.Native/AvaloniaNativePlatformOpenGlInterface.cs b/src/Avalonia.Native/AvaloniaNativePlatformOpenGlInterface.cs
index dbe968b82f..3b3d8836fd 100644
--- a/src/Avalonia.Native/AvaloniaNativePlatformOpenGlInterface.cs
+++ b/src/Avalonia.Native/AvaloniaNativePlatformOpenGlInterface.cs
@@ -150,12 +150,12 @@ namespace Avalonia.Native
{
get
{
- var s = _session.GetPixelSize();
+ var s = _session.PixelSize;
return new PixelSize(s.Width, s.Height);
}
}
- public double Scaling => _session.GetScaling();
+ public double Scaling => _session.Scaling;
public bool IsYFlipped => true;
diff --git a/src/Avalonia.Native/AvnString.cs b/src/Avalonia.Native/AvnString.cs
index 11b1a33276..dcd473bae3 100644
--- a/src/Avalonia.Native/AvnString.cs
+++ b/src/Avalonia.Native/AvnString.cs
@@ -1,8 +1,22 @@
+using System;
using System.Runtime.InteropServices;
namespace Avalonia.Native.Interop
{
- unsafe partial class IAvnString
+ partial interface IAvnString
+ {
+ public string String { get; }
+ public byte[] Bytes { get; }
+ }
+
+ partial interface IAvnStringArray
+ {
+ string[] ToStringArray();
+ }
+}
+namespace Avalonia.Native.Interop.Impl
+{
+ unsafe partial class __MicroComIAvnStringProxy
{
private string _managed;
private byte[] _bytes;
@@ -16,7 +30,7 @@ namespace Avalonia.Native.Interop
var ptr = Pointer();
if (ptr == null)
return null;
- _managed = System.Text.Encoding.UTF8.GetString((byte*)ptr.ToPointer(), Length());
+ _managed = System.Text.Encoding.UTF8.GetString((byte*)ptr, Length());
}
return _managed;
@@ -30,7 +44,7 @@ namespace Avalonia.Native.Interop
if (_bytes == null)
{
_bytes = new byte[Length()];
- Marshal.Copy(Pointer(), _bytes, 0, _bytes.Length);
+ Marshal.Copy(new IntPtr(Pointer()), _bytes, 0, _bytes.Length);
}
return _bytes;
@@ -40,7 +54,7 @@ namespace Avalonia.Native.Interop
public override string ToString() => String;
}
- partial class IAvnStringArray
+ partial class __MicroComIAvnStringArrayProxy
{
public string[] ToStringArray()
{
diff --git a/src/Avalonia.Native/CallbackBase.cs b/src/Avalonia.Native/CallbackBase.cs
index 4cda358d0a..455ed4b159 100644
--- a/src/Avalonia.Native/CallbackBase.cs
+++ b/src/Avalonia.Native/CallbackBase.cs
@@ -1,44 +1,30 @@
using System;
using System.Runtime.ExceptionServices;
-using SharpGen.Runtime;
+using Avalonia.MicroCom;
using Avalonia.Platform;
namespace Avalonia.Native
{
- public class CallbackBase : SharpGen.Runtime.IUnknown, IExceptionCallback
+ public class CallbackBase : IUnknown, IMicroComShadowContainer, IMicroComExceptionCallback
{
- private uint _refCount;
- private bool _disposed;
private readonly object _lock = new object();
- private ShadowContainer _shadow;
+ private bool _referencedFromManaged = true;
+ private bool _referencedFromNative = false;
+ private bool _destroyed;
+
- public CallbackBase()
- {
- _refCount = 1;
- }
-
- public ShadowContainer Shadow
+ protected virtual void Destroyed()
{
- get => _shadow;
- set
- {
- lock (_lock)
- {
- if (_disposed && value != null)
- {
- throw new ObjectDisposedException("CallbackBase");
- }
- _shadow = value;
- }
- }
}
- public uint AddRef()
+ public void RaiseException(Exception e)
{
- lock (_lock)
+ if (AvaloniaLocator.Current.GetService() is PlatformThreadingInterface threadingInterface)
{
- return ++_refCount;
+ threadingInterface.TerminateNativeApp();
+
+ threadingInterface.DispatchException(ExceptionDispatchInfo.Capture(e));
}
}
@@ -46,43 +32,35 @@ namespace Avalonia.Native
{
lock (_lock)
{
- if (!_disposed)
- {
- _disposed = true;
- Release();
- }
+ _referencedFromManaged = false;
+ DestroyIfNeeded();
}
}
- public uint Release()
+ void DestroyIfNeeded()
{
- lock (_lock)
+ if(_destroyed)
+ return;
+ if (_referencedFromManaged == false && _referencedFromNative == false)
{
- _refCount--;
-
- if (_refCount == 0)
- {
- Shadow?.Dispose();
- Shadow = null;
- Destroyed();
- }
-
- return _refCount;
+ _destroyed = true;
+ Destroyed();
}
}
- protected virtual void Destroyed()
+ public MicroComShadow Shadow { get; set; }
+ public void OnReferencedFromNative()
{
-
+ lock (_lock)
+ _referencedFromNative = true;
}
- public void RaiseException(Exception e)
+ public void OnUnreferencedFromNative()
{
- if (AvaloniaLocator.Current.GetService() is PlatformThreadingInterface threadingInterface)
+ lock (_lock)
{
- threadingInterface.TerminateNativeApp();
-
- threadingInterface.DispatchException(ExceptionDispatchInfo.Capture(e));
+ _referencedFromNative = false;
+ DestroyIfNeeded();
}
}
}
diff --git a/src/Avalonia.Native/ClipboardImpl.cs b/src/Avalonia.Native/ClipboardImpl.cs
index 554e7a497a..4ee590516b 100644
--- a/src/Avalonia.Native/ClipboardImpl.cs
+++ b/src/Avalonia.Native/ClipboardImpl.cs
@@ -35,17 +35,12 @@ namespace Avalonia.Native
return Task.FromResult(text.String);
}
- public Task SetTextAsync(string text)
+ public unsafe Task SetTextAsync(string text)
{
_native.Clear();
- if (text != null)
- {
- using (var buffer = new Utf8Buffer(text))
- {
- _native.SetText(NSPasteboardTypeString, buffer.DangerousGetHandle());
- }
- }
+ if (text != null)
+ _native.SetText(NSPasteboardTypeString, text);
return Task.CompletedTask;
}
@@ -90,11 +85,10 @@ namespace Avalonia.Native
{
var o = data.Get(fmt);
if(o is string s)
- using (var b = new Utf8Buffer(s))
- _native.SetText(fmt, b.DangerousGetHandle());
+ _native.SetText(fmt, s);
else if(o is byte[] bytes)
fixed (byte* pbytes = bytes)
- _native.SetBytes(fmt, new IntPtr(pbytes), bytes.Length);
+ _native.SetBytes(fmt, pbytes, bytes.Length);
}
return Task.CompletedTask;
}
diff --git a/src/Avalonia.Native/DeferredFramebuffer.cs b/src/Avalonia.Native/DeferredFramebuffer.cs
index 8ea7b20b8c..950b6a3197 100644
--- a/src/Avalonia.Native/DeferredFramebuffer.cs
+++ b/src/Avalonia.Native/DeferredFramebuffer.cs
@@ -2,11 +2,10 @@
using System.Runtime.InteropServices;
using Avalonia.Native.Interop;
using Avalonia.Platform;
-using SharpGen.Runtime;
namespace Avalonia.Native
{
- public class DeferredFramebuffer : ILockedFramebuffer
+ internal unsafe class DeferredFramebuffer : ILockedFramebuffer
{
private readonly Func, bool> _lockWindow;
@@ -56,7 +55,7 @@ namespace Avalonia.Native
{
var fb = new AvnFramebuffer
{
- Data = Address,
+ Data = Address.ToPointer(),
Dpi = new AvnVector
{
X = Dpi.X,
@@ -70,7 +69,7 @@ namespace Avalonia.Native
using (var d = new Disposer(Address))
{
- win.ThreadSafeSetSwRenderedFrame(ref fb, d);
+ win.ThreadSafeSetSwRenderedFrame(&fb, d);
}
}))
{
diff --git a/src/Avalonia.Native/DoubleClickHelper.cs b/src/Avalonia.Native/DoubleClickHelper.cs
new file mode 100644
index 0000000000..7618d6976a
--- /dev/null
+++ b/src/Avalonia.Native/DoubleClickHelper.cs
@@ -0,0 +1,31 @@
+using Avalonia.Platform;
+
+namespace Avalonia.Native
+{
+ internal class DoubleClickHelper
+ {
+ private int _clickCount;
+ private Rect _lastClickRect;
+ private ulong _lastClickTime;
+
+ public bool IsDoubleClick(
+ ulong timestamp,
+ Point p)
+ {
+ var settings = AvaloniaLocator.Current.GetService();
+ var doubleClickTime = settings.DoubleClickTime.TotalMilliseconds;
+
+ if (!_lastClickRect.Contains(p) || timestamp - _lastClickTime > doubleClickTime)
+ {
+ _clickCount = 0;
+ }
+
+ ++_clickCount;
+ _lastClickTime = timestamp;
+ _lastClickRect = new Rect(p, new Size())
+ .Inflate(new Thickness(settings.DoubleClickSize.Width / 2, settings.DoubleClickSize.Height / 2));
+
+ return _clickCount == 2;
+ }
+ }
+}
diff --git a/src/Avalonia.Native/Extensions.cs b/src/Avalonia.Native/Extensions.cs
new file mode 100644
index 0000000000..c0d90f7a85
--- /dev/null
+++ b/src/Avalonia.Native/Extensions.cs
@@ -0,0 +1,8 @@
+namespace Avalonia.Native
+{
+ internal static class Extensions
+ {
+ public static int AsComBool(this bool b) => b ? 1 : 0;
+ public static bool FromComBool(this int b) => b != 0;
+ }
+}
diff --git a/src/Avalonia.Native/Generated/Enumerations.cs b/src/Avalonia.Native/Generated/Enumerations.cs
deleted file mode 100644
index 0b30ce50c0..0000000000
--- a/src/Avalonia.Native/Generated/Enumerations.cs
+++ /dev/null
@@ -1,628 +0,0 @@
-//
-
-namespace Avalonia.Native.Interop
-{
- ///
- /// No documentation.
- ///
- /// AvnDragDropEffects
- /// AvnDragDropEffects
- public enum AvnDragDropEffects : System.Int32
- {
- ///
- /// No documentation.
- ///
- /// None
- /// None
- None = unchecked ((System.Int32)(0)),
- ///
- /// No documentation.
- ///
- /// Copy
- /// Copy
- Copy = unchecked ((System.Int32)(1)),
- ///
- /// No documentation.
- ///
- /// Move
- /// Move
- Move = unchecked ((System.Int32)(2)),
- ///
- /// No documentation.
- ///
- /// Link
- /// Link
- Link = unchecked ((System.Int32)(4))}
-
- ///
- /// No documentation.
- ///
- /// AvnDragEventType
- /// AvnDragEventType
- public enum AvnDragEventType : System.Int32
- {
- ///
- /// No documentation.
- ///
- /// Enter
- /// Enter
- Enter = unchecked ((System.Int32)(0)),
- ///
- /// No documentation.
- ///
- /// Over
- /// Over
- Over = unchecked ((System.Int32)(1)),
- ///
- /// No documentation.
- ///
- /// Leave
- /// Leave
- Leave = unchecked ((System.Int32)(2)),
- ///
- /// No documentation.
- ///
- /// Drop
- /// Drop
- Drop = unchecked ((System.Int32)(3))}
-
- ///
- /// No documentation.
- ///
- /// AvnExtendClientAreaChromeHints
- /// AvnExtendClientAreaChromeHints
- public enum AvnExtendClientAreaChromeHints : System.Int32
- {
- ///
- /// No documentation.
- ///
- /// AvnNoChrome
- /// AvnNoChrome
- AvnNoChrome = unchecked ((System.Int32)(0)),
- ///
- /// No documentation.
- ///
- /// AvnSystemChrome
- /// AvnSystemChrome
- AvnSystemChrome = unchecked ((System.Int32)(1)),
- ///
- /// No documentation.
- ///
- /// AvnPreferSystemChrome
- /// AvnPreferSystemChrome
- AvnPreferSystemChrome = unchecked ((System.Int32)(2)),
- ///
- /// No documentation.
- ///
- /// AvnOSXThickTitleBar
- /// AvnOSXThickTitleBar
- AvnOSXThickTitleBar = unchecked ((System.Int32)(8)),
- ///
- /// No documentation.
- ///
- /// AvnDefaultChrome
- /// AvnDefaultChrome
- AvnDefaultChrome = unchecked ((System.Int32)(1))}
-
- ///
- /// No documentation.
- ///
- /// AvnInputModifiers
- /// AvnInputModifiers
- public enum AvnInputModifiers : System.Int32
- {
- ///
- /// No documentation.
- ///
- /// AvnInputModifiersNone
- /// AvnInputModifiersNone
- AvnInputModifiersNone = unchecked ((System.Int32)(0)),
- ///
- /// No documentation.
- ///
- /// Alt
- /// Alt
- Alt = unchecked ((System.Int32)(1)),
- ///
- /// No documentation.
- ///
- /// Control
- /// Control
- Control = unchecked ((System.Int32)(2)),
- ///
- /// No documentation.
- ///
- /// Shift
- /// Shift
- Shift = unchecked ((System.Int32)(4)),
- ///
- /// No documentation.
- ///
- /// Windows
- /// Windows
- Windows = unchecked ((System.Int32)(8)),
- ///
- /// No documentation.
- ///
- /// LeftMouseButton
- /// LeftMouseButton
- LeftMouseButton = unchecked ((System.Int32)(16)),
- ///
- /// No documentation.
- ///
- /// RightMouseButton
- /// RightMouseButton
- RightMouseButton = unchecked ((System.Int32)(32)),
- ///
- /// No documentation.
- ///
- /// MiddleMouseButton
- /// MiddleMouseButton
- MiddleMouseButton = unchecked ((System.Int32)(64)),
- ///
- /// No documentation.
- ///
- /// XButton1MouseButton
- /// XButton1MouseButton
- XButton1MouseButton = unchecked ((System.Int32)(128)),
- ///
- /// No documentation.
- ///
- /// XButton2MouseButton
- /// XButton2MouseButton
- XButton2MouseButton = unchecked ((System.Int32)(256))}
-
- ///
- /// No documentation.
- ///
- /// AvnMenuItemToggleType
- /// AvnMenuItemToggleType
- public enum AvnMenuItemToggleType : System.Int32
- {
- ///
- /// No documentation.
- ///
- /// None
- /// None
- None = unchecked ((System.Int32)(0)),
- ///
- /// No documentation.
- ///
- /// CheckMark
- /// CheckMark
- CheckMark = unchecked ((System.Int32)(1)),
- ///
- /// No documentation.
- ///
- /// Radio
- /// Radio
- Radio = unchecked ((System.Int32)(2))}
-
- ///
- /// No documentation.
- ///
- /// AvnPixelFormat
- /// AvnPixelFormat
- public enum AvnPixelFormat : System.Int32
- {
- ///
- /// No documentation.
- ///
- /// kAvnRgb565
- /// kAvnRgb565
- KAvnRgb565 = unchecked ((System.Int32)(0)),
- ///
- /// No documentation.
- ///
- /// kAvnRgba8888
- /// kAvnRgba8888
- KAvnRgba8888 = unchecked ((System.Int32)(1)),
- ///
- /// No documentation.
- ///
- /// kAvnBgra8888
- /// kAvnBgra8888
- KAvnBgra8888 = unchecked ((System.Int32)(2))}
-
- ///
- /// No documentation.
- ///
- /// AvnRawKeyEventType
- /// AvnRawKeyEventType
- public enum AvnRawKeyEventType : System.Int32
- {
- ///
- /// No documentation.
- ///
- /// KeyDown
- /// KeyDown
- KeyDown = unchecked ((System.Int32)(0)),
- ///
- /// No documentation.
- ///
- /// KeyUp
- /// KeyUp
- KeyUp = unchecked ((System.Int32)(1))}
-
- ///
- /// No documentation.
- ///
- /// AvnRawMouseEventType
- /// AvnRawMouseEventType
- public enum AvnRawMouseEventType : System.Int32
- {
- ///
- /// No documentation.
- ///
- /// LeaveWindow
- /// LeaveWindow
- LeaveWindow = unchecked ((System.Int32)(0)),
- ///
- /// No documentation.
- ///
- /// LeftButtonDown
- /// LeftButtonDown
- LeftButtonDown = unchecked ((System.Int32)(1)),
- ///
- /// No documentation.
- ///
- /// LeftButtonUp
- /// LeftButtonUp
- LeftButtonUp = unchecked ((System.Int32)(2)),
- ///
- /// No documentation.
- ///
- /// RightButtonDown
- /// RightButtonDown
- RightButtonDown = unchecked ((System.Int32)(3)),
- ///
- /// No documentation.
- ///
- /// RightButtonUp
- /// RightButtonUp
- RightButtonUp = unchecked ((System.Int32)(4)),
- ///
- /// No documentation.
- ///
- /// MiddleButtonDown
- /// MiddleButtonDown
- MiddleButtonDown = unchecked ((System.Int32)(5)),
- ///
- /// No documentation.
- ///
- /// MiddleButtonUp
- /// MiddleButtonUp
- MiddleButtonUp = unchecked ((System.Int32)(6)),
- ///
- /// No documentation.
- ///
- /// XButton1Down
- /// XButton1Down
- XButton1Down = unchecked ((System.Int32)(7)),
- ///
- /// No documentation.
- ///
- /// XButton1Up
- /// XButton1Up
- XButton1Up = unchecked ((System.Int32)(8)),
- ///
- /// No documentation.
- ///
- /// XButton2Down
- /// XButton2Down
- XButton2Down = unchecked ((System.Int32)(9)),
- ///
- /// No documentation.
- ///
- /// XButton2Up
- /// XButton2Up
- XButton2Up = unchecked ((System.Int32)(10)),
- ///
- /// No documentation.
- ///
- /// Move
- /// Move
- Move = unchecked ((System.Int32)(11)),
- ///
- /// No documentation.
- ///
- /// Wheel
- /// Wheel
- Wheel = unchecked ((System.Int32)(12)),
- ///
- /// No documentation.
- ///
- /// NonClientLeftButtonDown
- /// NonClientLeftButtonDown
- NonClientLeftButtonDown = unchecked ((System.Int32)(13)),
- ///
- /// No documentation.
- ///
- /// TouchBegin
- /// TouchBegin
- TouchBegin = unchecked ((System.Int32)(14)),
- ///
- /// No documentation.
- ///
- /// TouchUpdate
- /// TouchUpdate
- TouchUpdate = unchecked ((System.Int32)(15)),
- ///
- /// No documentation.
- ///
- /// TouchEnd
- /// TouchEnd
- TouchEnd = unchecked ((System.Int32)(16)),
- ///
- /// No documentation.
- ///
- /// TouchCancel
- /// TouchCancel
- TouchCancel = unchecked ((System.Int32)(17))}
-
- ///
- /// No documentation.
- ///
- /// AvnStandardCursorType
- /// AvnStandardCursorType
- public enum AvnStandardCursorType : System.Int32
- {
- ///
- /// No documentation.
- ///
- /// CursorArrow
- /// CursorArrow
- CursorArrow = unchecked ((System.Int32)(0)),
- ///
- /// No documentation.
- ///
- /// CursorIbeam
- /// CursorIbeam
- CursorIbeam = unchecked ((System.Int32)(1)),
- ///
- /// No documentation.
- ///
- /// CursorWait
- /// CursorWait
- CursorWait = unchecked ((System.Int32)(2)),
- ///
- /// No documentation.
- ///
- /// CursorCross
- /// CursorCross
- CursorCross = unchecked ((System.Int32)(3)),
- ///
- /// No documentation.
- ///
- /// CursorUpArrow
- /// CursorUpArrow
- CursorUpArrow = unchecked ((System.Int32)(4)),
- ///
- /// No documentation.
- ///
- /// CursorSizeWestEast
- /// CursorSizeWestEast
- CursorSizeWestEast = unchecked ((System.Int32)(5)),
- ///
- /// No documentation.
- ///
- /// CursorSizeNorthSouth
- /// CursorSizeNorthSouth
- CursorSizeNorthSouth = unchecked ((System.Int32)(6)),
- ///
- /// No documentation.
- ///
- /// CursorSizeAll
- /// CursorSizeAll
- CursorSizeAll = unchecked ((System.Int32)(7)),
- ///
- /// No documentation.
- ///
- /// CursorNo
- /// CursorNo
- CursorNo = unchecked ((System.Int32)(8)),
- ///
- /// No documentation.
- ///
- /// CursorHand
- /// CursorHand
- CursorHand = unchecked ((System.Int32)(9)),
- ///
- /// No documentation.
- ///
- /// CursorAppStarting
- /// CursorAppStarting
- CursorAppStarting = unchecked ((System.Int32)(10)),
- ///
- /// No documentation.
- ///
- /// CursorHelp
- /// CursorHelp
- CursorHelp = unchecked ((System.Int32)(11)),
- ///
- /// No documentation.
- ///
- /// CursorTopSide
- /// CursorTopSide
- CursorTopSide = unchecked ((System.Int32)(12)),
- ///
- /// No documentation.
- ///
- /// CursorBottomSize
- /// CursorBottomSize
- CursorBottomSize = unchecked ((System.Int32)(13)),
- ///
- /// No documentation.
- ///
- /// CursorLeftSide
- /// CursorLeftSide
- CursorLeftSide = unchecked ((System.Int32)(14)),
- ///
- /// No documentation.
- ///
- /// CursorRightSide
- /// CursorRightSide
- CursorRightSide = unchecked ((System.Int32)(15)),
- ///
- /// No documentation.
- ///
- /// CursorTopLeftCorner
- /// CursorTopLeftCorner
- CursorTopLeftCorner = unchecked ((System.Int32)(16)),
- ///
- /// No documentation.
- ///
- /// CursorTopRightCorner
- /// CursorTopRightCorner
- CursorTopRightCorner = unchecked ((System.Int32)(17)),
- ///
- /// No documentation.
- ///
- /// CursorBottomLeftCorner
- /// CursorBottomLeftCorner
- CursorBottomLeftCorner = unchecked ((System.Int32)(18)),
- ///
- /// No documentation.
- ///
- /// CursorBottomRightCorner
- /// CursorBottomRightCorner
- CursorBottomRightCorner = unchecked ((System.Int32)(19)),
- ///
- /// No documentation.
- ///
- /// CursorDragMove
- /// CursorDragMove
- CursorDragMove = unchecked ((System.Int32)(20)),
- ///
- /// No documentation.
- ///
- /// CursorDragCopy
- /// CursorDragCopy
- CursorDragCopy = unchecked ((System.Int32)(21)),
- ///
- /// No documentation.
- ///
- /// CursorDragLink
- /// CursorDragLink
- CursorDragLink = unchecked ((System.Int32)(22)),
- ///
- /// No documentation.
- ///
- /// CursorNone
- /// CursorNone
- CursorNone = unchecked ((System.Int32)(23))}
-
- ///
- /// No documentation.
- ///
- /// AvnWindowEdge
- /// AvnWindowEdge
- public enum AvnWindowEdge : System.Int32
- {
- ///
- /// No documentation.
- ///
- /// WindowEdgeNorthWest
- /// WindowEdgeNorthWest
- WindowEdgeNorthWest = unchecked ((System.Int32)(0)),
- ///
- /// No documentation.
- ///
- /// WindowEdgeNorth
- /// WindowEdgeNorth
- WindowEdgeNorth = unchecked ((System.Int32)(1)),
- ///
- /// No documentation.
- ///
- /// WindowEdgeNorthEast
- /// WindowEdgeNorthEast
- WindowEdgeNorthEast = unchecked ((System.Int32)(2)),
- ///
- /// No documentation.
- ///
- /// WindowEdgeWest
- /// WindowEdgeWest
- WindowEdgeWest = unchecked ((System.Int32)(3)),
- ///
- /// No documentation.
- ///
- /// WindowEdgeEast
- /// WindowEdgeEast
- WindowEdgeEast = unchecked ((System.Int32)(4)),
- ///
- /// No documentation.
- ///
- /// WindowEdgeSouthWest
- /// WindowEdgeSouthWest
- WindowEdgeSouthWest = unchecked ((System.Int32)(5)),
- ///
- /// No documentation.
- ///
- /// WindowEdgeSouth
- /// WindowEdgeSouth
- WindowEdgeSouth = unchecked ((System.Int32)(6)),
- ///
- /// No documentation.
- ///
- /// WindowEdgeSouthEast
- /// WindowEdgeSouthEast
- WindowEdgeSouthEast = unchecked ((System.Int32)(7))}
-
- ///
- /// No documentation.
- ///
- /// AvnWindowState
- /// AvnWindowState
- public enum AvnWindowState : System.Int32
- {
- ///
- /// No documentation.
- ///
- /// Normal
- /// Normal
- Normal = unchecked ((System.Int32)(0)),
- ///
- /// No documentation.
- ///
- /// Minimized
- /// Minimized
- Minimized = unchecked ((System.Int32)(1)),
- ///
- /// No documentation.
- ///
- /// Maximized
- /// Maximized
- Maximized = unchecked ((System.Int32)(2)),
- ///
- /// No documentation.
- ///
- /// FullScreen
- /// FullScreen
- FullScreen = unchecked ((System.Int32)(3))}
-
- ///
- /// No documentation.
- ///
- /// SystemDecorations
- /// SystemDecorations
- public enum SystemDecorations : System.Int32
- {
- ///
- /// No documentation.
- ///
- /// SystemDecorationsNone
- /// SystemDecorationsNone
- SystemDecorationsNone = unchecked ((System.Int32)(0)),
- ///
- /// No documentation.
- ///
- /// SystemDecorationsBorderOnly
- /// SystemDecorationsBorderOnly
- SystemDecorationsBorderOnly = unchecked ((System.Int32)(1)),
- ///
- /// No documentation.
- ///
- /// SystemDecorationsFull
- /// SystemDecorationsFull
- SystemDecorationsFull = unchecked ((System.Int32)(2))}
-}
\ No newline at end of file
diff --git a/src/Avalonia.Native/Generated/Functions.cs b/src/Avalonia.Native/Generated/Functions.cs
deleted file mode 100644
index 6ab648dc50..0000000000
--- a/src/Avalonia.Native/Generated/Functions.cs
+++ /dev/null
@@ -1,5 +0,0 @@
-//
-
-namespace Avalonia.Native.Interop
-{
-}
\ No newline at end of file
diff --git a/src/Avalonia.Native/Generated/Interfaces.cs b/src/Avalonia.Native/Generated/Interfaces.cs
deleted file mode 100644
index 161ada1e50..0000000000
--- a/src/Avalonia.Native/Generated/Interfaces.cs
+++ /dev/null
@@ -1,3092 +0,0 @@
-//
-
-namespace Avalonia.Native.Interop
-{
- [System.Runtime.InteropServices.GuidAttribute("2e2cda0a-9ae5-4f1b-8e20-081a04279f01")]
- public partial class IAvaloniaNativeFactory : SharpGen.Runtime.ComObject
- {
- public IAvaloniaNativeFactory(System.IntPtr nativePtr): base (nativePtr)
- {
- }
-
- public static explicit operator IAvaloniaNativeFactory(System.IntPtr nativePtr) => nativePtr == System.IntPtr.Zero ? null : new IAvaloniaNativeFactory(nativePtr);
- ///
- /// No documentation.
- ///
- /// GetMacOptions
- /// GetMacOptions
- public Avalonia.Native.Interop.IAvnMacOptions MacOptions
- {
- get => GetMacOptions();
- }
-
- ///
- /// No documentation.
- ///
- /// SetAppMenu
- /// SetAppMenu
- public Avalonia.Native.Interop.IAvnMenu AppMenu
- {
- set => SetAppMenu(value);
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvaloniaNativeFactory::Initialize([In] IAvnGCHandleDeallocatorCallback* deallocator)
- /// IAvaloniaNativeFactory::Initialize
- public unsafe void Initialize(Avalonia.Native.Interop.IAvnGCHandleDeallocatorCallback deallocator)
- {
- System.IntPtr deallocator_ = System.IntPtr.Zero;
- SharpGen.Runtime.Result __result__;
- deallocator_ = SharpGen.Runtime.CppObject.ToCallbackPtr(deallocator);
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, (void *)deallocator_, (*(void ***)this._nativePointer)[3]);
- System.GC.KeepAlive(deallocator);
- __result__.CheckError();
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// IAvnMacOptions* IAvaloniaNativeFactory::GetMacOptions()
- /// IAvaloniaNativeFactory::GetMacOptions
- internal unsafe Avalonia.Native.Interop.IAvnMacOptions GetMacOptions()
- {
- Avalonia.Native.Interop.IAvnMacOptions __result__;
- System.IntPtr __result__native = System.IntPtr.Zero;
- __result__native = Avalonia.Native.LocalInterop.CalliThisCallSystemIntPtr(this._nativePointer, (*(void ***)this._nativePointer)[4]);
- if (__result__native != System.IntPtr.Zero)
- __result__ = new Avalonia.Native.Interop.IAvnMacOptions(__result__native);
- else
- __result__ = null;
- return __result__;
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvaloniaNativeFactory::CreateWindow([In] IAvnWindowEvents* cb,[In] IAvnGlContext* gl,[In] IAvnWindow** ppv)
- /// IAvaloniaNativeFactory::CreateWindow
- public unsafe Avalonia.Native.Interop.IAvnWindow CreateWindow(Avalonia.Native.Interop.IAvnWindowEvents cb, Avalonia.Native.Interop.IAvnGlContext gl)
- {
- System.IntPtr cb_ = System.IntPtr.Zero;
- System.IntPtr gl_ = System.IntPtr.Zero;
- Avalonia.Native.Interop.IAvnWindow vOut;
- System.IntPtr vOut_ = System.IntPtr.Zero;
- SharpGen.Runtime.Result __result__;
- cb_ = SharpGen.Runtime.CppObject.ToCallbackPtr(cb);
- gl_ = SharpGen.Runtime.CppObject.ToCallbackPtr(gl);
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, (void *)cb_, (void *)gl_, &vOut_, (*(void ***)this._nativePointer)[5]);
- if (vOut_ != System.IntPtr.Zero)
- vOut = new Avalonia.Native.Interop.IAvnWindow(vOut_);
- else
- vOut = null;
- System.GC.KeepAlive(cb);
- System.GC.KeepAlive(gl);
- __result__.CheckError();
- return vOut;
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvaloniaNativeFactory::CreatePopup([In] IAvnWindowEvents* cb,[In] IAvnGlContext* gl,[In] IAvnPopup** ppv)
- /// IAvaloniaNativeFactory::CreatePopup
- public unsafe Avalonia.Native.Interop.IAvnPopup CreatePopup(Avalonia.Native.Interop.IAvnWindowEvents cb, Avalonia.Native.Interop.IAvnGlContext gl)
- {
- System.IntPtr cb_ = System.IntPtr.Zero;
- System.IntPtr gl_ = System.IntPtr.Zero;
- Avalonia.Native.Interop.IAvnPopup vOut;
- System.IntPtr vOut_ = System.IntPtr.Zero;
- SharpGen.Runtime.Result __result__;
- cb_ = SharpGen.Runtime.CppObject.ToCallbackPtr(cb);
- gl_ = SharpGen.Runtime.CppObject.ToCallbackPtr(gl);
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, (void *)cb_, (void *)gl_, &vOut_, (*(void ***)this._nativePointer)[6]);
- if (vOut_ != System.IntPtr.Zero)
- vOut = new Avalonia.Native.Interop.IAvnPopup(vOut_);
- else
- vOut = null;
- System.GC.KeepAlive(cb);
- System.GC.KeepAlive(gl);
- __result__.CheckError();
- return vOut;
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// HRESULT IAvaloniaNativeFactory::CreatePlatformThreadingInterface([In] IAvnPlatformThreadingInterface** ppv)
- /// IAvaloniaNativeFactory::CreatePlatformThreadingInterface
- public unsafe Avalonia.Native.Interop.IAvnPlatformThreadingInterface CreatePlatformThreadingInterface()
- {
- Avalonia.Native.Interop.IAvnPlatformThreadingInterface vOut;
- System.IntPtr vOut_ = System.IntPtr.Zero;
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, &vOut_, (*(void ***)this._nativePointer)[7]);
- if (vOut_ != System.IntPtr.Zero)
- vOut = new Avalonia.Native.Interop.IAvnPlatformThreadingInterface(vOut_);
- else
- vOut = null;
- __result__.CheckError();
- return vOut;
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// HRESULT IAvaloniaNativeFactory::CreateSystemDialogs([In] IAvnSystemDialogs** ppv)
- /// IAvaloniaNativeFactory::CreateSystemDialogs
- public unsafe Avalonia.Native.Interop.IAvnSystemDialogs CreateSystemDialogs()
- {
- Avalonia.Native.Interop.IAvnSystemDialogs vOut;
- System.IntPtr vOut_ = System.IntPtr.Zero;
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, &vOut_, (*(void ***)this._nativePointer)[8]);
- if (vOut_ != System.IntPtr.Zero)
- vOut = new Avalonia.Native.Interop.IAvnSystemDialogs(vOut_);
- else
- vOut = null;
- __result__.CheckError();
- return vOut;
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// HRESULT IAvaloniaNativeFactory::CreateScreens([In] IAvnScreens** ppv)
- /// IAvaloniaNativeFactory::CreateScreens
- public unsafe Avalonia.Native.Interop.IAvnScreens CreateScreens()
- {
- Avalonia.Native.Interop.IAvnScreens vOut;
- System.IntPtr vOut_ = System.IntPtr.Zero;
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, &vOut_, (*(void ***)this._nativePointer)[9]);
- if (vOut_ != System.IntPtr.Zero)
- vOut = new Avalonia.Native.Interop.IAvnScreens(vOut_);
- else
- vOut = null;
- __result__.CheckError();
- return vOut;
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// HRESULT IAvaloniaNativeFactory::CreateClipboard([In] IAvnClipboard** ppv)
- /// IAvaloniaNativeFactory::CreateClipboard
- public unsafe Avalonia.Native.Interop.IAvnClipboard CreateClipboard()
- {
- Avalonia.Native.Interop.IAvnClipboard vOut;
- System.IntPtr vOut_ = System.IntPtr.Zero;
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, &vOut_, (*(void ***)this._nativePointer)[10]);
- if (vOut_ != System.IntPtr.Zero)
- vOut = new Avalonia.Native.Interop.IAvnClipboard(vOut_);
- else
- vOut = null;
- __result__.CheckError();
- return vOut;
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// HRESULT IAvaloniaNativeFactory::CreateDndClipboard([In] IAvnClipboard** ppv)
- /// IAvaloniaNativeFactory::CreateDndClipboard
- public unsafe Avalonia.Native.Interop.IAvnClipboard CreateDndClipboard()
- {
- Avalonia.Native.Interop.IAvnClipboard vOut;
- System.IntPtr vOut_ = System.IntPtr.Zero;
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, &vOut_, (*(void ***)this._nativePointer)[11]);
- if (vOut_ != System.IntPtr.Zero)
- vOut = new Avalonia.Native.Interop.IAvnClipboard(vOut_);
- else
- vOut = null;
- __result__.CheckError();
- return vOut;
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// HRESULT IAvaloniaNativeFactory::CreateCursorFactory([In] IAvnCursorFactory** ppv)
- /// IAvaloniaNativeFactory::CreateCursorFactory
- public unsafe Avalonia.Native.Interop.IAvnCursorFactory CreateCursorFactory()
- {
- Avalonia.Native.Interop.IAvnCursorFactory vOut;
- System.IntPtr vOut_ = System.IntPtr.Zero;
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, &vOut_, (*(void ***)this._nativePointer)[12]);
- if (vOut_ != System.IntPtr.Zero)
- vOut = new Avalonia.Native.Interop.IAvnCursorFactory(vOut_);
- else
- vOut = null;
- __result__.CheckError();
- return vOut;
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// HRESULT IAvaloniaNativeFactory::ObtainGlDisplay([In] IAvnGlDisplay** ppv)
- /// IAvaloniaNativeFactory::ObtainGlDisplay
- public unsafe Avalonia.Native.Interop.IAvnGlDisplay ObtainGlDisplay()
- {
- Avalonia.Native.Interop.IAvnGlDisplay vOut;
- System.IntPtr vOut_ = System.IntPtr.Zero;
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, &vOut_, (*(void ***)this._nativePointer)[13]);
- if (vOut_ != System.IntPtr.Zero)
- vOut = new Avalonia.Native.Interop.IAvnGlDisplay(vOut_);
- else
- vOut = null;
- __result__.CheckError();
- return vOut;
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvaloniaNativeFactory::SetAppMenu([In] IAvnMenu* menu)
- /// IAvaloniaNativeFactory::SetAppMenu
- internal unsafe void SetAppMenu(Avalonia.Native.Interop.IAvnMenu menu)
- {
- System.IntPtr menu_ = System.IntPtr.Zero;
- SharpGen.Runtime.Result __result__;
- menu_ = SharpGen.Runtime.CppObject.ToCallbackPtr(menu);
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, (void *)menu_, (*(void ***)this._nativePointer)[14]);
- System.GC.KeepAlive(menu);
- __result__.CheckError();
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvaloniaNativeFactory::CreateMenu([In] IAvnMenuEvents* cb,[In] IAvnMenu** ppv)
- /// IAvaloniaNativeFactory::CreateMenu
- public unsafe Avalonia.Native.Interop.IAvnMenu CreateMenu(Avalonia.Native.Interop.IAvnMenuEvents cb)
- {
- System.IntPtr cb_ = System.IntPtr.Zero;
- Avalonia.Native.Interop.IAvnMenu vOut;
- System.IntPtr vOut_ = System.IntPtr.Zero;
- SharpGen.Runtime.Result __result__;
- cb_ = SharpGen.Runtime.CppObject.ToCallbackPtr(cb);
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, (void *)cb_, &vOut_, (*(void ***)this._nativePointer)[15]);
- if (vOut_ != System.IntPtr.Zero)
- vOut = new Avalonia.Native.Interop.IAvnMenu(vOut_);
- else
- vOut = null;
- System.GC.KeepAlive(cb);
- __result__.CheckError();
- return vOut;
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// HRESULT IAvaloniaNativeFactory::CreateMenuItem([In] IAvnMenuItem** ppv)
- /// IAvaloniaNativeFactory::CreateMenuItem
- public unsafe Avalonia.Native.Interop.IAvnMenuItem CreateMenuItem()
- {
- Avalonia.Native.Interop.IAvnMenuItem vOut;
- System.IntPtr vOut_ = System.IntPtr.Zero;
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, &vOut_, (*(void ***)this._nativePointer)[16]);
- if (vOut_ != System.IntPtr.Zero)
- vOut = new Avalonia.Native.Interop.IAvnMenuItem(vOut_);
- else
- vOut = null;
- __result__.CheckError();
- return vOut;
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// HRESULT IAvaloniaNativeFactory::CreateMenuItemSeperator([In] IAvnMenuItem** ppv)
- /// IAvaloniaNativeFactory::CreateMenuItemSeperator
- public unsafe Avalonia.Native.Interop.IAvnMenuItem CreateMenuItemSeperator()
- {
- Avalonia.Native.Interop.IAvnMenuItem vOut;
- System.IntPtr vOut_ = System.IntPtr.Zero;
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, &vOut_, (*(void ***)this._nativePointer)[17]);
- if (vOut_ != System.IntPtr.Zero)
- vOut = new Avalonia.Native.Interop.IAvnMenuItem(vOut_);
- else
- vOut = null;
- __result__.CheckError();
- return vOut;
- }
- }
-
- class IAvnActionCallbackShadow : SharpGen.Runtime.ComObjectShadow
- {
- protected unsafe class IAvnActionCallbackVtbl : SharpGen.Runtime.ComObjectShadow.ComObjectVtbl
- {
- public IAvnActionCallbackVtbl(int numberOfCallbackMethods): base (numberOfCallbackMethods + 1)
- {
- AddMethod(new RunDelegate(Run));
- }
-
- [System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(System.Runtime.InteropServices.CallingConvention.ThisCall)]
- private delegate void RunDelegate(System.IntPtr thisObject);
- private static unsafe void Run(System.IntPtr thisObject)
- {
- try
- {
- IAvnActionCallback @this = (IAvnActionCallback)ToShadow(thisObject).Callback;
- @this.Run();
- }
- catch (System.Exception __exception__)
- {
- IAvnActionCallback @this = (IAvnActionCallback)ToShadow(thisObject).Callback;
- (@this as SharpGen.Runtime.IExceptionCallback)?.RaiseException(__exception__);
- }
- }
- }
-
- protected override SharpGen.Runtime.CppObjectVtbl Vtbl
- {
- get;
- }
-
- = new Avalonia.Native.Interop.IAvnActionCallbackShadow.IAvnActionCallbackVtbl(0);
- }
-
- [System.Runtime.InteropServices.GuidAttribute("2e2cda0a-9ae5-4f1b-8e20-081a04279f08"), SharpGen.Runtime.ShadowAttribute(typeof (Avalonia.Native.Interop.IAvnActionCallbackShadow))]
- public partial interface IAvnActionCallback : SharpGen.Runtime.IUnknown
- {
- void Run();
- }
-
- [System.Runtime.InteropServices.GuidAttribute("2e2cda0a-9ae5-4f1b-8e20-081a04279f0f")]
- public partial class IAvnClipboard : SharpGen.Runtime.ComObject
- {
- public IAvnClipboard(System.IntPtr nativePtr): base (nativePtr)
- {
- }
-
- public static explicit operator IAvnClipboard(System.IntPtr nativePtr) => nativePtr == System.IntPtr.Zero ? null : new IAvnClipboard(nativePtr);
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnClipboard::GetText([In] char* type,[In] IAvnString** ppv)
- /// IAvnClipboard::GetText
- public unsafe Avalonia.Native.Interop.IAvnString GetText(System.String type)
- {
- System.IntPtr type_;
- Avalonia.Native.Interop.IAvnString vOut;
- System.IntPtr vOut_ = System.IntPtr.Zero;
- SharpGen.Runtime.Result __result__;
- type_ = System.Runtime.InteropServices.Marshal.StringToHGlobalAnsi(type);
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, (void *)type_, &vOut_, (*(void ***)this._nativePointer)[3]);
- if (vOut_ != System.IntPtr.Zero)
- vOut = new Avalonia.Native.Interop.IAvnString(vOut_);
- else
- vOut = null;
- System.Runtime.InteropServices.Marshal.FreeHGlobal(type_);
- __result__.CheckError();
- return vOut;
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnClipboard::SetText([In] char* type,[In] void* utf8Text)
- /// IAvnClipboard::SetText
- public unsafe void SetText(System.String type, System.IntPtr utf8Text)
- {
- System.IntPtr type_;
- SharpGen.Runtime.Result __result__;
- type_ = System.Runtime.InteropServices.Marshal.StringToHGlobalAnsi(type);
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, (void *)type_, (void *)utf8Text, (*(void ***)this._nativePointer)[4]);
- System.Runtime.InteropServices.Marshal.FreeHGlobal(type_);
- __result__.CheckError();
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// HRESULT IAvnClipboard::ObtainFormats([In] IAvnStringArray** ppv)
- /// IAvnClipboard::ObtainFormats
- public unsafe Avalonia.Native.Interop.IAvnStringArray ObtainFormats()
- {
- Avalonia.Native.Interop.IAvnStringArray vOut;
- System.IntPtr vOut_ = System.IntPtr.Zero;
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, &vOut_, (*(void ***)this._nativePointer)[5]);
- if (vOut_ != System.IntPtr.Zero)
- vOut = new Avalonia.Native.Interop.IAvnStringArray(vOut_);
- else
- vOut = null;
- __result__.CheckError();
- return vOut;
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnClipboard::GetStrings([In] char* type,[In] IAvnStringArray** ppv)
- /// IAvnClipboard::GetStrings
- public unsafe Avalonia.Native.Interop.IAvnStringArray GetStrings(System.String type)
- {
- System.IntPtr type_;
- Avalonia.Native.Interop.IAvnStringArray vOut;
- System.IntPtr vOut_ = System.IntPtr.Zero;
- SharpGen.Runtime.Result __result__;
- type_ = System.Runtime.InteropServices.Marshal.StringToHGlobalAnsi(type);
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, (void *)type_, &vOut_, (*(void ***)this._nativePointer)[6]);
- if (vOut_ != System.IntPtr.Zero)
- vOut = new Avalonia.Native.Interop.IAvnStringArray(vOut_);
- else
- vOut = null;
- System.Runtime.InteropServices.Marshal.FreeHGlobal(type_);
- __result__.CheckError();
- return vOut;
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnClipboard::SetBytes([In] char* type,[In] void* utf8Text,[In] int len)
- /// IAvnClipboard::SetBytes
- public unsafe void SetBytes(System.String type, System.IntPtr utf8Text, System.Int32 len)
- {
- System.IntPtr type_;
- SharpGen.Runtime.Result __result__;
- type_ = System.Runtime.InteropServices.Marshal.StringToHGlobalAnsi(type);
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, (void *)type_, (void *)utf8Text, len, (*(void ***)this._nativePointer)[7]);
- System.Runtime.InteropServices.Marshal.FreeHGlobal(type_);
- __result__.CheckError();
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnClipboard::GetBytes([In] char* type,[In] IAvnString** ppv)
- /// IAvnClipboard::GetBytes
- public unsafe Avalonia.Native.Interop.IAvnString GetBytes(System.String type)
- {
- System.IntPtr type_;
- Avalonia.Native.Interop.IAvnString vOut;
- System.IntPtr vOut_ = System.IntPtr.Zero;
- SharpGen.Runtime.Result __result__;
- type_ = System.Runtime.InteropServices.Marshal.StringToHGlobalAnsi(type);
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, (void *)type_, &vOut_, (*(void ***)this._nativePointer)[8]);
- if (vOut_ != System.IntPtr.Zero)
- vOut = new Avalonia.Native.Interop.IAvnString(vOut_);
- else
- vOut = null;
- System.Runtime.InteropServices.Marshal.FreeHGlobal(type_);
- __result__.CheckError();
- return vOut;
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// HRESULT IAvnClipboard::Clear()
- /// IAvnClipboard::Clear
- public unsafe void Clear()
- {
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, (*(void ***)this._nativePointer)[9]);
- __result__.CheckError();
- }
- }
-
- [System.Runtime.InteropServices.GuidAttribute("2e2cda0a-9ae5-4f1b-8e20-081a04279f10")]
- public partial class IAvnCursor : SharpGen.Runtime.ComObject
- {
- public IAvnCursor(System.IntPtr nativePtr): base (nativePtr)
- {
- }
-
- public static explicit operator IAvnCursor(System.IntPtr nativePtr) => nativePtr == System.IntPtr.Zero ? null : new IAvnCursor(nativePtr);
- }
-
- [System.Runtime.InteropServices.GuidAttribute("2e2cda0a-9ae5-4f1b-8e20-081a04279f11")]
- public partial class IAvnCursorFactory : SharpGen.Runtime.ComObject
- {
- public IAvnCursorFactory(System.IntPtr nativePtr): base (nativePtr)
- {
- }
-
- public static explicit operator IAvnCursorFactory(System.IntPtr nativePtr) => nativePtr == System.IntPtr.Zero ? null : new IAvnCursorFactory(nativePtr);
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnCursorFactory::GetCursor([In] AvnStandardCursorType cursorType,[Out] IAvnCursor** retOut)
- /// IAvnCursorFactory::GetCursor
- public unsafe Avalonia.Native.Interop.IAvnCursor GetCursor(Avalonia.Native.Interop.AvnStandardCursorType cursorType)
- {
- Avalonia.Native.Interop.IAvnCursor retOut;
- System.IntPtr retOut_ = System.IntPtr.Zero;
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, unchecked ((System.Int32)cursorType), &retOut_, (*(void ***)this._nativePointer)[3]);
- if (retOut_ != System.IntPtr.Zero)
- retOut = new Avalonia.Native.Interop.IAvnCursor(retOut_);
- else
- retOut = null;
- __result__.CheckError();
- return retOut;
- }
- }
-
- class IAvnDndResultCallbackShadow : SharpGen.Runtime.ComObjectShadow
- {
- protected unsafe class IAvnDndResultCallbackVtbl : SharpGen.Runtime.ComObjectShadow.ComObjectVtbl
- {
- public IAvnDndResultCallbackVtbl(int numberOfCallbackMethods): base (numberOfCallbackMethods + 1)
- {
- AddMethod(new OnDragAndDropCompleteDelegate(OnDragAndDropComplete));
- }
-
- [System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(System.Runtime.InteropServices.CallingConvention.ThisCall)]
- private delegate void OnDragAndDropCompleteDelegate(System.IntPtr thisObject, int arg0);
- private static unsafe void OnDragAndDropComplete(System.IntPtr thisObject, int param0)
- {
- try
- {
- Avalonia.Native.Interop.AvnDragDropEffects effecct = default (Avalonia.Native.Interop.AvnDragDropEffects);
- effecct = (Avalonia.Native.Interop.AvnDragDropEffects)param0;
- IAvnDndResultCallback @this = (IAvnDndResultCallback)ToShadow(thisObject).Callback;
- @this.OnDragAndDropComplete(effecct);
- }
- catch (System.Exception __exception__)
- {
- IAvnDndResultCallback @this = (IAvnDndResultCallback)ToShadow(thisObject).Callback;
- (@this as SharpGen.Runtime.IExceptionCallback)?.RaiseException(__exception__);
- }
- }
- }
-
- protected override SharpGen.Runtime.CppObjectVtbl Vtbl
- {
- get;
- }
-
- = new Avalonia.Native.Interop.IAvnDndResultCallbackShadow.IAvnDndResultCallbackVtbl(0);
- }
-
- [System.Runtime.InteropServices.GuidAttribute("2e2cda0a-9ae5-4f1b-8e20-081a04279f21"), SharpGen.Runtime.ShadowAttribute(typeof (Avalonia.Native.Interop.IAvnDndResultCallbackShadow))]
- public partial interface IAvnDndResultCallback : SharpGen.Runtime.IUnknown
- {
- void OnDragAndDropComplete(Avalonia.Native.Interop.AvnDragDropEffects effecct);
- }
-
- class IAvnGCHandleDeallocatorCallbackShadow : SharpGen.Runtime.ComObjectShadow
- {
- protected unsafe class IAvnGCHandleDeallocatorCallbackVtbl : SharpGen.Runtime.ComObjectShadow.ComObjectVtbl
- {
- public IAvnGCHandleDeallocatorCallbackVtbl(int numberOfCallbackMethods): base (numberOfCallbackMethods + 1)
- {
- AddMethod(new FreeGCHandleDelegate(FreeGCHandle));
- }
-
- [System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(System.Runtime.InteropServices.CallingConvention.ThisCall)]
- private delegate void FreeGCHandleDelegate(System.IntPtr thisObject, void *arg0);
- private static unsafe void FreeGCHandle(System.IntPtr thisObject, void *param0)
- {
- try
- {
- System.IntPtr handle = default (System.IntPtr);
- handle = (System.IntPtr)param0;
- IAvnGCHandleDeallocatorCallback @this = (IAvnGCHandleDeallocatorCallback)ToShadow(thisObject).Callback;
- @this.FreeGCHandle(handle);
- }
- catch (System.Exception __exception__)
- {
- IAvnGCHandleDeallocatorCallback @this = (IAvnGCHandleDeallocatorCallback)ToShadow(thisObject).Callback;
- (@this as SharpGen.Runtime.IExceptionCallback)?.RaiseException(__exception__);
- }
- }
- }
-
- protected override SharpGen.Runtime.CppObjectVtbl Vtbl
- {
- get;
- }
-
- = new Avalonia.Native.Interop.IAvnGCHandleDeallocatorCallbackShadow.IAvnGCHandleDeallocatorCallbackVtbl(0);
- }
-
- [System.Runtime.InteropServices.GuidAttribute("2e2cda0a-9ae5-4f1b-8e20-081a04279f22"), SharpGen.Runtime.ShadowAttribute(typeof (Avalonia.Native.Interop.IAvnGCHandleDeallocatorCallbackShadow))]
- public partial interface IAvnGCHandleDeallocatorCallback : SharpGen.Runtime.IUnknown
- {
- void FreeGCHandle(System.IntPtr handle);
- }
-
- [System.Runtime.InteropServices.GuidAttribute("2e2cda0a-9ae5-4f1b-8e20-081a04279f14")]
- public partial class IAvnGlContext : SharpGen.Runtime.ComObject
- {
- public IAvnGlContext(System.IntPtr nativePtr): base (nativePtr)
- {
- }
-
- public static explicit operator IAvnGlContext(System.IntPtr nativePtr) => nativePtr == System.IntPtr.Zero ? null : new IAvnGlContext(nativePtr);
- ///
- /// No documentation.
- ///
- /// GetSampleCount
- /// GetSampleCount
- public System.Int32 SampleCount
- {
- get => GetSampleCount();
- }
-
- ///
- /// No documentation.
- ///
- /// GetStencilSize
- /// GetStencilSize
- public System.Int32 StencilSize
- {
- get => GetStencilSize();
- }
-
- ///
- /// No documentation.
- ///
- /// GetNativeHandle
- /// GetNativeHandle
- public System.IntPtr NativeHandle
- {
- get => GetNativeHandle();
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// HRESULT IAvnGlContext::MakeCurrent([In] IUnknown** ppv)
- /// IAvnGlContext::MakeCurrent
- public unsafe SharpGen.Runtime.IUnknown MakeCurrent()
- {
- SharpGen.Runtime.IUnknown vOut;
- System.IntPtr vOut_ = System.IntPtr.Zero;
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, &vOut_, (*(void ***)this._nativePointer)[3]);
- if (vOut_ != System.IntPtr.Zero)
- vOut = new SharpGen.Runtime.ComObject(vOut_);
- else
- vOut = null;
- __result__.CheckError();
- return vOut;
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// HRESULT IAvnGlContext::LegacyMakeCurrent()
- /// IAvnGlContext::LegacyMakeCurrent
- public unsafe void LegacyMakeCurrent()
- {
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, (*(void ***)this._nativePointer)[4]);
- __result__.CheckError();
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// int IAvnGlContext::GetSampleCount()
- /// IAvnGlContext::GetSampleCount
- internal unsafe System.Int32 GetSampleCount()
- {
- System.Int32 __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, (*(void ***)this._nativePointer)[5]);
- return __result__;
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// int IAvnGlContext::GetStencilSize()
- /// IAvnGlContext::GetStencilSize
- internal unsafe System.Int32 GetStencilSize()
- {
- System.Int32 __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, (*(void ***)this._nativePointer)[6]);
- return __result__;
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// void* IAvnGlContext::GetNativeHandle()
- /// IAvnGlContext::GetNativeHandle
- internal unsafe System.IntPtr GetNativeHandle()
- {
- System.IntPtr __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallSystemIntPtr(this._nativePointer, (*(void ***)this._nativePointer)[7]);
- return __result__;
- }
- }
-
- [System.Runtime.InteropServices.GuidAttribute("2e2cda0a-9ae5-4f1b-8e20-081a04279f13")]
- public partial class IAvnGlDisplay : SharpGen.Runtime.ComObject
- {
- public IAvnGlDisplay(System.IntPtr nativePtr): base (nativePtr)
- {
- }
-
- public static explicit operator IAvnGlDisplay(System.IntPtr nativePtr) => nativePtr == System.IntPtr.Zero ? null : new IAvnGlDisplay(nativePtr);
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnGlDisplay::CreateContext([In] IAvnGlContext* share,[In] IAvnGlContext** ppv)
- /// IAvnGlDisplay::CreateContext
- public unsafe Avalonia.Native.Interop.IAvnGlContext CreateContext(Avalonia.Native.Interop.IAvnGlContext share)
- {
- System.IntPtr share_ = System.IntPtr.Zero;
- Avalonia.Native.Interop.IAvnGlContext vOut;
- System.IntPtr vOut_ = System.IntPtr.Zero;
- SharpGen.Runtime.Result __result__;
- share_ = SharpGen.Runtime.CppObject.ToCallbackPtr(share);
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, (void *)share_, &vOut_, (*(void ***)this._nativePointer)[3]);
- if (vOut_ != System.IntPtr.Zero)
- vOut = new Avalonia.Native.Interop.IAvnGlContext(vOut_);
- else
- vOut = null;
- System.GC.KeepAlive(share);
- __result__.CheckError();
- return vOut;
- }
-
- ///
- /// No documentation.
- ///
- /// void IAvnGlDisplay::LegacyClearCurrentContext()
- /// IAvnGlDisplay::LegacyClearCurrentContext
- public unsafe void LegacyClearCurrentContext()
- {
- Avalonia.Native.LocalInterop.CalliThisCallvoid(this._nativePointer, (*(void ***)this._nativePointer)[4]);
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnGlDisplay::WrapContext([In] void* native,[In] IAvnGlContext** ppv)
- /// IAvnGlDisplay::WrapContext
- public unsafe Avalonia.Native.Interop.IAvnGlContext WrapContext(System.IntPtr native)
- {
- Avalonia.Native.Interop.IAvnGlContext vOut;
- System.IntPtr vOut_ = System.IntPtr.Zero;
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, (void *)native, &vOut_, (*(void ***)this._nativePointer)[5]);
- if (vOut_ != System.IntPtr.Zero)
- vOut = new Avalonia.Native.Interop.IAvnGlContext(vOut_);
- else
- vOut = null;
- __result__.CheckError();
- return vOut;
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// void* IAvnGlDisplay::GetProcAddress([In] char* proc)
- /// IAvnGlDisplay::GetProcAddress
- public unsafe System.IntPtr GetProcAddress(System.String rocRef)
- {
- System.IntPtr rocRef_;
- System.IntPtr __result__;
- rocRef_ = System.Runtime.InteropServices.Marshal.StringToHGlobalAnsi(rocRef);
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallSystemIntPtr(this._nativePointer, (void *)rocRef_, (*(void ***)this._nativePointer)[6]);
- System.Runtime.InteropServices.Marshal.FreeHGlobal(rocRef_);
- return __result__;
- }
- }
-
- [System.Runtime.InteropServices.GuidAttribute("2e2cda0a-9ae5-4f1b-8e20-081a04279f16")]
- public partial class IAvnGlSurfaceRenderingSession : SharpGen.Runtime.ComObject
- {
- public IAvnGlSurfaceRenderingSession(System.IntPtr nativePtr): base (nativePtr)
- {
- }
-
- public static explicit operator IAvnGlSurfaceRenderingSession(System.IntPtr nativePtr) => nativePtr == System.IntPtr.Zero ? null : new IAvnGlSurfaceRenderingSession(nativePtr);
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// HRESULT IAvnGlSurfaceRenderingSession::GetPixelSize([In] AvnPixelSize* ret)
- /// IAvnGlSurfaceRenderingSession::GetPixelSize
- public unsafe Avalonia.Native.Interop.AvnPixelSize GetPixelSize()
- {
- Avalonia.Native.Interop.AvnPixelSize ret;
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, &ret, (*(void ***)this._nativePointer)[3]);
- __result__.CheckError();
- return ret;
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// HRESULT IAvnGlSurfaceRenderingSession::GetScaling([In] double* ret)
- /// IAvnGlSurfaceRenderingSession::GetScaling
- public unsafe System.Double GetScaling()
- {
- System.Double ret;
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, &ret, (*(void ***)this._nativePointer)[4]);
- __result__.CheckError();
- return ret;
- }
- }
-
- [System.Runtime.InteropServices.GuidAttribute("2e2cda0a-9ae5-4f1b-8e20-081a04279f15")]
- public partial class IAvnGlSurfaceRenderTarget : SharpGen.Runtime.ComObject
- {
- public IAvnGlSurfaceRenderTarget(System.IntPtr nativePtr): base (nativePtr)
- {
- }
-
- public static explicit operator IAvnGlSurfaceRenderTarget(System.IntPtr nativePtr) => nativePtr == System.IntPtr.Zero ? null : new IAvnGlSurfaceRenderTarget(nativePtr);
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// HRESULT IAvnGlSurfaceRenderTarget::BeginDrawing([In] IAvnGlSurfaceRenderingSession** ret)
- /// IAvnGlSurfaceRenderTarget::BeginDrawing
- public unsafe Avalonia.Native.Interop.IAvnGlSurfaceRenderingSession BeginDrawing()
- {
- Avalonia.Native.Interop.IAvnGlSurfaceRenderingSession ret;
- System.IntPtr ret_ = System.IntPtr.Zero;
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, &ret_, (*(void ***)this._nativePointer)[3]);
- if (ret_ != System.IntPtr.Zero)
- ret = new Avalonia.Native.Interop.IAvnGlSurfaceRenderingSession(ret_);
- else
- ret = null;
- __result__.CheckError();
- return ret;
- }
- }
-
- [System.Runtime.InteropServices.GuidAttribute("2e2cda0a-9ae5-4f1b-8e20-081a04279f0a")]
- public partial class IAvnLoopCancellation : SharpGen.Runtime.ComObject
- {
- public IAvnLoopCancellation(System.IntPtr nativePtr): base (nativePtr)
- {
- }
-
- public static explicit operator IAvnLoopCancellation(System.IntPtr nativePtr) => nativePtr == System.IntPtr.Zero ? null : new IAvnLoopCancellation(nativePtr);
- ///
- /// No documentation.
- ///
- /// void IAvnLoopCancellation::Cancel()
- /// IAvnLoopCancellation::Cancel
- public unsafe void Cancel()
- {
- Avalonia.Native.LocalInterop.CalliThisCallvoid(this._nativePointer, (*(void ***)this._nativePointer)[3]);
- }
- }
-
- [System.Runtime.InteropServices.GuidAttribute("2e2cda0a-9ae5-4f1b-8e20-081a04279f07")]
- public partial class IAvnMacOptions : SharpGen.Runtime.ComObject
- {
- public IAvnMacOptions(System.IntPtr nativePtr): base (nativePtr)
- {
- }
-
- public static explicit operator IAvnMacOptions(System.IntPtr nativePtr) => nativePtr == System.IntPtr.Zero ? null : new IAvnMacOptions(nativePtr);
- ///
- /// No documentation.
- ///
- /// SetShowInDock
- /// SetShowInDock
- public System.Int32 ShowInDock
- {
- set => SetShowInDock(value);
- }
-
- ///
- /// No documentation.
- ///
- /// SetApplicationTitle
- /// SetApplicationTitle
- public System.IntPtr ApplicationTitle
- {
- set => SetApplicationTitle(value);
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnMacOptions::SetShowInDock([In] int show)
- /// IAvnMacOptions::SetShowInDock
- internal unsafe void SetShowInDock(System.Int32 show)
- {
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, show, (*(void ***)this._nativePointer)[3]);
- __result__.CheckError();
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnMacOptions::SetApplicationTitle([In] void* utf8string)
- /// IAvnMacOptions::SetApplicationTitle
- internal unsafe void SetApplicationTitle(System.IntPtr utf8string)
- {
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, (void *)utf8string, (*(void ***)this._nativePointer)[4]);
- __result__.CheckError();
- }
- }
-
- [System.Runtime.InteropServices.GuidAttribute("2e2cda0a-9ae5-4f1b-8e20-081a04279f17")]
- public partial class IAvnMenu : SharpGen.Runtime.ComObject
- {
- public IAvnMenu(System.IntPtr nativePtr): base (nativePtr)
- {
- }
-
- public static explicit operator IAvnMenu(System.IntPtr nativePtr) => nativePtr == System.IntPtr.Zero ? null : new IAvnMenu(nativePtr);
- ///
- /// No documentation.
- ///
- /// SetTitle
- /// SetTitle
- public System.IntPtr Title
- {
- set => SetTitle(value);
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnMenu::InsertItem([In] int index,[In] IAvnMenuItem* item)
- /// IAvnMenu::InsertItem
- public unsafe void InsertItem(System.Int32 index, Avalonia.Native.Interop.IAvnMenuItem item)
- {
- System.IntPtr item_ = System.IntPtr.Zero;
- SharpGen.Runtime.Result __result__;
- item_ = SharpGen.Runtime.CppObject.ToCallbackPtr(item);
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, index, (void *)item_, (*(void ***)this._nativePointer)[3]);
- System.GC.KeepAlive(item);
- __result__.CheckError();
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnMenu::RemoveItem([In] IAvnMenuItem* item)
- /// IAvnMenu::RemoveItem
- public unsafe void RemoveItem(Avalonia.Native.Interop.IAvnMenuItem item)
- {
- System.IntPtr item_ = System.IntPtr.Zero;
- SharpGen.Runtime.Result __result__;
- item_ = SharpGen.Runtime.CppObject.ToCallbackPtr(item);
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, (void *)item_, (*(void ***)this._nativePointer)[4]);
- System.GC.KeepAlive(item);
- __result__.CheckError();
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnMenu::SetTitle([In] void* utf8String)
- /// IAvnMenu::SetTitle
- internal unsafe void SetTitle(System.IntPtr utf8String)
- {
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, (void *)utf8String, (*(void ***)this._nativePointer)[5]);
- __result__.CheckError();
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// HRESULT IAvnMenu::Clear()
- /// IAvnMenu::Clear
- public unsafe void Clear()
- {
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, (*(void ***)this._nativePointer)[6]);
- __result__.CheckError();
- }
- }
-
- class IAvnMenuEventsShadow : SharpGen.Runtime.ComObjectShadow
- {
- protected unsafe class IAvnMenuEventsVtbl : SharpGen.Runtime.ComObjectShadow.ComObjectVtbl
- {
- public IAvnMenuEventsVtbl(int numberOfCallbackMethods): base (numberOfCallbackMethods + 1)
- {
- AddMethod(new NeedsUpdateDelegate(NeedsUpdate));
- }
-
- [System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(System.Runtime.InteropServices.CallingConvention.ThisCall)]
- private delegate void NeedsUpdateDelegate(System.IntPtr thisObject);
- private static unsafe void NeedsUpdate(System.IntPtr thisObject)
- {
- try
- {
- IAvnMenuEvents @this = (IAvnMenuEvents)ToShadow(thisObject).Callback;
- @this.NeedsUpdate();
- }
- catch (System.Exception __exception__)
- {
- IAvnMenuEvents @this = (IAvnMenuEvents)ToShadow(thisObject).Callback;
- (@this as SharpGen.Runtime.IExceptionCallback)?.RaiseException(__exception__);
- }
- }
- }
-
- protected override SharpGen.Runtime.CppObjectVtbl Vtbl
- {
- get;
- }
-
- = new Avalonia.Native.Interop.IAvnMenuEventsShadow.IAvnMenuEventsVtbl(0);
- }
-
- [System.Runtime.InteropServices.GuidAttribute("2e2cda0a-9ae5-4f1b-8e20-081a04279f1A"), SharpGen.Runtime.ShadowAttribute(typeof (Avalonia.Native.Interop.IAvnMenuEventsShadow))]
- public partial interface IAvnMenuEvents : SharpGen.Runtime.IUnknown
- {
- void NeedsUpdate();
- }
-
- [System.Runtime.InteropServices.GuidAttribute("2e2cda0a-9ae5-4f1b-8e20-081a04279f19")]
- public partial class IAvnMenuItem : SharpGen.Runtime.ComObject
- {
- public IAvnMenuItem(System.IntPtr nativePtr): base (nativePtr)
- {
- }
-
- public static explicit operator IAvnMenuItem(System.IntPtr nativePtr) => nativePtr == System.IntPtr.Zero ? null : new IAvnMenuItem(nativePtr);
- ///
- /// No documentation.
- ///
- /// SetSubMenu
- /// SetSubMenu
- public Avalonia.Native.Interop.IAvnMenu SubMenu
- {
- set => SetSubMenu(value);
- }
-
- ///
- /// No documentation.
- ///
- /// SetTitle
- /// SetTitle
- public System.IntPtr Title
- {
- set => SetTitle(value);
- }
-
- ///
- /// No documentation.
- ///
- /// SetIsChecked
- /// SetIsChecked
- public System.Boolean IsChecked
- {
- set => SetIsChecked(value);
- }
-
- ///
- /// No documentation.
- ///
- /// SetToggleType
- /// SetToggleType
- public Avalonia.Native.Interop.AvnMenuItemToggleType ToggleType
- {
- set => SetToggleType(value);
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnMenuItem::SetSubMenu([In] IAvnMenu* menu)
- /// IAvnMenuItem::SetSubMenu
- internal unsafe void SetSubMenu(Avalonia.Native.Interop.IAvnMenu menu)
- {
- System.IntPtr menu_ = System.IntPtr.Zero;
- SharpGen.Runtime.Result __result__;
- menu_ = SharpGen.Runtime.CppObject.ToCallbackPtr(menu);
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, (void *)menu_, (*(void ***)this._nativePointer)[3]);
- System.GC.KeepAlive(menu);
- __result__.CheckError();
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnMenuItem::SetTitle([In] void* utf8String)
- /// IAvnMenuItem::SetTitle
- internal unsafe void SetTitle(System.IntPtr utf8String)
- {
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, (void *)utf8String, (*(void ***)this._nativePointer)[4]);
- __result__.CheckError();
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnMenuItem::SetGesture([In] void* utf8String,[In] AvnInputModifiers modifiers)
- /// IAvnMenuItem::SetGesture
- public unsafe void SetGesture(System.IntPtr utf8String, Avalonia.Native.Interop.AvnInputModifiers modifiers)
- {
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, (void *)utf8String, unchecked ((System.Int32)modifiers), (*(void ***)this._nativePointer)[5]);
- __result__.CheckError();
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnMenuItem::SetAction([In] IAvnPredicateCallback* predicate,[In] IAvnActionCallback* callback)
- /// IAvnMenuItem::SetAction
- public unsafe void SetAction(Avalonia.Native.Interop.IAvnPredicateCallback redicateRef, Avalonia.Native.Interop.IAvnActionCallback callback)
- {
- System.IntPtr redicateRef_ = System.IntPtr.Zero;
- System.IntPtr callback_ = System.IntPtr.Zero;
- SharpGen.Runtime.Result __result__;
- redicateRef_ = SharpGen.Runtime.CppObject.ToCallbackPtr(redicateRef);
- callback_ = SharpGen.Runtime.CppObject.ToCallbackPtr(callback);
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, (void *)redicateRef_, (void *)callback_, (*(void ***)this._nativePointer)[6]);
- System.GC.KeepAlive(redicateRef);
- System.GC.KeepAlive(callback);
- __result__.CheckError();
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnMenuItem::SetIsChecked([In] bool isChecked)
- /// IAvnMenuItem::SetIsChecked
- internal unsafe void SetIsChecked(System.Boolean isChecked)
- {
- System.Byte isChecked_;
- SharpGen.Runtime.Result __result__;
- isChecked_ = (System.Byte)(isChecked ? 1 : 0);
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, isChecked_, (*(void ***)this._nativePointer)[7]);
- __result__.CheckError();
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnMenuItem::SetToggleType([In] AvnMenuItemToggleType toggleType)
- /// IAvnMenuItem::SetToggleType
- internal unsafe void SetToggleType(Avalonia.Native.Interop.AvnMenuItemToggleType toggleType)
- {
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, unchecked ((System.Int32)toggleType), (*(void ***)this._nativePointer)[8]);
- __result__.CheckError();
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnMenuItem::SetIcon([In] void* data,[In] size_t length)
- /// IAvnMenuItem::SetIcon
- public unsafe void SetIcon(System.IntPtr data, SharpGen.Runtime.PointerSize length)
- {
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, (void *)data, (void *)length, (*(void ***)this._nativePointer)[9]);
- __result__.CheckError();
- }
- }
-
- [System.Runtime.InteropServices.GuidAttribute("2e2cda0a-9ae5-4f1b-8e20-081a04279f20")]
- public partial class IAvnNativeControlHost : SharpGen.Runtime.ComObject
- {
- public IAvnNativeControlHost(System.IntPtr nativePtr): base (nativePtr)
- {
- }
-
- public static explicit operator IAvnNativeControlHost(System.IntPtr nativePtr) => nativePtr == System.IntPtr.Zero ? null : new IAvnNativeControlHost(nativePtr);
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnNativeControlHost::CreateDefaultChild([In] void* parent,[Out] void** retOut)
- /// IAvnNativeControlHost::CreateDefaultChild
- public unsafe System.IntPtr CreateDefaultChild(System.IntPtr arentRef)
- {
- System.IntPtr retOut;
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, (void *)arentRef, &retOut, (*(void ***)this._nativePointer)[3]);
- __result__.CheckError();
- return retOut;
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// IAvnNativeControlHostTopLevelAttachment* IAvnNativeControlHost::CreateAttachment()
- /// IAvnNativeControlHost::CreateAttachment
- public unsafe Avalonia.Native.Interop.IAvnNativeControlHostTopLevelAttachment CreateAttachment()
- {
- Avalonia.Native.Interop.IAvnNativeControlHostTopLevelAttachment __result__;
- System.IntPtr __result__native = System.IntPtr.Zero;
- __result__native = Avalonia.Native.LocalInterop.CalliThisCallSystemIntPtr(this._nativePointer, (*(void ***)this._nativePointer)[4]);
- if (__result__native != System.IntPtr.Zero)
- __result__ = new Avalonia.Native.Interop.IAvnNativeControlHostTopLevelAttachment(__result__native);
- else
- __result__ = null;
- return __result__;
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// void IAvnNativeControlHost::DestroyDefaultChild([In] void* child)
- /// IAvnNativeControlHost::DestroyDefaultChild
- public unsafe void DestroyDefaultChild(System.IntPtr child)
- {
- Avalonia.Native.LocalInterop.CalliThisCallvoid(this._nativePointer, (void *)child, (*(void ***)this._nativePointer)[5]);
- }
- }
-
- [System.Runtime.InteropServices.GuidAttribute("2e2cda0a-9ae5-4f1b-8e20-081a04279f21")]
- public partial class IAvnNativeControlHostTopLevelAttachment : SharpGen.Runtime.ComObject
- {
- public IAvnNativeControlHostTopLevelAttachment(System.IntPtr nativePtr): base (nativePtr)
- {
- }
-
- public static explicit operator IAvnNativeControlHostTopLevelAttachment(System.IntPtr nativePtr) => nativePtr == System.IntPtr.Zero ? null : new IAvnNativeControlHostTopLevelAttachment(nativePtr);
- ///
- /// No documentation.
- ///
- /// GetParentHandle
- /// GetParentHandle
- public System.IntPtr ParentHandle
- {
- get => GetParentHandle();
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// void* IAvnNativeControlHostTopLevelAttachment::GetParentHandle()
- /// IAvnNativeControlHostTopLevelAttachment::GetParentHandle
- internal unsafe System.IntPtr GetParentHandle()
- {
- System.IntPtr __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallSystemIntPtr(this._nativePointer, (*(void ***)this._nativePointer)[3]);
- return __result__;
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnNativeControlHostTopLevelAttachment::InitializeWithChildHandle([In] void* child)
- /// IAvnNativeControlHostTopLevelAttachment::InitializeWithChildHandle
- public unsafe void InitializeWithChildHandle(System.IntPtr child)
- {
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, (void *)child, (*(void ***)this._nativePointer)[4]);
- __result__.CheckError();
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnNativeControlHostTopLevelAttachment::AttachTo([In] IAvnNativeControlHost* host)
- /// IAvnNativeControlHostTopLevelAttachment::AttachTo
- public unsafe void AttachTo(Avalonia.Native.Interop.IAvnNativeControlHost host)
- {
- System.IntPtr host_ = System.IntPtr.Zero;
- SharpGen.Runtime.Result __result__;
- host_ = SharpGen.Runtime.CppObject.ToCallbackPtr(host);
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, (void *)host_, (*(void ***)this._nativePointer)[5]);
- System.GC.KeepAlive(host);
- __result__.CheckError();
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// No documentation.
- /// No documentation.
- /// void IAvnNativeControlHostTopLevelAttachment::ShowInBounds([In] float x,[In] float y,[In] float width,[In] float height)
- /// IAvnNativeControlHostTopLevelAttachment::ShowInBounds
- public unsafe void ShowInBounds(System.Single x, System.Single y, System.Single width, System.Single height)
- {
- Avalonia.Native.LocalInterop.CalliThisCallvoid(this._nativePointer, x, y, width, height, (*(void ***)this._nativePointer)[6]);
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// void IAvnNativeControlHostTopLevelAttachment::HideWithSize([In] float width,[In] float height)
- /// IAvnNativeControlHostTopLevelAttachment::HideWithSize
- public unsafe void HideWithSize(System.Single width, System.Single height)
- {
- Avalonia.Native.LocalInterop.CalliThisCallvoid(this._nativePointer, width, height, (*(void ***)this._nativePointer)[7]);
- }
-
- ///
- /// No documentation.
- ///
- /// void IAvnNativeControlHostTopLevelAttachment::ReleaseChild()
- /// IAvnNativeControlHostTopLevelAttachment::ReleaseChild
- public unsafe void ReleaseChild()
- {
- Avalonia.Native.LocalInterop.CalliThisCallvoid(this._nativePointer, (*(void ***)this._nativePointer)[8]);
- }
- }
-
- [System.Runtime.InteropServices.GuidAttribute("2e2cda0a-9ae5-4f1b-8e20-081a04279f0b")]
- public partial class IAvnPlatformThreadingInterface : SharpGen.Runtime.ComObject
- {
- public IAvnPlatformThreadingInterface(System.IntPtr nativePtr): base (nativePtr)
- {
- }
-
- public static explicit operator IAvnPlatformThreadingInterface(System.IntPtr nativePtr) => nativePtr == System.IntPtr.Zero ? null : new IAvnPlatformThreadingInterface(nativePtr);
- ///
- /// No documentation.
- ///
- /// GetCurrentThreadIsLoopThread
- /// GetCurrentThreadIsLoopThread
- public System.Boolean CurrentThreadIsLoopThread
- {
- get => GetCurrentThreadIsLoopThread();
- }
-
- ///
- /// No documentation.
- ///
- /// SetSignaledCallback
- /// SetSignaledCallback
- public Avalonia.Native.Interop.IAvnSignaledCallback SignaledCallback
- {
- set => SetSignaledCallback(value);
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// bool IAvnPlatformThreadingInterface::GetCurrentThreadIsLoopThread()
- /// IAvnPlatformThreadingInterface::GetCurrentThreadIsLoopThread
- internal unsafe System.Boolean GetCurrentThreadIsLoopThread()
- {
- System.Boolean __result__;
- System.Byte __result__native;
- __result__native = Avalonia.Native.LocalInterop.CalliThisCallSystemByte(this._nativePointer, (*(void ***)this._nativePointer)[3]);
- __result__ = __result__native != 0;
- return __result__;
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// void IAvnPlatformThreadingInterface::SetSignaledCallback([In] IAvnSignaledCallback* cb)
- /// IAvnPlatformThreadingInterface::SetSignaledCallback
- internal unsafe void SetSignaledCallback(Avalonia.Native.Interop.IAvnSignaledCallback cb)
- {
- System.IntPtr cb_ = System.IntPtr.Zero;
- cb_ = SharpGen.Runtime.CppObject.ToCallbackPtr(cb);
- Avalonia.Native.LocalInterop.CalliThisCallvoid(this._nativePointer, (void *)cb_, (*(void ***)this._nativePointer)[4]);
- System.GC.KeepAlive(cb);
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// IAvnLoopCancellation* IAvnPlatformThreadingInterface::CreateLoopCancellation()
- /// IAvnPlatformThreadingInterface::CreateLoopCancellation
- public unsafe Avalonia.Native.Interop.IAvnLoopCancellation CreateLoopCancellation()
- {
- Avalonia.Native.Interop.IAvnLoopCancellation __result__;
- System.IntPtr __result__native = System.IntPtr.Zero;
- __result__native = Avalonia.Native.LocalInterop.CalliThisCallSystemIntPtr(this._nativePointer, (*(void ***)this._nativePointer)[5]);
- if (__result__native != System.IntPtr.Zero)
- __result__ = new Avalonia.Native.Interop.IAvnLoopCancellation(__result__native);
- else
- __result__ = null;
- return __result__;
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnPlatformThreadingInterface::RunLoop([In] IAvnLoopCancellation* cancel)
- /// IAvnPlatformThreadingInterface::RunLoop
- public unsafe void RunLoop(Avalonia.Native.Interop.IAvnLoopCancellation cancel)
- {
- System.IntPtr cancel_ = System.IntPtr.Zero;
- SharpGen.Runtime.Result __result__;
- cancel_ = SharpGen.Runtime.CppObject.ToCallbackPtr(cancel);
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, (void *)cancel_, (*(void ***)this._nativePointer)[6]);
- System.GC.KeepAlive(cancel);
- __result__.CheckError();
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// void IAvnPlatformThreadingInterface::Signal([In] int priority)
- /// IAvnPlatformThreadingInterface::Signal
- public unsafe void Signal(System.Int32 priority)
- {
- Avalonia.Native.LocalInterop.CalliThisCallvoid(this._nativePointer, priority, (*(void ***)this._nativePointer)[7]);
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// No documentation.
- /// No documentation.
- /// IUnknown* IAvnPlatformThreadingInterface::StartTimer([In] int priority,[In] int ms,[In] IAvnActionCallback* callback)
- /// IAvnPlatformThreadingInterface::StartTimer
- public unsafe SharpGen.Runtime.ComObject StartTimer(System.Int32 priority, System.Int32 ms, Avalonia.Native.Interop.IAvnActionCallback callback)
- {
- System.IntPtr callback_ = System.IntPtr.Zero;
- SharpGen.Runtime.ComObject __result__;
- System.IntPtr __result__native = System.IntPtr.Zero;
- callback_ = SharpGen.Runtime.CppObject.ToCallbackPtr(callback);
- __result__native = Avalonia.Native.LocalInterop.CalliThisCallSystemIntPtr(this._nativePointer, priority, ms, (void *)callback_, (*(void ***)this._nativePointer)[8]);
- if (__result__native != System.IntPtr.Zero)
- __result__ = new SharpGen.Runtime.ComObject(__result__native);
- else
- __result__ = null;
- System.GC.KeepAlive(callback);
- return __result__;
- }
- }
-
- [System.Runtime.InteropServices.GuidAttribute("2e2cda0a-9ae5-4f1b-8e20-081a04279f03")]
- public partial class IAvnPopup : Avalonia.Native.Interop.IAvnWindowBase
- {
- public IAvnPopup(System.IntPtr nativePtr): base (nativePtr)
- {
- }
-
- public static explicit operator IAvnPopup(System.IntPtr nativePtr) => nativePtr == System.IntPtr.Zero ? null : new IAvnPopup(nativePtr);
- }
-
- class IAvnPredicateCallbackShadow : SharpGen.Runtime.ComObjectShadow
- {
- protected unsafe class IAvnPredicateCallbackVtbl : SharpGen.Runtime.ComObjectShadow.ComObjectVtbl
- {
- public IAvnPredicateCallbackVtbl(int numberOfCallbackMethods): base (numberOfCallbackMethods + 1)
- {
- AddMethod(new EvaluateDelegate(Evaluate));
- }
-
- [System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(System.Runtime.InteropServices.CallingConvention.ThisCall)]
- private delegate System.Byte EvaluateDelegate(System.IntPtr thisObject);
- private static unsafe System.Byte Evaluate(System.IntPtr thisObject)
- {
- try
- {
- System.Boolean __result__ = default (System.Boolean);
- System.Byte __result__native;
- IAvnPredicateCallback @this = (IAvnPredicateCallback)ToShadow(thisObject).Callback;
- __result__ = @this.Evaluate();
- __result__native = (System.Byte)(__result__ ? 1 : 0);
- return __result__native;
- }
- catch (System.Exception __exception__)
- {
- IAvnPredicateCallback @this = (IAvnPredicateCallback)ToShadow(thisObject).Callback;
- (@this as SharpGen.Runtime.IExceptionCallback)?.RaiseException(__exception__);
- return default (System.Byte);
- }
- }
- }
-
- protected override SharpGen.Runtime.CppObjectVtbl Vtbl
- {
- get;
- }
-
- = new Avalonia.Native.Interop.IAvnPredicateCallbackShadow.IAvnPredicateCallbackVtbl(0);
- }
-
- [System.Runtime.InteropServices.GuidAttribute("2e2cda0a-9ae5-4f1b-8e20-081a04279f18"), SharpGen.Runtime.ShadowAttribute(typeof (Avalonia.Native.Interop.IAvnPredicateCallbackShadow))]
- public partial interface IAvnPredicateCallback : SharpGen.Runtime.IUnknown
- {
- System.Boolean Evaluate();
- }
-
- [System.Runtime.InteropServices.GuidAttribute("2e2cda0a-9ae5-4f1b-8e20-081a04279f0e")]
- public partial class IAvnScreens : SharpGen.Runtime.ComObject
- {
- public IAvnScreens(System.IntPtr nativePtr): base (nativePtr)
- {
- }
-
- public static explicit operator IAvnScreens(System.IntPtr nativePtr) => nativePtr == System.IntPtr.Zero ? null : new IAvnScreens(nativePtr);
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// HRESULT IAvnScreens::GetScreenCount([In] int* ret)
- /// IAvnScreens::GetScreenCount
- public unsafe System.Int32 GetScreenCount()
- {
- System.Int32 ret;
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, &ret, (*(void ***)this._nativePointer)[3]);
- __result__.CheckError();
- return ret;
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnScreens::GetScreen([In] int index,[In] AvnScreen* ret)
- /// IAvnScreens::GetScreen
- public unsafe Avalonia.Native.Interop.AvnScreen GetScreen(System.Int32 index)
- {
- Avalonia.Native.Interop.AvnScreen ret;
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, index, &ret, (*(void ***)this._nativePointer)[4]);
- __result__.CheckError();
- return ret;
- }
- }
-
- class IAvnSignaledCallbackShadow : SharpGen.Runtime.ComObjectShadow
- {
- protected unsafe class IAvnSignaledCallbackVtbl : SharpGen.Runtime.ComObjectShadow.ComObjectVtbl
- {
- public IAvnSignaledCallbackVtbl(int numberOfCallbackMethods): base (numberOfCallbackMethods + 1)
- {
- AddMethod(new SignaledDelegate(Signaled));
- }
-
- [System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(System.Runtime.InteropServices.CallingConvention.ThisCall)]
- private delegate void SignaledDelegate(System.IntPtr thisObject, int arg0, System.Byte arg1);
- private static unsafe void Signaled(System.IntPtr thisObject, int param0, System.Byte param1)
- {
- try
- {
- System.Int32 priority = default (System.Int32);
- priority = (System.Int32)param0;
- System.Boolean priorityContainsMeaningfulValue = default (System.Boolean);
- System.Byte priorityContainsMeaningfulValue_ = (System.Byte)param1;
- IAvnSignaledCallback @this = (IAvnSignaledCallback)ToShadow(thisObject).Callback;
- priorityContainsMeaningfulValue = priorityContainsMeaningfulValue_ != 0;
- @this.Signaled(priority, priorityContainsMeaningfulValue);
- }
- catch (System.Exception __exception__)
- {
- IAvnSignaledCallback @this = (IAvnSignaledCallback)ToShadow(thisObject).Callback;
- (@this as SharpGen.Runtime.IExceptionCallback)?.RaiseException(__exception__);
- }
- }
- }
-
- protected override SharpGen.Runtime.CppObjectVtbl Vtbl
- {
- get;
- }
-
- = new Avalonia.Native.Interop.IAvnSignaledCallbackShadow.IAvnSignaledCallbackVtbl(0);
- }
-
- [System.Runtime.InteropServices.GuidAttribute("2e2cda0a-9ae5-4f1b-8e20-081a04279f09"), SharpGen.Runtime.ShadowAttribute(typeof (Avalonia.Native.Interop.IAvnSignaledCallbackShadow))]
- public partial interface IAvnSignaledCallback : SharpGen.Runtime.IUnknown
- {
- void Signaled(System.Int32 priority, System.Boolean priorityContainsMeaningfulValue);
- }
-
- [System.Runtime.InteropServices.GuidAttribute("2e2cda0a-9ae5-4f1b-8e20-081a04279f17")]
- public partial class IAvnString : SharpGen.Runtime.ComObject
- {
- public IAvnString(System.IntPtr nativePtr): base (nativePtr)
- {
- }
-
- public static explicit operator IAvnString(System.IntPtr nativePtr) => nativePtr == System.IntPtr.Zero ? null : new IAvnString(nativePtr);
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// HRESULT IAvnString::Pointer([Out] void** retOut)
- /// IAvnString::Pointer
- public unsafe System.IntPtr Pointer()
- {
- System.IntPtr retOut;
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, &retOut, (*(void ***)this._nativePointer)[3]);
- __result__.CheckError();
- return retOut;
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// HRESULT IAvnString::Length([In] int* ret)
- /// IAvnString::Length
- public unsafe System.Int32 Length()
- {
- System.Int32 ret;
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, &ret, (*(void ***)this._nativePointer)[4]);
- __result__.CheckError();
- return ret;
- }
- }
-
- [System.Runtime.InteropServices.GuidAttribute("2e2cda0a-9ae5-4f1b-8e20-081a04279f20")]
- public partial class IAvnStringArray : SharpGen.Runtime.ComObject
- {
- public IAvnStringArray(System.IntPtr nativePtr): base (nativePtr)
- {
- }
-
- public static explicit operator IAvnStringArray(System.IntPtr nativePtr) => nativePtr == System.IntPtr.Zero ? null : new IAvnStringArray(nativePtr);
- ///
- /// No documentation.
- ///
- /// GetCount
- /// GetCount
- public System.UInt32 Count
- {
- get => GetCount();
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// unsigned int IAvnStringArray::GetCount()
- /// IAvnStringArray::GetCount
- internal unsafe System.UInt32 GetCount()
- {
- System.UInt32 __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallSystemUInt32(this._nativePointer, (*(void ***)this._nativePointer)[3]);
- return __result__;
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnStringArray::Get([In] unsigned int index,[In] IAvnString** ppv)
- /// IAvnStringArray::Get
- public unsafe Avalonia.Native.Interop.IAvnString Get(System.UInt32 index)
- {
- Avalonia.Native.Interop.IAvnString vOut;
- System.IntPtr vOut_ = System.IntPtr.Zero;
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, index, &vOut_, (*(void ***)this._nativePointer)[4]);
- if (vOut_ != System.IntPtr.Zero)
- vOut = new Avalonia.Native.Interop.IAvnString(vOut_);
- else
- vOut = null;
- __result__.CheckError();
- return vOut;
- }
- }
-
- class IAvnSystemDialogEventsShadow : SharpGen.Runtime.ComObjectShadow
- {
- protected unsafe class IAvnSystemDialogEventsVtbl : SharpGen.Runtime.ComObjectShadow.ComObjectVtbl
- {
- public IAvnSystemDialogEventsVtbl(int numberOfCallbackMethods): base (numberOfCallbackMethods + 1)
- {
- AddMethod(new OnCompletedDelegate(OnCompleted));
- }
-
- [System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(System.Runtime.InteropServices.CallingConvention.ThisCall)]
- private delegate void OnCompletedDelegate(System.IntPtr thisObject, int arg0, void *arg1);
- private static unsafe void OnCompleted(System.IntPtr thisObject, int param0, void *param1)
- {
- try
- {
- System.Int32 numResults = default (System.Int32);
- numResults = (System.Int32)param0;
- System.IntPtr trFirstResultRef = default (System.IntPtr);
- trFirstResultRef = (System.IntPtr)param1;
- IAvnSystemDialogEvents @this = (IAvnSystemDialogEvents)ToShadow(thisObject).Callback;
- @this.OnCompleted(numResults, trFirstResultRef);
- }
- catch (System.Exception __exception__)
- {
- IAvnSystemDialogEvents @this = (IAvnSystemDialogEvents)ToShadow(thisObject).Callback;
- (@this as SharpGen.Runtime.IExceptionCallback)?.RaiseException(__exception__);
- }
- }
- }
-
- protected override SharpGen.Runtime.CppObjectVtbl Vtbl
- {
- get;
- }
-
- = new Avalonia.Native.Interop.IAvnSystemDialogEventsShadow.IAvnSystemDialogEventsVtbl(0);
- }
-
- [System.Runtime.InteropServices.GuidAttribute("2e2cda0a-9ae5-4f1b-8e20-081a04279f0c"), SharpGen.Runtime.ShadowAttribute(typeof (Avalonia.Native.Interop.IAvnSystemDialogEventsShadow))]
- public partial interface IAvnSystemDialogEvents : SharpGen.Runtime.IUnknown
- {
- void OnCompleted(System.Int32 numResults, System.IntPtr trFirstResultRef);
- }
-
- [System.Runtime.InteropServices.GuidAttribute("2e2cda0a-9ae5-4f1b-8e20-081a04279f0d")]
- public partial class IAvnSystemDialogs : SharpGen.Runtime.ComObject
- {
- public IAvnSystemDialogs(System.IntPtr nativePtr): base (nativePtr)
- {
- }
-
- public static explicit operator IAvnSystemDialogs(System.IntPtr nativePtr) => nativePtr == System.IntPtr.Zero ? null : new IAvnSystemDialogs(nativePtr);
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// No documentation.
- /// No documentation.
- /// void IAvnSystemDialogs::SelectFolderDialog([In] IAvnWindow* parentWindowHandle,[In] IAvnSystemDialogEvents* events,[In] const char* title,[In] const char* initialPath)
- /// IAvnSystemDialogs::SelectFolderDialog
- public unsafe void SelectFolderDialog(Avalonia.Native.Interop.IAvnWindow arentWindowHandleRef, Avalonia.Native.Interop.IAvnSystemDialogEvents events, System.String title, System.String initialPath)
- {
- System.IntPtr arentWindowHandleRef_ = System.IntPtr.Zero;
- System.IntPtr events_ = System.IntPtr.Zero;
- System.IntPtr title_;
- System.IntPtr initialPath_;
- arentWindowHandleRef_ = SharpGen.Runtime.CppObject.ToCallbackPtr(arentWindowHandleRef);
- events_ = SharpGen.Runtime.CppObject.ToCallbackPtr(events);
- title_ = System.Runtime.InteropServices.Marshal.StringToHGlobalAnsi(title);
- initialPath_ = System.Runtime.InteropServices.Marshal.StringToHGlobalAnsi(initialPath);
- Avalonia.Native.LocalInterop.CalliThisCallvoid(this._nativePointer, (void *)arentWindowHandleRef_, (void *)events_, (void *)title_, (void *)initialPath_, (*(void ***)this._nativePointer)[3]);
- System.GC.KeepAlive(arentWindowHandleRef);
- System.GC.KeepAlive(events);
- System.Runtime.InteropServices.Marshal.FreeHGlobal(title_);
- System.Runtime.InteropServices.Marshal.FreeHGlobal(initialPath_);
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// No documentation.
- /// No documentation.
- /// No documentation.
- /// No documentation.
- /// No documentation.
- /// void IAvnSystemDialogs::OpenFileDialog([In] IAvnWindow* parentWindowHandle,[In] IAvnSystemDialogEvents* events,[In] bool allowMultiple,[In] const char* title,[In] const char* initialDirectory,[In] const char* initialFile,[In] const char* filters)
- /// IAvnSystemDialogs::OpenFileDialog
- public unsafe void OpenFileDialog(Avalonia.Native.Interop.IAvnWindow arentWindowHandleRef, Avalonia.Native.Interop.IAvnSystemDialogEvents events, System.Boolean allowMultiple, System.String title, System.String initialDirectory, System.String initialFile, System.String filters)
- {
- System.IntPtr arentWindowHandleRef_ = System.IntPtr.Zero;
- System.IntPtr events_ = System.IntPtr.Zero;
- System.Byte allowMultiple_;
- System.IntPtr title_;
- System.IntPtr initialDirectory_;
- System.IntPtr initialFile_;
- System.IntPtr filters_;
- arentWindowHandleRef_ = SharpGen.Runtime.CppObject.ToCallbackPtr(arentWindowHandleRef);
- events_ = SharpGen.Runtime.CppObject.ToCallbackPtr(events);
- allowMultiple_ = (System.Byte)(allowMultiple ? 1 : 0);
- title_ = System.Runtime.InteropServices.Marshal.StringToHGlobalAnsi(title);
- initialDirectory_ = System.Runtime.InteropServices.Marshal.StringToHGlobalAnsi(initialDirectory);
- initialFile_ = System.Runtime.InteropServices.Marshal.StringToHGlobalAnsi(initialFile);
- filters_ = System.Runtime.InteropServices.Marshal.StringToHGlobalAnsi(filters);
- Avalonia.Native.LocalInterop.CalliThisCallvoid(this._nativePointer, (void *)arentWindowHandleRef_, (void *)events_, allowMultiple_, (void *)title_, (void *)initialDirectory_, (void *)initialFile_, (void *)filters_, (*(void ***)this._nativePointer)[4]);
- System.GC.KeepAlive(arentWindowHandleRef);
- System.GC.KeepAlive(events);
- System.Runtime.InteropServices.Marshal.FreeHGlobal(title_);
- System.Runtime.InteropServices.Marshal.FreeHGlobal(initialDirectory_);
- System.Runtime.InteropServices.Marshal.FreeHGlobal(initialFile_);
- System.Runtime.InteropServices.Marshal.FreeHGlobal(filters_);
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// No documentation.
- /// No documentation.
- /// No documentation.
- /// No documentation.
- /// void IAvnSystemDialogs::SaveFileDialog([In] IAvnWindow* parentWindowHandle,[In] IAvnSystemDialogEvents* events,[In] const char* title,[In] const char* initialDirectory,[In] const char* initialFile,[In] const char* filters)
- /// IAvnSystemDialogs::SaveFileDialog
- public unsafe void SaveFileDialog(Avalonia.Native.Interop.IAvnWindow arentWindowHandleRef, Avalonia.Native.Interop.IAvnSystemDialogEvents events, System.String title, System.String initialDirectory, System.String initialFile, System.String filters)
- {
- System.IntPtr arentWindowHandleRef_ = System.IntPtr.Zero;
- System.IntPtr events_ = System.IntPtr.Zero;
- System.IntPtr title_;
- System.IntPtr initialDirectory_;
- System.IntPtr initialFile_;
- System.IntPtr filters_;
- arentWindowHandleRef_ = SharpGen.Runtime.CppObject.ToCallbackPtr(arentWindowHandleRef);
- events_ = SharpGen.Runtime.CppObject.ToCallbackPtr(events);
- title_ = System.Runtime.InteropServices.Marshal.StringToHGlobalAnsi(title);
- initialDirectory_ = System.Runtime.InteropServices.Marshal.StringToHGlobalAnsi(initialDirectory);
- initialFile_ = System.Runtime.InteropServices.Marshal.StringToHGlobalAnsi(initialFile);
- filters_ = System.Runtime.InteropServices.Marshal.StringToHGlobalAnsi(filters);
- Avalonia.Native.LocalInterop.CalliThisCallvoid(this._nativePointer, (void *)arentWindowHandleRef_, (void *)events_, (void *)title_, (void *)initialDirectory_, (void *)initialFile_, (void *)filters_, (*(void ***)this._nativePointer)[5]);
- System.GC.KeepAlive(arentWindowHandleRef);
- System.GC.KeepAlive(events);
- System.Runtime.InteropServices.Marshal.FreeHGlobal(title_);
- System.Runtime.InteropServices.Marshal.FreeHGlobal(initialDirectory_);
- System.Runtime.InteropServices.Marshal.FreeHGlobal(initialFile_);
- System.Runtime.InteropServices.Marshal.FreeHGlobal(filters_);
- }
- }
-
- [System.Runtime.InteropServices.GuidAttribute("2e2cda0a-9ae5-4f1b-8e20-081a04279f04")]
- public partial class IAvnWindow : Avalonia.Native.Interop.IAvnWindowBase
- {
- public IAvnWindow(System.IntPtr nativePtr): base (nativePtr)
- {
- }
-
- public static explicit operator IAvnWindow(System.IntPtr nativePtr) => nativePtr == System.IntPtr.Zero ? null : new IAvnWindow(nativePtr);
- ///
- /// No documentation.
- ///
- /// SetEnabled
- /// SetEnabled
- public System.Boolean Enabled
- {
- set => SetEnabled(value);
- }
-
- ///
- /// No documentation.
- ///
- /// SetParent
- /// SetParent
- public Avalonia.Native.Interop.IAvnWindow Parent
- {
- set => SetParent(value);
- }
-
- ///
- /// No documentation.
- ///
- /// SetCanResize
- /// SetCanResize
- public System.Boolean CanResize
- {
- set => SetCanResize(value);
- }
-
- ///
- /// No documentation.
- ///
- /// SetDecorations
- /// SetDecorations
- public Avalonia.Native.Interop.SystemDecorations Decorations
- {
- set => SetDecorations(value);
- }
-
- ///
- /// No documentation.
- ///
- /// SetTitle
- /// SetTitle
- public System.IntPtr Title
- {
- set => SetTitle(value);
- }
-
- ///
- /// No documentation.
- ///
- /// SetTitleBarColor
- /// SetTitleBarColor
- public Avalonia.Native.Interop.AvnColor TitleBarColor
- {
- set => SetTitleBarColor(value);
- }
-
- ///
- /// No documentation.
- ///
- /// SetExtendClientArea
- /// SetExtendClientArea
- public System.Boolean ExtendClientArea
- {
- set => SetExtendClientArea(value);
- }
-
- ///
- /// No documentation.
- ///
- /// SetExtendClientAreaHints
- /// SetExtendClientAreaHints
- public Avalonia.Native.Interop.AvnExtendClientAreaChromeHints ExtendClientAreaHints
- {
- set => SetExtendClientAreaHints(value);
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnWindow::SetEnabled([In] bool enable)
- /// IAvnWindow::SetEnabled
- internal unsafe void SetEnabled(System.Boolean enable)
- {
- System.Byte enable_;
- SharpGen.Runtime.Result __result__;
- enable_ = (System.Byte)(enable ? 1 : 0);
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, enable_, (*(void ***)this._nativePointer)[30]);
- __result__.CheckError();
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnWindow::SetParent([In] IAvnWindow* parent)
- /// IAvnWindow::SetParent
- internal unsafe void SetParent(Avalonia.Native.Interop.IAvnWindow arentRef)
- {
- System.IntPtr arentRef_ = System.IntPtr.Zero;
- SharpGen.Runtime.Result __result__;
- arentRef_ = SharpGen.Runtime.CppObject.ToCallbackPtr(arentRef);
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, (void *)arentRef_, (*(void ***)this._nativePointer)[31]);
- System.GC.KeepAlive(arentRef);
- __result__.CheckError();
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnWindow::SetCanResize([In] bool value)
- /// IAvnWindow::SetCanResize
- internal unsafe void SetCanResize(System.Boolean value)
- {
- System.Byte value_;
- SharpGen.Runtime.Result __result__;
- value_ = (System.Byte)(value ? 1 : 0);
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, value_, (*(void ***)this._nativePointer)[32]);
- __result__.CheckError();
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnWindow::SetDecorations([In] SystemDecorations value)
- /// IAvnWindow::SetDecorations
- internal unsafe void SetDecorations(Avalonia.Native.Interop.SystemDecorations value)
- {
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, unchecked ((System.Int32)value), (*(void ***)this._nativePointer)[33]);
- __result__.CheckError();
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnWindow::SetTitle([In] void* utf8Title)
- /// IAvnWindow::SetTitle
- internal unsafe void SetTitle(System.IntPtr utf8Title)
- {
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, (void *)utf8Title, (*(void ***)this._nativePointer)[34]);
- __result__.CheckError();
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnWindow::SetTitleBarColor([In] AvnColor color)
- /// IAvnWindow::SetTitleBarColor
- internal unsafe void SetTitleBarColor(Avalonia.Native.Interop.AvnColor color)
- {
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint0(this._nativePointer, color, (*(void ***)this._nativePointer)[35]);
- __result__.CheckError();
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnWindow::SetWindowState([In] AvnWindowState state)
- /// IAvnWindow::SetWindowState
- public unsafe void SetWindowState(Avalonia.Native.Interop.AvnWindowState state)
- {
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, unchecked ((System.Int32)state), (*(void ***)this._nativePointer)[36]);
- __result__.CheckError();
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// HRESULT IAvnWindow::GetWindowState([In] AvnWindowState* ret)
- /// IAvnWindow::GetWindowState
- public unsafe Avalonia.Native.Interop.AvnWindowState GetWindowState()
- {
- Avalonia.Native.Interop.AvnWindowState ret;
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, &ret, (*(void ***)this._nativePointer)[37]);
- __result__.CheckError();
- return ret;
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// HRESULT IAvnWindow::TakeFocusFromChildren()
- /// IAvnWindow::TakeFocusFromChildren
- public unsafe void TakeFocusFromChildren()
- {
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, (*(void ***)this._nativePointer)[38]);
- __result__.CheckError();
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnWindow::SetExtendClientArea([In] bool enable)
- /// IAvnWindow::SetExtendClientArea
- internal unsafe void SetExtendClientArea(System.Boolean enable)
- {
- System.Byte enable_;
- SharpGen.Runtime.Result __result__;
- enable_ = (System.Byte)(enable ? 1 : 0);
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, enable_, (*(void ***)this._nativePointer)[39]);
- __result__.CheckError();
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnWindow::SetExtendClientAreaHints([In] AvnExtendClientAreaChromeHints hints)
- /// IAvnWindow::SetExtendClientAreaHints
- internal unsafe void SetExtendClientAreaHints(Avalonia.Native.Interop.AvnExtendClientAreaChromeHints hints)
- {
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, unchecked ((System.Int32)hints), (*(void ***)this._nativePointer)[40]);
- __result__.CheckError();
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// HRESULT IAvnWindow::GetExtendTitleBarHeight([In] double* ret)
- /// IAvnWindow::GetExtendTitleBarHeight
- public unsafe System.Double GetExtendTitleBarHeight()
- {
- System.Double ret;
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, &ret, (*(void ***)this._nativePointer)[41]);
- __result__.CheckError();
- return ret;
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnWindow::SetExtendTitleBarHeight([In] double value)
- /// IAvnWindow::SetExtendTitleBarHeight
- public unsafe void SetExtendTitleBarHeight(System.Double value)
- {
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, value, (*(void ***)this._nativePointer)[42]);
- __result__.CheckError();
- }
- }
-
- [System.Runtime.InteropServices.GuidAttribute("2e2cda0a-9ae5-4f1b-8e20-081a04279f02")]
- public partial class IAvnWindowBase : SharpGen.Runtime.ComObject
- {
- public IAvnWindowBase(System.IntPtr nativePtr): base (nativePtr)
- {
- }
-
- public static explicit operator IAvnWindowBase(System.IntPtr nativePtr) => nativePtr == System.IntPtr.Zero ? null : new IAvnWindowBase(nativePtr);
- ///
- /// No documentation.
- ///
- /// SetTopMost
- /// SetTopMost
- public System.Boolean TopMost
- {
- set => SetTopMost(value);
- }
-
- ///
- /// No documentation.
- ///
- /// SetCursor
- /// SetCursor
- public Avalonia.Native.Interop.IAvnCursor Cursor
- {
- set => SetCursor(value);
- }
-
- ///
- /// No documentation.
- ///
- /// SetMainMenu
- /// SetMainMenu
- public Avalonia.Native.Interop.IAvnMenu MainMenu
- {
- set => SetMainMenu(value);
- }
-
- ///
- /// No documentation.
- ///
- /// SetBlurEnabled
- /// SetBlurEnabled
- public System.Boolean BlurEnabled
- {
- set => SetBlurEnabled(value);
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// HRESULT IAvnWindowBase::Show()
- /// IAvnWindowBase::Show
- public unsafe void Show()
- {
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, (*(void ***)this._nativePointer)[3]);
- __result__.CheckError();
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// HRESULT IAvnWindowBase::Hide()
- /// IAvnWindowBase::Hide
- public unsafe void Hide()
- {
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, (*(void ***)this._nativePointer)[4]);
- __result__.CheckError();
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// HRESULT IAvnWindowBase::Close()
- /// IAvnWindowBase::Close
- public unsafe void Close()
- {
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, (*(void ***)this._nativePointer)[5]);
- __result__.CheckError();
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// HRESULT IAvnWindowBase::Activate()
- /// IAvnWindowBase::Activate
- public unsafe void Activate()
- {
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, (*(void ***)this._nativePointer)[6]);
- __result__.CheckError();
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// HRESULT IAvnWindowBase::GetClientSize([In] AvnSize* ret)
- /// IAvnWindowBase::GetClientSize
- public unsafe Avalonia.Native.Interop.AvnSize GetClientSize()
- {
- Avalonia.Native.Interop.AvnSize ret;
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, &ret, (*(void ***)this._nativePointer)[7]);
- __result__.CheckError();
- return ret;
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// HRESULT IAvnWindowBase::GetScaling([In] double* ret)
- /// IAvnWindowBase::GetScaling
- public unsafe System.Double GetScaling()
- {
- System.Double ret;
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, &ret, (*(void ***)this._nativePointer)[8]);
- __result__.CheckError();
- return ret;
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnWindowBase::SetMinMaxSize([In] AvnSize minSize,[In] AvnSize maxSize)
- /// IAvnWindowBase::SetMinMaxSize
- public unsafe void SetMinMaxSize(Avalonia.Native.Interop.AvnSize minSize, Avalonia.Native.Interop.AvnSize maxSize)
- {
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint0(this._nativePointer, minSize, maxSize, (*(void ***)this._nativePointer)[9]);
- __result__.CheckError();
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnWindowBase::Resize([In] double width,[In] double height)
- /// IAvnWindowBase::Resize
- public unsafe void Resize(System.Double width, System.Double height)
- {
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, width, height, (*(void ***)this._nativePointer)[10]);
- __result__.CheckError();
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnWindowBase::Invalidate([In] AvnRect rect)
- /// IAvnWindowBase::Invalidate
- public unsafe void Invalidate(Avalonia.Native.Interop.AvnRect rect)
- {
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint0(this._nativePointer, rect, (*(void ***)this._nativePointer)[11]);
- __result__.CheckError();
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// HRESULT IAvnWindowBase::BeginMoveDrag()
- /// IAvnWindowBase::BeginMoveDrag
- public unsafe void BeginMoveDrag()
- {
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, (*(void ***)this._nativePointer)[12]);
- __result__.CheckError();
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnWindowBase::BeginResizeDrag([In] AvnWindowEdge edge)
- /// IAvnWindowBase::BeginResizeDrag
- public unsafe void BeginResizeDrag(Avalonia.Native.Interop.AvnWindowEdge edge)
- {
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, unchecked ((System.Int32)edge), (*(void ***)this._nativePointer)[13]);
- __result__.CheckError();
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// HRESULT IAvnWindowBase::GetPosition([In] AvnPoint* ret)
- /// IAvnWindowBase::GetPosition
- public unsafe Avalonia.Native.Interop.AvnPoint GetPosition()
- {
- Avalonia.Native.Interop.AvnPoint ret;
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, &ret, (*(void ***)this._nativePointer)[14]);
- __result__.CheckError();
- return ret;
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnWindowBase::SetPosition([In] AvnPoint point)
- /// IAvnWindowBase::SetPosition
- public unsafe void SetPosition(Avalonia.Native.Interop.AvnPoint point)
- {
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint0(this._nativePointer, point, (*(void ***)this._nativePointer)[15]);
- __result__.CheckError();
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnWindowBase::PointToClient([In] AvnPoint point,[In] AvnPoint* ret)
- /// IAvnWindowBase::PointToClient
- public unsafe Avalonia.Native.Interop.AvnPoint PointToClient(Avalonia.Native.Interop.AvnPoint point)
- {
- Avalonia.Native.Interop.AvnPoint ret;
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint0(this._nativePointer, point, &ret, (*(void ***)this._nativePointer)[16]);
- __result__.CheckError();
- return ret;
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnWindowBase::PointToScreen([In] AvnPoint point,[In] AvnPoint* ret)
- /// IAvnWindowBase::PointToScreen
- public unsafe Avalonia.Native.Interop.AvnPoint PointToScreen(Avalonia.Native.Interop.AvnPoint point)
- {
- Avalonia.Native.Interop.AvnPoint ret;
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint0(this._nativePointer, point, &ret, (*(void ***)this._nativePointer)[17]);
- __result__.CheckError();
- return ret;
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnWindowBase::ThreadSafeSetSwRenderedFrame([In] AvnFramebuffer* fb,[In] IUnknown* dispose)
- /// IAvnWindowBase::ThreadSafeSetSwRenderedFrame
- public unsafe void ThreadSafeSetSwRenderedFrame(ref Avalonia.Native.Interop.AvnFramebuffer fb, SharpGen.Runtime.IUnknown dispose)
- {
- System.IntPtr dispose_ = System.IntPtr.Zero;
- SharpGen.Runtime.Result __result__;
- dispose_ = SharpGen.Runtime.CppObject.ToCallbackPtr(dispose);
- fixed (void *fb_ = &fb)
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, fb_, (void *)dispose_, (*(void ***)this._nativePointer)[18]);
- System.GC.KeepAlive(dispose);
- __result__.CheckError();
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnWindowBase::SetTopMost([In] bool value)
- /// IAvnWindowBase::SetTopMost
- internal unsafe void SetTopMost(System.Boolean value)
- {
- System.Byte value_;
- SharpGen.Runtime.Result __result__;
- value_ = (System.Byte)(value ? 1 : 0);
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, value_, (*(void ***)this._nativePointer)[19]);
- __result__.CheckError();
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnWindowBase::SetCursor([In] IAvnCursor* cursor)
- /// IAvnWindowBase::SetCursor
- internal unsafe void SetCursor(Avalonia.Native.Interop.IAvnCursor cursor)
- {
- System.IntPtr cursor_ = System.IntPtr.Zero;
- SharpGen.Runtime.Result __result__;
- cursor_ = SharpGen.Runtime.CppObject.ToCallbackPtr(cursor);
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, (void *)cursor_, (*(void ***)this._nativePointer)[20]);
- System.GC.KeepAlive(cursor);
- __result__.CheckError();
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// HRESULT IAvnWindowBase::CreateGlRenderTarget([In] IAvnGlSurfaceRenderTarget** ret)
- /// IAvnWindowBase::CreateGlRenderTarget
- public unsafe Avalonia.Native.Interop.IAvnGlSurfaceRenderTarget CreateGlRenderTarget()
- {
- Avalonia.Native.Interop.IAvnGlSurfaceRenderTarget ret;
- System.IntPtr ret_ = System.IntPtr.Zero;
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, &ret_, (*(void ***)this._nativePointer)[21]);
- if (ret_ != System.IntPtr.Zero)
- ret = new Avalonia.Native.Interop.IAvnGlSurfaceRenderTarget(ret_);
- else
- ret = null;
- __result__.CheckError();
- return ret;
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnWindowBase::SetMainMenu([In] IAvnMenu* menu)
- /// IAvnWindowBase::SetMainMenu
- internal unsafe void SetMainMenu(Avalonia.Native.Interop.IAvnMenu menu)
- {
- System.IntPtr menu_ = System.IntPtr.Zero;
- SharpGen.Runtime.Result __result__;
- menu_ = SharpGen.Runtime.CppObject.ToCallbackPtr(menu);
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, (void *)menu_, (*(void ***)this._nativePointer)[22]);
- System.GC.KeepAlive(menu);
- __result__.CheckError();
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// HRESULT IAvnWindowBase::ObtainNSWindowHandle([Out] void** retOut)
- /// IAvnWindowBase::ObtainNSWindowHandle
- public unsafe System.IntPtr ObtainNSWindowHandle()
- {
- System.IntPtr retOut;
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, &retOut, (*(void ***)this._nativePointer)[23]);
- __result__.CheckError();
- return retOut;
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// HRESULT IAvnWindowBase::ObtainNSWindowHandleRetained([Out] void** retOut)
- /// IAvnWindowBase::ObtainNSWindowHandleRetained
- public unsafe System.IntPtr ObtainNSWindowHandleRetained()
- {
- System.IntPtr retOut;
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, &retOut, (*(void ***)this._nativePointer)[24]);
- __result__.CheckError();
- return retOut;
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// HRESULT IAvnWindowBase::ObtainNSViewHandle([Out] void** retOut)
- /// IAvnWindowBase::ObtainNSViewHandle
- public unsafe System.IntPtr ObtainNSViewHandle()
- {
- System.IntPtr retOut;
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, &retOut, (*(void ***)this._nativePointer)[25]);
- __result__.CheckError();
- return retOut;
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// HRESULT IAvnWindowBase::ObtainNSViewHandleRetained([Out] void** retOut)
- /// IAvnWindowBase::ObtainNSViewHandleRetained
- public unsafe System.IntPtr ObtainNSViewHandleRetained()
- {
- System.IntPtr retOut;
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, &retOut, (*(void ***)this._nativePointer)[26]);
- __result__.CheckError();
- return retOut;
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// HRESULT IAvnWindowBase::CreateNativeControlHost([Out] IAvnNativeControlHost** retOut)
- /// IAvnWindowBase::CreateNativeControlHost
- public unsafe Avalonia.Native.Interop.IAvnNativeControlHost CreateNativeControlHost()
- {
- Avalonia.Native.Interop.IAvnNativeControlHost retOut;
- System.IntPtr retOut_ = System.IntPtr.Zero;
- SharpGen.Runtime.Result __result__;
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, &retOut_, (*(void ***)this._nativePointer)[27]);
- if (retOut_ != System.IntPtr.Zero)
- retOut = new Avalonia.Native.Interop.IAvnNativeControlHost(retOut_);
- else
- retOut = null;
- __result__.CheckError();
- return retOut;
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// No documentation.
- /// No documentation.
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnWindowBase::BeginDragAndDropOperation([In] AvnDragDropEffects effects,[In] AvnPoint point,[In] IAvnClipboard* clipboard,[In] IAvnDndResultCallback* cb,[In] void* sourceHandle)
- /// IAvnWindowBase::BeginDragAndDropOperation
- public unsafe void BeginDragAndDropOperation(Avalonia.Native.Interop.AvnDragDropEffects effects, Avalonia.Native.Interop.AvnPoint point, Avalonia.Native.Interop.IAvnClipboard clipboard, Avalonia.Native.Interop.IAvnDndResultCallback cb, System.IntPtr sourceHandle)
- {
- System.IntPtr clipboard_ = System.IntPtr.Zero;
- System.IntPtr cb_ = System.IntPtr.Zero;
- SharpGen.Runtime.Result __result__;
- clipboard_ = SharpGen.Runtime.CppObject.ToCallbackPtr(clipboard);
- cb_ = SharpGen.Runtime.CppObject.ToCallbackPtr(cb);
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint0(this._nativePointer, unchecked ((System.Int32)effects), point, (void *)clipboard_, (void *)cb_, (void *)sourceHandle, (*(void ***)this._nativePointer)[28]);
- System.GC.KeepAlive(clipboard);
- System.GC.KeepAlive(cb);
- __result__.CheckError();
- }
-
- ///
- /// No documentation.
- ///
- /// No documentation.
- /// No documentation.
- /// HRESULT IAvnWindowBase::SetBlurEnabled([In] bool enable)
- /// IAvnWindowBase::SetBlurEnabled
- internal unsafe void SetBlurEnabled(System.Boolean enable)
- {
- System.Byte enable_;
- SharpGen.Runtime.Result __result__;
- enable_ = (System.Byte)(enable ? 1 : 0);
- __result__ = Avalonia.Native.LocalInterop.CalliThisCallint(this._nativePointer, enable_, (*(void ***)this._nativePointer)[29]);
- __result__.CheckError();
- }
- }
-
- class IAvnWindowBaseEventsShadow : SharpGen.Runtime.ComObjectShadow
- {
- protected unsafe class IAvnWindowBaseEventsVtbl : SharpGen.Runtime.ComObjectShadow.ComObjectVtbl
- {
- public IAvnWindowBaseEventsVtbl(int numberOfCallbackMethods): base (numberOfCallbackMethods + 13)
- {
- AddMethod(new PaintDelegate(Paint));
- AddMethod(new ClosedDelegate(Closed));
- AddMethod(new ActivatedDelegate(Activated));
- AddMethod(new DeactivatedDelegate(Deactivated));
- AddMethod(new ResizedDelegate(Resized));
- AddMethod(new PositionChangedDelegate(PositionChanged));
- AddMethod(new RawMouseEventDelegate(RawMouseEvent));
- AddMethod(new RawKeyEventDelegate(RawKeyEvent));
- AddMethod(new RawTextInputEventDelegate(RawTextInputEvent));
- AddMethod(new ScalingChangedDelegate(ScalingChanged));
- AddMethod(new RunRenderPriorityJobsDelegate(RunRenderPriorityJobs));
- AddMethod(new LostFocusDelegate(LostFocus));
- AddMethod(new DragEventDelegate(DragEvent));
- }
-
- [System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(System.Runtime.InteropServices.CallingConvention.ThisCall)]
- private delegate int PaintDelegate(System.IntPtr thisObject);
- private static unsafe int Paint(System.IntPtr thisObject)
- {
- try
- {
- IAvnWindowBaseEvents @this = (IAvnWindowBaseEvents)ToShadow(thisObject).Callback;
- @this.Paint();
- return SharpGen.Runtime.Result.Ok.Code;
- }
- catch (System.Exception __exception__)
- {
- IAvnWindowBaseEvents @this = (IAvnWindowBaseEvents)ToShadow(thisObject).Callback;
- (@this as SharpGen.Runtime.IExceptionCallback)?.RaiseException(__exception__);
- return SharpGen.Runtime.Result.GetResultFromException(__exception__).Code;
- }
- }
-
- [System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(System.Runtime.InteropServices.CallingConvention.ThisCall)]
- private delegate void ClosedDelegate(System.IntPtr thisObject);
- private static unsafe void Closed(System.IntPtr thisObject)
- {
- try
- {
- IAvnWindowBaseEvents @this = (IAvnWindowBaseEvents)ToShadow(thisObject).Callback;
- @this.Closed();
- }
- catch (System.Exception __exception__)
- {
- IAvnWindowBaseEvents @this = (IAvnWindowBaseEvents)ToShadow(thisObject).Callback;
- (@this as SharpGen.Runtime.IExceptionCallback)?.RaiseException(__exception__);
- }
- }
-
- [System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(System.Runtime.InteropServices.CallingConvention.ThisCall)]
- private delegate void ActivatedDelegate(System.IntPtr thisObject);
- private static unsafe void Activated(System.IntPtr thisObject)
- {
- try
- {
- IAvnWindowBaseEvents @this = (IAvnWindowBaseEvents)ToShadow(thisObject).Callback;
- @this.Activated();
- }
- catch (System.Exception __exception__)
- {
- IAvnWindowBaseEvents @this = (IAvnWindowBaseEvents)ToShadow(thisObject).Callback;
- (@this as SharpGen.Runtime.IExceptionCallback)?.RaiseException(__exception__);
- }
- }
-
- [System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(System.Runtime.InteropServices.CallingConvention.ThisCall)]
- private delegate void DeactivatedDelegate(System.IntPtr thisObject);
- private static unsafe void Deactivated(System.IntPtr thisObject)
- {
- try
- {
- IAvnWindowBaseEvents @this = (IAvnWindowBaseEvents)ToShadow(thisObject).Callback;
- @this.Deactivated();
- }
- catch (System.Exception __exception__)
- {
- IAvnWindowBaseEvents @this = (IAvnWindowBaseEvents)ToShadow(thisObject).Callback;
- (@this as SharpGen.Runtime.IExceptionCallback)?.RaiseException(__exception__);
- }
- }
-
- [System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(System.Runtime.InteropServices.CallingConvention.ThisCall)]
- private delegate void ResizedDelegate(System.IntPtr thisObject, void *arg0);
- private static unsafe void Resized(System.IntPtr thisObject, void *param0)
- {
- try
- {
- Avalonia.Native.Interop.AvnSize size = System.Runtime.CompilerServices.Unsafe.AsRef(param0);
- IAvnWindowBaseEvents @this = (IAvnWindowBaseEvents)ToShadow(thisObject).Callback;
- @this.Resized(size);
- }
- catch (System.Exception __exception__)
- {
- IAvnWindowBaseEvents @this = (IAvnWindowBaseEvents)ToShadow(thisObject).Callback;
- (@this as SharpGen.Runtime.IExceptionCallback)?.RaiseException(__exception__);
- }
- }
-
- [System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(System.Runtime.InteropServices.CallingConvention.ThisCall)]
- private delegate void PositionChangedDelegate(System.IntPtr thisObject, Avalonia.Native.Interop.AvnPoint arg0);
- private static unsafe void PositionChanged(System.IntPtr thisObject, Avalonia.Native.Interop.AvnPoint param0)
- {
- try
- {
- Avalonia.Native.Interop.AvnPoint position = default (Avalonia.Native.Interop.AvnPoint);
- position = (Avalonia.Native.Interop.AvnPoint)param0;
- IAvnWindowBaseEvents @this = (IAvnWindowBaseEvents)ToShadow(thisObject).Callback;
- @this.PositionChanged(position);
- }
- catch (System.Exception __exception__)
- {
- IAvnWindowBaseEvents @this = (IAvnWindowBaseEvents)ToShadow(thisObject).Callback;
- (@this as SharpGen.Runtime.IExceptionCallback)?.RaiseException(__exception__);
- }
- }
-
- [System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(System.Runtime.InteropServices.CallingConvention.ThisCall)]
- private delegate void RawMouseEventDelegate(System.IntPtr thisObject, int arg0, System.UInt32 arg1, int arg2, Avalonia.Native.Interop.AvnPoint arg3, Avalonia.Native.Interop.AvnVector arg4);
- private static unsafe void RawMouseEvent(System.IntPtr thisObject, int param0, System.UInt32 param1, int param2, Avalonia.Native.Interop.AvnPoint param3, Avalonia.Native.Interop.AvnVector param4)
- {
- try
- {
- Avalonia.Native.Interop.AvnRawMouseEventType type = default (Avalonia.Native.Interop.AvnRawMouseEventType);
- type = (Avalonia.Native.Interop.AvnRawMouseEventType)param0;
- System.UInt32 timeStamp = default (System.UInt32);
- timeStamp = (System.UInt32)param1;
- Avalonia.Native.Interop.AvnInputModifiers modifiers = default (Avalonia.Native.Interop.AvnInputModifiers);
- modifiers = (Avalonia.Native.Interop.AvnInputModifiers)param2;
- Avalonia.Native.Interop.AvnPoint point = default (Avalonia.Native.Interop.AvnPoint);
- point = (Avalonia.Native.Interop.AvnPoint)param3;
- Avalonia.Native.Interop.AvnVector delta = default (Avalonia.Native.Interop.AvnVector);
- delta = (Avalonia.Native.Interop.AvnVector)param4;
- IAvnWindowBaseEvents @this = (IAvnWindowBaseEvents)ToShadow(thisObject).Callback;
- @this.RawMouseEvent(type, timeStamp, modifiers, point, delta);
- }
- catch (System.Exception __exception__)
- {
- IAvnWindowBaseEvents @this = (IAvnWindowBaseEvents)ToShadow(thisObject).Callback;
- (@this as SharpGen.Runtime.IExceptionCallback)?.RaiseException(__exception__);
- }
- }
-
- [System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(System.Runtime.InteropServices.CallingConvention.ThisCall)]
- private delegate System.Byte RawKeyEventDelegate(System.IntPtr thisObject, int arg0, System.UInt32 arg1, int arg2, System.UInt32 arg3);
- private static unsafe System.Byte RawKeyEvent(System.IntPtr thisObject, int param0, System.UInt32 param1, int param2, System.UInt32 param3)
- {
- try
- {
- System.Boolean __result__ = default (System.Boolean);
- System.Byte __result__native;
- Avalonia.Native.Interop.AvnRawKeyEventType type = default (Avalonia.Native.Interop.AvnRawKeyEventType);
- type = (Avalonia.Native.Interop.AvnRawKeyEventType)param0;
- System.UInt32 timeStamp = default (System.UInt32);
- timeStamp = (System.UInt32)param1;
- Avalonia.Native.Interop.AvnInputModifiers modifiers = default (Avalonia.Native.Interop.AvnInputModifiers);
- modifiers = (Avalonia.Native.Interop.AvnInputModifiers)param2;
- System.UInt32 key = default (System.UInt32);
- key = (System.UInt32)param3;
- IAvnWindowBaseEvents @this = (IAvnWindowBaseEvents)ToShadow(thisObject).Callback;
- __result__ = @this.RawKeyEvent(type, timeStamp, modifiers, key);
- __result__native = (System.Byte)(__result__ ? 1 : 0);
- return __result__native;
- }
- catch (System.Exception __exception__)
- {
- IAvnWindowBaseEvents @this = (IAvnWindowBaseEvents)ToShadow(thisObject).Callback;
- (@this as SharpGen.Runtime.IExceptionCallback)?.RaiseException(__exception__);
- return default (System.Byte);
- }
- }
-
- [System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(System.Runtime.InteropServices.CallingConvention.ThisCall)]
- private delegate System.Byte RawTextInputEventDelegate(System.IntPtr thisObject, System.UInt32 arg0, void *arg1);
- private static unsafe System.Byte RawTextInputEvent(System.IntPtr thisObject, System.UInt32 param0, void *param1)
- {
- try
- {
- System.Boolean __result__ = default (System.Boolean);
- System.Byte __result__native;
- System.UInt32 timeStamp = default (System.UInt32);
- timeStamp = (System.UInt32)param0;
- System.String text = default (System.String);
- System.IntPtr text_ = (System.IntPtr)param1;
- IAvnWindowBaseEvents @this = (IAvnWindowBaseEvents)ToShadow(thisObject).Callback;
- text = System.Runtime.InteropServices.Marshal.PtrToStringAnsi(text_);
- __result__ = @this.RawTextInputEvent(timeStamp, text);
- __result__native = (System.Byte)(__result__ ? 1 : 0);
- return __result__native;
- }
- catch (System.Exception __exception__)
- {
- IAvnWindowBaseEvents @this = (IAvnWindowBaseEvents)ToShadow(thisObject).Callback;
- (@this as SharpGen.Runtime.IExceptionCallback)?.RaiseException(__exception__);
- return default (System.Byte);
- }
- }
-
- [System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(System.Runtime.InteropServices.CallingConvention.ThisCall)]
- private delegate void ScalingChangedDelegate(System.IntPtr thisObject, double arg0);
- private static unsafe void ScalingChanged(System.IntPtr thisObject, double param0)
- {
- try
- {
- System.Double scaling = default (System.Double);
- scaling = (System.Double)param0;
- IAvnWindowBaseEvents @this = (IAvnWindowBaseEvents)ToShadow(thisObject).Callback;
- @this.ScalingChanged(scaling);
- }
- catch (System.Exception __exception__)
- {
- IAvnWindowBaseEvents @this = (IAvnWindowBaseEvents)ToShadow(thisObject).Callback;
- (@this as SharpGen.Runtime.IExceptionCallback)?.RaiseException(__exception__);
- }
- }
-
- [System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(System.Runtime.InteropServices.CallingConvention.ThisCall)]
- private delegate void RunRenderPriorityJobsDelegate(System.IntPtr thisObject);
- private static unsafe void RunRenderPriorityJobs(System.IntPtr thisObject)
- {
- try
- {
- IAvnWindowBaseEvents @this = (IAvnWindowBaseEvents)ToShadow(thisObject).Callback;
- @this.RunRenderPriorityJobs();
- }
- catch (System.Exception __exception__)
- {
- IAvnWindowBaseEvents @this = (IAvnWindowBaseEvents)ToShadow(thisObject).Callback;
- (@this as SharpGen.Runtime.IExceptionCallback)?.RaiseException(__exception__);
- }
- }
-
- [System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(System.Runtime.InteropServices.CallingConvention.ThisCall)]
- private delegate void LostFocusDelegate(System.IntPtr thisObject);
- private static unsafe void LostFocus(System.IntPtr thisObject)
- {
- try
- {
- IAvnWindowBaseEvents @this = (IAvnWindowBaseEvents)ToShadow(thisObject).Callback;
- @this.LostFocus();
- }
- catch (System.Exception __exception__)
- {
- IAvnWindowBaseEvents @this = (IAvnWindowBaseEvents)ToShadow(thisObject).Callback;
- (@this as SharpGen.Runtime.IExceptionCallback)?.RaiseException(__exception__);
- }
- }
-
- [System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(System.Runtime.InteropServices.CallingConvention.ThisCall)]
- private delegate Avalonia.Native.Interop.AvnDragDropEffects DragEventDelegate(System.IntPtr thisObject, int arg0, Avalonia.Native.Interop.AvnPoint arg1, int arg2, int arg3, void *arg4, void *arg5);
- private static unsafe Avalonia.Native.Interop.AvnDragDropEffects DragEvent(System.IntPtr thisObject, int param0, Avalonia.Native.Interop.AvnPoint param1, int param2, int param3, void *param4, void *param5)
- {
- try
- {
- Avalonia.Native.Interop.AvnDragDropEffects __result__ = default (Avalonia.Native.Interop.AvnDragDropEffects);
- Avalonia.Native.Interop.AvnDragEventType type = default (Avalonia.Native.Interop.AvnDragEventType);
- type = (Avalonia.Native.Interop.AvnDragEventType)param0;
- Avalonia.Native.Interop.AvnPoint position = default (Avalonia.Native.Interop.AvnPoint);
- position = (Avalonia.Native.Interop.AvnPoint)param1;
- Avalonia.Native.Interop.AvnInputModifiers modifiers = default (Avalonia.Native.Interop.AvnInputModifiers);
- modifiers = (Avalonia.Native.Interop.AvnInputModifiers)param2;
- Avalonia.Native.Interop.AvnDragDropEffects effects = default (Avalonia.Native.Interop.AvnDragDropEffects);
- effects = (Avalonia.Native.Interop.AvnDragDropEffects)param3;
- Avalonia.Native.Interop.IAvnClipboard clipboard = default (Avalonia.Native.Interop.IAvnClipboard);
- System.IntPtr clipboard_ = (System.IntPtr)param4;
- System.IntPtr dataObjectHandle = default (System.IntPtr);
- dataObjectHandle = (System.IntPtr)param5;
- IAvnWindowBaseEvents @this = (IAvnWindowBaseEvents)ToShadow(thisObject).Callback;
- if (clipboard_ != System.IntPtr.Zero)
- clipboard = new Avalonia.Native.Interop.IAvnClipboard(clipboard_);
- else
- clipboard = null;
- __result__ = @this.DragEvent(type, position, modifiers, effects, clipboard, dataObjectHandle);
- return __result__;
- }
- catch (System.Exception __exception__)
- {
- IAvnWindowBaseEvents @this = (IAvnWindowBaseEvents)ToShadow(thisObject).Callback;
- (@this as SharpGen.Runtime.IExceptionCallback)?.RaiseException(__exception__);
- return default (Avalonia.Native.Interop.AvnDragDropEffects);
- }
- }
- }
-
- protected override SharpGen.Runtime.CppObjectVtbl Vtbl
- {
- get;
- }
-
- = new Avalonia.Native.Interop.IAvnWindowBaseEventsShadow.IAvnWindowBaseEventsVtbl(0);
- }
-
- [System.Runtime.InteropServices.GuidAttribute("2e2cda0a-9ae5-4f1b-8e20-081a04279f05"), SharpGen.Runtime.ShadowAttribute(typeof (Avalonia.Native.Interop.IAvnWindowBaseEventsShadow))]
- public partial interface IAvnWindowBaseEvents : SharpGen.Runtime.IUnknown
- {
- void Paint();
- void Closed();
- void Activated();
- void Deactivated();
- void Resized(Avalonia.Native.Interop.AvnSize size);
- void PositionChanged(Avalonia.Native.Interop.AvnPoint position);
- void RawMouseEvent(Avalonia.Native.Interop.AvnRawMouseEventType type, System.UInt32 timeStamp, Avalonia.Native.Interop.AvnInputModifiers modifiers, Avalonia.Native.Interop.AvnPoint point, Avalonia.Native.Interop.AvnVector delta);
- System.Boolean RawKeyEvent(Avalonia.Native.Interop.AvnRawKeyEventType type, System.UInt32 timeStamp, Avalonia.Native.Interop.AvnInputModifiers modifiers, System.UInt32 key);
- System.Boolean RawTextInputEvent(System.UInt32 timeStamp, System.String text);
- void ScalingChanged(System.Double scaling);
- void RunRenderPriorityJobs();
- void LostFocus();
- Avalonia.Native.Interop.AvnDragDropEffects DragEvent(Avalonia.Native.Interop.AvnDragEventType type, Avalonia.Native.Interop.AvnPoint position, Avalonia.Native.Interop.AvnInputModifiers modifiers, Avalonia.Native.Interop.AvnDragDropEffects effects, Avalonia.Native.Interop.IAvnClipboard clipboard, System.IntPtr dataObjectHandle);
- }
-
- class IAvnWindowEventsShadow : Avalonia.Native.Interop.IAvnWindowBaseEventsShadow
- {
- protected unsafe class IAvnWindowEventsVtbl : Avalonia.Native.Interop.IAvnWindowBaseEventsShadow.IAvnWindowBaseEventsVtbl
- {
- public IAvnWindowEventsVtbl(int numberOfCallbackMethods): base (numberOfCallbackMethods + 3)
- {
- AddMethod(new ClosingDelegate(Closing));
- AddMethod(new WindowStateChangedDelegate(WindowStateChanged));
- AddMethod(new GotInputWhenDisabledDelegate(GotInputWhenDisabled));
- }
-
- [System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(System.Runtime.InteropServices.CallingConvention.ThisCall)]
- private delegate System.Byte ClosingDelegate(System.IntPtr thisObject);
- private static unsafe System.Byte Closing(System.IntPtr thisObject)
- {
- try
- {
- System.Boolean __result__ = default (System.Boolean);
- System.Byte __result__native;
- IAvnWindowEvents @this = (IAvnWindowEvents)ToShadow(thisObject).Callback;
- __result__ = @this.Closing();
- __result__native = (System.Byte)(__result__ ? 1 : 0);
- return __result__native;
- }
- catch (System.Exception __exception__)
- {
- IAvnWindowEvents @this = (IAvnWindowEvents)ToShadow(thisObject).Callback;
- (@this as SharpGen.Runtime.IExceptionCallback)?.RaiseException(__exception__);
- return default (System.Byte);
- }
- }
-
- [System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(System.Runtime.InteropServices.CallingConvention.ThisCall)]
- private delegate void WindowStateChangedDelegate(System.IntPtr thisObject, int arg0);
- private static unsafe void WindowStateChanged(System.IntPtr thisObject, int param0)
- {
- try
- {
- Avalonia.Native.Interop.AvnWindowState state = default (Avalonia.Native.Interop.AvnWindowState);
- state = (Avalonia.Native.Interop.AvnWindowState)param0;
- IAvnWindowEvents @this = (IAvnWindowEvents)ToShadow(thisObject).Callback;
- @this.WindowStateChanged(state);
- }
- catch (System.Exception __exception__)
- {
- IAvnWindowEvents @this = (IAvnWindowEvents)ToShadow(thisObject).Callback;
- (@this as SharpGen.Runtime.IExceptionCallback)?.RaiseException(__exception__);
- }
- }
-
- [System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(System.Runtime.InteropServices.CallingConvention.ThisCall)]
- private delegate void GotInputWhenDisabledDelegate(System.IntPtr thisObject);
- private static unsafe void GotInputWhenDisabled(System.IntPtr thisObject)
- {
- try
- {
- IAvnWindowEvents @this = (IAvnWindowEvents)ToShadow(thisObject).Callback;
- @this.GotInputWhenDisabled();
- }
- catch (System.Exception __exception__)
- {
- IAvnWindowEvents @this = (IAvnWindowEvents)ToShadow(thisObject).Callback;
- (@this as SharpGen.Runtime.IExceptionCallback)?.RaiseException(__exception__);
- }
- }
- }
-
- protected override SharpGen.Runtime.CppObjectVtbl Vtbl
- {
- get;
- }
-
- = new Avalonia.Native.Interop.IAvnWindowEventsShadow.IAvnWindowEventsVtbl(0);
- }
-
- [System.Runtime.InteropServices.GuidAttribute("2e2cda0a-9ae5-4f1b-8e20-081a04279f06"), SharpGen.Runtime.ShadowAttribute(typeof (Avalonia.Native.Interop.IAvnWindowEventsShadow))]
- public partial interface IAvnWindowEvents : Avalonia.Native.Interop.IAvnWindowBaseEvents
- {
- System.Boolean Closing();
- void WindowStateChanged(Avalonia.Native.Interop.AvnWindowState state);
- void GotInputWhenDisabled();
- }
-}
\ No newline at end of file
diff --git a/src/Avalonia.Native/Generated/LocalInterop.cs b/src/Avalonia.Native/Generated/LocalInterop.cs
deleted file mode 100644
index 41e69a6bdc..0000000000
--- a/src/Avalonia.Native/Generated/LocalInterop.cs
+++ /dev/null
@@ -1,202 +0,0 @@
-//
-
-namespace Avalonia.Native
-{
- internal static partial class LocalInterop
- {
- public static unsafe int CalliThisCallint(void *thisObject, void *methodPtr)
- {
- throw null;
- }
-
- public static unsafe void CalliThisCallvoid(void *thisObject, void *methodPtr)
- {
- throw null;
- }
-
- public static unsafe void CalliThisCallvoid(void *thisObject, void *param0, void *methodPtr)
- {
- throw null;
- }
-
- public static unsafe void CalliThisCallvoid0(void *thisObject, Avalonia.Native.Interop.AvnPoint param0, void *methodPtr)
- {
- throw null;
- }
-
- public static unsafe void CalliThisCallvoid0(void *thisObject, int param0, System.UInt32 param1, int param2, Avalonia.Native.Interop.AvnPoint param3, Avalonia.Native.Interop.AvnVector param4, void *methodPtr)
- {
- throw null;
- }
-
- public static unsafe System.Byte CalliThisCallSystemByte(void *thisObject, int param0, System.UInt32 param1, int param2, System.UInt32 param3, void *methodPtr)
- {
- throw null;
- }
-
- public static unsafe System.Byte CalliThisCallSystemByte(void *thisObject, System.UInt32 param0, void *param1, void *methodPtr)
- {
- throw null;
- }
-
- public static unsafe void CalliThisCallvoid(void *thisObject, double param0, void *methodPtr)
- {
- throw null;
- }
-
- public static unsafe Avalonia.Native.Interop.AvnDragDropEffects CalliThisCallAvaloniaNativeInteropAvnDragDropEffects0(void *thisObject, int param0, Avalonia.Native.Interop.AvnPoint param1, int param2, int param3, void *param4, void *param5, void *methodPtr)
- {
- throw null;
- }
-
- public static unsafe System.Byte CalliThisCallSystemByte(void *thisObject, void *methodPtr)
- {
- throw null;
- }
-
- public static unsafe void CalliThisCallvoid(void *thisObject, int param0, void *methodPtr)
- {
- throw null;
- }
-
- public static unsafe int CalliThisCallint(void *thisObject, void *param0, void *methodPtr)
- {
- throw null;
- }
-
- public static unsafe int CalliThisCallint0(void *thisObject, Avalonia.Native.Interop.AvnSize param0, Avalonia.Native.Interop.AvnSize param1, void *methodPtr)
- {
- throw null;
- }
-
- public static unsafe int CalliThisCallint(void *thisObject, double param0, double param1, void *methodPtr)
- {
- throw null;
- }
-
- public static unsafe int CalliThisCallint0(void *thisObject, Avalonia.Native.Interop.AvnRect param0, void *methodPtr)
- {
- throw null;
- }
-
- public static unsafe int CalliThisCallint(void *thisObject, int param0, void *methodPtr)
- {
- throw null;
- }
-
- public static unsafe int CalliThisCallint0(void *thisObject, Avalonia.Native.Interop.AvnPoint param0, void *methodPtr)
- {
- throw null;
- }
-
- public static unsafe int CalliThisCallint0(void *thisObject, Avalonia.Native.Interop.AvnPoint param0, void *param1, void *methodPtr)
- {
- throw null;
- }
-
- public static unsafe int CalliThisCallint(void *thisObject, void *param0, void *param1, void *methodPtr)
- {
- throw null;
- }
-
- public static unsafe int CalliThisCallint(void *thisObject, System.Byte param0, void *methodPtr)
- {
- throw null;
- }
-
- public static unsafe int CalliThisCallint0(void *thisObject, int param0, Avalonia.Native.Interop.AvnPoint param1, void *param2, void *param3, void *param4, void *methodPtr)
- {
- throw null;
- }
-
- public static unsafe int CalliThisCallint0(void *thisObject, Avalonia.Native.Interop.AvnColor param0, void *methodPtr)
- {
- throw null;
- }
-
- public static unsafe int CalliThisCallint(void *thisObject, double param0, void *methodPtr)
- {
- throw null;
- }
-
- public static unsafe System.IntPtr CalliThisCallSystemIntPtr(void *thisObject, void *methodPtr)
- {
- throw null;
- }
-
- public static unsafe System.IntPtr CalliThisCallSystemIntPtr(void *thisObject, int param0, int param1, void *param2, void *methodPtr)
- {
- throw null;
- }
-
- public static unsafe void CalliThisCallvoid(void *thisObject, int param0, void *param1, void *methodPtr)
- {
- throw null;
- }
-
- public static unsafe void CalliThisCallvoid(void *thisObject, void *param0, void *param1, void *param2, void *param3, void *methodPtr)
- {
- throw null;
- }
-
- public static unsafe void CalliThisCallvoid(void *thisObject, void *param0, void *param1, System.Byte param2, void *param3, void *param4, void *param5, void *param6, void *methodPtr)
- {
- throw null;
- }
-
- public static unsafe void CalliThisCallvoid(void *thisObject, void *param0, void *param1, void *param2, void *param3, void *param4, void *param5, void *methodPtr)
- {
- throw null;
- }
-
- public static unsafe int CalliThisCallint(void *thisObject, int param0, void *param1, void *methodPtr)
- {
- throw null;
- }
-
- public static unsafe int CalliThisCallint(void *thisObject, void *param0, void *param1, int param2, void *methodPtr)
- {
- throw null;
- }
-
- public static unsafe System.IntPtr CalliThisCallSystemIntPtr(void *thisObject, void *param0, void *methodPtr)
- {
- throw null;
- }
-
- public static unsafe int CalliThisCallint(void *thisObject, void *param0, int param1, void *methodPtr)
- {
- throw null;
- }
-
- public static unsafe System.UInt32 CalliThisCallSystemUInt32(void *thisObject, void *methodPtr)
- {
- throw null;
- }
-
- public static unsafe int CalliThisCallint(void *thisObject, System.UInt32 param0, void *param1, void *methodPtr)
- {
- throw null;
- }
-
- public static unsafe void CalliThisCallvoid(void *thisObject, float param0, float param1, float param2, float param3, void *methodPtr)
- {
- throw null;
- }
-
- public static unsafe void CalliThisCallvoid(void *thisObject, float param0, float param1, void *methodPtr)
- {
- throw null;
- }
-
- public static unsafe int CalliThisCallint(void *thisObject, void *param0, void *param1, void *param2, void *methodPtr)
- {
- throw null;
- }
-
- public static unsafe void CalliThisCallvoid(void *thisObject, int param0, System.Byte param1, void *methodPtr)
- {
- throw null;
- }
- }
-}
\ No newline at end of file
diff --git a/src/Avalonia.Native/Generated/Structures.cs b/src/Avalonia.Native/Generated/Structures.cs
deleted file mode 100644
index fc871a2516..0000000000
--- a/src/Avalonia.Native/Generated/Structures.cs
+++ /dev/null
@@ -1,246 +0,0 @@
-//
-
-namespace Avalonia.Native.Interop
-{
- ///
- /// No documentation.
- ///
- /// AvnColor
- /// AvnColor
- [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, Pack = 0, CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
- public partial struct AvnColor
- {
- ///
- /// No documentation.
- ///
- /// Alpha
- /// Alpha
- public System.Byte Alpha;
- ///
- /// No documentation.
- ///
- /// Red
- /// Red
- public System.Byte Red;
- ///
- /// No documentation.
- ///
- /// Green
- /// Green
- public System.Byte Green;
- ///
- /// No documentation.
- ///
- /// Blue
- /// Blue
- public System.Byte Blue;
- }
-
- ///
- /// No documentation.
- ///
- /// AvnFramebuffer
- /// AvnFramebuffer
- [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, Pack = 0, CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
- public partial struct AvnFramebuffer
- {
- ///
- /// No documentation.
- ///
- /// Data
- /// Data
- public System.IntPtr Data;
- ///
- /// No documentation.
- ///
- /// Width
- /// Width
- public System.Int32 Width;
- ///
- /// No documentation.
- ///
- /// Height
- /// Height
- public System.Int32 Height;
- ///
- /// No documentation.
- ///
- /// Stride
- /// Stride
- public System.Int32 Stride;
- ///
- /// No documentation.
- ///
- /// Dpi
- /// Dpi
- public Avalonia.Native.Interop.AvnVector Dpi;
- ///
- /// No documentation.
- ///
- /// PixelFormat
- /// PixelFormat
- public Avalonia.Native.Interop.AvnPixelFormat PixelFormat;
- }
-
- ///
- /// No documentation.
- ///
- /// AvnPixelSize
- /// AvnPixelSize
- [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, Pack = 0, CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
- public partial struct AvnPixelSize
- {
- ///
- /// No documentation.
- ///
- /// Width
- /// Width
- public System.Int32 Width;
- ///
- /// No documentation.
- ///
- /// Height
- /// Height
- public System.Int32 Height;
- }
-
- ///
- /// No documentation.
- ///
- /// AvnPoint
- /// AvnPoint
- [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, Pack = 0, CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
- public partial struct AvnPoint
- {
- ///
- /// No documentation.
- ///
- /// X
- /// X
- public System.Double X;
- ///
- /// No documentation.
- ///
- /// Y
- /// Y
- public System.Double Y;
- }
-
- ///
- /// No documentation.
- ///
- /// AvnRect
- /// AvnRect
- [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, Pack = 0, CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
- public partial struct AvnRect
- {
- ///
- /// No documentation.
- ///
- /// X
- /// X
- public System.Double X;
- ///
- /// No documentation.
- ///
- /// Y
- /// Y
- public System.Double Y;
- ///
- /// No documentation.
- ///
- /// Width
- /// Width
- public System.Double Width;
- ///
- /// No documentation.
- ///
- /// Height
- /// Height
- public System.Double Height;
- }
-
- ///
- /// No documentation.
- ///
- /// AvnScreen
- /// AvnScreen
- [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, Pack = 0, CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
- public partial struct AvnScreen
- {
- ///
- /// No documentation.
- ///
- /// Bounds
- /// Bounds
- public Avalonia.Native.Interop.AvnRect Bounds;
- ///
- /// No documentation.
- ///
- /// WorkingArea
- /// WorkingArea
- public Avalonia.Native.Interop.AvnRect WorkingArea;
- ///
- /// No documentation.
- ///
- /// PixelDensity
- /// PixelDensity
- public System.Single PixelDensity;
- ///
- /// No documentation.
- ///
- /// Primary
- /// Primary
- public bool Primary
- {
- get => 0 != _Primary;
- set => _Primary = (System.Byte)(value ? 1 : 0);
- }
-
- internal System.Byte _Primary;
- }
-
- ///
- /// No documentation.
- ///
- /// AvnSize
- /// AvnSize
- [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, Pack = 0, CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
- public partial struct AvnSize
- {
- ///
- /// No documentation.
- ///
- /// Width
- /// Width
- public System.Double Width;
- ///
- /// No documentation.
- ///
- /// Height
- /// Height
- public System.Double Height;
- }
-
- ///
- /// No documentation.
- ///
- /// AvnVector
- /// AvnVector
- [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, Pack = 0, CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
- public partial struct AvnVector
- {
- ///
- /// No documentation.
- ///
- /// X
- /// X
- public System.Double X;
- ///
- /// No documentation.
- ///
- /// Y
- /// Y
- public System.Double Y;
- }
-}
\ No newline at end of file
diff --git a/src/Avalonia.Native/Helpers.cs b/src/Avalonia.Native/Helpers.cs
index 25e8250232..564434a04c 100644
--- a/src/Avalonia.Native/Helpers.cs
+++ b/src/Avalonia.Native/Helpers.cs
@@ -2,7 +2,7 @@
namespace Avalonia.Native
{
- public static class Helpers
+ internal static class Helpers
{
public static Point ToAvaloniaPoint (this AvnPoint pt)
{
diff --git a/src/Avalonia.Native/IAvnMenu.cs b/src/Avalonia.Native/IAvnMenu.cs
index 8a49559a02..dd9464284f 100644
--- a/src/Avalonia.Native/IAvnMenu.cs
+++ b/src/Avalonia.Native/IAvnMenu.cs
@@ -22,15 +22,23 @@ namespace Avalonia.Native.Interop
}
}
- public partial class IAvnMenu
+ partial interface IAvnMenu
+ {
+ void RaiseNeedsUpdate();
+ void Deinitialise();
+ }
+}
+namespace Avalonia.Native.Interop.Impl
+{
+ partial class __MicroComIAvnMenuProxy
{
private MenuEvents _events;
private AvaloniaNativeMenuExporter _exporter;
- private List _menuItems = new List();
- private Dictionary _menuItemLookup = new Dictionary();
+ private List<__MicroComIAvnMenuItemProxy> _menuItems = new List<__MicroComIAvnMenuItemProxy>();
+ private Dictionary _menuItemLookup = new Dictionary();
private CompositeDisposable _propertyDisposables = new CompositeDisposable();
- internal void RaiseNeedsUpdate()
+ public void RaiseNeedsUpdate()
{
(ManagedMenu as INativeMenuExporterEventsImplBridge).RaiseNeedsUpdate();
@@ -39,11 +47,11 @@ namespace Avalonia.Native.Interop
internal NativeMenu ManagedMenu { get; private set; }
- public static IAvnMenu Create(IAvaloniaNativeFactory factory)
+ public static __MicroComIAvnMenuProxy Create(IAvaloniaNativeFactory factory)
{
var events = new MenuEvents();
- var menu = factory.CreateMenu(events);
+ var menu = (__MicroComIAvnMenuProxy)factory.CreateMenu(events);
events.Initialise(menu);
@@ -60,7 +68,7 @@ namespace Avalonia.Native.Interop
}
}
- private void RemoveAndDispose(IAvnMenuItem item)
+ private void RemoveAndDispose(__MicroComIAvnMenuItemProxy item)
{
_menuItemLookup.Remove(item.ManagedMenuItem);
_menuItems.Remove(item);
@@ -70,7 +78,7 @@ namespace Avalonia.Native.Interop
item.Dispose();
}
- private void MoveExistingTo(int index, IAvnMenuItem item)
+ private void MoveExistingTo(int index, __MicroComIAvnMenuItemProxy item)
{
_menuItems.Remove(item);
_menuItems.Insert(index, item);
@@ -79,7 +87,7 @@ namespace Avalonia.Native.Interop
InsertItem(index, item);
}
- private IAvnMenuItem CreateNewAt(IAvaloniaNativeFactory factory, int index, NativeMenuItemBase item)
+ private __MicroComIAvnMenuItemProxy CreateNewAt(IAvaloniaNativeFactory factory, int index, NativeMenuItemBase item)
{
var result = CreateNew(factory, item);
@@ -93,9 +101,11 @@ namespace Avalonia.Native.Interop
return result;
}
- private IAvnMenuItem CreateNew(IAvaloniaNativeFactory factory, NativeMenuItemBase item)
+ private __MicroComIAvnMenuItemProxy CreateNew(IAvaloniaNativeFactory factory, NativeMenuItemBase item)
{
- var nativeItem = item is NativeMenuItemSeperator ? factory.CreateMenuItemSeperator() : factory.CreateMenuItem();
+ var nativeItem = (__MicroComIAvnMenuItemProxy)(item is NativeMenuItemSeperator ?
+ factory.CreateMenuItemSeperator() :
+ factory.CreateMenuItem());
nativeItem.ManagedMenuItem = item;
return nativeItem;
@@ -108,16 +118,11 @@ namespace Avalonia.Native.Interop
((INotifyCollectionChanged)ManagedMenu.Items).CollectionChanged += OnMenuItemsChanged;
- if (!string.IsNullOrWhiteSpace(title))
- {
- using (var buffer = new Utf8Buffer(title))
- {
- Title = buffer.DangerousGetHandle();
- }
- }
+ if (!string.IsNullOrWhiteSpace(title))
+ SetTitle(title);
}
- internal void Deinitialise()
+ public void Deinitialise()
{
((INotifyCollectionChanged)ManagedMenu.Items).CollectionChanged -= OnMenuItemsChanged;
@@ -137,7 +142,7 @@ namespace Avalonia.Native.Interop
for (int i = 0; i < menu.Items.Count; i++)
{
- IAvnMenuItem nativeItem;
+ __MicroComIAvnMenuItemProxy nativeItem;
if (i >= _menuItems.Count)
{
diff --git a/src/Avalonia.Native/IAvnMenuItem.cs b/src/Avalonia.Native/IAvnMenuItem.cs
index c8819d1994..97838f8dea 100644
--- a/src/Avalonia.Native/IAvnMenuItem.cs
+++ b/src/Avalonia.Native/IAvnMenuItem.cs
@@ -7,37 +7,35 @@ using Avalonia.Platform.Interop;
namespace Avalonia.Native.Interop
{
- public partial class IAvnMenuItem
+ partial interface IAvnMenuItem
{
- private IAvnMenu _subMenu;
+
+ }
+}
+namespace Avalonia.Native.Interop.Impl
+{
+ partial class __MicroComIAvnMenuItemProxy
+ {
+ private __MicroComIAvnMenuProxy _subMenu;
private CompositeDisposable _propertyDisposables = new CompositeDisposable();
private IDisposable _currentActionDisposable;
public NativeMenuItemBase ManagedMenuItem { get; set; }
- private void UpdateTitle(string title)
- {
- using (var buffer = new Utf8Buffer(string.IsNullOrWhiteSpace(title) ? "" : title))
- {
- Title = buffer.DangerousGetHandle();
- }
- }
+ private void UpdateTitle(string title) => SetTitle(title ?? "");
- private void UpdateIsChecked(bool isChecked)
- {
- IsChecked = isChecked;
- }
+ private void UpdateIsChecked(bool isChecked) => SetIsChecked(isChecked.AsComBool());
private void UpdateToggleType(NativeMenuItemToggleType toggleType)
{
- ToggleType = (AvnMenuItemToggleType)toggleType;
+ SetToggleType((AvnMenuItemToggleType)toggleType);
}
private unsafe void UpdateIcon (IBitmap icon)
{
if(icon is null)
{
- SetIcon(IntPtr.Zero, 0);
+ SetIcon(null, IntPtr.Zero);
}
else
{
@@ -49,7 +47,7 @@ namespace Avalonia.Native.Interop
fixed(void* ptr = imageData)
{
- SetIcon(new IntPtr(ptr), imageData.Length);
+ SetIcon(ptr, new IntPtr(imageData.Length));
}
}
}
@@ -57,12 +55,9 @@ namespace Avalonia.Native.Interop
private void UpdateGesture(Input.KeyGesture gesture)
{
- // todo ensure backend can cope with setting null gesture.
- using (var buffer = new Utf8Buffer(gesture == null ? "" : OsxUnicodeKeys.ConvertOSXSpecialKeyCodes(gesture.Key)))
- {
- var modifiers = gesture == null ? AvnInputModifiers.AvnInputModifiersNone : (AvnInputModifiers)gesture.KeyModifiers;
- SetGesture(buffer.DangerousGetHandle(), modifiers);
- }
+ var modifiers = gesture == null ? AvnInputModifiers.AvnInputModifiersNone : (AvnInputModifiers)gesture.KeyModifiers;
+ var key = gesture == null ? AvnKey.AvnKeyNone : (AvnKey)gesture.Key;
+ SetGesture(key, modifiers);
}
private void UpdateAction(NativeMenuItem item)
@@ -153,7 +148,7 @@ namespace Avalonia.Native.Interop
{
if (_subMenu == null)
{
- _subMenu = IAvnMenu.Create(factory);
+ _subMenu = __MicroComIAvnMenuProxy.Create(factory);
_subMenu.Initialise(exporter, item.Menu, item.Header);
diff --git a/src/Avalonia.Native/NativeControlHostImpl.cs b/src/Avalonia.Native/NativeControlHostImpl.cs
index a46528dc48..2c9c1728d3 100644
--- a/src/Avalonia.Native/NativeControlHostImpl.cs
+++ b/src/Avalonia.Native/NativeControlHostImpl.cs
@@ -1,5 +1,6 @@
using System;
using Avalonia.Controls.Platform;
+using Avalonia.MicroCom;
using Avalonia.Native.Interop;
using Avalonia.Platform;
using Avalonia.VisualTree;
@@ -28,8 +29,7 @@ namespace Avalonia.Native
public DestroyableNSView(IAvnNativeControlHost impl)
{
- _impl = new IAvnNativeControlHost(impl.NativePointer);
- _impl.AddRef();
+ _impl = MicroComRuntime.CloneReference(impl);
_nsView = _impl.CreateDefaultChild(IntPtr.Zero);
}
diff --git a/src/Avalonia.Native/OsxUnicodeKeys.cs b/src/Avalonia.Native/OsxUnicodeKeys.cs
deleted file mode 100644
index fd9acfa714..0000000000
--- a/src/Avalonia.Native/OsxUnicodeKeys.cs
+++ /dev/null
@@ -1,152 +0,0 @@
-using System.Collections.Generic;
-using Avalonia.Input;
-
-namespace Avalonia.Native.Interop
-{
- internal static class OsxUnicodeKeys
- {
- enum OsxUnicodeSpecialKey
- {
- NSUpArrowFunctionKey = 0xF700,
- NSDownArrowFunctionKey = 0xF701,
- NSLeftArrowFunctionKey = 0xF702,
- NSRightArrowFunctionKey = 0xF703,
- NSF1FunctionKey = 0xF704,
- NSF2FunctionKey = 0xF705,
- NSF3FunctionKey = 0xF706,
- NSF4FunctionKey = 0xF707,
- NSF5FunctionKey = 0xF708,
- NSF6FunctionKey = 0xF709,
- NSF7FunctionKey = 0xF70A,
- NSF8FunctionKey = 0xF70B,
- NSF9FunctionKey = 0xF70C,
- NSF10FunctionKey = 0xF70D,
- NSF11FunctionKey = 0xF70E,
- NSF12FunctionKey = 0xF70F,
- NSF13FunctionKey = 0xF710,
- NSF14FunctionKey = 0xF711,
- NSF15FunctionKey = 0xF712,
- NSF16FunctionKey = 0xF713,
- NSF17FunctionKey = 0xF714,
- NSF18FunctionKey = 0xF715,
- NSF19FunctionKey = 0xF716,
- NSF20FunctionKey = 0xF717,
- NSF21FunctionKey = 0xF718,
- NSF22FunctionKey = 0xF719,
- NSF23FunctionKey = 0xF71A,
- NSF24FunctionKey = 0xF71B,
- NSF25FunctionKey = 0xF71C,
- NSF26FunctionKey = 0xF71D,
- NSF27FunctionKey = 0xF71E,
- NSF28FunctionKey = 0xF71F,
- NSF29FunctionKey = 0xF720,
- NSF30FunctionKey = 0xF721,
- NSF31FunctionKey = 0xF722,
- NSF32FunctionKey = 0xF723,
- NSF33FunctionKey = 0xF724,
- NSF34FunctionKey = 0xF725,
- NSF35FunctionKey = 0xF726,
- NSInsertFunctionKey = 0xF727,
- NSDeleteFunctionKey = 0xF728,
- NSHomeFunctionKey = 0xF729,
- NSBeginFunctionKey = 0xF72A,
- NSEndFunctionKey = 0xF72B,
- NSPageUpFunctionKey = 0xF72C,
- NSPageDownFunctionKey = 0xF72D,
- NSPrintScreenFunctionKey = 0xF72E,
- NSScrollLockFunctionKey = 0xF72F,
- NSPauseFunctionKey = 0xF730,
- NSSysReqFunctionKey = 0xF731,
- NSBreakFunctionKey = 0xF732,
- NSResetFunctionKey = 0xF733,
- NSStopFunctionKey = 0xF734,
- NSMenuFunctionKey = 0xF735,
- NSUserFunctionKey = 0xF736,
- NSSystemFunctionKey = 0xF737,
- NSPrintFunctionKey = 0xF738,
- NSClearLineFunctionKey = 0xF739,
- NSClearDisplayFunctionKey = 0xF73A,
- NSInsertLineFunctionKey = 0xF73B,
- NSDeleteLineFunctionKey = 0xF73C,
- NSInsertCharFunctionKey = 0xF73D,
- NSDeleteCharFunctionKey = 0xF73E,
- NSPrevFunctionKey = 0xF73F,
- NSNextFunctionKey = 0xF740,
- NSSelectFunctionKey = 0xF741,
- NSExecuteFunctionKey = 0xF742,
- NSUndoFunctionKey = 0xF743,
- NSRedoFunctionKey = 0xF744,
- NSFindFunctionKey = 0xF745,
- NSHelpFunctionKey = 0xF746,
- NSModeSwitchFunctionKey = 0xF747
- }
-
- private static Dictionary s_osxKeys = new Dictionary
- {
- {Key.Up, OsxUnicodeSpecialKey.NSUpArrowFunctionKey },
- {Key.Down, OsxUnicodeSpecialKey.NSDownArrowFunctionKey },
- {Key.Left, OsxUnicodeSpecialKey.NSLeftArrowFunctionKey },
- {Key.Right, OsxUnicodeSpecialKey.NSRightArrowFunctionKey },
- { Key.F1, OsxUnicodeSpecialKey.NSF1FunctionKey },
- { Key.F2, OsxUnicodeSpecialKey.NSF2FunctionKey },
- { Key.F3, OsxUnicodeSpecialKey.NSF3FunctionKey },
- { Key.F4, OsxUnicodeSpecialKey.NSF4FunctionKey },
- { Key.F5, OsxUnicodeSpecialKey.NSF5FunctionKey },
- { Key.F6, OsxUnicodeSpecialKey.NSF6FunctionKey },
- { Key.F7, OsxUnicodeSpecialKey.NSF7FunctionKey },
- { Key.F8, OsxUnicodeSpecialKey.NSF8FunctionKey },
- { Key.F9, OsxUnicodeSpecialKey.NSF9FunctionKey },
- { Key.F10, OsxUnicodeSpecialKey.NSF10FunctionKey },
- { Key.F11, OsxUnicodeSpecialKey.NSF11FunctionKey },
- { Key.F12, OsxUnicodeSpecialKey.NSF12FunctionKey },
- { Key.F13, OsxUnicodeSpecialKey.NSF13FunctionKey },
- { Key.F14, OsxUnicodeSpecialKey.NSF14FunctionKey },
- { Key.F15, OsxUnicodeSpecialKey.NSF15FunctionKey },
- { Key.F16, OsxUnicodeSpecialKey.NSF16FunctionKey },
- { Key.F17, OsxUnicodeSpecialKey.NSF17FunctionKey },
- { Key.F18, OsxUnicodeSpecialKey.NSF18FunctionKey },
- { Key.F19, OsxUnicodeSpecialKey.NSF19FunctionKey },
- { Key.F20, OsxUnicodeSpecialKey.NSF20FunctionKey },
- { Key.F21, OsxUnicodeSpecialKey.NSF21FunctionKey },
- { Key.F22, OsxUnicodeSpecialKey.NSF22FunctionKey },
- { Key.F23, OsxUnicodeSpecialKey.NSF23FunctionKey },
- { Key.F24, OsxUnicodeSpecialKey.NSF24FunctionKey },
- { Key.Insert, OsxUnicodeSpecialKey.NSInsertFunctionKey },
- { Key.Delete, OsxUnicodeSpecialKey.NSDeleteFunctionKey },
- { Key.Home, OsxUnicodeSpecialKey.NSHomeFunctionKey },
- //{ Key.Begin, OsxUnicodeSpecialKey.NSBeginFunctionKey },
- { Key.End, OsxUnicodeSpecialKey.NSEndFunctionKey },
- { Key.PageUp, OsxUnicodeSpecialKey.NSPageUpFunctionKey },
- { Key.PageDown, OsxUnicodeSpecialKey.NSPageDownFunctionKey },
- { Key.PrintScreen, OsxUnicodeSpecialKey.NSPrintScreenFunctionKey },
- { Key.Scroll, OsxUnicodeSpecialKey.NSScrollLockFunctionKey },
- //{ Key.SysReq, OsxUnicodeSpecialKey.NSSysReqFunctionKey },
- //{ Key.Break, OsxUnicodeSpecialKey.NSBreakFunctionKey },
- //{ Key.Reset, OsxUnicodeSpecialKey.NSResetFunctionKey },
- //{ Key.Stop, OsxUnicodeSpecialKey.NSStopFunctionKey },
- //{ Key.Menu, OsxUnicodeSpecialKey.NSMenuFunctionKey },
- //{ Key.UserFunction, OsxUnicodeSpecialKey.NSUserFunctionKey },
- //{ Key.SystemFunction, OsxUnicodeSpecialKey.NSSystemFunctionKey },
- { Key.Print, OsxUnicodeSpecialKey.NSPrintFunctionKey },
- //{ Key.ClearLine, OsxUnicodeSpecialKey.NSClearLineFunctionKey },
- //{ Key.ClearDisplay, OsxUnicodeSpecialKey.NSClearDisplayFunctionKey },
- };
-
- public static string ConvertOSXSpecialKeyCodes(Key key)
- {
- if (s_osxKeys.ContainsKey(key))
- {
- return ((char)s_osxKeys[key]).ToString();
- }
- else
- {
- if (key >= Key.D0 && key <= Key.D9)
- {
- return key.ToString().Replace("D", "");
- }
-
- return key.ToString().ToLower();
- }
- }
- }
-}
diff --git a/src/Avalonia.Native/PlatformThreadingInterface.cs b/src/Avalonia.Native/PlatformThreadingInterface.cs
index 5a81f6a3bf..882d5a2ed3 100644
--- a/src/Avalonia.Native/PlatformThreadingInterface.cs
+++ b/src/Avalonia.Native/PlatformThreadingInterface.cs
@@ -4,11 +4,10 @@ using System.Threading;
using Avalonia.Native.Interop;
using Avalonia.Platform;
using Avalonia.Threading;
-using SharpGen.Runtime;
namespace Avalonia.Native
{
- public class PlatformThreadingInterface : IPlatformThreadingInterface
+ internal class PlatformThreadingInterface : IPlatformThreadingInterface
{
class TimerCallback : CallbackBase, IAvnActionCallback
{
@@ -34,9 +33,9 @@ namespace Avalonia.Native
_parent = parent;
}
- public void Signaled(int priority, bool priorityContainsMeaningfulValue)
+ public void Signaled(int priority, int priorityContainsMeaningfulValue)
{
- _parent.Signaled?.Invoke(priorityContainsMeaningfulValue ? (DispatcherPriority?)priority : null);
+ _parent.Signaled?.Invoke(priorityContainsMeaningfulValue.FromComBool() ? (DispatcherPriority?)priority : null);
}
}
@@ -48,10 +47,10 @@ namespace Avalonia.Native
{
_native = native;
using (var cb = new SignaledCallback(this))
- _native.SignaledCallback = cb;
+ _native.SetSignaledCallback(cb);
}
- public bool CurrentThreadIsLoopThread => _native.CurrentThreadIsLoopThread;
+ public bool CurrentThreadIsLoopThread => _native.CurrentThreadIsLoopThread.FromComBool();
public event Action Signaled;
diff --git a/src/Avalonia.Native/PopupImpl.cs b/src/Avalonia.Native/PopupImpl.cs
index 2f98385038..c36675afcd 100644
--- a/src/Avalonia.Native/PopupImpl.cs
+++ b/src/Avalonia.Native/PopupImpl.cs
@@ -50,9 +50,9 @@ namespace Avalonia.Native
// NOP on Popup
}
- bool IAvnWindowEvents.Closing()
+ int IAvnWindowEvents.Closing()
{
- return true;
+ return true.AsComBool();
}
void IAvnWindowEvents.WindowStateChanged(AvnWindowState state)
@@ -60,14 +60,14 @@ namespace Avalonia.Native
}
}
- public override void Show()
+ public override void Show(bool activate)
{
var parent = _parent;
while (parent is PopupImpl p)
parent = p._parent;
if (parent is WindowImpl w)
w.Native.TakeFocusFromChildren();
- base.Show();
+ base.Show(false);
}
public override IPopupImpl CreatePopup() => new PopupImpl(_factory, _opts, _glFeature, this);
diff --git a/src/Avalonia.Native/PredicateCallback.cs b/src/Avalonia.Native/PredicateCallback.cs
index 1ed2ae36af..19c470bcb3 100644
--- a/src/Avalonia.Native/PredicateCallback.cs
+++ b/src/Avalonia.Native/PredicateCallback.cs
@@ -12,9 +12,9 @@ namespace Avalonia.Native
_predicate = predicate;
}
- bool IAvnPredicateCallback.Evaluate()
+ int IAvnPredicateCallback.Evaluate()
{
- return _predicate();
+ return _predicate().AsComBool();
}
}
}
diff --git a/src/Avalonia.Native/ScreenImpl.cs b/src/Avalonia.Native/ScreenImpl.cs
index f28be52dd5..7b4a001486 100644
--- a/src/Avalonia.Native/ScreenImpl.cs
+++ b/src/Avalonia.Native/ScreenImpl.cs
@@ -14,7 +14,7 @@ namespace Avalonia.Native
_native = native;
}
- public int ScreenCount => _native.GetScreenCount();
+ public int ScreenCount => _native.ScreenCount;
public IReadOnlyList AllScreens
{
@@ -33,7 +33,7 @@ namespace Avalonia.Native
screen.PixelDensity,
screen.Bounds.ToAvaloniaPixelRect(),
screen.WorkingArea.ToAvaloniaPixelRect(),
- screen.Primary);
+ screen.Primary.FromComBool());
}
return result;
diff --git a/src/Avalonia.Native/SystemDialogs.cs b/src/Avalonia.Native/SystemDialogs.cs
index 98e3e383dc..8012813644 100644
--- a/src/Avalonia.Native/SystemDialogs.cs
+++ b/src/Avalonia.Native/SystemDialogs.cs
@@ -8,7 +8,7 @@ using Avalonia.Native.Interop;
namespace Avalonia.Native
{
- public class SystemDialogs : ISystemDialogImpl
+ internal class SystemDialogs : ISystemDialogImpl
{
IAvnSystemDialogs _native;
@@ -26,7 +26,7 @@ namespace Avalonia.Native
if (dialog is OpenFileDialog ofd)
{
_native.OpenFileDialog(nativeParent,
- events, ofd.AllowMultiple,
+ events, ofd.AllowMultiple.AsComBool(),
ofd.Title ?? "",
ofd.Directory ?? "",
ofd.InitialFileName ?? "",
@@ -62,7 +62,7 @@ namespace Avalonia.Native
}
}
- public class SystemDialogEvents : CallbackBase, IAvnSystemDialogEvents
+ internal unsafe class SystemDialogEvents : CallbackBase, IAvnSystemDialogEvents
{
private TaskCompletionSource _tcs;
@@ -73,13 +73,13 @@ namespace Avalonia.Native
public Task Task => _tcs.Task;
- public void OnCompleted(int numResults, IntPtr trFirstResultRef)
+ public void OnCompleted(int numResults, void* trFirstResultRef)
{
string[] results = new string[numResults];
unsafe
{
- var ptr = (IntPtr*)trFirstResultRef.ToPointer();
+ var ptr = (IntPtr*)trFirstResultRef;
for (int i = 0; i < numResults; i++)
{
diff --git a/src/Avalonia.Native/WindowImpl.cs b/src/Avalonia.Native/WindowImpl.cs
index 11a0ebce61..f3b60f07be 100644
--- a/src/Avalonia.Native/WindowImpl.cs
+++ b/src/Avalonia.Native/WindowImpl.cs
@@ -1,4 +1,5 @@
using System;
+using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Platform;
using Avalonia.Input;
@@ -10,13 +11,15 @@ using Avalonia.Platform.Interop;
namespace Avalonia.Native
{
- public class WindowImpl : WindowBaseImpl, IWindowImpl, ITopLevelImplWithNativeMenuExporter
+ internal class WindowImpl : WindowBaseImpl, IWindowImpl, ITopLevelImplWithNativeMenuExporter
{
private readonly IAvaloniaNativeFactory _factory;
private readonly AvaloniaNativePlatformOptions _opts;
private readonly AvaloniaNativePlatformOpenGlInterface _glFeature;
IAvnWindow _native;
private double _extendTitleBarHeight = -1;
+ private DoubleClickHelper _doubleClickHelper;
+
internal WindowImpl(IAvaloniaNativeFactory factory, AvaloniaNativePlatformOptions opts,
AvaloniaNativePlatformOpenGlInterface glFeature) : base(opts, glFeature)
@@ -24,6 +27,8 @@ namespace Avalonia.Native
_factory = factory;
_opts = opts;
_glFeature = glFeature;
+ _doubleClickHelper = new DoubleClickHelper();
+
using (var e = new WindowEvents(this))
{
var context = _opts.UseGpu ? glFeature?.MainContext : null;
@@ -42,14 +47,14 @@ namespace Avalonia.Native
_parent = parent;
}
- bool IAvnWindowEvents.Closing()
+ int IAvnWindowEvents.Closing()
{
if (_parent.Closing != null)
{
- return _parent.Closing();
+ return _parent.Closing().AsComBool();
}
- return true;
+ return true.AsComBool();
}
void IAvnWindowEvents.WindowStateChanged(AvnWindowState state)
@@ -69,12 +74,12 @@ namespace Avalonia.Native
public void CanResize(bool value)
{
- _native.CanResize = value;
+ _native.SetCanResize(value.AsComBool());
}
public void SetSystemDecorations(Controls.SystemDecorations enabled)
{
- _native.Decorations = (Interop.SystemDecorations)enabled;
+ _native.SetDecorations((Interop.SystemDecorations)enabled);
}
public void SetTitleBarColor(Avalonia.Media.Color color)
@@ -82,24 +87,12 @@ namespace Avalonia.Native
_native.SetTitleBarColor(new AvnColor { Alpha = color.A, Red = color.R, Green = color.G, Blue = color.B });
}
- public void SetTitle(string title)
- {
- using (var buffer = new Utf8Buffer(title))
- {
- _native.SetTitle(buffer.DangerousGetHandle());
- }
- }
+ public void SetTitle(string title) => _native.SetTitle(title);
public WindowState WindowState
{
- get
- {
- return (WindowState)_native.GetWindowState();
- }
- set
- {
- _native.SetWindowState((AvnWindowState)value);
- }
+ get => (WindowState)_native.WindowState;
+ set => _native.SetWindowState((AvnWindowState)value);
}
public Action WindowStateChanged { get; set; }
@@ -130,7 +123,22 @@ namespace Avalonia.Native
if(visual == null)
{
- _native.BeginMoveDrag();
+ if (_doubleClickHelper.IsDoubleClick(e.Timestamp, e.Position))
+ {
+ // TOGGLE WINDOW STATE.
+ if (WindowState == WindowState.Maximized || WindowState == WindowState.FullScreen)
+ {
+ WindowState = WindowState.Normal;
+ }
+ else
+ {
+ WindowState = WindowState.Maximized;
+ }
+ }
+ else
+ {
+ _native.BeginMoveDrag();
+ }
}
}
}
@@ -146,7 +154,7 @@ namespace Avalonia.Native
}
else
{
- ExtendedMargins = _isExtended ? new Thickness(0, _extendTitleBarHeight == -1 ? _native.GetExtendTitleBarHeight() : _extendTitleBarHeight, 0, 0) : new Thickness();
+ ExtendedMargins = _isExtended ? new Thickness(0, _extendTitleBarHeight == -1 ? _native.ExtendTitleBarHeight : _extendTitleBarHeight, 0, 0) : new Thickness();
}
ExtendClientAreaToDecorationsChanged?.Invoke(_isExtended);
@@ -157,7 +165,7 @@ namespace Avalonia.Native
{
_isExtended = extendIntoClientAreaHint;
- _native.SetExtendClientArea(extendIntoClientAreaHint);
+ _native.SetExtendClientArea(extendIntoClientAreaHint.AsComBool());
InvalidateExtendedMargins();
}
@@ -174,7 +182,7 @@ namespace Avalonia.Native
_extendTitleBarHeight = titleBarHeight;
_native.SetExtendTitleBarHeight(titleBarHeight);
- ExtendedMargins = _isExtended ? new Thickness(0, titleBarHeight == -1 ? _native.GetExtendTitleBarHeight() : titleBarHeight, 0, 0) : new Thickness();
+ ExtendedMargins = _isExtended ? new Thickness(0, titleBarHeight == -1 ? _native.ExtendTitleBarHeight : titleBarHeight, 0, 0) : new Thickness();
ExtendClientAreaToDecorationsChanged?.Invoke(_isExtended);
}
@@ -210,7 +218,7 @@ namespace Avalonia.Native
public void SetEnabled(bool enable)
{
- _native.SetEnabled(enable);
+ _native.SetEnabled(enable.AsComBool());
}
}
}
diff --git a/src/Avalonia.Native/WindowImplBase.cs b/src/Avalonia.Native/WindowImplBase.cs
index 5d35c773d7..927b739b0c 100644
--- a/src/Avalonia.Native/WindowImplBase.cs
+++ b/src/Avalonia.Native/WindowImplBase.cs
@@ -15,7 +15,7 @@ using Avalonia.Threading;
namespace Avalonia.Native
{
- public class MacOSTopLevelWindowHandle : IPlatformHandle, IMacOSTopLevelPlatformHandle
+ internal class MacOSTopLevelWindowHandle : IPlatformHandle, IMacOSTopLevelPlatformHandle
{
IAvnWindowBase _native;
@@ -43,7 +43,7 @@ namespace Avalonia.Native
}
}
- public abstract class WindowBaseImpl : IWindowBaseImpl,
+ internal abstract class WindowBaseImpl : IWindowBaseImpl,
IFramebufferPlatformSurface, ITopLevelImplWithNativeControlHost
{
protected IInputRoot _inputRoot;
@@ -96,7 +96,7 @@ namespace Avalonia.Native
{
if (_native != null)
{
- var s = _native.GetClientSize();
+ var s = _native.ClientSize;
return new Size(s.Width, s.Height);
}
@@ -137,7 +137,7 @@ namespace Avalonia.Native
public IMouseDevice MouseDevice => _mouse;
public abstract IPopupImpl CreatePopup();
- protected class WindowBaseEvents : CallbackBase, IAvnWindowBaseEvents
+ protected unsafe class WindowBaseEvents : CallbackBase, IAvnWindowBaseEvents
{
private readonly WindowBaseImpl _parent;
@@ -155,10 +155,10 @@ namespace Avalonia.Native
}
finally
{
+
+ _parent?.Dispose();
n?.Dispose();
}
-
- _parent._mouse.Dispose();
}
void IAvnWindowBaseEvents.Activated() => _parent.Activated?.Invoke();
@@ -172,11 +172,11 @@ namespace Avalonia.Native
_parent.Paint?.Invoke(new Rect(0, 0, s.Width, s.Height));
}
- void IAvnWindowBaseEvents.Resized(AvnSize size)
+ void IAvnWindowBaseEvents.Resized(AvnSize* size)
{
- if (_parent._native != null)
+ if (_parent?._native != null)
{
- var s = new Size(size.Width, size.Height);
+ var s = new Size(size->Width, size->Height);
_parent._savedLogicalSize = s;
_parent.Resized?.Invoke(s);
}
@@ -192,14 +192,14 @@ namespace Avalonia.Native
_parent.RawMouseEvent(type, timeStamp, modifiers, point, delta);
}
- bool IAvnWindowBaseEvents.RawKeyEvent(AvnRawKeyEventType type, uint timeStamp, AvnInputModifiers modifiers, uint key)
+ int IAvnWindowBaseEvents.RawKeyEvent(AvnRawKeyEventType type, uint timeStamp, AvnInputModifiers modifiers, uint key)
{
- return _parent.RawKeyEvent(type, timeStamp, modifiers, key);
+ return _parent.RawKeyEvent(type, timeStamp, modifiers, key).AsComBool();
}
- bool IAvnWindowBaseEvents.RawTextInputEvent(uint timeStamp, string text)
+ int IAvnWindowBaseEvents.RawTextInputEvent(uint timeStamp, string text)
{
- return _parent.RawTextInputEvent(timeStamp, text);
+ return _parent.RawTextInputEvent(timeStamp, text).AsComBool();
}
@@ -251,6 +251,9 @@ namespace Avalonia.Native
public bool RawTextInputEvent(uint timeStamp, string text)
{
+ if (_inputRoot is null)
+ return false;
+
Dispatcher.UIThread.RunJobs(DispatcherPriority.Input + 1);
var args = new RawTextInputEventArgs(_keyboard, timeStamp, _inputRoot, text);
@@ -262,6 +265,9 @@ namespace Avalonia.Native
public bool RawKeyEvent(AvnRawKeyEventType type, uint timeStamp, AvnInputModifiers modifiers, uint key)
{
+ if (_inputRoot is null)
+ return false;
+
Dispatcher.UIThread.RunJobs(DispatcherPriority.Input + 1);
var args = new RawKeyEventArgs(_keyboard, timeStamp, _inputRoot, (RawKeyEventType)type, (Key)key, (RawInputModifiers)modifiers);
@@ -278,6 +284,9 @@ namespace Avalonia.Native
public void RawMouseEvent(AvnRawMouseEventType type, uint timeStamp, AvnInputModifiers modifiers, AvnPoint point, AvnVector delta)
{
+ if (_inputRoot is null)
+ return;
+
Dispatcher.UIThread.RunJobs(DispatcherPriority.Input + 1);
switch (type)
@@ -327,13 +336,13 @@ namespace Avalonia.Native
_nativeControlHost = null;
(Screen as ScreenImpl)?.Dispose();
+ _mouse.Dispose();
}
public void Invalidate(Rect rect)
{
- if (!_deferredRendering && _native != null)
- _native.Invalidate(new AvnRect { Height = rect.Height, Width = rect.Width, X = rect.X, Y = rect.Y });
+ _native?.Invalidate(new AvnRect { Height = rect.Height, Width = rect.Width, X = rect.X, Y = rect.Y });
}
public void SetInputRoot(IInputRoot inputRoot)
@@ -342,15 +351,15 @@ namespace Avalonia.Native
}
- public virtual void Show()
+ public virtual void Show(bool activate)
{
- _native.Show();
+ _native.Show(activate.AsComBool());
}
public PixelPoint Position
{
- get => _native.GetPosition().ToAvaloniaPixelPoint();
+ get => _native.Position.ToAvaloniaPixelPoint();
set => _native.SetPosition(value.ToAvnPoint());
}
@@ -379,10 +388,10 @@ namespace Avalonia.Native
public void SetTopmost(bool value)
{
- _native.SetTopMost(value);
+ _native.SetTopMost(value.AsComBool());
}
- public double RenderScaling => _native?.GetScaling() ?? 1;
+ public double RenderScaling => _native?.Scaling ?? 1;
public double DesktopScaling => 1;
@@ -398,7 +407,7 @@ namespace Avalonia.Native
var newCursor = cursor as AvaloniaNativeCursor;
newCursor = newCursor ?? (_cursorFactory.GetCursor(StandardCursorType.Arrow) as AvaloniaNativeCursor);
- _native.Cursor = newCursor.Cursor;
+ _native.SetCursor(newCursor.Cursor);
}
public Action PositionChanged { get; set; }
@@ -447,7 +456,7 @@ namespace Avalonia.Native
TransparencyLevel = transparencyLevel;
- _native?.SetBlurEnabled(TransparencyLevel >= WindowTransparencyLevel.Blur);
+ _native?.SetBlurEnabled((TransparencyLevel >= WindowTransparencyLevel.Blur).AsComBool());
TransparencyLevelChanged?.Invoke(TransparencyLevel);
}
}
diff --git a/src/Avalonia.Native/avn.idl b/src/Avalonia.Native/avn.idl
new file mode 100644
index 0000000000..166046ca24
--- /dev/null
+++ b/src/Avalonia.Native/avn.idl
@@ -0,0 +1,728 @@
+@clr-namespace Avalonia.Native.Interop
+@clr-access internal
+@clr-map bool int
+@cpp-preamble @@
+#include "com.h"
+#include "stddef.h"
+@@
+
+enum AvnKey
+{
+ AvnKeyNone = 0,
+ AvnKeyCancel = 1,
+ AvnKeyBack = 2,
+ AvnKeyTab = 3,
+ AvnKeyLineFeed = 4,
+ AvnKeyClear = 5,
+ AvnKeyReturn = 6,
+ AvnKeyEnter = 6,
+ AvnKeyPause = 7,
+ AvnKeyCapsLock = 8,
+ AvnKeyCapital = 8,
+ AvnKeyHangulMode = 9,
+ AvnKeyKanaMode = 9,
+ AvnKeyJunjaMode = 10,
+ AvnKeyFinalMode = 11,
+ AvnKeyKanjiMode = 12,
+ HanjaMode = 12,
+ Escape = 13,
+ ImeConvert = 14,
+ ImeNonConvert = 15,
+ ImeAccept = 16,
+ ImeModeChange = 17,
+ Space = 18,
+ PageUp = 19,
+ Prior = 19,
+ PageDown = 20,
+ Next = 20,
+ End = 21,
+ Home = 22,
+ Left = 23,
+ Up = 24,
+ Right = 25,
+ Down = 26,
+ Select = 27,
+ Print = 28,
+ Execute = 29,
+ Snapshot = 30,
+ PrintScreen = 30,
+ Insert = 31,
+ Delete = 32,
+ Help = 33,
+ D0 = 34,
+ D1 = 35,
+ D2 = 36,
+ D3 = 37,
+ D4 = 38,
+ D5 = 39,
+ D6 = 40,
+ D7 = 41,
+ D8 = 42,
+ D9 = 43,
+ A = 44,
+ B = 45,
+ C = 46,
+ D = 47,
+ E = 48,
+ F = 49,
+ G = 50,
+ H = 51,
+ I = 52,
+ J = 53,
+ AvnKeyK = 54,
+ L = 55,
+ M = 56,
+ N = 57,
+ O = 58,
+ P = 59,
+ Q = 60,
+ R = 61,
+ S = 62,
+ T = 63,
+ U = 64,
+ V = 65,
+ W = 66,
+ X = 67,
+ Y = 68,
+ Z = 69,
+ LWin = 70,
+ RWin = 71,
+ Apps = 72,
+ Sleep = 73,
+ NumPad0 = 74,
+ NumPad1 = 75,
+ NumPad2 = 76,
+ NumPad3 = 77,
+ NumPad4 = 78,
+ NumPad5 = 79,
+ NumPad6 = 80,
+ NumPad7 = 81,
+ NumPad8 = 82,
+ NumPad9 = 83,
+ Multiply = 84,
+ Add = 85,
+ Separator = 86,
+ Subtract = 87,
+ Decimal = 88,
+ Divide = 89,
+ F1 = 90,
+ F2 = 91,
+ F3 = 92,
+ F4 = 93,
+ F5 = 94,
+ F6 = 95,
+ F7 = 96,
+ F8 = 97,
+ F9 = 98,
+ F10 = 99,
+ F11 = 100,
+ F12 = 101,
+ F13 = 102,
+ F14 = 103,
+ F15 = 104,
+ F16 = 105,
+ F17 = 106,
+ F18 = 107,
+ F19 = 108,
+ F20 = 109,
+ F21 = 110,
+ F22 = 111,
+ F23 = 112,
+ F24 = 113,
+ NumLock = 114,
+ Scroll = 115,
+ LeftShift = 116,
+ RightShift = 117,
+ LeftCtrl = 118,
+ RightCtrl = 119,
+ LeftAlt = 120,
+ RightAlt = 121,
+ BrowserBack = 122,
+ BrowserForward = 123,
+ BrowserRefresh = 124,
+ BrowserStop = 125,
+ BrowserSearch = 126,
+ BrowserFavorites = 127,
+ BrowserHome = 128,
+ VolumeMute = 129,
+ VolumeDown = 130,
+ VolumeUp = 131,
+ MediaNextTrack = 132,
+ MediaPreviousTrack = 133,
+ MediaStop = 134,
+ MediaPlayPause = 135,
+ LaunchMail = 136,
+ SelectMedia = 137,
+ LaunchApplication1 = 138,
+ LaunchApplication2 = 139,
+ OemSemicolon = 140,
+ Oem1 = 140,
+ OemPlus = 141,
+ OemComma = 142,
+ OemMinus = 143,
+ OemPeriod = 144,
+ OemQuestion = 145,
+ Oem2 = 145,
+ OemTilde = 146,
+ Oem3 = 146,
+ AbntC1 = 147,
+ AbntC2 = 148,
+ OemOpenBrackets = 149,
+ Oem4 = 149,
+ OemPipe = 150,
+ Oem5 = 150,
+ OemCloseBrackets = 151,
+ Oem6 = 151,
+ OemQuotes = 152,
+ Oem7 = 152,
+ Oem8 = 153,
+ OemBackslash = 154,
+ Oem102 = 154,
+ ImeProcessed = 155,
+ System = 156,
+ OemAttn = 157,
+ DbeAlphanumeric = 157,
+ OemFinish = 158,
+ DbeKatakana = 158,
+ DbeHiragana = 159,
+ OemCopy = 159,
+ DbeSbcsChar = 160,
+ OemAuto = 160,
+ DbeDbcsChar = 161,
+ OemEnlw = 161,
+ OemBackTab = 162,
+ DbeRoman = 162,
+ DbeNoRoman = 163,
+ Attn = 163,
+ CrSel = 164,
+ DbeEnterWordRegisterMode = 164,
+ ExSel = 165,
+ DbeEnterImeConfigureMode = 165,
+ EraseEof = 166,
+ DbeFlushString = 166,
+ Play = 167,
+ DbeCodeInput = 167,
+ DbeNoCodeInput = 168,
+ Zoom = 168,
+ NoName = 169,
+ DbeDetermineString = 169,
+ DbeEnterDialogConversionMode = 170,
+ Pa1 = 170,
+ OemClear = 171,
+ DeadCharProcessed = 172,
+};
+
+enum SystemDecorations {
+ SystemDecorationsNone = 0,
+ SystemDecorationsBorderOnly = 1,
+ SystemDecorationsFull = 2,
+}
+
+struct AvnSize
+{
+ double Width, Height;
+}
+
+struct AvnPixelSize
+{
+ int Width, Height;
+}
+
+struct AvnRect
+{
+ double X, Y, Width, Height;
+}
+
+struct AvnVector
+{
+ double X, Y;
+}
+
+struct AvnPoint
+{
+ double X, Y;
+}
+
+struct AvnScreen
+{
+ AvnRect Bounds;
+ AvnRect WorkingArea;
+ float PixelDensity;
+ bool Primary;
+}
+
+enum AvnPixelFormat
+{
+ kAvnRgb565,
+ kAvnRgba8888,
+ kAvnBgra8888
+}
+
+struct AvnFramebuffer
+{
+ void* Data;
+ int Width;
+ int Height;
+ int Stride;
+ AvnVector Dpi;
+ AvnPixelFormat PixelFormat;
+}
+
+struct AvnColor
+{
+ byte Alpha;
+ byte Red;
+ byte Green;
+ byte Blue;
+}
+
+enum AvnRawMouseEventType
+{
+ LeaveWindow,
+ LeftButtonDown,
+ LeftButtonUp,
+ RightButtonDown,
+ RightButtonUp,
+ MiddleButtonDown,
+ MiddleButtonUp,
+ XButton1Down,
+ XButton1Up,
+ XButton2Down,
+ XButton2Up,
+ Move,
+ Wheel,
+ NonClientLeftButtonDown,
+ TouchBegin,
+ TouchUpdate,
+ TouchEnd,
+ TouchCancel
+}
+
+enum AvnRawKeyEventType
+{
+ KeyDown,
+ KeyUp
+}
+
+enum AvnInputModifiers
+{
+ AvnInputModifiersNone = 0,
+ Alt = 1,
+ Control = 2,
+ Shift = 4,
+ Windows = 8,
+ LeftMouseButton = 16,
+ RightMouseButton = 32,
+ MiddleMouseButton = 64,
+ XButton1MouseButton = 128,
+ XButton2MouseButton = 256
+}
+
+[class-enum]
+enum AvnDragDropEffects
+{
+ None = 0,
+ Copy = 1,
+ Move = 2,
+ Link = 4,
+}
+
+[class-enum]
+enum AvnDragEventType
+{
+ Enter,
+ Over,
+ Leave,
+ Drop
+}
+
+enum AvnWindowState
+{
+ Normal,
+ Minimized,
+ Maximized,
+ FullScreen,
+}
+
+enum AvnStandardCursorType
+{
+ CursorArrow,
+ CursorIbeam,
+ CursorWait,
+ CursorCross,
+ CursorUpArrow,
+ CursorSizeWestEast,
+ CursorSizeNorthSouth,
+ CursorSizeAll,
+ CursorNo,
+ CursorHand,
+ CursorAppStarting,
+ CursorHelp,
+ CursorTopSide,
+ CursorBottomSize,
+ CursorLeftSide,
+ CursorRightSide,
+ CursorTopLeftCorner,
+ CursorTopRightCorner,
+ CursorBottomLeftCorner,
+ CursorBottomRightCorner,
+ CursorDragMove,
+ CursorDragCopy,
+ CursorDragLink,
+ CursorNone
+}
+
+enum AvnWindowEdge
+{
+ WindowEdgeNorthWest,
+ WindowEdgeNorth,
+ WindowEdgeNorthEast,
+ WindowEdgeWest,
+ WindowEdgeEast,
+ WindowEdgeSouthWest,
+ WindowEdgeSouth,
+ WindowEdgeSouthEast
+}
+
+enum AvnMenuItemToggleType
+{
+ None,
+ CheckMark,
+ Radio
+}
+
+enum AvnExtendClientAreaChromeHints
+{
+ AvnNoChrome = 0,
+ AvnSystemChrome = 0x01,
+ AvnPreferSystemChrome = 0x02,
+ AvnOSXThickTitleBar = 0x08,
+ AvnDefaultChrome = AvnSystemChrome,
+}
+
+[uuid(809c652e-7396-11d2-9771-00a0c9b4d50c)]
+interface IAvaloniaNativeFactory : IUnknown
+{
+ HRESULT Initialize(IAvnGCHandleDeallocatorCallback* deallocator);
+ IAvnMacOptions* GetMacOptions();
+ HRESULT CreateWindow(IAvnWindowEvents* cb, IAvnGlContext* gl, IAvnWindow** ppv);
+ HRESULT CreatePopup(IAvnWindowEvents* cb, IAvnGlContext* gl, IAvnPopup** ppv);
+ HRESULT CreatePlatformThreadingInterface(IAvnPlatformThreadingInterface** ppv);
+ HRESULT CreateSystemDialogs(IAvnSystemDialogs** ppv);
+ HRESULT CreateScreens(IAvnScreens** ppv);
+ HRESULT CreateClipboard(IAvnClipboard** ppv);
+ HRESULT CreateDndClipboard(IAvnClipboard** ppv);
+ HRESULT CreateCursorFactory(IAvnCursorFactory** ppv);
+ HRESULT ObtainGlDisplay(IAvnGlDisplay** ppv);
+ HRESULT SetAppMenu(IAvnMenu* menu);
+ HRESULT CreateMenu(IAvnMenuEvents* cb, IAvnMenu** ppv);
+ HRESULT CreateMenuItem(IAvnMenuItem** ppv);
+ HRESULT CreateMenuItemSeperator(IAvnMenuItem** ppv);
+}
+
+[uuid(233e094f-9b9f-44a3-9a6e-6948bbdd9fb1)]
+interface IAvnString : IUnknown
+{
+ HRESULT Pointer(void**retOut);
+ HRESULT Length(int*ret);
+}
+
+[uuid(e5aca675-02b7-4129-aa79-d6e417210bda)]
+interface IAvnWindowBase : IUnknown
+{
+ HRESULT Show(bool activate);
+ HRESULT Hide();
+ HRESULT Close();
+ HRESULT Activate();
+ HRESULT GetClientSize(AvnSize*ret);
+ HRESULT GetScaling(double*ret);
+ HRESULT SetMinMaxSize(AvnSize minSize, AvnSize maxSize);
+ HRESULT Resize(double width, double height);
+ HRESULT Invalidate(AvnRect rect);
+ HRESULT BeginMoveDrag();
+ HRESULT BeginResizeDrag(AvnWindowEdge edge);
+ HRESULT GetPosition(AvnPoint*ret);
+ HRESULT SetPosition(AvnPoint point);
+ HRESULT PointToClient(AvnPoint point, AvnPoint*ret);
+ HRESULT PointToScreen(AvnPoint point, AvnPoint*ret);
+ HRESULT ThreadSafeSetSwRenderedFrame(AvnFramebuffer* fb, IUnknown* dispose);
+ HRESULT SetTopMost(bool value);
+ HRESULT SetCursor(IAvnCursor* cursor);
+ HRESULT CreateGlRenderTarget(IAvnGlSurfaceRenderTarget** ret);
+ HRESULT SetMainMenu(IAvnMenu* menu);
+ HRESULT ObtainNSWindowHandle([intptr]void** retOut);
+ HRESULT ObtainNSWindowHandleRetained([intptr]void** retOut);
+ HRESULT ObtainNSViewHandle([intptr]void** retOut);
+ HRESULT ObtainNSViewHandleRetained([intptr]void** retOut);
+ HRESULT CreateNativeControlHost(IAvnNativeControlHost** retOut);
+ HRESULT BeginDragAndDropOperation(AvnDragDropEffects effects, AvnPoint point,
+ IAvnClipboard* clipboard, IAvnDndResultCallback* cb, [intptr]void* sourceHandle);
+ HRESULT SetBlurEnabled(bool enable);
+}
+
+[uuid(83e588f3-6981-4e48-9ea0-e1e569f79a91), cpp-virtual-inherits]
+interface IAvnPopup : IAvnWindowBase
+{
+
+}
+
+[uuid(cab661de-49d6-4ead-b59c-eac9b2b6c28d), cpp-virtual-inherits]
+interface IAvnWindow : IAvnWindowBase
+{
+ HRESULT SetEnabled(bool enable);
+ HRESULT SetParent(IAvnWindow* parent);
+ HRESULT SetCanResize(bool value);
+ HRESULT SetDecorations(SystemDecorations value);
+ HRESULT SetTitle(char* utf8Title);
+ HRESULT SetTitleBarColor(AvnColor color);
+ HRESULT SetWindowState(AvnWindowState state);
+ HRESULT GetWindowState(AvnWindowState*ret);
+ HRESULT TakeFocusFromChildren();
+ HRESULT SetExtendClientArea(bool enable);
+ HRESULT SetExtendClientAreaHints(AvnExtendClientAreaChromeHints hints);
+ HRESULT GetExtendTitleBarHeight(double*ret);
+ HRESULT SetExtendTitleBarHeight(double value);
+}
+
+[uuid(939b6599-40a8-4710-a4c8-5d72d8f174fb)]
+interface IAvnWindowBaseEvents : IUnknown
+{
+ HRESULT Paint();
+ void Closed();
+ void Activated();
+ void Deactivated();
+ void Resized([const] AvnSize& size);
+ void PositionChanged(AvnPoint position);
+ void RawMouseEvent(AvnRawMouseEventType type,
+ uint timeStamp,
+ AvnInputModifiers modifiers,
+ AvnPoint point,
+ AvnVector delta);
+ bool RawKeyEvent(AvnRawKeyEventType type, uint timeStamp, AvnInputModifiers modifiers, uint key);
+ bool RawTextInputEvent(uint timeStamp, [const] char* text);
+ void ScalingChanged(double scaling);
+ void RunRenderPriorityJobs();
+ void LostFocus();
+ AvnDragDropEffects DragEvent(AvnDragEventType type, AvnPoint position,
+ AvnInputModifiers modifiers, AvnDragDropEffects effects,
+ IAvnClipboard* clipboard, [intptr]void* dataObjectHandle);
+}
+
+[uuid(1ae178ee-1fcc-447f-b6dd-b7bb727f934c)]
+interface IAvnWindowEvents : IAvnWindowBaseEvents
+{
+ /**
+ * Closing Event
+ * Called when the user presses the OS window close button.
+ * return true to allow the close, return false to prevent close.
+ */
+ bool Closing();
+
+ void WindowStateChanged(AvnWindowState state);
+
+ void GotInputWhenDisabled();
+}
+
+[uuid(e34ae0f8-18b4-48a3-b09d-2e6b19a3cf5e)]
+interface IAvnMacOptions : IUnknown
+{
+ HRESULT SetShowInDock(int show);
+ HRESULT SetApplicationTitle(char* utf8string);
+}
+
+[uuid(04c1b049-1f43-418a-9159-cae627ec1367)]
+interface IAvnActionCallback : IUnknown
+{
+ void Run();
+}
+
+[uuid(6df4d2db-0b80-4f59-ad88-0baa5e21eb14)]
+interface IAvnSignaledCallback : IUnknown
+{
+ void Signaled(int priority, bool priorityContainsMeaningfulValue);
+}
+
+[uuid(97330f88-c22b-4a8e-a130-201520091b01)]
+interface IAvnLoopCancellation : IUnknown
+{
+ void Cancel();
+}
+
+[uuid(fbc06f3d-7860-42df-83fd-53c4b02dd9c3)]
+interface IAvnPlatformThreadingInterface : IUnknown
+{
+ bool GetCurrentThreadIsLoopThread();
+ void SetSignaledCallback(IAvnSignaledCallback* cb);
+ IAvnLoopCancellation* CreateLoopCancellation();
+ HRESULT RunLoop(IAvnLoopCancellation* cancel);
+ // Can't pass int* to sharpgentools for some reason
+ void Signal(int priority);
+ IUnknown* StartTimer(int priority, int ms, IAvnActionCallback* callback);
+}
+
+[uuid(6c621a6e-e4c1-4ae3-9749-83eeeffa09b6)]
+interface IAvnSystemDialogEvents : IUnknown
+{
+ void OnCompleted(int numResults, void* ptrFirstResult);
+}
+
+[uuid(4d7a47db-a944-4061-abe7-62cb6aa0ffd5)]
+interface IAvnSystemDialogs : IUnknown
+{
+ void SelectFolderDialog(IAvnWindow* parentWindowHandle,
+ IAvnSystemDialogEvents* events,
+ [const] char* title,
+ [const] char* initialPath);
+
+ void OpenFileDialog(IAvnWindow* parentWindowHandle,
+ IAvnSystemDialogEvents* events,
+ bool allowMultiple,
+ [const] char* title,
+ [const] char* initialDirectory,
+ [const] char* initialFile,
+ [const] char* filters);
+
+ void SaveFileDialog(IAvnWindow* parentWindowHandle,
+ IAvnSystemDialogEvents* events,
+ [const] char* title,
+ [const] char* initialDirectory,
+ [const] char* initialFile,
+ [const] char* filters);
+}
+
+[uuid(9a52bc7a-d8c7-4230-8d34-704a0b70a933)]
+interface IAvnScreens : IUnknown
+{
+ HRESULT GetScreenCount(int* ret);
+ HRESULT GetScreen(int index, AvnScreen* ret);
+}
+
+[uuid(792b1bd4-76cc-46ea-bfd0-9d642154b1b3)]
+interface IAvnClipboard : IUnknown
+{
+ HRESULT GetText(char* type, IAvnString**ppv);
+ HRESULT SetText(char* type, char* utf8Text);
+ HRESULT ObtainFormats(IAvnStringArray**ppv);
+ HRESULT GetStrings(char* type, IAvnStringArray**ppv);
+ HRESULT SetBytes(char* type, void* utf8Text, int len);
+ HRESULT GetBytes(char* type, IAvnString**ppv);
+
+ HRESULT Clear();
+}
+
+[uuid(3f998545-f027-4d4d-bd2a-1a80926d984e)]
+interface IAvnCursor : IUnknown
+{
+}
+
+[uuid(51ecfb12-c427-4757-a2c9-1596bfce53ef)]
+interface IAvnCursorFactory : IUnknown
+{
+ HRESULT GetCursor(AvnStandardCursorType cursorType, IAvnCursor** retOut);
+}
+
+[uuid(60452465-8616-40af-bc00-042e69828ce7)]
+interface IAvnGlDisplay : IUnknown
+{
+ HRESULT CreateContext(IAvnGlContext* share, IAvnGlContext**ppv);
+ void LegacyClearCurrentContext();
+ HRESULT WrapContext([intptr]void* native, IAvnGlContext**ppv);
+ [intptr]void* GetProcAddress(char* proc);
+}
+
+[uuid(78c5711e-2a98-40d2-bac4-0cc9a49dc4f3)]
+interface IAvnGlContext : IUnknown
+{
+ HRESULT MakeCurrent(IUnknown** ppv);
+ HRESULT LegacyMakeCurrent();
+ int GetSampleCount();
+ int GetStencilSize();
+ [intptr]void* GetNativeHandle();
+}
+
+[uuid(931062d2-5bc8-4062-8588-83dd8deb99c2)]
+interface IAvnGlSurfaceRenderTarget : IUnknown
+{
+ HRESULT BeginDrawing(IAvnGlSurfaceRenderingSession** ret);
+}
+
+[uuid(e625b406-f04c-484e-946a-4abd2c6015ad)]
+interface IAvnGlSurfaceRenderingSession : IUnknown
+{
+ HRESULT GetPixelSize(AvnPixelSize* ret);
+ HRESULT GetScaling(double* ret);
+}
+
+[uuid(a7724dc1-cf6b-4fa8-9d23-228bf2593edc)]
+interface IAvnMenu : IUnknown
+{
+ HRESULT InsertItem(int index, IAvnMenuItem* item);
+ HRESULT RemoveItem(IAvnMenuItem* item);
+ HRESULT SetTitle(char* utf8String);
+ HRESULT Clear();
+}
+
+[uuid(59e0586d-bd1c-4b85-9882-80d448b0fed9)]
+interface IAvnPredicateCallback : IUnknown
+{
+ bool Evaluate();
+}
+
+[uuid(f890219a-1720-4cd5-9a26-cd95fccbf53c)]
+interface IAvnMenuItem : IUnknown
+{
+ HRESULT SetSubMenu(IAvnMenu* menu);
+ HRESULT SetTitle(char* utf8String);
+ HRESULT SetGesture(AvnKey key, AvnInputModifiers modifiers);
+ HRESULT SetAction(IAvnPredicateCallback* predicate, IAvnActionCallback* callback);
+ HRESULT SetIsChecked(bool isChecked);
+ HRESULT SetToggleType(AvnMenuItemToggleType toggleType);
+ HRESULT SetIcon(void* data, size_t length);
+}
+
+[uuid(0af7df53-7632-42f4-a650-0992c361b477)]
+interface IAvnMenuEvents : IUnknown
+{
+ /**
+ * NeedsUpdate
+ */
+ void NeedsUpdate();
+}
+
+[uuid(5142bb41-66ab-49e7-bb37-cd079c000f27)]
+interface IAvnStringArray : IUnknown
+{
+ uint GetCount();
+ HRESULT Get(uint index, IAvnString**ppv);
+}
+
+[uuid(a13d2382-3b3a-4d1c-9b27-8f34653d3f01)]
+interface IAvnDndResultCallback : IUnknown
+{
+ void OnDragAndDropComplete(AvnDragDropEffects effecct);
+}
+
+[uuid(f07c608e-52e9-422d-836e-c70f6e9b80f5)]
+interface IAvnGCHandleDeallocatorCallback : IUnknown
+{
+ void FreeGCHandle([intptr]void* handle);
+}
+
+[uuid(91c7f677-f26b-4ff3-93cc-cf15aa966ffa)]
+interface IAvnNativeControlHost : IUnknown
+{
+ HRESULT CreateDefaultChild([intptr]void* parent, [intptr]void** retOut);
+ IAvnNativeControlHostTopLevelAttachment* CreateAttachment();
+ void DestroyDefaultChild([intptr]void* child);
+}
+
+[uuid(14a9e164-1aae-4271-bb78-7b5230999b52)]
+interface IAvnNativeControlHostTopLevelAttachment : IUnknown
+{
+ [intptr]void* GetParentHandle();
+ HRESULT InitializeWithChildHandle([intptr]void* child);
+ HRESULT AttachTo(IAvnNativeControlHost* host);
+ void ShowInBounds(float x, float y, float width, float height);
+ void HideWithSize(float width, float height);
+ void ReleaseChild();
+}
diff --git a/src/Avalonia.OpenGL/Angle/AngleEglInterface.cs b/src/Avalonia.OpenGL/Angle/AngleEglInterface.cs
index 8c9b028164..3a332f37ad 100644
--- a/src/Avalonia.OpenGL/Angle/AngleEglInterface.cs
+++ b/src/Avalonia.OpenGL/Angle/AngleEglInterface.cs
@@ -1,15 +1,13 @@
using System;
using System.Runtime.InteropServices;
using Avalonia.OpenGL.Egl;
-using Avalonia.Platform;
-using Avalonia.Platform.Interop;
namespace Avalonia.OpenGL.Angle
{
public class AngleEglInterface : EglInterface
{
- [DllImport("libegl.dll", CharSet = CharSet.Ansi)]
- static extern IntPtr eglGetProcAddress(string proc);
+ [DllImport("av_libGLESv2.dll", CharSet = CharSet.Ansi)]
+ static extern IntPtr EGL_GetProcAddress(string proc);
public AngleEglInterface() : base(LoadAngle())
{
@@ -20,14 +18,14 @@ namespace Avalonia.OpenGL.Angle
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
- var disp = eglGetProcAddress("eglGetPlatformDisplayEXT");
+ var disp = EGL_GetProcAddress("eglGetPlatformDisplayEXT");
if (disp == IntPtr.Zero)
{
throw new OpenGlException("libegl.dll doesn't have eglGetPlatformDisplayEXT entry point");
}
- return eglGetProcAddress;
+ return EGL_GetProcAddress;
}
throw new PlatformNotSupportedException();
diff --git a/src/Avalonia.OpenGL/Angle/AngleWin32EglDisplay.cs b/src/Avalonia.OpenGL/Angle/AngleWin32EglDisplay.cs
index 191fb53204..94e7728d68 100644
--- a/src/Avalonia.OpenGL/Angle/AngleWin32EglDisplay.cs
+++ b/src/Avalonia.OpenGL/Angle/AngleWin32EglDisplay.cs
@@ -82,7 +82,14 @@ namespace Avalonia.OpenGL.Angle
{
if (PlatformApi != AngleOptions.PlatformApi.DirectX11)
throw new InvalidOperationException("Current platform API is " + PlatformApi);
- return egl.CreatePBufferFromClientBuffer(EGL_D3D_TEXTURE_ANGLE, handle, new[] { EGL_NONE, EGL_NONE });
+ return egl.CreatePBufferFromClientBuffer(EGL_D3D_TEXTURE_ANGLE, handle, new[] { EGL_NONE, EGL_NONE });
+ }
+
+ public EglSurface WrapDirect3D11Texture(EglPlatformOpenGlInterface egl, IntPtr handle, int offsetX, int offsetY, int width, int height)
+ {
+ if (PlatformApi != AngleOptions.PlatformApi.DirectX11)
+ throw new InvalidOperationException("Current platform API is " + PlatformApi);
+ return egl.CreatePBufferFromClientBuffer(EGL_D3D_TEXTURE_ANGLE, handle, new[] { EGL_WIDTH, width, EGL_HEIGHT, height, EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE, EGL_TRUE, EGL_TEXTURE_OFFSET_X_ANGLE, offsetX, EGL_TEXTURE_OFFSET_Y_ANGLE, offsetY, EGL_NONE });
}
}
}
diff --git a/src/Avalonia.OpenGL/Egl/EglConsts.cs b/src/Avalonia.OpenGL/Egl/EglConsts.cs
index 58f5f1cef5..530d3401f6 100644
--- a/src/Avalonia.OpenGL/Egl/EglConsts.cs
+++ b/src/Avalonia.OpenGL/Egl/EglConsts.cs
@@ -205,5 +205,11 @@ namespace Avalonia.OpenGL.Egl
public const int EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE = 0x3200;
public const int EGL_D3D_TEXTURE_ANGLE = 0x33A3;
+
+
+ public const int EGL_TEXTURE_OFFSET_X_ANGLE = 0x3490;
+ public const int EGL_TEXTURE_OFFSET_Y_ANGLE = 0x3491;
+
+ public const int EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE = 0x33A6;
}
}
diff --git a/src/Avalonia.OpenGL/Egl/EglContext.cs b/src/Avalonia.OpenGL/Egl/EglContext.cs
index 5365354418..58137dfff0 100644
--- a/src/Avalonia.OpenGL/Egl/EglContext.cs
+++ b/src/Avalonia.OpenGL/Egl/EglContext.cs
@@ -73,7 +73,8 @@ namespace Avalonia.OpenGL.Egl
var old = new RestoreContext(_egl, _disp.Handle, _lock);
var surf = surface ?? OffscreenSurface;
_egl.MakeCurrent(_disp.Handle, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
- if (!_egl.MakeCurrent(_disp.Handle, surf.DangerousGetHandle(), surf.DangerousGetHandle(), Context))
+ if (!_egl.MakeCurrent(_disp.Handle, surf?.DangerousGetHandle() ?? IntPtr.Zero,
+ surf?.DangerousGetHandle() ?? IntPtr.Zero, Context))
throw OpenGlException.GetFormattedException("eglMakeCurrent", _egl);
success = true;
return old;
@@ -92,6 +93,14 @@ namespace Avalonia.OpenGL.Egl
return MakeCurrent();
}
+ public IDisposable EnsureLocked()
+ {
+ if (IsCurrent)
+ return Disposable.Empty;
+ Monitor.Enter(_lock);
+ return Disposable.Create(() => Monitor.Exit(_lock));
+ }
+
public bool IsSharedWith(IGlContext context)
{
var c = (EglContext)context;
diff --git a/src/Avalonia.OpenGL/Egl/EglDisplay.cs b/src/Avalonia.OpenGL/Egl/EglDisplay.cs
index fd3de854f5..623364866b 100644
--- a/src/Avalonia.OpenGL/Egl/EglDisplay.cs
+++ b/src/Avalonia.OpenGL/Egl/EglDisplay.cs
@@ -158,15 +158,21 @@ namespace Avalonia.OpenGL.Egl
var ctx = _egl.CreateContext(_display, _config, shareCtx?.Context ?? IntPtr.Zero, _contextAttributes);
if (ctx == IntPtr.Zero)
throw OpenGlException.GetFormattedException("eglCreateContext", _egl);
- var surf = _egl.CreatePBufferSurface(_display, _config, new[]
+
+ var extensions = _egl.QueryString(Handle, EGL_EXTENSIONS);
+
+ IntPtr surf = IntPtr.Zero;
+ if (extensions?.Contains("EGL_KHR_surfaceless_context") != true)
{
- EGL_WIDTH, 1,
- EGL_HEIGHT, 1,
- EGL_NONE
- });
- if (surf == IntPtr.Zero)
- throw OpenGlException.GetFormattedException("eglCreatePBufferSurface", _egl);
- var rv = new EglContext(this, _egl, shareCtx, ctx, context => new EglSurface(this, context, surf),
+ surf = _egl.CreatePBufferSurface(_display, _config,
+ new[] { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE });
+ if (surf == IntPtr.Zero)
+ throw OpenGlException.GetFormattedException("eglCreatePBufferSurface", _egl);
+ }
+
+ var rv = new EglContext(this, _egl, shareCtx, ctx,
+ context =>
+ surf == IntPtr.Zero ? null : new EglSurface(this, context, surf),
_version, _sampleCount, _stencilSize);
return rv;
}
diff --git a/src/Avalonia.OpenGL/GlInterface.cs b/src/Avalonia.OpenGL/GlInterface.cs
index ea2fe0a99c..28b62136da 100644
--- a/src/Avalonia.OpenGL/GlInterface.cs
+++ b/src/Avalonia.OpenGL/GlInterface.cs
@@ -117,6 +117,19 @@ namespace Avalonia.OpenGL
public delegate int GlCheckFramebufferStatus(int target);
[GlEntryPoint("glCheckFramebufferStatus")]
public GlCheckFramebufferStatus CheckFramebufferStatus { get; }
+
+ public delegate void GlBlitFramebuffer(int srcX0,
+ int srcY0,
+ int srcX1,
+ int srcY1,
+ int dstX0,
+ int dstY0,
+ int dstX1,
+ int dstY1,
+ int mask,
+ int filter);
+ [GlMinVersionEntryPoint("glBlitFramebuffer", 3, 0)]
+ public GlBlitFramebuffer BlitFramebuffer { get; }
public delegate void GlGenRenderbuffers(int count, int[] res);
[GlEntryPoint("glGenRenderbuffers")]
diff --git a/src/Avalonia.ReactiveUI.Events/Avalonia.ReactiveUI.Events.csproj b/src/Avalonia.ReactiveUI.Events/Avalonia.ReactiveUI.Events.csproj
index 75eeb92f42..7f58e455f9 100644
--- a/src/Avalonia.ReactiveUI.Events/Avalonia.ReactiveUI.Events.csproj
+++ b/src/Avalonia.ReactiveUI.Events/Avalonia.ReactiveUI.Events.csproj
@@ -2,6 +2,7 @@
netstandard2.0
Avalonia.ReactiveUI.Events
+ false
diff --git a/src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj b/src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj
index d01a495108..624c5772a9 100644
--- a/src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj
+++ b/src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj
@@ -2,6 +2,7 @@
netstandard2.0
Avalonia.ReactiveUI
+ false
diff --git a/src/Avalonia.ReactiveUI/ReactiveUserControl.cs b/src/Avalonia.ReactiveUI/ReactiveUserControl.cs
index fc48a8853d..f4824ade0a 100644
--- a/src/Avalonia.ReactiveUI/ReactiveUserControl.cs
+++ b/src/Avalonia.ReactiveUI/ReactiveUserControl.cs
@@ -1,3 +1,6 @@
+using System;
+using System.Reactive.Disposables;
+using System.Reactive.Linq;
using Avalonia;
using Avalonia.VisualTree;
using Avalonia.Controls;
@@ -6,8 +9,10 @@ using ReactiveUI;
namespace Avalonia.ReactiveUI
{
///
- /// A ReactiveUI UserControl that implements
- /// and will activate your ViewModel automatically if it supports activation.
+ /// A ReactiveUI that implements the interface and
+ /// will activate your ViewModel automatically if the view model implements .
+ /// When the DataContext property changes, this class will update the ViewModel property with the new DataContext
+ /// value, and vice versa.
///
/// ViewModel type.
public class ReactiveUserControl : UserControl, IViewFor where TViewModel : class
@@ -20,7 +25,10 @@ namespace Avalonia.ReactiveUI
///
public ReactiveUserControl()
{
- DataContextChanged += (sender, args) => ViewModel = DataContext as TViewModel;
+ // This WhenActivated block calls ViewModel's WhenActivated
+ // block if the ViewModel implements IActivatableViewModel.
+ this.WhenActivated(disposables => { });
+ this.GetObservable(ViewModelProperty).Subscribe(OnViewModelChanged);
}
///
@@ -37,5 +45,22 @@ namespace Avalonia.ReactiveUI
get => ViewModel;
set => ViewModel = (TViewModel)value;
}
+
+ protected override void OnDataContextChanged(EventArgs e)
+ {
+ ViewModel = DataContext as TViewModel;
+ }
+
+ private void OnViewModelChanged(object value)
+ {
+ if (value == null)
+ {
+ ClearValue(DataContextProperty);
+ }
+ else if (DataContext != value)
+ {
+ DataContext = value;
+ }
+ }
}
}
diff --git a/src/Avalonia.ReactiveUI/ReactiveWindow.cs b/src/Avalonia.ReactiveUI/ReactiveWindow.cs
index 5695a727af..758a807bfc 100644
--- a/src/Avalonia.ReactiveUI/ReactiveWindow.cs
+++ b/src/Avalonia.ReactiveUI/ReactiveWindow.cs
@@ -1,3 +1,6 @@
+using System;
+using System.Reactive.Disposables;
+using System.Reactive.Linq;
using Avalonia;
using Avalonia.VisualTree;
using Avalonia.Controls;
@@ -6,8 +9,10 @@ using ReactiveUI;
namespace Avalonia.ReactiveUI
{
///
- /// A ReactiveUI Window that implements
- /// and will activate your ViewModel automatically if it supports activation.
+ /// A ReactiveUI that implements the interface and will
+ /// activate your ViewModel automatically if the view model implements . When
+ /// the DataContext property changes, this class will update the ViewModel property with the new DataContext value,
+ /// and vice versa.
///
/// ViewModel type.
public class ReactiveWindow : Window, IViewFor where TViewModel : class
@@ -20,7 +25,11 @@ namespace Avalonia.ReactiveUI
///
public ReactiveWindow()
{
- DataContextChanged += (sender, args) => ViewModel = DataContext as TViewModel;
+ // This WhenActivated block calls ViewModel's WhenActivated
+ // block if the ViewModel implements IActivatableViewModel.
+ this.WhenActivated(disposables => { });
+ this.GetObservable(DataContextProperty).Subscribe(OnDataContextChanged);
+ this.GetObservable(ViewModelProperty).Subscribe(OnViewModelChanged);
}
///
@@ -37,5 +46,29 @@ namespace Avalonia.ReactiveUI
get => ViewModel;
set => ViewModel = (TViewModel)value;
}
+
+ private void OnDataContextChanged(object value)
+ {
+ if (value is TViewModel viewModel)
+ {
+ ViewModel = viewModel;
+ }
+ else
+ {
+ ViewModel = null;
+ }
+ }
+
+ private void OnViewModelChanged(object value)
+ {
+ if (value == null)
+ {
+ ClearValue(DataContextProperty);
+ }
+ else if (DataContext != value)
+ {
+ DataContext = value;
+ }
+ }
}
}
diff --git a/src/Avalonia.Styling/ApiCompatBaseline.txt b/src/Avalonia.Styling/ApiCompatBaseline.txt
new file mode 100644
index 0000000000..001e165830
--- /dev/null
+++ b/src/Avalonia.Styling/ApiCompatBaseline.txt
@@ -0,0 +1,3 @@
+Compat issues with assembly Avalonia.Styling:
+MembersMustExist : Member 'public System.IObservable Avalonia.Controls.ResourceNodeExtensions.GetResourceObservable(Avalonia.IStyledElement, System.Object, System.Func)' does not exist in the implementation but it does exist in the contract.
+Total Issues: 1
diff --git a/src/Avalonia.Styling/Controls/ResourceNodeExtensions.cs b/src/Avalonia.Styling/Controls/ResourceNodeExtensions.cs
index 250274c39b..be1069a4da 100644
--- a/src/Avalonia.Styling/Controls/ResourceNodeExtensions.cs
+++ b/src/Avalonia.Styling/Controls/ResourceNodeExtensions.cs
@@ -60,7 +60,7 @@ namespace Avalonia.Controls
}
public static IObservable GetResourceObservable(
- this IStyledElement control,
+ this IResourceHost control,
object key,
Func? converter = null)
{
@@ -83,11 +83,11 @@ namespace Avalonia.Controls
private class ResourceObservable : LightweightObservableBase
{
- private readonly IStyledElement _target;
+ private readonly IResourceHost _target;
private readonly object _key;
private readonly Func? _converter;
- public ResourceObservable(IStyledElement target, object key, Func? converter)
+ public ResourceObservable(IResourceHost target, object key, Func? converter)
{
_target = target;
_key = key;
@@ -147,13 +147,16 @@ namespace Avalonia.Controls
{
if (_target.Owner is object)
{
- observer.OnNext(Convert(_target.Owner?.FindResource(_key)));
+ observer.OnNext(Convert(_target.Owner.FindResource(_key)));
}
}
private void PublishNext()
{
- PublishNext(Convert(_target.Owner?.FindResource(_key)));
+ if (_target.Owner is object)
+ {
+ PublishNext(Convert(_target.Owner.FindResource(_key)));
+ }
}
private void OwnerChanged(object sender, EventArgs e)
diff --git a/src/Avalonia.Styling/Properties/AssemblyInfo.cs b/src/Avalonia.Styling/Properties/AssemblyInfo.cs
index b231f3b406..34c71fffe3 100644
--- a/src/Avalonia.Styling/Properties/AssemblyInfo.cs
+++ b/src/Avalonia.Styling/Properties/AssemblyInfo.cs
@@ -5,4 +5,8 @@ using Avalonia.Metadata;
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Controls")]
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.LogicalTree")]
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Styling")]
-[assembly: InternalsVisibleTo("Avalonia.Styling.UnitTests")]
\ No newline at end of file
+#if SIGNED_BUILD
+[assembly: InternalsVisibleTo("Avalonia.Styling.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")]
+#else
+[assembly: InternalsVisibleTo("Avalonia.Styling.UnitTests")]
+#endif
diff --git a/src/Avalonia.Styling/StyledElement.cs b/src/Avalonia.Styling/StyledElement.cs
index 65885ddebe..cc8d91462d 100644
--- a/src/Avalonia.Styling/StyledElement.cs
+++ b/src/Avalonia.Styling/StyledElement.cs
@@ -1,8 +1,8 @@
using System;
+using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
-using System.Linq;
using Avalonia.Animation;
using Avalonia.Collections;
using Avalonia.Controls;
@@ -479,16 +479,16 @@ namespace Avalonia
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
- SetLogicalParent(e.NewItems.Cast());
+ SetLogicalParent(e.NewItems);
break;
case NotifyCollectionChangedAction.Remove:
- ClearLogicalParent(e.OldItems.Cast());
+ ClearLogicalParent(e.OldItems);
break;
case NotifyCollectionChangedAction.Replace:
- ClearLogicalParent(e.OldItems.Cast());
- SetLogicalParent(e.NewItems.Cast());
+ ClearLogicalParent(e.OldItems);
+ SetLogicalParent(e.NewItems);
break;
case NotifyCollectionChangedAction.Reset:
@@ -702,13 +702,32 @@ namespace Avalonia
OnDataContextChanged(EventArgs.Empty);
}
- private void SetLogicalParent(IEnumerable children)
+ private void SetLogicalParent(IList children)
{
- foreach (var i in children)
+ var count = children.Count;
+
+ for (var i = 0; i < count; i++)
+ {
+ var logical = (ILogical) children[i];
+
+ if (logical.LogicalParent is null)
+ {
+ ((ISetLogicalParent)logical).SetParent(this);
+ }
+ }
+ }
+
+ private void ClearLogicalParent(IList children)
+ {
+ var count = children.Count;
+
+ for (var i = 0; i < count; i++)
{
- if (i.LogicalParent == null)
+ var logical = (ILogical) children[i];
+
+ if (logical.LogicalParent == this)
{
- ((ISetLogicalParent)i).SetParent(this);
+ ((ISetLogicalParent)logical).SetParent(null);
}
}
}
@@ -784,17 +803,6 @@ namespace Avalonia
}
}
- private void ClearLogicalParent(IEnumerable children)
- {
- foreach (var i in children)
- {
- if (i.LogicalParent == this)
- {
- ((ISetLogicalParent)i).SetParent(null);
- }
- }
- }
-
private void NotifyResourcesChanged(
ResourcesChangedEventArgs? e = null,
bool propagate = true)
diff --git a/src/Avalonia.Themes.Default/CaptionButtons.xaml b/src/Avalonia.Themes.Default/CaptionButtons.xaml
index 68249905a1..95967547c6 100644
--- a/src/Avalonia.Themes.Default/CaptionButtons.xaml
+++ b/src/Avalonia.Themes.Default/CaptionButtons.xaml
@@ -4,7 +4,7 @@
-
+
+
diff --git a/src/Avalonia.Themes.Default/PathIcon.xaml b/src/Avalonia.Themes.Default/PathIcon.xaml
index a2d01f7b5b..039f0ef10c 100644
--- a/src/Avalonia.Themes.Default/PathIcon.xaml
+++ b/src/Avalonia.Themes.Default/PathIcon.xaml
@@ -2,16 +2,19 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
diff --git a/src/Avalonia.Themes.Default/SplitView.xaml b/src/Avalonia.Themes.Default/SplitView.xaml
index 2fb59cdbc4..18da3edb46 100644
--- a/src/Avalonia.Themes.Default/SplitView.xaml
+++ b/src/Avalonia.Themes.Default/SplitView.xaml
@@ -32,12 +32,12 @@
ClipToBounds="True"
HorizontalAlignment="Left"
ZIndex="100">
-
+
-
+
@@ -106,14 +106,14 @@
ClipToBounds="True"
HorizontalAlignment="Right"
ZIndex="100">
-
+
-
+
diff --git a/src/Avalonia.Themes.Default/ToggleSwitch.xaml b/src/Avalonia.Themes.Default/ToggleSwitch.xaml
index 9ce4da0873..f11f77df5a 100644
--- a/src/Avalonia.Themes.Default/ToggleSwitch.xaml
+++ b/src/Avalonia.Themes.Default/ToggleSwitch.xaml
@@ -5,7 +5,7 @@
0,0,0,6
6
6
- 154
+ 0
0
1
@@ -87,7 +87,6 @@
Grid.Row="0"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
- Margin="{DynamicResource ToggleSwitchTopHeaderMargin}"
VerticalAlignment="Top"/>
+
+
+
+
+
diff --git a/src/Avalonia.Themes.Fluent/ButtonSpinner.xaml b/src/Avalonia.Themes.Fluent/Controls/ButtonSpinner.xaml
similarity index 60%
rename from src/Avalonia.Themes.Fluent/ButtonSpinner.xaml
rename to src/Avalonia.Themes.Fluent/Controls/ButtonSpinner.xaml
index 82265ea282..12b4845522 100644
--- a/src/Avalonia.Themes.Fluent/ButtonSpinner.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/ButtonSpinner.xaml
@@ -65,56 +65,59 @@
-
-
-
+
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
diff --git a/src/Avalonia.Themes.Fluent/Calendar.xaml b/src/Avalonia.Themes.Fluent/Controls/Calendar.xaml
similarity index 100%
rename from src/Avalonia.Themes.Fluent/Calendar.xaml
rename to src/Avalonia.Themes.Fluent/Controls/Calendar.xaml
diff --git a/src/Avalonia.Themes.Fluent/CalendarButton.xaml b/src/Avalonia.Themes.Fluent/Controls/CalendarButton.xaml
similarity index 100%
rename from src/Avalonia.Themes.Fluent/CalendarButton.xaml
rename to src/Avalonia.Themes.Fluent/Controls/CalendarButton.xaml
diff --git a/src/Avalonia.Themes.Fluent/CalendarDatePicker.xaml b/src/Avalonia.Themes.Fluent/Controls/CalendarDatePicker.xaml
similarity index 100%
rename from src/Avalonia.Themes.Fluent/CalendarDatePicker.xaml
rename to src/Avalonia.Themes.Fluent/Controls/CalendarDatePicker.xaml
diff --git a/src/Avalonia.Themes.Fluent/CalendarDayButton.xaml b/src/Avalonia.Themes.Fluent/Controls/CalendarDayButton.xaml
similarity index 100%
rename from src/Avalonia.Themes.Fluent/CalendarDayButton.xaml
rename to src/Avalonia.Themes.Fluent/Controls/CalendarDayButton.xaml
diff --git a/src/Avalonia.Themes.Fluent/CalendarItem.xaml b/src/Avalonia.Themes.Fluent/Controls/CalendarItem.xaml
similarity index 100%
rename from src/Avalonia.Themes.Fluent/CalendarItem.xaml
rename to src/Avalonia.Themes.Fluent/Controls/CalendarItem.xaml
diff --git a/src/Avalonia.Themes.Fluent/CaptionButtons.xaml b/src/Avalonia.Themes.Fluent/Controls/CaptionButtons.xaml
similarity index 91%
rename from src/Avalonia.Themes.Fluent/CaptionButtons.xaml
rename to src/Avalonia.Themes.Fluent/Controls/CaptionButtons.xaml
index f288372b77..1f8887c283 100644
--- a/src/Avalonia.Themes.Fluent/CaptionButtons.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/CaptionButtons.xaml
@@ -3,7 +3,7 @@
-
+
+
+
+
+
+
@@ -226,4 +226,17 @@
+
+
+
+
+
+
+
diff --git a/src/Avalonia.Themes.Fluent/ComboBoxItem.xaml b/src/Avalonia.Themes.Fluent/Controls/ComboBoxItem.xaml
similarity index 100%
rename from src/Avalonia.Themes.Fluent/ComboBoxItem.xaml
rename to src/Avalonia.Themes.Fluent/Controls/ComboBoxItem.xaml
diff --git a/src/Avalonia.Themes.Fluent/Common.xaml b/src/Avalonia.Themes.Fluent/Controls/Common.xaml
similarity index 100%
rename from src/Avalonia.Themes.Fluent/Common.xaml
rename to src/Avalonia.Themes.Fluent/Controls/Common.xaml
diff --git a/src/Avalonia.Themes.Fluent/ContentControl.xaml b/src/Avalonia.Themes.Fluent/Controls/ContentControl.xaml
similarity index 100%
rename from src/Avalonia.Themes.Fluent/ContentControl.xaml
rename to src/Avalonia.Themes.Fluent/Controls/ContentControl.xaml
diff --git a/src/Avalonia.Themes.Fluent/ContextMenu.xaml b/src/Avalonia.Themes.Fluent/Controls/ContextMenu.xaml
similarity index 97%
rename from src/Avalonia.Themes.Fluent/ContextMenu.xaml
rename to src/Avalonia.Themes.Fluent/Controls/ContextMenu.xaml
index 33447ffd6c..a4e716c7f6 100644
--- a/src/Avalonia.Themes.Fluent/ContextMenu.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/ContextMenu.xaml
@@ -39,6 +39,7 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Avalonia.Themes.Fluent/DatePicker.xaml b/src/Avalonia.Themes.Fluent/Controls/DatePicker.xaml
similarity index 77%
rename from src/Avalonia.Themes.Fluent/DatePicker.xaml
rename to src/Avalonia.Themes.Fluent/Controls/DatePicker.xaml
index 6fbfa1bbf7..b6e36861e0 100644
--- a/src/Avalonia.Themes.Fluent/DatePicker.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/DatePicker.xaml
@@ -125,77 +125,79 @@
-
-
+
+
+
-
+
-
-
-
+
+
+
-
+
+
@@ -228,6 +230,11 @@
+
+
+
diff --git a/src/Avalonia.Themes.Fluent/ListBox.xaml b/src/Avalonia.Themes.Fluent/Controls/ListBox.xaml
similarity index 100%
rename from src/Avalonia.Themes.Fluent/ListBox.xaml
rename to src/Avalonia.Themes.Fluent/Controls/ListBox.xaml
diff --git a/src/Avalonia.Themes.Fluent/ListBoxItem.xaml b/src/Avalonia.Themes.Fluent/Controls/ListBoxItem.xaml
similarity index 100%
rename from src/Avalonia.Themes.Fluent/ListBoxItem.xaml
rename to src/Avalonia.Themes.Fluent/Controls/ListBoxItem.xaml
diff --git a/src/Avalonia.Themes.Fluent/Menu.xaml b/src/Avalonia.Themes.Fluent/Controls/Menu.xaml
similarity index 100%
rename from src/Avalonia.Themes.Fluent/Menu.xaml
rename to src/Avalonia.Themes.Fluent/Controls/Menu.xaml
diff --git a/src/Avalonia.Themes.Fluent/MenuItem.xaml b/src/Avalonia.Themes.Fluent/Controls/MenuItem.xaml
similarity index 99%
rename from src/Avalonia.Themes.Fluent/MenuItem.xaml
rename to src/Avalonia.Themes.Fluent/Controls/MenuItem.xaml
index 1f1dcf22e2..fff7baf3bd 100644
--- a/src/Avalonia.Themes.Fluent/MenuItem.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/MenuItem.xaml
@@ -110,7 +110,7 @@
diff --git a/src/Avalonia.Themes.Fluent/PopupRoot.xaml b/src/Avalonia.Themes.Fluent/Controls/PopupRoot.xaml
similarity index 100%
rename from src/Avalonia.Themes.Fluent/PopupRoot.xaml
rename to src/Avalonia.Themes.Fluent/Controls/PopupRoot.xaml
diff --git a/src/Avalonia.Themes.Fluent/ProgressBar.xaml b/src/Avalonia.Themes.Fluent/Controls/ProgressBar.xaml
similarity index 100%
rename from src/Avalonia.Themes.Fluent/ProgressBar.xaml
rename to src/Avalonia.Themes.Fluent/Controls/ProgressBar.xaml
diff --git a/src/Avalonia.Themes.Fluent/RadioButton.xaml b/src/Avalonia.Themes.Fluent/Controls/RadioButton.xaml
similarity index 98%
rename from src/Avalonia.Themes.Fluent/RadioButton.xaml
rename to src/Avalonia.Themes.Fluent/Controls/RadioButton.xaml
index 078f51c87a..2847d1fa5a 100644
--- a/src/Avalonia.Themes.Fluent/RadioButton.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/RadioButton.xaml
@@ -25,8 +25,7 @@
+ BorderThickness="{TemplateBinding BorderThickness}">
@@ -77,6 +76,10 @@
+
+
diff --git a/src/Avalonia.Themes.Fluent/RepeatButton.xaml b/src/Avalonia.Themes.Fluent/Controls/RepeatButton.xaml
similarity index 100%
rename from src/Avalonia.Themes.Fluent/RepeatButton.xaml
rename to src/Avalonia.Themes.Fluent/Controls/RepeatButton.xaml
diff --git a/src/Avalonia.Themes.Fluent/ScrollBar.xaml b/src/Avalonia.Themes.Fluent/Controls/ScrollBar.xaml
similarity index 100%
rename from src/Avalonia.Themes.Fluent/ScrollBar.xaml
rename to src/Avalonia.Themes.Fluent/Controls/ScrollBar.xaml
diff --git a/src/Avalonia.Themes.Fluent/ScrollViewer.xaml b/src/Avalonia.Themes.Fluent/Controls/ScrollViewer.xaml
similarity index 100%
rename from src/Avalonia.Themes.Fluent/ScrollViewer.xaml
rename to src/Avalonia.Themes.Fluent/Controls/ScrollViewer.xaml
diff --git a/src/Avalonia.Themes.Fluent/Separator.xaml b/src/Avalonia.Themes.Fluent/Controls/Separator.xaml
similarity index 100%
rename from src/Avalonia.Themes.Fluent/Separator.xaml
rename to src/Avalonia.Themes.Fluent/Controls/Separator.xaml
diff --git a/src/Avalonia.Themes.Fluent/Controls/Slider.xaml b/src/Avalonia.Themes.Fluent/Controls/Slider.xaml
new file mode 100644
index 0000000000..d70eb1abe3
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/Controls/Slider.xaml
@@ -0,0 +1,275 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0,0,0,4
+ 15
+ 15
+ 32
+ 32
+ 10
+ 20
+ 20
+ 20
+ 20
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Avalonia.Themes.Fluent/SplitView.xaml b/src/Avalonia.Themes.Fluent/Controls/SplitView.xaml
similarity index 94%
rename from src/Avalonia.Themes.Fluent/SplitView.xaml
rename to src/Avalonia.Themes.Fluent/Controls/SplitView.xaml
index 71e92459f1..7d6f7a9b9a 100644
--- a/src/Avalonia.Themes.Fluent/SplitView.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/SplitView.xaml
@@ -32,12 +32,12 @@
ClipToBounds="True"
HorizontalAlignment="Left"
ZIndex="100">
-
+
-
+
@@ -106,14 +106,14 @@
ClipToBounds="True"
HorizontalAlignment="Right"
ZIndex="100">
-
+
-
+
diff --git a/src/Avalonia.Themes.Fluent/TabControl.xaml b/src/Avalonia.Themes.Fluent/Controls/TabControl.xaml
similarity index 100%
rename from src/Avalonia.Themes.Fluent/TabControl.xaml
rename to src/Avalonia.Themes.Fluent/Controls/TabControl.xaml
diff --git a/src/Avalonia.Themes.Fluent/TabItem.xaml b/src/Avalonia.Themes.Fluent/Controls/TabItem.xaml
similarity index 98%
rename from src/Avalonia.Themes.Fluent/TabItem.xaml
rename to src/Avalonia.Themes.Fluent/Controls/TabItem.xaml
index 2b0a0c1ea0..1c9574f169 100644
--- a/src/Avalonia.Themes.Fluent/TabItem.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/TabItem.xaml
@@ -39,7 +39,6 @@
TextBlock.FontSize="{TemplateBinding FontSize}"
TextBlock.FontWeight="{TemplateBinding FontWeight}" />
@@ -53,6 +52,7 @@
diff --git a/src/Avalonia.Themes.Fluent/TabStrip.xaml b/src/Avalonia.Themes.Fluent/Controls/TabStrip.xaml
similarity index 100%
rename from src/Avalonia.Themes.Fluent/TabStrip.xaml
rename to src/Avalonia.Themes.Fluent/Controls/TabStrip.xaml
diff --git a/src/Avalonia.Themes.Fluent/TabStripItem.xaml b/src/Avalonia.Themes.Fluent/Controls/TabStripItem.xaml
similarity index 96%
rename from src/Avalonia.Themes.Fluent/TabStripItem.xaml
rename to src/Avalonia.Themes.Fluent/Controls/TabStripItem.xaml
index 628ab8dddd..78ef102705 100644
--- a/src/Avalonia.Themes.Fluent/TabStripItem.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/TabStripItem.xaml
@@ -38,7 +38,6 @@
TextBlock.FontSize="{TemplateBinding FontSize}"
TextBlock.FontWeight="{TemplateBinding FontWeight}" />
@@ -46,6 +45,9 @@
+
@@ -156,6 +143,10 @@
+
+
diff --git a/src/Avalonia.Themes.Fluent/TimePicker.xaml b/src/Avalonia.Themes.Fluent/Controls/TimePicker.xaml
similarity index 67%
rename from src/Avalonia.Themes.Fluent/TimePicker.xaml
rename to src/Avalonia.Themes.Fluent/Controls/TimePicker.xaml
index 84352213e1..91969d8733 100644
--- a/src/Avalonia.Themes.Fluent/TimePicker.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/TimePicker.xaml
@@ -41,94 +41,96 @@
-
-
+
+
+
-
+
-
-
-
+
+
+
-
+
+
@@ -161,6 +163,10 @@
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
diff --git a/src/Avalonia.Themes.Fluent/Accents/FluentDark.xaml b/src/Avalonia.Themes.Fluent/FluentDark.xaml
similarity index 85%
rename from src/Avalonia.Themes.Fluent/Accents/FluentDark.xaml
rename to src/Avalonia.Themes.Fluent/FluentDark.xaml
index 9ef92a44d5..74b583a240 100644
--- a/src/Avalonia.Themes.Fluent/Accents/FluentDark.xaml
+++ b/src/Avalonia.Themes.Fluent/FluentDark.xaml
@@ -5,5 +5,5 @@
-
+
diff --git a/src/Avalonia.Themes.Fluent/Accents/FluentLight.xaml b/src/Avalonia.Themes.Fluent/FluentLight.xaml
similarity index 85%
rename from src/Avalonia.Themes.Fluent/Accents/FluentLight.xaml
rename to src/Avalonia.Themes.Fluent/FluentLight.xaml
index 8c92040122..1bc51f655e 100644
--- a/src/Avalonia.Themes.Fluent/Accents/FluentLight.xaml
+++ b/src/Avalonia.Themes.Fluent/FluentLight.xaml
@@ -5,5 +5,5 @@
-
+
diff --git a/src/Avalonia.Themes.Fluent/FluentTheme.cs b/src/Avalonia.Themes.Fluent/FluentTheme.cs
new file mode 100644
index 0000000000..43b71567fa
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/FluentTheme.cs
@@ -0,0 +1,114 @@
+using System;
+using System.Collections.Generic;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+using Avalonia.Styling;
+
+#nullable enable
+
+namespace Avalonia.Themes.Fluent
+{
+ public enum FluentThemeMode
+ {
+ Light,
+ Dark,
+ }
+
+ ///
+ /// Includes the fluent theme in an application.
+ ///
+ public class FluentTheme : IStyle, IResourceProvider
+ {
+ private readonly Uri _baseUri;
+ private IStyle[]? _loaded;
+ private bool _isLoading;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The base URL for the XAML context.
+ public FluentTheme(Uri baseUri)
+ {
+ _baseUri = baseUri;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The XAML service provider.
+ public FluentTheme(IServiceProvider serviceProvider)
+ {
+ _baseUri = ((IUriContext)serviceProvider.GetService(typeof(IUriContext))).BaseUri;
+ }
+
+ ///
+ /// Gets or sets the mode of the fluent theme (light, dark).
+ ///
+ public FluentThemeMode Mode { get; set; }
+
+ public IResourceHost? Owner => (Loaded as IResourceProvider)?.Owner;
+
+ ///
+ /// Gets the loaded style.
+ ///
+ public IStyle Loaded
+ {
+ get
+ {
+ if (_loaded == null)
+ {
+ _isLoading = true;
+ var loaded = (IStyle)AvaloniaXamlLoader.Load(GetUri(), _baseUri);
+ _loaded = new[] { loaded };
+ _isLoading = false;
+ }
+
+ return _loaded?[0]!;
+ }
+ }
+
+ bool IResourceNode.HasResources => (Loaded as IResourceProvider)?.HasResources ?? false;
+
+ IReadOnlyList IStyle.Children => _loaded ?? Array.Empty();
+
+ public event EventHandler OwnerChanged
+ {
+ add
+ {
+ if (Loaded is IResourceProvider rp)
+ {
+ rp.OwnerChanged += value;
+ }
+ }
+ remove
+ {
+ if (Loaded is IResourceProvider rp)
+ {
+ rp.OwnerChanged -= value;
+ }
+ }
+ }
+
+ public SelectorMatchResult TryAttach(IStyleable target, IStyleHost? host) => Loaded.TryAttach(target, host);
+
+ public bool TryGetResource(object key, out object? value)
+ {
+ if (!_isLoading && Loaded is IResourceProvider p)
+ {
+ return p.TryGetResource(key, out value);
+ }
+
+ value = null;
+ return false;
+ }
+
+ void IResourceProvider.AddOwner(IResourceHost owner) => (Loaded as IResourceProvider)?.AddOwner(owner);
+ void IResourceProvider.RemoveOwner(IResourceHost owner) => (Loaded as IResourceProvider)?.RemoveOwner(owner);
+
+ private Uri GetUri() => Mode switch
+ {
+ FluentThemeMode.Dark => new Uri("avares://Avalonia.Themes.Fluent/FluentDark.xaml", UriKind.Absolute),
+ _ => new Uri("avares://Avalonia.Themes.Fluent/FluentLight.xaml", UriKind.Absolute),
+ };
+ }
+}
diff --git a/src/Avalonia.Themes.Fluent/FluentTheme.xaml b/src/Avalonia.Themes.Fluent/FluentTheme.xaml
deleted file mode 100644
index 90c0f55b68..0000000000
--- a/src/Avalonia.Themes.Fluent/FluentTheme.xaml
+++ /dev/null
@@ -1,61 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/Avalonia.Themes.Fluent/Properties/AssemblyInfo.cs b/src/Avalonia.Themes.Fluent/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..0bad226ba7
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/Properties/AssemblyInfo.cs
@@ -0,0 +1,3 @@
+using Avalonia.Metadata;
+
+[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Themes.Fluent")]
diff --git a/src/Avalonia.Themes.Fluent/Slider.xaml b/src/Avalonia.Themes.Fluent/Slider.xaml
deleted file mode 100644
index 8abf78cc81..0000000000
--- a/src/Avalonia.Themes.Fluent/Slider.xaml
+++ /dev/null
@@ -1,263 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 0,0,0,4
- 15
- 15
- 32
- 32
- 10
- 20
- 20
- 20
- 20
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/Avalonia.Visuals/Animation/CompositePageTransition.cs b/src/Avalonia.Visuals/Animation/CompositePageTransition.cs
new file mode 100644
index 0000000000..9489914c97
--- /dev/null
+++ b/src/Avalonia.Visuals/Animation/CompositePageTransition.cs
@@ -0,0 +1,61 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Avalonia.Metadata;
+
+namespace Avalonia.Animation
+{
+ ///
+ /// Defines a composite page transition that can be used to combine multiple transitions.
+ ///
+ ///
+ ///
+ /// Instantiate the in XAML and initialize the
+ /// property in order to have many animations triggered at once.
+ /// For example, you can combine and .
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// ]]>
+ ///
+ ///
+ ///
+ public class CompositePageTransition : IPageTransition
+ {
+ ///
+ /// Gets or sets the transitions to be executed. Can be defined from XAML.
+ ///
+ [Content]
+ public List PageTransitions { get; set; } = new List();
+
+ ///
+ /// Starts the animation.
+ ///
+ ///
+ /// The control that is being transitioned away from. May be null.
+ ///
+ ///
+ /// The control that is being transitioned to. May be null.
+ ///
+ ///
+ /// Defines the direction of the transition.
+ ///
+ ///
+ /// A that tracks the progress of the animation.
+ ///
+ public Task Start(Visual from, Visual to, bool forward)
+ {
+ var transitionTasks = PageTransitions
+ .Select(transition => transition.Start(from, to, forward))
+ .ToList();
+ return Task.WhenAll(transitionTasks);
+ }
+ }
+}
diff --git a/src/Avalonia.Visuals/Animation/CrossFade.cs b/src/Avalonia.Visuals/Animation/CrossFade.cs
index 640f401418..0615b854da 100644
--- a/src/Avalonia.Visuals/Animation/CrossFade.cs
+++ b/src/Avalonia.Visuals/Animation/CrossFade.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
+using Avalonia.Animation.Easings;
using Avalonia.Styling;
using Avalonia.VisualTree;
@@ -74,14 +75,26 @@ namespace Avalonia.Animation
///
public TimeSpan Duration
{
- get
- {
- return _fadeOutAnimation.Duration;
- }
- set
- {
- _fadeOutAnimation.Duration = _fadeInAnimation.Duration = value;
- }
+ get => _fadeOutAnimation.Duration;
+ set => _fadeOutAnimation.Duration = _fadeInAnimation.Duration = value;
+ }
+
+ ///
+ /// Gets or sets element entrance easing.
+ ///
+ public Easing FadeInEasing
+ {
+ get => _fadeInAnimation.Easing;
+ set => _fadeInAnimation.Easing = value;
+ }
+
+ ///
+ /// Gets or sets element exit easing.
+ ///
+ public Easing FadeOutEasing
+ {
+ get => _fadeOutAnimation.Easing;
+ set => _fadeOutAnimation.Easing = value;
}
///
diff --git a/src/Avalonia.Visuals/Animation/PageSlide.cs b/src/Avalonia.Visuals/Animation/PageSlide.cs
index 501c8c0ba4..dd5d598e12 100644
--- a/src/Avalonia.Visuals/Animation/PageSlide.cs
+++ b/src/Avalonia.Visuals/Animation/PageSlide.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
+using Avalonia.Animation.Easings;
using Avalonia.Media;
using Avalonia.Styling;
using Avalonia.VisualTree;
@@ -48,6 +49,16 @@ namespace Avalonia.Animation
/// Gets the duration of the animation.
///
public SlideAxis Orientation { get; set; }
+
+ ///
+ /// Gets or sets element entrance easing.
+ ///
+ public Easing SlideInEasing { get; set; } = new LinearEasing();
+
+ ///
+ /// Gets or sets element exit easing.
+ ///
+ public Easing SlideOutEasing { get; set; } = new LinearEasing();
///
/// Starts the animation.
@@ -75,18 +86,12 @@ namespace Avalonia.Animation
{
var animation = new Animation
{
- Children =
+ Easing = SlideOutEasing,
+ Children =
{
new KeyFrame
{
- Setters =
- {
- new Setter
- {
- Property = translateProperty,
- Value = 0d
- }
- },
+ Setters = { new Setter { Property = translateProperty, Value = 0d } },
Cue = new Cue(0d)
},
new KeyFrame
@@ -100,10 +105,10 @@ namespace Avalonia.Animation
}
},
Cue = new Cue(1d)
- }
- }
+ }
+ },
+ Duration = Duration
};
- animation.Duration = Duration;
tasks.Add(animation.RunAsync(from));
}
@@ -112,9 +117,9 @@ namespace Avalonia.Animation
to.IsVisible = true;
var animation = new Animation
{
+ Easing = SlideInEasing,
Children =
{
-
new KeyFrame
{
Setters =
@@ -129,19 +134,12 @@ namespace Avalonia.Animation
},
new KeyFrame
{
- Setters =
- {
- new Setter
- {
- Property = translateProperty,
- Value = 0d
- }
- },
+ Setters = { new Setter { Property = translateProperty, Value = 0d } },
Cue = new Cue(1d)
}
- }
+ },
+ Duration = Duration
};
- animation.Duration = Duration;
tasks.Add(animation.RunAsync(to));
}
diff --git a/src/Avalonia.Visuals/ApiCompatBaseline.txt b/src/Avalonia.Visuals/ApiCompatBaseline.txt
index 148916932f..62f4def701 100644
--- a/src/Avalonia.Visuals/ApiCompatBaseline.txt
+++ b/src/Avalonia.Visuals/ApiCompatBaseline.txt
@@ -1,33 +1,5 @@
Compat issues with assembly Avalonia.Visuals:
-MembersMustExist : Member 'public void Avalonia.Media.DrawingContext.DrawGlyphRun(Avalonia.Media.IBrush, Avalonia.Media.GlyphRun, Avalonia.Point)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'public Avalonia.Media.Typeface Avalonia.Media.FontManager.GetOrAddTypeface(Avalonia.Media.FontFamily, Avalonia.Media.FontStyle, Avalonia.Media.FontWeight)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'public Avalonia.Media.Typeface Avalonia.Media.FontManager.MatchCharacter(System.Int32, Avalonia.Media.FontStyle, Avalonia.Media.FontWeight, Avalonia.Media.FontFamily, System.Globalization.CultureInfo)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'public Avalonia.Rect Avalonia.Media.GlyphRun.Bounds.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'public Avalonia.StyledProperty Avalonia.StyledProperty Avalonia.Media.GlyphRunDrawing.BaselineOriginProperty' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'public Avalonia.Point Avalonia.Media.GlyphRunDrawing.BaselineOrigin.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'public void Avalonia.Media.GlyphRunDrawing.BaselineOrigin.set(Avalonia.Point)' does not exist in the implementation but it does exist in the contract.
-CannotSealType : Type 'Avalonia.Media.Typeface' is actually (has the sealed modifier) sealed in the implementation but not sealed in the contract.
-TypeCannotChangeClassification : Type 'Avalonia.Media.Typeface' is a 'struct' in the implementation but is a 'class' in the contract.
-CannotMakeMemberNonVirtual : Member 'public System.Boolean Avalonia.Media.Typeface.Equals(System.Object)' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'public System.Int32 Avalonia.Media.Typeface.GetHashCode()' is non-virtual in the implementation but is virtual in the contract.
-TypesMustExist : Type 'Avalonia.Media.Fonts.FontKey' does not exist in the implementation but it does exist in the contract.
-CannotAddAbstractMembers : Member 'public Avalonia.Size Avalonia.Media.TextFormatting.DrawableTextRun.Size' is abstract in the implementation but is missing in the contract.
-MembersMustExist : Member 'public Avalonia.Rect Avalonia.Media.TextFormatting.DrawableTextRun.Bounds.get()' does not exist in the implementation but it does exist in the contract.
-CannotAddAbstractMembers : Member 'public void Avalonia.Media.TextFormatting.DrawableTextRun.Draw(Avalonia.Media.DrawingContext)' is abstract in the implementation but is missing in the contract.
-MembersMustExist : Member 'public void Avalonia.Media.TextFormatting.DrawableTextRun.Draw(Avalonia.Media.DrawingContext, Avalonia.Point)' does not exist in the implementation but it does exist in the contract.
-CannotAddAbstractMembers : Member 'public Avalonia.Size Avalonia.Media.TextFormatting.DrawableTextRun.Size.get()' is abstract in the implementation but is missing in the contract.
-MembersMustExist : Member 'public Avalonia.Rect Avalonia.Media.TextFormatting.ShapedTextCharacters.Bounds.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'public void Avalonia.Media.TextFormatting.ShapedTextCharacters.Draw(Avalonia.Media.DrawingContext, Avalonia.Point)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'public void Avalonia.Media.TextFormatting.TextLayout.Draw(Avalonia.Media.DrawingContext, Avalonia.Point)' does not exist in the implementation but it does exist in the contract.
-CannotAddAbstractMembers : Member 'public Avalonia.Media.TextFormatting.TextLineBreak Avalonia.Media.TextFormatting.TextLine.TextLineBreak' is abstract in the implementation but is missing in the contract.
-CannotAddAbstractMembers : Member 'public void Avalonia.Media.TextFormatting.TextLine.Draw(Avalonia.Media.DrawingContext)' is abstract in the implementation but is missing in the contract.
-MembersMustExist : Member 'public void Avalonia.Media.TextFormatting.TextLine.Draw(Avalonia.Media.DrawingContext, Avalonia.Point)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'public Avalonia.Media.TextFormatting.TextLineBreak Avalonia.Media.TextFormatting.TextLine.LineBreak.get()' does not exist in the implementation but it does exist in the contract.
-CannotAddAbstractMembers : Member 'public Avalonia.Media.TextFormatting.TextLineBreak Avalonia.Media.TextFormatting.TextLine.TextLineBreak.get()' is abstract in the implementation but is missing in the contract.
-InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Platform.IDrawingContextImpl.DrawGlyphRun(Avalonia.Media.IBrush, Avalonia.Media.GlyphRun)' is present in the implementation but not in the contract.
-InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Platform.IDrawingContextImpl.DrawGlyphRun(Avalonia.Media.IBrush, Avalonia.Media.GlyphRun, Avalonia.Point)' is present in the contract but not in the implementation.
-MembersMustExist : Member 'public void Avalonia.Platform.IDrawingContextImpl.DrawGlyphRun(Avalonia.Media.IBrush, Avalonia.Media.GlyphRun, Avalonia.Point)' does not exist in the implementation but it does exist in the contract.
-InterfacesShouldHaveSameMembers : Interface member 'public System.Boolean Avalonia.Platform.IFontManagerImpl.TryMatchCharacter(System.Int32, Avalonia.Media.FontStyle, Avalonia.Media.FontWeight, Avalonia.Media.FontFamily, System.Globalization.CultureInfo, Avalonia.Media.Fonts.FontKey)' is present in the contract but not in the implementation.
-MembersMustExist : Member 'public System.Boolean Avalonia.Platform.IFontManagerImpl.TryMatchCharacter(System.Int32, Avalonia.Media.FontStyle, Avalonia.Media.FontWeight, Avalonia.Media.FontFamily, System.Globalization.CultureInfo, Avalonia.Media.Fonts.FontKey)' does not exist in the implementation but it does exist in the contract.
-InterfacesShouldHaveSameMembers : Interface member 'public System.Boolean Avalonia.Platform.IFontManagerImpl.TryMatchCharacter(System.Int32, Avalonia.Media.FontStyle, Avalonia.Media.FontWeight, Avalonia.Media.FontFamily, System.Globalization.CultureInfo, Avalonia.Media.Typeface)' is present in the implementation but not in the contract.
-Total Issues: 31
+MembersMustExist : Member 'public Avalonia.StyledProperty> Avalonia.StyledProperty> Avalonia.Media.DashStyle.DashesProperty' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'public System.Collections.Generic.IReadOnlyList Avalonia.Media.DashStyle.Dashes.get()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'public void Avalonia.Media.DashStyle.Dashes.set(System.Collections.Generic.IReadOnlyList)' does not exist in the implementation but it does exist in the contract.
+Total Issues: 3
diff --git a/src/Avalonia.Visuals/CornerRadius.cs b/src/Avalonia.Visuals/CornerRadius.cs
index c02aacfb4d..037bb16e31 100644
--- a/src/Avalonia.Visuals/CornerRadius.cs
+++ b/src/Avalonia.Visuals/CornerRadius.cs
@@ -1,6 +1,8 @@
using System;
using System.Globalization;
+#if !BUILDTASK
using Avalonia.Animation.Animators;
+#endif
using Avalonia.Utilities;
namespace Avalonia
@@ -8,11 +10,16 @@ namespace Avalonia
///
/// Represents the radii of a rectangle's corners.
///
- public readonly struct CornerRadius : IEquatable
+#if !BUILDTASK
+ public
+#endif
+ readonly struct CornerRadius : IEquatable
{
static CornerRadius()
{
+#if !BUILDTASK
Animation.Animation.RegisterAnimator(prop => typeof(CornerRadius).IsAssignableFrom(prop.PropertyType));
+#endif
}
public CornerRadius(double uniformRadius)
diff --git a/src/Avalonia.Visuals/Matrix.cs b/src/Avalonia.Visuals/Matrix.cs
index 206b842220..8136f843df 100644
--- a/src/Avalonia.Visuals/Matrix.cs
+++ b/src/Avalonia.Visuals/Matrix.cs
@@ -7,7 +7,10 @@ namespace Avalonia
///
/// A 2x3 matrix.
///
- public readonly struct Matrix : IEquatable
+#if !BUILDTASK
+ public
+#endif
+ readonly struct Matrix : IEquatable
{
private readonly double _m11;
private readonly double _m12;
@@ -279,25 +282,44 @@ namespace Avalonia
}
///
- /// Inverts the Matrix.
+ /// Attempts to invert the Matrix.
///
- /// The inverted matrix.
- public Matrix Invert()
+ /// The inverted matrix or when matrix is not invertible.
+ public bool TryInvert(out Matrix inverted)
{
double d = GetDeterminant();
if (MathUtilities.IsZero(d))
{
- throw new InvalidOperationException("Transform is not invertible.");
+ inverted = default;
+
+ return false;
}
- return new Matrix(
+ inverted = new Matrix(
_m22 / d,
-_m12 / d,
-_m21 / d,
_m11 / d,
((_m21 * _m32) - (_m22 * _m31)) / d,
((_m12 * _m31) - (_m11 * _m32)) / d);
+
+ return true;
+ }
+
+ ///
+ /// Inverts the Matrix.
+ ///
+ /// Matrix is not invertible.
+ /// The inverted matrix.
+ public Matrix Invert()
+ {
+ if (!TryInvert(out Matrix inverted))
+ {
+ throw new InvalidOperationException("Transform is not invertible.");
+ }
+
+ return inverted;
}
///
diff --git a/src/Avalonia.Visuals/Media/Color.cs b/src/Avalonia.Visuals/Media/Color.cs
index 16b4f90d57..a57a962db4 100644
--- a/src/Avalonia.Visuals/Media/Color.cs
+++ b/src/Avalonia.Visuals/Media/Color.cs
@@ -1,17 +1,24 @@
using System;
using System.Globalization;
+#if !BUILDTASK
using Avalonia.Animation.Animators;
+#endif
namespace Avalonia.Media
{
///
/// An ARGB color.
///
- public readonly struct Color : IEquatable
+#if !BUILDTASK
+ public
+#endif
+ readonly struct Color : IEquatable
{
static Color()
{
+#if !BUILDTASK
Animation.Animation.RegisterAnimator(prop => typeof(Color).IsAssignableFrom(prop.PropertyType));
+#endif
}
///
@@ -223,7 +230,12 @@ namespace Avalonia.Media
if (input.Length == 3 || input.Length == 4)
{
var extendedLength = 2 * input.Length;
+
+#if !BUILDTASK
Span extended = stackalloc char[extendedLength];
+#else
+ char[] extended = new char[extendedLength];
+#endif
for (int i = 0; i < input.Length; i++)
{
diff --git a/src/Avalonia.Visuals/Media/ConicGradientBrush.cs b/src/Avalonia.Visuals/Media/ConicGradientBrush.cs
new file mode 100644
index 0000000000..7c1266fa17
--- /dev/null
+++ b/src/Avalonia.Visuals/Media/ConicGradientBrush.cs
@@ -0,0 +1,55 @@
+using Avalonia.Media.Immutable;
+
+namespace Avalonia.Media
+{
+ ///
+ /// Paints an area with a swept circular gradient.
+ ///
+ public sealed class ConicGradientBrush : GradientBrush, IConicGradientBrush
+ {
+ ///
+ /// Defines the property.
+ ///
+ public static readonly StyledProperty CenterProperty =
+ AvaloniaProperty.Register(
+ nameof(Center),
+ RelativePoint.Center);
+
+ ///
+ /// Defines the property.
+ ///
+ public static readonly StyledProperty AngleProperty =
+ AvaloniaProperty.Register(
+ nameof(Angle),
+ 0);
+
+ static ConicGradientBrush()
+ {
+ AffectsRender(CenterProperty, AngleProperty);
+ }
+
+ ///
+ /// Gets or sets the center point of the gradient.
+ ///
+ public RelativePoint Center
+ {
+ get { return GetValue(CenterProperty); }
+ set { SetValue(CenterProperty, value); }
+ }
+
+ ///
+ /// Gets or sets the angle of the start and end of the sweep, measured from above the center point.
+ ///
+ public double Angle
+ {
+ get { return GetValue(AngleProperty); }
+ set { SetValue(AngleProperty, value); }
+ }
+
+ ///
+ public override IBrush ToImmutable()
+ {
+ return new ImmutableConicGradientBrush(this);
+ }
+ }
+}
diff --git a/src/Avalonia.Visuals/Media/DashStyle.cs b/src/Avalonia.Visuals/Media/DashStyle.cs
index 1e813edc13..acba2d3615 100644
--- a/src/Avalonia.Visuals/Media/DashStyle.cs
+++ b/src/Avalonia.Visuals/Media/DashStyle.cs
@@ -1,11 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using Avalonia.Animation;
+using Avalonia.Collections;
+using Avalonia.Media.Immutable;
+
+#nullable enable
+
namespace Avalonia.Media
{
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using Avalonia.Animation;
- using Avalonia.Media.Immutable;
-
///
/// Represents the sequence of dashes and gaps that will be applied by a .
///
@@ -14,8 +17,8 @@ namespace Avalonia.Media
///
/// Defines the property.
///
- public static readonly StyledProperty> DashesProperty =
- AvaloniaProperty.Register>(nameof(Dashes));
+ public static readonly StyledProperty> DashesProperty =
+ AvaloniaProperty.Register>(nameof(Dashes));
///
/// Defines the property.
@@ -23,10 +26,10 @@ namespace Avalonia.Media
public static readonly StyledProperty OffsetProperty =
AvaloniaProperty.Register(nameof(Offset));
- private static ImmutableDashStyle s_dash;
- private static ImmutableDashStyle s_dot;
- private static ImmutableDashStyle s_dashDot;
- private static ImmutableDashStyle s_dashDotDot;
+ private static ImmutableDashStyle? s_dash;
+ private static ImmutableDashStyle? s_dot;
+ private static ImmutableDashStyle? s_dashDot;
+ private static ImmutableDashStyle? s_dashDotDot;
///
/// Initializes a new instance of the class.
@@ -41,9 +44,9 @@ namespace Avalonia.Media
///
/// The dashes collection.
/// The dash sequence offset.
- public DashStyle(IEnumerable dashes, double offset)
+ public DashStyle(IEnumerable? dashes, double offset)
{
- Dashes = (IReadOnlyList)dashes?.ToList() ?? Array.Empty();
+ Dashes = (dashes as AvaloniaList) ?? new AvaloniaList(dashes ?? Array.Empty());
Offset = offset;
}
@@ -61,31 +64,27 @@ namespace Avalonia.Media
///
/// Represents a dashed .
///
- public static IDashStyle Dash =>
- s_dash ?? (s_dash = new ImmutableDashStyle(new double[] { 2, 2 }, 1));
+ public static IDashStyle Dash => s_dash ??= new ImmutableDashStyle(new double[] { 2, 2 }, 1);
///
/// Represents a dotted .
///
- public static IDashStyle Dot =>
- s_dot ?? (s_dot = new ImmutableDashStyle(new double[] { 0, 2 }, 0));
+ public static IDashStyle Dot => s_dot ??= new ImmutableDashStyle(new double[] { 0, 2 }, 0);
///
/// Represents a dashed dotted .
///
- public static IDashStyle DashDot =>
- s_dashDot ?? (s_dashDot = new ImmutableDashStyle(new double[] { 2, 2, 0, 2 }, 1));
+ public static IDashStyle DashDot => s_dashDot ??= new ImmutableDashStyle(new double[] { 2, 2, 0, 2 }, 1);
///
/// Represents a dashed double dotted .
///
- public static IDashStyle DashDotDot =>
- s_dashDotDot ?? (s_dashDotDot = new ImmutableDashStyle(new double[] { 2, 2, 0, 2, 0, 2 }, 1));
+ public static IDashStyle DashDotDot => s_dashDotDot ??= new ImmutableDashStyle(new double[] { 2, 2, 0, 2, 0, 2 }, 1);
///
/// Gets or sets the length of alternating dashes and gaps.
///
- public IReadOnlyList Dashes
+ public AvaloniaList Dashes
{
get => GetValue(DashesProperty);
set => SetValue(DashesProperty, value);
@@ -100,15 +99,43 @@ namespace Avalonia.Media
set => SetValue(OffsetProperty, value);
}
+ IReadOnlyList IDashStyle.Dashes => Dashes;
+
///
/// Raised when the dash style changes.
///
- public event EventHandler Invalidated;
+ public event EventHandler? Invalidated;
///
/// Returns an immutable clone of the .
///
///
public ImmutableDashStyle ToImmutable() => new ImmutableDashStyle(Dashes, Offset);
+
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ {
+ base.OnPropertyChanged(change);
+
+ if (change.Property == DashesProperty)
+ {
+ var oldValue = change.OldValue.GetValueOrDefault>();
+ var newValue = change.NewValue.GetValueOrDefault>();
+
+ if (oldValue is object)
+ {
+ oldValue.CollectionChanged -= DashesChanged;
+ }
+
+ if (newValue is object)
+ {
+ newValue.CollectionChanged += DashesChanged;
+ }
+ }
+ }
+
+ private void DashesChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ Invalidated?.Invoke(this, e);
+ }
}
}
diff --git a/src/Avalonia.Visuals/Media/Drawing.cs b/src/Avalonia.Visuals/Media/Drawing.cs
index 6bc808e407..66d05e7e48 100644
--- a/src/Avalonia.Visuals/Media/Drawing.cs
+++ b/src/Avalonia.Visuals/Media/Drawing.cs
@@ -1,11 +1,19 @@
-using Avalonia.Platform;
-
-namespace Avalonia.Media
+namespace Avalonia.Media
{
+ ///
+ /// Abstract class that describes a 2-D drawing.
+ ///
public abstract class Drawing : AvaloniaObject
{
+ ///
+ /// Draws this drawing to the given .
+ ///
+ /// The drawing context.
public abstract void Draw(DrawingContext context);
+ ///
+ /// Gets the drawing's bounding rectangle.
+ ///
public abstract Rect GetBounds();
}
}
diff --git a/src/Avalonia.Visuals/Media/EllipseGeometry.cs b/src/Avalonia.Visuals/Media/EllipseGeometry.cs
index fd73eee69a..bae6dc3d8c 100644
--- a/src/Avalonia.Visuals/Media/EllipseGeometry.cs
+++ b/src/Avalonia.Visuals/Media/EllipseGeometry.cs
@@ -12,10 +12,28 @@ namespace Avalonia.Media
///
public static readonly StyledProperty RectProperty =
AvaloniaProperty.Register(nameof(Rect));
+
+ ///
+ /// Defines the property.
+ ///
+ public static readonly StyledProperty RadiusXProperty =
+ AvaloniaProperty.Register(nameof(RadiusX));
+
+ ///
+ /// Defines the property.
+ ///
+ public static readonly StyledProperty RadiusYProperty =
+ AvaloniaProperty.Register(nameof(RadiusY));
+
+ ///
+ /// Defines the property.
+ ///
+ public static readonly StyledProperty CenterProperty =
+ AvaloniaProperty.Register(nameof(Center));
static EllipseGeometry()
{
- AffectsGeometry(RectProperty);
+ AffectsGeometry(RectProperty, RadiusXProperty, RadiusYProperty, CenterProperty);
}
///
@@ -43,6 +61,33 @@ namespace Avalonia.Media
set => SetValue(RectProperty, value);
}
+ ///
+ /// Gets or sets a double that defines the radius in the X-axis of the ellipse.
+ ///
+ public double RadiusX
+ {
+ get => GetValue(RadiusXProperty);
+ set => SetValue(RadiusXProperty, value);
+ }
+
+ ///
+ /// Gets or sets a double that defines the radius in the Y-axis of the ellipse.
+ ///
+ public double RadiusY
+ {
+ get => GetValue(RadiusYProperty);
+ set => SetValue(RadiusYProperty, value);
+ }
+
+ ///
+ /// Gets or sets a point that defines the center of the ellipse.
+ ///
+ public Point Center
+ {
+ get => GetValue(CenterProperty);
+ set => SetValue(CenterProperty, value);
+ }
+
///
public override Geometry Clone()
{
@@ -54,7 +99,14 @@ namespace Avalonia.Media
{
var factory = AvaloniaLocator.Current.GetService();
- return factory.CreateEllipseGeometry(Rect);
+ if (Rect != default) return factory.CreateEllipseGeometry(Rect);
+
+ var originX = Center.X - RadiusX;
+ var originY = Center.Y - RadiusY;
+ var width = RadiusX * 2;
+ var height = RadiusY * 2;
+
+ return factory.CreateEllipseGeometry(new Rect(originX, originY, width, height));
}
}
}
diff --git a/src/Avalonia.Visuals/Media/FontFamily.cs b/src/Avalonia.Visuals/Media/FontFamily.cs
index 9db49200cd..f018733235 100644
--- a/src/Avalonia.Visuals/Media/FontFamily.cs
+++ b/src/Avalonia.Visuals/Media/FontFamily.cs
@@ -133,6 +133,16 @@ namespace Avalonia.Media
}
}
+ ///
+ /// Parses a string.
+ ///
+ /// The string.
+ ///
+ ///
+ /// Specified family is not supported.
+ ///
+ public static FontFamily Parse(string s) => Parse(s, null);
+
///
/// Parses a string.
///
@@ -142,7 +152,7 @@ namespace Avalonia.Media
///
/// Specified family is not supported.
///
- public static FontFamily Parse(string s, Uri baseUri = null)
+ public static FontFamily Parse(string s, Uri baseUri)
{
if (string.IsNullOrEmpty(s))
{
diff --git a/src/Avalonia.Visuals/Media/Geometry.cs b/src/Avalonia.Visuals/Media/Geometry.cs
index 33aafb58fc..ccef6665a9 100644
--- a/src/Avalonia.Visuals/Media/Geometry.cs
+++ b/src/Avalonia.Visuals/Media/Geometry.cs
@@ -84,7 +84,7 @@ namespace Avalonia.Media
///
/// The stroke thickness.
/// The bounding rectangle.
- public Rect GetRenderBounds(Pen pen) => PlatformImpl?.GetRenderBounds(pen) ?? Rect.Empty;
+ public Rect GetRenderBounds(IPen pen) => PlatformImpl?.GetRenderBounds(pen) ?? Rect.Empty;
///
/// Indicates whether the geometry's fill contains the specified point.
@@ -102,7 +102,7 @@ namespace Avalonia.Media
/// The pen to use.
/// The point.
/// true if the geometry contains the point; otherwise, false.
- public bool StrokeContains(Pen pen, Point point)
+ public bool StrokeContains(IPen pen, Point point)
{
return PlatformImpl?.StrokeContains(pen, point) == true;
}
diff --git a/src/Avalonia.Visuals/Media/GeometryDrawing.cs b/src/Avalonia.Visuals/Media/GeometryDrawing.cs
index 4df3aa8ae2..e46e3a7d5f 100644
--- a/src/Avalonia.Visuals/Media/GeometryDrawing.cs
+++ b/src/Avalonia.Visuals/Media/GeometryDrawing.cs
@@ -1,12 +1,38 @@
-using Avalonia.Metadata;
+using Avalonia.Media.Immutable;
+using Avalonia.Metadata;
namespace Avalonia.Media
{
+ ///
+ /// Represents a drawing operation that combines
+ /// a geometry with and brush and/or pen to produce rendered content.
+ ///
public class GeometryDrawing : Drawing
{
+ // Adding the Pen's stroke thickness here could yield wrong results due to transforms.
+ private static readonly IPen s_boundsPen = new ImmutablePen(Colors.Black.ToUint32(), 0);
+
+ ///
+ /// Defines the property.
+ ///
public static readonly StyledProperty GeometryProperty =
AvaloniaProperty.Register(nameof(Geometry));
+ ///
+ /// Defines the property.
+ ///
+ public static readonly StyledProperty BrushProperty =
+ AvaloniaProperty.Register(nameof(Brush), Brushes.Transparent);
+
+ ///
+ /// Defines the property.
+ ///
+ public static readonly StyledProperty PenProperty =
+ AvaloniaProperty.Register(nameof(Pen));
+
+ ///
+ /// Gets or sets the that describes the shape of this .
+ ///
[Content]
public Geometry Geometry
{
@@ -14,18 +40,18 @@ namespace Avalonia.Media
set => SetValue(GeometryProperty, value);
}
- public static readonly StyledProperty BrushProperty =
- AvaloniaProperty.Register(nameof(Brush), Brushes.Transparent);
-
+ ///
+ /// Gets or sets the used to fill the interior of the shape described by this .
+ ///
public IBrush Brush
{
get => GetValue(BrushProperty);
set => SetValue(BrushProperty, value);
}
- public static readonly StyledProperty PenProperty =
- AvaloniaProperty.Register(nameof(Pen));
-
+ ///
+ /// Gets or sets the used to stroke this .
+ ///
public IPen Pen
{
get => GetValue(PenProperty);
@@ -42,9 +68,7 @@ namespace Avalonia.Media
public override Rect GetBounds()
{
- // adding the Pen's stroke thickness here could yield wrong results due to transforms
- var pen = new Pen(Brushes.Black, 0);
- return Geometry?.GetRenderBounds(pen) ?? new Rect();
+ return Geometry?.GetRenderBounds(s_boundsPen) ?? Rect.Empty;
}
}
}
diff --git a/src/Avalonia.Visuals/Media/GlyphRun.cs b/src/Avalonia.Visuals/Media/GlyphRun.cs
index 14ab083b4f..af228ec57b 100644
--- a/src/Avalonia.Visuals/Media/GlyphRun.cs
+++ b/src/Avalonia.Visuals/Media/GlyphRun.cs
@@ -399,14 +399,14 @@ namespace Avalonia.Media
if (characterIndex > GlyphClusters[GlyphClusters.Length - 1])
{
- return _glyphClusters.End;
+ return _glyphClusters.Length - 1;
}
}
else
{
if (characterIndex < GlyphClusters[GlyphClusters.Length - 1])
{
- return _glyphClusters.End;
+ return _glyphClusters.Length - 1;
}
if (characterIndex > GlyphClusters[0])
@@ -611,8 +611,6 @@ namespace Avalonia.Media
throw new InvalidOperationException();
}
- _baselineOrigin = new Point(0, -GlyphTypeface.Ascent * Scale);
-
var platformRenderInterface = AvaloniaLocator.Current.GetService();
_glyphRunImpl = platformRenderInterface.CreateGlyphRun(this, out var width);
diff --git a/src/Avalonia.Visuals/Media/IConicGradientBrush.cs b/src/Avalonia.Visuals/Media/IConicGradientBrush.cs
new file mode 100644
index 0000000000..5368dd1851
--- /dev/null
+++ b/src/Avalonia.Visuals/Media/IConicGradientBrush.cs
@@ -0,0 +1,19 @@
+namespace Avalonia.Media
+{
+ ///
+ /// Paints an area with a conic gradient.
+ ///
+ public interface IConicGradientBrush : IGradientBrush
+ {
+ ///
+ /// Gets the center point for the gradient.
+ ///
+ RelativePoint Center { get; }
+
+ ///
+ /// Gets the starting angle for the gradient in degrees, measured from
+ /// the point above the center point.
+ ///
+ double Angle { get; }
+ }
+}
diff --git a/src/Avalonia.Visuals/Media/Imaging/Bitmap.cs b/src/Avalonia.Visuals/Media/Imaging/Bitmap.cs
index ca303211cd..5a0c57b333 100644
--- a/src/Avalonia.Visuals/Media/Imaging/Bitmap.cs
+++ b/src/Avalonia.Visuals/Media/Imaging/Bitmap.cs
@@ -99,7 +99,6 @@ namespace Avalonia.Media.Imaging
/// Initializes a new instance of the class.
///
/// The pixel format.
- /// The alpha format.
/// The pointer to the source bytes.
/// The size of the bitmap in device pixels.
/// The DPI of the bitmap.
diff --git a/src/Avalonia.Visuals/Media/Immutable/ImmutableConicGradientBrush.cs b/src/Avalonia.Visuals/Media/Immutable/ImmutableConicGradientBrush.cs
new file mode 100644
index 0000000000..d3c80dfcad
--- /dev/null
+++ b/src/Avalonia.Visuals/Media/Immutable/ImmutableConicGradientBrush.cs
@@ -0,0 +1,47 @@
+using System.Collections.Generic;
+
+namespace Avalonia.Media.Immutable
+{
+ ///
+ /// A brush that draws with a sweep gradient.
+ ///
+ public class ImmutableConicGradientBrush : ImmutableGradientBrush, IConicGradientBrush
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The gradient stops.
+ /// The opacity of the brush.
+ /// The spread method.
+ /// The center point for the gradient.
+ /// The starting angle for the gradient.
+ public ImmutableConicGradientBrush(
+ IReadOnlyList gradientStops,
+ double opacity = 1,
+ GradientSpreadMethod spreadMethod = GradientSpreadMethod.Pad,
+ RelativePoint? center = null,
+ double angle = 0)
+ : base(gradientStops, opacity, spreadMethod)
+ {
+ Center = center ?? RelativePoint.Center;
+ Angle = angle;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The brush from which this brush's properties should be copied.
+ public ImmutableConicGradientBrush(ConicGradientBrush source)
+ : base(source)
+ {
+ Center = source.Center;
+ Angle = source.Angle;
+ }
+
+ ///
+ public RelativePoint Center { get; }
+
+ ///
+ public double Angle { get; }
+ }
+}
diff --git a/src/Avalonia.Visuals/Media/KnownColors.cs b/src/Avalonia.Visuals/Media/KnownColors.cs
index 0887d2c913..fe09f5f538 100644
--- a/src/Avalonia.Visuals/Media/KnownColors.cs
+++ b/src/Avalonia.Visuals/Media/KnownColors.cs
@@ -8,7 +8,9 @@ namespace Avalonia.Media
{
private static readonly IReadOnlyDictionary _knownColorNames;
private static readonly IReadOnlyDictionary _knownColors;
+#if !BUILDTASK
private static readonly Dictionary _knownBrushes;
+#endif
static KnownColors()
{
@@ -32,14 +34,19 @@ namespace Avalonia.Media
_knownColorNames = knownColorNames;
_knownColors = knownColors;
+
+#if !BUILDTASK
_knownBrushes = new Dictionary();
+#endif
}
+#if !BUILDTASK
public static ISolidColorBrush GetKnownBrush(string s)
{
var color = GetKnownColor(s);
return color != KnownColor.None ? color.ToBrush() : null;
}
+#endif
public static KnownColor GetKnownColor(string s)
{
@@ -61,6 +68,7 @@ namespace Avalonia.Media
return Color.FromUInt32((uint)color);
}
+#if !BUILDTASK
public static ISolidColorBrush ToBrush(this KnownColor color)
{
lock (_knownBrushes)
@@ -74,6 +82,7 @@ namespace Avalonia.Media
return brush;
}
}
+#endif
}
internal enum KnownColor : uint
diff --git a/src/Avalonia.Visuals/Media/PathFigure.cs b/src/Avalonia.Visuals/Media/PathFigure.cs
index d0eb67ba39..caf86cb234 100644
--- a/src/Avalonia.Visuals/Media/PathFigure.cs
+++ b/src/Avalonia.Visuals/Media/PathFigure.cs
@@ -1,3 +1,7 @@
+#nullable enable
+using System;
+using System.Linq;
+using Avalonia.Collections;
using Avalonia.Metadata;
namespace Avalonia.Media
@@ -8,22 +12,36 @@ namespace Avalonia.Media
/// Defines the property.
///
public static readonly StyledProperty IsClosedProperty
- = AvaloniaProperty.Register(nameof(IsClosed), true);
+ = AvaloniaProperty.Register(nameof(IsClosed), true);
+
///
/// Defines the property.
///
public static readonly StyledProperty IsFilledProperty
- = AvaloniaProperty.Register(nameof(IsFilled), true);
+ = AvaloniaProperty.Register(nameof(IsFilled), true);
+
///
/// Defines the property.
///
- public static readonly DirectProperty SegmentsProperty
- = AvaloniaProperty.RegisterDirect(nameof(Segments), f => f.Segments, (f, s) => f.Segments = s);
+ public static readonly DirectProperty SegmentsProperty
+ = AvaloniaProperty.RegisterDirect(
+ nameof(Segments),
+ f => f.Segments,
+ (f, s) => f.Segments = s);
+
///
/// Defines the property.
///
public static readonly StyledProperty StartPointProperty
- = AvaloniaProperty.Register(nameof(StartPoint));
+ = AvaloniaProperty.Register(nameof(StartPoint));
+
+ internal event EventHandler? SegmentsInvalidated;
+
+ private PathSegments? _segments;
+
+ private IDisposable? _segmentsDisposable;
+
+ private IDisposable? _segmentsPropertiesDisposable;
///
/// Initializes a new instance of the class.
@@ -33,6 +51,31 @@ namespace Avalonia.Media
Segments = new PathSegments();
}
+ static PathFigure()
+ {
+ SegmentsProperty.Changed.AddClassHandler(
+ (s, e) =>
+ s.OnSegmentsChanged());
+ }
+
+ private void OnSegmentsChanged()
+ {
+ _segmentsDisposable?.Dispose();
+ _segmentsPropertiesDisposable?.Dispose();
+
+ _segmentsDisposable = _segments?.ForEachItem(
+ _ => InvalidateSegments(),
+ _ => InvalidateSegments(),
+ InvalidateSegments);
+
+ _segmentsPropertiesDisposable = _segments?.TrackItemPropertyChanged(_ => InvalidateSegments());
+ }
+
+ private void InvalidateSegments()
+ {
+ SegmentsInvalidated?.Invoke(this, EventArgs.Empty);
+ }
+
///
/// Gets or sets a value indicating whether this instance is closed.
///
@@ -64,7 +107,7 @@ namespace Avalonia.Media
/// The segments.
///
[Content]
- public PathSegments Segments
+ public PathSegments? Segments
{
get { return _segments; }
set { SetAndRaise(SegmentsProperty, ref _segments, value); }
@@ -81,22 +124,23 @@ namespace Avalonia.Media
get { return GetValue(StartPointProperty); }
set { SetValue(StartPointProperty, value); }
}
+
+ public override string ToString()
+ => $"M {StartPoint} {string.Join(" ", _segments ?? Enumerable.Empty())}{(IsClosed ? "Z" : "")}";
internal void ApplyTo(StreamGeometryContext ctx)
{
ctx.BeginFigure(StartPoint, IsFilled);
- foreach (var segment in Segments)
+ if (Segments != null)
{
- segment.ApplyTo(ctx);
+ foreach (var segment in Segments)
+ {
+ segment.ApplyTo(ctx);
+ }
}
ctx.EndFigure(IsClosed);
}
-
- private PathSegments _segments;
-
- public override string ToString()
- => $"M {StartPoint} {string.Join(" ", _segments)}{(IsClosed ? "Z" : "")}";
}
-}
\ No newline at end of file
+}
diff --git a/src/Avalonia.Visuals/Media/PathGeometry.cs b/src/Avalonia.Visuals/Media/PathGeometry.cs
index fbc29aedc8..3d11c19b7d 100644
--- a/src/Avalonia.Visuals/Media/PathGeometry.cs
+++ b/src/Avalonia.Visuals/Media/PathGeometry.cs
@@ -104,12 +104,26 @@ namespace Avalonia.Media
_figuresPropertiesObserver?.Dispose();
_figuresObserver = figures?.ForEachItem(
- _ => InvalidateGeometry(),
- _ => InvalidateGeometry(),
- () => InvalidateGeometry());
+ s =>
+ {
+ s.SegmentsInvalidated += InvalidateGeometryFromSegments;
+ InvalidateGeometry();
+ },
+ s =>
+ {
+ s.SegmentsInvalidated -= InvalidateGeometryFromSegments;
+ InvalidateGeometry();
+ },
+ InvalidateGeometry);
+
_figuresPropertiesObserver = figures?.TrackItemPropertyChanged(_ => InvalidateGeometry());
+
}
+ private void InvalidateGeometryFromSegments(object _, EventArgs __)
+ {
+ InvalidateGeometry();
+ }
public override string ToString()
=> $"{(FillRule != FillRule.EvenOdd ? "F1 " : "")}{(string.Join(" ", Figures))}";
diff --git a/src/Avalonia.Visuals/Media/TextDecoration.cs b/src/Avalonia.Visuals/Media/TextDecoration.cs
index d9b3f664ce..57936426f3 100644
--- a/src/Avalonia.Visuals/Media/TextDecoration.cs
+++ b/src/Avalonia.Visuals/Media/TextDecoration.cs
@@ -189,11 +189,11 @@ namespace Avalonia.Media
break;
case TextDecorationLocation.Strikethrough:
origin += new Point(shapedTextCharacters.GlyphRun.BaselineOrigin.X,
- shapedTextCharacters.GlyphRun.BaselineOrigin.Y - fontMetrics.StrikethroughPosition);
+ shapedTextCharacters.GlyphRun.BaselineOrigin.Y + fontMetrics.StrikethroughPosition);
break;
case TextDecorationLocation.Underline:
origin += new Point(shapedTextCharacters.GlyphRun.BaselineOrigin.X,
- shapedTextCharacters.GlyphRun.BaselineOrigin.Y - fontMetrics.UnderlinePosition);
+ shapedTextCharacters.GlyphRun.BaselineOrigin.Y + fontMetrics.UnderlinePosition);
break;
}
diff --git a/src/Avalonia.Visuals/Media/TextFormatting/ShapedTextCharacters.cs b/src/Avalonia.Visuals/Media/TextFormatting/ShapedTextCharacters.cs
index 09ecc0a026..9f6f2b2f43 100644
--- a/src/Avalonia.Visuals/Media/TextFormatting/ShapedTextCharacters.cs
+++ b/src/Avalonia.Visuals/Media/TextFormatting/ShapedTextCharacters.cs
@@ -52,7 +52,7 @@ namespace Avalonia.Media.TextFormatting
return;
}
- if (Properties.Typeface == null)
+ if (Properties.Typeface == default)
{
return;
}
diff --git a/src/Avalonia.Visuals/Media/TextFormatting/TextFormatterImpl.cs b/src/Avalonia.Visuals/Media/TextFormatting/TextFormatterImpl.cs
index 3e85f0f6f0..6ae5258323 100644
--- a/src/Avalonia.Visuals/Media/TextFormatting/TextFormatterImpl.cs
+++ b/src/Avalonia.Visuals/Media/TextFormatting/TextFormatterImpl.cs
@@ -43,18 +43,23 @@ namespace Avalonia.Media.TextFormatting
}
///
- /// Measures the number of characters that fits into available width.
+ /// Measures the number of characters that fit into available width.
///
/// The text run.
/// The available width.
- ///
- internal static int MeasureCharacters(ShapedTextCharacters textCharacters, double availableWidth)
+ /// The count of fitting characters.
+ ///
+ /// true if characters fit into the available width; otherwise, false.
+ ///
+ internal static bool TryMeasureCharacters(ShapedTextCharacters textCharacters, double availableWidth, out int count)
{
var glyphRun = textCharacters.GlyphRun;
if (glyphRun.Size.Width < availableWidth)
{
- return glyphRun.Characters.Length;
+ count = glyphRun.Characters.Length;
+
+ return true;
}
var glyphCount = 0;
@@ -96,21 +101,42 @@ namespace Avalonia.Media.TextFormatting
}
}
+ if (glyphCount == 0)
+ {
+ count = 0;
+
+ return false;
+ }
+
if (glyphCount == glyphRun.GlyphIndices.Length)
{
- return glyphRun.Characters.Length;
+ count = glyphRun.Characters.Length;
+
+ return true;
}
if (glyphRun.GlyphClusters.IsEmpty)
{
- return glyphCount;
+ count = glyphCount;
+
+ return true;
}
var firstCluster = glyphRun.GlyphClusters[0];
var lastCluster = glyphRun.GlyphClusters[glyphCount];
- return lastCluster - firstCluster;
+ if (glyphRun.IsLeftToRight)
+ {
+ count = lastCluster - firstCluster;
+ }
+ else
+ {
+ count = firstCluster - lastCluster;
+ }
+
+
+ return count > 0;
}
///
@@ -313,14 +339,6 @@ namespace Avalonia.Media.TextFormatting
return true;
}
- //The line breaker isn't treating \n\r as a pair so we have to fix that here.
- if (textRun.Text[lineBreak.PositionMeasure] == '\n'
- && textRun.Text[lineBreak.PositionWrap] == '\r')
- {
- lineBreak = new LineBreak(lineBreak.PositionMeasure, lineBreak.PositionWrap + 1,
- lineBreak.Required);
- }
-
return true;
}
@@ -350,29 +368,38 @@ namespace Avalonia.Media.TextFormatting
if (currentWidth + currentRun.Size.Width > availableWidth)
{
- var measuredLength = MeasureCharacters(currentRun, paragraphWidth - currentWidth);
-
var breakFound = false;
var currentBreakPosition = 0;
- if (measuredLength < currentRun.Text.Length)
+ if (TryMeasureCharacters(currentRun, paragraphWidth - currentWidth, out var measuredLength))
{
- var lineBreaker = new LineBreakEnumerator(currentRun.Text);
-
- while (currentBreakPosition < measuredLength && lineBreaker.MoveNext())
+ if (measuredLength < currentRun.Text.Length)
{
- var nextBreakPosition = lineBreaker.Current.PositionWrap;
+ var lineBreaker = new LineBreakEnumerator(currentRun.Text);
- if (nextBreakPosition == 0 || nextBreakPosition > measuredLength)
+ while (currentBreakPosition < measuredLength && lineBreaker.MoveNext())
{
- break;
- }
+ var nextBreakPosition = lineBreaker.Current.PositionWrap;
+
+ if (nextBreakPosition == 0 || nextBreakPosition > measuredLength)
+ {
+ break;
+ }
- breakFound = lineBreaker.Current.Required ||
- lineBreaker.Current.PositionWrap != currentRun.Text.Length;
+ breakFound = lineBreaker.Current.Required ||
+ lineBreaker.Current.PositionWrap != currentRun.Text.Length;
- currentBreakPosition = nextBreakPosition;
+ currentBreakPosition = nextBreakPosition;
+ }
+ }
+ }
+ else
+ {
+ // Make sure we wrap at least one character.
+ if (currentLength == 0)
+ {
+ measuredLength = 1;
}
}
diff --git a/src/Avalonia.Visuals/Media/TextFormatting/TextLineImpl.cs b/src/Avalonia.Visuals/Media/TextFormatting/TextLineImpl.cs
index f5e87d097b..fc98e9f6f8 100644
--- a/src/Avalonia.Visuals/Media/TextFormatting/TextLineImpl.cs
+++ b/src/Avalonia.Visuals/Media/TextFormatting/TextLineImpl.cs
@@ -39,7 +39,9 @@ namespace Avalonia.Media.TextFormatting
foreach (var textRun in _textRuns)
{
- using (drawingContext.PushPostTransform(Matrix.CreateTranslation(currentX, 0)))
+ var offsetY = LineMetrics.TextBaseline - textRun.GlyphRun.BaselineOrigin.Y;
+
+ using (drawingContext.PushPostTransform(Matrix.CreateTranslation(currentX, offsetY)))
{
textRun.Draw(drawingContext);
}
@@ -75,37 +77,35 @@ namespace Avalonia.Media.TextFormatting
if (currentWidth > availableWidth)
{
- var measuredLength = TextFormatterImpl.MeasureCharacters(currentRun, availableWidth);
-
- var currentBreakPosition = 0;
-
- if (measuredLength < textRange.End)
+ if (TextFormatterImpl.TryMeasureCharacters(currentRun, availableWidth, out var measuredLength))
{
- var lineBreaker = new LineBreakEnumerator(currentRun.Text);
-
- while (currentBreakPosition < measuredLength && lineBreaker.MoveNext())
+ if (collapsingProperties.Style == TextCollapsingStyle.TrailingWord && measuredLength < textRange.End)
{
- var nextBreakPosition = lineBreaker.Current.PositionWrap;
+ var currentBreakPosition = 0;
- if (nextBreakPosition == 0)
- {
- break;
- }
+ var lineBreaker = new LineBreakEnumerator(currentRun.Text);
- if (nextBreakPosition > measuredLength)
+ while (currentBreakPosition < measuredLength && lineBreaker.MoveNext())
{
- break;
+ var nextBreakPosition = lineBreaker.Current.PositionWrap;
+
+ if (nextBreakPosition == 0)
+ {
+ break;
+ }
+
+ if (nextBreakPosition > measuredLength)
+ {
+ break;
+ }
+
+ currentBreakPosition = nextBreakPosition;
}
- currentBreakPosition = nextBreakPosition;
+ measuredLength = currentBreakPosition;
}
}
- if (collapsingProperties.Style == TextCollapsingStyle.TrailingWord)
- {
- measuredLength = currentBreakPosition;
- }
-
collapsedLength += measuredLength;
var splitResult = TextFormatterImpl.SplitTextRuns(_textRuns, collapsedLength);
diff --git a/src/Avalonia.Visuals/Platform/IDrawingContextImpl.cs b/src/Avalonia.Visuals/Platform/IDrawingContextImpl.cs
index 019614ae80..d6e88a7507 100644
--- a/src/Avalonia.Visuals/Platform/IDrawingContextImpl.cs
+++ b/src/Avalonia.Visuals/Platform/IDrawingContextImpl.cs
@@ -69,7 +69,7 @@ namespace Avalonia.Platform
/// If the pen is null, then no stoke is performed. If both the pen and the brush are null, then the drawing is not visible.
///
void DrawRectangle(IBrush brush, IPen pen, RoundedRect rect,
- BoxShadows boxShadow = default);
+ BoxShadows boxShadows = default);
///
/// Draws text.
@@ -98,7 +98,7 @@ namespace Avalonia.Platform
/// has to do a format conversion each time a standard render target bitmap is rendered,
/// but a layer created via this method has no such overhead.
///
- IRenderTargetBitmapImpl CreateLayer(Size size);
+ IDrawingContextLayerImpl CreateLayer(Size size);
///
/// Pushes a clip rectangle.
@@ -155,4 +155,18 @@ namespace Avalonia.Platform
/// Custom draw operation
void Custom(ICustomDrawOperation custom);
}
+
+ public interface IDrawingContextLayerImpl : IRenderTargetBitmapImpl
+ {
+ ///
+ /// Does optimized blit with Src blend mode
+ ///
+ ///
+ void Blit(IDrawingContextImpl context);
+
+ ///
+ /// Returns true if layer supports optimized blit
+ ///
+ bool CanBlit { get; }
+ }
}
diff --git a/src/Avalonia.Visuals/Point.cs b/src/Avalonia.Visuals/Point.cs
index 7324f5fbd0..6febe9c802 100644
--- a/src/Avalonia.Visuals/Point.cs
+++ b/src/Avalonia.Visuals/Point.cs
@@ -1,6 +1,8 @@
using System;
using System.Globalization;
+#if !BUILDTASK
using Avalonia.Animation.Animators;
+#endif
using Avalonia.Utilities;
namespace Avalonia
@@ -8,11 +10,16 @@ namespace Avalonia
///
/// Defines a point.
///
- public readonly struct Point : IEquatable
+#if !BUILDTASK
+ public
+#endif
+ readonly struct Point : IEquatable
{
static Point()
{
+#if !BUILDTASK
Animation.Animation.RegisterAnimator(prop => typeof(Point).IsAssignableFrom(prop.PropertyType));
+#endif
}
///
diff --git a/src/Avalonia.Visuals/Properties/AssemblyInfo.cs b/src/Avalonia.Visuals/Properties/AssemblyInfo.cs
index 5d802c27b9..48107a31f8 100644
--- a/src/Avalonia.Visuals/Properties/AssemblyInfo.cs
+++ b/src/Avalonia.Visuals/Properties/AssemblyInfo.cs
@@ -2,13 +2,20 @@ using System.Reflection;
using System.Runtime.CompilerServices;
using Avalonia.Metadata;
-[assembly: InternalsVisibleTo("Avalonia.Visuals.UnitTests")]
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Animation")]
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Media")]
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Media.Imaging")]
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Media.Transformation")]
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia")]
+#if SIGNED_BUILD
+[assembly: InternalsVisibleTo("Avalonia.Visuals.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")]
+[assembly: InternalsVisibleTo("Avalonia.Direct2D1.RenderTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")]
+[assembly: InternalsVisibleTo("Avalonia.Skia.RenderTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")]
+[assembly: InternalsVisibleTo("Avalonia.Skia.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")]
+#else
+[assembly: InternalsVisibleTo("Avalonia.Visuals.UnitTests")]
[assembly: InternalsVisibleTo("Avalonia.Direct2D1.RenderTests")]
[assembly: InternalsVisibleTo("Avalonia.Skia.RenderTests")]
[assembly: InternalsVisibleTo("Avalonia.Skia.UnitTests")]
+#endif
diff --git a/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs b/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs
index 8c020fc073..3bd8e05ee2 100644
--- a/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs
+++ b/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs
@@ -99,6 +99,11 @@ namespace Avalonia.Rendering
///
public string DebugFramesPath { get; set; }
+ ///
+ /// Forces the renderer to only draw frames on the render thread. Makes Paint to wait until frame is rendered
+ ///
+ public bool RenderOnlyOnRenderThread { get; set; }
+
///
public event EventHandler SceneInvalidated;
@@ -180,11 +185,44 @@ namespace Avalonia.Rendering
///
public void Paint(Rect rect)
{
- var t = (IRenderLoopTask)this;
- if(t.NeedsUpdate)
- UpdateScene();
- if(_scene?.Item != null)
- Render(true);
+ if (RenderOnlyOnRenderThread)
+ {
+ // Renderer is stopped and doesn't tick on the render thread
+ // This indicates a bug somewhere in our code
+ // (currently happens when a window gets minimized with Show desktop on Windows 10)
+ if(!_running)
+ return;
+
+ while (true)
+ {
+ Scene scene;
+ bool? updated;
+ lock (_sceneLock)
+ {
+ updated = UpdateScene();
+ scene = _scene?.Item;
+ }
+
+ // Renderer is in invalid state, skip drawing
+ if(updated == null)
+ return;
+
+ // Wait for the scene to be rendered or disposed
+ scene?.Rendered.Wait();
+
+ // That was an up-to-date scene, we can return immediately
+ if (updated == true)
+ return;
+ }
+ }
+ else
+ {
+ var t = (IRenderLoopTask)this;
+ if (t.NeedsUpdate)
+ UpdateScene();
+ if (_scene?.Item != null)
+ Render(true);
+ }
}
///
@@ -270,13 +308,20 @@ namespace Avalonia.Rendering
{
if (scene?.Item != null)
{
- var overlay = DrawDirtyRects || DrawFps;
- if (DrawDirtyRects)
- _dirtyRectsDisplay.Tick();
- if (overlay)
- RenderOverlay(scene.Item, ref context);
- if (updated || forceComposite || overlay)
- RenderComposite(scene.Item, ref context);
+ try
+ {
+ var overlay = DrawDirtyRects || DrawFps;
+ if (DrawDirtyRects)
+ _dirtyRectsDisplay.Tick();
+ if (overlay)
+ RenderOverlay(scene.Item, ref context);
+ if (updated || forceComposite || overlay)
+ RenderComposite(scene.Item, ref context);
+ }
+ finally
+ {
+ scene.Item.MarkAsRendered();
+ }
}
}
}
@@ -489,6 +534,7 @@ namespace Avalonia.Rendering
var clientRect = new Rect(scene.Size);
+ var firstLayer = true;
foreach (var layer in scene.Layers)
{
var bitmap = Layers[layer.LayerRoot].Bitmap;
@@ -501,7 +547,10 @@ namespace Avalonia.Rendering
if (layer.OpacityMask == null)
{
- context.DrawBitmap(bitmap, layer.Opacity, sourceRect, clientRect);
+ if (firstLayer && bitmap.Item.CanBlit)
+ bitmap.Item.Blit(context);
+ else
+ context.DrawBitmap(bitmap, layer.Opacity, sourceRect, clientRect);
}
else
{
@@ -512,6 +561,8 @@ namespace Avalonia.Rendering
{
context.PopGeometryClip();
}
+
+ firstLayer = false;
}
if (_overlay != null)
@@ -553,15 +604,16 @@ namespace Avalonia.Rendering
UpdateScene();
}
- private void UpdateScene()
+ private bool? UpdateScene()
{
Dispatcher.UIThread.VerifyAccess();
+ using var noPump = NonPumpingLockHelper.Use();
lock (_sceneLock)
{
if (_disposed)
- return;
+ return null;
if (_scene?.Item.Generation > _lastSceneId)
- return;
+ return false;
}
if (_root.IsVisible)
{
@@ -613,6 +665,8 @@ namespace Avalonia.Rendering
SceneInvalidated(this, new SceneInvalidatedEventArgs((IRenderRoot)_root, rect));
}
+
+ return true;
}
else
{
@@ -622,6 +676,8 @@ namespace Avalonia.Rendering
_scene = null;
oldScene?.Dispose();
}
+
+ return null;
}
}
diff --git a/src/Avalonia.Visuals/Rendering/RenderLayer.cs b/src/Avalonia.Visuals/Rendering/RenderLayer.cs
index ddf5f4e5cf..768e832fe5 100644
--- a/src/Avalonia.Visuals/Rendering/RenderLayer.cs
+++ b/src/Avalonia.Visuals/Rendering/RenderLayer.cs
@@ -20,7 +20,7 @@ namespace Avalonia.Rendering
IsEmpty = true;
}
- public IRef Bitmap { get; private set; }
+ public IRef Bitmap { get; private set; }
public bool IsEmpty { get; set; }
public double Scaling { get; private set; }
public Size Size { get; private set; }
@@ -30,12 +30,12 @@ namespace Avalonia.Rendering
{
if (Size != size || Scaling != scaling)
{
- Bitmap.Dispose();
var resized = RefCountable.Create(drawingContext.CreateLayer(size));
using (var context = resized.Item.CreateDrawingContext(null))
{
- context.Clear(Colors.Transparent);
+ Bitmap.Dispose();
+ context.Clear(default);
Bitmap = resized;
Scaling = scaling;
diff --git a/src/Avalonia.Visuals/Rendering/SceneGraph/DeferredDrawingContextImpl.cs b/src/Avalonia.Visuals/Rendering/SceneGraph/DeferredDrawingContextImpl.cs
index cb6b1f59d4..28f426266d 100644
--- a/src/Avalonia.Visuals/Rendering/SceneGraph/DeferredDrawingContextImpl.cs
+++ b/src/Avalonia.Visuals/Rendering/SceneGraph/DeferredDrawingContextImpl.cs
@@ -218,7 +218,7 @@ namespace Avalonia.Rendering.SceneGraph
++_drawOperationindex;
}
}
- public IRenderTargetBitmapImpl CreateLayer(Size size)
+ public IDrawingContextLayerImpl CreateLayer(Size size)
{
throw new NotSupportedException("Creating layers on a deferred drawing context not supported");
}
diff --git a/src/Avalonia.Visuals/Rendering/SceneGraph/ExperimentalAcrylicNode.cs b/src/Avalonia.Visuals/Rendering/SceneGraph/ExperimentalAcrylicNode.cs
index 336d11e3fd..8bd079d070 100644
--- a/src/Avalonia.Visuals/Rendering/SceneGraph/ExperimentalAcrylicNode.cs
+++ b/src/Avalonia.Visuals/Rendering/SceneGraph/ExperimentalAcrylicNode.cs
@@ -13,10 +13,9 @@ namespace Avalonia.Rendering.SceneGraph
///
/// Initializes a new instance of the class.
///
- /// The transform.
+ /// The transform.
+ ///
/// The rectangle to draw.
- /// The box shadow parameters
- /// Child scenes for drawing visual brushes.
public ExperimentalAcrylicNode(
Matrix transform,
IExperimentalAcrylicMaterial material,
@@ -44,7 +43,7 @@ namespace Avalonia.Rendering.SceneGraph
/// Determines if this draw operation equals another.
///
/// The transform of the other draw operation.
- /// The fill of the other draw operation.
+ /// The fill of the other draw operation.
/// The rectangle of the other draw operation.
/// True if the draw operations are the same, otherwise false.
///
diff --git a/src/Avalonia.Visuals/Rendering/SceneGraph/GeometryNode.cs b/src/Avalonia.Visuals/Rendering/SceneGraph/GeometryNode.cs
index 8a19679c77..508ca0ad18 100644
--- a/src/Avalonia.Visuals/Rendering/SceneGraph/GeometryNode.cs
+++ b/src/Avalonia.Visuals/Rendering/SceneGraph/GeometryNode.cs
@@ -63,7 +63,6 @@ namespace Avalonia.Rendering.SceneGraph
/// The fill of the other draw operation.
/// The stroke of the other draw operation.
/// The geometry of the other draw operation.
- /// The box shadow parameters
/// True if the draw operations are the same, otherwise false.
///
/// The properties of the other draw operation are passed in as arguments to prevent
diff --git a/src/Avalonia.Visuals/Rendering/SceneGraph/RectangleNode.cs b/src/Avalonia.Visuals/Rendering/SceneGraph/RectangleNode.cs
index ec1a7753b1..d0c4566485 100644
--- a/src/Avalonia.Visuals/Rendering/SceneGraph/RectangleNode.cs
+++ b/src/Avalonia.Visuals/Rendering/SceneGraph/RectangleNode.cs
@@ -73,7 +73,7 @@ namespace Avalonia.Rendering.SceneGraph
/// The fill of the other draw operation.
/// The stroke of the other draw operation.
/// The rectangle of the other draw operation.
- /// The box shadow parameters of the other draw operation
+ /// The box shadow parameters of the other draw operation
/// True if the draw operations are the same, otherwise false.
///
/// The properties of the other draw operation are passed in as arguments to prevent
diff --git a/src/Avalonia.Visuals/Rendering/SceneGraph/Scene.cs b/src/Avalonia.Visuals/Rendering/SceneGraph/Scene.cs
index 4f5c97cdff..6a4c532d4a 100644
--- a/src/Avalonia.Visuals/Rendering/SceneGraph/Scene.cs
+++ b/src/Avalonia.Visuals/Rendering/SceneGraph/Scene.cs
@@ -2,6 +2,7 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
+using System.Threading.Tasks;
using Avalonia.Collections.Pooled;
using Avalonia.VisualTree;
@@ -13,6 +14,7 @@ namespace Avalonia.Rendering.SceneGraph
public class Scene : IDisposable
{
private readonly Dictionary _index;
+ private readonly TaskCompletionSource _rendered = new TaskCompletionSource();
///
/// Initializes a new instance of the class.
@@ -41,6 +43,8 @@ namespace Avalonia.Rendering.SceneGraph
root.LayerRoot = root.Visual;
}
+ public Task Rendered => _rendered.Task;
+
///
/// Gets a value identifying the scene's generation. This is incremented each time the scene is cloned.
///
@@ -97,6 +101,7 @@ namespace Avalonia.Rendering.SceneGraph
public void Dispose()
{
+ _rendered.TrySetResult(false);
foreach (var node in _index.Values)
{
node.Dispose();
@@ -340,5 +345,7 @@ namespace Avalonia.Rendering.SceneGraph
}
}
}
+
+ public void MarkAsRendered() => _rendered.TrySetResult(true);
}
}
diff --git a/src/Avalonia.Visuals/Rendering/SceneGraph/SceneBuilder.cs b/src/Avalonia.Visuals/Rendering/SceneGraph/SceneBuilder.cs
index 872f69c884..7d5d62a091 100644
--- a/src/Avalonia.Visuals/Rendering/SceneGraph/SceneBuilder.cs
+++ b/src/Avalonia.Visuals/Rendering/SceneGraph/SceneBuilder.cs
@@ -24,7 +24,8 @@ namespace Avalonia.Rendering.SceneGraph
using (var impl = new DeferredDrawingContextImpl(this, scene.Layers))
using (var context = new DrawingContext(impl))
{
- Update(context, scene, (VisualNode)scene.Root, scene.Root.Visual.Bounds, true);
+ var clip = new Rect(scene.Root.Visual.Bounds.Size);
+ Update(context, scene, (VisualNode)scene.Root, clip, true);
}
}
@@ -77,7 +78,7 @@ namespace Avalonia.Rendering.SceneGraph
using (var impl = new DeferredDrawingContextImpl(this, scene.Layers))
using (var context = new DrawingContext(impl))
{
- var clip = scene.Root.Visual.Bounds;
+ var clip = new Rect(scene.Root.Visual.Bounds.Size);
if (node.Parent != null)
{
@@ -174,7 +175,9 @@ namespace Avalonia.Rendering.SceneGraph
if (visual.IsVisible)
{
- var m = Matrix.CreateTranslation(visual.Bounds.Position);
+ var m = node != scene.Root ?
+ Matrix.CreateTranslation(visual.Bounds.Position) :
+ Matrix.Identity;
var renderTransform = Matrix.Identity;
diff --git a/src/Avalonia.Visuals/Size.cs b/src/Avalonia.Visuals/Size.cs
index d87d2c5fc2..8a805dc6c5 100644
--- a/src/Avalonia.Visuals/Size.cs
+++ b/src/Avalonia.Visuals/Size.cs
@@ -1,6 +1,8 @@
using System;
using System.Globalization;
+#if !BUILDTASK
using Avalonia.Animation.Animators;
+#endif
using Avalonia.Utilities;
namespace Avalonia
@@ -8,11 +10,16 @@ namespace Avalonia
///
/// Defines a size.
///
- public readonly struct Size : IEquatable
+#if !BUILDTASK
+ public
+#endif
+ readonly struct Size : IEquatable
{
static Size()
{
+#if !BUILDTASK
Animation.Animation.RegisterAnimator(prop => typeof(Size).IsAssignableFrom(prop.PropertyType));
+#endif
}
///
diff --git a/src/Avalonia.Visuals/Thickness.cs b/src/Avalonia.Visuals/Thickness.cs
index 6d69c4d9a9..06ebc9bfe7 100644
--- a/src/Avalonia.Visuals/Thickness.cs
+++ b/src/Avalonia.Visuals/Thickness.cs
@@ -1,6 +1,8 @@
using System;
using System.Globalization;
+#if !BUILDTASK
using Avalonia.Animation.Animators;
+#endif
using Avalonia.Utilities;
namespace Avalonia
@@ -8,11 +10,16 @@ namespace Avalonia
///
/// Describes the thickness of a frame around a rectangle.
///
- public readonly struct Thickness : IEquatable
+#if !BUILDTASK
+ public
+#endif
+ readonly struct Thickness : IEquatable
{
static Thickness()
{
+#if !BUILDTASK
Animation.Animation.RegisterAnimator(prop => typeof(Thickness).IsAssignableFrom(prop.PropertyType));
+#endif
}
///
diff --git a/src/Avalonia.Visuals/Vector.cs b/src/Avalonia.Visuals/Vector.cs
index 2fcf804f14..1b9f5c67d5 100644
--- a/src/Avalonia.Visuals/Vector.cs
+++ b/src/Avalonia.Visuals/Vector.cs
@@ -1,6 +1,8 @@
using System;
using System.Globalization;
+#if !BUILDTASK
using Avalonia.Animation.Animators;
+#endif
using Avalonia.Utilities;
#nullable enable
@@ -10,11 +12,16 @@ namespace Avalonia
///
/// Defines a vector.
///
- public readonly struct Vector : IEquatable
+#if !BUILDTASK
+ public
+#endif
+ readonly struct Vector : IEquatable
{
static Vector()
{
+#if !BUILDTASK
Animation.Animation.RegisterAnimator(prop => typeof(Vector).IsAssignableFrom(prop.PropertyType));
+#endif
}
///
diff --git a/src/Avalonia.Visuals/Visual.cs b/src/Avalonia.Visuals/Visual.cs
index 283d9deb52..9327531b46 100644
--- a/src/Avalonia.Visuals/Visual.cs
+++ b/src/Avalonia.Visuals/Visual.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections;
using System.Collections.Specialized;
using Avalonia.Collections;
using Avalonia.Data;
@@ -484,7 +485,7 @@ namespace Avalonia
BindingPriority.LocalValue);
}
- protected override sealed void LogBindingError(AvaloniaProperty property, Exception e)
+ protected internal sealed override void LogBindingError(AvaloniaProperty property, Exception e)
{
// Don't log a binding error unless the control is attached to a logical or visual tree.
// In theory this should only need to check for logical tree attachment, but in practise
@@ -619,34 +620,30 @@ namespace Avalonia
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
- foreach (Visual v in e.NewItems)
- {
- v.SetVisualParent(this);
- }
-
+ SetVisualParent(e.NewItems, this);
break;
case NotifyCollectionChangedAction.Remove:
- foreach (Visual v in e.OldItems)
- {
- v.SetVisualParent(null);
- }
-
+ SetVisualParent(e.OldItems, null);
break;
case NotifyCollectionChangedAction.Replace:
- foreach (Visual v in e.OldItems)
- {
- v.SetVisualParent(null);
- }
-
- foreach (Visual v in e.NewItems)
- {
- v.SetVisualParent(this);
- }
-
+ SetVisualParent(e.OldItems, null);
+ SetVisualParent(e.NewItems, this);
break;
}
}
+
+ private static void SetVisualParent(IList children, Visual parent)
+ {
+ var count = children.Count;
+
+ for (var i = 0; i < count; i++)
+ {
+ var visual = (Visual) children[i];
+
+ visual.SetVisualParent(parent);
+ }
+ }
}
}
diff --git a/src/Avalonia.Visuals/VisualExtensions.cs b/src/Avalonia.Visuals/VisualExtensions.cs
index 6079e5941f..e6523a1469 100644
--- a/src/Avalonia.Visuals/VisualExtensions.cs
+++ b/src/Avalonia.Visuals/VisualExtensions.cs
@@ -50,7 +50,13 @@ namespace Avalonia
{
var thisOffset = GetOffsetFrom(common, from);
var thatOffset = GetOffsetFrom(common, to);
- return -thatOffset * thisOffset;
+
+ if (!thatOffset.TryInvert(out var thatOffsetInverted))
+ {
+ return null;
+ }
+
+ return thatOffsetInverted * thisOffset;
}
return null;
diff --git a/src/Avalonia.X11/X11Window.cs b/src/Avalonia.X11/X11Window.cs
index 2cd3b973d8..b061920d6a 100644
--- a/src/Avalonia.X11/X11Window.cs
+++ b/src/Avalonia.X11/X11Window.cs
@@ -189,6 +189,11 @@ namespace Avalonia.X11
if (platform.Options.UseDBusMenu)
NativeMenuExporter = DBusMenuExporter.TryCreate(_handle);
NativeControlHost = new X11NativeControlHost(_platform, this);
+ DispatcherTimer.Run(() =>
+ {
+ Paint?.Invoke(default);
+ return _handle != IntPtr.Zero;
+ }, TimeSpan.FromMilliseconds(100));
}
class SurfaceInfo : EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo
@@ -338,7 +343,10 @@ namespace Avalonia.X11
return customRendererFactory.Create(root, loop);
return _platform.Options.UseDeferredRendering ?
- new DeferredRenderer(root, loop) :
+ new DeferredRenderer(root, loop)
+ {
+ RenderOnlyOnRenderThread = true
+ } :
(IRenderer)new X11ImmediateRendererProxy(root, loop);
}
@@ -815,7 +823,7 @@ namespace Avalonia.X11
XSetTransientForHint(_x11.Display, _handle, parent.Handle.Handle);
}
- public void Show()
+ public void Show(bool activate)
{
_wasMappedAtLeastOnce = true;
XMapWindow(_x11.Display, _handle);
diff --git a/src/Avalonia.X11/XI2Manager.cs b/src/Avalonia.X11/XI2Manager.cs
index 742973e0da..8cdf24cc7b 100644
--- a/src/Avalonia.X11/XI2Manager.cs
+++ b/src/Avalonia.X11/XI2Manager.cs
@@ -13,7 +13,10 @@ namespace Avalonia.X11
{
XiEventType.XI_Motion,
XiEventType.XI_ButtonPress,
- XiEventType.XI_ButtonRelease
+ XiEventType.XI_ButtonRelease,
+ XiEventType.XI_Leave,
+ XiEventType.XI_Enter,
+
};
private static readonly XiEventType[] MultiTouchEventTypes = new XiEventType[]
@@ -162,7 +165,9 @@ namespace Avalonia.X11
| XEventMask.Button4MotionMask
| XEventMask.Button5MotionMask
| XEventMask.ButtonPressMask
- | XEventMask.ButtonReleaseMask;
+ | XEventMask.ButtonReleaseMask
+ | XEventMask.LeaveWindowMask
+ | XEventMask.EnterWindowMask;
}
public void OnWindowDestroyed(IntPtr xid) => _clients.Remove(xid);
@@ -175,14 +180,39 @@ namespace Avalonia.X11
_pointerDevice.Update(changed->Classes, changed->NumClasses);
}
-
+
if ((xev->evtype >= XiEventType.XI_ButtonPress && xev->evtype <= XiEventType.XI_Motion)
- || (xev->evtype>=XiEventType.XI_TouchBegin&&xev->evtype<=XiEventType.XI_TouchEnd))
+ || (xev->evtype >= XiEventType.XI_TouchBegin && xev->evtype <= XiEventType.XI_TouchEnd))
{
var dev = (XIDeviceEvent*)xev;
if (_clients.TryGetValue(dev->EventWindow, out var client))
OnDeviceEvent(client, new ParsedDeviceEvent(dev));
}
+
+ if (xev->evtype == XiEventType.XI_Leave || xev->evtype == XiEventType.XI_Enter)
+ {
+ var rev = (XIEnterLeaveEvent*)xev;
+ if (_clients.TryGetValue(rev->EventWindow, out var client))
+ OnEnterLeaveEvent(client, ref *rev);
+ }
+ }
+
+ void OnEnterLeaveEvent(IXI2Client client, ref XIEnterLeaveEvent ev)
+ {
+ if (ev.evtype == XiEventType.XI_Leave)
+ {
+ var buttons = ParsedDeviceEvent.ParseButtonState(ev.buttons.MaskLen, ev.buttons.Mask);
+ var detail = ev.detail;
+ if ((detail == XiEnterLeaveDetail.XINotifyNonlinearVirtual ||
+ detail == XiEnterLeaveDetail.XINotifyNonlinear ||
+ detail == XiEnterLeaveDetail.XINotifyVirtual)
+ && buttons == default)
+ {
+ client.ScheduleXI2Input(new RawPointerEventArgs(client.MouseDevice, (ulong)ev.time.ToInt64(),
+ client.InputRoot,
+ RawPointerEventType.LeaveWindow, new Point(ev.event_x, ev.event_y), buttons));
+ }
+ }
}
void OnDeviceEvent(IXI2Client client, ParsedDeviceEvent ev)
@@ -284,6 +314,29 @@ namespace Avalonia.X11
public int Detail { get; set; }
public bool Emulated { get; set; }
public Dictionary Valuators { get; }
+
+ public static RawInputModifiers ParseButtonState(int len, byte* buttons)
+ {
+ RawInputModifiers rv = default;
+ if (len > 0)
+ {
+ if (XIMaskIsSet(buttons, 1))
+ rv |= RawInputModifiers.LeftMouseButton;
+ if (XIMaskIsSet(buttons, 2))
+ rv |= RawInputModifiers.MiddleMouseButton;
+ if (XIMaskIsSet(buttons, 3))
+ rv |= RawInputModifiers.RightMouseButton;
+ if (len > 1)
+ {
+ if (XIMaskIsSet(buttons, 8))
+ rv |= RawInputModifiers.XButton1MouseButton;
+ if (XIMaskIsSet(buttons, 9))
+ rv |= RawInputModifiers.XButton2MouseButton;
+ }
+ }
+ return rv;
+ }
+
public ParsedDeviceEvent(XIDeviceEvent* ev)
{
Type = ev->evtype;
@@ -298,27 +351,16 @@ namespace Avalonia.X11
if (state.HasFlag(XModifierMask.Mod4Mask))
Modifiers |= RawInputModifiers.Meta;
- if (ev->buttons.MaskLen > 0)
- {
- var buttons = ev->buttons.Mask;
- if (XIMaskIsSet(buttons, 1))
- Modifiers |= RawInputModifiers.LeftMouseButton;
- if (XIMaskIsSet(buttons, 2))
- Modifiers |= RawInputModifiers.MiddleMouseButton;
- if (XIMaskIsSet(buttons, 3))
- Modifiers |= RawInputModifiers.RightMouseButton;
- if (XIMaskIsSet(buttons, 8))
- Modifiers |= RawInputModifiers.XButton1MouseButton;
- if (XIMaskIsSet(buttons, 9))
- Modifiers |= RawInputModifiers.XButton2MouseButton;
- }
+ Modifiers |= ParseButtonState(ev->buttons.MaskLen, ev->buttons.Mask);
Valuators = new Dictionary();
Position = new Point(ev->event_x, ev->event_y);
var values = ev->valuators.Values;
- for (var c = 0; c < ev->valuators.MaskLen * 8; c++)
- if (XIMaskIsSet(ev->valuators.Mask, c))
- Valuators[c] = *values++;
+ if(ev->valuators.Mask != null)
+ for (var c = 0; c < ev->valuators.MaskLen * 8; c++)
+ if (XIMaskIsSet(ev->valuators.Mask, c))
+ Valuators[c] = *values++;
+
if (Type == XiEventType.XI_ButtonPress || Type == XiEventType.XI_ButtonRelease)
Button = ev->detail;
Detail = ev->detail;
diff --git a/src/Avalonia.X11/XIStructs.cs b/src/Avalonia.X11/XIStructs.cs
index 4675ef47f2..f4581a99ba 100644
--- a/src/Avalonia.X11/XIStructs.cs
+++ b/src/Avalonia.X11/XIStructs.cs
@@ -236,6 +236,34 @@ namespace Avalonia.X11
public XIModifierState mods;
public XIModifierState group;
}
+
+ [StructLayout(LayoutKind.Sequential)]
+ unsafe struct XIEnterLeaveEvent
+ {
+ public XEventName type; /* GenericEvent */
+ public UIntPtr serial; /* # of last request processed by server */
+ public Bool send_event; /* true if this came from a SendEvent request */
+ public IntPtr display; /* Display the event was read from */
+ public int extension; /* XI extension offset */
+ public XiEventType evtype;
+ public IntPtr time;
+ public int deviceid;
+ public int sourceid;
+ public XiEnterLeaveDetail detail;
+ public IntPtr RootWindow;
+ public IntPtr EventWindow;
+ public IntPtr ChildWindow;
+ public double root_x;
+ public double root_y;
+ public double event_x;
+ public double event_y;
+ public int mode;
+ public int focus;
+ public int same_screen;
+ public XIButtonState buttons;
+ public XIModifierState mods;
+ public XIModifierState group;
+ }
[Flags]
public enum XiDeviceEventFlags : int
@@ -286,5 +314,18 @@ namespace Avalonia.X11
XI_BarrierLeave = 26,
XI_LASTEVENT = XI_BarrierLeave,
}
-
+
+ enum XiEnterLeaveDetail
+ {
+ XINotifyAncestor = 0,
+ XINotifyVirtual = 1,
+ XINotifyInferior = 2,
+ XINotifyNonlinear = 3,
+ XINotifyNonlinearVirtual = 4,
+ XINotifyPointer = 5,
+ XINotifyPointerRoot = 6,
+ XINotifyDetailNone = 7
+
+ }
+
}
diff --git a/src/Linux/Avalonia.LinuxFramebuffer/Output/Drm.cs b/src/Linux/Avalonia.LinuxFramebuffer/Output/Drm.cs
index 787a2e4cb8..9c476b1b63 100644
--- a/src/Linux/Avalonia.LinuxFramebuffer/Output/Drm.cs
+++ b/src/Linux/Avalonia.LinuxFramebuffer/Output/Drm.cs
@@ -113,22 +113,22 @@ namespace Avalonia.LinuxFramebuffer.Output
[StructLayout(LayoutKind.Sequential)]
public struct drmModeConnector {
public uint connector_id;
- public uint encoder_id; /**< Encoder currently connected to */
+ public uint encoder_id; // Encoder currently connected to
public uint connector_type;
public uint connector_type_id;
public DrmModeConnection connection;
- public uint mmWidth, mmHeight; /**< HxW in millimeters */
+ public uint mmWidth, mmHeight; // HxW in millimeters
public DrmModeSubPixel subpixel;
public int count_modes;
public drmModeModeInfo* modes;
public int count_props;
- public uint *props; /**< List of property ids */
- public ulong *prop_values; /**< List of property values */
+ public uint *props; // List of property ids
+ public ulong *prop_values; // List of property values
public int count_encoders;
- public uint *encoders; /**< List of encoder ids */
+ public uint *encoders; //List of encoder ids
}
[StructLayout(LayoutKind.Sequential)]
@@ -143,14 +143,14 @@ namespace Avalonia.LinuxFramebuffer.Output
[StructLayout(LayoutKind.Sequential)]
public struct drmModeCrtc {
public uint crtc_id;
- public uint buffer_id; /**< FB id to connect to 0 = disconnect */
+ public uint buffer_id; // FB id to connect to 0 = disconnect
- public uint x, y; /**< Position on the framebuffer */
+ public uint x, y; // Position on the framebuffer
public uint width, height;
public int mode_valid;
public drmModeModeInfo mode;
- public int gamma_size; /**< Number of gamma stops */
+ public int gamma_size; // Number of gamma stops
}
diff --git a/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmOutput.cs b/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmOutput.cs
index 72eed9e543..dc44d2d55f 100644
--- a/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmOutput.cs
+++ b/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmOutput.cs
@@ -141,17 +141,7 @@ namespace Avalonia.LinuxFramebuffer.Output
_platformGl = new EglPlatformOpenGlInterface(_eglDisplay);
_eglSurface = _platformGl.CreateWindowSurface(_gbmTargetSurface);
-
- EglContext CreateContext(EglContext share)
- {
- var offSurf = gbm_surface_create(device, 1, 1, GbmColorFormats.GBM_FORMAT_XRGB8888,
- GbmBoFlags.GBM_BO_USE_RENDERING);
- if (offSurf == null)
- throw new InvalidOperationException("Unable to create 1x1 sized GBM surface");
- return _eglDisplay.CreateContext(share, _platformGl.CreateWindowSurface(offSurf));
- }
-
- _deferredContext = CreateContext(null);
+ _deferredContext = _platformGl.PrimaryEglContext;
using (_deferredContext.MakeCurrent(_eglSurface))
{
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/Avalonia.Markup.Xaml.Loader.csproj b/src/Markup/Avalonia.Markup.Xaml.Loader/Avalonia.Markup.Xaml.Loader.csproj
index 514556d0b9..db9c414840 100644
--- a/src/Markup/Avalonia.Markup.Xaml.Loader/Avalonia.Markup.Xaml.Loader.csproj
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/Avalonia.Markup.Xaml.Loader.csproj
@@ -4,6 +4,7 @@
netstandard2.0
true
Avalonia.Markup.Xaml.Loader
+ $(DefineConstants);XAMLX_INTERNAL
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/AvaloniaRuntimeXamlLoader.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/AvaloniaRuntimeXamlLoader.cs
index 4569970d01..4df07bcdd8 100644
--- a/src/Markup/Avalonia.Markup.Xaml.Loader/AvaloniaRuntimeXamlLoader.cs
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/AvaloniaRuntimeXamlLoader.cs
@@ -3,7 +3,6 @@ using System.IO;
using System.Reflection;
using System.Text;
using Avalonia.Markup.Xaml.XamlIl;
-// ReSharper disable CheckNamespace
namespace Avalonia.Markup.Xaml
{
@@ -13,10 +12,10 @@ namespace Avalonia.Markup.Xaml
/// Loads XAML from a string.
///
/// The string containing the XAML.
- /// Default assembly for clr-namespace:
- ///
- /// The optional instance into which the XAML should be loaded.
- ///
+ /// Default assembly for clr-namespace:.
+ /// The optional instance into which the XAML should be loaded.
+ /// The URI of the XAML being loaded.
+ /// Indicates whether the XAML is being loaded in design mode.
/// The loaded object.
public static object Load(string xaml, Assembly localAssembly = null, object rootInstance = null, Uri uri = null, bool designMode = false)
{
@@ -28,13 +27,35 @@ namespace Avalonia.Markup.Xaml
}
}
+ ///
+ /// Loads XAML from a stream.
+ ///
+ /// The stream containing the XAML.
+ /// Default assembly for clr-namespace:
+ /// The optional instance into which the XAML should be loaded.
+ /// The URI of the XAML being loaded.
+ /// Indicates whether the XAML is being loaded in design mode.
+ /// The loaded object.
public static object Load(Stream stream, Assembly localAssembly, object rootInstance = null, Uri uri = null,
bool designMode = false)
=> AvaloniaXamlIlRuntimeCompiler.Load(stream, localAssembly, rootInstance, uri, designMode);
+ ///
+ /// Parse XAML from a string.
+ ///
+ /// The string containing the XAML.
+ /// Default assembly for clr-namespace:.
+ /// The loaded object.
public static object Parse(string xaml, Assembly localAssembly = null)
=> Load(xaml, localAssembly);
+ ///
+ /// Parse XAML from a string.
+ ///
+ /// The type of the returned object.
+ /// >The string containing the XAML.
+ /// >Default assembly for clr-namespace:.
+ /// The loaded object.
public static T Parse(string xaml, Assembly localAssembly = null)
=> (T)Parse(xaml, localAssembly);
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/AvaloniaXamlIlRuntimeCompiler.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/AvaloniaXamlIlRuntimeCompiler.cs
index d9b4cd70da..ece90762cb 100644
--- a/src/Markup/Avalonia.Markup.Xaml.Loader/AvaloniaXamlIlRuntimeCompiler.cs
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/AvaloniaXamlIlRuntimeCompiler.cs
@@ -26,6 +26,7 @@ namespace Avalonia.Markup.Xaml.XamlIl
{
#if !RUNTIME_XAML_CECIL
private static SreTypeSystem _sreTypeSystem;
+ private static Type _ignoresAccessChecksFromAttribute;
private static ModuleBuilder _sreBuilder;
private static IXamlType _sreContextType;
private static XamlLanguageTypeMappings _sreMappings;
@@ -94,8 +95,60 @@ namespace Avalonia.Markup.Xaml.XamlIl
_sreTypeSystem.CreateTypeBuilder(
_sreBuilder.DefineType("XamlIlContext")), _sreTypeSystem, _sreMappings,
_sreEmitMappings);
+ if (_ignoresAccessChecksFromAttribute == null)
+ _ignoresAccessChecksFromAttribute = EmitIgnoresAccessCheckAttributeDefinition(_sreBuilder);
}
+ static Type EmitIgnoresAccessCheckAttributeDefinition(ModuleBuilder builder)
+ {
+ var tb = builder.DefineType("System.Runtime.CompilerServices.IgnoresAccessChecksToAttribute",
+ TypeAttributes.Class | TypeAttributes.Public, typeof(Attribute));
+ var field = tb.DefineField("_name", typeof(string), FieldAttributes.Private);
+ var propGet = tb.DefineMethod("get_AssemblyName", MethodAttributes.Public, typeof(string),
+ Array.Empty());
+ var propGetIl = propGet.GetILGenerator();
+ propGetIl.Emit(OpCodes.Ldarg_0);
+ propGetIl.Emit(OpCodes.Ldfld, field);
+ propGetIl.Emit(OpCodes.Ret);
+ var prop = tb.DefineProperty("AssemblyName", PropertyAttributes.None, typeof(string), Array.Empty());
+ prop.SetGetMethod(propGet);
+
+
+ var ctor = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard,
+ new[] { typeof(string) });
+ var ctorIl = ctor.GetILGenerator();
+ ctorIl.Emit(OpCodes.Ldarg_0);
+ ctorIl.Emit(OpCodes.Ldarg_1);
+ ctorIl.Emit(OpCodes.Stfld, field);
+ ctorIl.Emit(OpCodes.Ldarg_0);
+ ctorIl.Emit(OpCodes.Call, typeof(Attribute)
+ .GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
+ .First(x => x.GetParameters().Length == 0));
+
+ ctorIl.Emit(OpCodes.Ret);
+
+ tb.SetCustomAttribute(new CustomAttributeBuilder(
+ typeof(AttributeUsageAttribute).GetConstructor(new[] { typeof(AttributeTargets) }),
+ new object[] { AttributeTargets.Assembly },
+ new[] { typeof(AttributeUsageAttribute).GetProperty("AllowMultiple") },
+ new object[] { true }));
+
+ return tb.CreateTypeInfo();
+ }
+
+ static void EmitIgnoresAccessCheckToAttribute(AssemblyName assemblyName)
+ {
+ var name = assemblyName.Name;
+ if(string.IsNullOrWhiteSpace(name))
+ return;
+ var key = assemblyName.GetPublicKey();
+ if (key != null && key.Length != 0)
+ name += ", PublicKey=" + BitConverter.ToString(key).Replace("-", "").ToUpperInvariant();
+ _sreAsm.SetCustomAttribute(new CustomAttributeBuilder(
+ _ignoresAccessChecksFromAttribute.GetConstructors()[0],
+ new object[] { name }));
+ }
+
static object LoadSre(string xaml, Assembly localAssembly, object rootInstance, Uri uri, bool isDesignMode)
{
@@ -118,6 +171,8 @@ namespace Avalonia.Markup.Xaml.XamlIl
{
InitializeSre();
+ if (localAssembly?.GetName() != null)
+ EmitIgnoresAccessCheckToAttribute(localAssembly.GetName());
var asm = localAssembly == null ? null : _sreTypeSystem.GetAssembly(localAssembly);
var tb = _sreBuilder.DefineType("Builder_" + Guid.NewGuid().ToString("N") + "_" + uri);
var clrPropertyBuilder = tb.DefineNestedType("ClrProperties_" + Guid.NewGuid().ToString("N"));
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AstNodes/AvaloniaXamlIlAvaloniaListConstantAstNode.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AstNodes/AvaloniaXamlIlAvaloniaListConstantAstNode.cs
new file mode 100644
index 0000000000..0f4efc9f65
--- /dev/null
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AstNodes/AvaloniaXamlIlAvaloniaListConstantAstNode.cs
@@ -0,0 +1,54 @@
+using System.Collections.Generic;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers;
+using XamlX.Ast;
+using XamlX.Emit;
+using XamlX.IL;
+using XamlX.TypeSystem;
+
+namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.AstNodes
+{
+ class AvaloniaXamlIlAvaloniaListConstantAstNode : XamlAstNode, IXamlAstValueNode, IXamlAstILEmitableNode
+ {
+ private readonly IXamlType _elementType;
+ private readonly IReadOnlyList _values;
+ private readonly IXamlConstructor _constructor;
+ private readonly IXamlMethod _listAddMethod;
+ private readonly IXamlMethod _listSetCapacityMethod;
+
+ public AvaloniaXamlIlAvaloniaListConstantAstNode(IXamlLineInfo lineInfo, AvaloniaXamlIlWellKnownTypes types, IXamlType listType, IXamlType elementType, IReadOnlyList values) : base(lineInfo)
+ {
+ _constructor = listType.GetConstructor();
+ _listAddMethod = listType.GetMethod(new FindMethodMethodSignature("Add", types.XamlIlTypes.Void, elementType));
+ _listSetCapacityMethod = listType.GetMethod(new FindMethodMethodSignature("set_Capacity", types.XamlIlTypes.Void, types.Int));
+
+ _elementType = elementType;
+ _values = values;
+
+ Type = new XamlAstClrTypeReference(lineInfo, listType, false);
+ }
+
+ public IXamlAstTypeReference Type { get; }
+
+ public XamlILNodeEmitResult Emit(XamlEmitContext context, IXamlILEmitter codeGen)
+ {
+ codeGen.Newobj(_constructor);
+
+ codeGen
+ .Dup()
+ .Ldc_I4(_values.Count)
+ .EmitCall(_listSetCapacityMethod);
+
+ foreach (var value in _values)
+ {
+ codeGen.Dup();
+
+ context.Emit(value, codeGen, _elementType);
+
+ codeGen.EmitCall(_listAddMethod);
+ }
+
+ return XamlILNodeEmitResult.Type(0, Type.GetClrType());
+ }
+ }
+}
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AstNodes/AvaloniaXamlIlFontFamilyAstNode.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AstNodes/AvaloniaXamlIlFontFamilyAstNode.cs
new file mode 100644
index 0000000000..1f50e661d8
--- /dev/null
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AstNodes/AvaloniaXamlIlFontFamilyAstNode.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Collections.Generic;
+using Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers;
+using XamlX.Ast;
+using XamlX.Emit;
+using XamlX.IL;
+using XamlX.TypeSystem;
+
+namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.AstNodes
+{
+ class AvaloniaXamlIlFontFamilyAstNode: XamlAstNode, IXamlAstValueNode, IXamlAstILEmitableNode
+ {
+ private readonly AvaloniaXamlIlWellKnownTypes _types;
+ private readonly string _text;
+
+ public IXamlAstTypeReference Type { get; }
+
+ public AvaloniaXamlIlFontFamilyAstNode(AvaloniaXamlIlWellKnownTypes types,
+ string text,
+ IXamlLineInfo lineInfo) : base(lineInfo)
+ {
+ _types = types;
+ _text = text;
+ Type = new XamlAstClrTypeReference(lineInfo, types.FontFamily, false);
+ }
+
+ public XamlILNodeEmitResult Emit(XamlEmitContext context, IXamlILEmitter codeGen)
+ {
+ codeGen
+ .Ldloc(context.ContextLocal)
+ .Castclass(context.Configuration.TypeMappings.UriContextProvider)
+ .EmitCall(context.Configuration.TypeMappings.UriContextProvider.FindMethod(
+ "get_BaseUri", _types.Uri, false))
+ .Ldstr(_text)
+ .Newobj(_types.FontFamilyConstructorUriName);
+ return XamlILNodeEmitResult.Type(0, _types.FontFamily);
+ }
+ }
+}
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AstNodes/AvaloniaXamlIlGridLengthAstNode.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AstNodes/AvaloniaXamlIlGridLengthAstNode.cs
new file mode 100644
index 0000000000..218c49512c
--- /dev/null
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AstNodes/AvaloniaXamlIlGridLengthAstNode.cs
@@ -0,0 +1,34 @@
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers;
+using XamlX.Ast;
+using XamlX.Emit;
+using XamlX.IL;
+
+namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.AstNodes
+{
+ class AvaloniaXamlIlGridLengthAstNode : XamlAstNode, IXamlAstValueNode, IXamlAstILEmitableNode
+ {
+ private readonly AvaloniaXamlIlWellKnownTypes _types;
+ private readonly GridLength _gridLength;
+
+ public AvaloniaXamlIlGridLengthAstNode(IXamlLineInfo lineInfo, AvaloniaXamlIlWellKnownTypes types, GridLength gridLength) : base(lineInfo)
+ {
+ _types = types;
+ _gridLength = gridLength;
+
+ Type = new XamlAstClrTypeReference(lineInfo, types.GridLength, false);
+ }
+
+ public IXamlAstTypeReference Type { get; }
+
+ public XamlILNodeEmitResult Emit(XamlEmitContext context, IXamlILEmitter codeGen)
+ {
+ codeGen
+ .Ldc_R8(_gridLength.Value)
+ .Ldc_I4((int)_gridLength.GridUnitType)
+ .Newobj(_types.GridLengthConstructorValueType);
+
+ return XamlILNodeEmitResult.Type(0, Type.GetClrType());
+ }
+ }
+}
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AstNodes/AvaloniaXamlIlVectorLikeConstantAstNode.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AstNodes/AvaloniaXamlIlVectorLikeConstantAstNode.cs
new file mode 100644
index 0000000000..35cc9b3cf2
--- /dev/null
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AstNodes/AvaloniaXamlIlVectorLikeConstantAstNode.cs
@@ -0,0 +1,54 @@
+using Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers;
+using XamlX;
+using XamlX.Ast;
+using XamlX.Emit;
+using XamlX.IL;
+using XamlX.TypeSystem;
+
+namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.AstNodes
+{
+ class AvaloniaXamlIlVectorLikeConstantAstNode : XamlAstNode, IXamlAstValueNode, IXamlAstILEmitableNode
+ {
+ private readonly IXamlConstructor _constructor;
+ private readonly double[] _values;
+
+ public AvaloniaXamlIlVectorLikeConstantAstNode(IXamlLineInfo lineInfo, AvaloniaXamlIlWellKnownTypes types, IXamlType type, IXamlConstructor constructor, double[] values) : base(lineInfo)
+ {
+ var parameters = constructor.Parameters;
+
+ if (parameters.Count != values.Length)
+ {
+ throw new XamlTypeSystemException($"Constructor that takes {values.Length} parameters is expected, got {parameters.Count} instead.");
+ }
+
+ var elementType = types.XamlIlTypes.Double;
+
+ foreach (var parameter in parameters)
+ {
+ if (parameter != elementType)
+ {
+ throw new XamlTypeSystemException($"Expected parameter of type {elementType}, got {parameter} instead.");
+ }
+ }
+
+ _constructor = constructor;
+ _values = values;
+
+ Type = new XamlAstClrTypeReference(lineInfo, type, false);
+ }
+
+ public IXamlAstTypeReference Type { get; }
+
+ public XamlILNodeEmitResult Emit(XamlEmitContext context, IXamlILEmitter codeGen)
+ {
+ foreach (var value in _values)
+ {
+ codeGen.Ldc_R8(value);
+ }
+
+ codeGen.Newobj(_constructor);
+
+ return XamlILNodeEmitResult.Type(0, Type.GetClrType());
+ }
+ }
+}
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguage.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguage.cs
index 99ec3744bf..a82f5b9e60 100644
--- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguage.cs
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguage.cs
@@ -1,7 +1,11 @@
+using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.AstNodes;
using Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers;
+using Avalonia.Media;
using XamlX;
using XamlX.Ast;
using XamlX.Emit;
@@ -166,28 +170,27 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
public static bool CustomValueConverter(AstTransformationContext context,
IXamlAstValueNode node, IXamlType type, out IXamlAstValueNode result)
{
- if (type.FullName == "System.TimeSpan"
- && node is XamlAstTextNode tn
- && !tn.Text.Contains(":"))
+ if (!(node is XamlAstTextNode textNode))
{
- var seconds = double.Parse(tn.Text, CultureInfo.InvariantCulture);
- result = new XamlStaticOrTargetedReturnMethodCallNode(tn,
- type.FindMethod("FromSeconds", type, false, context.Configuration.WellKnownTypes.Double),
- new[]
- {
- new XamlConstantNode(tn, context.Configuration.WellKnownTypes.Double, seconds)
- });
- return true;
+ result = null;
+ return false;
}
+ var text = textNode.Text;
+ var types = context.GetAvaloniaTypes();
+
+ if (AvaloniaXamlIlLanguageParseIntrinsics.TryConvert(context, node, text, type, types, out result))
+ {
+ return true;
+ }
+
if (type.FullName == "Avalonia.AvaloniaProperty")
{
var scope = context.ParentNodes().OfType().FirstOrDefault();
if (scope == null)
throw new XamlX.XamlLoadException("Unable to find the parent scope for AvaloniaProperty lookup", node);
- if (!(node is XamlAstTextNode text))
- throw new XamlX.XamlLoadException("Property should be a text node", node);
- result = XamlIlAvaloniaPropertyHelper.CreateNode(context, text.Text, scope.TargetType, text);
+
+ result = XamlIlAvaloniaPropertyHelper.CreateNode(context, text, scope.TargetType, node );
return true;
}
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguageParseIntrinsics.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguageParseIntrinsics.cs
new file mode 100644
index 0000000000..7c4cc8d28b
--- /dev/null
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguageParseIntrinsics.cs
@@ -0,0 +1,243 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.AstNodes;
+using Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers;
+using Avalonia.Media;
+using XamlX.Ast;
+using XamlX.Transform;
+using XamlX.TypeSystem;
+
+namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
+{
+ class AvaloniaXamlIlLanguageParseIntrinsics
+ {
+ public static bool TryConvert(AstTransformationContext context, IXamlAstValueNode node, string text, IXamlType type, AvaloniaXamlIlWellKnownTypes types, out IXamlAstValueNode result)
+ {
+ if (type.FullName == "System.TimeSpan")
+ {
+ var tsText = text.Trim();
+
+ if (!TimeSpan.TryParse(tsText, CultureInfo.InvariantCulture, out var timeSpan))
+ {
+ // // shorthand seconds format (ie. "0.25")
+ if (!tsText.Contains(":") && double.TryParse(tsText,
+ NumberStyles.Float | NumberStyles.AllowThousands,
+ CultureInfo.InvariantCulture, out var seconds))
+ timeSpan = TimeSpan.FromSeconds(seconds);
+ else
+ throw new XamlX.XamlLoadException($"Unable to parse {text} as a time span", node);
+ }
+
+ result = new XamlStaticOrTargetedReturnMethodCallNode(node,
+ type.FindMethod("FromTicks", type, false, types.Long),
+ new[] { new XamlConstantNode(node, types.Long, timeSpan.Ticks) });
+ return true;
+ }
+
+ if (type.Equals(types.FontFamily))
+ {
+ result = new AvaloniaXamlIlFontFamilyAstNode(types, text, node);
+ return true;
+ }
+
+ if (type.Equals(types.Thickness))
+ {
+ try
+ {
+ var thickness = Thickness.Parse(text);
+
+ result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Thickness, types.ThicknessFullConstructor,
+ new[] { thickness.Left, thickness.Top, thickness.Right, thickness.Bottom });
+
+ return true;
+ }
+ catch
+ {
+ throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a thickness", node);
+ }
+ }
+
+ if (type.Equals(types.Point))
+ {
+ try
+ {
+ var point = Point.Parse(text);
+
+ result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Point, types.PointFullConstructor,
+ new[] { point.X, point.Y });
+
+ return true;
+ }
+ catch
+ {
+ throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a point", node);
+ }
+ }
+
+ if (type.Equals(types.Vector))
+ {
+ try
+ {
+ var vector = Vector.Parse(text);
+
+ result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Vector, types.VectorFullConstructor,
+ new[] { vector.X, vector.Y });
+
+ return true;
+ }
+ catch
+ {
+ throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a vector", node);
+ }
+ }
+
+ if (type.Equals(types.Size))
+ {
+ try
+ {
+ var size = Size.Parse(text);
+
+ result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Size, types.SizeFullConstructor,
+ new[] { size.Width, size.Height });
+
+ return true;
+ }
+ catch
+ {
+ throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a size", node);
+ }
+ }
+
+ if (type.Equals(types.Matrix))
+ {
+ try
+ {
+ var matrix = Matrix.Parse(text);
+
+ result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Matrix, types.MatrixFullConstructor,
+ new[] { matrix.M11, matrix.M12, matrix.M21, matrix.M22, matrix.M31, matrix.M32 });
+
+ return true;
+ }
+ catch
+ {
+ throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a matrix", node);
+ }
+ }
+
+ if (type.Equals(types.CornerRadius))
+ {
+ try
+ {
+ var cornerRadius = CornerRadius.Parse(text);
+
+ result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.CornerRadius, types.CornerRadiusFullConstructor,
+ new[] { cornerRadius.TopLeft, cornerRadius.TopRight, cornerRadius.BottomRight, cornerRadius.BottomLeft });
+
+ return true;
+ }
+ catch
+ {
+ throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a corner radius", node);
+ }
+ }
+
+ if (type.Equals(types.Color))
+ {
+ if (!Color.TryParse(text, out Color color))
+ {
+ throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a color", node);
+ }
+
+ result = new XamlStaticOrTargetedReturnMethodCallNode(node,
+ type.GetMethod(
+ new FindMethodMethodSignature("FromUInt32", type, types.UInt) { IsStatic = true }),
+ new[] { new XamlConstantNode(node, types.UInt, color.ToUint32()) });
+
+ return true;
+ }
+
+ if (type.Equals(types.GridLength))
+ {
+ try
+ {
+ var gridLength = GridLength.Parse(text);
+
+ result = new AvaloniaXamlIlGridLengthAstNode(node, types, gridLength);
+
+ return true;
+ }
+ catch
+ {
+ throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a grid length", node);
+ }
+ }
+
+ if (type.Equals(types.Cursor))
+ {
+ if (TypeSystemHelpers.TryGetEnumValueNode(types.StandardCursorType, text, node, out var enumConstantNode))
+ {
+ var cursorTypeRef = new XamlAstClrTypeReference(node, types.Cursor, false);
+
+ result = new XamlAstNewClrObjectNode(node, cursorTypeRef, types.CursorTypeConstructor, new List { enumConstantNode });
+
+ return true;
+ }
+ }
+
+ if (type.Equals(types.ColumnDefinitions))
+ {
+ return ConvertDefinitionList(node, text, types, types.ColumnDefinitions, types.ColumnDefinition, "column definitions", out result);
+ }
+
+ if (type.Equals(types.RowDefinitions))
+ {
+ return ConvertDefinitionList(node, text, types, types.RowDefinitions, types.RowDefinition, "row definitions", out result);
+ }
+
+ result = null;
+ return false;
+ }
+
+ private static bool ConvertDefinitionList(
+ IXamlAstValueNode node,
+ string text,
+ AvaloniaXamlIlWellKnownTypes types,
+ IXamlType listType,
+ IXamlType elementType,
+ string errorDisplayName,
+ out IXamlAstValueNode result)
+ {
+ try
+ {
+ var lengths = GridLength.ParseLengths(text);
+
+ var definitionTypeRef = new XamlAstClrTypeReference(node, elementType, false);
+
+ var definitionConstructorGridLength = elementType.GetConstructor(new List {types.GridLength});
+
+ IXamlAstValueNode CreateDefinitionNode(GridLength length)
+ {
+ var lengthNode = new AvaloniaXamlIlGridLengthAstNode(node, types, length);
+
+ return new XamlAstNewClrObjectNode(node, definitionTypeRef,
+ definitionConstructorGridLength, new List {lengthNode});
+ }
+
+ var definitionNodes =
+ new List(lengths.Select(CreateDefinitionNode));
+
+ result = new AvaloniaXamlIlAvaloniaListConstantAstNode(node, types, listType, elementType, definitionNodes);
+
+ return true;
+ }
+ catch
+ {
+ throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a {errorDisplayName}", node);
+ }
+ }
+ }
+}
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlBindingPathParser.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlBindingPathParser.cs
index 7944d8b569..24cded1d22 100644
--- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlBindingPathParser.cs
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlBindingPathParser.cs
@@ -72,16 +72,16 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
v.Property is AvaloniaSyntheticCompiledBindingProperty prop
&& prop.Name == SyntheticCompiledBindingPropertyName.ElementName);
- var sourceProperty = syntheticCompiledBindingProperties
- .FirstOrDefault(v =>
- v.Property is AvaloniaSyntheticCompiledBindingProperty prop
- && prop.Name == SyntheticCompiledBindingPropertyName.Source);
-
var relativeSourceProperty = syntheticCompiledBindingProperties
.FirstOrDefault(v =>
v.Property is AvaloniaSyntheticCompiledBindingProperty prop
&& prop.Name == SyntheticCompiledBindingPropertyName.RelativeSource);
+ var sourceProperty = binding.Children.OfType()
+ .FirstOrDefault(v =>
+ v.Property is XamlAstClrProperty prop
+ && prop.Name == "Source");
+
if (elementNameProperty?.Values[0] is XamlAstTextNode elementName)
{
convertedNode = new BindingExpressionGrammar.NameNode { Name = elementName.Text };
@@ -91,14 +91,9 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
throw new XamlParseException($"Invalid ElementName '{elementNameProperty.Values[0]}'.", elementNameProperty.Values[0]);
}
- if (sourceProperty?.Values[0] != null)
+ if (sourceProperty != null && convertedNode != null)
{
- if (convertedNode != null)
- {
- throw new XamlParseException("Only one of ElementName, Source, or RelativeSource specified as a binding source. Only one property is allowed.", binding);
- }
-
- convertedNode = new RawSourceBindingExpressionNode(sourceProperty?.Values[0]);
+ throw new XamlParseException("Only one of ElementName, Source, or RelativeSource specified as a binding source. Only one property is allowed.", binding);
}
if (GetRelativeSourceObjectFromAssignment(
@@ -223,10 +218,6 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
{
binding.Children.Remove(elementNameProperty);
}
- if (sourceProperty != null)
- {
- binding.Children.Remove(sourceProperty);
- }
if (relativeSourceProperty != null)
{
binding.Children.Remove(relativeSourceProperty);
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlBindingPathTransformer.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlBindingPathTransformer.cs
index fc32084687..4d8c940bbc 100644
--- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlBindingPathTransformer.cs
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlBindingPathTransformer.cs
@@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
-using XamlX;
using XamlX.Ast;
using XamlX.Transform;
using XamlX.TypeSystem;
@@ -15,14 +13,102 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
{
if (node is XamlAstConstructableObjectNode binding && binding.Type.GetClrType().Equals(context.GetAvaloniaTypes().CompiledBindingExtension))
{
- IXamlType startType;
- var parentDataContextNode = context.ParentNodes().OfType().FirstOrDefault();
- if (parentDataContextNode is null)
+ IXamlType startType = null;
+ var sourceProperty = binding.Children.OfType().FirstOrDefault(c => c.Property.Name == "Source");
+ if ((sourceProperty?.Values.Count ?? 0) == 1)
{
- throw new XamlX.XamlParseException("Cannot parse a compiled binding without an explicit x:DataType directive to give a starting data type for bindings.", binding);
+ var sourceValue = sourceProperty.Values[0];
+ switch (sourceValue)
+ {
+ case XamlAstTextNode textNode:
+ startType = textNode.Type?.GetClrType();
+ break;
+
+ case XamlMarkupExtensionNode extension:
+ startType = extension.Type?.GetClrType();
+
+ //let's try to infer StaticResource type from parent resources in xaml
+ if (extension.Value.Type.GetClrType().FullName == "Avalonia.Markup.Xaml.MarkupExtensions.StaticResourceExtension" &&
+ extension.Value is XamlAstConstructableObjectNode cn &&
+ cn.Arguments.Count == 1 && cn.Arguments[0] is XamlAstTextNode keyNode)
+ {
+ bool matchProperty(IXamlAstNode node, IXamlType styledElementType, string propertyName)
+ {
+ return (node is XamlPropertyAssignmentNode p &&
+ p.Property.DeclaringType == styledElementType && p.Property.Name == propertyName)
+ ||
+ (node is XamlManipulationGroupNode m && m.Children.Count > 0 &&
+ m.Children[0] is XamlPropertyAssignmentNode pm &&
+ pm.Property.DeclaringType == styledElementType && pm.Property.Name == propertyName);
+ }
+
+ string getResourceValue_xKey(XamlPropertyAssignmentNode node)
+ => node.Values.Count == 2 && node.Values[0] is XamlAstTextNode t ? t.Text : "";
+
+ IXamlType getResourceValue_Type(XamlPropertyAssignmentNode node, IXamlType xamlType)
+ => node.Values.Count == 2 ? node.Values[1].Type.GetClrType() : xamlType;
+
+ IEnumerable getResourceValues(IXamlAstNode node)
+ {
+ if (node is XamlPropertyAssignmentNode propertyNode)
+ {
+ if (propertyNode.Values.Count == 1 &&
+ propertyNode.Values[0] is XamlAstConstructableObjectNode obj &&
+ obj.Type.GetClrType().FullName == "Avalonia.Controls.ResourceDictionary")
+ {
+ foreach (var r in obj.Children.SelectMany(c => getResourceValues(c)))
+ {
+ yield return r;
+ }
+ }
+ else
+ {
+ yield return propertyNode;
+ }
+ }
+ else if (node is XamlManipulationGroupNode m)
+ {
+ foreach (var r in m.Children.OfType())
+ {
+ yield return r;
+ }
+ }
+ }
+
+ string key = keyNode.Text;
+
+ var styledElement = context.GetAvaloniaTypes().StyledElement;
+ var resource = context.ParentNodes()
+ .OfType()
+ .Where(o => styledElement.IsAssignableFrom(o.Type.GetClrType()))
+ .Select(o => o.Children.FirstOrDefault(p => matchProperty(p, styledElement, "Resources")))
+ .Where(r => r != null)
+ .SelectMany(r => getResourceValues(r))
+ .FirstOrDefault(r => getResourceValue_xKey(r) == key);
+
+ if (resource != null)
+ {
+ startType = getResourceValue_Type(resource, startType);
+ }
+ }
+ break;
+
+ case XamlStaticExtensionNode staticExtension:
+ startType = staticExtension.Type?.GetClrType();
+ break;
+ }
}
- startType = parentDataContextNode.DataContextType;
+ if (startType == null)
+ {
+ var parentDataContextNode = context.ParentNodes().OfType().FirstOrDefault();
+ if (parentDataContextNode is null)
+ {
+ throw new XamlX.XamlParseException("Cannot parse a compiled binding without an explicit x:DataType directive to give a starting data type for bindings.", binding);
+ }
+
+ startType = parentDataContextNode.DataContextType;
+ }
XamlIlBindingPathHelper.UpdateCompiledBindingExtension(context, binding, startType);
}
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlTransformInstanceAttachedProperties.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlTransformInstanceAttachedProperties.cs
index d78ceeb918..f87e73a783 100644
--- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlTransformInstanceAttachedProperties.cs
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlTransformInstanceAttachedProperties.cs
@@ -22,7 +22,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
var avaloniaObject = context.Configuration.TypeSystem.FindType("Avalonia.AvaloniaObject");
if (avaloniaObject.IsAssignableFrom(targetRef.Type)
&& avaloniaObject.IsAssignableFrom(declaringRef.Type)
- && !targetRef.Type.IsAssignableFrom(declaringRef.Type))
+ && !declaringRef.Type.IsAssignableFrom(targetRef.Type))
{
// Instance property
var clrProp = declaringRef.Type.GetAllProperties().FirstOrDefault(p => p.Name == prop.Name);
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlTransformSyntheticCompiledBindingMembers.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlTransformSyntheticCompiledBindingMembers.cs
index 154c6a235c..ba05347a52 100644
--- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlTransformSyntheticCompiledBindingMembers.cs
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlTransformSyntheticCompiledBindingMembers.cs
@@ -25,11 +25,6 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
return new AvaloniaSyntheticCompiledBindingProperty(node,
SyntheticCompiledBindingPropertyName.RelativeSource);
}
- else if (prop.Name == "Source")
- {
- return new AvaloniaSyntheticCompiledBindingProperty(node,
- SyntheticCompiledBindingPropertyName.Source);
- }
}
return node;
@@ -39,8 +34,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
enum SyntheticCompiledBindingPropertyName
{
ElementName,
- RelativeSource,
- Source
+ RelativeSource
}
class AvaloniaSyntheticCompiledBindingProperty : XamlAstNode, IXamlAstPropertyReference
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs
index 3dec96dc43..125701ca9e 100644
--- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs
@@ -1,3 +1,5 @@
+using System.Collections.Generic;
+using System.Linq;
using XamlX.Emit;
using XamlX.IL;
using XamlX.Transform;
@@ -47,6 +49,34 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
public IXamlType ReflectionBindingExtension { get; }
public IXamlType RelativeSource { get; }
+ public IXamlType UInt { get; }
+ public IXamlType Int { get; }
+ public IXamlType Long { get; }
+ public IXamlType Uri { get; }
+ public IXamlType FontFamily { get; }
+ public IXamlConstructor FontFamilyConstructorUriName { get; }
+ public IXamlType Thickness { get; }
+ public IXamlConstructor ThicknessFullConstructor { get; }
+ public IXamlType Point { get; }
+ public IXamlConstructor PointFullConstructor { get; }
+ public IXamlType Vector { get; }
+ public IXamlConstructor VectorFullConstructor { get; }
+ public IXamlType Size { get; }
+ public IXamlConstructor SizeFullConstructor { get; }
+ public IXamlType Matrix { get; }
+ public IXamlConstructor MatrixFullConstructor { get; }
+ public IXamlType CornerRadius { get; }
+ public IXamlConstructor CornerRadiusFullConstructor { get; }
+ public IXamlType GridLength { get; }
+ public IXamlConstructor GridLengthConstructorValueType { get; }
+ public IXamlType Color { get; }
+ public IXamlType StandardCursorType { get; }
+ public IXamlType Cursor { get; }
+ public IXamlConstructor CursorTypeConstructor { get; }
+ public IXamlType RowDefinition { get; }
+ public IXamlType RowDefinitions { get; }
+ public IXamlType ColumnDefinition { get; }
+ public IXamlType ColumnDefinitions { get; }
public AvaloniaXamlIlWellKnownTypes(TransformerConfiguration cfg)
{
@@ -104,6 +134,38 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
ItemsRepeater = cfg.TypeSystem.GetType("Avalonia.Controls.ItemsRepeater");
ReflectionBindingExtension = cfg.TypeSystem.GetType("Avalonia.Markup.Xaml.MarkupExtensions.ReflectionBindingExtension");
RelativeSource = cfg.TypeSystem.GetType("Avalonia.Data.RelativeSource");
+ UInt = cfg.TypeSystem.GetType("System.UInt32");
+ Int = cfg.TypeSystem.GetType("System.Int32");
+ Long = cfg.TypeSystem.GetType("System.Int64");
+ Uri = cfg.TypeSystem.GetType("System.Uri");
+ FontFamily = cfg.TypeSystem.GetType("Avalonia.Media.FontFamily");
+ FontFamilyConstructorUriName = FontFamily.GetConstructor(new List { Uri, XamlIlTypes.String });
+
+ (IXamlType, IXamlConstructor) GetNumericTypeInfo(string name, IXamlType componentType, int componentCount)
+ {
+ var type = cfg.TypeSystem.GetType(name);
+ var ctor = type.GetConstructor(Enumerable.Range(0, componentCount).Select(_ => componentType).ToList());
+
+ return (type, ctor);
+ }
+
+ (Thickness, ThicknessFullConstructor) = GetNumericTypeInfo("Avalonia.Thickness", XamlIlTypes.Double, 4);
+ (Point, PointFullConstructor) = GetNumericTypeInfo("Avalonia.Point", XamlIlTypes.Double, 2);
+ (Vector, VectorFullConstructor) = GetNumericTypeInfo("Avalonia.Vector", XamlIlTypes.Double, 2);
+ (Size, SizeFullConstructor) = GetNumericTypeInfo("Avalonia.Size", XamlIlTypes.Double, 2);
+ (Matrix, MatrixFullConstructor) = GetNumericTypeInfo("Avalonia.Matrix", XamlIlTypes.Double, 6);
+ (CornerRadius, CornerRadiusFullConstructor) = GetNumericTypeInfo("Avalonia.CornerRadius", XamlIlTypes.Double, 4);
+
+ GridLength = cfg.TypeSystem.GetType("Avalonia.Controls.GridLength");
+ GridLengthConstructorValueType = GridLength.GetConstructor(new List { XamlIlTypes.Double, cfg.TypeSystem.GetType("Avalonia.Controls.GridUnitType") });
+ Color = cfg.TypeSystem.GetType("Avalonia.Media.Color");
+ StandardCursorType = cfg.TypeSystem.GetType("Avalonia.Input.StandardCursorType");
+ Cursor = cfg.TypeSystem.GetType("Avalonia.Input.Cursor");
+ CursorTypeConstructor = Cursor.GetConstructor(new List { StandardCursorType });
+ ColumnDefinition = cfg.TypeSystem.GetType("Avalonia.Controls.ColumnDefinition");
+ ColumnDefinitions = cfg.TypeSystem.GetType("Avalonia.Controls.ColumnDefinitions");
+ RowDefinition = cfg.TypeSystem.GetType("Avalonia.Controls.RowDefinition");
+ RowDefinitions = cfg.TypeSystem.GetType("Avalonia.Controls.RowDefinitions");
}
}
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlBindingPathHelper.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlBindingPathHelper.cs
index 03ec32b9cf..1974dfe3bc 100644
--- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlBindingPathHelper.cs
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlBindingPathHelper.cs
@@ -203,6 +203,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
.ParentNodes()
.OfType()
.Where(x => styledElementType.IsAssignableFrom(x.Type.GetClrType()))
+ .Skip(1)
.ElementAtOrDefault(ancestor.Level)
?.Type.GetClrType();
@@ -242,6 +243,16 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
case RawSourceBindingExpressionNode rawSource:
nodes.Add(new RawSourcePathElementNode(rawSource.RawSource));
break;
+ case BindingExpressionGrammar.TypeCastNode typeCastNode:
+ var castType = GetType(typeCastNode.Namespace, typeCastNode.TypeName);
+
+ if (castType is null)
+ {
+ throw new XamlX.XamlParseException($"Unable to resolve cast to type {typeCastNode.Namespace}:{typeCastNode.TypeName} based on XAML tree.", lineInfo);
+ }
+
+ nodes.Add(new TypeCastPathElementNode(castType));
+ break;
}
}
@@ -422,7 +433,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
{
codeGen.Ldtype(Type)
.Ldc_I4(_level)
- .EmitCall(context.GetAvaloniaTypes().CompiledBindingPathBuilder.FindMethod(m => m.Name == "FindAncestor"));
+ .EmitCall(context.GetAvaloniaTypes().CompiledBindingPathBuilder.FindMethod(m => m.Name == "Ancestor"));
}
}
@@ -608,10 +619,10 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
private readonly IXamlAstValueNode _rawSource;
public RawSourcePathElementNode(IXamlAstValueNode rawSource)
- :base(rawSource)
+ : base(rawSource)
{
_rawSource = rawSource;
-
+
}
public IXamlType Type => _rawSource.Type.GetClrType();
@@ -625,6 +636,21 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
}
}
+ class TypeCastPathElementNode : IXamlIlBindingPathElementNode
+ {
+ public TypeCastPathElementNode(IXamlType ancestorType)
+ {
+ Type = ancestorType;
+ }
+
+ public IXamlType Type { get; }
+
+ public void Emit(XamlIlEmitContext context, IXamlILEmitter codeGen)
+ {
+ codeGen.EmitCall(context.GetAvaloniaTypes().CompiledBindingPathBuilder.FindMethod(m => m.Name == "TypeCast").MakeGenericMethod(new[] { Type }));
+ }
+ }
+
class XamlIlBindingPathNode : XamlAstNode, IXamlIlBindingPathNode, IXamlAstEmitableNode
{
private readonly List _transformElements;
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/xamlil.github b/src/Markup/Avalonia.Markup.Xaml.Loader/xamlil.github
index 7d15a92274..ea80a607c5 160000
--- a/src/Markup/Avalonia.Markup.Xaml.Loader/xamlil.github
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/xamlil.github
@@ -1 +1 @@
-Subproject commit 7d15a9227461cf4d62bc2ed251fcc25c96b28aaf
+Subproject commit ea80a607c5e9d8f000160dbbb48c27ed4cfafbc9
diff --git a/src/Markup/Avalonia.Markup.Xaml/ApiCompatBaseline.txt b/src/Markup/Avalonia.Markup.Xaml/ApiCompatBaseline.txt
index c87dcacda4..fcc74cf864 100644
--- a/src/Markup/Avalonia.Markup.Xaml/ApiCompatBaseline.txt
+++ b/src/Markup/Avalonia.Markup.Xaml/ApiCompatBaseline.txt
@@ -1,4 +1 @@
-Compat issues with assembly Avalonia.Markup.Xaml:
-MembersMustExist : Member 'public Avalonia.Data.Binding Avalonia.Markup.Xaml.Templates.TreeDataTemplate.ItemsSource.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'public void Avalonia.Markup.Xaml.Templates.TreeDataTemplate.ItemsSource.set(Avalonia.Data.Binding)' does not exist in the implementation but it does exist in the contract.
-Total Issues: 2
+Total Issues: 0
diff --git a/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj b/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj
index 44a082e2df..217da2d50d 100644
--- a/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj
+++ b/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj
@@ -1,7 +1,7 @@
netstandard2.0
- PCL;NETSTANDARD;NETSTANDARD2_0;HAS_TYPE_CONVERTER;HAS_CUSTOM_ATTRIBUTE_PROVIDER;XAMLX_INTERNAL
+ $(DefineConstants);PCL;NETSTANDARD;NETSTANDARD2_0;HAS_TYPE_CONVERTER;HAS_CUSTOM_ATTRIBUTE_PROVIDER;XAMLX_INTERNAL
false
$(DefineConstants);RUNTIME_XAML_CECIL
False
@@ -23,6 +23,7 @@
+
diff --git a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindingExtension.cs b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindingExtension.cs
index aab733cb43..17d2ea7ae9 100644
--- a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindingExtension.cs
+++ b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindingExtension.cs
@@ -26,10 +26,13 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions
{
Path = Path,
Converter = Converter,
+ ConverterParameter = ConverterParameter,
+ TargetNullValue = TargetNullValue,
FallbackValue = FallbackValue,
Mode = Mode,
Priority = Priority,
StringFormat = StringFormat,
+ Source = Source,
DefaultAnchor = new WeakReference(GetDefaultAnchor(provider))
};
}
@@ -50,6 +53,13 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions
protected override ExpressionObserver CreateExpressionObserver(IAvaloniaObject target, AvaloniaProperty targetProperty, object anchor, bool enableDataValidation)
{
+ if (Source != null)
+ {
+ return CreateSourceObserver(
+ Source,
+ Path.BuildExpression(enableDataValidation));
+ }
+
if (Path.RawSource != null)
{
return CreateSourceObserver(
@@ -75,5 +85,7 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions
[ConstructorArgument("path")]
public CompiledBindingPath Path { get; set; }
+
+ public object Source { get; set; }
}
}
diff --git a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/CompiledBindingPath.cs b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/CompiledBindingPath.cs
index d627fe3cd3..f6636664c1 100644
--- a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/CompiledBindingPath.cs
+++ b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/CompiledBindingPath.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using Avalonia.Controls;
using Avalonia.Data.Core;
using Avalonia.Data.Core.Plugins;
@@ -53,6 +54,9 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings
case IStronglyTypedStreamElement stream:
node = new StreamNode(stream.CreatePlugin());
break;
+ case ITypeCastElement typeCast:
+ node = new StrongTypeCastNode(typeCast.Type, typeCast.Cast);
+ break;
default:
throw new InvalidOperationException($"Unknown binding path element type {element.GetType().FullName}");
}
@@ -66,6 +70,9 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings
internal SourceMode SourceMode => _elements.Count > 0 && _elements[0] is IControlSourceBindingPathElement ? SourceMode.Control : SourceMode.Data;
internal object RawSource { get; }
+
+ public override string ToString()
+ => string.Concat(_elements.Select(e => e.ToString()));
}
public class CompiledBindingPathBuilder
@@ -126,6 +133,12 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings
return this;
}
+ public CompiledBindingPathBuilder TypeCast()
+ {
+ _elements.Add(new TypeCastPathElement());
+ return this;
+ }
+
public CompiledBindingPathBuilder SetRawSource(object rawSource)
{
_rawSource = rawSource;
@@ -157,6 +170,9 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings
public IPropertyInfo Property { get; }
public Func, IPropertyInfo, IPropertyAccessor> AccessorFactory { get; }
+
+ public override string ToString()
+ => $".{Property.Name}";
}
internal interface IStronglyTypedStreamElement : ICompiledBindingPathElement
@@ -164,6 +180,13 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings
IStreamPlugin CreatePlugin();
}
+ internal interface ITypeCastElement : ICompiledBindingPathElement
+ {
+ Type Type { get; }
+
+ Func Cast { get; }
+ }
+
internal class TaskStreamPathElement : IStronglyTypedStreamElement
{
public static readonly TaskStreamPathElement Instance = new TaskStreamPathElement();
@@ -181,6 +204,9 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings
internal class SelfPathElement : ICompiledBindingPathElement, IControlSourceBindingPathElement
{
public static readonly SelfPathElement Instance = new SelfPathElement();
+
+ public override string ToString()
+ => "$self";
}
internal class AncestorPathElement : ICompiledBindingPathElement, IControlSourceBindingPathElement
@@ -193,6 +219,9 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings
public Type AncestorType { get; }
public int Level { get; }
+
+ public override string ToString()
+ => $"$parent[{AncestorType?.Name},{Level}]";
}
internal class VisualAncestorPathElement : ICompiledBindingPathElement, IControlSourceBindingPathElement
@@ -217,6 +246,9 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings
public INameScope NameScope { get; }
public string Name { get; }
+
+ public override string ToString()
+ => $"#{Name}";
}
internal class ArrayElementPathElement : ICompiledBindingPathElement
@@ -229,5 +261,24 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings
public int[] Indices { get; }
public Type ElementType { get; }
+ public override string ToString()
+ => $"[{string.Join(",", Indices)}]";
+ }
+
+ internal class TypeCastPathElement : ITypeCastElement
+ {
+ private static object TryCast(object obj)
+ {
+ if (obj is T result)
+ return result;
+ return null;
+ }
+
+ public Type Type => typeof(T);
+
+ public Func Cast => TryCast;
+
+ public override string ToString()
+ => $"({Type.FullName})";
}
}
diff --git a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/StrongTypeCastNode.cs b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/StrongTypeCastNode.cs
new file mode 100644
index 0000000000..1252ec7eca
--- /dev/null
+++ b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/StrongTypeCastNode.cs
@@ -0,0 +1,18 @@
+using System;
+using Avalonia.Data.Core;
+
+namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings
+{
+ public class StrongTypeCastNode : TypeCastNode
+ {
+ private Func _cast;
+
+ public StrongTypeCastNode(Type type, Func cast) : base(type)
+ {
+ _cast = cast;
+ }
+
+ protected override object Cast(object value)
+ => _cast(value);
+ }
+}
diff --git a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/DynamicResourceExtension.cs b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/DynamicResourceExtension.cs
index 03fd2e60dd..95380be65f 100644
--- a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/DynamicResourceExtension.cs
+++ b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/DynamicResourceExtension.cs
@@ -10,8 +10,7 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions
{
public class DynamicResourceExtension : IBinding
{
- private IStyledElement? _anchor;
- private IResourceProvider? _resourceProvider;
+ private object? _anchor;
public DynamicResourceExtension()
{
@@ -30,12 +29,9 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions
if (!(provideTarget.TargetObject is IStyledElement))
{
- _anchor = serviceProvider.GetFirstParent();
-
- if (_anchor is null)
- {
- _resourceProvider = serviceProvider.GetFirstParent();
- }
+ _anchor = serviceProvider.GetFirstParent() ??
+ serviceProvider.GetFirstParent() ??
+ (object?)serviceProvider.GetFirstParent();
}
return this;
@@ -52,16 +48,16 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions
return null;
}
- var control = target as IStyledElement ?? _anchor as IStyledElement;
+ var control = target as IResourceHost ?? _anchor as IResourceHost;
if (control != null)
{
var source = control.GetResourceObservable(ResourceKey, GetConverter(targetProperty));
return InstancedBinding.OneWay(source);
}
- else if (_resourceProvider is object)
+ else if (_anchor is IResourceProvider resourceProvider)
{
- var source = _resourceProvider.GetResourceObservable(ResourceKey, GetConverter(targetProperty));
+ var source = resourceProvider.GetResourceObservable(ResourceKey, GetConverter(targetProperty));
return InstancedBinding.OneWay(source);
}
diff --git a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/ResolveByNameExtension.cs b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/ResolveByNameExtension.cs
index 8561aa898b..909462392c 100644
--- a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/ResolveByNameExtension.cs
+++ b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/ResolveByNameExtension.cs
@@ -30,7 +30,7 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions
if (provideValueTarget.TargetProperty is IPropertyInfo property)
value.OnCompleted(() => property.Set(target, value.GetResult()));
- return null;
+ return AvaloniaProperty.UnsetValue;
}
}
}
diff --git a/src/Markup/Avalonia.Markup.Xaml/Properties/AssemblyInfo.cs b/src/Markup/Avalonia.Markup.Xaml/Properties/AssemblyInfo.cs
index 7e4a095bdf..706729a5ac 100644
--- a/src/Markup/Avalonia.Markup.Xaml/Properties/AssemblyInfo.cs
+++ b/src/Markup/Avalonia.Markup.Xaml/Properties/AssemblyInfo.cs
@@ -5,5 +5,8 @@ using System.Runtime.CompilerServices;
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Markup.Xaml.MarkupExtensions")]
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Markup.Xaml.Styling")]
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Markup.Xaml.Templates")]
+#if SIGNED_BUILD
+[assembly: InternalsVisibleTo("Avalonia.Markup.Xaml.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")]
+#else
[assembly: InternalsVisibleTo("Avalonia.Markup.Xaml.UnitTests")]
-
+#endif
diff --git a/src/Markup/Avalonia.Markup/Data/MultiBinding.cs b/src/Markup/Avalonia.Markup/Data/MultiBinding.cs
index 7aa1eed890..cbc5f414f2 100644
--- a/src/Markup/Avalonia.Markup/Data/MultiBinding.cs
+++ b/src/Markup/Avalonia.Markup/Data/MultiBinding.cs
@@ -48,7 +48,7 @@ namespace Avalonia.Data
/// Gets or sets the binding priority.
///
public BindingPriority Priority { get; set; }
-
+
///
/// Gets or sets the relative source for the binding.
///
@@ -77,12 +77,12 @@ namespace Avalonia.Data
// We only respect `StringFormat` if the type of the property we're assigning to will
// accept a string. Note that this is slightly different to WPF in that WPF only applies
// `StringFormat` for target type `string` (not `object`).
- if (!string.IsNullOrWhiteSpace(StringFormat) &&
+ if (!string.IsNullOrWhiteSpace(StringFormat) &&
(targetType == typeof(string) || targetType == typeof(object)))
{
converter = new StringFormatMultiValueConverter(StringFormat, converter);
}
-
+
var children = Bindings.Select(x => x.Initiate(target, null));
var input = children.Select(x => x.Observable)
@@ -116,7 +116,16 @@ namespace Avalonia.Data
}
var culture = CultureInfo.CurrentCulture;
- var converted = converter.Convert(values, targetType, ConverterParameter, culture);
+ values = new System.Collections.ObjectModel.ReadOnlyCollection(values);
+ object converted;
+ if (converter != null)
+ {
+ converted = converter.Convert(values, targetType, ConverterParameter, culture);
+ }
+ else
+ {
+ converted = values;
+ }
if (converted == null)
{
diff --git a/src/Markup/Avalonia.Markup/Markup/Parsers/BindingExpressionGrammar.cs b/src/Markup/Avalonia.Markup/Markup/Parsers/BindingExpressionGrammar.cs
index 8de64e56ff..7c362e24cc 100644
--- a/src/Markup/Avalonia.Markup/Markup/Parsers/BindingExpressionGrammar.cs
+++ b/src/Markup/Avalonia.Markup/Markup/Parsers/BindingExpressionGrammar.cs
@@ -16,7 +16,7 @@ namespace Avalonia.Markup.Parsers
internal static class BindingExpressionGrammar
{
- public static (IList Nodes, SourceMode Mode) Parse(ref CharacterReader r)
+ public static (List Nodes, SourceMode Mode) Parse(ref CharacterReader r)
{
var nodes = new List();
var state = State.Start;
@@ -46,6 +46,10 @@ namespace Avalonia.Markup.Parsers
state = ParseIndexer(ref r, nodes);
break;
+ case State.TypeCast:
+ state = ParseTypeCast(ref r, nodes);
+ break;
+
case State.ElementName:
state = ParseElementName(ref r, nodes);
mode = SourceMode.Control;
@@ -84,6 +88,11 @@ namespace Avalonia.Markup.Parsers
}
else if (ParseOpenBrace(ref r))
{
+ if (PeekOpenBrace(ref r))
+ {
+ return State.TypeCast;
+ }
+
return State.AttachedProperty;
}
else if (PeekOpenBracket(ref r))
@@ -124,6 +133,10 @@ namespace Avalonia.Markup.Parsers
{
return State.Indexer;
}
+ else if (ParseOpenBrace(ref r))
+ {
+ return State.TypeCast;
+ }
return State.End;
}
@@ -132,6 +145,11 @@ namespace Avalonia.Markup.Parsers
{
if (ParseOpenBrace(ref r))
{
+ if (PeekOpenBrace(ref r))
+ {
+ return State.TypeCast;
+ }
+
return State.AttachedProperty;
}
else
@@ -152,6 +170,12 @@ namespace Avalonia.Markup.Parsers
{
var (ns, owner) = ParseTypeName(ref r);
+ if(!r.End && r.TakeIf(')'))
+ {
+ nodes.Add(new TypeCastNode() { Namespace = ns, TypeName = owner });
+ return State.AfterMember;
+ }
+
if (r.End || !r.TakeIf('.'))
{
throw new ExpressionParseException(r.Position, "Invalid attached property name.");
@@ -159,6 +183,11 @@ namespace Avalonia.Markup.Parsers
var name = r.ParseIdentifier();
+ if (name.Length == 0)
+ {
+ throw new ExpressionParseException(r.Position, "Attached Property name expected after '.'.");
+ }
+
if (r.End || !r.TakeIf(')'))
{
throw new ExpressionParseException(r.Position, "Expected ')'.");
@@ -186,6 +215,39 @@ namespace Avalonia.Markup.Parsers
return State.AfterMember;
}
+ private static State ParseTypeCast(ref CharacterReader r, List nodes)
+ {
+ bool parseMemberBeforeAddCast = ParseOpenBrace(ref r);
+
+ var (ns, typeName) = ParseTypeName(ref r);
+
+ var result = State.AfterMember;
+
+ if (parseMemberBeforeAddCast)
+ {
+ if (!ParseCloseBrace(ref r))
+ {
+ throw new ExpressionParseException(r.Position, "Expected ')'.");
+ }
+
+ result = ParseBeforeMember(ref r, nodes);
+
+ if(r.Peek == '[')
+ {
+ result = ParseIndexer(ref r, nodes);
+ }
+ }
+
+ nodes.Add(new TypeCastNode { Namespace = ns, TypeName = typeName });
+
+ if (r.End || !r.TakeIf(')'))
+ {
+ throw new ExpressionParseException(r.Position, "Expected ')'.");
+ }
+
+ return result;
+ }
+
private static State ParseElementName(ref CharacterReader r, List nodes)
{
var name = r.ParseIdentifier();
@@ -288,11 +350,21 @@ namespace Avalonia.Markup.Parsers
return !r.End && r.TakeIf('(');
}
+ private static bool ParseCloseBrace(ref CharacterReader r)
+ {
+ return !r.End && r.TakeIf(')');
+ }
+
private static bool PeekOpenBracket(ref CharacterReader r)
{
return !r.End && r.Peek == '[';
}
+ private static bool PeekOpenBrace(ref CharacterReader r)
+ {
+ return !r.End && r.Peek == '(';
+ }
+
private static bool ParseStreamOperator(ref CharacterReader r)
{
return !r.End && r.TakeIf('^');
@@ -322,6 +394,7 @@ namespace Avalonia.Markup.Parsers
BeforeMember,
AttachedProperty,
Indexer,
+ TypeCast,
End,
}
@@ -343,9 +416,9 @@ namespace Avalonia.Markup.Parsers
}
}
- public interface INode {}
+ public interface INode { }
- public interface ITransformNode {}
+ public interface ITransformNode { }
public class EmptyExpressionNode : INode { }
@@ -366,11 +439,11 @@ namespace Avalonia.Markup.Parsers
public IList Arguments { get; set; }
}
- public class NotNode : INode, ITransformNode {}
+ public class NotNode : INode, ITransformNode { }
- public class StreamNode : INode {}
+ public class StreamNode : INode { }
- public class SelfNode : INode {}
+ public class SelfNode : INode { }
public class NameNode : INode
{
@@ -383,5 +456,11 @@ namespace Avalonia.Markup.Parsers
public string TypeName { get; set; }
public int Level { get; set; }
}
+
+ public class TypeCastNode : INode
+ {
+ public string Namespace { get; set; }
+ public string TypeName { get; set; }
+ }
}
}
diff --git a/src/Markup/Avalonia.Markup/Markup/Parsers/ExpressionParser.cs b/src/Markup/Avalonia.Markup/Markup/Parsers/ExpressionParser.cs
index 1048148c1f..558130e23f 100644
--- a/src/Markup/Avalonia.Markup/Markup/Parsers/ExpressionParser.cs
+++ b/src/Markup/Avalonia.Markup/Markup/Parsers/ExpressionParser.cs
@@ -59,6 +59,9 @@ namespace Avalonia.Markup.Parsers
case BindingExpressionGrammar.NameNode elementName:
nextNode = new ElementNameNode(_nameScope, elementName.Name);
break;
+ case BindingExpressionGrammar.TypeCastNode typeCast:
+ nextNode = ParseTypeCastNode(typeCast);
+ break;
}
if (rootNode is null)
{
@@ -92,6 +95,22 @@ namespace Avalonia.Markup.Parsers
return new FindAncestorNode(ancestorType, ancestorLevel);
}
+ private TypeCastNode ParseTypeCastNode(BindingExpressionGrammar.TypeCastNode node)
+ {
+ Type castType = null;
+ if (!(node.Namespace is null) && !(node.TypeName is null))
+ {
+ if (_typeResolver == null)
+ {
+ throw new InvalidOperationException("Cannot parse a binding path with a typed Cast without a type resolver. Maybe you can use a LINQ Expression binding path instead?");
+ }
+
+ castType = _typeResolver(node.Namespace, node.TypeName);
+ }
+
+ return new TypeCastNode(castType);
+ }
+
private AvaloniaPropertyAccessorNode ParseAttachedProperty(BindingExpressionGrammar.AttachedPropertyNameNode node)
{
if (_typeResolver == null)
diff --git a/src/Markup/Avalonia.Markup/Properties/AssemblyInfo.cs b/src/Markup/Avalonia.Markup/Properties/AssemblyInfo.cs
index 72c1659a1e..ac055af98b 100644
--- a/src/Markup/Avalonia.Markup/Properties/AssemblyInfo.cs
+++ b/src/Markup/Avalonia.Markup/Properties/AssemblyInfo.cs
@@ -4,4 +4,8 @@ using System.Runtime.CompilerServices;
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Data")]
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Markup.Data")]
+#if SIGNED_BUILD
+[assembly: InternalsVisibleTo("Avalonia.Markup.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")]
+#else
[assembly: InternalsVisibleTo("Avalonia.Markup.UnitTests")]
+#endif
diff --git a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs
index 98528a128a..2a79a4bb50 100644
--- a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs
+++ b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs
@@ -31,16 +31,23 @@ namespace Avalonia.Skia
private bool _disposed;
private GRContext _grContext;
public GRContext GrContext => _grContext;
+ private ISkiaGpu _gpu;
private readonly SKPaint _strokePaint = new SKPaint();
private readonly SKPaint _fillPaint = new SKPaint();
private readonly SKPaint _boxShadowPaint = new SKPaint();
private static SKShader s_acrylicNoiseShader;
+ private readonly ISkiaGpuRenderSession _session;
///
/// Context create info.
///
public struct CreateInfo
{
+ ///
+ /// Canvas to draw to.
+ ///
+ public SKCanvas Canvas;
+
///
/// Surface to draw to.
///
@@ -65,6 +72,13 @@ namespace Avalonia.Skia
/// GPU-accelerated context (optional)
///
public GRContext GrContext;
+
+ ///
+ /// Skia GPU provider context (optional)
+ ///
+ public ISkiaGpu Gpu;
+
+ public ISkiaGpuRenderSession CurrentSession;
}
///
@@ -79,10 +93,13 @@ namespace Avalonia.Skia
_disposables = disposables;
_canTextUseLcdRendering = !createInfo.DisableTextLcdRendering;
_grContext = createInfo.GrContext;
+ _gpu = createInfo.Gpu;
if (_grContext != null)
Monitor.Enter(_grContext);
Surface = createInfo.Surface;
- Canvas = createInfo.Surface.Canvas;
+ Canvas = createInfo.Canvas ?? createInfo.Surface?.Canvas;
+
+ _session = createInfo.CurrentSession;
if (Canvas == null)
{
@@ -415,9 +432,9 @@ namespace Avalonia.Skia
}
///
- public IRenderTargetBitmapImpl CreateLayer(Size size)
+ public IDrawingContextLayerImpl CreateLayer(Size size)
{
- return CreateRenderTarget(size);
+ return CreateRenderTarget(size, true);
}
///
@@ -583,12 +600,60 @@ namespace Avalonia.Skia
var center = radialGradient.Center.ToPixels(targetSize).ToSKPoint();
var radius = (float)(radialGradient.Radius * targetSize.Width);
- // TODO: There is no SetAlpha in SkiaSharp
- //paint.setAlpha(128);
+ var origin = radialGradient.GradientOrigin.ToPixels(targetSize).ToSKPoint();
- // would be nice to cache these shaders possibly?
- using (var shader =
- SKShader.CreateRadialGradient(center, radius, stopColors, stopOffsets, tileMode))
+ if (origin.Equals(center))
+ {
+ // when the origin is the same as the center the Skia RadialGradient acts the same as D2D
+ using (var shader =
+ SKShader.CreateRadialGradient(center, radius, stopColors, stopOffsets, tileMode))
+ {
+ paintWrapper.Paint.Shader = shader;
+ }
+ }
+ else
+ {
+ // when the origin is different to the center use a two point ConicalGradient to match the behaviour of D2D
+
+ // reverse the order of the stops to match D2D
+ var reversedColors = new SKColor[stopColors.Length];
+ Array.Copy(stopColors, reversedColors, stopColors.Length);
+ Array.Reverse(reversedColors);
+
+ // and then reverse the reference point of the stops
+ var reversedStops = new float[stopOffsets.Length];
+ for (var i = 0; i < stopOffsets.Length; i++)
+ {
+ reversedStops[i] = stopOffsets[i];
+ if (reversedStops[i] > 0 && reversedStops[i] < 1)
+ {
+ reversedStops[i] = Math.Abs(1 - stopOffsets[i]);
+ }
+ }
+
+ // compose with a background colour of the final stop to match D2D's behaviour of filling with the final color
+ using (var shader = SKShader.CreateCompose(
+ SKShader.CreateColor(reversedColors[0]),
+ SKShader.CreateTwoPointConicalGradient(center, radius, origin, 0, reversedColors, reversedStops, tileMode)
+ ))
+ {
+ paintWrapper.Paint.Shader = shader;
+ }
+ }
+
+ break;
+ }
+ case IConicGradientBrush conicGradient:
+ {
+ var center = conicGradient.Center.ToPixels(targetSize).ToSKPoint();
+
+ // Skia's default is that angle 0 is from the right hand side of the center point
+ // but we are matching CSS where the vertical point above the center is 0.
+ var angle = (float)(conicGradient.Angle - 90);
+ var rotation = SKMatrix.CreateRotationDegrees(angle, center.X, center.Y);
+
+ using (var shader =
+ SKShader.CreateSweepGradient(center, stopColors, stopOffsets, rotation))
{
paintWrapper.Paint.Shader = shader;
}
@@ -608,7 +673,7 @@ namespace Avalonia.Skia
private void ConfigureTileBrush(ref PaintWrapper paintWrapper, Size targetSize, ITileBrush tileBrush, IDrawableBitmapImpl tileBrushImage)
{
var calc = new TileBrushCalculator(tileBrush, tileBrushImage.PixelSize.ToSizeWithDpi(_dpi), targetSize);
- var intermediate = CreateRenderTarget(calc.IntermediateSize);
+ var intermediate = CreateRenderTarget(calc.IntermediateSize, false);
paintWrapper.AddDisposable(intermediate);
@@ -683,7 +748,7 @@ namespace Avalonia.Skia
if (intermediateSize.Width >= 1 && intermediateSize.Height >= 1)
{
- var intermediate = CreateRenderTarget(intermediateSize);
+ var intermediate = CreateRenderTarget(intermediateSize, false);
using (var ctx = intermediate.CreateDrawingContext(visualBrushRenderer))
{
@@ -913,9 +978,10 @@ namespace Avalonia.Skia
/// Create new render target compatible with this drawing context.
///
/// The size of the render target in DIPs.
+ /// Whether the render target is being created for a layer.
/// Pixel format.
///
- private SurfaceRenderTarget CreateRenderTarget(Size size, PixelFormat? format = null)
+ private SurfaceRenderTarget CreateRenderTarget(Size size, bool isLayer, PixelFormat? format = null)
{
var pixelSize = PixelSize.FromSizeWithDpi(size, _dpi);
var createInfo = new SurfaceRenderTarget.CreateInfo
@@ -925,7 +991,10 @@ namespace Avalonia.Skia
Dpi = _dpi,
Format = format,
DisableTextLcdRendering = !_canTextUseLcdRendering,
- GrContext = _grContext
+ GrContext = _grContext,
+ Gpu = _gpu,
+ Session = _session,
+ DisableManualFbo = !isLayer,
};
return new SurfaceRenderTarget(createInfo);
diff --git a/src/Skia/Avalonia.Skia/GlyphTypefaceImpl.cs b/src/Skia/Avalonia.Skia/GlyphTypefaceImpl.cs
index 5571bd890d..ceccc481f9 100644
--- a/src/Skia/Avalonia.Skia/GlyphTypefaceImpl.cs
+++ b/src/Skia/Avalonia.Skia/GlyphTypefaceImpl.cs
@@ -1,6 +1,5 @@
using System;
using System.Runtime.InteropServices;
-using Avalonia.Media;
using Avalonia.Platform;
using HarfBuzzSharp;
using SkiaSharp;
@@ -24,40 +23,33 @@ namespace Avalonia.Skia
Font.SetFunctionsOpenType();
- Font.GetScale(out var xScale, out _);
+ DesignEmHeight = (short)Typeface.UnitsPerEm;
- DesignEmHeight = (short)xScale;
+ var metrics = Typeface.ToFont().Metrics;
- if (!Font.TryGetHorizontalFontExtents(out var fontExtents))
- {
- Font.TryGetVerticalFontExtents(out fontExtents);
- }
+ const double defaultFontRenderingEmSize = 12.0;
- Ascent = -fontExtents.Ascender;
+ Ascent = (int)(metrics.Ascent / defaultFontRenderingEmSize * Typeface.UnitsPerEm);
- Descent = -fontExtents.Descender;
+ Descent = (int)(metrics.Descent / defaultFontRenderingEmSize * Typeface.UnitsPerEm);
- LineGap = fontExtents.LineGap;
+ LineGap = (int)(metrics.Leading / defaultFontRenderingEmSize * Typeface.UnitsPerEm);
- if (Font.OpenTypeMetrics.TryGetPosition(OpenTypeMetricsTag.UnderlineOffset, out var underlinePosition))
- {
- UnderlinePosition = underlinePosition;
- }
+ UnderlinePosition = metrics.UnderlinePosition != null ?
+ (int)(metrics.UnderlinePosition / defaultFontRenderingEmSize * Typeface.UnitsPerEm) :
+ 0;
- if (Font.OpenTypeMetrics.TryGetPosition(OpenTypeMetricsTag.UnderlineSize, out var underlineThickness))
- {
- UnderlineThickness = underlineThickness;
- }
+ UnderlineThickness = metrics.UnderlineThickness != null ?
+ (int)(metrics.UnderlineThickness / defaultFontRenderingEmSize * Typeface.UnitsPerEm) :
+ 0;
- if (Font.OpenTypeMetrics.TryGetPosition(OpenTypeMetricsTag.StrikeoutOffset, out var strikethroughPosition))
- {
- StrikethroughPosition = strikethroughPosition;
- }
+ StrikethroughPosition = metrics.StrikeoutPosition != null ?
+ (int)(metrics.StrikeoutPosition / defaultFontRenderingEmSize * Typeface.UnitsPerEm) :
+ 0;
- if (Font.OpenTypeMetrics.TryGetPosition(OpenTypeMetricsTag.StrikeoutSize, out var strikethroughThickness))
- {
- StrikethroughThickness = strikethroughThickness;
- }
+ StrikethroughThickness = metrics.StrikeoutThickness != null ?
+ (int)(metrics.StrikeoutThickness / defaultFontRenderingEmSize * Typeface.UnitsPerEm) :
+ 0;
IsFixedPitch = Typeface.IsFixedPitch;
}
diff --git a/src/Skia/Avalonia.Skia/Gpu/ISkiaGpu.cs b/src/Skia/Avalonia.Skia/Gpu/ISkiaGpu.cs
index 1a7a9b75cf..aa86df7c23 100644
--- a/src/Skia/Avalonia.Skia/Gpu/ISkiaGpu.cs
+++ b/src/Skia/Avalonia.Skia/Gpu/ISkiaGpu.cs
@@ -1,3 +1,4 @@
+using System;
using System.Collections.Generic;
using Avalonia.OpenGL.Imaging;
using SkiaSharp;
@@ -15,6 +16,19 @@ namespace Avalonia.Skia
/// Surfaces.
/// Created render target or if it fails.
ISkiaGpuRenderTarget TryCreateRenderTarget(IEnumerable surfaces);
+
+ ///
+ /// Creates an offscreen render target surface
+ ///
+ /// size in pixels
+ ISkiaSurface TryCreateSurface(PixelSize size, ISkiaGpuRenderSession session);
+ }
+
+ public interface ISkiaSurface : IDisposable
+ {
+ SKSurface Surface { get; }
+ bool CanBlit { get; }
+ void Blit(SKCanvas canvas);
}
public interface IOpenGlAwareSkiaGpu : ISkiaGpu
diff --git a/src/Skia/Avalonia.Skia/Gpu/ISkiaGpuRenderSession.cs b/src/Skia/Avalonia.Skia/Gpu/ISkiaGpuRenderSession.cs
index a4e2bfed52..5faa6a41ec 100644
--- a/src/Skia/Avalonia.Skia/Gpu/ISkiaGpuRenderSession.cs
+++ b/src/Skia/Avalonia.Skia/Gpu/ISkiaGpuRenderSession.cs
@@ -22,5 +22,7 @@ namespace Avalonia.Skia
/// Scaling factor.
///
double ScaleFactor { get; }
+
+ GRSurfaceOrigin SurfaceOrigin { get; }
}
}
diff --git a/src/Skia/Avalonia.Skia/Gpu/OpenGl/FboSkiaSurface.cs b/src/Skia/Avalonia.Skia/Gpu/OpenGl/FboSkiaSurface.cs
new file mode 100644
index 0000000000..8ab275df63
--- /dev/null
+++ b/src/Skia/Avalonia.Skia/Gpu/OpenGl/FboSkiaSurface.cs
@@ -0,0 +1,134 @@
+using System;
+using Avalonia.OpenGL;
+using SkiaSharp;
+using static Avalonia.OpenGL.GlConsts;
+namespace Avalonia.Skia
+{
+ public class FboSkiaSurface : ISkiaSurface
+ {
+ private readonly GRContext _grContext;
+ private readonly IGlContext _glContext;
+ private readonly PixelSize _pixelSize;
+ private int _fbo;
+ private int _depthStencil;
+ private int _texture;
+
+ private static readonly bool[] TrueFalse = new[] { true, false };
+ public FboSkiaSurface(GRContext grContext, IGlContext glContext, PixelSize pixelSize, GRSurfaceOrigin surfaceOrigin)
+ {
+ _grContext = grContext;
+ _glContext = glContext;
+ _pixelSize = pixelSize;
+ var InternalFormat = glContext.Version.Type == GlProfileType.OpenGLES ? GL_RGBA : GL_RGBA8;
+ var gl = glContext.GlInterface;
+
+ // Save old bindings
+ gl.GetIntegerv(GL_FRAMEBUFFER_BINDING, out var oldFbo);
+ gl.GetIntegerv(GL_RENDERBUFFER_BINDING, out var oldRenderbuffer);
+ gl.GetIntegerv(GL_TEXTURE_BINDING_2D, out var oldTexture);
+
+ var arr = new int[2];
+
+ // Generate FBO
+ gl.GenFramebuffers(1, arr);
+ _fbo = arr[0];
+ gl.BindFramebuffer(GL_FRAMEBUFFER, _fbo);
+
+ // Create a texture to render into
+ gl.GenTextures(1, arr);
+ _texture = arr[0];
+ gl.BindTexture(GL_TEXTURE_2D, _texture);
+ gl.TexImage2D(GL_TEXTURE_2D, 0,
+ InternalFormat, pixelSize.Width, pixelSize.Height,
+ 0, GL_RGBA, GL_UNSIGNED_BYTE, IntPtr.Zero);
+ gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ gl.FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _texture, 0);
+
+ var success = false;
+ foreach (var useStencil8 in TrueFalse)
+ {
+ gl.GenRenderbuffers(1, arr);
+ _depthStencil = arr[0];
+ gl.BindRenderbuffer(GL_RENDERBUFFER, _depthStencil);
+
+ if (useStencil8)
+ {
+ gl.RenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, pixelSize.Width, pixelSize.Height);
+ gl.FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _depthStencil);
+ }
+ else
+ {
+ gl.RenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, pixelSize.Width, pixelSize.Height);
+ gl.FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthStencil);
+ gl.FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _depthStencil);
+ }
+
+ var status = gl.CheckFramebufferStatus(GL_FRAMEBUFFER);
+ if (status == GL_FRAMEBUFFER_COMPLETE)
+ {
+ success = true;
+ break;
+ }
+ else
+ {
+ gl.BindRenderbuffer(GL_RENDERBUFFER, oldRenderbuffer);
+ gl.DeleteRenderbuffers(1, arr);
+ }
+ }
+
+ gl.BindRenderbuffer(GL_RENDERBUFFER, oldRenderbuffer);
+ gl.BindTexture(GL_TEXTURE_2D, oldTexture);
+ gl.BindFramebuffer(GL_FRAMEBUFFER, oldFbo);
+
+ if (!success)
+ {
+ arr[0] = _fbo;
+ gl.DeleteFramebuffers(1, arr);
+ arr[0] = _texture;
+ gl.DeleteTextures(1, arr);
+ throw new OpenGlException("Unable to create FBO with stencil");
+ }
+
+ var target = new GRBackendRenderTarget(pixelSize.Width, pixelSize.Height, 0, 8,
+ new GRGlFramebufferInfo((uint)_fbo, SKColorType.Rgba8888.ToGlSizedFormat()));
+ Surface = SKSurface.Create(_grContext, target,
+ surfaceOrigin, SKColorType.Rgba8888);
+ CanBlit = gl.BlitFramebuffer != null;
+ }
+
+ public void Dispose()
+ {
+ using (_glContext.EnsureCurrent())
+ {
+ Surface?.Dispose();
+ Surface = null;
+ var gl = _glContext.GlInterface;
+ if (_fbo != 0)
+ {
+ gl.DeleteFramebuffers(1, new[] { _fbo });
+ gl.DeleteTextures(1, new[] { _texture });
+ gl.DeleteRenderbuffers(1, new[] { _depthStencil });
+ _fbo = _texture = _depthStencil = 0;
+ }
+ }
+ }
+
+ public SKSurface Surface { get; private set; }
+ public bool CanBlit { get; }
+ public void Blit(SKCanvas canvas)
+ {
+ // This should set the render target as the current FBO
+ // which is definitely not the best method, but it works
+ canvas.Clear();
+ canvas.Flush();
+
+ var gl = _glContext.GlInterface;
+ gl.GetIntegerv(GL_READ_FRAMEBUFFER_BINDING, out var oldRead);
+ gl.BindFramebuffer(GL_READ_FRAMEBUFFER, _fbo);
+ gl.BlitFramebuffer(0, 0, _pixelSize.Width, _pixelSize.Height, 0, 0, _pixelSize.Width, _pixelSize.Height,
+ GL_COLOR_BUFFER_BIT, GL_LINEAR);
+ gl.BindFramebuffer(GL_READ_FRAMEBUFFER, oldRead);
+ }
+ }
+}
diff --git a/src/Skia/Avalonia.Skia/Gpu/OpenGl/GlRenderTarget.cs b/src/Skia/Avalonia.Skia/Gpu/OpenGl/GlRenderTarget.cs
index 6df8df9a4c..b4c5619c85 100644
--- a/src/Skia/Avalonia.Skia/Gpu/OpenGl/GlRenderTarget.cs
+++ b/src/Skia/Avalonia.Skia/Gpu/OpenGl/GlRenderTarget.cs
@@ -39,6 +39,8 @@ namespace Avalonia.Skia
_backendRenderTarget = backendRenderTarget;
_surface = surface;
_glSession = glSession;
+
+ SurfaceOrigin = glSession.IsYFlipped ? GRSurfaceOrigin.TopLeft : GRSurfaceOrigin.BottomLeft;
}
public void Dispose()
{
@@ -48,6 +50,8 @@ namespace Avalonia.Skia
GrContext.Flush();
_glSession.Dispose();
}
+
+ public GRSurfaceOrigin SurfaceOrigin { get; }
public GRContext GrContext { get; }
public SKSurface SkSurface => _surface;
@@ -73,10 +77,6 @@ namespace Avalonia.Skia
$"Can't create drawing context for surface with {size} size and {scaling} scaling");
}
- gl.Viewport(0, 0, size.Width, size.Height);
- gl.ClearStencil(0);
- gl.ClearColor(0, 0, 0, 0);
- gl.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
lock (_grContext)
{
_grContext.ResetContext();
@@ -89,6 +89,7 @@ namespace Avalonia.Skia
SKColorType.Rgba8888);
success = true;
+
return new GlGpuSession(_grContext, renderTarget, surface, glSession);
}
}
diff --git a/src/Skia/Avalonia.Skia/Gpu/OpenGl/GlSkiaGpu.cs b/src/Skia/Avalonia.Skia/Gpu/OpenGl/GlSkiaGpu.cs
index 46d42dfdab..a393f0b64d 100644
--- a/src/Skia/Avalonia.Skia/Gpu/OpenGl/GlSkiaGpu.cs
+++ b/src/Skia/Avalonia.Skia/Gpu/OpenGl/GlSkiaGpu.cs
@@ -1,4 +1,7 @@
+using System;
using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using Avalonia.Logging;
using Avalonia.OpenGL;
using Avalonia.OpenGL.Imaging;
using Avalonia.OpenGL.Surfaces;
@@ -10,6 +13,7 @@ namespace Avalonia.Skia
{
private GRContext _grContext;
private IGlContext _glContext;
+ private bool? _canCreateSurfaces;
public GlSkiaGpu(IPlatformOpenGlInterface openGl, long? maxResourceBytes)
{
@@ -43,6 +47,34 @@ namespace Avalonia.Skia
return null;
}
+ public ISkiaSurface TryCreateSurface(PixelSize size, ISkiaGpuRenderSession session)
+ {
+ // Only windows platform needs our FBO trickery
+ if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ return null;
+
+ // Blit feature requires glBlitFramebuffer
+ if (_glContext.GlInterface.BlitFramebuffer == null)
+ return null;
+
+ size = new PixelSize(Math.Max(size.Width, 1), Math.Max(size.Height, 1));
+ if (_canCreateSurfaces == false)
+ return null;
+ try
+ {
+ var surface = new FboSkiaSurface(_grContext, _glContext, size, session?.SurfaceOrigin ?? GRSurfaceOrigin.TopLeft);
+ _canCreateSurfaces = true;
+ return surface;
+ }
+ catch (Exception e)
+ {
+ Logger.TryGet(LogEventLevel.Error, "OpenGL")
+ ?.Log(this, "Unable to create a Skia-compatible FBO manually");
+ _canCreateSurfaces ??= false;
+ return null;
+ }
+ }
+
public IOpenGlBitmapImpl CreateOpenGlBitmap(PixelSize size, Vector dpi) => new GlOpenGlBitmapImpl(_glContext, size, dpi);
}
}
diff --git a/src/Skia/Avalonia.Skia/Gpu/SkiaGpuRenderTarget.cs b/src/Skia/Avalonia.Skia/Gpu/SkiaGpuRenderTarget.cs
index ef5da5eb08..6626546c0c 100644
--- a/src/Skia/Avalonia.Skia/Gpu/SkiaGpuRenderTarget.cs
+++ b/src/Skia/Avalonia.Skia/Gpu/SkiaGpuRenderTarget.cs
@@ -8,10 +8,12 @@ namespace Avalonia.Skia
///
internal class SkiaGpuRenderTarget : IRenderTargetWithCorruptionInfo
{
+ private readonly ISkiaGpu _skiaGpu;
private readonly ISkiaGpuRenderTarget _renderTarget;
- public SkiaGpuRenderTarget(ISkiaGpuRenderTarget renderTarget)
+ public SkiaGpuRenderTarget(ISkiaGpu skiaGpu, ISkiaGpuRenderTarget renderTarget)
{
+ _skiaGpu = skiaGpu;
_renderTarget = renderTarget;
}
@@ -30,7 +32,9 @@ namespace Avalonia.Skia
Surface = session.SkSurface,
Dpi = SkiaPlatform.DefaultDpi * session.ScaleFactor,
VisualBrushRenderer = visualBrushRenderer,
- DisableTextLcdRendering = true
+ DisableTextLcdRendering = true,
+ Gpu = _skiaGpu,
+ CurrentSession = session
};
return new DrawingContextImpl(nfo, session);
diff --git a/src/Skia/Avalonia.Skia/Helpers/DrawingContextHelper.cs b/src/Skia/Avalonia.Skia/Helpers/DrawingContextHelper.cs
new file mode 100644
index 0000000000..72438609d5
--- /dev/null
+++ b/src/Skia/Avalonia.Skia/Helpers/DrawingContextHelper.cs
@@ -0,0 +1,31 @@
+using Avalonia.Platform;
+using Avalonia.Rendering;
+using SkiaSharp;
+
+namespace Avalonia.Skia.Helpers
+{
+ public class DrawingContextHelper
+ {
+ ///
+ /// Wrap Skia canvas in drawing context so we can use Avalonia api to render to external skia canvas
+ /// this is useful in scenarios where canvas is not controlled by application, but received from another non avalonia api
+ /// like: SKCanvas canvas = SKDocument.BeginPage(...);
+ ///
+ ///
+ ///
+ ///
+ /// DrawingContext
+ public static IDrawingContextImpl WrapSkiaCanvas(SKCanvas canvas, Vector dpi, IVisualBrushRenderer visualBrushRenderer = null)
+ {
+ var createInfo = new DrawingContextImpl.CreateInfo
+ {
+ Canvas = canvas,
+ Dpi = dpi,
+ VisualBrushRenderer = visualBrushRenderer,
+ DisableTextLcdRendering = true,
+ };
+
+ return new DrawingContextImpl(createInfo);
+ }
+ }
+}
diff --git a/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs b/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs
index b9c1cbc673..6d0be9f64d 100644
--- a/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs
+++ b/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs
@@ -3,6 +3,8 @@ using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using System.Threading;
+
using Avalonia.Controls.Platform.Surfaces;
using Avalonia.Media;
using Avalonia.OpenGL;
@@ -124,7 +126,8 @@ namespace Avalonia.Skia
Width = size.Width,
Height = size.Height,
Dpi = dpi,
- DisableTextLcdRendering = false
+ DisableTextLcdRendering = false,
+ DisableManualFbo = true,
};
return new SurfaceRenderTarget(createInfo);
@@ -138,7 +141,7 @@ namespace Avalonia.Skia
var gpuRenderTarget = _skiaGpu?.TryCreateRenderTarget(surfaces);
if (gpuRenderTarget != null)
{
- return new SkiaGpuRenderTarget(gpuRenderTarget);
+ return new SkiaGpuRenderTarget(_skiaGpu, gpuRenderTarget);
}
foreach (var surface in surfaces)
@@ -165,12 +168,13 @@ namespace Avalonia.Skia
LinearMetrics = true
};
- private static readonly SKTextBlobBuilder s_textBlobBuilder = new SKTextBlobBuilder();
+ private static readonly ThreadLocal s_textBlobBuilderThreadLocal = new ThreadLocal(() => new SKTextBlobBuilder());
///
public IGlyphRunImpl CreateGlyphRun(GlyphRun glyphRun, out double width)
{
var count = glyphRun.GlyphIndices.Length;
+ var textBlobBuilder = s_textBlobBuilderThreadLocal.Value;
var glyphTypeface = (GlyphTypefaceImpl)glyphRun.GlyphTypeface.PlatformImpl;
@@ -190,15 +194,15 @@ namespace Avalonia.Skia
{
if (glyphTypeface.IsFixedPitch)
{
- s_textBlobBuilder.AddRun(glyphRun.GlyphIndices.Buffer.Span, s_font);
+ textBlobBuilder.AddRun(glyphRun.GlyphIndices.Buffer.Span, s_font);
- textBlob = s_textBlobBuilder.Build();
+ textBlob = textBlobBuilder.Build();
width = glyphTypeface.GetGlyphAdvance(glyphRun.GlyphIndices[0]) * scale * glyphRun.GlyphIndices.Length;
}
else
{
- var buffer = s_textBlobBuilder.AllocateHorizontalRun(s_font, count, 0);
+ var buffer = textBlobBuilder.AllocateHorizontalRun(s_font, count, 0);
var positions = buffer.GetPositionSpan();
@@ -218,12 +222,12 @@ namespace Avalonia.Skia
buffer.SetGlyphs(glyphRun.GlyphIndices.Buffer.Span);
- textBlob = s_textBlobBuilder.Build();
+ textBlob = textBlobBuilder.Build();
}
}
else
{
- var buffer = s_textBlobBuilder.AllocatePositionedRun(s_font, count);
+ var buffer = textBlobBuilder.AllocatePositionedRun(s_font, count);
var glyphPositions = buffer.GetPositionSpan();
@@ -249,7 +253,7 @@ namespace Avalonia.Skia
width = currentX;
- textBlob = s_textBlobBuilder.Build();
+ textBlob = textBlobBuilder.Build();
}
return new GlyphRunImpl(textBlob);
diff --git a/src/Skia/Avalonia.Skia/Properties/AssemblyInfo.cs b/src/Skia/Avalonia.Skia/Properties/AssemblyInfo.cs
index f6aabfae39..309129ccd9 100644
--- a/src/Skia/Avalonia.Skia/Properties/AssemblyInfo.cs
+++ b/src/Skia/Avalonia.Skia/Properties/AssemblyInfo.cs
@@ -1,4 +1,8 @@
using System.Runtime.CompilerServices;
-
+#if SIGNED_BUILD
+[assembly: InternalsVisibleTo("Avalonia.Skia.RenderTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")]
+[assembly: InternalsVisibleTo("Avalonia.Skia.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")]
+#else
[assembly: InternalsVisibleTo("Avalonia.Skia.RenderTests")]
[assembly: InternalsVisibleTo("Avalonia.Skia.UnitTests")]
+#endif
diff --git a/src/Skia/Avalonia.Skia/SurfaceRenderTarget.cs b/src/Skia/Avalonia.Skia/SurfaceRenderTarget.cs
index 428087ac56..01b7449b64 100644
--- a/src/Skia/Avalonia.Skia/SurfaceRenderTarget.cs
+++ b/src/Skia/Avalonia.Skia/SurfaceRenderTarget.cs
@@ -1,6 +1,7 @@
using System;
using System.IO;
using System.Reactive.Disposables;
+using Avalonia.Media;
using Avalonia.Platform;
using Avalonia.Rendering;
using Avalonia.Skia.Helpers;
@@ -11,12 +12,31 @@ namespace Avalonia.Skia
///
/// Skia render target that writes to a surface.
///
- internal class SurfaceRenderTarget : IRenderTargetBitmapImpl, IDrawableBitmapImpl
+ internal class SurfaceRenderTarget : IDrawingContextLayerImpl, IDrawableBitmapImpl
{
- private readonly SKSurface _surface;
+ private readonly ISkiaSurface _surface;
private readonly SKCanvas _canvas;
private readonly bool _disableLcdRendering;
private readonly GRContext _grContext;
+ private readonly ISkiaGpu _gpu;
+
+ class SkiaSurfaceWrapper : ISkiaSurface
+ {
+ public SKSurface Surface { get; private set; }
+ public bool CanBlit => false;
+ public void Blit(SKCanvas canvas) => throw new NotSupportedException();
+
+ public SkiaSurfaceWrapper(SKSurface surface)
+ {
+ Surface = surface;
+ }
+
+ public void Dispose()
+ {
+ Surface?.Dispose();
+ Surface = null;
+ }
+ }
///
/// Create new surface render target.
@@ -29,9 +49,15 @@ namespace Avalonia.Skia
_disableLcdRendering = createInfo.DisableTextLcdRendering;
_grContext = createInfo.GrContext;
- _surface = CreateSurface(createInfo.GrContext, PixelSize.Width, PixelSize.Height, createInfo.Format);
+ _gpu = createInfo.Gpu;
- _canvas = _surface?.Canvas;
+ if (!createInfo.DisableManualFbo)
+ _surface = _gpu?.TryCreateSurface(PixelSize, createInfo.Session);
+ if (_surface == null)
+ _surface = new SkiaSurfaceWrapper(CreateSurface(createInfo.GrContext, PixelSize.Width, PixelSize.Height,
+ createInfo.Format));
+
+ _canvas = _surface?.Surface.Canvas;
if (_surface == null || _canvas == null)
{
@@ -70,11 +96,12 @@ namespace Avalonia.Skia
var createInfo = new DrawingContextImpl.CreateInfo
{
- Surface = _surface,
+ Surface = _surface.Surface,
Dpi = Dpi,
VisualBrushRenderer = visualBrushRenderer,
DisableTextLcdRendering = _disableLcdRendering,
- GrContext = _grContext
+ GrContext = _grContext,
+ Gpu = _gpu,
};
return new DrawingContextImpl(createInfo, Disposable.Create(() => Version++));
@@ -106,19 +133,31 @@ namespace Avalonia.Skia
}
}
- ///
- public void Draw(DrawingContextImpl context, SKRect sourceRect, SKRect destRect, SKPaint paint)
+ public void Blit(IDrawingContextImpl contextImpl)
{
- if (sourceRect.Left == 0 && sourceRect.Top == 0 && sourceRect.Size == destRect.Size)
+ var context = (DrawingContextImpl)contextImpl;
+
+ if (_surface.CanBlit)
{
- _surface.Canvas.Flush();
- _surface.Draw(context.Canvas, destRect.Left, destRect.Top, paint);
+ _surface.Surface.Canvas.Flush();
+ _surface.Blit(context.Canvas);
}
else
- using (var image = SnapshotImage())
- {
- context.Canvas.DrawImage(image, sourceRect, destRect, paint);
- }
+ {
+ var oldMatrix = context.Canvas.TotalMatrix;
+ context.Canvas.ResetMatrix();
+ _surface.Surface.Draw(context.Canvas, 0, 0, null);
+ context.Canvas.SetMatrix(oldMatrix);
+ }
+ }
+
+ public bool CanBlit => true;
+
+ ///
+ public void Draw(DrawingContextImpl context, SKRect sourceRect, SKRect destRect, SKPaint paint)
+ {
+ using var image = SnapshotImage();
+ context.Canvas.DrawImage(image, sourceRect, destRect, paint);
}
///
@@ -127,7 +166,7 @@ namespace Avalonia.Skia
/// Image snapshot.
public SKImage SnapshotImage()
{
- return _surface.Snapshot();
+ return _surface.Surface.Snapshot();
}
///
@@ -178,6 +217,12 @@ namespace Avalonia.Skia
/// GPU-accelerated context (optional)
///
public GRContext GrContext;
+
+ public ISkiaGpu Gpu;
+
+ public ISkiaGpuRenderSession Session;
+
+ public bool DisableManualFbo;
}
}
}
diff --git a/src/Skia/Avalonia.Skia/TextShaperImpl.cs b/src/Skia/Avalonia.Skia/TextShaperImpl.cs
index 61075171fe..31724bfee9 100644
--- a/src/Skia/Avalonia.Skia/TextShaperImpl.cs
+++ b/src/Skia/Avalonia.Skia/TextShaperImpl.cs
@@ -64,7 +64,8 @@ namespace Avalonia.Skia
new ReadOnlySlice(glyphAdvances),
new ReadOnlySlice(glyphOffsets),
text,
- new ReadOnlySlice(clusters));
+ new ReadOnlySlice(clusters),
+ buffer.Direction == Direction.LeftToRight ? 0 : 1);
}
}
diff --git a/src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs b/src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs
index ae927d44a5..6ae27870e8 100644
--- a/src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs
+++ b/src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs
@@ -238,22 +238,46 @@ namespace Avalonia.Direct2D1
width = 0;
- for (var i = 0; i < glyphCount; i++)
+ var scale = (float)(glyphRun.FontRenderingEmSize / glyphTypeface.DesignEmHeight);
+
+ if (glyphRun.GlyphAdvances.IsEmpty)
+ {
+ for (var i = 0; i < glyphCount; i++)
+ {
+ var advance = glyphTypeface.GetGlyphAdvance(glyphRun.GlyphIndices[i]) * scale;
+
+ run.Advances[i] = advance;
+
+ width += advance;
+ }
+ }
+ else
+ {
+ for (var i = 0; i < glyphCount; i++)
+ {
+ var advance = (float)glyphRun.GlyphAdvances[i];
+
+ run.Advances[i] = advance;
+
+ width += advance;
+ }
+ }
+
+ if (glyphRun.GlyphOffsets.IsEmpty)
{
- run.Advances[i] = (float)glyphRun.GlyphAdvances[i];
- width += run.Advances[i];
+ return new GlyphRunImpl(run);
}
run.Offsets = new GlyphOffset[glyphCount];
for (var i = 0; i < glyphCount; i++)
{
- var offset = glyphRun.GlyphOffsets[i];
+ var (x, y) = glyphRun.GlyphOffsets[i];
run.Offsets[i] = new GlyphOffset
{
- AdvanceOffset = (float)offset.X,
- AscenderOffset = (float)offset.Y
+ AdvanceOffset = (float)x,
+ AscenderOffset = (float)y
};
}
diff --git a/src/Windows/Avalonia.Direct2D1/ExternalRenderTarget.cs b/src/Windows/Avalonia.Direct2D1/ExternalRenderTarget.cs
index aad50331d2..2c0adcac32 100644
--- a/src/Windows/Avalonia.Direct2D1/ExternalRenderTarget.cs
+++ b/src/Windows/Avalonia.Direct2D1/ExternalRenderTarget.cs
@@ -38,7 +38,7 @@ namespace Avalonia.Direct2D1
});
}
- public IRenderTargetBitmapImpl CreateLayer(Size size)
+ public IDrawingContextLayerImpl CreateLayer(Size size)
{
var renderTarget = _externalRenderTargetProvider.GetOrCreateRenderTarget();
return D2DRenderTargetBitmapImpl.CreateCompatible(renderTarget, size);
diff --git a/src/Windows/Avalonia.Direct2D1/ILayerFactory.cs b/src/Windows/Avalonia.Direct2D1/ILayerFactory.cs
index 08273f1bb2..a15bc0056a 100644
--- a/src/Windows/Avalonia.Direct2D1/ILayerFactory.cs
+++ b/src/Windows/Avalonia.Direct2D1/ILayerFactory.cs
@@ -4,6 +4,6 @@ namespace Avalonia.Direct2D1
{
public interface ILayerFactory
{
- IRenderTargetBitmapImpl CreateLayer(Size size);
+ IDrawingContextLayerImpl CreateLayer(Size size);
}
}
diff --git a/src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs b/src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs
index 258a51db5a..136ff63f3d 100644
--- a/src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs
+++ b/src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs
@@ -323,7 +323,6 @@ namespace Avalonia.Direct2D1.Media
///
/// The foreground.
/// The glyph run.
- ///
public void DrawGlyphRun(IBrush foreground, GlyphRun glyphRun)
{
using (var brush = CreateBrush(foreground, glyphRun.Size))
@@ -335,7 +334,7 @@ namespace Avalonia.Direct2D1.Media
}
}
- public IRenderTargetBitmapImpl CreateLayer(Size size)
+ public IDrawingContextLayerImpl CreateLayer(Size size)
{
if (_layerFactory != null)
{
@@ -346,7 +345,7 @@ namespace Avalonia.Direct2D1.Media
var platform = AvaloniaLocator.Current.GetService();
var dpi = new Vector(_deviceContext.DotsPerInch.Width, _deviceContext.DotsPerInch.Height);
var pixelSize = PixelSize.FromSizeWithDpi(size, dpi);
- return platform.CreateRenderTargetBitmap(pixelSize, dpi);
+ return (IDrawingContextLayerImpl)platform.CreateRenderTargetBitmap(pixelSize, dpi);
}
}
@@ -424,6 +423,7 @@ namespace Avalonia.Direct2D1.Media
var solidColorBrush = brush as ISolidColorBrush;
var linearGradientBrush = brush as ILinearGradientBrush;
var radialGradientBrush = brush as IRadialGradientBrush;
+ var conicGradientBrush = brush as IConicGradientBrush;
var imageBrush = brush as IImageBrush;
var visualBrush = brush as IVisualBrush;
@@ -439,6 +439,11 @@ namespace Avalonia.Direct2D1.Media
{
return new RadialGradientBrushImpl(radialGradientBrush, _deviceContext, destinationSize);
}
+ else if (conicGradientBrush != null)
+ {
+ // there is no Direct2D implementation of Conic Gradients so use Radial as a stand-in
+ return new SolidColorBrushImpl(conicGradientBrush, _deviceContext);
+ }
else if (imageBrush?.Source != null)
{
return new ImageBrushImpl(
diff --git a/src/Windows/Avalonia.Direct2D1/Media/Imaging/D2DRenderTargetBitmapImpl.cs b/src/Windows/Avalonia.Direct2D1/Media/Imaging/D2DRenderTargetBitmapImpl.cs
index 3a3f9a9f7d..9a0e2ec00c 100644
--- a/src/Windows/Avalonia.Direct2D1/Media/Imaging/D2DRenderTargetBitmapImpl.cs
+++ b/src/Windows/Avalonia.Direct2D1/Media/Imaging/D2DRenderTargetBitmapImpl.cs
@@ -1,4 +1,5 @@
-using System.IO;
+using System;
+using System.IO;
using Avalonia.Platform;
using Avalonia.Rendering;
using Avalonia.Utilities;
@@ -8,7 +9,7 @@ using D2DBitmap = SharpDX.Direct2D1.Bitmap;
namespace Avalonia.Direct2D1.Media.Imaging
{
- public class D2DRenderTargetBitmapImpl : D2DBitmapImpl, IRenderTargetBitmapImpl, ILayerFactory
+ public class D2DRenderTargetBitmapImpl : D2DBitmapImpl, IDrawingContextLayerImpl, ILayerFactory
{
private readonly BitmapRenderTarget _renderTarget;
@@ -34,7 +35,11 @@ namespace Avalonia.Direct2D1.Media.Imaging
return new DrawingContextImpl(visualBrushRenderer, this, _renderTarget, null, () => Version++);
}
- public IRenderTargetBitmapImpl CreateLayer(Size size)
+ public void Blit(IDrawingContextImpl context) => throw new NotSupportedException();
+
+ public bool CanBlit => false;
+
+ public IDrawingContextLayerImpl CreateLayer(Size size)
{
return CreateCompatible(_renderTarget, size);
}
diff --git a/src/Windows/Avalonia.Direct2D1/Media/Imaging/WicRenderTargetBitmapImpl.cs b/src/Windows/Avalonia.Direct2D1/Media/Imaging/WicRenderTargetBitmapImpl.cs
index e8e27f3f5d..1265a7bdf0 100644
--- a/src/Windows/Avalonia.Direct2D1/Media/Imaging/WicRenderTargetBitmapImpl.cs
+++ b/src/Windows/Avalonia.Direct2D1/Media/Imaging/WicRenderTargetBitmapImpl.cs
@@ -5,7 +5,7 @@ using SharpDX.Direct2D1;
namespace Avalonia.Direct2D1.Media
{
- public class WicRenderTargetBitmapImpl : WicBitmapImpl, IRenderTargetBitmapImpl
+ public class WicRenderTargetBitmapImpl : WicBitmapImpl, IDrawingContextLayerImpl
{
private readonly WicRenderTarget _renderTarget;
@@ -45,5 +45,8 @@ namespace Avalonia.Direct2D1.Media
finishedCallback?.Invoke();
});
}
+
+ public void Blit(IDrawingContextImpl context) => throw new NotSupportedException();
+ public bool CanBlit => false;
}
}
diff --git a/src/Windows/Avalonia.Direct2D1/Media/SolidColorBrushImpl.cs b/src/Windows/Avalonia.Direct2D1/Media/SolidColorBrushImpl.cs
index f93b4a2e08..fea1ca9157 100644
--- a/src/Windows/Avalonia.Direct2D1/Media/SolidColorBrushImpl.cs
+++ b/src/Windows/Avalonia.Direct2D1/Media/SolidColorBrushImpl.cs
@@ -16,5 +16,22 @@ namespace Avalonia.Direct2D1.Media
}
);
}
+
+ ///
+ /// Direct2D has no ConicGradient implementation so fall back to a solid colour brush based on
+ /// the first gradient stop.
+ ///
+ public SolidColorBrushImpl(IConicGradientBrush brush, SharpDX.Direct2D1.DeviceContext target)
+ {
+ PlatformBrush = new SharpDX.Direct2D1.SolidColorBrush(
+ target,
+ brush?.GradientStops[0].Color.ToDirect2D() ?? new SharpDX.Mathematics.Interop.RawColor4(),
+ new SharpDX.Direct2D1.BrushProperties
+ {
+ Opacity = brush != null ? (float)brush.Opacity : 1.0f,
+ Transform = target.Transform
+ }
+ );
+ }
}
}
diff --git a/src/Windows/Avalonia.Direct2D1/Media/TextShaperImpl.cs b/src/Windows/Avalonia.Direct2D1/Media/TextShaperImpl.cs
index 254b5684a4..20b09a9aac 100644
--- a/src/Windows/Avalonia.Direct2D1/Media/TextShaperImpl.cs
+++ b/src/Windows/Avalonia.Direct2D1/Media/TextShaperImpl.cs
@@ -1,6 +1,6 @@
-using System.Globalization;
+using System;
+using System.Globalization;
using Avalonia.Media;
-using Avalonia.Media.TextFormatting;
using Avalonia.Media.TextFormatting.Unicode;
using Avalonia.Platform;
using Avalonia.Utilities;
@@ -15,51 +15,9 @@ namespace Avalonia.Direct2D1.Media
{
using (var buffer = new Buffer())
{
- buffer.ContentType = ContentType.Unicode;
+ FillBuffer(buffer, text);
- var breakCharPosition = text.Length - 1;
-
- var codepoint = Codepoint.ReadAt(text, breakCharPosition, out var count);
-
- if (codepoint.IsBreakChar)
- {
- var breakCharCount = 1;
-
- if (text.Length > 1)
- {
- var previousCodepoint = Codepoint.ReadAt(text, breakCharPosition - count, out _);
-
- if (codepoint == '\r' && previousCodepoint == '\n'
- || codepoint == '\n' && previousCodepoint == '\r')
- {
- breakCharCount = 2;
- }
- }
-
- if (breakCharPosition != text.Start)
- {
- buffer.AddUtf16(text.Buffer.Span.Slice(0, text.Length - breakCharCount));
- }
-
- var cluster = buffer.GlyphInfos.Length > 0 ?
- buffer.GlyphInfos[buffer.Length - 1].Cluster + 1 :
- (uint)text.Start;
-
- switch (breakCharCount)
- {
- case 1:
- buffer.Add('\u200C', cluster);
- break;
- case 2:
- buffer.Add('\u200C', cluster);
- buffer.Add('\u200D', cluster);
- break;
- }
- }
- else
- {
- buffer.AddUtf16(text.Buffer.Span);
- }
+ buffer.Language = new Language(culture ?? CultureInfo.CurrentCulture);
buffer.GuessSegmentProperties();
@@ -67,44 +25,38 @@ namespace Avalonia.Direct2D1.Media
var font = ((GlyphTypefaceImpl)glyphTypeface.PlatformImpl).Font;
- buffer.Language = new Language(culture ?? CultureInfo.CurrentCulture);
-
font.Shape(buffer);
font.GetScale(out var scaleX, out _);
var textScale = fontRenderingEmSize / scaleX;
- var len = buffer.Length;
+ var bufferLength = buffer.Length;
- var info = buffer.GetGlyphInfoSpan();
+ var glyphInfos = buffer.GetGlyphInfoSpan();
- var pos = buffer.GetGlyphPositionSpan();
+ var glyphPositions = buffer.GetGlyphPositionSpan();
- var glyphIndices = new ushort[len];
+ var glyphIndices = new ushort[bufferLength];
- var clusters = new ushort[len];
+ var clusters = new ushort[bufferLength];
- var glyphAdvances = new double[len];
+ double[] glyphAdvances = null;
- var glyphOffsets = new Vector[len];
+ Vector[] glyphOffsets = null;
- for (var i = 0; i < len; i++)
+ for (var i = 0; i < bufferLength; i++)
{
- glyphIndices[i] = (ushort)info[i].Codepoint;
-
- clusters[i] = (ushort)(text.Start + info[i].Cluster);
-
- var advanceX = pos[i].XAdvance * textScale;
- // Depends on direction of layout
- //var advanceY = pos[i].YAdvance * textScale;
+ glyphIndices[i] = (ushort)glyphInfos[i].Codepoint;
- glyphAdvances[i] = advanceX;
+ clusters[i] = (ushort)glyphInfos[i].Cluster;
- var offsetX = pos[i].XOffset * textScale;
- var offsetY = pos[i].YOffset * textScale;
+ if (!glyphTypeface.IsFixedPitch)
+ {
+ SetAdvance(glyphPositions, i, textScale, ref glyphAdvances);
+ }
- glyphOffsets[i] = new Vector(offsetX, offsetY);
+ SetOffset(glyphPositions, i, textScale, ref glyphOffsets);
}
return new GlyphRun(glyphTypeface, fontRenderingEmSize,
@@ -115,5 +67,79 @@ namespace Avalonia.Direct2D1.Media
new ReadOnlySlice(clusters));
}
}
+
+ private static void FillBuffer(Buffer buffer, ReadOnlySlice text)
+ {
+ buffer.ContentType = ContentType.Unicode;
+
+ var i = 0;
+
+ while (i < text.Length)
+ {
+ var codepoint = Codepoint.ReadAt(text, i, out var count);
+
+ var cluster = (uint)(text.Start + i);
+
+ if (codepoint.IsBreakChar)
+ {
+ if (i + 1 < text.Length)
+ {
+ var nextCodepoint = Codepoint.ReadAt(text, i + 1, out _);
+
+ if (nextCodepoint == '\r' && codepoint == '\n' || nextCodepoint == '\n' && codepoint == '\r')
+ {
+ count++;
+
+ buffer.Add('\u200C', cluster);
+
+ buffer.Add('\u200D', cluster);
+ }
+ else
+ {
+ buffer.Add('\u200C', cluster);
+ }
+ }
+ else
+ {
+ buffer.Add('\u200C', cluster);
+ }
+ }
+ else
+ {
+ buffer.Add(codepoint, cluster);
+ }
+
+ i += count;
+ }
+ }
+
+ private static void SetOffset(ReadOnlySpan glyphPositions, int index, double textScale,
+ ref Vector[] offsetBuffer)
+ {
+ var position = glyphPositions[index];
+
+ if (position.XOffset == 0 && position.YOffset == 0)
+ {
+ return;
+ }
+
+ offsetBuffer ??= new Vector[glyphPositions.Length];
+
+ var offsetX = position.XOffset * textScale;
+
+ var offsetY = position.YOffset * textScale;
+
+ offsetBuffer[index] = new Vector(offsetX, offsetY);
+ }
+
+ private static void SetAdvance(ReadOnlySpan glyphPositions, int index, double textScale,
+ ref double[] advanceBuffer)
+ {
+ advanceBuffer ??= new double[glyphPositions.Length];
+
+ // Depends on direction of layout
+ // advanceBuffer[index] = buffer.GlyphPositions[index].YAdvance * textScale;
+ advanceBuffer[index] = glyphPositions[index].XAdvance * textScale;
+ }
}
}
diff --git a/src/Windows/Avalonia.Direct2D1/Properties/AssemblyInfo.cs b/src/Windows/Avalonia.Direct2D1/Properties/AssemblyInfo.cs
index 5d53fd4aae..6cc8b793c0 100644
--- a/src/Windows/Avalonia.Direct2D1/Properties/AssemblyInfo.cs
+++ b/src/Windows/Avalonia.Direct2D1/Properties/AssemblyInfo.cs
@@ -6,6 +6,10 @@ using Avalonia.Direct2D1;
[assembly: ExportRenderingSubsystem(OperatingSystemType.WinNT, 1, "Direct2D1", typeof(Direct2D1Platform), nameof(Direct2D1Platform.Initialize),
typeof(Direct2DChecker))]
+#if SIGNED_BUILD
+[assembly: InternalsVisibleTo("Avalonia.Direct2D1.RenderTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")]
+[assembly: InternalsVisibleTo("Avalonia.Direct2D1.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")]
+#else
[assembly: InternalsVisibleTo("Avalonia.Direct2D1.RenderTests")]
[assembly: InternalsVisibleTo("Avalonia.Direct2D1.UnitTests")]
-
+#endif
diff --git a/src/Windows/Avalonia.Direct2D1/RenderTarget.cs b/src/Windows/Avalonia.Direct2D1/RenderTarget.cs
index 4433c8d50a..d04c616bd9 100644
--- a/src/Windows/Avalonia.Direct2D1/RenderTarget.cs
+++ b/src/Windows/Avalonia.Direct2D1/RenderTarget.cs
@@ -30,7 +30,7 @@ namespace Avalonia.Direct2D1
return new DrawingContextImpl(visualBrushRenderer, this, _renderTarget);
}
- public IRenderTargetBitmapImpl CreateLayer(Size size)
+ public IDrawingContextLayerImpl CreateLayer(Size size)
{
return D2DRenderTargetBitmapImpl.CreateCompatible(_renderTarget, size);
}
diff --git a/src/Windows/Avalonia.Direct2D1/SwapChainRenderTarget.cs b/src/Windows/Avalonia.Direct2D1/SwapChainRenderTarget.cs
index 5f4d06dab0..f319cfae03 100644
--- a/src/Windows/Avalonia.Direct2D1/SwapChainRenderTarget.cs
+++ b/src/Windows/Avalonia.Direct2D1/SwapChainRenderTarget.cs
@@ -35,7 +35,7 @@ namespace Avalonia.Direct2D1
return new DrawingContextImpl(visualBrushRenderer, this, _deviceContext, _swapChain);
}
- public IRenderTargetBitmapImpl CreateLayer(Size size)
+ public IDrawingContextLayerImpl CreateLayer(Size size)
{
if (_deviceContext == null)
{
diff --git a/src/Windows/Avalonia.Win32.Interop/Avalonia.Win32.Interop.csproj b/src/Windows/Avalonia.Win32.Interop/Avalonia.Win32.Interop.csproj
index 0d0dd98a77..0e11ee3b92 100644
--- a/src/Windows/Avalonia.Win32.Interop/Avalonia.Win32.Interop.csproj
+++ b/src/Windows/Avalonia.Win32.Interop/Avalonia.Win32.Interop.csproj
@@ -2,7 +2,7 @@
net461
true
- true
+ true
true
true
Avalonia.Win32.Interoperability
diff --git a/src/Windows/Avalonia.Win32/.gitignore b/src/Windows/Avalonia.Win32/.gitignore
new file mode 100644
index 0000000000..7882fa6540
--- /dev/null
+++ b/src/Windows/Avalonia.Win32/.gitignore
@@ -0,0 +1 @@
+*.Generated.cs
diff --git a/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj b/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj
index 7fc24d4d3d..fe5f806fbe 100644
--- a/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj
+++ b/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj
@@ -5,8 +5,11 @@
Avalonia.Win32
+
-
+
+
+
diff --git a/src/Windows/Avalonia.Win32/ClipboardImpl.cs b/src/Windows/Avalonia.Win32/ClipboardImpl.cs
index 7d9e0a8bd2..047b7c361f 100644
--- a/src/Windows/Avalonia.Win32/ClipboardImpl.cs
+++ b/src/Windows/Avalonia.Win32/ClipboardImpl.cs
@@ -12,10 +12,17 @@ namespace Avalonia.Win32
{
internal class ClipboardImpl : IClipboard
{
+ private const int OleRetryCount = 10;
+ private const int OleRetryDelay = 100;
+
private async Task OpenClipboard()
{
+ var i = OleRetryCount;
+
while (!UnmanagedMethods.OpenClipboard(IntPtr.Zero))
{
+ if (--i == 0)
+ throw new TimeoutException("Timeout opening clipboard.");
await Task.Delay(100);
}
@@ -72,20 +79,32 @@ namespace Avalonia.Win32
{
Dispatcher.UIThread.VerifyAccess();
var wrapper = new DataObject(data);
+ var i = OleRetryCount;
+
while (true)
{
- if (UnmanagedMethods.OleSetClipboard(wrapper) == 0)
+ var hr = UnmanagedMethods.OleSetClipboard(wrapper);
+
+ if (hr == 0)
break;
- await Task.Delay(100);
+
+ if (--i == 0)
+ Marshal.ThrowExceptionForHR(hr);
+
+ await Task.Delay(OleRetryDelay);
}
}
public async Task GetFormatsAsync()
{
Dispatcher.UIThread.VerifyAccess();
+ var i = OleRetryCount;
+
while (true)
{
- if (UnmanagedMethods.OleGetClipboard(out var dataObject) == 0)
+ var hr = UnmanagedMethods.OleGetClipboard(out var dataObject);
+
+ if (hr == 0)
{
var wrapper = new OleDataObject(dataObject);
var formats = wrapper.GetDataFormats().ToArray();
@@ -93,16 +112,23 @@ namespace Avalonia.Win32
return formats;
}
- await Task.Delay(100);
+ if (--i == 0)
+ Marshal.ThrowExceptionForHR(hr);
+
+ await Task.Delay(OleRetryDelay);
}
}
public async Task GetDataAsync(string format)
{
Dispatcher.UIThread.VerifyAccess();
+ var i = OleRetryCount;
+
while (true)
{
- if (UnmanagedMethods.OleGetClipboard(out var dataObject) == 0)
+ var hr = UnmanagedMethods.OleGetClipboard(out var dataObject);
+
+ if (hr == 0)
{
var wrapper = new OleDataObject(dataObject);
var rv = wrapper.Get(format);
@@ -110,7 +136,10 @@ namespace Avalonia.Win32
return rv;
}
- await Task.Delay(100);
+ if (--i == 0)
+ Marshal.ThrowExceptionForHR(hr);
+
+ await Task.Delay(OleRetryDelay);
}
}
}
diff --git a/src/Windows/Avalonia.Win32/FramebufferManager.cs b/src/Windows/Avalonia.Win32/FramebufferManager.cs
index 6969a49dad..699dc7c25d 100644
--- a/src/Windows/Avalonia.Win32/FramebufferManager.cs
+++ b/src/Windows/Avalonia.Win32/FramebufferManager.cs
@@ -1,41 +1,191 @@
using System;
+using System.Threading;
using Avalonia.Controls.Platform.Surfaces;
using Avalonia.Platform;
using Avalonia.Win32.Interop;
+#nullable enable
+
namespace Avalonia.Win32
{
- class FramebufferManager : IFramebufferPlatformSurface, IDisposable
+ internal class FramebufferManager : IFramebufferPlatformSurface, IDisposable
{
+ private const int _bytesPerPixel = 4;
+ private const PixelFormat _format = PixelFormat.Bgra8888;
+
private readonly IntPtr _hwnd;
- private WindowFramebuffer _fb;
+ private readonly object _lock;
+ private readonly Action _onDisposeAction;
+
+ private FramebufferData? _framebufferData;
public FramebufferManager(IntPtr hwnd)
{
_hwnd = hwnd;
+ _lock = new object();
+ _onDisposeAction = DrawAndUnlock;
}
public ILockedFramebuffer Lock()
{
- UnmanagedMethods.GetClientRect(_hwnd, out var rc);
+ Monitor.Enter(_lock);
- var width = Math.Max(1, rc.right - rc.left);
- var height = Math.Max(1, rc.bottom - rc.top);
+ LockedFramebuffer? fb = null;
- if ((_fb == null || _fb.Size.Width != width || _fb.Size.Height != height))
+ try
{
- _fb?.Deallocate();
- _fb = null;
- _fb = new WindowFramebuffer(_hwnd, new PixelSize(width, height));
- }
+ UnmanagedMethods.GetClientRect(_hwnd, out var rc);
+
+ var width = Math.Max(1, rc.right - rc.left);
+ var height = Math.Max(1, rc.bottom - rc.top);
+
+ if (_framebufferData is null || _framebufferData?.Size.Width != width || _framebufferData?.Size.Height != height)
+ {
+ _framebufferData?.Dispose();
+
+ _framebufferData = AllocateFramebufferData(width, height);
+ }
+
+ var framebufferData = _framebufferData.Value;
- return _fb;
+ return fb = new LockedFramebuffer(
+ framebufferData.Data.Address, framebufferData.Size, framebufferData.RowBytes,
+ GetCurrentDpi(), _format, _onDisposeAction);
+ }
+ finally
+ {
+ // We free the lock when for whatever reason framebuffer was not created.
+ // This allows for a potential retry later.
+ if (fb is null)
+ {
+ Monitor.Exit(_lock);
+ }
+ }
}
public void Dispose()
{
- _fb?.Deallocate();
- _fb = null;
+ lock (_lock)
+ {
+ _framebufferData?.Dispose();
+ _framebufferData = null;
+ }
+ }
+
+ private void DrawAndUnlock()
+ {
+ try
+ {
+ if (_framebufferData.HasValue)
+ DrawToWindow(_hwnd, _framebufferData.Value);
+ }
+ finally
+ {
+ Monitor.Exit(_lock);
+ }
+ }
+
+ private Vector GetCurrentDpi()
+ {
+ if (UnmanagedMethods.ShCoreAvailable)
+ {
+ var monitor =
+ UnmanagedMethods.MonitorFromWindow(_hwnd, UnmanagedMethods.MONITOR.MONITOR_DEFAULTTONEAREST);
+
+ if (UnmanagedMethods.GetDpiForMonitor(
+ monitor,
+ UnmanagedMethods.MONITOR_DPI_TYPE.MDT_EFFECTIVE_DPI,
+ out var dpix,
+ out var dpiy) == 0)
+ {
+ return new Vector(dpix, dpiy);
+ }
+ }
+
+ return new Vector(96, 96);
+ }
+
+ private static FramebufferData AllocateFramebufferData(int width, int height)
+ {
+ var bitmapBlob = AvaloniaLocator.Current.GetService().AllocBlob(width * height * _bytesPerPixel);
+
+ return new FramebufferData(bitmapBlob, width, height);
+ }
+
+ private static void DrawToDevice(FramebufferData framebufferData, IntPtr hDC, int destX = 0, int destY = 0, int srcX = 0,
+ int srcY = 0, int width = -1,
+ int height = -1)
+ {
+ if (width == -1)
+ width = framebufferData.Size.Width;
+ if (height == -1)
+ height = framebufferData.Size.Height;
+
+ var bmpInfo = framebufferData.Header;
+
+ UnmanagedMethods.SetDIBitsToDevice(hDC, destX, destY, (uint)width, (uint)height, srcX, srcY,
+ 0, (uint)framebufferData.Size.Height, framebufferData.Data.Address, ref bmpInfo, 0);
+ }
+
+ private static bool DrawToWindow(IntPtr hWnd, FramebufferData framebufferData, int destX = 0, int destY = 0, int srcX = 0,
+ int srcY = 0, int width = -1,
+ int height = -1)
+ {
+ if (framebufferData.Data.IsDisposed)
+ throw new ObjectDisposedException("Framebuffer");
+
+ if (hWnd == IntPtr.Zero)
+ return false;
+
+ var hDC = UnmanagedMethods.GetDC(hWnd);
+
+ if (hDC == IntPtr.Zero)
+ return false;
+
+ try
+ {
+ DrawToDevice(framebufferData, hDC, destX, destY, srcX, srcY, width, height);
+ }
+ finally
+ {
+ UnmanagedMethods.ReleaseDC(hWnd, hDC);
+ }
+
+ return true;
+ }
+
+ private readonly struct FramebufferData
+ {
+ public IUnmanagedBlob Data { get; }
+
+ public PixelSize Size { get; }
+
+ public int RowBytes => Size.Width * _bytesPerPixel;
+
+ public UnmanagedMethods.BITMAPINFOHEADER Header { get; }
+
+ public FramebufferData(IUnmanagedBlob data, int width, int height)
+ {
+ Data = data;
+ Size = new PixelSize(width, height);
+
+ var header = new UnmanagedMethods.BITMAPINFOHEADER();
+ header.Init();
+
+ header.biPlanes = 1;
+ header.biBitCount = _bytesPerPixel * 8;
+ header.Init();
+
+ header.biWidth = width;
+ header.biHeight = -height;
+
+ Header = header;
+ }
+
+ public void Dispose()
+ {
+ Data.Dispose();
+ }
}
}
}
diff --git a/src/Windows/Avalonia.Win32/Interop/TaskBarList.cs b/src/Windows/Avalonia.Win32/Interop/TaskBarList.cs
index 1b01ebbe7f..88b907aeec 100644
--- a/src/Windows/Avalonia.Win32/Interop/TaskBarList.cs
+++ b/src/Windows/Avalonia.Win32/Interop/TaskBarList.cs
@@ -13,6 +13,7 @@ namespace Avalonia.Win32.Interop
///
/// Ported from https://github.com/chromium/chromium/blob/master/ui/views/win/fullscreen_handler.cc
///
+ /// The window handle.
/// Fullscreen state.
public static unsafe void MarkFullscreen(IntPtr hwnd, bool fullscreen)
{
diff --git a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs
index b7c68c4b95..b21741453c 100644
--- a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs
+++ b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs
@@ -466,6 +466,7 @@ namespace Avalonia.Win32.Interop
WS_VSCROLL = 0x200000,
WS_EX_DLGMODALFRAME = 0x00000001,
WS_EX_NOPARENTNOTIFY = 0x00000004,
+ WS_EX_NOREDIRECTIONBITMAP = 0x00200000,
WS_EX_TOPMOST = 0x00000008,
WS_EX_ACCEPTFILES = 0x00000010,
WS_EX_TRANSPARENT = 0x00000020,
@@ -930,8 +931,8 @@ namespace Avalonia.Win32.Interop
[DllImport("user32.dll", EntryPoint = "MapVirtualKeyW")]
public static extern uint MapVirtualKey(uint uCode, uint uMapType);
- [DllImport("user32.dll", EntryPoint = "GetMessageW")]
- public static extern sbyte GetMessage(out MSG lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax);
+ [DllImport("user32.dll", EntryPoint = "GetMessageW", SetLastError = true)]
+ public static extern int GetMessage(out MSG lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax);
[DllImport("user32.dll")]
public static extern int GetMessageTime();
@@ -1011,7 +1012,14 @@ namespace Avalonia.Win32.Interop
[DllImport("user32.dll")]
public static extern bool InvalidateRect(IntPtr hWnd, RECT* lpRect, bool bErase);
+
+
+ [DllImport("user32.dll")]
+ public static extern bool ValidateRect(IntPtr hWnd, IntPtr lpRect);
+ [DllImport("user32.dll")]
+ public static extern bool IsWindow(IntPtr hWnd);
+
[DllImport("user32.dll")]
public static extern bool IsWindowEnabled(IntPtr hWnd);
@@ -1045,6 +1053,9 @@ namespace Avalonia.Win32.Interop
[DllImport("user32.dll")]
public static extern bool ScreenToClient(IntPtr hWnd, ref POINT lpPoint);
+ [DllImport("user32.dll", SetLastError = true)]
+ public static extern IntPtr GetActiveWindow();
+
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr SetActiveWindow(IntPtr hWnd);
@@ -1214,6 +1225,9 @@ namespace Avalonia.Win32.Interop
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr LoadLibrary(string fileName);
+
+ [DllImport("kernel32.dll", SetLastError = true)]
+ public static extern IntPtr LoadLibraryEx(string fileName, IntPtr hFile, int flags);
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Ansi)]
public static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
@@ -1292,6 +1306,41 @@ namespace Avalonia.Win32.Interop
[DllImport("gdi32.dll")]
public static extern IntPtr SelectObject(IntPtr hdc, IntPtr hObject);
+ [DllImport("gdi32.dll")]
+ public static extern int ChoosePixelFormat(IntPtr hdc, ref PixelFormatDescriptor pfd);
+
+ [DllImport("gdi32.dll")]
+ public static extern int DescribePixelFormat(IntPtr hdc, ref PixelFormatDescriptor pfd);
+
+ [DllImport("gdi32.dll")]
+ public static extern int SetPixelFormat(IntPtr hdc, int iPixelFormat, ref PixelFormatDescriptor pfd);
+
+
+ [DllImport("gdi32.dll")]
+ public static extern int DescribePixelFormat(IntPtr hdc, int iPixelFormat, int bytes, ref PixelFormatDescriptor pfd);
+
+ [DllImport("gdi32.dll")]
+ public static extern bool SwapBuffers(IntPtr hdc);
+
+ [DllImport("opengl32.dll")]
+ public static extern IntPtr wglCreateContext(IntPtr hdc);
+
+ [DllImport("opengl32.dll")]
+ public static extern bool wglDeleteContext(IntPtr context);
+
+
+ [DllImport("opengl32.dll")]
+ public static extern bool wglMakeCurrent(IntPtr hdc, IntPtr context);
+
+ [DllImport("opengl32.dll")]
+ public static extern IntPtr wglGetCurrentContext();
+
+ [DllImport("opengl32.dll")]
+ public static extern IntPtr wglGetCurrentDC();
+
+ [DllImport("opengl32.dll", CharSet = CharSet.Ansi)]
+ public static extern IntPtr wglGetProcAddress(string name);
+
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr CreateFileMapping(IntPtr hFile,
IntPtr lpFileMappingAttributes,
@@ -1336,6 +1385,9 @@ namespace Avalonia.Win32.Interop
[DllImport("dwmapi.dll")]
public static extern int DwmIsCompositionEnabled(out bool enabled);
+ [DllImport("dwmapi.dll")]
+ public static extern void DwmFlush();
+
[DllImport("dwmapi.dll")]
public static extern bool DwmDefWindowProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam, ref IntPtr plResult);
@@ -1567,6 +1619,12 @@ namespace Avalonia.Win32.Interop
public int X;
public int Y;
}
+
+ public struct SIZE
+ {
+ public int X;
+ public int Y;
+ }
public struct RECT
{
@@ -2121,4 +2179,57 @@ namespace Avalonia.Win32.Interop
public bool fNC;
public bool fWide;
}
+
+ [Flags]
+ internal enum PixelFormatDescriptorFlags : uint
+ {
+ PFD_DOUBLEBUFFER = 0x00000001,
+ PFD_STEREO = 0x00000002,
+ PFD_DRAW_TO_WINDOW = 0x00000004,
+ PFD_DRAW_TO_BITMAP = 0x00000008,
+ PFD_SUPPORT_GDI = 0x00000010,
+ PFD_SUPPORT_OPENGL = 0x00000020,
+ PFD_GENERIC_FORMAT = 0x00000040,
+ PFD_NEED_PALETTE = 0x00000080,
+ PFD_NEED_SYSTEM_PALETTE = 0x00000100,
+ PFD_SWAP_EXCHANGE = 0x00000200,
+ PFD_SWAP_COPY = 0x00000400,
+ PFD_SWAP_LAYER_BUFFERS = 0x00000800,
+ PFD_GENERIC_ACCELERATED = 0x00001000,
+ PFD_SUPPORT_DIRECTDRAW = 0x00002000,
+ PFD_DEPTH_DONTCARE = 0x20000000,
+ PFD_DOUBLEBUFFER_DONTCARE = 0x40000000,
+ PFD_STEREO_DONTCARE = 0x80000000,
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct PixelFormatDescriptor
+ {
+ public ushort Size;
+ public ushort Version;
+ public PixelFormatDescriptorFlags Flags;
+ public byte PixelType;
+ public byte ColorBits;
+ public byte RedBits;
+ public byte RedShift;
+ public byte GreenBits;
+ public byte GreenShift;
+ public byte BlueBits;
+ public byte BlueShift;
+ public byte AlphaBits;
+ public byte AlphaShift;
+ public byte AccumBits;
+ public byte AccumRedBits;
+ public byte AccumGreenBits;
+ public byte AccumBlueBits;
+ public byte AccumAlphaBits;
+ public byte DepthBits;
+ public byte StencilBits;
+ public byte AuxBuffers;
+ public byte LayerType;
+ private byte Reserved;
+ public uint LayerMask;
+ public uint VisibleMask;
+ public uint DamageMask;
+ }
}
diff --git a/src/Windows/Avalonia.Win32/NonPumpingSyncContext.cs b/src/Windows/Avalonia.Win32/NonPumpingSyncContext.cs
new file mode 100644
index 0000000000..5577664cc4
--- /dev/null
+++ b/src/Windows/Avalonia.Win32/NonPumpingSyncContext.cs
@@ -0,0 +1,52 @@
+using System;
+using System.Runtime.ConstrainedExecution;
+using System.Threading;
+using Avalonia.Threading;
+using Avalonia.Utilities;
+using Avalonia.Win32.Interop;
+
+namespace Avalonia.Win32
+{
+ internal class NonPumpingSyncContext : SynchronizationContext, IDisposable
+ {
+ private readonly SynchronizationContext _inner;
+
+ private NonPumpingSyncContext(SynchronizationContext inner)
+ {
+ _inner = inner;
+ SetWaitNotificationRequired();
+ SetSynchronizationContext(this);
+ }
+
+ public override void Post(SendOrPostCallback d, object state) => _inner.Post(d, state);
+ public override void Send(SendOrPostCallback d, object state) => _inner.Send(d, state);
+
+ [PrePrepareMethod]
+ public override int Wait(IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout)
+ {
+ return UnmanagedMethods.WaitForMultipleObjectsEx(waitHandles.Length, waitHandles, waitAll,
+ millisecondsTimeout, false);
+ }
+
+ public void Dispose() => SetSynchronizationContext(_inner);
+
+ public static IDisposable Use()
+ {
+ var current = Current;
+ if (current == null)
+ {
+ if (Thread.CurrentThread.GetApartmentState() != ApartmentState.STA)
+ return null;
+ }
+ if (current is NonPumpingSyncContext)
+ return null;
+
+ return new NonPumpingSyncContext(current);
+ }
+
+ internal class HelperImpl : NonPumpingLockHelper.IHelperImpl
+ {
+ IDisposable NonPumpingLockHelper.IHelperImpl.Use() => NonPumpingSyncContext.Use();
+ }
+ }
+}
diff --git a/src/Windows/Avalonia.Win32/NonPumpingWaitProvider.cs b/src/Windows/Avalonia.Win32/NonPumpingWaitProvider.cs
deleted file mode 100644
index a0160fcfbd..0000000000
--- a/src/Windows/Avalonia.Win32/NonPumpingWaitProvider.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using System;
-using Avalonia.Threading;
-using Avalonia.Win32.Interop;
-
-namespace Avalonia.Win32
-{
- internal class NonPumpingWaitProvider : AvaloniaSynchronizationContext.INonPumpingPlatformWaitProvider
- {
- public int Wait(IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout)
- {
- return UnmanagedMethods.WaitForMultipleObjectsEx(waitHandles.Length, waitHandles, waitAll,
- millisecondsTimeout, false);
- }
- }
-}
diff --git a/src/Windows/Avalonia.Win32/OpenGl/WglConsts.cs b/src/Windows/Avalonia.Win32/OpenGl/WglConsts.cs
new file mode 100644
index 0000000000..3cb3dc25bb
--- /dev/null
+++ b/src/Windows/Avalonia.Win32/OpenGl/WglConsts.cs
@@ -0,0 +1,62 @@
+namespace Avalonia.Win32.OpenGl
+{
+ internal class WglConsts
+ {
+ public const int WGL_CONTEXT_MAJOR_VERSION_ARB = 0x2091;
+ public const int WGL_CONTEXT_MINOR_VERSION_ARB = 0x2092;
+ public const int WGL_CONTEXT_LAYER_PLANE_ARB = 0x2093;
+ public const int WGL_CONTEXT_FLAGS_ARB = 0x2094;
+ public const int WGL_CONTEXT_PROFILE_MASK_ARB = 0x9126;
+ public const int WGL_NUMBER_PIXEL_FORMATS_ARB = 0x2000;
+
+ public const int WGL_DRAW_TO_WINDOW_ARB = 0x2001;
+ public const int WGL_DRAW_TO_BITMAP_ARB = 0x2002;
+ public const int WGL_ACCELERATION_ARB = 0x2003;
+ public const int WGL_NEED_PALETTE_ARB = 0x2004;
+ public const int WGL_NEED_SYSTEM_PALETTE_ARB = 0x2005;
+ public const int WGL_SWAP_LAYER_BUFFERS_ARB = 0x2006;
+ public const int WGL_SWAP_METHOD_ARB = 0x2007;
+ public const int WGL_NUMBER_OVERLAYS_ARB = 0x2008;
+ public const int WGL_NUMBER_UNDERLAYS_ARB = 0x2009;
+ public const int WGL_TRANSPARENT_ARB = 0x200A;
+ public const int WGL_TRANSPARENT_RED_VALUE_ARB = 0x2037;
+ public const int WGL_TRANSPARENT_GREEN_VALUE_ARB = 0x2038;
+ public const int WGL_TRANSPARENT_BLUE_VALUE_ARB = 0x2039;
+ public const int WGL_TRANSPARENT_ALPHA_VALUE_ARB = 0x203A;
+ public const int WGL_TRANSPARENT_INDEX_VALUE_ARB = 0x203B;
+ public const int WGL_SHARE_DEPTH_ARB = 0x200C;
+ public const int WGL_SHARE_STENCIL_ARB = 0x200D;
+ public const int WGL_SHARE_ACCUM_ARB = 0x200E;
+ public const int WGL_SUPPORT_GDI_ARB = 0x200F;
+ public const int WGL_SUPPORT_OPENGL_ARB = 0x2010;
+ public const int WGL_DOUBLE_BUFFER_ARB = 0x2011;
+ public const int WGL_STEREO_ARB = 0x2012;
+ public const int WGL_PIXEL_TYPE_ARB = 0x2013;
+ public const int WGL_COLOR_BITS_ARB = 0x2014;
+ public const int WGL_RED_BITS_ARB = 0x2015;
+ public const int WGL_RED_SHIFT_ARB = 0x2016;
+ public const int WGL_GREEN_BITS_ARB = 0x2017;
+ public const int WGL_GREEN_SHIFT_ARB = 0x2018;
+ public const int WGL_BLUE_BITS_ARB = 0x2019;
+ public const int WGL_BLUE_SHIFT_ARB = 0x201A;
+ public const int WGL_ALPHA_BITS_ARB = 0x201B;
+ public const int WGL_ALPHA_SHIFT_ARB = 0x201C;
+ public const int WGL_ACCUM_BITS_ARB = 0x201D;
+ public const int WGL_ACCUM_RED_BITS_ARB = 0x201E;
+ public const int WGL_ACCUM_GREEN_BITS_ARB = 0x201F;
+ public const int WGL_ACCUM_BLUE_BITS_ARB = 0x2020;
+ public const int WGL_ACCUM_ALPHA_BITS_ARB = 0x2021;
+ public const int WGL_DEPTH_BITS_ARB = 0x2022;
+ public const int WGL_STENCIL_BITS_ARB = 0x2023;
+ public const int WGL_AUX_BUFFERS_ARB = 0x2024;
+ public const int WGL_NO_ACCELERATION_ARB = 0x2025;
+ public const int WGL_GENERIC_ACCELERATION_ARB = 0x2026;
+ public const int WGL_FULL_ACCELERATION_ARB = 0x2027;
+ public const int WGL_SWAP_EXCHANGE_ARB = 0x2028;
+ public const int WGL_SWAP_COPY_ARB = 0x2029;
+ public const int WGL_SWAP_UNDEFINED_ARB = 0x202A;
+ public const int WGL_TYPE_RGBA_ARB = 0x202B;
+ public const int WGL_TYPE_COLORINDEX_ARB = 0x202C;
+
+ }
+}
diff --git a/src/Windows/Avalonia.Win32/OpenGl/WglContext.cs b/src/Windows/Avalonia.Win32/OpenGl/WglContext.cs
new file mode 100644
index 0000000000..d6633ddb61
--- /dev/null
+++ b/src/Windows/Avalonia.Win32/OpenGl/WglContext.cs
@@ -0,0 +1,85 @@
+using System;
+using System.Reactive.Disposables;
+using Avalonia.OpenGL;
+using Avalonia.Win32.Interop;
+using static Avalonia.Win32.Interop.UnmanagedMethods;
+using static Avalonia.Win32.OpenGl.WglConsts;
+
+namespace Avalonia.Win32.OpenGl
+{
+ class WglContext : IGlContext
+ {
+ private object _lock = new object();
+ private readonly WglContext _sharedWith;
+ private readonly IntPtr _context;
+ private readonly IntPtr _hWnd;
+ private readonly IntPtr _dc;
+ private readonly int _pixelFormat;
+ private readonly PixelFormatDescriptor _formatDescriptor;
+ public IntPtr Handle => _context;
+
+ public WglContext(WglContext sharedWith, GlVersion version, IntPtr context, IntPtr hWnd, IntPtr dc, int pixelFormat,
+ PixelFormatDescriptor formatDescriptor)
+ {
+ Version = version;
+ _sharedWith = sharedWith;
+ _context = context;
+ _hWnd = hWnd;
+ _dc = dc;
+ _pixelFormat = pixelFormat;
+ _formatDescriptor = formatDescriptor;
+ StencilSize = formatDescriptor.StencilBits;
+ using (MakeCurrent())
+ GlInterface = new GlInterface(version, proc =>
+ {
+ var ext = wglGetProcAddress(proc);
+ if (ext != IntPtr.Zero)
+ return ext;
+ return GetProcAddress(WglDisplay.OpenGl32Handle, proc);
+ });
+
+ }
+
+ public void Dispose()
+ {
+ wglDeleteContext(_context);
+ ReleaseDC(_hWnd, _dc);
+ DestroyWindow(_hWnd);
+ }
+
+ public GlVersion Version { get; }
+ public GlInterface GlInterface { get; }
+ public int SampleCount { get; }
+ public int StencilSize { get; }
+
+ private bool IsCurrent => wglGetCurrentContext() == _context && wglGetCurrentDC() == _dc;
+ public IDisposable MakeCurrent()
+ {
+ if(IsCurrent)
+ return Disposable.Empty;
+ return new WglRestoreContext(_dc, _context, _lock);
+ }
+
+ public IDisposable EnsureCurrent() => MakeCurrent();
+
+
+ public IntPtr CreateConfiguredDeviceContext(IntPtr hWnd)
+ {
+ var dc = GetDC(hWnd);
+ var fmt = _formatDescriptor;
+ SetPixelFormat(dc, _pixelFormat, ref fmt);
+ return dc;
+ }
+
+ public IDisposable MakeCurrent(IntPtr hdc) => new WglRestoreContext(hdc, _context, _lock);
+
+ public bool IsSharedWith(IGlContext context)
+ {
+ var c = (WglContext)context;
+ return c == this
+ || c._sharedWith == this
+ || _sharedWith == context
+ || _sharedWith != null && _sharedWith == c._sharedWith;
+ }
+ }
+}
diff --git a/src/Windows/Avalonia.Win32/OpenGl/WglDisplay.cs b/src/Windows/Avalonia.Win32/OpenGl/WglDisplay.cs
new file mode 100644
index 0000000000..dc3c16b4a3
--- /dev/null
+++ b/src/Windows/Avalonia.Win32/OpenGl/WglDisplay.cs
@@ -0,0 +1,183 @@
+using System;
+using System.Runtime.InteropServices;
+using Avalonia.OpenGL;
+using Avalonia.Win32.Interop;
+using static Avalonia.Win32.Interop.UnmanagedMethods;
+using static Avalonia.Win32.OpenGl.WglConsts;
+namespace Avalonia.Win32.OpenGl
+{
+ internal class WglDisplay
+ {
+ private static bool? _initialized;
+ private static ushort _windowClass;
+ private static readonly WndProc _wndProcDelegate = WndProc;
+ private static readonly DebugCallbackDelegate _debugCallback = DebugCallback;
+
+ private static IntPtr _bootstrapContext;
+ private static IntPtr _bootstrapWindow;
+ private static IntPtr _bootstrapDc;
+ private static PixelFormatDescriptor _defaultPfd;
+ private static int _defaultPixelFormat;
+ public static IntPtr OpenGl32Handle = LoadLibrary("opengl32");
+
+ private delegate bool WglChoosePixelFormatARBDelegate(IntPtr hdc, int[] piAttribIList, float[] pfAttribFList,
+ int nMaxFormats, int[] piFormats, out int nNumFormats);
+
+ private static WglChoosePixelFormatARBDelegate WglChoosePixelFormatArb;
+
+ private delegate IntPtr WglCreateContextAttribsARBDelegate(IntPtr hDC, IntPtr hShareContext, int[] attribList);
+
+ private static WglCreateContextAttribsARBDelegate WglCreateContextAttribsArb;
+
+ private delegate void GlDebugMessageCallbackDelegate(IntPtr callback, IntPtr userParam);
+
+ private static GlDebugMessageCallbackDelegate GlDebugMessageCallback;
+
+ private delegate void DebugCallbackDelegate(int source, int type, int id, int severity, int len, IntPtr message,
+ IntPtr userParam);
+
+ static bool Initialize()
+ {
+ if (!_initialized.HasValue)
+ _initialized = InitializeCore();
+ return _initialized.Value;
+ }
+ static bool InitializeCore()
+ {
+ var wndClassEx = new WNDCLASSEX
+ {
+ cbSize = Marshal.SizeOf(),
+ hInstance = GetModuleHandle(null),
+ lpfnWndProc = _wndProcDelegate,
+ lpszClassName = "AvaloniaGlWindow-" + Guid.NewGuid(),
+ style = (int)ClassStyles.CS_OWNDC
+ };
+
+ _windowClass = RegisterClassEx(ref wndClassEx);
+ _bootstrapWindow = CreateOffscreenWindow();
+ _bootstrapDc = GetDC(_bootstrapWindow);
+ _defaultPfd = new PixelFormatDescriptor
+ {
+ Size = (ushort)Marshal.SizeOf(),
+ Version = 1,
+ Flags = PixelFormatDescriptorFlags.PFD_DRAW_TO_WINDOW |
+ PixelFormatDescriptorFlags.PFD_SUPPORT_OPENGL | PixelFormatDescriptorFlags.PFD_DOUBLEBUFFER,
+ DepthBits = 24,
+ StencilBits = 8,
+ ColorBits = 32
+ };
+ _defaultPixelFormat = ChoosePixelFormat(_bootstrapDc, ref _defaultPfd);
+ SetPixelFormat(_bootstrapDc, _defaultPixelFormat, ref _defaultPfd);
+
+ _bootstrapContext = wglCreateContext(_bootstrapDc);
+ if (_bootstrapContext == IntPtr.Zero)
+ return false;
+
+ wglMakeCurrent(_bootstrapDc, _bootstrapContext);
+ WglCreateContextAttribsArb = Marshal.GetDelegateForFunctionPointer(
+ wglGetProcAddress("wglCreateContextAttribsARB"));
+
+ WglChoosePixelFormatArb =
+ Marshal.GetDelegateForFunctionPointer(
+ wglGetProcAddress("wglChoosePixelFormatARB"));
+
+ GlDebugMessageCallback =
+ Marshal.GetDelegateForFunctionPointer(
+ wglGetProcAddress("glDebugMessageCallback"));
+
+
+ var formats = new int[1];
+ WglChoosePixelFormatArb(_bootstrapDc, new int[]
+ {
+ WGL_DRAW_TO_WINDOW_ARB, 1,
+ WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
+ WGL_SUPPORT_OPENGL_ARB, 1,
+ WGL_DOUBLE_BUFFER_ARB, 1,
+ WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
+ WGL_COLOR_BITS_ARB, 32,
+ WGL_DEPTH_BITS_ARB, 0,
+ WGL_STENCIL_BITS_ARB, 0,
+ 0, // End
+ }, null, 1, formats, out int numFormats);
+ if (numFormats != 0)
+ {
+ DescribePixelFormat(_bootstrapDc, formats[0], Marshal.SizeOf(), ref _defaultPfd);
+ _defaultPixelFormat = formats[0];
+ }
+
+
+ wglMakeCurrent(IntPtr.Zero, IntPtr.Zero);
+ return true;
+ }
+
+ static IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
+ {
+ return DefWindowProc(hWnd, msg, wParam, lParam);
+ }
+
+ private static void DebugCallback(int source, int type, int id, int severity, int len, IntPtr message, IntPtr userparam)
+ {
+ var err = Marshal.PtrToStringAnsi(message, len);
+ Console.Error.WriteLine(err);
+ }
+
+ public static WglContext CreateContext(GlVersion[] versions, IGlContext share)
+ {
+ if (!Initialize())
+ return null;
+
+ var shareContext = (WglContext)share;
+
+ using (new WglRestoreContext(_bootstrapDc, _bootstrapContext, null))
+ {
+ var window = CreateOffscreenWindow();
+ var dc = GetDC(window);
+ SetPixelFormat(dc, _defaultPixelFormat, ref _defaultPfd);
+ foreach (var version in versions)
+ {
+ if(version.Type != GlProfileType.OpenGL)
+ continue;
+ var context = WglCreateContextAttribsArb(dc, shareContext?.Handle ?? IntPtr.Zero,
+ new[]
+ {
+ // major
+ WGL_CONTEXT_MAJOR_VERSION_ARB, version.Major,
+ // minor
+ WGL_CONTEXT_MINOR_VERSION_ARB, version.Minor,
+ // core profile
+ WGL_CONTEXT_PROFILE_MASK_ARB, 1,
+ // debug
+ // WGL_CONTEXT_FLAGS_ARB, 1,
+ // end
+ 0, 0
+ });
+ using(new WglRestoreContext(dc, context, null))
+ GlDebugMessageCallback(Marshal.GetFunctionPointerForDelegate(_debugCallback), IntPtr.Zero);
+ if (context != IntPtr.Zero)
+ return new WglContext(shareContext, version, context, window, dc,
+ _defaultPixelFormat, _defaultPfd);
+ }
+
+ ReleaseDC(window, dc);
+ DestroyWindow(window);
+ return null;
+ }
+ }
+
+
+ static IntPtr CreateOffscreenWindow() =>
+ CreateWindowEx(
+ 0,
+ _windowClass,
+ null,
+ (int)WindowStyles.WS_OVERLAPPEDWINDOW,
+ 0,
+ 0,
+ 640,
+ 480,
+ IntPtr.Zero,
+ IntPtr.Zero,
+ IntPtr.Zero,
+ IntPtr.Zero);
+ }
+}
diff --git a/src/Windows/Avalonia.Win32/OpenGl/WglGlPlatformSurface.cs b/src/Windows/Avalonia.Win32/OpenGl/WglGlPlatformSurface.cs
new file mode 100644
index 0000000000..72bcffd447
--- /dev/null
+++ b/src/Windows/Avalonia.Win32/OpenGl/WglGlPlatformSurface.cs
@@ -0,0 +1,85 @@
+using System;
+using System.Diagnostics;
+using Avalonia.OpenGL;
+using Avalonia.OpenGL.Egl;
+using Avalonia.OpenGL.Surfaces;
+using Avalonia.Win32.Interop;
+using static Avalonia.OpenGL.GlConsts;
+using static Avalonia.Win32.Interop.UnmanagedMethods;
+namespace Avalonia.Win32.OpenGl
+{
+ class WglGlPlatformSurface: IGlPlatformSurface
+ {
+
+ private readonly WglContext _context;
+ private readonly EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo _info;
+
+ public WglGlPlatformSurface(WglContext context, EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo info)
+ {
+ _context = context;
+ _info = info;
+ }
+
+ public IGlPlatformSurfaceRenderTarget CreateGlRenderTarget()
+ {
+ return new RenderTarget(_context, _info);
+ }
+
+ class RenderTarget : IGlPlatformSurfaceRenderTarget
+ {
+ private readonly WglContext _context;
+ private readonly EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo _info;
+ private IntPtr _hdc;
+ public RenderTarget(WglContext context, EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo info)
+ {
+ _context = context;
+ _info = info;
+ _hdc = context.CreateConfiguredDeviceContext(info.Handle);
+ }
+
+ public void Dispose()
+ {
+ UnmanagedMethods.ReleaseDC(_hdc, _info.Handle);
+ }
+
+ public IGlPlatformSurfaceRenderingSession BeginDraw()
+ {
+ var oldContext = _context.MakeCurrent(_hdc);
+
+ // Reset to default FBO first
+ _context.GlInterface.BindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ return new Session(_context, _hdc, _info, oldContext);
+ }
+
+ class Session : IGlPlatformSurfaceRenderingSession
+ {
+ private readonly WglContext _context;
+ private readonly IntPtr _hdc;
+ private readonly EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo _info;
+ private readonly IDisposable _clearContext;
+ public IGlContext Context => _context;
+
+ public Session(WglContext context, IntPtr hdc, EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo info,
+ IDisposable clearContext)
+ {
+ _context = context;
+ _hdc = hdc;
+ _info = info;
+ _clearContext = clearContext;
+ }
+
+ public void Dispose()
+ {
+ _context.GlInterface.Flush();
+ UnmanagedMethods.SwapBuffers(_hdc);
+ _clearContext.Dispose();
+ }
+
+ public PixelSize Size => _info.Size;
+ public double Scaling => _info.Scaling;
+ public bool IsYFlipped { get; }
+ }
+ }
+ }
+}
diff --git a/src/Windows/Avalonia.Win32/OpenGl/WglPlatformOpenGlInterface.cs b/src/Windows/Avalonia.Win32/OpenGl/WglPlatformOpenGlInterface.cs
new file mode 100644
index 0000000000..b948495b99
--- /dev/null
+++ b/src/Windows/Avalonia.Win32/OpenGl/WglPlatformOpenGlInterface.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Linq;
+using Avalonia.Logging;
+using Avalonia.OpenGL;
+
+namespace Avalonia.Win32.OpenGl
+{
+ class WglPlatformOpenGlInterface : IPlatformOpenGlInterface
+ {
+ public WglContext PrimaryContext { get; }
+ IGlContext IPlatformOpenGlInterface.PrimaryContext => PrimaryContext;
+ public IGlContext CreateSharedContext() => WglDisplay.CreateContext(new[] { PrimaryContext.Version }, PrimaryContext);
+
+ public bool CanShareContexts => true;
+ public bool CanCreateContexts => true;
+ public IGlContext CreateContext() => WglDisplay.CreateContext(new[] { PrimaryContext.Version }, null);
+
+ private WglPlatformOpenGlInterface(WglContext primary)
+ {
+ PrimaryContext = primary;
+ }
+
+ public static WglPlatformOpenGlInterface TryCreate()
+ {
+ try
+ {
+ var opts = AvaloniaLocator.Current.GetService() ?? new Win32PlatformOptions();
+ var primary = WglDisplay.CreateContext(opts.WglProfiles.ToArray(), null);
+ return new WglPlatformOpenGlInterface(primary);
+ }
+ catch (Exception e)
+ {
+ Logger.TryGet(LogEventLevel.Error, "OpenGL")?.Log("WGL", "Unable to initialize WGL: " + e);
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/src/Windows/Avalonia.Win32/OpenGl/WglRestoreContext.cs b/src/Windows/Avalonia.Win32/OpenGl/WglRestoreContext.cs
new file mode 100644
index 0000000000..265f078a5c
--- /dev/null
+++ b/src/Windows/Avalonia.Win32/OpenGl/WglRestoreContext.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Threading;
+using Avalonia.OpenGL;
+using static Avalonia.Win32.Interop.UnmanagedMethods;
+
+namespace Avalonia.Win32.OpenGl
+{
+ internal class WglRestoreContext : IDisposable
+ {
+ private readonly object _monitor;
+ private readonly IntPtr _oldDc;
+ private readonly IntPtr _oldContext;
+
+ public WglRestoreContext(IntPtr gc, IntPtr context, object monitor, bool takeMonitor = true)
+ {
+ _monitor = monitor;
+ _oldDc = wglGetCurrentDC();
+ _oldContext = wglGetCurrentContext();
+
+ if (monitor != null && takeMonitor)
+ Monitor.Enter(monitor);
+
+ if (!wglMakeCurrent(gc, context))
+ {
+ if(monitor != null && takeMonitor)
+ Monitor.Exit(monitor);
+ throw new OpenGlException("Unable to make the context current");
+ }
+ }
+
+ public void Dispose()
+ {
+ if (!wglMakeCurrent(_oldDc, _oldContext))
+ wglMakeCurrent(IntPtr.Zero, IntPtr.Zero);
+ if (_monitor != null)
+ Monitor.Exit(_monitor);
+ }
+ }
+}
diff --git a/src/Windows/Avalonia.Win32/PopupImpl.cs b/src/Windows/Avalonia.Win32/PopupImpl.cs
index 57da1c4d66..dd3fd1342c 100644
--- a/src/Windows/Avalonia.Win32/PopupImpl.cs
+++ b/src/Windows/Avalonia.Win32/PopupImpl.cs
@@ -17,8 +17,9 @@ namespace Avalonia.Win32
[ThreadStatic]
private static IntPtr s_parentHandle;
- public override void Show()
+ public override void Show(bool activate)
{
+ // Popups are always shown non-activated.
UnmanagedMethods.ShowWindow(Handle.Handle, UnmanagedMethods.ShowWindowCommand.ShowNoActivate);
// We need to steal focus if it's held by a child window of our toplevel window
@@ -69,7 +70,8 @@ namespace Avalonia.Win32
{
UnmanagedMethods.WindowStyles style =
UnmanagedMethods.WindowStyles.WS_POPUP |
- UnmanagedMethods.WindowStyles.WS_CLIPSIBLINGS;
+ UnmanagedMethods.WindowStyles.WS_CLIPSIBLINGS |
+ UnmanagedMethods.WindowStyles.WS_CLIPCHILDREN;
UnmanagedMethods.WindowStyles exStyle =
UnmanagedMethods.WindowStyles.WS_EX_TOOLWINDOW |
diff --git a/src/Windows/Avalonia.Win32/Win32GlManager.cs b/src/Windows/Avalonia.Win32/Win32GlManager.cs
index fbc56e7703..b51f80e397 100644
--- a/src/Windows/Avalonia.Win32/Win32GlManager.cs
+++ b/src/Windows/Avalonia.Win32/Win32GlManager.cs
@@ -1,27 +1,37 @@
+using System;
using Avalonia.OpenGL;
using Avalonia.OpenGL.Angle;
using Avalonia.OpenGL.Egl;
+using Avalonia.Win32.OpenGl;
+using Avalonia.Win32.WinRT.Composition;
namespace Avalonia.Win32
{
static class Win32GlManager
{
- /// This property is initialized if drawing platform requests OpenGL support
- public static EglPlatformOpenGlInterface EglPlatformInterface { get; private set; }
-
- private static bool s_attemptedToInitialize;
-
public static void Initialize()
{
- AvaloniaLocator.CurrentMutable.Bind().ToFunc(() =>
+ AvaloniaLocator.CurrentMutable.Bind().ToLazy(() =>
{
- if (!s_attemptedToInitialize)
+ var opts = AvaloniaLocator.Current.GetService();
+ if (opts?.UseWgl == true)
{
- EglPlatformInterface = EglPlatformOpenGlInterface.TryCreate(() => new AngleWin32EglDisplay());
- s_attemptedToInitialize = true;
+ var wgl = WglPlatformOpenGlInterface.TryCreate();
+ return wgl;
+ }
+
+ if (opts?.AllowEglInitialization == true)
+ {
+ var egl = EglPlatformOpenGlInterface.TryCreate(() => new AngleWin32EglDisplay());
+
+ if (egl is { } &&
+ opts?.UseWindowsUIComposition == true)
+ WinUICompositorConnection.TryCreateAndRegister(egl);
+
+ return egl;
}
- return EglPlatformInterface;
+ return null;
});
}
}
diff --git a/src/Windows/Avalonia.Win32/Win32Platform.cs b/src/Windows/Avalonia.Win32/Win32Platform.cs
index af6058d197..97eb0c6119 100644
--- a/src/Windows/Avalonia.Win32/Win32Platform.cs
+++ b/src/Windows/Avalonia.Win32/Win32Platform.cs
@@ -11,9 +11,12 @@ using Avalonia.Controls;
using Avalonia.Controls.Platform;
using Avalonia.Input;
using Avalonia.Input.Platform;
+using Avalonia.OpenGL;
+using Avalonia.OpenGL.Egl;
using Avalonia.Platform;
using Avalonia.Rendering;
using Avalonia.Threading;
+using Avalonia.Utilities;
using Avalonia.Win32.Input;
using Avalonia.Win32.Interop;
using static Avalonia.Win32.Interop.UnmanagedMethods;
@@ -39,6 +42,21 @@ namespace Avalonia
public bool AllowEglInitialization { get; set; } = true;
public bool? EnableMultitouch { get; set; }
public bool OverlayPopups { get; set; }
+ public bool UseWgl { get; set; }
+ public IList WglProfiles { get; set; } = new List
+ {
+ new GlVersion(GlProfileType.OpenGL, 4, 0),
+ new GlVersion(GlProfileType.OpenGL, 3, 2),
+ };
+
+ ///
+ /// Render Avalonia to a Texture inside the Windows.UI.Composition tree.
+ ///
+ ///
+ /// Supported on Windows 10 build 16299 and above. Ignored on other versions.
+ /// This is recommended if you need to use AcrylicBlur or acrylic in your applications.
+ ///
+ public bool UseWindowsUIComposition { get; set; } = true;
}
}
@@ -93,12 +111,11 @@ namespace Avalonia.Win32
.Bind().ToConstant(s_instance)
.Bind().ToSingleton()
.Bind().ToConstant(s_instance)
- .Bind().ToConstant(new NonPumpingWaitProvider())
+ .Bind().ToConstant(new NonPumpingSyncContext.HelperImpl())
.Bind().ToConstant(new WindowsMountedVolumeInfoProvider());
- if (options.AllowEglInitialization)
- Win32GlManager.Initialize();
-
+ Win32GlManager.Initialize();
+
_uiThread = Thread.CurrentThread;
if (OleContext.Current != null)
@@ -113,21 +130,34 @@ namespace Avalonia.Win32
public void ProcessMessage()
{
- UnmanagedMethods.MSG msg;
- UnmanagedMethods.GetMessage(out msg, IntPtr.Zero, 0, 0);
- UnmanagedMethods.TranslateMessage(ref msg);
- UnmanagedMethods.DispatchMessage(ref msg);
+
+ if (UnmanagedMethods.GetMessage(out var msg, IntPtr.Zero, 0, 0) > -1)
+ {
+ UnmanagedMethods.TranslateMessage(ref msg);
+ UnmanagedMethods.DispatchMessage(ref msg);
+ }
+ else
+ {
+ Logging.Logger.TryGet(Logging.LogEventLevel.Error, Logging.LogArea.Win32Platform)
+ ?.Log(this, "Unmanaged error in {0}. Error Code: {1}", nameof(ProcessMessage), Marshal.GetLastWin32Error());
+
+ }
}
public void RunLoop(CancellationToken cancellationToken)
{
- while (!cancellationToken.IsCancellationRequested)
+ var result = 0;
+ while (!cancellationToken.IsCancellationRequested
+ && (result = UnmanagedMethods.GetMessage(out var msg, IntPtr.Zero, 0, 0)) > 0)
{
- UnmanagedMethods.MSG msg;
- UnmanagedMethods.GetMessage(out msg, IntPtr.Zero, 0, 0);
UnmanagedMethods.TranslateMessage(ref msg);
UnmanagedMethods.DispatchMessage(ref msg);
}
+ if (result < 0)
+ {
+ Logging.Logger.TryGet(Logging.LogEventLevel.Error, Logging.LogArea.Win32Platform)
+ ?.Log(this, "Unmanaged error in {0}. Error Code: {1}", nameof(RunLoop), Marshal.GetLastWin32Error());
+ }
}
public IDisposable StartTimer(DispatcherPriority priority, TimeSpan interval, Action callback)
@@ -213,7 +243,7 @@ namespace Avalonia.Win32
public IWindowImpl CreateEmbeddableWindow()
{
var embedded = new EmbeddedWindowImpl();
- embedded.Show();
+ embedded.Show(true);
return embedded;
}
diff --git a/src/Windows/Avalonia.Win32/WinRT/Composition/D2DEffects.cs b/src/Windows/Avalonia.Win32/WinRT/Composition/D2DEffects.cs
new file mode 100644
index 0000000000..bef5a55b06
--- /dev/null
+++ b/src/Windows/Avalonia.Win32/WinRT/Composition/D2DEffects.cs
@@ -0,0 +1,130 @@
+using System;
+
+namespace Avalonia.Win32.WinRT.Composition
+{
+ class D2DEffects
+ {
+ public static readonly Guid CLSID_D2D12DAffineTransform =
+ new Guid(0x6AA97485, 0x6354, 0x4CFC, 0x90, 0x8C, 0xE4, 0xA7, 0x4F, 0x62, 0xC9, 0x6C);
+
+ public static readonly Guid CLSID_D2D13DPerspectiveTransform =
+ new Guid(0xC2844D0B, 0x3D86, 0x46E7, 0x85, 0xBA, 0x52, 0x6C, 0x92, 0x40, 0xF3, 0xFB);
+
+ public static readonly Guid CLSID_D2D13DTransform =
+ new Guid(0xE8467B04, 0xEC61, 0x4B8A, 0xB5, 0xDE, 0xD4, 0xD7, 0x3D, 0xEB, 0xEA, 0x5A);
+
+ public static readonly Guid CLSID_D2D1ArithmeticComposite =
+ new Guid(0xFC151437, 0x049A, 0x4784, 0xA2, 0x4A, 0xF1, 0xC4, 0xDA, 0xF2, 0x09, 0x87);
+
+ public static readonly Guid CLSID_D2D1Atlas =
+ new Guid(0x913E2BE4, 0xFDCF, 0x4FE2, 0xA5, 0xF0, 0x24, 0x54, 0xF1, 0x4F, 0xF4, 0x08);
+
+ public static readonly Guid CLSID_D2D1BitmapSource =
+ new Guid(0x5FB6C24D, 0xC6DD, 0x4231, 0x94, 0x4, 0x50, 0xF4, 0xD5, 0xC3, 0x25, 0x2D);
+
+ public static readonly Guid CLSID_D2D1Blend =
+ new Guid(0x81C5B77B, 0x13F8, 0x4CDD, 0xAD, 0x20, 0xC8, 0x90, 0x54, 0x7A, 0xC6, 0x5D);
+
+ public static readonly Guid CLSID_D2D1Border =
+ new Guid(0x2A2D49C0, 0x4ACF, 0x43C7, 0x8C, 0x6A, 0x7C, 0x4A, 0x27, 0x87, 0x4D, 0x27);
+
+ public static readonly Guid CLSID_D2D1Brightness =
+ new Guid(0x8CEA8D1E, 0x77B0, 0x4986, 0xB3, 0xB9, 0x2F, 0x0C, 0x0E, 0xAE, 0x78, 0x87);
+
+ public static readonly Guid CLSID_D2D1ColorManagement =
+ new Guid(0x1A28524C, 0xFDD6, 0x4AA4, 0xAE, 0x8F, 0x83, 0x7E, 0xB8, 0x26, 0x7B, 0x37);
+
+ public static readonly Guid CLSID_D2D1ColorMatrix =
+ new Guid(0x921F03D6, 0x641C, 0x47DF, 0x85, 0x2D, 0xB4, 0xBB, 0x61, 0x53, 0xAE, 0x11);
+
+ public static readonly Guid CLSID_D2D1Composite =
+ new Guid(0x48FC9F51, 0xF6AC, 0x48F1, 0x8B, 0x58, 0x3B, 0x28, 0xAC, 0x46, 0xF7, 0x6D);
+
+ public static readonly Guid CLSID_D2D1ConvolveMatrix =
+ new Guid(0x407F8C08, 0x5533, 0x4331, 0xA3, 0x41, 0x23, 0xCC, 0x38, 0x77, 0x84, 0x3E);
+
+ public static readonly Guid CLSID_D2D1Crop =
+ new Guid(0xE23F7110, 0x0E9A, 0x4324, 0xAF, 0x47, 0x6A, 0x2C, 0x0C, 0x46, 0xF3, 0x5B);
+
+ public static readonly Guid CLSID_D2D1DirectionalBlur =
+ new Guid(0x174319A6, 0x58E9, 0x49B2, 0xBB, 0x63, 0xCA, 0xF2, 0xC8, 0x11, 0xA3, 0xDB);
+
+ public static readonly Guid CLSID_D2D1DiscreteTransfer =
+ new Guid(0x90866FCD, 0x488E, 0x454B, 0xAF, 0x06, 0xE5, 0x04, 0x1B, 0x66, 0xC3, 0x6C);
+
+ public static readonly Guid CLSID_D2D1DisplacementMap =
+ new Guid(0xEDC48364, 0x417, 0x4111, 0x94, 0x50, 0x43, 0x84, 0x5F, 0xA9, 0xF8, 0x90);
+
+ public static readonly Guid CLSID_D2D1DistantDiffuse =
+ new Guid(0x3E7EFD62, 0xA32D, 0x46D4, 0xA8, 0x3C, 0x52, 0x78, 0x88, 0x9A, 0xC9, 0x54);
+
+ public static readonly Guid CLSID_D2D1DistantSpecular =
+ new Guid(0x428C1EE5, 0x77B8, 0x4450, 0x8A, 0xB5, 0x72, 0x21, 0x9C, 0x21, 0xAB, 0xDA);
+
+ public static readonly Guid CLSID_D2D1DpiCompensation =
+ new Guid(0x6C26C5C7, 0x34E0, 0x46FC, 0x9C, 0xFD, 0xE5, 0x82, 0x37, 0x6, 0xE2, 0x28);
+
+ public static readonly Guid CLSID_D2D1Flood =
+ new Guid(0x61C23C20, 0xAE69, 0x4D8E, 0x94, 0xCF, 0x50, 0x07, 0x8D, 0xF6, 0x38, 0xF2);
+
+ public static readonly Guid CLSID_D2D1GammaTransfer =
+ new Guid(0x409444C4, 0xC419, 0x41A0, 0xB0, 0xC1, 0x8C, 0xD0, 0xC0, 0xA1, 0x8E, 0x42);
+
+ public static readonly Guid CLSID_D2D1GaussianBlur =
+ new Guid(0x1FEB6D69, 0x2FE6, 0x4AC9, 0x8C, 0x58, 0x1D, 0x7F, 0x93, 0xE7, 0xA6, 0xA5);
+
+ public static readonly Guid CLSID_D2D1Scale =
+ new Guid(0x9DAF9369, 0x3846, 0x4D0E, 0xA4, 0x4E, 0xC, 0x60, 0x79, 0x34, 0xA5, 0xD7);
+
+ public static readonly Guid CLSID_D2D1Histogram =
+ new Guid(0x881DB7D0, 0xF7EE, 0x4D4D, 0xA6, 0xD2, 0x46, 0x97, 0xAC, 0xC6, 0x6E, 0xE8);
+
+ public static readonly Guid CLSID_D2D1HueRotation =
+ new Guid(0x0F4458EC, 0x4B32, 0x491B, 0x9E, 0x85, 0xBD, 0x73, 0xF4, 0x4D, 0x3E, 0xB6);
+
+ public static readonly Guid CLSID_D2D1LinearTransfer =
+ new Guid(0xAD47C8FD, 0x63EF, 0x4ACC, 0x9B, 0x51, 0x67, 0x97, 0x9C, 0x03, 0x6C, 0x06);
+
+ public static readonly Guid CLSID_D2D1LuminanceToAlpha =
+ new Guid(0x41251AB7, 0x0BEB, 0x46F8, 0x9D, 0xA7, 0x59, 0xE9, 0x3F, 0xCC, 0xE5, 0xDE);
+
+ public static readonly Guid CLSID_D2D1Morphology =
+ new Guid(0xEAE6C40D, 0x626A, 0x4C2D, 0xBF, 0xCB, 0x39, 0x10, 0x01, 0xAB, 0xE2, 0x02);
+
+ public static readonly Guid CLSID_D2D1OpacityMetadata =
+ new Guid(0x6C53006A, 0x4450, 0x4199, 0xAA, 0x5B, 0xAD, 0x16, 0x56, 0xFE, 0xCE, 0x5E);
+
+ public static readonly Guid CLSID_D2D1PointDiffuse =
+ new Guid(0xB9E303C3, 0xC08C, 0x4F91, 0x8B, 0x7B, 0x38, 0x65, 0x6B, 0xC4, 0x8C, 0x20);
+
+ public static readonly Guid CLSID_D2D1PointSpecular =
+ new Guid(0x09C3CA26, 0x3AE2, 0x4F09, 0x9E, 0xBC, 0xED, 0x38, 0x65, 0xD5, 0x3F, 0x22);
+
+ public static readonly Guid CLSID_D2D1Premultiply =
+ new Guid(0x06EAB419, 0xDEED, 0x4018, 0x80, 0xD2, 0x3E, 0x1D, 0x47, 0x1A, 0xDE, 0xB2);
+
+ public static readonly Guid CLSID_D2D1Saturation =
+ new Guid(0x5CB2D9CF, 0x327D, 0x459F, 0xA0, 0xCE, 0x40, 0xC0, 0xB2, 0x08, 0x6B, 0xF7);
+
+ public static readonly Guid CLSID_D2D1Shadow =
+ new Guid(0xC67EA361, 0x1863, 0x4E69, 0x89, 0xDB, 0x69, 0x5D, 0x3E, 0x9A, 0x5B, 0x6B);
+
+ public static readonly Guid CLSID_D2D1SpotDiffuse =
+ new Guid(0x818A1105, 0x7932, 0x44F4, 0xAA, 0x86, 0x08, 0xAE, 0x7B, 0x2F, 0x2C, 0x93);
+
+ public static readonly Guid CLSID_D2D1SpotSpecular =
+ new Guid(0xEDAE421E, 0x7654, 0x4A37, 0x9D, 0xB8, 0x71, 0xAC, 0xC1, 0xBE, 0xB3, 0xC1);
+
+ public static readonly Guid CLSID_D2D1TableTransfer =
+ new Guid(0x5BF818C3, 0x5E43, 0x48CB, 0xB6, 0x31, 0x86, 0x83, 0x96, 0xD6, 0xA1, 0xD4);
+
+ public static readonly Guid CLSID_D2D1Tile =
+ new Guid(0xB0784138, 0x3B76, 0x4BC5, 0xB1, 0x3B, 0x0F, 0xA2, 0xAD, 0x02, 0x65, 0x9F);
+
+ public static readonly Guid CLSID_D2D1Turbulence =
+ new Guid(0xCF2BB6AE, 0x889A, 0x4AD7, 0xBA, 0x29, 0xA2, 0xFD, 0x73, 0x2C, 0x9F, 0xC9);
+
+ public static readonly Guid CLSID_D2D1UnPremultiply =
+ new Guid(0xFB9AC489, 0xAD8D, 0x41ED, 0x99, 0x99, 0xBB, 0x63, 0x47, 0xD1, 0x10, 0xF7);
+ }
+}
diff --git a/src/Windows/Avalonia.Win32/WinRT/Composition/WinUICompositedWindow.cs b/src/Windows/Avalonia.Win32/WinRT/Composition/WinUICompositedWindow.cs
new file mode 100644
index 0000000000..4ae9c08410
--- /dev/null
+++ b/src/Windows/Avalonia.Win32/WinRT/Composition/WinUICompositedWindow.cs
@@ -0,0 +1,99 @@
+using System;
+using System.Numerics;
+using System.Reactive.Disposables;
+using System.Threading;
+using Avalonia.MicroCom;
+using Avalonia.OpenGL;
+using Avalonia.OpenGL.Egl;
+using Avalonia.Win32.Interop;
+
+namespace Avalonia.Win32.WinRT.Composition
+{
+ public class WinUICompositedWindow : IDisposable
+ {
+ private EglContext _syncContext;
+ private readonly object _pumpLock;
+ private readonly IVisual _blurVisual;
+ private ICompositionTarget _compositionTarget;
+ private IVisual _contentVisual;
+ private ICompositionDrawingSurfaceInterop _surfaceInterop;
+ private PixelSize _size;
+
+ private static Guid IID_ID3D11Texture2D = Guid.Parse("6f15aaf2-d208-4e89-9ab4-489535d34f9c");
+ private ICompositor _compositor;
+
+
+ internal WinUICompositedWindow(EglContext syncContext,
+ ICompositor compositor,
+ object pumpLock,
+ ICompositionTarget compositionTarget,
+ ICompositionDrawingSurfaceInterop surfaceInterop,
+ IVisual contentVisual, IVisual blurVisual)
+ {
+ _compositor = compositor.CloneReference();
+ _syncContext = syncContext;
+ _pumpLock = pumpLock;
+ _blurVisual = blurVisual.CloneReference();
+ _compositionTarget = compositionTarget.CloneReference();
+ _contentVisual = contentVisual.CloneReference();
+ _surfaceInterop = surfaceInterop.CloneReference();
+ }
+
+
+ public void ResizeIfNeeded(PixelSize size)
+ {
+ using (_syncContext.EnsureLocked())
+ {
+ if (_size != size)
+ {
+ _surfaceInterop.Resize(new UnmanagedMethods.POINT { X = size.Width, Y = size.Height });
+ _contentVisual.SetSize(new Vector2(size.Width, size.Height));
+ _size = size;
+ }
+ }
+ }
+
+ public unsafe IUnknown BeginDrawToTexture(out PixelPoint offset)
+ {
+ if (!_syncContext.IsCurrent)
+ throw new InvalidOperationException();
+
+ var iid = IID_ID3D11Texture2D;
+ void* pTexture;
+ var off = _surfaceInterop.BeginDraw(null, &iid, &pTexture);
+ offset = new PixelPoint(off.X, off.Y);
+ return MicroComRuntime.CreateProxyFor(pTexture, true);
+ }
+
+ public void EndDraw()
+ {
+ if (!_syncContext.IsCurrent)
+ throw new InvalidOperationException();
+ _surfaceInterop.EndDraw();
+ }
+
+ public void SetBlur(bool enable)
+ {
+ using (_syncContext.EnsureLocked())
+ _blurVisual.SetIsVisible(enable ? 1 : 0);
+ }
+
+ public IDisposable BeginTransaction()
+ {
+ Monitor.Enter(_pumpLock);
+ return Disposable.Create(() => Monitor.Exit(_pumpLock));
+ }
+
+ public void Dispose()
+ {
+ if (_syncContext == null)
+ {
+ _compositor.Dispose();
+ _blurVisual.Dispose();
+ _contentVisual.Dispose();
+ _surfaceInterop.Dispose();
+ _compositionTarget.Dispose();
+ }
+ }
+ }
+}
diff --git a/src/Windows/Avalonia.Win32/WinRT/Composition/WinUICompositorConnection.cs b/src/Windows/Avalonia.Win32/WinRT/Composition/WinUICompositorConnection.cs
new file mode 100644
index 0000000000..2aa82436f6
--- /dev/null
+++ b/src/Windows/Avalonia.Win32/WinRT/Composition/WinUICompositorConnection.cs
@@ -0,0 +1,238 @@
+using System;
+using System.Diagnostics;
+using System.Numerics;
+using System.Runtime.InteropServices;
+using System.Threading;
+using System.Threading.Tasks;
+using Avalonia.Logging;
+using Avalonia.MicroCom;
+using Avalonia.OpenGL;
+using Avalonia.OpenGL.Angle;
+using Avalonia.OpenGL.Egl;
+using Avalonia.Rendering;
+using Avalonia.Win32.Interop;
+
+namespace Avalonia.Win32.WinRT.Composition
+{
+ class WinUICompositorConnection : IRenderTimer
+ {
+ private readonly EglContext _syncContext;
+ private IntPtr _queue;
+ private ICompositor _compositor;
+ private ICompositor2 _compositor2;
+ private ICompositor5 _compositor5;
+ private ICompositorInterop _compositorInterop;
+ private AngleWin32EglDisplay _angle;
+ private ICompositionGraphicsDevice _device;
+ private EglPlatformOpenGlInterface _gl;
+ private ICompositorDesktopInterop _compositorDesktopInterop;
+ private ICompositionBrush _blurBrush;
+ private object _pumpLock = new object();
+
+ public WinUICompositorConnection(EglPlatformOpenGlInterface gl, object pumpLock)
+ {
+ _gl = gl;
+ _pumpLock = pumpLock;
+ _syncContext = _gl.PrimaryEglContext;
+ _angle = (AngleWin32EglDisplay)_gl.Display;
+ _compositor = NativeWinRTMethods.CreateInstance("Windows.UI.Composition.Compositor");
+ _compositor2 = _compositor.QueryInterface();
+ _compositor5 = _compositor.QueryInterface();
+ _compositorInterop = _compositor.QueryInterface();
+ _compositorDesktopInterop = _compositor.QueryInterface();
+ using var device = MicroComRuntime.CreateProxyFor(_angle.GetDirect3DDevice(), true);
+
+ _device = _compositorInterop.CreateGraphicsDevice(device);
+ _blurBrush = CreateBlurBrush();
+
+ }
+
+ public EglPlatformOpenGlInterface Egl => _gl;
+
+ static bool TryCreateAndRegisterCore(EglPlatformOpenGlInterface angle)
+ {
+ var tcs = new TaskCompletionSource();
+ var pumpLock = new object();
+ var th = new Thread(() =>
+ {
+ WinUICompositorConnection connect;
+ try
+ {
+ NativeWinRTMethods.CreateDispatcherQueueController(new NativeWinRTMethods.DispatcherQueueOptions
+ {
+ apartmentType = NativeWinRTMethods.DISPATCHERQUEUE_THREAD_APARTMENTTYPE.DQTAT_COM_NONE,
+ dwSize = Marshal.SizeOf(),
+ threadType = NativeWinRTMethods.DISPATCHERQUEUE_THREAD_TYPE.DQTYPE_THREAD_CURRENT
+ });
+ connect = new WinUICompositorConnection(angle, pumpLock);
+ AvaloniaLocator.CurrentMutable.BindToSelf(connect);
+ AvaloniaLocator.CurrentMutable.Bind().ToConstant(connect);
+ tcs.SetResult(true);
+
+ }
+ catch (Exception e)
+ {
+ tcs.SetException(e);
+ return;
+ }
+ connect.RunLoop();
+ })
+ {
+ IsBackground = true
+ };
+ th.SetApartmentState(ApartmentState.STA);
+ th.Start();
+ return tcs.Task.Result;
+ }
+
+ class RunLoopHandler : IAsyncActionCompletedHandler, IMicroComShadowContainer
+ {
+ private readonly WinUICompositorConnection _parent;
+ private Stopwatch _st = Stopwatch.StartNew();
+
+ public RunLoopHandler(WinUICompositorConnection parent)
+ {
+ _parent = parent;
+ }
+ public void Dispose()
+ {
+
+ }
+
+ public void Invoke(IAsyncAction asyncInfo, AsyncStatus asyncStatus)
+ {
+ _parent.Tick?.Invoke(_st.Elapsed);
+ using var act = _parent._compositor5.RequestCommitAsync();
+ act.SetCompleted(this);
+ }
+
+ public MicroComShadow Shadow { get; set; }
+ public void OnReferencedFromNative()
+ {
+ }
+
+ public void OnUnreferencedFromNative()
+ {
+ }
+ }
+
+ private void RunLoop()
+ {
+ {
+ var st = Stopwatch.StartNew();
+ using (var act = _compositor5.RequestCommitAsync())
+ act.SetCompleted(new RunLoopHandler(this));
+ while (true)
+ {
+ UnmanagedMethods.GetMessage(out var msg, IntPtr.Zero, 0, 0);
+ lock (_pumpLock)
+ UnmanagedMethods.DispatchMessage(ref msg);
+ }
+ }
+ }
+
+ public static void TryCreateAndRegister(EglPlatformOpenGlInterface angle)
+ {
+ const int majorRequired = 10;
+ const int buildRequired = 17134;
+
+ var majorInstalled = Win32Platform.WindowsVersion.Major;
+ var buildInstalled = Win32Platform.WindowsVersion.Build;
+
+ if (majorInstalled >= majorRequired &&
+ buildInstalled >= buildRequired)
+ {
+ try
+ {
+ TryCreateAndRegisterCore(angle);
+ }
+ catch (Exception e)
+ {
+ Logger.TryGet(LogEventLevel.Error, "WinUIComposition")
+ ?.Log(null, "Unable to initialize WinUI compositor: {0}", e);
+
+ }
+ }
+
+ var osVersionNotice =
+ $"Windows {majorRequired} Build {buildRequired} is required. Your machine has Windows {majorInstalled} Build {buildInstalled} installed.";
+
+ Logger.TryGet(LogEventLevel.Warning, "WinUIComposition")?.Log(null,
+ $"Unable to initialize WinUI compositor: {osVersionNotice}");
+ }
+
+
+ public WinUICompositedWindow CreateWindow(IntPtr hWnd)
+ {
+ using var sc = _syncContext.EnsureLocked();
+ using var desktopTarget = _compositorDesktopInterop.CreateDesktopWindowTarget(hWnd, 0);
+ using var target = desktopTarget.QueryInterface();
+
+ using var drawingSurface = _device.CreateDrawingSurface(new UnmanagedMethods.SIZE(), DirectXPixelFormat.B8G8R8A8UIntNormalized,
+ DirectXAlphaMode.Premultiplied);
+ using var surface = drawingSurface.QueryInterface();
+ using var surfaceInterop = drawingSurface.QueryInterface();
+
+ using var surfaceBrush = _compositor.CreateSurfaceBrushWithSurface(surface);
+ using var brush = surfaceBrush.QueryInterface();
+
+ using var spriteVisual = _compositor.CreateSpriteVisual();
+ spriteVisual.SetBrush(brush);
+ using var visual = spriteVisual.QueryInterface();
+ using var visual2 = spriteVisual.QueryInterface();
+ using var container = _compositor.CreateContainerVisual();
+ using var containerVisual = container.QueryInterface();
+ using var containerVisual2 = container.QueryInterface();
+ containerVisual2.SetRelativeSizeAdjustment(new Vector2(1, 1));
+ using var containerChildren = container.Children;
+
+ target.SetRoot(containerVisual);
+
+ using var blur = CreateBlurVisual();
+
+ containerChildren.InsertAtTop(blur);
+ containerChildren.InsertAtTop(visual);
+
+ return new WinUICompositedWindow(_syncContext, _compositor, _pumpLock, target, surfaceInterop, visual, blur);
+ }
+
+
+ private unsafe ICompositionBrush CreateBlurBrush()
+ {
+ using var backDropParameterFactory = NativeWinRTMethods.CreateActivationFactory(
+ "Windows.UI.Composition.CompositionEffectSourceParameter");
+ using var backdropString = new HStringInterop("backdrop");
+ using var backDropParameter =
+ backDropParameterFactory.Create(backdropString.Handle);
+ using var backDropParameterAsSource = backDropParameter.QueryInterface();
+ var blurEffect = new WinUIGaussianBlurEffect(backDropParameterAsSource);
+ using var blurEffectFactory = _compositor.CreateEffectFactory(blurEffect);
+ using var backdrop = _compositor2.CreateBackdropBrush();
+ using var backdropBrush = backdrop.QueryInterface();
+
+
+ var saturateEffect = new SaturationEffect(blurEffect);
+ using var satEffectFactory = _compositor.CreateEffectFactory(saturateEffect);
+ using var sat = satEffectFactory.CreateBrush();
+ sat.SetSourceParameter(backdropString.Handle, backdropBrush);
+ return sat.QueryInterface();
+ }
+
+ private unsafe IVisual CreateBlurVisual()
+ {
+ using var spriteVisual = _compositor.CreateSpriteVisual();
+ using var visual = spriteVisual.QueryInterface();
+ using var visual2 = spriteVisual.QueryInterface();
+
+
+ spriteVisual.SetBrush(_blurBrush);
+ visual.SetIsVisible(0);
+ visual2.SetRelativeSizeAdjustment(new Vector2(1.0f, 1.0f));
+
+ return visual.CloneReference();
+ }
+
+
+ public event Action Tick;
+ }
+}
diff --git a/src/Windows/Avalonia.Win32/WinRT/Composition/WinUIEffectBase.cs b/src/Windows/Avalonia.Win32/WinRT/Composition/WinUIEffectBase.cs
new file mode 100644
index 0000000000..ea75a2f311
--- /dev/null
+++ b/src/Windows/Avalonia.Win32/WinRT/Composition/WinUIEffectBase.cs
@@ -0,0 +1,135 @@
+using System;
+using System.Linq;
+using System.Runtime.InteropServices;
+using Avalonia.MicroCom;
+
+namespace Avalonia.Win32.WinRT.Composition
+{
+ abstract class WinUIEffectBase : WinRTInspectable, IGraphicsEffect, IGraphicsEffectSource, IGraphicsEffectD2D1Interop
+ {
+ private IGraphicsEffectSource[] _sources;
+
+ public WinUIEffectBase(params IGraphicsEffectSource[] _sources)
+ {
+ this._sources = _sources.Select(e =>
+ {
+ if (e is WinUIEffectBase)
+ return e;
+ return e.CloneReference();
+ }).ToArray();
+ }
+
+ public IntPtr Name => IntPtr.Zero;
+
+ public void SetName(IntPtr name)
+ {
+
+ }
+
+ public abstract Guid EffectId { get; }
+ public unsafe void GetNamedPropertyMapping(IntPtr name, uint* index, GRAPHICS_EFFECT_PROPERTY_MAPPING* mapping) =>
+ throw new COMException("Not supported", unchecked((int)0x80004001));
+
+ public abstract uint PropertyCount { get; }
+ public abstract IPropertyValue GetProperty(uint index);
+
+ public IGraphicsEffectSource GetSource(uint index)
+ {
+ if (_sources == null || index> _sources.Length)
+ throw new COMException("Invalid index", unchecked((int)0x80070057));
+ return _sources[index];
+ }
+
+ public uint SourceCount => (uint)(_sources?.Length ?? 0);
+
+ public override void OnUnreferencedFromNative()
+ {
+ if (_sources == null)
+ return;
+
+ /*foreach(var s in _sources)
+ s.Dispose();*/
+ _sources = null;
+ }
+ }
+
+ class WinUIGaussianBlurEffect : WinUIEffectBase
+ {
+ public WinUIGaussianBlurEffect(IGraphicsEffectSource source) : base(source)
+ {
+ }
+
+ enum D2D1_GAUSSIANBLUR_OPTIMIZATION
+ {
+ D2D1_GAUSSIANBLUR_OPTIMIZATION_SPEED,
+ D2D1_GAUSSIANBLUR_OPTIMIZATION_BALANCED,
+ D2D1_GAUSSIANBLUR_OPTIMIZATION_QUALITY,
+ D2D1_GAUSSIANBLUR_OPTIMIZATION_FORCE_DWORD
+ };
+
+ enum D2D1_BORDER_MODE
+ {
+ D2D1_BORDER_MODE_SOFT,
+ D2D1_BORDER_MODE_HARD,
+ D2D1_BORDER_MODE_FORCE_DWORD
+ };
+
+ enum D2D1GaussianBlurProp
+ {
+ D2D1_GAUSSIANBLUR_PROP_STANDARD_DEVIATION,
+ D2D1_GAUSSIANBLUR_PROP_OPTIMIZATION,
+ D2D1_GAUSSIANBLUR_PROP_BORDER_MODE,
+ D2D1_GAUSSIANBLUR_PROP_FORCE_DWORD
+ };
+
+ public override Guid EffectId => D2DEffects.CLSID_D2D1GaussianBlur;
+
+ public override uint PropertyCount => 3;
+
+ public override IPropertyValue GetProperty(uint index)
+ {
+ switch ((D2D1GaussianBlurProp)index)
+ {
+ case D2D1GaussianBlurProp.D2D1_GAUSSIANBLUR_PROP_STANDARD_DEVIATION:
+ return new WinRTPropertyValue(30.0f);
+
+ case D2D1GaussianBlurProp.D2D1_GAUSSIANBLUR_PROP_OPTIMIZATION:
+ return new WinRTPropertyValue((uint)D2D1_GAUSSIANBLUR_OPTIMIZATION
+ .D2D1_GAUSSIANBLUR_OPTIMIZATION_BALANCED);
+
+ case D2D1GaussianBlurProp.D2D1_GAUSSIANBLUR_PROP_BORDER_MODE:
+ return new WinRTPropertyValue((uint)D2D1_BORDER_MODE.D2D1_BORDER_MODE_HARD);
+ }
+
+ return null;
+ }
+ }
+
+ class SaturationEffect : WinUIEffectBase
+ {
+ public SaturationEffect(IGraphicsEffectSource source) : base(source)
+ {
+ }
+
+ enum D2D1_SATURATION_PROP
+ {
+ D2D1_SATURATION_PROP_SATURATION,
+ D2D1_SATURATION_PROP_FORCE_DWORD
+ };
+
+ public override Guid EffectId => D2DEffects.CLSID_D2D1Saturation;
+
+ public override uint PropertyCount => 1;
+
+ public override IPropertyValue GetProperty(uint index)
+ {
+ switch ((D2D1_SATURATION_PROP)index)
+ {
+ case D2D1_SATURATION_PROP.D2D1_SATURATION_PROP_SATURATION:
+ return new WinRTPropertyValue(2.0f);
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindowSurface.cs b/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindowSurface.cs
new file mode 100644
index 0000000000..f59d50860a
--- /dev/null
+++ b/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindowSurface.cs
@@ -0,0 +1,118 @@
+using System;
+using System.Runtime.InteropServices;
+using Avalonia.MicroCom;
+using Avalonia.OpenGL.Angle;
+using Avalonia.OpenGL.Egl;
+using Avalonia.OpenGL.Surfaces;
+using Avalonia.Utilities;
+using Avalonia.Win32.Interop;
+
+namespace Avalonia.Win32.WinRT.Composition
+{
+ internal class WinUiCompositedWindowSurface : EglGlPlatformSurfaceBase, IBlurHost, IDisposable
+ {
+ private readonly WinUICompositorConnection _connection;
+ private EglPlatformOpenGlInterface _egl;
+ private readonly EglGlPlatformSurfaceBase.IEglWindowGlPlatformSurfaceInfo _info;
+ private IRef _window;
+ private bool _enableBlur;
+
+ public WinUiCompositedWindowSurface(WinUICompositorConnection connection, IEglWindowGlPlatformSurfaceInfo info) : base()
+ {
+ _connection = connection;
+ _egl = connection.Egl;
+ _info = info;
+ }
+
+ public override IGlPlatformSurfaceRenderTarget CreateGlRenderTarget()
+ {
+ using (_egl.PrimaryContext.EnsureCurrent())
+ {
+ if (_window?.Item == null)
+ {
+ _window = RefCountable.Create(_connection.CreateWindow(_info.Handle));
+ _window.Item.SetBlur(_enableBlur);
+ }
+
+ return new CompositionRenderTarget(_egl, _window, _info);
+ }
+ }
+
+ class CompositionRenderTarget : EglPlatformSurfaceRenderTargetBase
+ {
+ private readonly EglPlatformOpenGlInterface _egl;
+ private readonly IRef _window;
+ private readonly IEglWindowGlPlatformSurfaceInfo _info;
+
+ public CompositionRenderTarget(EglPlatformOpenGlInterface egl,
+ IRef window,
+ IEglWindowGlPlatformSurfaceInfo info)
+ : base(egl)
+ {
+ _egl = egl;
+ _window = window.Clone();
+ _info = info;
+ _window.Item.ResizeIfNeeded(_info.Size);
+ }
+
+ public override IGlPlatformSurfaceRenderingSession BeginDraw()
+ {
+ var contextLock = _egl.PrimaryEglContext.EnsureCurrent();
+ IUnknown texture = null;
+ EglSurface surface = null;
+ IDisposable transaction = null;
+ var success = false;
+ try
+ {
+ if (_window?.Item == null)
+ throw new ObjectDisposedException(GetType().FullName);
+
+ var size = _info.Size;
+ transaction = _window.Item.BeginTransaction();
+ _window.Item.ResizeIfNeeded(size);
+ texture = _window.Item.BeginDrawToTexture(out var offset);
+
+ surface = ((AngleWin32EglDisplay) _egl.Display).WrapDirect3D11Texture(_egl,
+ texture.GetNativeIntPtr(),
+ offset.X, offset.Y, size.Width, size.Height);
+
+ var res = base.BeginDraw(surface, _info, () =>
+ {
+ surface?.Dispose();
+ texture?.Dispose();
+ _window.Item.EndDraw();
+ transaction?.Dispose();
+ contextLock?.Dispose();
+ }, true);
+ success = true;
+ return res;
+ }
+ finally
+ {
+ if (!success)
+ {
+ surface?.Dispose();
+ texture?.Dispose();
+ transaction?.Dispose();
+ contextLock.Dispose();
+ }
+ }
+ }
+ }
+
+ public void SetBlur(bool enable)
+ {
+ _enableBlur = enable;
+ _window?.Item?.SetBlur(enable);
+ }
+
+ public void Dispose()
+ {
+ using (_egl.PrimaryEglContext.EnsureLocked())
+ {
+ _window?.Dispose();
+ _window = null;
+ }
+ }
+ }
+}
diff --git a/src/Windows/Avalonia.Win32/WinRT/IBlurHost.cs b/src/Windows/Avalonia.Win32/WinRT/IBlurHost.cs
new file mode 100644
index 0000000000..81c0e3e185
--- /dev/null
+++ b/src/Windows/Avalonia.Win32/WinRT/IBlurHost.cs
@@ -0,0 +1,7 @@
+namespace Avalonia.Win32.WinRT
+{
+ public interface IBlurHost
+ {
+ void SetBlur(bool enable);
+ }
+}
diff --git a/src/Windows/Avalonia.Win32/WinRT/NativeWinRTMethods.cs b/src/Windows/Avalonia.Win32/WinRT/NativeWinRTMethods.cs
new file mode 100644
index 0000000000..087bd2fd43
--- /dev/null
+++ b/src/Windows/Avalonia.Win32/WinRT/NativeWinRTMethods.cs
@@ -0,0 +1,140 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.IO;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.WindowsRuntime;
+using System.Threading;
+using Avalonia.MicroCom;
+using Avalonia.Win32.Interop;
+
+namespace Avalonia.Win32.WinRT
+{
+ internal static class NativeWinRTMethods
+ {
+ [DllImport("api-ms-win-core-winrt-string-l1-1-0.dll", CallingConvention = CallingConvention.StdCall,
+ PreserveSig = false)]
+ internal static extern unsafe IntPtr WindowsCreateString(
+ [MarshalAs(UnmanagedType.LPWStr)] string sourceString,
+ int length);
+
+ internal static IntPtr WindowsCreateString(string sourceString)
+ => WindowsCreateString(sourceString, sourceString.Length);
+
+ [DllImport("api-ms-win-core-winrt-string-l1-1-0.dll",
+ CallingConvention = CallingConvention.StdCall, PreserveSig = false)]
+ internal static extern unsafe IntPtr WindowsDeleteString(IntPtr hString);
+
+ [DllImport("Windows.UI.Composition", EntryPoint = "DllGetActivationFactory",
+ CallingConvention = CallingConvention.StdCall, PreserveSig = false)]
+ private extern static IntPtr GetWindowsUICompositionActivationFactory(
+ IntPtr activatableClassId);
+
+ internal static IActivationFactory GetWindowsUICompositionActivationFactory(string className)
+ {//"Windows.UI.Composition.Compositor"
+ var s = WindowsCreateString(className);
+ var factory = GetWindowsUICompositionActivationFactory(s);
+ return MicroComRuntime.CreateProxyFor(factory, true);
+ }
+
+ [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+ delegate int GetActivationFactoryDelegate(IntPtr classId, out IntPtr ppv);
+
+ internal static T CreateInstance(string fullName) where T : IUnknown
+ {
+ var s = WindowsCreateString(fullName);
+ EnsureRoInitialized();
+ var pUnk = RoActivateInstance(s);
+ using var unk = MicroComRuntime.CreateProxyFor(pUnk, true);
+ WindowsDeleteString(s);
+ return MicroComRuntime.QueryInterface(unk);
+ }
+
+ internal static TFactory CreateActivationFactory(string fullName) where TFactory : IUnknown
+ {
+ var s = WindowsCreateString(fullName);
+ EnsureRoInitialized();
+ var guid = MicroComRuntime.GetGuidFor(typeof(TFactory));
+ var pUnk = RoGetActivationFactory(s, ref guid);
+ using var unk = MicroComRuntime.CreateProxyFor(pUnk, true);
+ WindowsDeleteString(s);
+ return MicroComRuntime.QueryInterface(unk);
+ }
+
+ internal enum DISPATCHERQUEUE_THREAD_APARTMENTTYPE
+ {
+ DQTAT_COM_NONE = 0,
+ DQTAT_COM_ASTA = 1,
+ DQTAT_COM_STA = 2
+ };
+
+ internal enum DISPATCHERQUEUE_THREAD_TYPE
+ {
+ DQTYPE_THREAD_DEDICATED = 1,
+ DQTYPE_THREAD_CURRENT = 2,
+ };
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct DispatcherQueueOptions
+ {
+ public int dwSize;
+
+ [MarshalAs(UnmanagedType.I4)]
+ public DISPATCHERQUEUE_THREAD_TYPE threadType;
+
+ [MarshalAs(UnmanagedType.I4)]
+ public DISPATCHERQUEUE_THREAD_APARTMENTTYPE apartmentType;
+ };
+
+ [DllImport("coremessaging.dll", PreserveSig = false)]
+ internal static extern IntPtr CreateDispatcherQueueController(DispatcherQueueOptions options);
+
+ internal enum RO_INIT_TYPE
+ {
+ RO_INIT_SINGLETHREADED = 0, // Single-threaded application
+ RO_INIT_MULTITHREADED = 1, // COM calls objects on any thread.
+ }
+
+ [DllImport("combase.dll", PreserveSig = false)]
+ private static extern void RoInitialize(RO_INIT_TYPE initType);
+
+ [DllImport("combase.dll", PreserveSig = false)]
+ private static extern IntPtr RoActivateInstance(IntPtr activatableClassId);
+
+ [DllImport("combase.dll", PreserveSig = false)]
+ private static extern IntPtr RoGetActivationFactory(IntPtr activatableClassId, ref Guid iid);
+
+ private static bool _initialized;
+ private static void EnsureRoInitialized()
+ {
+ if (_initialized)
+ return;
+ RoInitialize(Thread.CurrentThread.GetApartmentState() == ApartmentState.STA ?
+ RO_INIT_TYPE.RO_INIT_SINGLETHREADED :
+ RO_INIT_TYPE.RO_INIT_MULTITHREADED);
+ _initialized = true;
+ }
+ }
+
+ class HStringInterop : IDisposable
+ {
+ private IntPtr _s;
+
+ public HStringInterop(string s)
+ {
+ _s = s == null ? IntPtr.Zero : NativeWinRTMethods.WindowsCreateString(s);
+ }
+
+ public IntPtr Handle => _s;
+
+ public void Dispose()
+ {
+ if (_s != IntPtr.Zero)
+ {
+ NativeWinRTMethods.WindowsDeleteString(_s);
+ _s = IntPtr.Zero;
+ }
+ }
+ }
+}
diff --git a/src/Windows/Avalonia.Win32/WinRT/WinRTColor.cs b/src/Windows/Avalonia.Win32/WinRT/WinRTColor.cs
new file mode 100644
index 0000000000..786d698daa
--- /dev/null
+++ b/src/Windows/Avalonia.Win32/WinRT/WinRTColor.cs
@@ -0,0 +1,18 @@
+using System.Runtime.InteropServices;
+
+namespace Avalonia.Win32.WinRT
+{
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ public struct WinRTColor
+ {
+ public byte A;
+ public byte R;
+ public byte G;
+ public byte B;
+
+ public static WinRTColor FromArgb(byte a, byte r, byte g, byte b) => new WinRTColor()
+ {
+ A = a, R = r, G = g, B = b
+ };
+ }
+}
diff --git a/src/Windows/Avalonia.Win32/WinRT/WinRTInspectable.cs b/src/Windows/Avalonia.Win32/WinRT/WinRTInspectable.cs
new file mode 100644
index 0000000000..d2ec957b8e
--- /dev/null
+++ b/src/Windows/Avalonia.Win32/WinRT/WinRTInspectable.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using Avalonia.MicroCom;
+
+namespace Avalonia.Win32.WinRT
+{
+ class WinRTInspectable : IInspectable, IMicroComShadowContainer
+ {
+ public virtual void Dispose()
+ {
+
+ }
+
+ public unsafe void GetIids(ulong* iidCount, Guid** iids)
+ {
+ var interfaces = GetType().GetInterfaces().Where(typeof(IUnknown).IsAssignableFrom)
+ .Select(MicroComRuntime.GetGuidFor).ToArray();
+ var mem = (Guid*)Marshal.AllocCoTaskMem(Unsafe.SizeOf() * interfaces.Length);
+ for (var c = 0; c < interfaces.Length; c++)
+ mem[c] = interfaces[c];
+ *iids = mem;
+ *iidCount = (ulong) interfaces.Length;
+ }
+
+ public IntPtr RuntimeClassName => NativeWinRTMethods.WindowsCreateString(GetType().FullName);
+ public TrustLevel TrustLevel => TrustLevel.BaseTrust;
+ public MicroComShadow Shadow { get; set; }
+ public virtual void OnReferencedFromNative()
+ {
+ }
+
+ public virtual void OnUnreferencedFromNative()
+ {
+ }
+ }
+}
diff --git a/src/Windows/Avalonia.Win32/WinRT/WinRTPropertyValue.cs b/src/Windows/Avalonia.Win32/WinRT/WinRTPropertyValue.cs
new file mode 100644
index 0000000000..684e7ff7b5
--- /dev/null
+++ b/src/Windows/Avalonia.Win32/WinRT/WinRTPropertyValue.cs
@@ -0,0 +1,89 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace Avalonia.Win32.WinRT
+{
+ class WinRTPropertyValue : WinRTInspectable, IPropertyValue
+ {
+ public WinRTPropertyValue(float f)
+ {
+ Type = PropertyType.Single;
+ Single = f;
+ }
+
+ public WinRTPropertyValue(uint u)
+ {
+ UInt32 = u;
+ Type = PropertyType.UInt32;
+ }
+
+ public PropertyType Type { get; }
+ public int IsNumericScalar { get; }
+ public byte UInt8 { get; }
+ public short Int16 { get; }
+ public ushort UInt16 { get; }
+ public int Int32 { get; }
+ public uint UInt32 { get; }
+ public long Int64 { get; }
+ public ulong UInt64 { get; }
+ public float Single { get; }
+ public double Double { get; }
+ public char Char16 { get; }
+ public int Boolean { get; }
+ public IntPtr String { get; }
+ public Guid Guid { get; }
+
+ private static COMException NotImplemented => new COMException("Not supported", unchecked((int)0x80004001));
+
+ public unsafe void GetDateTime(void* value) => throw NotImplemented;
+
+ public unsafe void GetTimeSpan(void* value) => throw NotImplemented;
+
+ public unsafe void GetPoint(void* value) => throw NotImplemented;
+
+ public unsafe void GetSize(void* value) => throw NotImplemented;
+
+ public unsafe void GetRect(void* value) => throw NotImplemented;
+
+ public unsafe byte* GetUInt8Array(uint* __valueSize) => throw NotImplemented;
+
+ public unsafe short* GetInt16Array(uint* __valueSize) => throw NotImplemented;
+
+ public unsafe ushort* GetUInt16Array(uint* __valueSize) => throw NotImplemented;
+
+ public unsafe int* GetInt32Array(uint* __valueSize)
+ {
+ throw NotImplemented;
+ }
+
+ public unsafe uint* GetUInt32Array(uint* __valueSize) => throw NotImplemented;
+
+ public unsafe long* GetInt64Array(uint* __valueSize) => throw NotImplemented;
+
+ public unsafe ulong* GetUInt64Array(uint* __valueSize) => throw NotImplemented;
+
+ public unsafe float* GetSingleArray(uint* __valueSize) => throw NotImplemented;
+
+ public unsafe double* GetDoubleArray(uint* __valueSize) => throw NotImplemented;
+
+ public unsafe char* GetChar16Array(uint* __valueSize) => throw NotImplemented;
+
+ public unsafe int* GetBooleanArray(uint* __valueSize) => throw NotImplemented;
+
+ public unsafe IntPtr* GetStringArray(uint* __valueSize) => throw NotImplemented;
+
+ public unsafe void** GetInspectableArray(uint* __valueSize) => throw NotImplemented;
+
+ public unsafe Guid* GetGuidArray(uint* __valueSize) => throw NotImplemented;
+
+ public unsafe void* GetDateTimeArray(uint* __valueSize) => throw NotImplemented;
+
+ public unsafe void* GetTimeSpanArray(uint* __valueSize) => throw NotImplemented;
+
+ public unsafe void* GetPointArray(uint* __valueSize) => throw NotImplemented;
+
+ public unsafe void* GetSizeArray(uint* __valueSize) => throw NotImplemented;
+
+ public unsafe void* GetRectArray(uint* __valueSize) => throw NotImplemented;
+ }
+}
diff --git a/src/Windows/Avalonia.Win32/WinRT/winrt.idl b/src/Windows/Avalonia.Win32/WinRT/winrt.idl
new file mode 100644
index 0000000000..929377999c
--- /dev/null
+++ b/src/Windows/Avalonia.Win32/WinRT/winrt.idl
@@ -0,0 +1,718 @@
+@clr-namespace Avalonia.Win32.WinRT
+@clr-access internal
+@clr-map FLOAT float
+@clr-map HSTRING IntPtr
+@clr-map Vector2 System.Numerics.Vector2
+@clr-map Vector3 System.Numerics.Vector3
+@clr-map Quaternion System.Numerics.Quaternion
+@clr-map Matrix4x4 System.Numerics.Matrix4x4
+@clr-map RECT Avalonia.Win32.Interop.UnmanagedMethods.RECT
+@clr-map SIZE Avalonia.Win32.Interop.UnmanagedMethods.SIZE
+@clr-map POINT Avalonia.Win32.Interop.UnmanagedMethods.POINT
+@clr-map HWND IntPtr
+@clr-map BOOL int
+@clr-map DWORD int
+@clr-map boolean int
+@clr-map BYTE byte
+@clr-map INT16 short
+@clr-map INT32 int
+@clr-map INT64 long
+@clr-map UINT16 ushort
+@clr-map UINT32 uint
+@clr-map UINT64 ulong
+@clr-map DOUBLE double
+@clr-map GUID System.Guid
+@clr-map WCHAR System.Char
+@clr-map Color Avalonia.Win32.WinRT.WinRTColor
+
+enum TrustLevel
+{
+ BaseTrust,
+ PartialTrust,
+ FullTrust
+}
+
+enum DirectXAlphaMode
+{
+ Unspecified,
+ Premultiplied,
+ Straight,
+ Ignore
+}
+
+enum DirectXPixelFormat
+{
+ Unknown = 0,
+ R32G32B32A32Typeless = 1,
+ R32G32B32A32Float = 2,
+ R32G32B32A32UInt = 3,
+ R32G32B32A32Int = 4,
+ R32G32B32Typeless = 5,
+ R32G32B32Float = 6,
+ R32G32B32UInt = 7,
+ R32G32B32Int = 8,
+ R16G16B16A16Typeless = 9,
+ R16G16B16A16Float = 10,
+ R16G16B16A16UIntNormalized = 11,
+ R16G16B16A16UInt = 12,
+ R16G16B16A16IntNormalized = 13,
+ R16G16B16A16Int = 14,
+ R32G32Typeless = 15,
+ R32G32Float = 16,
+ R32G32UInt = 17,
+ R32G32Int = 18,
+ R32G8X24Typeless = 19,
+ D32FloatS8X24UInt = 20,
+ R32FloatX8X24Typeless = 21,
+ X32TypelessG8X24UInt = 22,
+ R10G10B10A2Typeless = 23,
+ R10G10B10A2UIntNormalized = 24,
+ R10G10B10A2UInt = 25,
+ R11G11B10Float = 26,
+ R8G8B8A8Typeless = 27,
+ R8G8B8A8UIntNormalized = 28,
+ R8G8B8A8UIntNormalizedSrgb = 29,
+ R8G8B8A8UInt = 30,
+ R8G8B8A8IntNormalized = 31,
+ R8G8B8A8Int = 32,
+ R16G16Typeless = 33,
+ R16G16Float = 34,
+ R16G16UIntNormalized = 35,
+ R16G16UInt = 36,
+ R16G16IntNormalized = 37,
+ R16G16Int = 38,
+ R32Typeless = 39,
+ D32Float = 40,
+ R32Float = 41,
+ R32UInt = 42,
+ R32Int = 43,
+ R24G8Typeless = 44,
+ D24UIntNormalizedS8UInt = 45,
+ R24UIntNormalizedX8Typeless = 46,
+ X24TypelessG8UInt = 47,
+ R8G8Typeless = 48,
+ R8G8UIntNormalized = 49,
+ R8G8UInt = 50,
+ R8G8IntNormalized = 51,
+ R8G8Int = 52,
+ R16Typeless = 53,
+ R16Float = 54,
+ D16UIntNormalized = 55,
+ R16UIntNormalized = 56,
+ R16UInt = 57,
+ R16IntNormalized = 58,
+ R16Int = 59,
+ R8Typeless = 60,
+ R8UIntNormalized = 61,
+ R8UInt = 62,
+ R8IntNormalized = 63,
+ R8Int = 64,
+ A8UIntNormalized = 65,
+ R1UIntNormalized = 66,
+ R9G9B9E5SharedExponent = 67,
+ R8G8B8G8UIntNormalized = 68,
+ G8R8G8B8UIntNormalized = 69,
+ BC1Typeless = 70,
+ BC1UIntNormalized = 71,
+ BC1UIntNormalizedSrgb = 72,
+ BC2Typeless = 73,
+ BC2UIntNormalized = 74,
+ BC2UIntNormalizedSrgb = 75,
+ BC3Typeless = 76,
+ BC3UIntNormalized = 77,
+ BC3UIntNormalizedSrgb = 78,
+ BC4Typeless = 79,
+ BC4UIntNormalized = 80,
+ BC4IntNormalized = 81,
+ BC5Typeless = 82,
+ BC5UIntNormalized = 83,
+ BC5IntNormalized = 84,
+ B5G6R5UIntNormalized = 85,
+ B5G5R5A1UIntNormalized = 86,
+ B8G8R8A8UIntNormalized = 87,
+ B8G8R8X8UIntNormalized = 88,
+ R10G10B10XRBiasA2UIntNormalized = 89,
+ B8G8R8A8Typeless = 90,
+ B8G8R8A8UIntNormalizedSrgb = 91,
+ B8G8R8X8Typeless = 92,
+ B8G8R8X8UIntNormalizedSrgb = 93,
+ BC6HTypeless = 94,
+ BC6H16UnsignedFloat = 95,
+ BC6H16Float = 96,
+ BC7Typeless = 97,
+ BC7UIntNormalized = 98,
+ BC7UIntNormalizedSrgb = 99,
+ Ayuv = 100,
+ Y410 = 101,
+ Y416 = 102,
+ NV12 = 103,
+ P010 = 104,
+ P016 = 105,
+ Opaque420 = 106,
+ Yuy2 = 107,
+ Y210 = 108,
+ Y216 = 109,
+ NV11 = 110,
+ AI44 = 111,
+ IA44 = 112,
+ P8 = 113,
+ A8P8 = 114,
+ B4G4R4A4UIntNormalized = 115,
+ P208 = 130,
+ V208 = 131,
+ V408 = 132,
+}
+
+[uuid(AF86E2E0-B12D-4c6a-9C5A-D7AA65101E90)]
+interface IInspectable : IUnknown
+{
+ HRESULT GetIids(ulong * iidCount, Guid ** iids);
+ HRESULT GetRuntimeClassName( [out] IntPtr* className);
+ HRESULT GetTrustLevel([out] TrustLevel * trustLevel);
+}
+
+enum PropertyType
+{
+ Empty = 0,
+ UInt8 = 1,
+ Int16 = 2,
+ UInt16 = 3,
+ Int32 = 4,
+ UInt32 = 5,
+ Int64 = 6,
+ UInt64 = 7,
+ Single = 8,
+ Double = 9,
+ Char16 = 10,
+ Boolean = 11,
+ String = 12,
+ Inspectable = 13,
+ DateTime = 14,
+ TimeSpan = 15,
+ Guid = 16,
+ Point = 17,
+ Size = 18,
+ Rect = 19,
+ OtherType = 20,
+ UInt8Array = 1025,
+ Int16Array = 1026,
+ UInt16Array = 1027,
+ Int32Array = 1028,
+ UInt32Array = 1029,
+ Int64Array = 1030,
+ UInt64Array = 1031,
+ SingleArray = 1032,
+ DoubleArray = 1033,
+ Char16Array = 1034,
+ BooleanArray = 1035,
+ StringArray = 1036,
+ InspectableArray = 1037,
+ DateTimeArray = 1038,
+ TimeSpanArray = 1039,
+ GuidArray = 1040,
+ PointArray = 1041,
+ SizeArray = 1042,
+ RectArray = 1043,
+ OtherTypeArray = 1044
+}
+
+[uuid(4BD682DD-7554-40E9-9A9B-82654EDE7E62)]
+interface IPropertyValue : IInspectable
+{
+ [propget] HRESULT Type([out] [retval] PropertyType* value);
+ [propget] HRESULT IsNumericScalar([out] [retval] boolean* value);
+ HRESULT GetUInt8([out] [retval] BYTE* value);
+ HRESULT GetInt16([out] [retval] INT16* value);
+ HRESULT GetUInt16([out] [retval] UINT16* value);
+ HRESULT GetInt32([out] [retval] INT32* value);
+ HRESULT GetUInt32([out] [retval] UINT32* value);
+ HRESULT GetInt64([out] [retval] INT64* value);
+ HRESULT GetUInt64([out] [retval] UINT64* value);
+ HRESULT GetSingle([out] [retval] FLOAT* value);
+ HRESULT GetDouble([out] [retval] DOUBLE* value);
+ HRESULT GetChar16([out] [retval] WCHAR* value);
+ HRESULT GetBoolean([out] [retval] boolean* value);
+ HRESULT GetString([out] [retval] HSTRING* value);
+ HRESULT GetGuid([out] [retval] GUID* value);
+ HRESULT GetDateTime( void* value);
+ HRESULT GetTimeSpan(void* value);
+ HRESULT GetPoint(void* value);
+ HRESULT GetSize(void* value);
+ HRESULT GetRect(void* value);
+ HRESULT GetUInt8Array([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] BYTE** value);
+ HRESULT GetInt16Array([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] INT16** value);
+ HRESULT GetUInt16Array([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] UINT16** value);
+ HRESULT GetInt32Array([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] INT32** value);
+ HRESULT GetUInt32Array([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] UINT32** value);
+ HRESULT GetInt64Array([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] INT64** value);
+ HRESULT GetUInt64Array([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] UINT64** value);
+ HRESULT GetSingleArray([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] FLOAT** value);
+ HRESULT GetDoubleArray([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] DOUBLE** value);
+ HRESULT GetChar16Array([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] WCHAR** value);
+ HRESULT GetBooleanArray([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] boolean** value);
+ HRESULT GetStringArray([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] HSTRING** value);
+ HRESULT GetInspectableArray([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] void*** value);
+ HRESULT GetGuidArray([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] GUID** value);
+ HRESULT GetDateTimeArray([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] void** value);
+ HRESULT GetTimeSpanArray([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] void** value);
+ HRESULT GetPointArray([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] void** value);
+ HRESULT GetSizeArray([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] void** value);
+ HRESULT GetRectArray([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] void** value);
+}
+
+enum AsyncStatus {
+ Started = 0,
+ Completed,
+ Canceled,
+ Error,
+}
+
+[uuid(A4ED5C81-76C9-40BD-8BE6-B1D90FB20AE7)]
+interface IAsyncActionCompletedHandler : IUnknown
+{
+ HRESULT Invoke([in] IAsyncAction* asyncInfo, [in] AsyncStatus asyncStatus);
+}
+
+[uuid(5A648006-843A-4DA9-865B-9D26E5DFAD7B)]
+interface IAsyncAction : IInspectable
+{
+ HRESULT SetCompleted([in] IAsyncActionCompletedHandler* handler);
+ HRESULT GetCompleted([out] [retval] IAsyncActionCompletedHandler** ppv);
+ HRESULT GetResults();
+}
+
+[uuid(603E88E4-A338-4FFE-A457-A5CFB9CEB899)]
+interface IDispatcherQueue : IInspectable
+{
+ //TODO
+}
+
+[uuid(22F34E66-50DB-4E36-A98D-61C01B384D20)]
+interface IDispatcherQueueController : IInspectable
+{
+ [propget] HRESULT DispatcherQueue([out] [retval] IDispatcherQueue** value);
+ HRESULT ShutdownQueueAsync([out] [retval] IAsyncAction** operation);
+}
+
+[uuid(00000035-0000-0000-C000-000000000046)]
+interface IActivationFactory : IInspectable
+{
+ HRESULT ActivateInstance([out, retval] IntPtr* instance);
+}
+
+[flags]
+enum CompositionBatchTypes
+{
+ None = 0x0,
+ Animation = 0x1,
+ Effect = 0x2,
+ InfiniteAnimation = 0x4,
+ AllAnimations = 0x5
+}
+
+[uuid(B403CA50-7F8C-4E83-985F-CC45060036D8)]
+interface ICompositor : IInspectable
+{
+ HRESULT CreateColorKeyFrameAnimation([out] [retval] void** result);
+ [overload("CreateColorBrush")] HRESULT CreateColorBrush([out] [retval]void** result);
+ [overload("CreateColorBrush")] HRESULT CreateColorBrushWithColor([in] Color* color, [out] [retval] ICompositionColorBrush** result);
+ HRESULT CreateContainerVisual([out] [retval] IContainerVisual** result);
+ HRESULT CreateCubicBezierEasingFunction([in] Vector2 controlPoint1, [in] Vector2 controlPoint2, [out] [retval] void** result);
+ [overload("CreateEffectFactory")] HRESULT CreateEffectFactory([in] IGraphicsEffect* graphicsEffect, [out] [retval] ICompositionEffectFactory** result);
+ [overload("CreateEffectFactory")] HRESULT CreateEffectFactoryWithProperties([in] void* graphicsEffect, [in] void* animatableProperties, [out] [retval] void** result);
+ [overload("CreateExpressionAnimation")] HRESULT CreateExpressionAnimation([out] [retval] void** result);
+ [overload("CreateExpressionAnimation")] HRESULT CreateExpressionAnimationWithExpression([in] HSTRING expression, [out] [retval] void** result);
+ [overload("CreateInsetClip")] HRESULT CreateInsetClip([out] [retval] void** result);
+ [overload("CreateInsetClip")] HRESULT CreateInsetClipWithInsets([in] FLOAT leftInset, [in] FLOAT topInset, [in] FLOAT rightInset, [in] FLOAT bottomInset, [out] [retval] void** result);
+ HRESULT CreateLinearEasingFunction([out] [retval] void** result);
+ HRESULT CreatePropertySet([out] [retval] void** result);
+ HRESULT CreateQuaternionKeyFrameAnimation([out] [retval] void** result);
+ HRESULT CreateScalarKeyFrameAnimation([out] [retval] void** result);
+ HRESULT CreateScopedBatch([in] CompositionBatchTypes batchType, [out] [retval] ICompositionScopedBatch** result);
+ HRESULT CreateSpriteVisual([out] [retval] ISpriteVisual** result);
+ HRESULT CreateSurfaceBrush([out] [retval] ICompositionSurfaceBrush** result);
+ HRESULT CreateSurfaceBrushWithSurface([in] ICompositionSurface* surface,
+ [out] [retval] ICompositionSurfaceBrush** result);
+ HRESULT CreateTargetForCurrentView([out] [retval] void** result);
+ HRESULT CreateVector2KeyFrameAnimation([out] [retval] void** result);
+ HRESULT CreateVector3KeyFrameAnimation([out] [retval] void** result);
+ HRESULT CreateVector4KeyFrameAnimation([out] [retval] void** result);
+ HRESULT GetCommitBatch([in] CompositionBatchTypes batchType, [out] [retval] void** result);
+}
+
+[uuid(735081DC-5E24-45DA-A38F-E32CC349A9A0)]
+interface ICompositor2 : IInspectable
+{
+ HRESULT CreateAmbientLight([out] [retval] void** result);
+ HRESULT CreateAnimationGroup([out] [retval] void** result);
+ HRESULT CreateBackdropBrush([out] [retval] ICompositionBackdropBrush** result);
+ HRESULT CreateDistantLight([out] [retval] void** result);
+ HRESULT CreateDropShadow([out] [retval] void** result);
+ HRESULT CreateImplicitAnimationCollection([out] [retval] void** result);
+ HRESULT CreateLayerVisual([out] [retval] void** result);
+ HRESULT CreateMaskBrush([out] [retval] void** result);
+ HRESULT CreateNineGridBrush([out] [retval] void** result);
+ HRESULT CreatePointLight([out] [retval] void** result);
+ HRESULT CreateSpotLight([out] [retval] void** result);
+ [overload("CreateStepEasingFunction")] HRESULT CreateStepEasingFunction([out] [retval] void** result);
+ [overload("CreateStepEasingFunction")] HRESULT CreateStepEasingFunctionWithStepCount([in] INT32 stepCount, [out] [retval] void** result);
+}
+
+[uuid(08E05581-1AD1-4F97-9757-402D76E4233B)]
+interface ISpriteVisual : IInspectable
+{
+ [propget] HRESULT GetBrush([out] [retval] ICompositionBrush** value);
+ [propput] HRESULT SetBrush([in] ICompositionBrush* value);
+}
+
+[uuid(FD04E6E3-FE0C-4C3C-AB19-A07601A576EE)]
+interface ICompositionDrawingSurfaceInterop : IUnknown
+{
+ HRESULT BeginDraw(RECT* updateRect, Guid* iid, void** updateObject, [out, retval]POINT* updateOffset);
+ HRESULT EndDraw();
+ HRESULT Resize(POINT sizePixels);
+ HRESULT Scroll(RECT * scrollRect, RECT * clipRect, int offsetX, int offsetY);
+ HRESULT ResumeDraw();
+ HRESULT SuspendDraw();
+};
+
+[uuid(A116FF71-F8BF-4C8A-9C98-70779A32A9C8)]
+interface ICompositionGraphicsDeviceInterop : IUnknown
+{
+ HRESULT GetRenderingDevice([out] IUnknown ** value);
+ HRESULT SetRenderingDevice([out] IUnknown * value);
+};
+
+[uuid(25297D5C-3AD4-4C9C-B5CF-E36A38512330)]
+interface ICompositorInterop : IUnknown
+{
+ HRESULT CreateCompositionSurfaceForHandle(IntPtr swapChain, [out] ICompositionSurface ** res);
+ HRESULT CreateCompositionSurfaceForSwapChain(IUnknown* swapChain, [out] ICompositionSurface ** result);
+ HRESULT CreateGraphicsDevice(IUnknown * renderingDevice, [out] ICompositionGraphicsDevice ** result);
+};
+
+[uuid(26f496a0-7f38-45fb-88f7-faaabe67dd59)]
+interface ISwapChainInterop : IUnknown
+{
+ HRESULT SetSwapChain(IUnknown * swapChain);
+};
+
+/*
+[uuid(2C9DB356-E70D-4642-8298-BC4AA5B4865C)]
+interface ICompositionCapabilitiesInteropFactory : IInspectable
+{
+ HRESULT GetForWindow(IntPtr hwnd, [out] ICompositionCapabilities ** result);
+}*/
+
+[uuid(29E691FA-4567-4DCA-B319-D0F207EB6807)]
+interface ICompositorDesktopInterop : IUnknown
+{
+ HRESULT CreateDesktopWindowTarget(HWND hwndTarget, BOOL isTopmost, [out] IDesktopWindowTarget ** result);
+ HRESULT EnsureOnThread(DWORD threadId);
+};
+
+
+[uuid(35DBF59E-E3F9-45B0-81E7-FE75F4145DC9)]
+interface IDesktopWindowTargetInterop : IUnknown
+{
+ HRESULT GetHWnd([out] IntPtr* value);
+};
+
+[uuid(37642806-F421-4FD0-9F82-23AE7C776182)]
+interface IDesktopWindowContentBridgeInterop : IUnknown
+{
+ HRESULT Initialize(ICompositor* compositor, HWND parentHwnd);
+ HRESULT GetHWnd([out] IntPtr* value);
+
+ HRESULT GetAppliedScaleFactor([out] float* value);
+};
+
+[uuid(FB22C6E1-80A2-4667-9936-DBEAF6EEFE95)]
+interface ICompositionGraphicsDevice : IInspectable
+{
+ HRESULT CreateDrawingSurface([in] SIZE sizePixels, [in] DirectXPixelFormat pixelFormat,
+ [in] DirectXAlphaMode alphaMode, [out] [retval] ICompositionDrawingSurface** result);
+ HRESULT AddRenderingDeviceReplaced(void* handler, void* token);
+ HRESULT RemoveRenderingDeviceReplaced([in] int token);
+}
+
+[uuid(1527540D-42C7-47A6-A408-668F79A90DFB)]
+interface ICompositionSurface : IInspectable
+{
+}
+
+[uuid(6329D6CA-3366-490E-9DB3-25312929AC51)]
+interface IDesktopWindowTarget : IInspectable
+{
+ [propget] HRESULT IsTopmost([out] [retval] int* value);
+}
+
+
+[uuid(A166C300-FAD0-4D11-9E67-E433162FF49E)]
+interface ICompositionDrawingSurface : IInspectable
+{
+ [propget] HRESULT GetAlphaMode([out] [retval] DirectXAlphaMode* value);
+ [propget] HRESULT GetPixelFormat([out] [retval] DirectXPixelFormat* value);
+ [propget] HRESULT GetSize([out] [retval] POINT* value);
+}
+
+enum CompositionBitmapInterpolationMode
+{
+ NearestNeighbor,
+ Linear,
+ MagLinearMinLinearMipLinear,
+ MagLinearMinLinearMipNearest,
+ MagLinearMinNearestMipLinear,
+ MagLinearMinNearestMipNearest,
+ MagNearestMinLinearMipLinear,
+ MagNearestMinLinearMipNearest,
+ MagNearestMinNearestMipLinear,
+ MagNearestMinNearestMipNearest,
+}
+
+enum CompositionStretch
+{
+ None,
+ Fill,
+ Uniform,
+ UniformToFill,
+}
+
+[uuid(AD016D79-1E4C-4C0D-9C29-83338C87C162)]
+interface ICompositionSurfaceBrush : IInspectable
+{
+ [propget] HRESULT BitmapInterpolationMode([out] [retval] CompositionBitmapInterpolationMode* value);
+ [propput] HRESULT BitmapInterpolationMode([in] CompositionBitmapInterpolationMode value);
+ [propget] HRESULT HorizontalAlignmentRatio([out] [retval] FLOAT* value);
+ [propput] HRESULT HorizontalAlignmentRatio([in] FLOAT value);
+ [propget] HRESULT Stretch([out] [retval] CompositionStretch* value);
+ [propput] HRESULT Stretch([in] CompositionStretch value);
+ [propget] HRESULT Surface([out] [retval] ICompositionSurface** value);
+ [propput] HRESULT Surface([in] ICompositionSurface* value);
+ [propget] HRESULT VerticalAlignmentRatio([out] [retval] FLOAT* value);
+ [propput] HRESULT VerticalAlignmentRatio([in] FLOAT value);
+}
+
+[uuid(AB0D7608-30C0-40E9-B568-B60A6BD1FB46)]
+interface ICompositionBrush : IInspectable
+{
+}
+
+enum CompositionBackfaceVisibility
+{
+ Inherit,
+ Visible,
+ Hidden
+}
+
+enum CompositionBorderMode
+{
+ Inherit,
+ Soft,
+ Hard
+}
+
+enum CompositionCompositeMode
+{
+ Inherit,
+ SourceOver,
+ DestinationInvert,
+ MinBlend,
+}
+
+[uuid(117E202D-A859-4C89-873B-C2AA566788E3)]
+interface IVisual : IInspectable
+{
+ [propget] HRESULT AnchorPoint([out] [retval] Vector2* value);
+ [propput] HRESULT AnchorPoint([in] Vector2 value);
+ [propget] HRESULT BackfaceVisibility([out] [retval] CompositionBackfaceVisibility* value);
+ [propput] HRESULT BackfaceVisibility([in] CompositionBackfaceVisibility value);
+ [propget] HRESULT BorderMode([out] [retval] CompositionBorderMode* value);
+ [propput] HRESULT BorderMode([in] CompositionBorderMode value);
+ [propget] HRESULT CenterPoint([out] [retval] Vector3* value);
+ [propput] HRESULT CenterPoint([in] Vector3 value);
+ [propget] HRESULT Clip([out] [retval]void** value);
+ [propput] HRESULT Clip([in] void* value);
+ [propget] HRESULT CompositeMode([out] [retval] CompositionCompositeMode* value);
+ [propput] HRESULT CompositeMode([in] CompositionCompositeMode value);
+ [propget] HRESULT IsVisible([out] [retval] boolean* value);
+ [propput] HRESULT IsVisible([in] boolean value);
+ [propget] HRESULT Offset([out] [retval] Vector3* value);
+ [propput] HRESULT Offset([in] Vector3 value);
+ [propget] HRESULT Opacity([out] [retval] FLOAT* value);
+ [propput] HRESULT Opacity([in] FLOAT value);
+ [propget] HRESULT Orientation([out] [retval] Quaternion* value);
+ [propput] HRESULT Orientation([in] Quaternion value);
+ [propget] HRESULT Parent([out] [retval] IContainerVisual** value);
+ [propget] HRESULT RotationAngle([out] [retval] FLOAT* value);
+ [propput] HRESULT RotationAngle([in] FLOAT value);
+ [propget] HRESULT RotationAngleInDegrees([out] [retval] FLOAT* value);
+ [propput] HRESULT RotationAngleInDegrees([in] FLOAT value);
+ [propget] HRESULT RotationAxis([out] [retval] Vector3* value);
+ [propput] HRESULT RotationAxis([in] Vector3 value);
+ [propget] HRESULT Scale([out] [retval] Vector3* value);
+ [propput] HRESULT Scale([in] Vector3 value);
+ [propget] HRESULT Size([out] [retval] Vector2* value);
+ [propput] HRESULT Size([in] Vector2 value);
+ [propget] HRESULT TransformMatrix([out] [retval] Matrix4x4* value);
+ [propput] HRESULT TransformMatrix([in] Matrix4x4 value);
+}
+
+[uuid(3052B611-56C3-4C3E-8BF3-F6E1AD473F06)]
+interface IVisual2 : IInspectable
+{
+ [propget] HRESULT ParentForTransform([out] [retval] IVisual** value);
+ [propput] HRESULT ParentForTransform([in] IVisual* value);
+ [propget] HRESULT RelativeOffsetAdjustment([out] [retval] Vector3* value);
+ [propput] HRESULT RelativeOffsetAdjustment([in] Vector3 value);
+ [propget] HRESULT RelativeSizeAdjustment([out] [retval] Vector2* value);
+ [propput] HRESULT RelativeSizeAdjustment([in] Vector2 value);
+}
+
+[uuid(02F6BC74-ED20-4773-AFE6-D49B4A93DB32)]
+interface IContainerVisual : IInspectable
+{
+ [propget] HRESULT GetChildren([out] [retval] IVisualCollection** value);
+}
+
+[uuid(8B745505-FD3E-4A98-84A8-E949468C6BCB)]
+interface IVisualCollection : IInspectable
+{
+ [propget] HRESULT GetCount([out] [retval] INT32* value);
+ HRESULT InsertAbove([in] IVisual* newChild, [in] IVisual* sibling);
+ HRESULT InsertAtBottom([in] IVisual* newChild);
+ HRESULT InsertAtTop([in] IVisual* newChild);
+ HRESULT InsertBelow([in] IVisual* newChild, [in] IVisual* sibling);
+ HRESULT Remove([in] IVisual* child);
+ HRESULT RemoveAll();
+}
+
+[uuid(A1BEA8BA-D726-4663-8129-6B5E7927FFA6)]
+interface ICompositionTarget : IInspectable
+{
+ [propget] HRESULT Root([out] [retval] IVisual** value);
+ [propput] HRESULT Root([in] IVisual* value);
+}
+
+
+[uuid(CB51C0CE-8FE6-4636-B202-861FAA07D8F3)]
+interface IGraphicsEffect : IInspectable
+{
+ [propget] HRESULT Name([out] [retval] HSTRING* name);
+ [propput] HRESULT Name([in] HSTRING name);
+}
+
+[uuid(2D8F9DDC-4339-4EB9-9216-F9DEB75658A2)]
+interface IGraphicsEffectSource : IInspectable
+{
+}
+
+enum GRAPHICS_EFFECT_PROPERTY_MAPPING
+{
+ GRAPHICS_EFFECT_PROPERTY_MAPPING_UNKNOWN,
+ GRAPHICS_EFFECT_PROPERTY_MAPPING_DIRECT,
+ GRAPHICS_EFFECT_PROPERTY_MAPPING_VECTORX,
+ GRAPHICS_EFFECT_PROPERTY_MAPPING_VECTORY,
+ GRAPHICS_EFFECT_PROPERTY_MAPPING_VECTORZ,
+ GRAPHICS_EFFECT_PROPERTY_MAPPING_VECTORW,
+ GRAPHICS_EFFECT_PROPERTY_MAPPING_RECT_TO_VECTOR4,
+ GRAPHICS_EFFECT_PROPERTY_MAPPING_RADIANS_TO_DEGREES,
+ GRAPHICS_EFFECT_PROPERTY_MAPPING_COLORMATRIX_ALPHA_MODE,
+ GRAPHICS_EFFECT_PROPERTY_MAPPING_COLOR_TO_VECTOR3,
+ GRAPHICS_EFFECT_PROPERTY_MAPPING_COLOR_TO_VECTOR4
+}
+
+[uuid(2FC57384-A068-44D7-A331-30982FCF7177)]
+interface IGraphicsEffectD2D1Interop : IUnknown
+{
+ HRESULT GetEffectId([out] Guid* id);
+ HRESULT GetNamedPropertyMapping(IntPtr name, uint* index, GRAPHICS_EFFECT_PROPERTY_MAPPING* mapping);
+ HRESULT GetPropertyCount([out] uint* count);
+ HRESULT GetProperty(uint index, [out]IPropertyValue** value);
+ HRESULT GetSource(uint index, [out, retval] IGraphicsEffectSource** source);
+ HRESULT GetSourceCount([retval]uint *count);
+};
+
+[uuid(858AB13A-3292-4E4E-B3BB-2B6C6544A6EE)]
+interface ICompositionEffectSourceParameter : IInspectable
+{
+ [propget] HRESULT Name([out] [retval] HSTRING* value);
+}
+
+[uuid(B3D9F276-ABA3-4724-ACF3-D0397464DB1C)]
+interface ICompositionEffectSourceParameterFactory : IInspectable
+{
+ HRESULT Create([in] HSTRING name, [out] [retval] ICompositionEffectSourceParameter** instance);
+}
+
+enum CompositionEffectFactoryLoadStatus
+{
+ Success = 0,
+ EffectTooComplex = 1,
+ Pending = 2,
+ Other = -1
+}
+
+[uuid(BE5624AF-BA7E-4510-9850-41C0B4FF74DF)]
+interface ICompositionEffectFactory : IInspectable
+{
+ HRESULT CreateBrush([out] [retval] ICompositionEffectBrush** result);
+ [propget] HRESULT ExtendedError([out] [retval] int* value);
+ [propget] HRESULT LoadStatus([out] [retval] CompositionEffectFactoryLoadStatus* value);
+}
+
+[uuid(BF7F795E-83CC-44BF-A447-3E3C071789EC)]
+interface ICompositionEffectBrush : IInspectable
+{
+ HRESULT GetSourceParameter([in] HSTRING name, [out] [retval] ICompositionBrush** result);
+ HRESULT SetSourceParameter([in] HSTRING name, [in] ICompositionBrush* source);
+}
+
+[uuid(C5ACAE58-3898-499E-8D7F-224E91286A5D)]
+interface ICompositionBackdropBrush : IInspectable
+{
+}
+
+[uuid(2B264C5E-BF35-4831-8642-CF70C20FFF2F)]
+interface ICompositionColorBrush : IInspectable
+{
+ [propget] HRESULT Color([out] [retval] Color* value);
+ [propput] HRESULT Color([in] Color value);
+}
+
+[uuid(0D00DAD0-FB07-46FD-8C72-6280D1A3D1DD)]
+interface ICompositionScopedBatch : IInspectable
+{
+ [propget] HRESULT IsActive([out] [retval] boolean* value);
+ [propget] HRESULT IsEnded([out] [retval] boolean* value);
+ HRESULT End();
+ HRESULT Resume();
+ HRESULT Suspend();
+ [eventadd] HRESULT AddCompleted([in] void* handler, [out] [retval] int* token);
+ [eventremove] HRESULT RemoveCompleted([in] int token);
+}
+
+[uuid(48EA31AD-7FCD-4076-A79C-90CC4B852C9B)]
+interface ICompositor5 : IInspectable
+{
+ [propget] HRESULT GetComment([out] [retval] HSTRING* value);
+ [propput] HRESULT SetComment([in] HSTRING value);
+ [propget] HRESULT GetGlobalPlaybackRate([out] [retval] FLOAT* value);
+ [propput] HRESULT SetGlobalPlaybackRate([in] FLOAT value);
+ HRESULT CreateBounceScalarAnimation([out] [retval] void** result);
+ HRESULT CreateBounceVector2Animation([out] [retval] void** result);
+ HRESULT CreateBounceVector3Animation([out] [retval] void** result);
+ HRESULT CreateContainerShape([out] [retval] void** result);
+ HRESULT CreateEllipseGeometry([out] [retval] void** result);
+ HRESULT CreateLineGeometry([out] [retval] void** result);
+ [overload("CreatePathGeometry")] HRESULT CreatePathGeometry([out] [retval] void** result);
+ [overload("CreatePathGeometry")] HRESULT CreatePathGeometryWithPath([in] void* path, [out] [retval] void** result);
+ HRESULT CreatePathKeyFrameAnimation([out] [retval] void** result);
+ HRESULT CreateRectangleGeometry([out] [retval] void** result);
+ HRESULT CreateRoundedRectangleGeometry([out] [retval] void** result);
+ HRESULT CreateShapeVisual([out] [retval] void** result);
+ [overload("CreateSpriteShape")] HRESULT CreateSpriteShape([out] [retval] void** result);
+ [overload("CreateSpriteShape")] HRESULT CreateSpriteShapeWithGeometry([in] void* geometry, [out] [retval] void** result);
+ HRESULT CreateViewBox([out] [retval] void** result);
+ HRESULT RequestCommitAsync([out] [retval] IAsyncAction** operation);
+}
diff --git a/src/Windows/Avalonia.Win32/WindowFramebuffer.cs b/src/Windows/Avalonia.Win32/WindowFramebuffer.cs
deleted file mode 100644
index 19b90685bf..0000000000
--- a/src/Windows/Avalonia.Win32/WindowFramebuffer.cs
+++ /dev/null
@@ -1,100 +0,0 @@
-using System;
-using Avalonia.Platform;
-using Avalonia.Win32.Interop;
-using PixelFormat = Avalonia.Platform.PixelFormat;
-
-namespace Avalonia.Win32
-{
- public class WindowFramebuffer : ILockedFramebuffer
- {
- private readonly IntPtr _handle;
- private IUnmanagedBlob _bitmapBlob;
- private UnmanagedMethods.BITMAPINFOHEADER _bmpInfo;
-
- public WindowFramebuffer(IntPtr handle, PixelSize size)
- {
-
- if (size.Width <= 0)
- throw new ArgumentException("Width is less than zero");
- if (size.Height <= 0)
- throw new ArgumentException("Height is less than zero");
- _handle = handle;
- _bmpInfo.Init();
- _bmpInfo.biPlanes = 1;
- _bmpInfo.biBitCount = 32;
- _bmpInfo.Init();
- _bmpInfo.biWidth = size.Width;
- _bmpInfo.biHeight = -size.Height;
- _bitmapBlob = AvaloniaLocator.Current.GetService().AllocBlob(size.Width * size.Height * 4);
- }
-
- ~WindowFramebuffer()
- {
- Deallocate();
- }
-
- public IntPtr Address => _bitmapBlob.Address;
- public int RowBytes => Size.Width * 4;
- public PixelFormat Format => PixelFormat.Bgra8888;
-
- public Vector Dpi
- {
- get
- {
- if (UnmanagedMethods.ShCoreAvailable)
- {
- uint dpix, dpiy;
-
- var monitor = UnmanagedMethods.MonitorFromWindow(_handle,
- UnmanagedMethods.MONITOR.MONITOR_DEFAULTTONEAREST);
-
- if (UnmanagedMethods.GetDpiForMonitor(
- monitor,
- UnmanagedMethods.MONITOR_DPI_TYPE.MDT_EFFECTIVE_DPI,
- out dpix,
- out dpiy) == 0)
- {
- return new Vector(dpix, dpiy);
- }
- }
- return new Vector(96, 96);
- }
- }
-
- public PixelSize Size => new PixelSize(_bmpInfo.biWidth, -_bmpInfo.biHeight);
-
- public void DrawToDevice(IntPtr hDC, int destX = 0, int destY = 0, int srcX = 0, int srcY = 0, int width = -1,
- int height = -1)
- {
- if (width == -1)
- width = Size.Width;
- if (height == -1)
- height = Size.Height;
- UnmanagedMethods.SetDIBitsToDevice(hDC, destX, destY, (uint) width, (uint) height, srcX, srcY,
- 0, (uint)Size.Height, _bitmapBlob.Address, ref _bmpInfo, 0);
- }
-
- public bool DrawToWindow(IntPtr hWnd, int destX = 0, int destY = 0, int srcX = 0, int srcY = 0, int width = -1,
- int height = -1)
- {
- if (_bitmapBlob.IsDisposed)
- throw new ObjectDisposedException("Framebuffer");
- if (hWnd == IntPtr.Zero)
- return false;
- IntPtr hDC = UnmanagedMethods.GetDC(hWnd);
- if (hDC == IntPtr.Zero)
- return false;
- DrawToDevice(hDC, destX, destY, srcX, srcY, width, height);
- UnmanagedMethods.ReleaseDC(hWnd, hDC);
- return true;
- }
-
- public void Dispose()
- {
- //It's not an *actual* dispose. This call means "We are done drawing"
- DrawToWindow(_handle);
- }
-
- public void Deallocate() => _bitmapBlob.Dispose();
- }
-}
diff --git a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs
index 25a34561fc..e7d16f731c 100644
--- a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs
+++ b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs
@@ -65,6 +65,11 @@ namespace Avalonia.Win32
return IntPtr.Zero;
}
+ BeforeCloseCleanup(false);
+
+ // Used to distinguish between programmatic and regular close requests.
+ _isCloseRequested = true;
+
break;
}
@@ -200,6 +205,10 @@ namespace Avalonia.Win32
DipFromLParam(lParam), GetMouseModifiers(wParam));
break;
}
+ // Mouse capture is lost
+ case WindowsMessage.WM_CANCELMODE:
+ _mouseDevice.Capture(null);
+ break;
case WindowsMessage.WM_MOUSEMOVE:
{
@@ -338,24 +347,26 @@ namespace Avalonia.Win32
}
case WindowsMessage.WM_PAINT:
+ {
+ using(NonPumpingSyncContext.Use())
+ using (_rendererLock.Lock())
{
- using (_rendererLock.Lock())
+ if (BeginPaint(_hwnd, out PAINTSTRUCT ps) != IntPtr.Zero)
{
- if (BeginPaint(_hwnd, out PAINTSTRUCT ps) != IntPtr.Zero)
- {
- var f = RenderScaling;
- var r = ps.rcPaint;
- Paint?.Invoke(new Rect(r.left / f, r.top / f, (r.right - r.left) / f,
- (r.bottom - r.top) / f));
- EndPaint(_hwnd, ref ps);
- }
+ var f = RenderScaling;
+ var r = ps.rcPaint;
+ Paint?.Invoke(new Rect(r.left / f, r.top / f, (r.right - r.left) / f,
+ (r.bottom - r.top) / f));
+ EndPaint(_hwnd, ref ps);
}
-
- return IntPtr.Zero;
}
+ return IntPtr.Zero;
+ }
+
case WindowsMessage.WM_SIZE:
{
+ using(NonPumpingSyncContext.Use())
using (_rendererLock.Lock())
{
// Do nothing here, just block until the pending frame render is completed on the render thread
diff --git a/src/Windows/Avalonia.Win32/WindowImpl.CustomCaptionProc.cs b/src/Windows/Avalonia.Win32/WindowImpl.CustomCaptionProc.cs
index a3b7574369..68bd40da79 100644
--- a/src/Windows/Avalonia.Win32/WindowImpl.CustomCaptionProc.cs
+++ b/src/Windows/Avalonia.Win32/WindowImpl.CustomCaptionProc.cs
@@ -1,5 +1,4 @@
using System;
-using System.Diagnostics;
using Avalonia.Controls;
using Avalonia.Input;
using static Avalonia.Win32.Interop.UnmanagedMethods;
@@ -11,70 +10,78 @@ namespace Avalonia.Win32
public partial class WindowImpl
{
// Hit test the frame for resizing and moving.
- HitTestValues HitTestNCA(IntPtr hWnd, IntPtr wParam, IntPtr lParam)
+ private HitTestValues HitTestNCA(IntPtr hWnd, IntPtr wParam, IntPtr lParam)
{
- // Get the point coordinates for the hit test.
+ // Get the point coordinates for the hit test (screen space).
var ptMouse = PointFromLParam(lParam);
- // Get the window rectangle.
+ // Get the window rectangle.
GetWindowRect(hWnd, out var rcWindow);
// Get the frame rectangle, adjusted for the style without a caption.
- RECT rcFrame = new RECT();
+ var rcFrame = new RECT();
AdjustWindowRectEx(ref rcFrame, (uint)(WindowStyles.WS_OVERLAPPEDWINDOW & ~WindowStyles.WS_CAPTION), false, 0);
- RECT border_thickness = new RECT();
+ var borderThickness = new RECT();
if (GetStyle().HasFlag(WindowStyles.WS_THICKFRAME))
{
- AdjustWindowRectEx(ref border_thickness, (uint)(GetStyle()), false, 0);
- border_thickness.left *= -1;
- border_thickness.top *= -1;
+ AdjustWindowRectEx(ref borderThickness, (uint)(GetStyle()), false, 0);
+ borderThickness.left *= -1;
+ borderThickness.top *= -1;
}
else if (GetStyle().HasFlag(WindowStyles.WS_BORDER))
{
- border_thickness = new RECT { bottom = 1, left = 1, right = 1, top = 1 };
+ borderThickness = new RECT { bottom = 1, left = 1, right = 1, top = 1 };
}
if (_extendTitleBarHint >= 0)
{
- border_thickness.top = (int)(_extendedMargins.Top * RenderScaling);
+ borderThickness.top = (int)(_extendedMargins.Top * RenderScaling);
}
// Determine if the hit test is for resizing. Default middle (1,1).
ushort uRow = 1;
ushort uCol = 1;
- bool fOnResizeBorder = false;
+ bool onResizeBorder = false;
- // Determine if the point is at the top or bottom of the window.
- if (ptMouse.Y >= rcWindow.top && ptMouse.Y < rcWindow.top + border_thickness.top)
+ // Determine if the point is at the left or right of the window.
+ if (ptMouse.X >= rcWindow.left && ptMouse.X < rcWindow.left + borderThickness.left)
{
- fOnResizeBorder = (ptMouse.Y < (rcWindow.top - rcFrame.top));
- uRow = 0;
+ uCol = 0; // left side
}
- else if (ptMouse.Y < rcWindow.bottom && ptMouse.Y >= rcWindow.bottom - border_thickness.bottom)
+ else if (ptMouse.X < rcWindow.right && ptMouse.X >= rcWindow.right - borderThickness.right)
{
- uRow = 2;
+ uCol = 2; // right side
}
- // Determine if the point is at the left or right of the window.
- if (ptMouse.X >= rcWindow.left && ptMouse.X < rcWindow.left + border_thickness.left)
+ // Determine if the point is at the top or bottom of the window.
+ if (ptMouse.Y >= rcWindow.top && ptMouse.Y < rcWindow.top + borderThickness.top)
{
- uCol = 0; // left side
+ onResizeBorder = (ptMouse.Y < (rcWindow.top - rcFrame.top));
+
+ // Two cases where we have a valid row 0 hit test:
+ // - window resize border (top resize border hit)
+ // - area below resize border that is actual titlebar (caption hit).
+ if (onResizeBorder || uCol == 1)
+ {
+ uRow = 0;
+ }
}
- else if (ptMouse.X < rcWindow.right && ptMouse.X >= rcWindow.right - border_thickness.right)
+ else if (ptMouse.Y < rcWindow.bottom && ptMouse.Y >= rcWindow.bottom - borderThickness.bottom)
{
- uCol = 2; // right side
+ uRow = 2;
}
- // Hit test (HTTOPLEFT, ... HTBOTTOMRIGHT)
- HitTestValues[][] hitTests = new[]
+ ReadOnlySpan hitZones = stackalloc HitTestValues[]
{
- new []{ HitTestValues.HTTOPLEFT, fOnResizeBorder ? HitTestValues.HTTOP : HitTestValues.HTCAPTION, HitTestValues.HTTOPRIGHT },
- new []{ HitTestValues.HTLEFT, HitTestValues.HTNOWHERE, HitTestValues.HTRIGHT },
- new []{ HitTestValues.HTBOTTOMLEFT, HitTestValues.HTBOTTOM, HitTestValues.HTBOTTOMRIGHT },
+ HitTestValues.HTTOPLEFT, onResizeBorder ? HitTestValues.HTTOP : HitTestValues.HTCAPTION,
+ HitTestValues.HTTOPRIGHT, HitTestValues.HTLEFT, HitTestValues.HTNOWHERE, HitTestValues.HTRIGHT,
+ HitTestValues.HTBOTTOMLEFT, HitTestValues.HTBOTTOM, HitTestValues.HTBOTTOMRIGHT
};
- return hitTests[uRow][uCol];
+ var zoneIndex = uRow * 3 + uCol;
+
+ return hitZones[zoneIndex];
}
protected virtual IntPtr CustomCaptionProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam, ref bool callDwp)
diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs
index cb85e14e5a..3c09d2b7a0 100644
--- a/src/Windows/Avalonia.Win32/WindowImpl.cs
+++ b/src/Windows/Avalonia.Win32/WindowImpl.cs
@@ -7,12 +7,16 @@ using Avalonia.Controls.Platform;
using Avalonia.Input;
using Avalonia.Input.Raw;
using Avalonia.OpenGL;
+using Avalonia.OpenGL.Angle;
using Avalonia.OpenGL.Egl;
using Avalonia.OpenGL.Surfaces;
using Avalonia.Platform;
using Avalonia.Rendering;
using Avalonia.Win32.Input;
using Avalonia.Win32.Interop;
+using Avalonia.Win32.OpenGl;
+using Avalonia.Win32.WinRT;
+using Avalonia.Win32.WinRT.Composition;
using static Avalonia.Win32.Interop.UnmanagedMethods;
namespace Avalonia.Win32
@@ -47,6 +51,8 @@ namespace Avalonia.Win32
private Thickness _extendedMargins;
private Thickness _offScreenMargin;
private double _extendTitleBarHint = -1;
+ private bool _isUsingComposition;
+ private IBlurHost _blurHost;
#if USE_MANAGED_DRAG
private readonly ManagedWindowResizeDragHelper _managedDrag;
@@ -77,6 +83,7 @@ namespace Avalonia.Win32
private POINT _maxTrackSize;
private WindowImpl _parent;
private ExtendClientAreaChromeHints _extendChromeHints = ExtendClientAreaChromeHints.Default;
+ private bool _isCloseRequested;
public WindowImpl()
{
@@ -101,12 +108,37 @@ namespace Avalonia.Win32
};
_rendererLock = new ManagedDeferredRendererLock();
+ var glPlatform = AvaloniaLocator.Current.GetService();
+
+ var compositionConnector = AvaloniaLocator.Current.GetService();
+
+ _isUsingComposition = compositionConnector is { } &&
+ glPlatform is EglPlatformOpenGlInterface egl &&
+ egl.Display is AngleWin32EglDisplay angleDisplay &&
+ angleDisplay.PlatformApi == AngleOptions.PlatformApi.DirectX11;
CreateWindow();
_framebuffer = new FramebufferManager(_hwnd);
+
+ if (glPlatform != null)
+ {
+ if (_isUsingComposition)
+ {
+ var cgl = new WinUiCompositedWindowSurface(compositionConnector, this);
+ _blurHost = cgl;
+
+ _gl = cgl;
- if (Win32GlManager.EglPlatformInterface != null)
- _gl = new EglGlPlatformSurface(Win32GlManager.EglPlatformInterface, this);
+ _isUsingComposition = true;
+ }
+ else
+ {
+ if (glPlatform is EglPlatformOpenGlInterface egl2)
+ _gl = new EglGlPlatformSurface(egl2, this);
+ else if (glPlatform is WglPlatformOpenGlInterface wgl)
+ _gl = new WglGlPlatformSurface(wgl.PrimaryContext, this);
+ }
+ }
Screen = new ScreenImpl();
@@ -211,7 +243,7 @@ namespace Avalonia.Win32
{
if (IsWindowVisible(_hwnd))
{
- ShowWindow(value);
+ ShowWindow(value, true);
}
else
{
@@ -323,54 +355,63 @@ namespace Avalonia.Win32
private WindowTransparencyLevel Win10EnableBlur(WindowTransparencyLevel transparencyLevel)
{
- bool canUseAcrylic = Win32Platform.WindowsVersion.Major > 10 || Win32Platform.WindowsVersion.Build >= 19628;
-
- var accent = new AccentPolicy();
- var accentStructSize = Marshal.SizeOf(accent);
-
- if (transparencyLevel == WindowTransparencyLevel.AcrylicBlur && !canUseAcrylic)
+ if (_isUsingComposition)
{
- transparencyLevel = WindowTransparencyLevel.Blur;
- }
+ _blurHost?.SetBlur(transparencyLevel >= WindowTransparencyLevel.Blur);
- switch (transparencyLevel)
+ return transparencyLevel;
+ }
+ else
{
- default:
- case WindowTransparencyLevel.None:
- accent.AccentState = AccentState.ACCENT_DISABLED;
- break;
+ bool canUseAcrylic = Win32Platform.WindowsVersion.Major > 10 || Win32Platform.WindowsVersion.Build >= 19628;
- case WindowTransparencyLevel.Transparent:
- accent.AccentState = AccentState.ACCENT_ENABLE_TRANSPARENTGRADIENT;
- break;
+ var accent = new AccentPolicy();
+ var accentStructSize = Marshal.SizeOf(accent);
- case WindowTransparencyLevel.Blur:
- accent.AccentState = AccentState.ACCENT_ENABLE_BLURBEHIND;
- break;
+ if (transparencyLevel == WindowTransparencyLevel.AcrylicBlur && !canUseAcrylic)
+ {
+ transparencyLevel = WindowTransparencyLevel.Blur;
+ }
- case WindowTransparencyLevel.AcrylicBlur:
- case (WindowTransparencyLevel.AcrylicBlur + 1): // hack-force acrylic.
- accent.AccentState = AccentState.ACCENT_ENABLE_ACRYLIC;
- transparencyLevel = WindowTransparencyLevel.AcrylicBlur;
- break;
- }
+ switch (transparencyLevel)
+ {
+ default:
+ case WindowTransparencyLevel.None:
+ accent.AccentState = AccentState.ACCENT_DISABLED;
+ break;
+
+ case WindowTransparencyLevel.Transparent:
+ accent.AccentState = AccentState.ACCENT_ENABLE_TRANSPARENTGRADIENT;
+ break;
+
+ case WindowTransparencyLevel.Blur:
+ accent.AccentState = AccentState.ACCENT_ENABLE_BLURBEHIND;
+ break;
+
+ case WindowTransparencyLevel.AcrylicBlur:
+ case (WindowTransparencyLevel.AcrylicBlur + 1): // hack-force acrylic.
+ accent.AccentState = AccentState.ACCENT_ENABLE_ACRYLIC;
+ transparencyLevel = WindowTransparencyLevel.AcrylicBlur;
+ break;
+ }
- accent.AccentFlags = 2;
- accent.GradientColor = 0x01000000;
+ accent.AccentFlags = 2;
+ accent.GradientColor = 0x01000000;
- var accentPtr = Marshal.AllocHGlobal(accentStructSize);
- Marshal.StructureToPtr(accent, accentPtr, false);
+ var accentPtr = Marshal.AllocHGlobal(accentStructSize);
+ Marshal.StructureToPtr(accent, accentPtr, false);
- var data = new WindowCompositionAttributeData();
- data.Attribute = WindowCompositionAttribute.WCA_ACCENT_POLICY;
- data.SizeOfData = accentStructSize;
- data.Data = accentPtr;
+ var data = new WindowCompositionAttributeData();
+ data.Attribute = WindowCompositionAttribute.WCA_ACCENT_POLICY;
+ data.SizeOfData = accentStructSize;
+ data.Data = accentPtr;
- SetWindowCompositionAttribute(_hwnd, ref data);
+ SetWindowCompositionAttribute(_hwnd, ref data);
- Marshal.FreeHGlobal(accentPtr);
+ Marshal.FreeHGlobal(accentPtr);
- return transparencyLevel;
+ return transparencyLevel;
+ }
}
public IEnumerable Surfaces => new object[] { Handle, _gl, _framebuffer };
@@ -414,9 +455,14 @@ namespace Avalonia.Win32
if (customRendererFactory != null)
return customRendererFactory.Create(root, loop);
- return Win32Platform.UseDeferredRendering ?
- (IRenderer)new DeferredRenderer(root, loop, rendererLock: _rendererLock) :
- new ImmediateRenderer(root);
+ return Win32Platform.UseDeferredRendering
+ ? _isUsingComposition
+ ? new DeferredRenderer(root, loop)
+ {
+ RenderOnlyOnRenderThread = true
+ }
+ : (IRenderer)new DeferredRenderer(root, loop, rendererLock: _rendererLock)
+ : new ImmediateRenderer(root);
}
public void Resize(Size value)
@@ -451,6 +497,8 @@ namespace Avalonia.Win32
public void Dispose()
{
+ (_gl as IDisposable)?.Dispose();
+
if (_dropTarget != null)
{
OleContext.Current?.UnregisterDragDrop(Handle);
@@ -459,6 +507,13 @@ namespace Avalonia.Win32
if (_hwnd != IntPtr.Zero)
{
+ // Detect if we are being closed programmatically - this would mean that WM_CLOSE was not called
+ // and we didn't prepare this window for destruction.
+ if (!_isCloseRequested)
+ {
+ BeforeCloseCleanup(true);
+ }
+
DestroyWindow(_hwnd);
_hwnd = IntPtr.Zero;
}
@@ -512,10 +567,11 @@ namespace Avalonia.Win32
UnmanagedMethods.ShowWindow(_hwnd, ShowWindowCommand.Hide);
}
- public virtual void Show()
+ public virtual void Show(bool activate)
{
SetWindowLongPtr(_hwnd, (int)WindowLongParam.GWL_HWNDPARENT, _parent != null ? _parent._hwnd : IntPtr.Zero);
- ShowWindow(_showWindowState);
+
+ ShowWindow(_showWindowState, activate);
}
public Action GotInputWhenDisabled { get; set; }
@@ -617,7 +673,7 @@ namespace Avalonia.Win32
protected virtual IntPtr CreateWindowOverride(ushort atom)
{
return CreateWindowEx(
- 0,
+ _isUsingComposition ? (int)WindowStyles.WS_EX_NOREDIRECTIONBITMAP : 0,
atom,
null,
(int)WindowStyles.WS_OVERLAPPEDWINDOW | (int) WindowStyles.WS_CLIPCHILDREN,
@@ -853,7 +909,7 @@ namespace Avalonia.Win32
ExtendClientAreaToDecorationsChanged?.Invoke(_isClientAreaExtended);
}
- private void ShowWindow(WindowState state)
+ private void ShowWindow(WindowState state, bool activate)
{
ShowWindowCommand? command;
@@ -863,7 +919,7 @@ namespace Avalonia.Win32
{
case WindowState.Minimized:
newWindowProperties.IsFullScreen = false;
- command = ShowWindowCommand.Minimize;
+ command = activate ? ShowWindowCommand.Minimize : ShowWindowCommand.ShowMinNoActive;
break;
case WindowState.Maximized:
newWindowProperties.IsFullScreen = false;
@@ -872,7 +928,8 @@ namespace Avalonia.Win32
case WindowState.Normal:
newWindowProperties.IsFullScreen = false;
- command = ShowWindowCommand.Restore;
+ command = IsWindowVisible(_hwnd) ? ShowWindowCommand.Restore :
+ activate ? ShowWindowCommand.Normal : ShowWindowCommand.ShowNoActivate;
break;
case WindowState.FullScreen:
@@ -901,6 +958,32 @@ namespace Avalonia.Win32
SetFocus(_hwnd);
}
}
+
+ private void BeforeCloseCleanup(bool isDisposing)
+ {
+ // Based on https://github.com/dotnet/wpf/blob/master/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Window.cs#L4270-L4337
+ // We need to enable parent window before destroying child window to prevent OS from activating a random window behind us (or last active window).
+ // This is described here: https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-enablewindow#remarks
+ // We need to verify if parent is still alive (perhaps it got destroyed somehow).
+ if (_parent != null && IsWindow(_parent._hwnd))
+ {
+ var wasActive = GetActiveWindow() == _hwnd;
+
+ // We can only set enabled state if we are not disposing - generally Dispose happens after enabled state has been set.
+ // Ignoring this would cause us to enable a window that might be disabled.
+ if (!isDisposing)
+ {
+ // Our window closed callback will set enabled state to a correct value after child window gets destroyed.
+ _parent.SetEnabled(true);
+ }
+
+ // We also need to activate our parent window since again OS might try to activate a window behind if it is not set.
+ if (wasActive)
+ {
+ SetActiveWindow(_parent._hwnd);
+ }
+ }
+ }
private void MaximizeWithoutCoveringTaskbar()
{
diff --git a/src/tools/Avalonia.Designer.HostApp/Avalonia.Designer.HostApp.csproj b/src/tools/Avalonia.Designer.HostApp/Avalonia.Designer.HostApp.csproj
index 51d18e55d1..a2d27fd579 100644
--- a/src/tools/Avalonia.Designer.HostApp/Avalonia.Designer.HostApp.csproj
+++ b/src/tools/Avalonia.Designer.HostApp/Avalonia.Designer.HostApp.csproj
@@ -23,5 +23,8 @@
+
+
+
diff --git a/src/tools/MicroComGenerator/Ast.cs b/src/tools/MicroComGenerator/Ast.cs
new file mode 100644
index 0000000000..e9a55308be
--- /dev/null
+++ b/src/tools/MicroComGenerator/Ast.cs
@@ -0,0 +1,241 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace MicroComGenerator.Ast
+{
+ public class AstAttributeNode
+ {
+ public string Name { get; set; }
+ public string Value { get; set; }
+
+ public AstAttributeNode(string name, string value)
+ {
+ Name = name;
+ Value = value;
+ }
+
+ public override string ToString() => $"{Name} = {Value}";
+ public AstAttributeNode Clone() => new AstAttributeNode(Name, Value);
+ }
+
+ public class AstAttributes : List
+ {
+ public bool HasAttribute(string a) => this.Any(x => x.Name == a);
+
+ public AstAttributes Clone()
+ {
+ var rv= new AstAttributes();
+ rv.AddRange(this.Select(x => x.Clone()));
+ return rv;
+ }
+ }
+
+ public interface IAstNodeWithAttributes
+ {
+ public AstAttributes Attributes { get; set; }
+ }
+
+ public class AstEnumNode : List, IAstNodeWithAttributes
+ {
+ public AstAttributes Attributes { get; set; } = new AstAttributes();
+ public string Name { get; set; }
+ public override string ToString() => "Enum " + Name;
+
+ public AstEnumNode Clone()
+ {
+ var rv = new AstEnumNode { Name = Name, Attributes = Attributes.Clone() };
+ rv.AddRange(this.Select(x => x.Clone()));
+ return rv;
+ }
+ }
+
+ public class AstEnumMemberNode
+ {
+ public string Name { get; set; }
+ public string Value { get; set; }
+
+ public AstEnumMemberNode(string name, string value)
+ {
+ Name = name;
+ Value = value;
+ }
+
+ public override string ToString() => $"Enum member {Name} = {Value}";
+ public AstEnumMemberNode Clone() => new AstEnumMemberNode(Name, Value);
+ }
+
+ public class AstStructNode : List, IAstNodeWithAttributes
+ {
+ public AstAttributes Attributes { get; set; } = new AstAttributes();
+ public string Name { get; set; }
+ public override string ToString() => "Struct " + Name;
+
+ public AstStructNode Clone()
+ {
+ var rv = new AstStructNode { Name = Name, Attributes = Attributes.Clone() };
+ rv.AddRange(this.Select(x => x.Clone()));
+ return rv;
+ }
+ }
+
+ public class AstTypeNode
+ {
+ public string Name { get; set; }
+ public int PointerLevel { get; set; }
+ public bool IsLink { get; set; }
+
+ public string Format() => Name + new string('*', PointerLevel)
+ + (IsLink ? "&" : "");
+ public override string ToString() => Format();
+ public AstTypeNode Clone() => new AstTypeNode() {
+ Name = Name,
+ PointerLevel = PointerLevel,
+ IsLink = IsLink
+ };
+ }
+
+ public class AstStructMemberNode : IAstNodeWithAttributes
+ {
+ public string Name { get; set; }
+ public AstTypeNode Type { get; set; }
+
+ public override string ToString() => $"Struct member {Type.Format()} {Name}";
+ public AstStructMemberNode Clone() => new AstStructMemberNode() { Name = Name, Type = Type.Clone() };
+ public AstAttributes Attributes { get; set; } = new AstAttributes();
+ }
+
+ public class AstInterfaceNode : List, IAstNodeWithAttributes
+ {
+ public AstAttributes Attributes { get; set; } = new AstAttributes();
+ public string Name { get; set; }
+ public string Inherits { get; set; }
+
+ public override string ToString()
+ {
+ if (Inherits == null)
+ return Name;
+ return $"Interface {Name} : {Inherits}";
+ }
+ public AstInterfaceNode Clone()
+ {
+ var rv = new AstInterfaceNode { Name = Name, Inherits = Inherits, Attributes = Attributes.Clone() };
+ rv.AddRange(this.Select(x => x.Clone()));
+ return rv;
+ }
+ }
+
+ public class AstInterfaceMemberNode : List, IAstNodeWithAttributes
+ {
+ public string Name { get; set; }
+ public AstTypeNode ReturnType { get; set; }
+ public AstAttributes Attributes { get; set; } = new AstAttributes();
+
+ public AstInterfaceMemberNode Clone()
+ {
+ var rv = new AstInterfaceMemberNode()
+ {
+ Name = Name, Attributes = Attributes.Clone(), ReturnType = ReturnType
+ };
+ rv.AddRange(this.Select(x => x.Clone()));
+ return rv;
+ }
+
+ public override string ToString() =>
+ $"Interface member {ReturnType.Format()} {Name} ({string.Join(", ", this.Select(x => x.Format()))})";
+ }
+
+ public class AstInterfaceMemberArgumentNode : IAstNodeWithAttributes
+ {
+ public string Name { get; set; }
+ public AstTypeNode Type { get; set; }
+ public AstAttributes Attributes { get; set; } = new AstAttributes();
+
+
+ public string Format() => $"{Type.Format()} {Name}";
+ public override string ToString() => "Argument " + Format();
+
+ public AstInterfaceMemberArgumentNode Clone() => new AstInterfaceMemberArgumentNode
+ {
+ Name = Name, Type = Type.Clone(), Attributes = Attributes.Clone()
+ };
+ }
+
+ public static class AstExtensions
+ {
+ public static bool HasAttribute(this IAstNodeWithAttributes node, string s) => node.Attributes.HasAttribute(s);
+
+ public static string GetAttribute(this IAstNodeWithAttributes node, string s)
+ {
+ var value = node.Attributes.FirstOrDefault(a => a.Name == s)?.Value;
+ if (value == null)
+ throw new CodeGenException("Expected attribute " + s + " for node " + node);
+ return value;
+ }
+
+ public static string GetAttributeOrDefault(this IAstNodeWithAttributes node, string s)
+ => node.Attributes.FirstOrDefault(a => a.Name == s)?.Value;
+ }
+
+ class AstVisitor
+ {
+ protected virtual void VisitType(AstTypeNode type)
+ {
+ }
+
+ protected virtual void VisitArgument(AstInterfaceMemberArgumentNode argument)
+ {
+ VisitType(argument.Type);
+ }
+
+ protected virtual void VisitInterfaceMember(AstInterfaceMemberNode member)
+ {
+ foreach(var a in member)
+ VisitArgument(a);
+ VisitType(member.ReturnType);
+ }
+
+ protected virtual void VisitInterface(AstInterfaceNode iface)
+ {
+ foreach(var m in iface)
+ VisitInterfaceMember(m);
+ }
+
+ protected virtual void VisitStructMember(AstStructMemberNode member)
+ {
+ VisitType(member.Type);
+ }
+
+ protected virtual void VisitStruct(AstStructNode node)
+ {
+ foreach(var m in node)
+ VisitStructMember(m);
+ }
+
+ public virtual void VisitAst(AstIdlNode ast)
+ {
+ foreach(var iface in ast.Interfaces)
+ VisitInterface(iface);
+ foreach (var s in ast.Structs)
+ VisitStruct(s);
+ }
+
+
+ }
+
+ public class AstIdlNode : IAstNodeWithAttributes
+ {
+ public AstAttributes Attributes { get; set; } = new AstAttributes();
+ public List Enums { get; set; } = new List();
+ public List Structs { get; set; } = new List();
+ public List Interfaces { get; set; } = new List();
+
+ public AstIdlNode Clone() => new AstIdlNode()
+ {
+ Attributes = Attributes.Clone(),
+ Enums = Enums.Select(x => x.Clone()).ToList(),
+ Structs = Structs.Select(x => x.Clone()).ToList(),
+ Interfaces = Interfaces.Select(x => x.Clone()).ToList()
+ };
+ }
+}
diff --git a/src/tools/MicroComGenerator/AstParser.cs b/src/tools/MicroComGenerator/AstParser.cs
new file mode 100644
index 0000000000..388a8eb018
--- /dev/null
+++ b/src/tools/MicroComGenerator/AstParser.cs
@@ -0,0 +1,232 @@
+using System.Collections.Generic;
+using MicroComGenerator.Ast;
+
+namespace MicroComGenerator
+{
+ public class AstParser
+ {
+ public static AstIdlNode Parse(string source)
+ {
+ var parser = new TokenParser(source);
+ var idl = new AstIdlNode { Attributes = ParseGlobalAttributes(ref parser) };
+
+ while (!parser.Eof)
+ {
+ var attrs = ParseLocalAttributes(ref parser);
+ if (parser.TryConsume(";"))
+ continue;
+ if (parser.TryParseKeyword("enum"))
+ idl.Enums.Add(ParseEnum(attrs, ref parser));
+ else if (parser.TryParseKeyword("struct"))
+ idl.Structs.Add(ParseStruct(attrs, ref parser));
+ else if (parser.TryParseKeyword("interface"))
+ idl.Interfaces.Add(ParseInterface(attrs, ref parser));
+ else
+ throw new ParseException("Unexpected character", ref parser);
+ }
+
+ return idl;
+ }
+
+ static AstAttributes ParseGlobalAttributes(ref TokenParser parser)
+ {
+ var rv = new AstAttributes();
+ while (!parser.Eof)
+ {
+ parser.SkipWhitespace();
+ if (parser.TryConsume('@'))
+ {
+ var ident = parser.ParseIdentifier("-");
+ var value = parser.ReadToEol().Trim();
+ if (value == "@@")
+ {
+ parser.Advance(1);
+ value = "";
+ while (true)
+ {
+ var l = parser.ReadToEol();
+ if (l == "@@")
+ break;
+ else
+ value = value.Length == 0 ? l : (value + "\n" + l);
+ parser.Advance(1);
+ }
+
+ }
+ rv.Add(new AstAttributeNode(ident, value));
+ }
+ else
+ return rv;
+ }
+
+ return rv;
+ }
+
+ static AstAttributes ParseLocalAttributes(ref TokenParser parser)
+ {
+ var rv = new AstAttributes();
+ while (parser.TryConsume("["))
+ {
+ while (!parser.TryConsume("]") && !parser.Eof)
+ {
+ if (parser.TryConsume(','))
+ continue;
+
+ // Get identifier
+ var ident = parser.ParseIdentifier("-");
+
+ // No value, end of attribute list
+ if (parser.TryConsume(']'))
+ {
+ rv.Add(new AstAttributeNode(ident, null));
+ break;
+ }
+ // No value, next attribute
+ else if (parser.TryConsume(','))
+ rv.Add(new AstAttributeNode(ident, null));
+ // Has value
+ else if (parser.TryConsume('('))
+ {
+ var value = parser.ReadTo(')');
+ parser.Consume(')');
+ rv.Add(new AstAttributeNode(ident, value));
+ }
+ else
+ throw new ParseException("Unexpected character", ref parser);
+ }
+
+ if (parser.Eof)
+ throw new ParseException("Unexpected EOF", ref parser);
+ }
+
+ return rv;
+ }
+
+ static void EnsureOpenBracket(ref TokenParser parser)
+ {
+ if (!parser.TryConsume('{'))
+ throw new ParseException("{ expected", ref parser);
+ }
+
+ static AstEnumNode ParseEnum(AstAttributes attrs, ref TokenParser parser)
+ {
+ var name = parser.ParseIdentifier();
+ EnsureOpenBracket(ref parser);
+ var rv = new AstEnumNode { Name = name, Attributes = attrs };
+ while (!parser.TryConsume('}') && !parser.Eof)
+ {
+ if (parser.TryConsume(','))
+ continue;
+
+ var ident = parser.ParseIdentifier();
+
+ // Automatic value
+ if (parser.TryConsume(',') || parser.Peek == '}')
+ {
+ rv.Add(new AstEnumMemberNode(ident, null));
+ continue;
+ }
+
+ if (!parser.TryConsume('='))
+ throw new ParseException("Unexpected character", ref parser);
+
+ var value = parser.ReadToAny(",}").Trim();
+ rv.Add(new AstEnumMemberNode(ident, value));
+
+ if (parser.Eof)
+ throw new ParseException("Unexpected EOF", ref parser);
+ }
+
+
+ return rv;
+ }
+
+ static AstTypeNode ParseType(ref TokenParser parser)
+ {
+ var ident = parser.ParseIdentifier();
+ var t = new AstTypeNode { Name = ident };
+ while (parser.TryConsume('*'))
+ t.PointerLevel++;
+ if (parser.TryConsume("&"))
+ t.IsLink = true;
+ return t;
+ }
+
+ static AstStructNode ParseStruct(AstAttributes attrs, ref TokenParser parser)
+ {
+ var name = parser.ParseIdentifier();
+ EnsureOpenBracket(ref parser);
+ var rv = new AstStructNode { Name = name, Attributes = attrs };
+ while (!parser.TryConsume('}') && !parser.Eof)
+ {
+ var memberAttrs = ParseLocalAttributes(ref parser);
+ var t = ParseType(ref parser);
+ bool parsedAtLeastOneMember = false;
+ while (!parser.TryConsume(';'))
+ {
+ // Skip any ,
+ while (parser.TryConsume(',')) { }
+
+ var ident = parser.ParseIdentifier();
+ parsedAtLeastOneMember = true;
+ rv.Add(new AstStructMemberNode { Name = ident, Type = t, Attributes = memberAttrs});
+ }
+
+ if (!parsedAtLeastOneMember)
+ throw new ParseException("Expected at least one enum member with declared type " + t, ref parser);
+ }
+
+ return rv;
+ }
+
+ static AstInterfaceNode ParseInterface(AstAttributes interfaceAttrs, ref TokenParser parser)
+ {
+ var interfaceName = parser.ParseIdentifier();
+ string inheritsFrom = null;
+ if (parser.TryConsume(":"))
+ inheritsFrom = parser.ParseIdentifier();
+
+ EnsureOpenBracket(ref parser);
+ var rv = new AstInterfaceNode
+ {
+ Name = interfaceName, Attributes = interfaceAttrs, Inherits = inheritsFrom
+ };
+ while (!parser.TryConsume('}') && !parser.Eof)
+ {
+ var memberAttrs = ParseLocalAttributes(ref parser);
+ var returnType = ParseType(ref parser);
+ var name = parser.ParseIdentifier();
+ var member = new AstInterfaceMemberNode
+ {
+ Name = name, ReturnType = returnType, Attributes = memberAttrs
+ };
+ rv.Add(member);
+
+ parser.Consume('(');
+ while (true)
+ {
+ if (parser.TryConsume(')'))
+ break;
+
+ var argumentAttrs = ParseLocalAttributes(ref parser);
+ var type = ParseType(ref parser);
+ var argName = parser.ParseIdentifier();
+ member.Add(new AstInterfaceMemberArgumentNode
+ {
+ Name = argName, Type = type, Attributes = argumentAttrs
+ });
+
+ if (parser.TryConsume(')'))
+ break;
+ if (parser.TryConsume(','))
+ continue;
+ throw new ParseException("Unexpected character", ref parser);
+ }
+
+ parser.Consume(';');
+ }
+
+ return rv;
+ }
+ }
+}
diff --git a/src/tools/MicroComGenerator/CSharpGen.InterfaceGen.cs b/src/tools/MicroComGenerator/CSharpGen.InterfaceGen.cs
new file mode 100644
index 0000000000..adb8faf938
--- /dev/null
+++ b/src/tools/MicroComGenerator/CSharpGen.InterfaceGen.cs
@@ -0,0 +1,484 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using MicroComGenerator.Ast;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
+
+// ReSharper disable CoVariantArrayConversion
+
+// HERE BE DRAGONS
+
+namespace MicroComGenerator
+{
+ public partial class CSharpGen
+ {
+ abstract class Arg
+ {
+ public string Name;
+ public string NativeType;
+ public AstAttributes Attributes { get; set; }
+ public virtual StatementSyntax CreateFixed(StatementSyntax inner) => inner;
+
+ public virtual void PreMarshal(List body)
+ {
+ }
+
+ public virtual void PreMarshalForReturn(List body) =>
+ throw new InvalidOperationException("Don't know how to use " + NativeType + " as HRESULT-return");
+
+ public virtual ExpressionSyntax Value(bool isHresultReturn) => ParseExpression(Name);
+ public abstract string ManagedType { get; }
+ public virtual string ReturnManagedType => ManagedType;
+
+ public virtual StatementSyntax[] ReturnMarshalResult() => new[] { ParseStatement("return " + Name + ";") };
+
+
+ public virtual void BackPreMarshal(List body)
+ {
+ }
+
+ public virtual ExpressionSyntax BackMarshalValue() => ParseExpression(Name);
+ public virtual ExpressionSyntax BackMarshalReturn(string resultVar) => ParseExpression(resultVar);
+
+ }
+
+ class InterfaceReturnArg : Arg
+ {
+ public string InterfaceType;
+ public override ExpressionSyntax Value(bool isHresultReturn) => ParseExpression("&" + PName);
+ public override string ManagedType => InterfaceType;
+
+ private string PName => "__marshal_" + Name;
+
+ public override void PreMarshalForReturn(List body)
+ {
+ body.Add(ParseStatement("void* " + PName + " = null;"));
+ }
+
+ public override StatementSyntax[] ReturnMarshalResult() => new[]
+ {
+ ParseStatement("return Avalonia.MicroCom.MicroComRuntime.CreateProxyFor<" + InterfaceType + ">(" +
+ PName + ", true);")
+ };
+
+ public override ExpressionSyntax BackMarshalValue()
+ {
+ return ParseExpression("INVALID");
+ }
+
+ public override ExpressionSyntax BackMarshalReturn(string resultVar)
+ {
+ return ParseExpression($"Avalonia.MicroCom.MicroComRuntime.GetNativePointer({resultVar}, true)");
+ }
+ }
+
+ class InterfaceArg : Arg
+ {
+ public string InterfaceType;
+
+ public override ExpressionSyntax Value(bool isHresultReturn) =>
+ ParseExpression("Avalonia.MicroCom.MicroComRuntime.GetNativePointer(" + Name + ")");
+
+ public override string ManagedType => InterfaceType;
+
+ public override StatementSyntax[] ReturnMarshalResult() => new[]
+ {
+ ParseStatement("return Avalonia.MicroCom.MicroComRuntime.CreateProxyFor<" + InterfaceType + ">(" +
+ Name + ", true);")
+ };
+
+ public override ExpressionSyntax BackMarshalValue()
+ {
+ return ParseExpression("Avalonia.MicroCom.MicroComRuntime.CreateProxyFor<" + InterfaceType + ">(" +
+ Name + ", false)");
+ }
+
+ public override ExpressionSyntax BackMarshalReturn(string resultVar)
+ {
+ return ParseExpression($"Avalonia.MicroCom.MicroComRuntime.GetNativePointer({resultVar}, true)");
+ }
+ }
+
+ class BypassArg : Arg
+ {
+ public string Type { get; set; }
+ public int PointerLevel;
+ public override string ManagedType => Type + new string('*', PointerLevel);
+ public override string ReturnManagedType => Type + new string('*', PointerLevel - 1);
+
+ public override ExpressionSyntax Value(bool isHresultReturn)
+ {
+ if (isHresultReturn)
+ return ParseExpression("&" + Name);
+ return base.Value(false);
+ }
+
+ public override void PreMarshalForReturn(List body)
+ {
+ if (PointerLevel == 0)
+ base.PreMarshalForReturn(body);
+ else
+ body.Add(ParseStatement(Type + new string('*', PointerLevel - 1) + " " + Name + "=default;"));
+ }
+ }
+
+ class StringArg : Arg
+ {
+ private string BName => "__bytemarshal_" + Name;
+ private string FName => "__fixedmarshal_" + Name;
+
+ public override void PreMarshal(List body)
+ {
+ body.Add(ParseStatement($"var {BName} = new byte[System.Text.Encoding.UTF8.GetByteCount({Name})+1];"));
+ body.Add(ParseStatement($"System.Text.Encoding.UTF8.GetBytes({Name}, 0, {Name}.Length, {BName}, 0);"));
+ }
+
+ public override StatementSyntax CreateFixed(StatementSyntax inner)
+ {
+ return FixedStatement(DeclareVar("byte*", FName, ParseExpression(BName)), inner);
+ }
+
+ public override ExpressionSyntax Value(bool isHresultReturn) => ParseExpression(FName);
+ public override string ManagedType => "string";
+ public override ExpressionSyntax BackMarshalValue()
+ {
+ return ParseExpression(
+ $"({Name} == null ? null : System.Runtime.InteropServices.Marshal.PtrToStringAnsi(new IntPtr(" + Name + ")))");
+ }
+ }
+
+ string ConvertNativeType(string type)
+ {
+ if (type == "size_t")
+ return "System.IntPtr";
+ if (type == "HRESULT")
+ return "int";
+ return type;
+ }
+
+ Arg ConvertArg(AstInterfaceMemberArgumentNode node)
+ {
+ var arg = ConvertArg(node.Name, node.Type);
+ arg.Attributes = node.Attributes.Clone();
+ return arg;
+ }
+
+ Arg ConvertArg(string name, AstTypeNode type)
+ {
+ type = new AstTypeNode { Name = ConvertNativeType(type.Name), PointerLevel = type.PointerLevel };
+
+ if (type.PointerLevel == 2)
+ {
+ if (IsInterface(type))
+ return new InterfaceReturnArg { Name = name, InterfaceType = type.Name, NativeType = "void**" };
+ }
+ else if (type.PointerLevel == 1)
+ {
+ if (IsInterface(type))
+ return new InterfaceArg { Name = name, InterfaceType = type.Name, NativeType = "void*" };
+ if (type.Name == "char")
+ return new StringArg { Name = name, NativeType = "byte*" };
+ }
+
+ return new BypassArg
+ {
+ Name = name, Type = type.Name, PointerLevel = type.PointerLevel, NativeType = type.ToString()
+ };
+ }
+
+
+ void GenerateInterfaceMember(AstInterfaceMemberNode member, ref InterfaceDeclarationSyntax iface,
+ ref ClassDeclarationSyntax proxy, ref ClassDeclarationSyntax vtbl,
+ List vtblCtor, int num)
+ {
+ // Prepare method information
+ if (member.Name == "GetRenderingDevice")
+ Console.WriteLine();
+ var args = member.Select(ConvertArg).ToList();
+ var returnArg = ConvertArg("__result", member.ReturnType);
+ bool isHresult = member.ReturnType.Name == "HRESULT";
+ bool isHresultLastArgumentReturn = isHresult
+ && args.Count > 0
+ && (args.Last().Name == "ppv"
+ || args.Last().Name == "retOut"
+ || args.Last().Name == "ret"
+ || args.Last().Attributes.HasAttribute("out")
+ || args.Last().Attributes.HasAttribute("retval")
+ )
+ && ((member.Last().Type.PointerLevel > 0
+ && !IsInterface(member.Last().Type))
+ || member.Last().Type.PointerLevel == 2);
+
+ bool isVoidReturn = member.ReturnType.Name == "void" && member.ReturnType.PointerLevel == 0;
+
+
+ // Generate method signature
+ MethodDeclarationSyntax GenerateManagedSig(string returnType, string name,
+ IEnumerable<(string n, string t)> args)
+ => MethodDeclaration(ParseTypeName(returnType), name).WithParameterList(
+ ParameterList(
+ SeparatedList(args.Select(x => Parameter(Identifier(x.n)).WithType(ParseTypeName(x.t))))));
+
+ var managedSig =
+ isHresult ?
+ GenerateManagedSig(isHresultLastArgumentReturn ? args.Last().ReturnManagedType : "void",
+ member.Name,
+ (isHresultLastArgumentReturn ? args.SkipLast(1) : args).Select(a => (a.Name, a.ManagedType))) :
+ GenerateManagedSig(returnArg.ManagedType, member.Name, args.Select(a => (a.Name, a.ManagedType)));
+
+ iface = iface.AddMembers(managedSig.WithSemicolonToken(Semicolon()));
+
+ // Prepare args for marshaling
+ var preMarshal = new List();
+ if (!isVoidReturn)
+ preMarshal.Add(ParseStatement(returnArg.NativeType + " __result;"));
+
+ for (var idx = 0; idx < args.Count; idx++)
+ {
+ if (isHresultLastArgumentReturn && idx == args.Count - 1)
+ args[idx].PreMarshalForReturn(preMarshal);
+ else
+ args[idx].PreMarshal(preMarshal);
+ }
+
+ // Generate call expression
+ ExpressionSyntax callExpr = InvocationExpression(_localInterop.GetCaller(returnArg.NativeType,
+ args.Select(x => x.NativeType).ToList()))
+ .AddArgumentListArguments(Argument(ParseExpression("PPV")))
+ .AddArgumentListArguments(args
+ .Select((a, i) => Argument(a.Value(isHresultLastArgumentReturn && i == args.Count - 1))).ToArray())
+ .AddArgumentListArguments(Argument(ParseExpression("(*PPV)[base.VTableSize + " + num + "]")));
+
+ if (!isVoidReturn)
+ callExpr = CastExpression(ParseTypeName(returnArg.NativeType), callExpr);
+
+ // Save call result if needed
+ if (!isVoidReturn)
+ callExpr = AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, ParseExpression("__result"),
+ callExpr);
+
+
+ // Wrap call into fixed() blocks
+ StatementSyntax callStatement = ExpressionStatement(callExpr);
+ foreach (var arg in args)
+ callStatement = arg.CreateFixed(callStatement);
+
+ // Build proxy body
+ var proxyBody = Block()
+ .AddStatements(preMarshal.ToArray())
+ .AddStatements(callStatement);
+
+ // Process return value
+ if (!isVoidReturn)
+ {
+ if (isHresult)
+ {
+ proxyBody = proxyBody.AddStatements(
+ ParseStatement(
+ $"if(__result != 0) throw new System.Runtime.InteropServices.COMException(\"{member.Name} failed\", __result);"));
+
+ if (isHresultLastArgumentReturn)
+ proxyBody = proxyBody.AddStatements(args.Last().ReturnMarshalResult());
+ }
+ else
+ proxyBody = proxyBody.AddStatements(returnArg.ReturnMarshalResult());
+ }
+
+ // Add the proxy method
+ proxy = proxy.AddMembers(managedSig.AddModifiers(SyntaxKind.PublicKeyword)
+ .WithBody(proxyBody));
+
+
+ // Generate VTable method
+ var shadowDelegate = DelegateDeclaration(ParseTypeName(returnArg.NativeType), member.Name + "Delegate")
+ .AddParameterListParameters(Parameter(Identifier("@this")).WithType(ParseTypeName("IntPtr")))
+ .AddParameterListParameters(args.Select(x =>
+ Parameter(Identifier(x.Name)).WithType(ParseTypeName(x.NativeType))).ToArray())
+ .AddAttribute("System.Runtime.InteropServices.UnmanagedFunctionPointer",
+ "System.Runtime.InteropServices.CallingConvention.StdCall");
+
+ var shadowMethod = MethodDeclaration(shadowDelegate.ReturnType, member.Name)
+ .WithParameterList(shadowDelegate.ParameterList)
+ .AddModifiers(Token(SyntaxKind.StaticKeyword));
+
+ var backPreMarshal = new List();
+ foreach (var arg in args)
+ arg.BackPreMarshal(backPreMarshal);
+
+ backPreMarshal.Add(
+ ParseStatement($"__target = ({iface.Identifier.Text})Avalonia.MicroCom.MicroComRuntime.GetObjectFromCcw(@this);"));
+
+ var isBackVoidReturn = isVoidReturn || (isHresult && !isHresultLastArgumentReturn);
+
+ StatementSyntax backCallStatement;
+
+ var backCallExpr =
+ IsPropertyRewriteCandidate(managedSig) ?
+ ParseExpression("__target." + member.Name.Substring(3)) :
+ InvocationExpression(ParseExpression("__target." + member.Name))
+ .WithArgumentList(ArgumentList(SeparatedList(
+ (isHresultLastArgumentReturn ? args.SkipLast(1) : args)
+ .Select(a =>
+ Argument(a.BackMarshalValue())))));
+
+ if (isBackVoidReturn)
+ backCallStatement = ExpressionStatement(backCallExpr);
+ else
+ {
+ backCallStatement = LocalDeclarationStatement(DeclareVar("var", "__result", backCallExpr));
+ if (isHresultLastArgumentReturn)
+ {
+ backCallStatement = Block(backCallStatement,
+ ExpressionStatement(AssignmentExpression(SyntaxKind.SimpleAssignmentExpression,
+ ParseExpression("*" + args.Last().Name),
+ args.Last().BackMarshalReturn("__result")
+ )));
+
+ }
+ else
+ backCallStatement = Block(backCallStatement,
+ ReturnStatement(returnArg.BackMarshalReturn("__result")));
+ }
+
+ BlockSyntax backBodyBlock = Block().AddStatements(backPreMarshal.ToArray()).AddStatements(backCallStatement);
+
+
+ var exceptions = new List()
+ {
+ CatchClause(
+ CatchDeclaration(ParseTypeName("System.Exception"), Identifier("__exception__")), null,
+ Block(
+ ParseStatement(
+ "Avalonia.MicroCom.MicroComRuntime.UnhandledException(__target, __exception__);"),
+ isHresult ? ParseStatement("return unchecked((int)0x80004005u);")
+ : isVoidReturn ? EmptyStatement() : ParseStatement("return default;")
+ ))
+ };
+
+ if (isHresult)
+ exceptions.Insert(0, CatchClause(
+ CatchDeclaration(ParseTypeName("System.Runtime.InteropServices.COMException"),
+ Identifier("__com_exception__")),
+ null, Block(ParseStatement("return __com_exception__.ErrorCode;"))));
+
+ backBodyBlock = Block(
+ TryStatement(
+ List(exceptions))
+ .WithBlock(Block(backBodyBlock))
+ );
+ if (isHresult)
+ backBodyBlock = backBodyBlock.AddStatements(ParseStatement("return 0;"));
+
+
+ backBodyBlock = Block()
+ .AddStatements(ParseStatement($"{iface.Identifier.Text} __target = null;"))
+ .AddStatements(backBodyBlock.Statements.ToArray());
+
+ shadowMethod = shadowMethod.WithBody(backBodyBlock);
+
+ vtbl = vtbl.AddMembers(shadowDelegate).AddMembers(shadowMethod);
+ vtblCtor.Add(ParseStatement("base.AddMethod((" + shadowDelegate.Identifier.Text + ")" +
+ shadowMethod.Identifier.Text + ");"));
+
+
+
+
+ }
+
+ class LocalInteropHelper
+ {
+ public ClassDeclarationSyntax Class { get; private set; } = ClassDeclaration("LocalInterop");
+ private HashSet _existing = new HashSet();
+
+ public ExpressionSyntax GetCaller(string returnType, List args)
+ {
+ string ConvertType(string t) => t.EndsWith("*") ? "void*" : t;
+ returnType = ConvertType(returnType);
+ args = args.Select(ConvertType).ToList();
+
+ var name = "CalliStdCall" + returnType.Replace("*", "_ptr");
+ var signature = returnType + "::" + name + "::" + string.Join("::", args);
+ if (_existing.Add(signature))
+ {
+ Class = Class.AddMembers(MethodDeclaration(ParseTypeName(returnType), name)
+ .AddModifiers(SyntaxKind.StaticKeyword, SyntaxKind.UnsafeKeyword, SyntaxKind.PublicKeyword)
+ .AddParameterListParameters(Parameter(Identifier("thisObj")).WithType(ParseTypeName("void*")))
+ .AddParameterListParameters(args.Select((x, i) =>
+ Parameter(Identifier("arg" + i)).WithType(ParseTypeName(x))).ToArray())
+ .AddParameterListParameters(Parameter(Identifier("methodPtr")).WithType(ParseTypeName("void*")))
+ .WithBody(Block(ExpressionStatement(ThrowExpression(ParseExpression("null"))))));
+ }
+
+ return ParseExpression("LocalInterop." + name);
+ }
+ }
+
+
+ void GenerateInterface(ref NamespaceDeclarationSyntax ns, ref NamespaceDeclarationSyntax implNs,
+ AstInterfaceNode iface)
+ {
+ var guidString = iface.GetAttribute("uuid");
+ var inheritsUnknown = iface.Inherits == null || iface.Inherits == "IUnknown";
+
+ var ifaceDec = InterfaceDeclaration(iface.Name)
+ .WithBaseType(inheritsUnknown ? "Avalonia.MicroCom.IUnknown" : iface.Inherits)
+ .AddModifiers(Token(_visibility), Token(SyntaxKind.UnsafeKeyword), Token(SyntaxKind.PartialKeyword));
+
+ var proxyClassName = "__MicroCom" + iface.Name + "Proxy";
+ var proxy = ClassDeclaration(proxyClassName)
+ .AddModifiers(Token(SyntaxKind.UnsafeKeyword), Token(_visibility), Token(SyntaxKind.PartialKeyword))
+ .WithBaseType(inheritsUnknown ?
+ "Avalonia.MicroCom.MicroComProxyBase" :
+ ("__MicroCom" + iface.Inherits + "Proxy"))
+ .AddBaseListTypes(SimpleBaseType(ParseTypeName(iface.Name)));
+
+
+ // Generate vtable
+ var vtbl = ClassDeclaration("__MicroCom" + iface.Name + "VTable")
+ .AddModifiers(Token(SyntaxKind.UnsafeKeyword));
+
+ vtbl = vtbl.WithBaseType(inheritsUnknown ?
+ "Avalonia.MicroCom.MicroComVtblBase" :
+ "__MicroCom" + iface.Inherits + "VTable");
+
+ var vtblCtor = new List();
+ for (var idx = 0; idx < iface.Count; idx++)
+ GenerateInterfaceMember(iface[idx], ref ifaceDec, ref proxy, ref vtbl, vtblCtor, idx);
+
+ vtbl = vtbl.AddMembers(
+ ConstructorDeclaration(vtbl.Identifier.Text)
+ .AddModifiers(Token(SyntaxKind.PublicKeyword))
+ .WithBody(Block(vtblCtor))
+ )
+ .AddMembers(MethodDeclaration(ParseTypeName("void"), "__MicroComModuleInit")
+ .AddModifiers(Token(SyntaxKind.StaticKeyword), Token(SyntaxKind.InternalKeyword))
+ .WithExpressionBody(ArrowExpressionClause(
+ ParseExpression("Avalonia.MicroCom.MicroComRuntime.RegisterVTable(typeof(" +
+ iface.Name + "), new " + vtbl.Identifier.Text + "().CreateVTable())")))
+ .WithSemicolonToken(Semicolon()));
+
+
+ // Finalize proxy code
+ proxy = proxy.AddMembers(
+ MethodDeclaration(ParseTypeName("void"), "__MicroComModuleInit")
+ .AddModifiers(Token(SyntaxKind.StaticKeyword), Token(SyntaxKind.InternalKeyword))
+ .WithBody(Block(
+ ParseStatement("Avalonia.MicroCom.MicroComRuntime.Register(typeof(" +
+ iface.Name + "), new Guid(\"" + guidString + "\"), (p, owns) => new " +
+ proxyClassName + "(p, owns));")
+ )))
+ .AddMembers(ParseMemberDeclaration("public " + proxyClassName +
+ "(IntPtr nativePointer, bool ownsHandle) : base(nativePointer, ownsHandle) {}"))
+ .AddMembers(ParseMemberDeclaration("protected override int VTableSize => base.VTableSize + " +
+ iface.Count + ";"));
+
+ ns = ns.AddMembers(RewriteMethodsToProperties(ifaceDec));
+ implNs = implNs.AddMembers(RewriteMethodsToProperties(proxy), RewriteMethodsToProperties(vtbl));
+ }
+ }
+}
diff --git a/src/tools/MicroComGenerator/CSharpGen.Utils.cs b/src/tools/MicroComGenerator/CSharpGen.Utils.cs
new file mode 100644
index 0000000000..da845b0ecd
--- /dev/null
+++ b/src/tools/MicroComGenerator/CSharpGen.Utils.cs
@@ -0,0 +1,111 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using MicroComGenerator.Ast;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.CSharp.Formatting;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+
+using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
+namespace MicroComGenerator
+{
+ public partial class CSharpGen
+ {
+
+ CompilationUnitSyntax Unit()
+ => CompilationUnit().WithUsings(List(new[]
+ {
+ "System", "System.Text", "System.Collections", "System.Collections.Generic", "Avalonia.MicroCom"
+ }
+ .Concat(_extraUsings).Select(u => UsingDirective(IdentifierName(u)))));
+
+ string Format(CompilationUnitSyntax unit)
+ {
+ var cw = new AdhocWorkspace();
+ return
+ "#pragma warning disable 108\n" +
+ Microsoft.CodeAnalysis.Formatting.Formatter.Format(unit.NormalizeWhitespace(), cw, cw.Options
+ .WithChangedOption(CSharpFormattingOptions.NewLineForMembersInObjectInit, true)
+ .WithChangedOption(CSharpFormattingOptions.NewLinesForBracesInObjectCollectionArrayInitializers,
+ true)
+ .WithChangedOption(CSharpFormattingOptions.NewLineForMembersInAnonymousTypes, true)
+ .WithChangedOption(CSharpFormattingOptions.NewLinesForBracesInMethods, true)
+
+ ).ToFullString();
+ }
+
+
+ SyntaxToken Semicolon() => Token(SyntaxKind.SemicolonToken);
+
+ static VariableDeclarationSyntax DeclareVar(string type, string name,
+ ExpressionSyntax? initializer = null)
+ => VariableDeclaration(ParseTypeName(type),
+ SingletonSeparatedList(VariableDeclarator(name)
+ .WithInitializer(initializer == null ? null : EqualsValueClause(initializer))));
+
+ FieldDeclarationSyntax DeclareConstant(string type, string name, LiteralExpressionSyntax value)
+ => FieldDeclaration(
+ VariableDeclaration(ParseTypeName(type),
+ SingletonSeparatedList(
+ VariableDeclarator(name).WithInitializer(EqualsValueClause(value))
+ ))
+ ).WithSemicolonToken(Semicolon())
+ .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.ConstKeyword)));
+
+ FieldDeclarationSyntax DeclareField(string type, string name, params SyntaxKind[] modifiers) =>
+ DeclareField(type, name, null, modifiers);
+
+ FieldDeclarationSyntax DeclareField(string type, string name, EqualsValueClauseSyntax initializer,
+ params SyntaxKind[] modifiers) =>
+ FieldDeclaration(
+ VariableDeclaration(ParseTypeName(type),
+ SingletonSeparatedList(
+ VariableDeclarator(name).WithInitializer(initializer))))
+ .WithSemicolonToken(Semicolon())
+ .WithModifiers(TokenList(modifiers.Select(x => Token(x))));
+
+ bool IsPropertyRewriteCandidate(MethodDeclarationSyntax method)
+ {
+
+ return
+ method.ReturnType.ToFullString() != "void"
+ && method.Identifier.Text.StartsWith("Get")
+ && method.ParameterList.Parameters.Count == 0;
+ }
+
+ TypeDeclarationSyntax RewriteMethodsToProperties(T decl) where T : TypeDeclarationSyntax
+ {
+ var replace = new Dictionary();
+ foreach (var method in decl.Members.OfType().ToList())
+ {
+ if (IsPropertyRewriteCandidate(method))
+ {
+ var getter = AccessorDeclaration(SyntaxKind.GetAccessorDeclaration);
+ if (method.Body != null)
+ getter = getter.WithBody(method.Body);
+ else
+ getter = getter.WithSemicolonToken(Semicolon());
+
+ replace[method] = PropertyDeclaration(method.ReturnType,
+ method.Identifier.Text.Substring(3))
+ .WithModifiers(method.Modifiers).AddAccessorListAccessors(getter);
+
+ }
+ }
+
+ return decl.ReplaceNodes(replace.Keys, (m, m2) => replace[m]);
+ }
+
+ bool IsInterface(string name)
+ {
+ if (name == "IUnknown")
+ return true;
+ return _idl.Interfaces.Any(i => i.Name == name);
+ }
+
+ private bool IsInterface(AstTypeNode type) => IsInterface(type.Name);
+
+ }
+}
diff --git a/src/tools/MicroComGenerator/CSharpGen.cs b/src/tools/MicroComGenerator/CSharpGen.cs
new file mode 100644
index 0000000000..ff4c351fd9
--- /dev/null
+++ b/src/tools/MicroComGenerator/CSharpGen.cs
@@ -0,0 +1,155 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using MicroComGenerator.Ast;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
+// ReSharper disable CoVariantArrayConversion
+
+namespace MicroComGenerator
+{
+ public partial class CSharpGen
+ {
+ private readonly AstIdlNode _idl;
+ private List _extraUsings;
+ private string _namespace;
+ private SyntaxKind _visibility;
+ private LocalInteropHelper _localInterop = new LocalInteropHelper();
+
+ public CSharpGen(AstIdlNode idl)
+ {
+ _idl = idl.Clone();
+ new AstRewriter(_idl.Attributes.Where(a => a.Name == "clr-map")
+ .Select(x => x.Value.Trim().Split(' '))
+ .ToDictionary(x => x[0], x => x[1])
+ ).VisitAst(_idl);
+
+ _extraUsings = _idl.Attributes.Where(u => u.Name == "clr-using").Select(u => u.Value).ToList();
+ _namespace = _idl.GetAttribute("clr-namespace");
+ var visibilityString = _idl.GetAttribute("clr-access");
+
+ if (visibilityString == "internal")
+ _visibility = SyntaxKind.InternalKeyword;
+ else if (visibilityString == "public")
+ _visibility = SyntaxKind.PublicKeyword;
+ else
+ throw new CodeGenException("Invalid clr-access attribute");
+ }
+
+ class AstRewriter : AstVisitor
+ {
+ private readonly Dictionary _typeMap = new Dictionary();
+
+ public AstRewriter(Dictionary typeMap)
+ {
+ _typeMap = typeMap;
+ }
+
+ void ConvertIntPtr(AstTypeNode type)
+ {
+ if (type.Name == "void" && type.PointerLevel > 0)
+ {
+ type.Name = "IntPtr";
+ type.PointerLevel--;
+ }
+ }
+
+ protected override void VisitStructMember(AstStructMemberNode member)
+ {
+ if (member.HasAttribute("intptr"))
+ ConvertIntPtr(member.Type);
+ base.VisitStructMember(member);
+ }
+
+ protected override void VisitType(AstTypeNode type)
+ {
+ if (type.IsLink)
+ {
+ type.PointerLevel++;
+ type.IsLink = false;
+ }
+
+ if (_typeMap.TryGetValue(type.Name, out var mapped))
+ type.Name = mapped;
+
+ base.VisitType(type);
+ }
+
+ protected override void VisitArgument(AstInterfaceMemberArgumentNode argument)
+ {
+ if (argument.HasAttribute("intptr"))
+ {
+ if(argument.Name == "retOut")
+ Console.WriteLine();
+ ConvertIntPtr(argument.Type);
+ }
+
+ base.VisitArgument(argument);
+ }
+
+ protected override void VisitInterfaceMember(AstInterfaceMemberNode member)
+ {
+ if (member.HasAttribute("intptr"))
+ ConvertIntPtr(member.ReturnType);
+ if (member.HasAttribute("propget") && !member.Name.StartsWith("Get"))
+ member.Name = "Get" + member.Name;
+ if (member.HasAttribute("propput") && !member.Name.StartsWith("Set"))
+ member.Name = "Set" + member.Name;
+ base.VisitInterfaceMember(member);
+ }
+ }
+
+
+ public string Generate()
+ {
+ var ns = NamespaceDeclaration(ParseName(_namespace));
+ var implNs = NamespaceDeclaration(ParseName(_namespace + ".Impl"));
+ ns = GenerateEnums(ns);
+ ns = GenerateStructs(ns);
+ foreach (var i in _idl.Interfaces)
+ GenerateInterface(ref ns, ref implNs, i);
+
+ implNs = implNs.AddMembers(_localInterop.Class);
+ var unit = Unit().AddMembers(ns, implNs);
+
+ return Format(unit);
+ }
+
+ NamespaceDeclarationSyntax GenerateEnums(NamespaceDeclarationSyntax ns)
+ {
+ return ns.AddMembers(_idl.Enums.Select(e =>
+ {
+ var dec = EnumDeclaration(e.Name)
+ .WithModifiers(TokenList(Token(_visibility)))
+ .WithMembers(SeparatedList(e.Select(m =>
+ {
+ var member = EnumMemberDeclaration(m.Name);
+ if (m.Value != null)
+ return member.WithEqualsValue(EqualsValueClause(ParseExpression(m.Value)));
+ return member;
+ })));
+ if (e.HasAttribute("flags"))
+ dec = dec.AddAttribute("System.Flags");
+ return dec;
+ }).ToArray());
+ }
+
+ NamespaceDeclarationSyntax GenerateStructs(NamespaceDeclarationSyntax ns)
+ {
+ return ns.AddMembers(_idl.Structs.Select(e =>
+ StructDeclaration(e.Name)
+ .WithModifiers(TokenList(Token(_visibility)))
+ .AddAttribute("System.Runtime.InteropServices.StructLayout", "System.Runtime.InteropServices.LayoutKind.Sequential")
+ .AddModifiers(Token(SyntaxKind.UnsafeKeyword))
+ .WithMembers(new SyntaxList(SeparatedList(e.Select(m =>
+ DeclareField(m.Type.ToString(), m.Name, SyntaxKind.PublicKeyword)))))
+ ).ToArray());
+ }
+
+
+
+ }
+}
diff --git a/src/tools/MicroComGenerator/CppGen.cs b/src/tools/MicroComGenerator/CppGen.cs
new file mode 100644
index 0000000000..b053088ca9
--- /dev/null
+++ b/src/tools/MicroComGenerator/CppGen.cs
@@ -0,0 +1,119 @@
+using System;
+using System.Linq;
+using System.Text;
+using MicroComGenerator.Ast;
+
+namespace MicroComGenerator
+{
+ public class CppGen
+ {
+ static string ConvertType(AstTypeNode type)
+ {
+ var name = type.Name;
+ if (name == "byte")
+ name = "unsigned char";
+ else if(name == "uint")
+ name = "unsigned int";
+
+ type = type.Clone();
+ type.Name = name;
+ return type.Format();
+ }
+
+ public static string GenerateCpp(AstIdlNode idl)
+ {
+ var sb = new StringBuilder();
+ var preamble = idl.GetAttributeOrDefault("cpp-preamble");
+ if (preamble != null)
+ sb.AppendLine(preamble);
+
+ foreach (var s in idl.Structs)
+ sb.AppendLine("struct " + s.Name + ";");
+
+ foreach (var s in idl.Interfaces)
+ sb.AppendLine("struct " + s.Name + ";");
+
+ foreach (var en in idl.Enums)
+ {
+ sb.Append("enum ");
+ if (en.Attributes.Any(a => a.Name == "class-enum"))
+ sb.Append("class ");
+ sb.AppendLine(en.Name).AppendLine("{");
+
+ foreach (var m in en)
+ {
+ sb.Append(" ").Append(m.Name);
+ if (m.Value != null)
+ sb.Append(" = ").Append(m.Value);
+ sb.AppendLine(",");
+ }
+
+ sb.AppendLine("};");
+ }
+
+ foreach (var s in idl.Structs)
+ {
+ sb.Append("struct ").AppendLine(s.Name).AppendLine("{");
+ foreach (var m in s)
+ sb.Append(" ").Append(ConvertType(m.Type)).Append(" ").Append(m.Name).AppendLine(";");
+
+ sb.AppendLine("};");
+ }
+
+ foreach (var i in idl.Interfaces)
+ {
+ var guidString = i.GetAttribute("uuid");
+ var guid = Guid.Parse(guidString).ToString().Replace("-", "");
+
+
+ sb.Append("COMINTERFACE(").Append(i.Name).Append(", ")
+ .Append(guid.Substring(0, 8)).Append(", ")
+ .Append(guid.Substring(8, 4)).Append(", ")
+ .Append(guid.Substring(12, 4));
+ for (var c = 0; c < 8; c++)
+ {
+ sb.Append(", ").Append(guid.Substring(16 + c * 2, 2));
+ }
+
+ sb.Append(") : ");
+ if (i.HasAttribute("cpp-virtual-inherits"))
+ sb.Append("virtual ");
+ sb.AppendLine(i.Inherits ?? "IUnknown")
+ .AppendLine("{");
+
+ foreach (var m in i)
+ {
+ sb.Append(" ")
+ .Append("virtual ")
+ .Append(ConvertType(m.ReturnType))
+ .Append(" ").Append(m.Name).Append(" (");
+ if (m.Count == 0)
+ sb.AppendLine(") = 0;");
+ else
+ {
+ sb.AppendLine();
+ for (var c = 0; c < m.Count; c++)
+ {
+ var arg = m[c];
+ sb.Append(" ");
+ if (arg.Attributes.Any(a => a.Name == "const"))
+ sb.Append("const ");
+ sb.Append(ConvertType(arg.Type))
+ .Append(" ")
+ .Append(arg.Name);
+ if (c != m.Count - 1)
+ sb.Append(", ");
+ sb.AppendLine();
+ }
+
+ sb.AppendLine(" ) = 0;");
+ }
+ }
+
+ sb.AppendLine("};");
+ }
+
+ return sb.ToString();
+ }
+ }
+}
diff --git a/src/tools/MicroComGenerator/Extensions.cs b/src/tools/MicroComGenerator/Extensions.cs
new file mode 100644
index 0000000000..c8a4c8f45c
--- /dev/null
+++ b/src/tools/MicroComGenerator/Extensions.cs
@@ -0,0 +1,97 @@
+
+using System;
+using System.Linq;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
+namespace MicroComGenerator
+{
+ public static class Extensions
+ {
+ public static ClassDeclarationSyntax AddModifiers(this ClassDeclarationSyntax cl, params SyntaxKind[] modifiers)
+ {
+ if (modifiers == null)
+ return cl;
+ return cl.AddModifiers(modifiers.Select(x => SyntaxFactory.Token(x)).ToArray());
+ }
+
+ public static MethodDeclarationSyntax AddModifiers(this MethodDeclarationSyntax cl, params SyntaxKind[] modifiers)
+ {
+ if (modifiers == null)
+ return cl;
+ return cl.AddModifiers(modifiers.Select(x => SyntaxFactory.Token(x)).ToArray());
+ }
+
+ public static PropertyDeclarationSyntax AddModifiers(this PropertyDeclarationSyntax cl, params SyntaxKind[] modifiers)
+ {
+ if (modifiers == null)
+ return cl;
+ return cl.AddModifiers(modifiers.Select(x => SyntaxFactory.Token(x)).ToArray());
+ }
+
+ public static ConstructorDeclarationSyntax AddModifiers(this ConstructorDeclarationSyntax cl, params SyntaxKind[] modifiers)
+ {
+ if (modifiers == null)
+ return cl;
+ return cl.AddModifiers(modifiers.Select(x => SyntaxFactory.Token(x)).ToArray());
+ }
+
+ public static AccessorDeclarationSyntax AddModifiers(this AccessorDeclarationSyntax cl, params SyntaxKind[] modifiers)
+ {
+ if (modifiers == null)
+ return cl;
+ return cl.AddModifiers(modifiers.Select(x => SyntaxFactory.Token(x)).ToArray());
+ }
+
+ public static string WithLowerFirst(this string s)
+ {
+ if (string.IsNullOrEmpty(s))
+ return s;
+ return char.ToLowerInvariant(s[0]) + s.Substring(1);
+ }
+
+ public static ExpressionSyntax MemberAccess(params string[] identifiers)
+ {
+ if (identifiers == null || identifiers.Length == 0)
+ throw new ArgumentException();
+ var expr = (ExpressionSyntax)IdentifierName(identifiers[0]);
+ for (var c = 1; c < identifiers.Length; c++)
+ expr = MemberAccess(expr, identifiers[c]);
+ return expr;
+ }
+
+ public static ExpressionSyntax MemberAccess(ExpressionSyntax expr, params string[] identifiers)
+ {
+ foreach (var i in identifiers)
+ expr = MemberAccess(expr, i);
+ return expr;
+ }
+
+ public static MemberAccessExpressionSyntax MemberAccess(ExpressionSyntax expr, string identifier) =>
+ MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, expr, IdentifierName(identifier));
+
+ public static ClassDeclarationSyntax WithBaseType(this ClassDeclarationSyntax cl, string bt)
+ {
+ return cl.AddBaseListTypes(SimpleBaseType(SyntaxFactory.ParseTypeName(bt)));
+ }
+
+ public static InterfaceDeclarationSyntax WithBaseType(this InterfaceDeclarationSyntax cl, string bt)
+ {
+ return cl.AddBaseListTypes(SimpleBaseType(SyntaxFactory.ParseTypeName(bt)));
+ }
+
+ public static T AddAttribute(this T member, string attribute, params string[] args) where T : MemberDeclarationSyntax
+ {
+ return (T)member.AddAttributeLists(AttributeList(SingletonSeparatedList(
+ Attribute(ParseName(attribute), AttributeArgumentList(
+ SeparatedList(args.Select(a => AttributeArgument(ParseExpression(a)))))))));
+ }
+
+ public static string StripPrefix(this string s, string prefix) => string.IsNullOrEmpty(s)
+ ? s
+ : s.StartsWith(prefix)
+ ? s.Substring(prefix.Length)
+ : s;
+ }
+}
diff --git a/src/tools/MicroComGenerator/MicroComGenerator.csproj b/src/tools/MicroComGenerator/MicroComGenerator.csproj
new file mode 100644
index 0000000000..5ae431b4b9
--- /dev/null
+++ b/src/tools/MicroComGenerator/MicroComGenerator.csproj
@@ -0,0 +1,10 @@
+
+
+ Exe
+ netcoreapp3.1
+
+
+
+
+
+
diff --git a/src/tools/MicroComGenerator/ParseException.cs b/src/tools/MicroComGenerator/ParseException.cs
new file mode 100644
index 0000000000..dfa8dcfe54
--- /dev/null
+++ b/src/tools/MicroComGenerator/ParseException.cs
@@ -0,0 +1,27 @@
+using System;
+
+namespace MicroComGenerator
+{
+ class ParseException : Exception
+ {
+ public int Line { get; }
+ public int Position { get; }
+
+ public ParseException(string message, int line, int position) : base(message)
+ {
+ Line = line;
+ Position = position;
+ }
+
+ public ParseException(string message, ref TokenParser parser) : this(message, parser.Line, parser.Position)
+ {
+ }
+ }
+
+ class CodeGenException : Exception
+ {
+ public CodeGenException(string message) : base(message)
+ {
+ }
+ }
+}
diff --git a/src/tools/MicroComGenerator/Program.cs b/src/tools/MicroComGenerator/Program.cs
new file mode 100644
index 0000000000..578ba1465d
--- /dev/null
+++ b/src/tools/MicroComGenerator/Program.cs
@@ -0,0 +1,44 @@
+using System;
+using System.IO;
+using System.Linq;
+using CommandLine;
+
+namespace MicroComGenerator
+{
+ class Program
+ {
+ public class Options
+ {
+ [Option('i', "input", Required = true, HelpText = "Input IDL file")]
+ public string Input { get; set; }
+
+ [Option("cpp", Required = false, HelpText = "C++ output file")]
+ public string CppOutput { get; set; }
+
+ [Option("cs", Required = false, HelpText = "C# output file")]
+ public string CSharpOutput { get; set; }
+
+ }
+
+ static int Main(string[] args)
+ {
+ var p = Parser.Default.ParseArguments(args);
+ if (p is NotParsed)
+ {
+ return 1;
+ }
+
+ var opts = ((Parsed)p).Value;
+
+ var text = File.ReadAllText(opts.Input);
+ var ast = AstParser.Parse(text);
+
+ if (opts.CppOutput != null)
+ File.WriteAllText(opts.CppOutput, CppGen.GenerateCpp(ast));
+ if (opts.CSharpOutput != null)
+ File.WriteAllText(opts.CSharpOutput, new CSharpGen(ast).Generate());
+
+ return 0;
+ }
+ }
+}
diff --git a/src/tools/MicroComGenerator/TokenParser.cs b/src/tools/MicroComGenerator/TokenParser.cs
new file mode 100644
index 0000000000..ea8850b8e4
--- /dev/null
+++ b/src/tools/MicroComGenerator/TokenParser.cs
@@ -0,0 +1,417 @@
+using System;
+using System.Globalization;
+using System.IO;
+
+namespace MicroComGenerator
+{
+ internal ref struct TokenParser
+ {
+ private ReadOnlySpan _s;
+ public int Position { get; private set; }
+ public int Line { get; private set; }
+ public TokenParser(ReadOnlySpan s)
+ {
+ _s = s;
+ Position = 0;
+ Line = 0;
+ }
+
+ public void SkipWhitespace()
+ {
+ while (true)
+ {
+ if(_s.Length == 0)
+ return;
+ if (char.IsWhiteSpace(_s[0]))
+ Advance(1);
+ else if (_s[0] == '/' && _s.Length>1)
+ {
+ if (_s[1] == '/')
+ SkipOneLineComment();
+ else if (_s[1] == '*')
+ SkipMultiLineComment();
+ else
+ return;
+ }
+ else
+ return;
+ }
+ }
+
+ void SkipOneLineComment()
+ {
+ while (true)
+ {
+ if (_s.Length > 0 && _s[0] != '\n' && _s[0] != '\r')
+ Advance(1);
+ else
+ return;
+ }
+ }
+
+ void SkipMultiLineComment()
+ {
+ var l = Line;
+ var p = Position;
+ while (true)
+ {
+ if (_s.Length == 0)
+ throw new ParseException("No matched */ found for /*", l, p);
+
+ if (_s[0] == '*' && _s.Length > 1 && _s[1] == '/')
+ {
+ Advance(2);
+ return;
+ }
+
+ Advance(1);
+ }
+ }
+
+ static bool IsAlphaNumeric(char ch) => (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'z') ||
+ (ch >= 'A' && ch <= 'Z');
+
+ public void Consume(char c)
+ {
+ if (!TryConsume(c))
+ throw new ParseException("Expected " + c, Line, Position);
+ }
+ public bool TryConsume(char c)
+ {
+ SkipWhitespace();
+ if (_s.Length == 0 || _s[0] != c)
+ return false;
+
+ Advance(1);
+ return true;
+ }
+
+ public bool TryConsume(string s)
+ {
+ SkipWhitespace();
+ if (_s.Length < s.Length)
+ return false;
+ for (var c = 0; c < s.Length; c++)
+ {
+ if (_s[c] != s[c])
+ return false;
+ }
+
+ Advance(s.Length);
+ return true;
+ }
+
+ public bool TryConsumeAny(ReadOnlySpan chars, out char token)
+ {
+ SkipWhitespace();
+ token = default;
+ if (_s.Length == 0)
+ return false;
+
+ foreach (var c in chars)
+ {
+ if (c == _s[0])
+ {
+ token = c;
+ Advance(1);
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+
+ public bool TryParseKeyword(string keyword)
+ {
+ SkipWhitespace();
+ if (keyword.Length > _s.Length)
+ return false;
+ for(var c=0; c keyword.Length && IsAlphaNumeric(_s[keyword.Length]))
+ return false;
+
+ Advance(keyword.Length);
+ return true;
+ }
+
+ public bool TryParseKeywordLowerCase(string keywordInLowerCase)
+ {
+ SkipWhitespace();
+ if (keywordInLowerCase.Length > _s.Length)
+ return false;
+ for(var c=0; c keywordInLowerCase.Length && IsAlphaNumeric(_s[keywordInLowerCase.Length]))
+ return false;
+
+ Advance(keywordInLowerCase.Length);
+ return true;
+ }
+
+ public void Advance(int c)
+ {
+ while (c > 0)
+ {
+ if (_s[0] == '\n')
+ {
+ Line++;
+ Position = 0;
+ }
+ else
+ Position++;
+
+ _s = _s.Slice(1);
+ c--;
+ }
+ }
+
+ public int Length => _s.Length;
+ public bool Eof
+ {
+ get
+ {
+ SkipWhitespace();
+ return Length == 0;
+ }
+ }
+
+ public char Peek
+ {
+ get
+ {
+ if (_s.Length == 0)
+ throw new ParseException("Unexpected EOF", Line, Position);
+ return _s[0];
+ }
+ }
+
+ public string ParseIdentifier(ReadOnlySpan extraValidChars)
+ {
+ if (!TryParseIdentifier(extraValidChars, out var ident))
+ throw new ParseException("Identifier expected", Line, Position);
+ return ident.ToString();
+ }
+
+ public string ParseIdentifier()
+ {
+ if (!TryParseIdentifier(out var ident))
+ throw new ParseException("Identifier expected", Line, Position);
+ return ident.ToString();
+ }
+
+ public bool TryParseIdentifier(ReadOnlySpan extraValidChars, out ReadOnlySpan res)
+ {
+ res = ReadOnlySpan.Empty;
+ SkipWhitespace();
+ if (_s.Length == 0)
+ return false;
+ var first = _s[0];
+ if (!((first >= 'a' && first <= 'z') || (first >= 'A' && first <= 'Z') || first == '_'))
+ return false;
+ int len = 1;
+ for (var c = 1; c < _s.Length; c++)
+ {
+ var ch = _s[c];
+ if (IsAlphaNumeric(ch) || ch == '_')
+ len++;
+ else
+ {
+ var found = false;
+ foreach(var vc in extraValidChars)
+ if (vc == ch)
+ {
+ found = true;
+ break;
+ }
+
+ if (found)
+ len++;
+ else
+ break;
+ }
+ }
+
+ res = _s.Slice(0, len);
+ Advance(len);
+ return true;
+ }
+
+ public bool TryParseIdentifier(out ReadOnlySpan res)
+ {
+ res = ReadOnlySpan.Empty;
+ SkipWhitespace();
+ if (_s.Length == 0)
+ return false;
+ var first = _s[0];
+ if (!((first >= 'a' && first <= 'z') || (first >= 'A' && first <= 'Z') || first == '_'))
+ return false;
+ int len = 1;
+ for (var c = 1; c < _s.Length; c++)
+ {
+ var ch = _s[c];
+ if (IsAlphaNumeric(ch) || ch == '_')
+ len++;
+ else
+ break;
+ }
+
+ res = _s.Slice(0, len);
+ Advance(len);
+ return true;
+ }
+
+ public string ReadToEol()
+ {
+ var initial = _s;
+ var len = 0;
+ while (true)
+ {
+ if (_s.Length > 0 && _s[0] != '\n' && _s[0] != '\r')
+ {
+ len++;
+ Advance(1);
+ }
+ else
+ return initial.Slice(0, len).ToString();
+ }
+ }
+
+ public string ReadTo(char c)
+ {
+ var initial = _s;
+ var len = 0;
+ var l = Line;
+ var p = Position;
+ while (true)
+ {
+ if (_s.Length == 0)
+ throw new ParseException("Expected " + c + " before EOF", l, p);
+
+ if (_s[0] != c)
+ {
+ len++;
+ Advance(1);
+ }
+ else
+ return initial.Slice(0, len).ToString();
+ }
+ }
+
+ public string ReadToAny(ReadOnlySpan chars)
+ {
+ var initial = _s;
+ var len = 0;
+ var l = Line;
+ var p = Position;
+ while (true)
+ {
+ if (_s.Length == 0)
+ throw new ParseException("Expected any of '" + chars.ToString() + "' before EOF", l, p);
+
+ var foundTerminator = false;
+ foreach (var term in chars)
+ {
+ if (_s[0] == term)
+ {
+ foundTerminator = true;
+ break;
+ }
+ }
+
+ if (!foundTerminator)
+ {
+ len++;
+ Advance(1);
+ }
+ else
+ return initial.Slice(0, len).ToString();
+ }
+ }
+
+ public bool TryParseCall(out ReadOnlySpan res)
+ {
+ res = ReadOnlySpan.Empty;
+ SkipWhitespace();
+ if (_s.Length == 0)
+ return false;
+ var first = _s[0];
+ if (!((first >= 'a' && first <= 'z') || (first >= 'A' && first <= 'Z')))
+ return false;
+ int len = 1;
+ for (var c = 1; c < _s.Length; c++)
+ {
+ var ch = _s[c];
+ if ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch<= 'Z') || ch == '.')
+ len++;
+ else
+ break;
+ }
+
+ res = _s.Slice(0, len);
+
+ // Find '('
+ for (var c = len; c < _s.Length; c++)
+ {
+ if(char.IsWhiteSpace(_s[c]))
+ continue;
+ if(_s[c]=='(')
+ {
+ Advance(c + 1);
+ return true;
+ }
+
+ return false;
+
+ }
+
+ return false;
+
+ }
+
+
+ public bool TryParseFloat(out float res)
+ {
+ res = 0;
+ SkipWhitespace();
+ if (_s.Length == 0)
+ return false;
+
+ var len = 0;
+ var dotCount = 0;
+ for (var c = 0; c < _s.Length; c++)
+ {
+ var ch = _s[c];
+ if (ch >= '0' && ch <= '9')
+ len = c + 1;
+ else if (ch == '.' && dotCount == 0)
+ {
+ len = c + 1;
+ dotCount++;
+ }
+ else
+ break;
+ }
+
+ var span = _s.Slice(0, len);
+
+#if NETSTANDARD2_0
+ if (!float.TryParse(span.ToString(), NumberStyles.Number, CultureInfo.InvariantCulture, out res))
+ return false;
+#else
+ if (!float.TryParse(span, NumberStyles.Number, CultureInfo.InvariantCulture, out res))
+ return false;
+#endif
+ Advance(len);
+ return true;
+ }
+
+ public override string ToString() => _s.ToString();
+
+ }
+}
diff --git a/tests/Avalonia.Animation.UnitTests/AnimatableTests.cs b/tests/Avalonia.Animation.UnitTests/AnimatableTests.cs
index 784f40fe1f..7633a761a3 100644
--- a/tests/Avalonia.Animation.UnitTests/AnimatableTests.cs
+++ b/tests/Avalonia.Animation.UnitTests/AnimatableTests.cs
@@ -113,7 +113,7 @@ namespace Avalonia.Animation.UnitTests
It.IsAny(),
1.0,
0.5));
- target.ResetCalls();
+ target.Invocations.Clear();
control.SetValue(Visual.OpacityProperty, 0.8, BindingPriority.StyleTrigger);
@@ -135,7 +135,7 @@ namespace Avalonia.Animation.UnitTests
target.Setup(x => x.Apply(control, It.IsAny(), 1.0, 0.5)).Returns(sub.Object);
control.Opacity = 0.5;
- sub.ResetCalls();
+ sub.Invocations.Clear();
control.Opacity = 0.4;
sub.Verify(x => x.Dispose());
@@ -158,7 +158,7 @@ namespace Avalonia.Animation.UnitTests
control.Opacity = 0.5;
Assert.Equal(0.9, control.Opacity);
- target.ResetCalls();
+ target.Invocations.Clear();
control.Opacity = 0.4;
@@ -182,7 +182,7 @@ namespace Avalonia.Animation.UnitTests
It.IsAny(),
1.0,
0.5));
- target.ResetCalls();
+ target.Invocations.Clear();
var root = (TestRoot)control.Parent;
root.Child = null;
diff --git a/tests/Avalonia.Animation.UnitTests/Avalonia.Animation.UnitTests.csproj b/tests/Avalonia.Animation.UnitTests/Avalonia.Animation.UnitTests.csproj
index dd50eff2b6..5b686dea4c 100644
--- a/tests/Avalonia.Animation.UnitTests/Avalonia.Animation.UnitTests.csproj
+++ b/tests/Avalonia.Animation.UnitTests/Avalonia.Animation.UnitTests.csproj
@@ -10,6 +10,7 @@
+
diff --git a/tests/Avalonia.Base.UnitTests/Avalonia.Base.UnitTests.csproj b/tests/Avalonia.Base.UnitTests/Avalonia.Base.UnitTests.csproj
index 0d87f0eb03..badfd09430 100644
--- a/tests/Avalonia.Base.UnitTests/Avalonia.Base.UnitTests.csproj
+++ b/tests/Avalonia.Base.UnitTests/Avalonia.Base.UnitTests.csproj
@@ -10,6 +10,7 @@
+
@@ -17,4 +18,4 @@
-
\ No newline at end of file
+
diff --git a/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Metadata.cs b/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Metadata.cs
index 161911dfd5..2edb3deff0 100644
--- a/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Metadata.cs
+++ b/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Metadata.cs
@@ -67,7 +67,7 @@ namespace Avalonia.Base.UnitTests
public static readonly DirectProperty DirectProperty =
AvaloniaProperty.RegisterDirect("Styled", o => o.Direct, unsetValue: "foo");
- private string _direct;
+ private string _direct = default;
public string Direct
{
@@ -92,7 +92,7 @@ namespace Avalonia.Base.UnitTests
public static readonly DirectProperty DirectProperty =
Class1.DirectProperty.AddOwner(o => o.Direct, unsetValue: "baz");
- private string _direct;
+ private string _direct = default;
static Class3()
{
diff --git a/tests/Avalonia.Base.UnitTests/Collections/AvaloniaListExtenionsTests.cs b/tests/Avalonia.Base.UnitTests/Collections/AvaloniaListExtenionsTests.cs
index 7f118a2c1d..b1b2d3d8f2 100644
--- a/tests/Avalonia.Base.UnitTests/Collections/AvaloniaListExtenionsTests.cs
+++ b/tests/Avalonia.Base.UnitTests/Collections/AvaloniaListExtenionsTests.cs
@@ -6,10 +6,12 @@ namespace Avalonia.Base.UnitTests.Collections
{
public class AvaloniaListExtenionsTests
{
+#pragma warning disable CS0618 // Type or member is obsolete
[Fact]
public void CreateDerivedList_Creates_Initial_Items()
{
var source = new AvaloniaList(new[] { 0, 1, 2, 3 });
+
var target = source.CreateDerivedList(x => new Wrapper(x));
var result = target.Select(x => x.Value).ToList();
@@ -137,6 +139,8 @@ namespace Avalonia.Base.UnitTests.Collections
Assert.Equal(source, result);
}
+#pragma warning restore CS0618 // Type or member is obsolete
+
private class Wrapper
{
diff --git a/tests/Avalonia.Base.UnitTests/Data/Core/BindingExpressionTests.cs b/tests/Avalonia.Base.UnitTests/Data/Core/BindingExpressionTests.cs
index 1e1f4bd4b2..339cf8a334 100644
--- a/tests/Avalonia.Base.UnitTests/Data/Core/BindingExpressionTests.cs
+++ b/tests/Avalonia.Base.UnitTests/Data/Core/BindingExpressionTests.cs
@@ -356,7 +356,7 @@ namespace Avalonia.Base.UnitTests.Data.Core
}
[Fact]
- public async Task Null_Value_Should_Use_TargetNullValue()
+ public void Null_Value_Should_Use_TargetNullValue()
{
var data = new Class1 { StringValue = "foo" };
diff --git a/tests/Avalonia.Base.UnitTests/Data/Core/ExpressionObserverTests_Property.cs b/tests/Avalonia.Base.UnitTests/Data/Core/ExpressionObserverTests_Property.cs
index 784046ac0b..32cdd21e04 100644
--- a/tests/Avalonia.Base.UnitTests/Data/Core/ExpressionObserverTests_Property.cs
+++ b/tests/Avalonia.Base.UnitTests/Data/Core/ExpressionObserverTests_Property.cs
@@ -600,6 +600,24 @@ namespace Avalonia.Base.UnitTests.Data.Core
result);
}
+ [Fact]
+ public void Should_Not_Throw_Exception_On_Duplicate_Properties()
+ {
+ // Repro of https://github.com/AvaloniaUI/Avalonia/issues/4733.
+ var source = new MyViewModel();
+ var target = new PropertyAccessorNode("Name", false);
+
+ target.Target = new WeakReference(source);
+
+ var result = new List();
+
+ target.Subscribe(x => result.Add(x));
+ }
+
+ public class MyViewModelBase { public object Name => "Name"; }
+
+ public class MyViewModel : MyViewModelBase { public new string Name => "NewName"; }
+
private interface INext
{
int PropertyChangedSubscriptionCount { get; }
diff --git a/tests/Avalonia.Base.UnitTests/Data/DefaultValueConverterTests.cs b/tests/Avalonia.Base.UnitTests/Data/DefaultValueConverterTests.cs
index efa81dcc1b..f522acf9ce 100644
--- a/tests/Avalonia.Base.UnitTests/Data/DefaultValueConverterTests.cs
+++ b/tests/Avalonia.Base.UnitTests/Data/DefaultValueConverterTests.cs
@@ -1,12 +1,11 @@
+using System;
+using System.ComponentModel;
using System.Globalization;
-using Avalonia.Controls;
-using Avalonia.Data;
-using Xunit;
using System.Windows.Input;
-using System;
+using Avalonia.Data;
using Avalonia.Data.Converters;
using Avalonia.Layout;
-using System.ComponentModel;
+using Xunit;
namespace Avalonia.Base.UnitTests.Data.Converters
{
@@ -251,6 +250,11 @@ namespace Avalonia.Base.UnitTests.Data.Converters
{
return obj is CustomType other && this.Value == other.Value;
}
+
+ public override int GetHashCode()
+ {
+ return 8399587^Value.GetHashCode();
+ }
}
private class CustomTypeConverter : TypeConverter
diff --git a/tests/Avalonia.Benchmarks/Layout/ControlsBenchmark.cs b/tests/Avalonia.Benchmarks/Layout/ControlsBenchmark.cs
index 7170f6d7d4..3493dd0f53 100644
--- a/tests/Avalonia.Benchmarks/Layout/ControlsBenchmark.cs
+++ b/tests/Avalonia.Benchmarks/Layout/ControlsBenchmark.cs
@@ -17,7 +17,8 @@ namespace Avalonia.Benchmarks.Layout
_app = UnitTestApplication.Start(
TestServices.StyledWindow.With(
renderInterface: new NullRenderingPlatform(),
- threadingInterface: new NullThreadingPlatform()));
+ threadingInterface: new NullThreadingPlatform(),
+ standardCursorFactory: new NullCursorFactory()));
_root = new TestRoot(true, null)
{
diff --git a/tests/Avalonia.Benchmarks/NullCursorFactory.cs b/tests/Avalonia.Benchmarks/NullCursorFactory.cs
new file mode 100644
index 0000000000..012adce0f2
--- /dev/null
+++ b/tests/Avalonia.Benchmarks/NullCursorFactory.cs
@@ -0,0 +1,14 @@
+using System;
+using Avalonia.Input;
+using Avalonia.Platform;
+
+namespace Avalonia.Benchmarks
+{
+ internal class NullCursorFactory : IStandardCursorFactory
+ {
+ public IPlatformHandle GetCursor(StandardCursorType cursorType)
+ {
+ return new PlatformHandle(IntPtr.Zero, "null");
+ }
+ }
+}
diff --git a/tests/Avalonia.Benchmarks/NullRenderer.cs b/tests/Avalonia.Benchmarks/NullRenderer.cs
index 9a756aaf0b..c1701b5d57 100644
--- a/tests/Avalonia.Benchmarks/NullRenderer.cs
+++ b/tests/Avalonia.Benchmarks/NullRenderer.cs
@@ -9,8 +9,9 @@ namespace Avalonia.Benchmarks
{
public bool DrawFps { get; set; }
public bool DrawDirtyRects { get; set; }
+#pragma warning disable CS0067
public event EventHandler SceneInvalidated;
-
+#pragma warning restore CS0067
public void AddDirty(IVisual visual)
{
}
diff --git a/tests/Avalonia.Benchmarks/NullRenderingPlatform.cs b/tests/Avalonia.Benchmarks/NullRenderingPlatform.cs
index f632d85c26..1570205456 100644
--- a/tests/Avalonia.Benchmarks/NullRenderingPlatform.cs
+++ b/tests/Avalonia.Benchmarks/NullRenderingPlatform.cs
@@ -28,7 +28,7 @@ namespace Avalonia.Benchmarks
public IGeometryImpl CreateRectangleGeometry(Rect rect)
{
- throw new NotImplementedException();
+ return new MockStreamGeometryImpl();
}
public IStreamGeometryImpl CreateStreamGeometry()
diff --git a/tests/Avalonia.Benchmarks/NullThreadingPlatform.cs b/tests/Avalonia.Benchmarks/NullThreadingPlatform.cs
index ba84b5afcc..bb469a6b33 100644
--- a/tests/Avalonia.Benchmarks/NullThreadingPlatform.cs
+++ b/tests/Avalonia.Benchmarks/NullThreadingPlatform.cs
@@ -23,6 +23,9 @@ namespace Avalonia.Benchmarks
public bool CurrentThreadIsLoopThread => true;
+#pragma warning disable CS0067
public event Action Signaled;
+#pragma warning restore CS0067
+
}
}
diff --git a/tests/Avalonia.Controls.DataGrid.UnitTests/Avalonia.Controls.DataGrid.UnitTests.csproj b/tests/Avalonia.Controls.DataGrid.UnitTests/Avalonia.Controls.DataGrid.UnitTests.csproj
index 396dfee691..c0c9303767 100644
--- a/tests/Avalonia.Controls.DataGrid.UnitTests/Avalonia.Controls.DataGrid.UnitTests.csproj
+++ b/tests/Avalonia.Controls.DataGrid.UnitTests/Avalonia.Controls.DataGrid.UnitTests.csproj
@@ -12,6 +12,7 @@
+
diff --git a/tests/Avalonia.Controls.UnitTests/Avalonia.Controls.UnitTests.csproj b/tests/Avalonia.Controls.UnitTests/Avalonia.Controls.UnitTests.csproj
index 19c4454d3d..6b17427eda 100644
--- a/tests/Avalonia.Controls.UnitTests/Avalonia.Controls.UnitTests.csproj
+++ b/tests/Avalonia.Controls.UnitTests/Avalonia.Controls.UnitTests.csproj
@@ -12,6 +12,7 @@
+
@@ -22,7 +23,6 @@
-
diff --git a/tests/Avalonia.Controls.UnitTests/BorderTests.cs b/tests/Avalonia.Controls.UnitTests/BorderTests.cs
index 6e2599c9fd..ab33eaaff9 100644
--- a/tests/Avalonia.Controls.UnitTests/BorderTests.cs
+++ b/tests/Avalonia.Controls.UnitTests/BorderTests.cs
@@ -54,7 +54,7 @@ namespace Avalonia.Controls.UnitTests
var root = new TestRoot(target);
var renderer = Mock.Get(root.Renderer);
- renderer.ResetCalls();
+ renderer.Invocations.Clear();
((SolidColorBrush)target.Background).Color = Colors.Green;
diff --git a/tests/Avalonia.Controls.UnitTests/CanvasTests.cs b/tests/Avalonia.Controls.UnitTests/CanvasTests.cs
index da1698330f..11a349f53e 100644
--- a/tests/Avalonia.Controls.UnitTests/CanvasTests.cs
+++ b/tests/Avalonia.Controls.UnitTests/CanvasTests.cs
@@ -1,5 +1,6 @@
using System;
using Avalonia.Controls.Shapes;
+using Avalonia.UnitTests;
using Xunit;
namespace Avalonia.Controls.UnitTests
@@ -9,6 +10,8 @@ namespace Avalonia.Controls.UnitTests
[Fact]
public void Left_Property_Should_Work()
{
+ using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
+
Rectangle rect;
var target = new Canvas
{
@@ -34,6 +37,8 @@ namespace Avalonia.Controls.UnitTests
[Fact]
public void Top_Property_Should_Work()
{
+ using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
+
Rectangle rect;
var target = new Canvas
{
@@ -59,6 +64,8 @@ namespace Avalonia.Controls.UnitTests
[Fact]
public void Right_Property_Should_Work()
{
+ using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
+
Rectangle rect;
var target = new Canvas
{
@@ -84,6 +91,8 @@ namespace Avalonia.Controls.UnitTests
[Fact]
public void Bottom_Property_Should_Work()
{
+ using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
+
Rectangle rect;
var target = new Canvas
{
diff --git a/tests/Avalonia.Controls.UnitTests/ComboBoxTests.cs b/tests/Avalonia.Controls.UnitTests/ComboBoxTests.cs
index 783215fb5d..c8a30a42e9 100644
--- a/tests/Avalonia.Controls.UnitTests/ComboBoxTests.cs
+++ b/tests/Avalonia.Controls.UnitTests/ComboBoxTests.cs
@@ -40,6 +40,7 @@ namespace Avalonia.Controls.UnitTests
Items = items,
SelectedIndex = 0,
};
+ var root = new TestRoot(target);
var rectangle = target.GetValue(ComboBox.SelectionBoxItemProperty) as Rectangle;
Assert.NotNull(rectangle);
diff --git a/tests/Avalonia.Controls.UnitTests/ContextMenuTests.cs b/tests/Avalonia.Controls.UnitTests/ContextMenuTests.cs
index c179aef9ac..39a3250686 100644
--- a/tests/Avalonia.Controls.UnitTests/ContextMenuTests.cs
+++ b/tests/Avalonia.Controls.UnitTests/ContextMenuTests.cs
@@ -79,7 +79,7 @@ namespace Avalonia.Controls.UnitTests
{
using (Application())
{
- popupImpl.Setup(x => x.Show()).Verifiable();
+ popupImpl.Setup(x => x.Show(true)).Verifiable();
popupImpl.Setup(x => x.Hide()).Verifiable();
var sut = new ContextMenu();
@@ -99,7 +99,7 @@ namespace Avalonia.Controls.UnitTests
_mouse.Click(target);
Assert.False(sut.IsOpen);
- popupImpl.Verify(x => x.Show(), Times.Once);
+ popupImpl.Verify(x => x.Show(true), Times.Once);
popupImpl.Verify(x => x.Hide(), Times.Once);
}
}
@@ -109,7 +109,7 @@ namespace Avalonia.Controls.UnitTests
{
using (Application())
{
- popupImpl.Setup(x => x.Show()).Verifiable();
+ popupImpl.Setup(x => x.Show(true)).Verifiable();
popupImpl.Setup(x => x.Hide()).Verifiable();
var sut = new ContextMenu();
@@ -130,7 +130,7 @@ namespace Avalonia.Controls.UnitTests
Assert.True(sut.IsOpen);
popupImpl.Verify(x => x.Hide(), Times.Once);
- popupImpl.Verify(x => x.Show(), Times.Exactly(2));
+ popupImpl.Verify(x => x.Show(true), Times.Exactly(2));
}
}
@@ -177,7 +177,7 @@ namespace Avalonia.Controls.UnitTests
{
using (Application())
{
- popupImpl.Setup(x => x.Show()).Verifiable();
+ popupImpl.Setup(x => x.Show(true)).Verifiable();
bool eventCalled = false;
var sut = new ContextMenu();
@@ -193,7 +193,7 @@ namespace Avalonia.Controls.UnitTests
Assert.True(eventCalled);
Assert.False(sut.IsOpen);
- popupImpl.Verify(x => x.Show(), Times.Never);
+ popupImpl.Verify(x => x.Show(true), Times.Never);
}
}
@@ -297,7 +297,7 @@ namespace Avalonia.Controls.UnitTests
{
using (Application())
{
- popupImpl.Setup(x => x.Show()).Verifiable();
+ popupImpl.Setup(x => x.Show(true)).Verifiable();
popupImpl.Setup(x => x.Hide()).Verifiable();
bool eventCalled = false;
@@ -321,7 +321,7 @@ namespace Avalonia.Controls.UnitTests
Assert.True(eventCalled);
Assert.True(sut.IsOpen);
- popupImpl.Verify(x => x.Show(), Times.Once());
+ popupImpl.Verify(x => x.Show(true), Times.Once());
popupImpl.Verify(x => x.Hide(), Times.Never);
}
}
diff --git a/tests/Avalonia.Controls.UnitTests/LayoutTransformControlTests.cs b/tests/Avalonia.Controls.UnitTests/LayoutTransformControlTests.cs
index 13c946b549..60139c2881 100644
--- a/tests/Avalonia.Controls.UnitTests/LayoutTransformControlTests.cs
+++ b/tests/Avalonia.Controls.UnitTests/LayoutTransformControlTests.cs
@@ -1,5 +1,6 @@
using Avalonia.Controls.Shapes;
using Avalonia.Media;
+using Avalonia.UnitTests;
using Xunit;
namespace Avalonia.Controls.UnitTests
@@ -171,6 +172,8 @@ namespace Avalonia.Controls.UnitTests
[Fact]
public void Should_Generate_RotateTransform_90_degrees()
{
+ using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
+
LayoutTransformControl lt = CreateWithChildAndMeasureAndTransform(
100,
25,
@@ -193,6 +196,8 @@ namespace Avalonia.Controls.UnitTests
[Fact]
public void Should_Generate_RotateTransform_minus_90_degrees()
{
+ using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
+
LayoutTransformControl lt = CreateWithChildAndMeasureAndTransform(
100,
25,
@@ -215,6 +220,8 @@ namespace Avalonia.Controls.UnitTests
[Fact]
public void Should_Generate_ScaleTransform_x2()
{
+ using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
+
LayoutTransformControl lt = CreateWithChildAndMeasureAndTransform(
100,
50,
@@ -236,6 +243,8 @@ namespace Avalonia.Controls.UnitTests
[Fact]
public void Should_Generate_SkewTransform_45_degrees()
{
+ using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
+
LayoutTransformControl lt = CreateWithChildAndMeasureAndTransform(
100,
100,
@@ -258,6 +267,8 @@ namespace Avalonia.Controls.UnitTests
[Fact]
public void Should_Generate_SkewTransform_minus_45_degrees()
{
+ using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
+
LayoutTransformControl lt = CreateWithChildAndMeasureAndTransform(
100,
100,
@@ -279,6 +290,8 @@ namespace Avalonia.Controls.UnitTests
private static void TransformMeasureSizeTest(Size size, Transform transform, Size expectedSize)
{
+ using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
+
LayoutTransformControl lt = CreateWithChildAndMeasureAndTransform(
size.Width,
size.Height,
@@ -292,6 +305,8 @@ namespace Avalonia.Controls.UnitTests
private static void TransformRootBoundsTest(Size size, Transform transform, Rect expectedBounds)
{
+ using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
+
LayoutTransformControl lt = CreateWithChildAndMeasureAndTransform(size.Width, size.Height, transform);
Rect outBounds = lt.TransformRoot.Bounds;
diff --git a/tests/Avalonia.Controls.UnitTests/ListBoxTests.cs b/tests/Avalonia.Controls.UnitTests/ListBoxTests.cs
index 2e2ccf7326..145fce4fed 100644
--- a/tests/Avalonia.Controls.UnitTests/ListBoxTests.cs
+++ b/tests/Avalonia.Controls.UnitTests/ListBoxTests.cs
@@ -407,6 +407,53 @@ namespace Avalonia.Controls.UnitTests
Assert.Equal(1, raised);
}
+ [Fact]
+ public void Adding_And_Selecting_Item_With_AutoScrollToSelectedItem_Should_NotHide_FirstItem()
+ {
+ using (UnitTestApplication.Start(TestServices.StyledWindow))
+ {
+ var items = new AvaloniaList();
+
+ var wnd = new Window() { Width = 100, Height = 100, IsVisible = true };
+
+ var target = new ListBox()
+ {
+ VerticalAlignment = Layout.VerticalAlignment.Top,
+ AutoScrollToSelectedItem = true,
+ Width = 50,
+ VirtualizationMode = ItemVirtualizationMode.Simple,
+ ItemTemplate = new FuncDataTemplate((c, _) => new Border() { Height = 10 }),
+ Items = items,
+ };
+ wnd.Content = target;
+
+ var lm = wnd.LayoutManager;
+
+ lm.ExecuteInitialLayoutPass();
+
+ var panel = target.Presenter.Panel;
+
+ items.Add("Item 1");
+ target.Selection.Select(0);
+ lm.ExecuteLayoutPass();
+
+ Assert.Equal(1, panel.Children.Count);
+
+ items.Add("Item 2");
+ target.Selection.Select(1);
+ lm.ExecuteLayoutPass();
+
+ Assert.Equal(2, panel.Children.Count);
+
+ //make sure we have enough space to show all items
+ Assert.True(panel.Bounds.Height >= panel.Children.Sum(c => c.Bounds.Height));
+
+ //make sure we show items and they completelly visible, not only partially
+ Assert.True(panel.Children[0].Bounds.Top >= 0 && panel.Children[0].Bounds.Bottom <= panel.Bounds.Height, "first item is not completelly visible!");
+ Assert.True(panel.Children[1].Bounds.Top >= 0 && panel.Children[1].Bounds.Bottom <= panel.Bounds.Height, "second item is not completelly visible!");
+ }
+ }
+
private FuncControlTemplate ListBoxTemplate()
{
return new FuncControlTemplate((parent, scope) =>
diff --git a/tests/Avalonia.Controls.UnitTests/PanelTests.cs b/tests/Avalonia.Controls.UnitTests/PanelTests.cs
index 79ee6d1236..f189638c7d 100644
--- a/tests/Avalonia.Controls.UnitTests/PanelTests.cs
+++ b/tests/Avalonia.Controls.UnitTests/PanelTests.cs
@@ -127,7 +127,7 @@ namespace Avalonia.Controls.UnitTests
var root = new TestRoot(target);
var renderer = Mock.Get(root.Renderer);
- renderer.ResetCalls();
+ renderer.Invocations.Clear();
((SolidColorBrush)target.Background).Color = Colors.Green;
diff --git a/tests/Avalonia.Controls.UnitTests/Platform/DefaultMenuInteractionHandlerTests.cs b/tests/Avalonia.Controls.UnitTests/Platform/DefaultMenuInteractionHandlerTests.cs
index 64f35049ce..1a11091b81 100644
--- a/tests/Avalonia.Controls.UnitTests/Platform/DefaultMenuInteractionHandlerTests.cs
+++ b/tests/Avalonia.Controls.UnitTests/Platform/DefaultMenuInteractionHandlerTests.cs
@@ -503,26 +503,26 @@ namespace Avalonia.Controls.UnitTests.Platform
target.PointerEnter(item, enter);
Assert.True(timer.ActionIsQueued);
Mock.Get(parentItem).VerifySet(x => x.SelectedItem = item);
- Mock.Get(parentItem).ResetCalls();
+ Mock.Get(parentItem).Invocations.Clear();
// SubMenu shown after a delay.
timer.Pulse();
Mock.Get(item).Verify(x => x.Open());
Mock.Get(item).SetupGet(x => x.IsSubMenuOpen).Returns(true);
- Mock.Get(item).ResetCalls();
+ Mock.Get(item).Invocations.Clear();
// Pointer briefly exits item, but submenu remains open.
target.PointerLeave(item, leave);
Mock.Get(item).Verify(x => x.Close(), Times.Never);
- Mock.Get(item).ResetCalls();
+ Mock.Get(item).Invocations.Clear();
// Pointer enters child item; is selected.
enter.Source = childItem;
target.PointerEnter(childItem, enter);
Mock.Get(item).VerifySet(x => x.SelectedItem = childItem);
Mock.Get(parentItem).VerifySet(x => x.SelectedItem = item);
- Mock.Get(item).ResetCalls();
- Mock.Get(parentItem).ResetCalls();
+ Mock.Get(item).Invocations.Clear();
+ Mock.Get(parentItem).Invocations.Clear();
}
[Fact]
diff --git a/tests/Avalonia.Controls.UnitTests/Presenters/ContentPresenterTests_Standalone.cs b/tests/Avalonia.Controls.UnitTests/Presenters/ContentPresenterTests_Standalone.cs
index c0440ebc7b..c7aa583b6f 100644
--- a/tests/Avalonia.Controls.UnitTests/Presenters/ContentPresenterTests_Standalone.cs
+++ b/tests/Avalonia.Controls.UnitTests/Presenters/ContentPresenterTests_Standalone.cs
@@ -212,7 +212,7 @@ namespace Avalonia.Controls.UnitTests.Presenters
var root = new TestRoot(target);
var renderer = Mock.Get(root.Renderer);
- renderer.ResetCalls();
+ renderer.Invocations.Clear();
((SolidColorBrush)target.Background).Color = Colors.Green;
diff --git a/tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs b/tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs
index f032186bcd..9223b08c81 100644
--- a/tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs
+++ b/tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs
@@ -485,6 +485,85 @@ namespace Avalonia.Controls.UnitTests.Primitives
}
}
+ [Fact]
+ public void Closing_Popup_Sets_Focus_On_PlacementTarget()
+ {
+ using (CreateServicesWithFocus())
+ {
+ var window = PreparedWindow();
+
+ var tb = new TextBox();
+ var p = new Popup
+ {
+ PlacementTarget = window,
+ Child = tb
+ };
+ ((ISetLogicalParent)p).SetParent(p.PlacementTarget);
+ window.Show();
+
+ p.Open();
+
+ if (p.Host is OverlayPopupHost host)
+ {
+ //Need to measure/arrange for visual children to show up
+ //in OverlayPopupHost
+ host.Measure(Size.Infinity);
+ host.Arrange(new Rect(host.DesiredSize));
+ }
+
+ tb.Focus();
+
+ p.Close();
+
+ var focus = FocusManager.Instance?.Current;
+ Assert.True(focus == window);
+ }
+ }
+
+ [Fact]
+ public void Prog_Close_Popup_NoLightDismiss_Doesnt_Move_Focus_To_PlacementTarget()
+ {
+ using (CreateServicesWithFocus())
+ {
+ var window = PreparedWindow();
+
+ var windowTB = new TextBox();
+ window.Content = windowTB;
+
+ var popupTB = new TextBox();
+ var p = new Popup
+ {
+ PlacementTarget = window,
+ IsLightDismissEnabled = false,
+ Child = popupTB
+ };
+ ((ISetLogicalParent)p).SetParent(p.PlacementTarget);
+ window.Show();
+
+ p.Open();
+
+ if (p.Host is OverlayPopupHost host)
+ {
+ //Need to measure/arrange for visual children to show up
+ //in OverlayPopupHost
+ host.Measure(Size.Infinity);
+ host.Arrange(new Rect(host.DesiredSize));
+ }
+
+ popupTB.Focus();
+
+ windowTB.Focus();
+
+ var focus = FocusManager.Instance?.Current;
+
+ Assert.True(focus == windowTB);
+
+ p.Close();
+
+ Assert.True(focus == windowTB);
+ }
+ }
+
private IDisposable CreateServices()
{
return UnitTestApplication.Start(TestServices.StyledWindow.With(windowingPlatform:
diff --git a/tests/Avalonia.Controls.UnitTests/RelativePanelTests.cs b/tests/Avalonia.Controls.UnitTests/RelativePanelTests.cs
index 6e171a58e7..6b2f05c923 100644
--- a/tests/Avalonia.Controls.UnitTests/RelativePanelTests.cs
+++ b/tests/Avalonia.Controls.UnitTests/RelativePanelTests.cs
@@ -1,4 +1,5 @@
using Avalonia.Controls.Shapes;
+using Avalonia.UnitTests;
using Xunit;
namespace Avalonia.Controls.UnitTests
@@ -8,6 +9,7 @@ namespace Avalonia.Controls.UnitTests
[Fact]
public void Lays_Out_1_Child_Next_the_other()
{
+ using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
var rect1 = new Rectangle { Height = 20, Width = 20 };
var rect2 = new Rectangle { Height = 20, Width = 20 };
@@ -34,6 +36,7 @@ namespace Avalonia.Controls.UnitTests
[Fact]
public void Lays_Out_1_Child_Below_the_other()
{
+ using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
var rect1 = new Rectangle { Height = 20, Width = 20 };
var rect2 = new Rectangle { Height = 20, Width = 20 };
@@ -60,6 +63,7 @@ namespace Avalonia.Controls.UnitTests
[Fact]
public void RelativePanel_Can_Center()
{
+ using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
var rect1 = new Rectangle { Height = 20, Width = 20 };
var rect2 = new Rectangle { Height = 20, Width = 20 };
@@ -86,6 +90,7 @@ namespace Avalonia.Controls.UnitTests
[Fact]
public void LeftOf_Measures_Correctly()
{
+ using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
var rect1 = new Rectangle { Height = 20, Width = 20 };
var rect2 = new Rectangle { Height = 20, Width = 20 };
@@ -111,6 +116,7 @@ namespace Avalonia.Controls.UnitTests
[Fact]
public void Above_Measures_Correctly()
{
+ using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
var rect1 = new Rectangle { Height = 20, Width = 20 };
var rect2 = new Rectangle { Height = 20, Width = 20 };
diff --git a/tests/Avalonia.Controls.UnitTests/Selection/InternalSelectionModelTests.cs b/tests/Avalonia.Controls.UnitTests/Selection/InternalSelectionModelTests.cs
index b64812e290..ce3e698cf3 100644
--- a/tests/Avalonia.Controls.UnitTests/Selection/InternalSelectionModelTests.cs
+++ b/tests/Avalonia.Controls.UnitTests/Selection/InternalSelectionModelTests.cs
@@ -205,6 +205,49 @@ namespace Avalonia.Controls.UnitTests.Selection
Assert.Equal(2, target.SelectedIndex);
}
+ [Fact]
+ public void Raises_Selection_Changed_On_Items_Reset()
+ {
+ var items = new ResettingCollection(new[] { "foo", "bar", "baz" });
+ var target = CreateTarget(source: items);
+
+ target.SelectedIndex = 1;
+
+ var changed = new List();
+
+ target.PropertyChanged += (s, e) => changed.Add(e.PropertyName);
+
+ var oldSelectedIndex = target.SelectedIndex;
+ var oldSelectedItem = target.SelectedItem;
+
+ items.Reset(new string[0]);
+
+ Assert.NotEqual(oldSelectedIndex, target.SelectedIndex);
+ Assert.NotEqual(oldSelectedItem, target.SelectedItem);
+
+ Assert.Equal(-1, target.SelectedIndex);
+ Assert.Equal(null, target.SelectedItem);
+
+ Assert.Contains(nameof(target.SelectedIndex), changed);
+ Assert.Contains(nameof(target.SelectedItem), changed);
+ }
+
+ [Fact]
+ public void Preserves_SelectedItem_On_Items_Reset()
+ {
+ var items = new ResettingCollection(new[] { "foo", "bar", "baz" });
+ var target = CreateTarget(source: items);
+
+ target.SelectedItem = "foo";
+
+ Assert.Equal(0, target.SelectedIndex);
+
+ items.Reset(new string[] { "baz", "foo", "bar" });
+
+ Assert.Equal("foo", target.SelectedItem);
+ Assert.Equal(1, target.SelectedIndex);
+ }
+
[Fact]
public void Preserves_Selection_On_Source_Changed()
{
@@ -222,7 +265,7 @@ namespace Avalonia.Controls.UnitTests.Selection
bool nullSource = false)
{
source ??= !nullSource ? new[] { "foo", "bar", "baz" } : null;
-
+
var result = new InternalSelectionModel
{
SingleSelect = singleSelect,
diff --git a/tests/Avalonia.Controls.UnitTests/Selection/SelectionModelTests_Multiple.cs b/tests/Avalonia.Controls.UnitTests/Selection/SelectionModelTests_Multiple.cs
index 5d0c6d31e1..68bdbe51e8 100644
--- a/tests/Avalonia.Controls.UnitTests/Selection/SelectionModelTests_Multiple.cs
+++ b/tests/Avalonia.Controls.UnitTests/Selection/SelectionModelTests_Multiple.cs
@@ -1216,6 +1216,7 @@ namespace Avalonia.Controls.UnitTests.Selection
var data = (AvaloniaList)target.Source!;
var selectionChangedRaised = 0;
var selectedIndexRaised = 0;
+ var selectedItemRaised = 0;
var indexesChangedRaised = 0;
target.Source = data;
@@ -1227,6 +1228,11 @@ namespace Avalonia.Controls.UnitTests.Selection
{
++selectedIndexRaised;
}
+
+ if (e.PropertyName == nameof(target.SelectedItem))
+ {
+ ++selectedItemRaised;
+ }
};
target.IndexesChanged += (s, e) => ++indexesChangedRaised;
@@ -1249,6 +1255,7 @@ namespace Avalonia.Controls.UnitTests.Selection
Assert.Equal(2, target.AnchorIndex);
Assert.Equal(1, selectionChangedRaised);
Assert.Equal(1, selectedIndexRaised);
+ Assert.Equal(1, selectedItemRaised);
Assert.Equal(0, indexesChangedRaised);
}
diff --git a/tests/Avalonia.Controls.UnitTests/Selection/SelectionModelTests_Single.cs b/tests/Avalonia.Controls.UnitTests/Selection/SelectionModelTests_Single.cs
index 66a2cef921..668af3b5d7 100644
--- a/tests/Avalonia.Controls.UnitTests/Selection/SelectionModelTests_Single.cs
+++ b/tests/Avalonia.Controls.UnitTests/Selection/SelectionModelTests_Single.cs
@@ -1040,6 +1040,7 @@ namespace Avalonia.Controls.UnitTests.Selection
var data = (AvaloniaList)target.Source!;
var selectionChangedRaised = 0;
var selectedIndexRaised = 0;
+ var selectedItemRaised = 0;
target.Source = data;
target.Select(1);
@@ -1050,6 +1051,11 @@ namespace Avalonia.Controls.UnitTests.Selection
{
++selectedIndexRaised;
}
+
+ if (e.PropertyName == nameof(target.SelectedItem))
+ {
+ ++selectedItemRaised;
+ }
};
target.SelectionChanged += (s, e) =>
@@ -1070,6 +1076,7 @@ namespace Avalonia.Controls.UnitTests.Selection
Assert.Equal(-1, target.AnchorIndex);
Assert.Equal(1, selectionChangedRaised);
Assert.Equal(1, selectedIndexRaised);
+ Assert.Equal(1, selectedItemRaised);
}
[Fact]
diff --git a/tests/Avalonia.Controls.UnitTests/Shapes/EllipseTests.cs b/tests/Avalonia.Controls.UnitTests/Shapes/EllipseTests.cs
new file mode 100644
index 0000000000..626945894f
--- /dev/null
+++ b/tests/Avalonia.Controls.UnitTests/Shapes/EllipseTests.cs
@@ -0,0 +1,57 @@
+using Avalonia.Controls.Shapes;
+using Avalonia.Media;
+using Avalonia.UnitTests;
+using Xunit;
+
+namespace Avalonia.Controls.UnitTests.Shapes
+{
+ public class EllipseTests
+ {
+ [Fact]
+ public void Measure_Does_Not_Set_RenderedGeometry_Rect()
+ {
+ using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
+
+ var target = new Ellipse();
+
+ target.Measure(new Size(100, 100));
+
+ var geometry = Assert.IsType(target.RenderedGeometry);
+ Assert.Equal(default, geometry.Rect);
+ }
+
+ [Fact]
+ public void Arrange_Sets_RenderedGeometry_Properties()
+ {
+ using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
+
+ var target = new Ellipse();
+
+ target.Measure(new Size(100, 100));
+ target.Arrange(new Rect(0, 0, 100, 100));
+
+ var geometry = Assert.IsType(target.RenderedGeometry);
+ Assert.Equal(new Rect(0, 0, 100, 100), geometry.Rect);
+ }
+
+ [Fact]
+ public void Rearranging_Updates_RenderedGeometry_Rect()
+ {
+ using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
+
+ var target = new Ellipse();
+
+ target.Measure(new Size(100, 100));
+ target.Arrange(new Rect(0, 0, 100, 100));
+
+ var geometry = Assert.IsType(target.RenderedGeometry);
+ Assert.Equal(new Rect(0, 0, 100, 100), geometry.Rect);
+
+ target.Measure(new Size(200, 200));
+ target.Arrange(new Rect(0, 0, 200, 200));
+
+ geometry = Assert.IsType(target.RenderedGeometry);
+ Assert.Equal(new Rect(0, 0, 200, 200), geometry.Rect);
+ }
+ }
+}
diff --git a/tests/Avalonia.Controls.UnitTests/Shapes/PathTests.cs b/tests/Avalonia.Controls.UnitTests/Shapes/PathTests.cs
index 88c64e76cc..8b8656a76b 100644
--- a/tests/Avalonia.Controls.UnitTests/Shapes/PathTests.cs
+++ b/tests/Avalonia.Controls.UnitTests/Shapes/PathTests.cs
@@ -34,5 +34,149 @@ namespace Avalonia.Controls.UnitTests.Shapes
root.Child = null;
}
+
+ [Theory]
+ [InlineData(Stretch.None, 100, 200)]
+ [InlineData(Stretch.Fill, 500, 500)]
+ [InlineData(Stretch.Uniform, 250, 500)]
+ [InlineData(Stretch.UniformToFill, 500, 500)]
+ public void Calculates_Correct_DesiredSize_For_Finite_Bounds(Stretch stretch, double expectedWidth, double expectedHeight)
+ {
+ using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
+
+ var target = new Path()
+ {
+ Data = new RectangleGeometry { Rect = new Rect(0, 0, 100, 200) },
+ Stretch = stretch,
+ };
+
+ target.Measure(new Size(500, 500));
+
+ Assert.Equal(new Size(expectedWidth, expectedHeight), target.DesiredSize);
+ }
+
+ [Theory]
+ [InlineData(Stretch.None)]
+ [InlineData(Stretch.Fill)]
+ [InlineData(Stretch.Uniform)]
+ [InlineData(Stretch.UniformToFill)]
+ public void Calculates_Correct_DesiredSize_For_Infinite_Bounds(Stretch stretch)
+ {
+ using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
+
+ var target = new Path()
+ {
+ Data = new RectangleGeometry { Rect = new Rect(0, 0, 100, 200) },
+ Stretch = stretch,
+ };
+
+ target.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
+
+ Assert.Equal(new Size(100, 200), target.DesiredSize);
+ }
+
+ [Fact]
+ public void Measure_Does_Not_Update_RenderedGeometry_Transform()
+ {
+ using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
+
+ var target = new Path
+ {
+ Data = new RectangleGeometry { Rect = new Rect(0, 0, 100, 200) },
+ Stretch = Stretch.Fill,
+ };
+
+ target.Measure(new Size(500, 500));
+
+ Assert.Null(target.RenderedGeometry.Transform);
+ }
+
+ [Theory]
+ [InlineData(Stretch.None, 1, 1)]
+ [InlineData(Stretch.Fill, 5, 2.5)]
+ [InlineData(Stretch.Uniform, 2.5, 2.5)]
+ [InlineData(Stretch.UniformToFill, 5, 5)]
+ public void Arrange_Updates_RenderedGeometry_Transform(Stretch stretch, double expectedScaleX, double expectedScaleY)
+ {
+ using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
+
+ var target = new Path
+ {
+ Data = new RectangleGeometry { Rect = new Rect(0, 0, 100, 200) },
+ Stretch = stretch,
+ };
+
+ target.Measure(new Size(500, 500));
+ target.Arrange(new Rect(0, 0, 500, 500));
+
+ if (expectedScaleX == 1 && expectedScaleY == 1)
+ {
+ Assert.Null(target.RenderedGeometry.Transform);
+ }
+ else
+ {
+ Assert.Equal(Matrix.CreateScale(expectedScaleX, expectedScaleY), target.RenderedGeometry.Transform.Value);
+ }
+ }
+
+ [Fact]
+ public void Arrange_Reserves_All_Of_Arrange_Rect()
+ {
+ using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
+
+ RectangleGeometry geometry;
+ var target = new Path
+ {
+ Data = geometry = new RectangleGeometry { Rect = new Rect(0, 0, 100, 200) },
+ Stretch = Stretch.Uniform,
+ };
+
+ target.Measure(new Size(400, 400));
+ target.Arrange(new Rect(0, 0, 400, 400));
+
+ Assert.Equal(new Rect(0, 0, 100, 200), geometry.Rect);
+ Assert.Equal(Matrix.CreateScale(2, 2), target.RenderedGeometry.Transform.Value);
+ Assert.Equal(new Rect(0, 0, 400, 400), target.Bounds);
+ }
+
+ [Fact]
+ public void Measure_Without_Arrange_Does_Not_Clear_RenderedGeometry_Transform()
+ {
+ using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
+
+ var target = new Path
+ {
+ Data = new RectangleGeometry { Rect = new Rect(0, 0, 100, 100) },
+ Stretch = Stretch.Fill,
+ };
+
+ target.Measure(new Size(200, 200));
+ target.Arrange(new Rect(0, 0, 200, 200));
+
+ Assert.Equal(Matrix.CreateScale(2, 2), target.RenderedGeometry.Transform.Value);
+
+ target.Measure(new Size(300, 300));
+
+ Assert.Equal(Matrix.CreateScale(2, 2), target.RenderedGeometry.Transform.Value);
+ }
+
+ [Fact]
+ public void Arrange_Without_Measure_Updates_RenderedGeometry_Transform()
+ {
+ using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
+
+ var target = new Path
+ {
+ Data = new RectangleGeometry { Rect = new Rect(0, 0, 100, 100) },
+ Stretch = Stretch.Fill,
+ };
+
+ target.Measure(new Size(200, 200));
+ target.Arrange(new Rect(0, 0, 200, 200));
+ Assert.Equal(Matrix.CreateScale(2, 2), target.RenderedGeometry.Transform.Value);
+
+ target.Arrange(new Rect(0, 0, 300, 300));
+ Assert.Equal(Matrix.CreateScale(3, 3), target.RenderedGeometry.Transform.Value);
+ }
}
}
diff --git a/tests/Avalonia.Controls.UnitTests/Shapes/RectangleTests.cs b/tests/Avalonia.Controls.UnitTests/Shapes/RectangleTests.cs
index 0ec73edec0..8d8ce10d4c 100644
--- a/tests/Avalonia.Controls.UnitTests/Shapes/RectangleTests.cs
+++ b/tests/Avalonia.Controls.UnitTests/Shapes/RectangleTests.cs
@@ -1,7 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-using Avalonia.Controls.Shapes;
+using Avalonia.Controls.Shapes;
using Avalonia.Media;
using Avalonia.UnitTests;
using Moq;
@@ -11,6 +8,53 @@ namespace Avalonia.Controls.UnitTests.Shapes
{
public class RectangleTests
{
+ [Fact]
+ public void Measure_Does_Not_Set_RenderedGeometry_Rect()
+ {
+ using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
+
+ var target = new Rectangle();
+
+ target.Measure(new Size(100, 100));
+
+ var geometry = Assert.IsType(target.RenderedGeometry);
+ Assert.Equal(Rect.Empty, geometry.Rect);
+ }
+
+ [Fact]
+ public void Arrange_Sets_RenderedGeometry_Rect()
+ {
+ using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
+
+ var target = new Rectangle();
+
+ target.Measure(new Size(100, 100));
+ target.Arrange(new Rect(0, 0, 100, 100));
+
+ var geometry = Assert.IsType(target.RenderedGeometry);
+ Assert.Equal(new Rect(0, 0, 100, 100), geometry.Rect);
+ }
+
+ [Fact]
+ public void Rearranging_Updates_RenderedGeometry_Rect()
+ {
+ using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
+
+ var target = new Rectangle();
+
+ target.Measure(new Size(100, 100));
+ target.Arrange(new Rect(0, 0, 100, 100));
+
+ var geometry = Assert.IsType(target.RenderedGeometry);
+ Assert.Equal(new Rect(0, 0, 100, 100), geometry.Rect);
+
+ target.Measure(new Size(200, 200));
+ target.Arrange(new Rect(0, 0, 200, 200));
+
+ geometry = Assert.IsType(target.RenderedGeometry);
+ Assert.Equal(new Rect(0, 0, 200, 200), geometry.Rect);
+ }
+
[Fact]
public void Changing_Fill_Brush_Color_Should_Invalidate_Visual()
{
@@ -21,7 +65,7 @@ namespace Avalonia.Controls.UnitTests.Shapes
var root = new TestRoot(target);
var renderer = Mock.Get(root.Renderer);
- renderer.ResetCalls();
+ renderer.Invocations.Clear();
((SolidColorBrush)target.Fill).Color = Colors.Green;
@@ -38,7 +82,7 @@ namespace Avalonia.Controls.UnitTests.Shapes
var root = new TestRoot(target);
var renderer = Mock.Get(root.Renderer);
- renderer.ResetCalls();
+ renderer.Invocations.Clear();
((SolidColorBrush)target.Stroke).Color = Colors.Green;
diff --git a/tests/Avalonia.Controls.UnitTests/TextBlockTests.cs b/tests/Avalonia.Controls.UnitTests/TextBlockTests.cs
index 2d2c197220..b180a536a5 100644
--- a/tests/Avalonia.Controls.UnitTests/TextBlockTests.cs
+++ b/tests/Avalonia.Controls.UnitTests/TextBlockTests.cs
@@ -37,7 +37,7 @@ namespace Avalonia.Controls.UnitTests
var root = new TestRoot(target);
var renderer = Mock.Get(root.Renderer);
- renderer.ResetCalls();
+ renderer.Invocations.Clear();
((SolidColorBrush)target.Background).Color = Colors.Green;
@@ -54,7 +54,7 @@ namespace Avalonia.Controls.UnitTests
var root = new TestRoot(target);
var renderer = Mock.Get(root.Renderer);
- renderer.ResetCalls();
+ renderer.Invocations.Clear();
((SolidColorBrush)target.Foreground).Color = Colors.Green;
diff --git a/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs b/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs
index 7022fbf4c1..cea77bb7c9 100644
--- a/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs
+++ b/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs
@@ -1,7 +1,10 @@
using System;
using System.Collections;
using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
using System.Linq;
+using System.Runtime.CompilerServices;
using Avalonia.Collections;
using Avalonia.Controls.Presenters;
using Avalonia.Controls.Templates;
@@ -13,6 +16,7 @@ using Avalonia.Interactivity;
using Avalonia.LogicalTree;
using Avalonia.Styling;
using Avalonia.UnitTests;
+using JetBrains.Annotations;
using Xunit;
namespace Avalonia.Controls.UnitTests
@@ -454,6 +458,45 @@ namespace Avalonia.Controls.UnitTests
}
}
+ [Fact]
+ public void Bound_SelectedItem_Should_Not_Be_Cleared_when_Changing_Selection()
+ {
+ using (Application())
+ {
+ var dataContext = new TestDataContext();
+
+ var target = new TreeView
+ {
+ Template = CreateTreeViewTemplate(),
+ DataContext = dataContext
+ };
+
+ target.Bind(TreeView.ItemsProperty, new Binding("Items"));
+ target.Bind(TreeView.SelectedItemProperty, new Binding("SelectedItem"));
+
+ var visualRoot = new TestRoot();
+ visualRoot.Child = target;
+
+ CreateNodeDataTemplate(target);
+ ApplyTemplates(target);
+
+ var selectedValues = new List();
+
+ dataContext.PropertyChanged += (_, e) =>
+ {
+ if (e.PropertyName == nameof(TestDataContext.SelectedItem))
+ selectedValues.Add(dataContext.SelectedItem);
+ };
+ selectedValues.Add(dataContext.SelectedItem);
+
+ _mouse.Click((Interactive)target.Presenter.Panel.Children[0], MouseButton.Left);
+ _mouse.Click((Interactive)target.Presenter.Panel.Children[2], MouseButton.Left);
+
+ Assert.Equal(3, selectedValues.Count);
+ Assert.Equal(new[] { null, "Item 0", "Item 2" }, selectedValues.ToArray());
+ }
+ }
+
[Fact]
public void LogicalChildren_Should_Be_Set()
{
@@ -632,6 +675,50 @@ namespace Avalonia.Controls.UnitTests
Assert.Same(node, focus.Current);
}
}
+
+ [Fact]
+ public void Keyboard_Navigation_Should_Not_Crash_If_Selected_Item_Is_not_In_Tree()
+ {
+ using (Application())
+ {
+ var focus = FocusManager.Instance;
+ var navigation = AvaloniaLocator.Current.GetService();
+ var data = CreateTestTreeData();
+
+ var selectedNode = new Node { Value = "Out of Tree Selected Item" };
+
+ var target = new TreeView
+ {
+ Template = CreateTreeViewTemplate(),
+ Items = data,
+ SelectedItem = selectedNode
+ };
+
+ var button = new Button();
+
+ var root = new TestRoot
+ {
+ Child = new StackPanel
+ {
+ Children = { target, button },
+ }
+ };
+
+ CreateNodeDataTemplate(target);
+ ApplyTemplates(target);
+ ExpandAll(target);
+
+ var item = data[0].Children[0];
+ var node = target.ItemContainerGenerator.Index.ContainerFromItem(item);
+ Assert.NotNull(node);
+
+ target.SelectedItem = selectedNode;
+ node.Focus();
+ Assert.Same(node, focus.Current);
+
+ var next = KeyboardNavigationHandler.GetNext(node, NavigationDirection.Previous);
+ }
+ }
[Fact]
public void Pressing_SelectAll_Gesture_Should_Select_All_Nodes()
@@ -1288,5 +1375,30 @@ namespace Avalonia.Controls.UnitTests
private class DerivedTreeView : TreeView
{
}
+
+ private class TestDataContext : INotifyPropertyChanged
+ {
+ private string _selectedItem;
+
+ public TestDataContext()
+ {
+ Items = new ObservableCollection(Enumerable.Range(0, 5).Select(i => $"Item {i}"));
+ }
+
+ public ObservableCollection Items { get; }
+
+ public string SelectedItem
+ {
+ get { return _selectedItem; }
+ set
+ {
+ _selectedItem = value;
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SelectedItem)));
+ }
+ }
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ }
}
}
diff --git a/tests/Avalonia.Controls.UnitTests/Utils/HotKeyManagerTests.cs b/tests/Avalonia.Controls.UnitTests/Utils/HotKeyManagerTests.cs
index 9f2712c93c..151c3070f4 100644
--- a/tests/Avalonia.Controls.UnitTests/Utils/HotKeyManagerTests.cs
+++ b/tests/Avalonia.Controls.UnitTests/Utils/HotKeyManagerTests.cs
@@ -5,6 +5,9 @@ using Avalonia.Input;
using Avalonia.Platform;
using Avalonia.Styling;
using Xunit;
+using System;
+using Avalonia.Input.Raw;
+using Factory = System.Func, Avalonia.Controls.Window, Avalonia.AvaloniaObject>;
namespace Avalonia.Controls.UnitTests.Utils
{
@@ -54,6 +57,127 @@ namespace Avalonia.Controls.UnitTests.Utils
}
}
+ [Theory]
+ [MemberData(nameof(ElementsFactory))]
+ public void HotKeyManager_Should_Use_CommandParameter(string factoryName, Factory factory)
+ {
+ using (AvaloniaLocator.EnterScope())
+ {
+ var styler = new Mock();
+ var target = new KeyboardDevice();
+ var commandResult = 0;
+ var expectedParameter = 1;
+ AvaloniaLocator.CurrentMutable
+ .Bind().ToConstant(new WindowingPlatformMock())
+ .Bind().ToConstant(styler.Object);
+
+ var gesture = new KeyGesture(Key.A, KeyModifiers.Control);
+
+ var action = new Action(parameter =>
+ {
+ if (parameter is int value)
+ {
+ commandResult = value;
+ }
+ });
+
+ var root = new Window();
+ var element = factory(expectedParameter, action, root);
+
+ root.Template = CreateWindowTemplate();
+ root.ApplyTemplate();
+ root.Presenter.ApplyTemplate();
+
+ HotKeyManager.SetHotKey(element, gesture);
+
+ target.ProcessRawEvent(new RawKeyEventArgs(target,
+ 0,
+ root,
+ RawKeyEventType.KeyDown,
+ Key.A,
+ RawInputModifiers.Control));
+
+ Assert.True(expectedParameter == commandResult, $"{factoryName} HotKey did not carry the CommandParameter.");
+ }
+ }
+
+
+ [Theory]
+ [MemberData(nameof(ElementsFactory))]
+ public void HotKeyManager_Should_Do_Not_Executed_When_IsEnabled_False(string factoryName, Factory factory)
+ {
+ using (AvaloniaLocator.EnterScope())
+ {
+ var styler = new Mock();
+ var target = new KeyboardDevice();
+ var isExecuted = false;
+ AvaloniaLocator.CurrentMutable
+ .Bind().ToConstant(new WindowingPlatformMock())
+ .Bind().ToConstant(styler.Object);
+
+ var gesture = new KeyGesture(Key.A, KeyModifiers.Control);
+
+ var action = new Action(parameter =>
+ {
+ isExecuted = true;
+ });
+
+ var root = new Window();
+ var element = factory(0, action, root) as InputElement;
+
+ element.IsEnabled = false;
+
+ root.Template = CreateWindowTemplate();
+ root.ApplyTemplate();
+ root.Presenter.ApplyTemplate();
+
+ HotKeyManager.SetHotKey(element, gesture);
+
+ target.ProcessRawEvent(new RawKeyEventArgs(target,
+ 0,
+ root,
+ RawKeyEventType.KeyDown,
+ Key.A,
+ RawInputModifiers.Control));
+
+ Assert.True(isExecuted == false, $"{factoryName} Execution raised when IsEnabled is false.");
+ }
+ }
+
+ public static TheoryData ElementsFactory =>
+ new TheoryData()
+ {
+ {nameof(Button), MakeButton},
+ {nameof(MenuItem),MakeMenu},
+ };
+
+ private static AvaloniaObject MakeMenu(int expectedParameter, Action action, Window root)
+ {
+ var menuitem = new MenuItem()
+ {
+ Command = new Command(action),
+ CommandParameter = expectedParameter,
+ };
+ var rootMenu = new Menu();
+
+ rootMenu.Items = new[] { menuitem };
+
+ root.Content = rootMenu;
+ return menuitem;
+ }
+
+ private static AvaloniaObject MakeButton(int expectedParameter, Action action, Window root)
+ {
+ var button = new Button()
+ {
+ Command = new Command(action),
+ CommandParameter = expectedParameter,
+ };
+
+ root.Content = button;
+ return button;
+ }
+
private FuncControlTemplate CreateWindowTemplate()
{
return new FuncControlTemplate((parent, scope) =>
@@ -65,5 +189,22 @@ namespace Avalonia.Controls.UnitTests.Utils
}.RegisterInNameScope(scope);
});
}
+
+ class Command : System.Windows.Input.ICommand
+ {
+ private readonly Action _execeute;
+
+#pragma warning disable 67 // Event not used
+ public event EventHandler CanExecuteChanged;
+#pragma warning restore 67 // Event not used
+
+ public Command(Action execeute)
+ {
+ _execeute = execeute;
+ }
+ public bool CanExecute(object parameter) => true;
+
+ public void Execute(object parameter) => _execeute?.Invoke(parameter);
+ }
}
}
diff --git a/tests/Avalonia.Controls.UnitTests/ViewboxTests.cs b/tests/Avalonia.Controls.UnitTests/ViewboxTests.cs
index ad0f318d2f..e005bafbf9 100644
--- a/tests/Avalonia.Controls.UnitTests/ViewboxTests.cs
+++ b/tests/Avalonia.Controls.UnitTests/ViewboxTests.cs
@@ -1,5 +1,6 @@
using Avalonia.Controls.Shapes;
using Avalonia.Media;
+using Avalonia.UnitTests;
using Xunit;
namespace Avalonia.Controls.UnitTests
@@ -9,6 +10,8 @@ namespace Avalonia.Controls.UnitTests
[Fact]
public void Viewbox_Stretch_Uniform_Child()
{
+ using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
+
var target = new Viewbox() { Child = new Rectangle() { Width = 100, Height = 50 } };
target.Measure(new Size(200, 200));
@@ -25,6 +28,8 @@ namespace Avalonia.Controls.UnitTests
[Fact]
public void Viewbox_Stretch_None_Child()
{
+ using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
+
var target = new Viewbox() { Stretch = Stretch.None, Child = new Rectangle() { Width = 100, Height = 50 } };
target.Measure(new Size(200, 200));
@@ -41,6 +46,8 @@ namespace Avalonia.Controls.UnitTests
[Fact]
public void Viewbox_Stretch_Fill_Child()
{
+ using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
+
var target = new Viewbox() { Stretch = Stretch.Fill, Child = new Rectangle() { Width = 100, Height = 50 } };
target.Measure(new Size(200, 200));
@@ -57,6 +64,8 @@ namespace Avalonia.Controls.UnitTests
[Fact]
public void Viewbox_Stretch_UniformToFill_Child()
{
+ using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
+
var target = new Viewbox() { Stretch = Stretch.UniformToFill, Child = new Rectangle() { Width = 100, Height = 50 } };
target.Measure(new Size(200, 200));
@@ -73,6 +82,8 @@ namespace Avalonia.Controls.UnitTests
[Fact]
public void Viewbox_Stretch_Uniform_Child_With_Unrestricted_Width()
{
+ using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
+
var target = new Viewbox() { Child = new Rectangle() { Width = 100, Height = 50 } };
target.Measure(new Size(double.PositiveInfinity, 200));
@@ -89,6 +100,8 @@ namespace Avalonia.Controls.UnitTests
[Fact]
public void Viewbox_Stretch_Uniform_Child_With_Unrestricted_Height()
{
+ using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
+
var target = new Viewbox() { Child = new Rectangle() { Width = 100, Height = 50 } };
target.Measure(new Size(200, double.PositiveInfinity));
diff --git a/tests/Avalonia.Controls.UnitTests/WindowBaseTests.cs b/tests/Avalonia.Controls.UnitTests/WindowBaseTests.cs
index 84f212d1b3..8109b037c5 100644
--- a/tests/Avalonia.Controls.UnitTests/WindowBaseTests.cs
+++ b/tests/Avalonia.Controls.UnitTests/WindowBaseTests.cs
@@ -137,7 +137,7 @@ namespace Avalonia.Controls.UnitTests
var target = new TestWindowBase(windowImpl.Object);
target.IsVisible = true;
- windowImpl.Verify(x => x.Show());
+ windowImpl.Verify(x => x.Show(true));
}
}
diff --git a/tests/Avalonia.DesignerSupport.TestApp/App.xaml.cs b/tests/Avalonia.DesignerSupport.TestApp/App.xaml.cs
index 653a51232b..97b6b9021a 100644
--- a/tests/Avalonia.DesignerSupport.TestApp/App.xaml.cs
+++ b/tests/Avalonia.DesignerSupport.TestApp/App.xaml.cs
@@ -1,8 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
namespace Avalonia.DesignerSupport.TestApp
@@ -13,5 +9,12 @@ namespace Avalonia.DesignerSupport.TestApp
{
AvaloniaXamlLoader.Load(this);
}
+
+ public override void OnFrameworkInitializationCompleted()
+ {
+ if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
+ desktop.MainWindow = new MainWindow();
+ base.OnFrameworkInitializationCompleted();
+ }
}
}
diff --git a/tests/Avalonia.DesignerSupport.TestApp/Program.cs b/tests/Avalonia.DesignerSupport.TestApp/Program.cs
index c7c60a4eca..b8428511b3 100644
--- a/tests/Avalonia.DesignerSupport.TestApp/Program.cs
+++ b/tests/Avalonia.DesignerSupport.TestApp/Program.cs
@@ -1,24 +1,14 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using Avalonia.Controls;
-
-namespace Avalonia.DesignerSupport.TestApp
+namespace Avalonia.DesignerSupport.TestApp
{
static class Program
{
///
/// The main entry point for the application.
///
- static void Main()
- {
- BuildAvaloniaApp().Start();
- }
+ public static int Main(string[] args)
+ => BuildAvaloniaApp().StartWithClassicDesktopLifetime(args);
- private static AppBuilder BuildAvaloniaApp()
- {
- return AppBuilder.Configure().UsePlatformDetect();
- }
+ public static AppBuilder BuildAvaloniaApp()
+ => AppBuilder.Configure().UsePlatformDetect();
}
}
diff --git a/tests/Avalonia.DesignerSupport.Tests/DesignerSupportTests.cs b/tests/Avalonia.DesignerSupport.Tests/DesignerSupportTests.cs
index dd704bc775..d76ed9042f 100644
--- a/tests/Avalonia.DesignerSupport.Tests/DesignerSupportTests.cs
+++ b/tests/Avalonia.DesignerSupport.Tests/DesignerSupportTests.cs
@@ -11,6 +11,7 @@ using System.Threading;
using System.Threading.Tasks;
using Avalonia.Remote.Protocol;
using Avalonia.Remote.Protocol.Designer;
+using Avalonia.Remote.Protocol.Viewport;
using Xunit;
using Xunit.Extensions;
@@ -31,19 +32,38 @@ namespace Avalonia.DesignerSupport.Tests
@"..\..\..\..\..\tests/Avalonia.DesignerSupport.TestApp/bin/$BUILD/netcoreapp3.1/",
"Avalonia.DesignerSupport.TestApp",
"Avalonia.DesignerSupport.TestApp.dll",
- @"..\..\..\..\..\tests\Avalonia.DesignerSupport.TestApp\MainWindow.xaml"),
+ @"..\..\..\..\..\tests\Avalonia.DesignerSupport.TestApp\MainWindow.xaml",
+ "win32"),
InlineData(
@"..\..\..\..\..\samples\ControlCatalog.NetCore\bin\$BUILD\netcoreapp3.1\",
"ControlCatalog.NetCore",
"ControlCatalog.dll",
- @"..\..\..\..\..\samples\ControlCatalog\MainWindow.xaml")]
+ @"..\..\..\..\..\samples\ControlCatalog\MainWindow.xaml",
+ "win32"),
+ InlineData(
+ @"..\..\..\..\..\tests/Avalonia.DesignerSupport.TestApp/bin/$BUILD/netcoreapp3.1/",
+ "Avalonia.DesignerSupport.TestApp",
+ "Avalonia.DesignerSupport.TestApp.dll",
+ @"..\..\..\..\..\tests\Avalonia.DesignerSupport.TestApp\MainWindow.xaml",
+ "avalonia-remote"),
+ InlineData(
+ @"..\..\..\..\..\samples\ControlCatalog.NetCore\bin\$BUILD\netcoreapp3.1\",
+ "ControlCatalog.NetCore",
+ "ControlCatalog.dll",
+ @"..\..\..\..\..\samples\ControlCatalog\MainWindow.xaml",
+ "avalonia-remote")]
public async Task Designer_In_Win32_Mode_Should_Provide_Valid_Hwnd(
string outputDir,
string executableName,
string assemblyName,
- string xamlFile)
+ string xamlFile,
+ string method)
{
- Skip.IfNot(RuntimeInformation.IsOSPlatform(OSPlatform.Windows));
+ outputDir = Path.GetFullPath(outputDir.Replace('\\', Path.DirectorySeparatorChar));
+ xamlFile = Path.GetFullPath(xamlFile.Replace('\\', Path.DirectorySeparatorChar));
+
+ if (method == "win32")
+ Skip.IfNot(RuntimeInformation.IsOSPlatform(OSPlatform.Windows));
var xaml = File.ReadAllText(xamlFile);
string buildType;
@@ -56,6 +76,8 @@ namespace Avalonia.DesignerSupport.Tests
var sessionId = Guid.NewGuid();
long handle = 0;
+ bool success = false;
+ string error = null;
var resultMessageReceivedToken = new CancellationTokenSource();
@@ -71,6 +93,18 @@ namespace Avalonia.DesignerSupport.Tests
if (msg is StartDesignerSessionMessage start)
{
Assert.Equal(sessionId, Guid.Parse(start.SessionId));
+ if (method == "avalonia-remote")
+ {
+ await conn.Send(new ClientSupportedPixelFormatsMessage
+ {
+ Formats = new[] { PixelFormat.Rgba8888 }
+ });
+ await conn.Send(new ClientViewportAllocatedMessage
+ {
+ DpiX = 96, DpiY = 96, Width = 1024, Height = 768
+ });
+ }
+
await conn.Send(new UpdateXamlMessage
{
AssemblyPath = Path.Combine(outputDir, assemblyName),
@@ -80,8 +114,14 @@ namespace Avalonia.DesignerSupport.Tests
else if (msg is UpdateXamlResultMessage result)
{
if (result.Error != null)
+ {
+ error = result.Error;
outputHelper.WriteLine(result.Error);
- handle = result.Handle != null ? long.Parse(result.Handle) : 0;
+ }
+ else
+ success = true;
+ if (method == "win32")
+ handle = result.Handle != null ? long.Parse(result.Handle) : 0;
resultMessageReceivedToken.Cancel();
conn.Dispose();
}
@@ -91,7 +131,7 @@ namespace Avalonia.DesignerSupport.Tests
var cmdline =
$"exec --runtimeconfig \"{outputDir}{executableName}.runtimeconfig.json\" --depsfile \"{outputDir}{executableName}.deps.json\" "
+ $" \"{DesignerAppPath.Replace("$BUILD", buildType)}\" "
- + $"--transport tcp-bson://127.0.0.1:{port}/ --session-id {sessionId} --method win32 \"{outputDir}{executableName}.dll\"";
+ + $"--transport tcp-bson://127.0.0.1:{port}/ --session-id {sessionId} --method {method} \"{outputDir}{executableName}.dll\"";
using (var proc = new Process
{
@@ -128,10 +168,15 @@ namespace Avalonia.DesignerSupport.Tests
}
proc.WaitForExit();
+ var stdout = proc.StandardOutput.ReadToEnd();
+ var stderr = proc.StandardError.ReadToEnd();
Assert.True(cancelled,
$"Message Not Received.\n" + proc.StandardOutput.ReadToEnd() + "\n" +
- proc.StandardError.ReadToEnd());
- Assert.NotEqual(0, handle);
+ stderr + "\n" + stdout);
+ Assert.True(success, error);
+ if (method == "win32")
+ Assert.NotEqual(0, handle);
+
}
}
diff --git a/tests/Avalonia.DesignerSupport.Tests/Remote/HtmlTransport/webapp/.gitignore b/tests/Avalonia.DesignerSupport.Tests/Remote/HtmlTransport/webapp/.gitignore
new file mode 100644
index 0000000000..dc33b94747
--- /dev/null
+++ b/tests/Avalonia.DesignerSupport.Tests/Remote/HtmlTransport/webapp/.gitignore
@@ -0,0 +1,3 @@
+build
+node_modules
+.nyc_output
\ No newline at end of file
diff --git a/tests/Avalonia.DesignerSupport.Tests/Remote/HtmlTransport/webapp/Models/InputEventTests.ts b/tests/Avalonia.DesignerSupport.Tests/Remote/HtmlTransport/webapp/Models/InputEventTests.ts
new file mode 100644
index 0000000000..e96c4d4731
--- /dev/null
+++ b/tests/Avalonia.DesignerSupport.Tests/Remote/HtmlTransport/webapp/Models/InputEventTests.ts
@@ -0,0 +1,94 @@
+import { describe } from 'mocha';
+import { expect } from 'chai';
+import { Mock } from "moq.ts";
+import { MouseEvent, WheelEvent } from "react";
+import { InputModifiers } from "../../../../../../src/Avalonia.DesignerSupport/Remote/HtmlTransport/webapp/src/Models/Input/InputModifiers";
+import { MouseButton } from "../../../../../../src/Avalonia.DesignerSupport/Remote/HtmlTransport/webapp/src/Models/Input/MouseButton";
+import { PointerMovedEventMessage } from "../../../../../../src/Avalonia.DesignerSupport/Remote/HtmlTransport/webapp/src/Models/Input/PointerMovedEventMessage";
+import { PointerPressedEventMessage } from "../../../../../../src/Avalonia.DesignerSupport/Remote/HtmlTransport/webapp/src/Models/Input/PointerPressedEventMessage";
+import { PointerReleasedEventMessage } from "../../../../../../src/Avalonia.DesignerSupport/Remote/HtmlTransport/webapp/src/Models/Input/PointerReleasedEventMessage";
+import { ScrollEventMessage } from "../../../../../../src/Avalonia.DesignerSupport/Remote/HtmlTransport/webapp/src/Models/Input/ScrollEventMessage";
+import { getModifiers, getMouseButton } from '../../../../../../src/Avalonia.DesignerSupport/Remote/HtmlTransport/webapp/src/Models/Input/MouseEventHelpers';
+
+describe("Input event tests", () => {
+ describe("Helpers", () => {
+ it("getModifiers", () => {
+ const event = new Mock()
+ .setup(x => x.altKey).returns(false)
+ .setup(x => x.ctrlKey).returns(true)
+ .setup(x => x.shiftKey).returns(false)
+ .setup(x => x.metaKey).returns(false)
+ .setup(x => x.buttons).returns(1)
+ .object()
+ var actual = getModifiers(event)
+
+ expect(actual)
+ .eql([InputModifiers.Control, InputModifiers.LeftMouseButton])
+ })
+ it("getMouseButton", () => {
+ const event = new Mock()
+ .setup(x => x.button).returns(1)
+ .object()
+ var actual = getMouseButton(event)
+
+ expect(actual)
+ .equal(MouseButton.Middle)
+ })
+ })
+
+ describe("Messages", () => {
+ const x = .3
+ const y = .42
+ const modifiers = "0,1,2,3,4,5,6"
+
+ const button = "1"
+
+ const deltaX = -3.
+ const deltaY = -3.
+
+ const mouseEvent = new Mock()
+ .setup(x => x.altKey).returns(true)
+ .setup(x => x.ctrlKey).returns(true)
+ .setup(x => x.shiftKey).returns(true)
+ .setup(x => x.metaKey).returns(true)
+ .setup(x => x.buttons).returns(7)
+ .setup(x => x.button).returns(0)
+ .setup(x => x.clientX).returns(x)
+ .setup(x => x.clientY).returns(y)
+ .object()
+
+ it("PointerMovedEventMessage", () => {
+ const message = new PointerMovedEventMessage(mouseEvent)
+ expect(message.toString())
+ .equal(`pointer-moved:${modifiers}:${x}:${y}`)
+ })
+ it("PointerPressedEventMessage", () => {
+ const message = new PointerPressedEventMessage(mouseEvent)
+ expect(message.toString())
+ .equal(`pointer-pressed:${modifiers}:${x}:${y}:${button}`)
+ })
+ it("PointerReleasedEventMessage", () => {
+ const message = new PointerReleasedEventMessage(mouseEvent)
+ expect(message.toString())
+ .equal(`pointer-released:${modifiers}:${x}:${y}:${button}`)
+ })
+
+ it("ScrollEventMessage", () => {
+ const wheelEvent = new Mock()
+ .setup(x => x.altKey).returns(true)
+ .setup(x => x.ctrlKey).returns(true)
+ .setup(x => x.shiftKey).returns(true)
+ .setup(x => x.metaKey).returns(true)
+ .setup(x => x.buttons).returns(7)
+ .setup(x => x.clientX).returns(x)
+ .setup(x => x.clientY).returns(y)
+ .setup(x => x.deltaX).returns(-deltaX)
+ .setup(x => x.deltaY).returns(-deltaY)
+ .object()
+ const message = new ScrollEventMessage(wheelEvent)
+
+ expect(message.toString())
+ .equal(`scroll:${modifiers}:${x}:${y}:${deltaX}:${deltaY}`)
+ })
+ })
+})
diff --git a/tests/Avalonia.DesignerSupport.Tests/Remote/HtmlTransport/webapp/package-lock.json b/tests/Avalonia.DesignerSupport.Tests/Remote/HtmlTransport/webapp/package-lock.json
new file mode 100644
index 0000000000..eb707cb73f
--- /dev/null
+++ b/tests/Avalonia.DesignerSupport.Tests/Remote/HtmlTransport/webapp/package-lock.json
@@ -0,0 +1,2414 @@
+{
+ "name": "simple-test",
+ "version": "1.0.0",
+ "lockfileVersion": 1,
+ "requires": true,
+ "dependencies": {
+ "@babel/code-frame": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
+ "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
+ "dev": true,
+ "requires": {
+ "@babel/highlight": "^7.10.4"
+ }
+ },
+ "@babel/core": {
+ "version": "7.11.6",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.11.6.tgz",
+ "integrity": "sha512-Wpcv03AGnmkgm6uS6k8iwhIwTrcP0m17TL1n1sy7qD0qelDu4XNeW0dN0mHfa+Gei211yDaLoEe/VlbXQzM4Bg==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/generator": "^7.11.6",
+ "@babel/helper-module-transforms": "^7.11.0",
+ "@babel/helpers": "^7.10.4",
+ "@babel/parser": "^7.11.5",
+ "@babel/template": "^7.10.4",
+ "@babel/traverse": "^7.11.5",
+ "@babel/types": "^7.11.5",
+ "convert-source-map": "^1.7.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.1",
+ "json5": "^2.1.2",
+ "lodash": "^4.17.19",
+ "resolve": "^1.3.2",
+ "semver": "^5.4.1",
+ "source-map": "^0.5.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true
+ }
+ }
+ },
+ "@babel/generator": {
+ "version": "7.11.6",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.6.tgz",
+ "integrity": "sha512-DWtQ1PV3r+cLbySoHrwn9RWEgKMBLLma4OBQloPRyDYvc5msJM9kvTLo1YnlJd1P/ZuKbdli3ijr5q3FvAF3uA==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.11.5",
+ "jsesc": "^2.5.1",
+ "source-map": "^0.5.0"
+ }
+ },
+ "@babel/helper-function-name": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz",
+ "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-get-function-arity": "^7.10.4",
+ "@babel/template": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-get-function-arity": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz",
+ "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-member-expression-to-functions": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz",
+ "integrity": "sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.11.0"
+ }
+ },
+ "@babel/helper-module-imports": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz",
+ "integrity": "sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-module-transforms": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz",
+ "integrity": "sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-module-imports": "^7.10.4",
+ "@babel/helper-replace-supers": "^7.10.4",
+ "@babel/helper-simple-access": "^7.10.4",
+ "@babel/helper-split-export-declaration": "^7.11.0",
+ "@babel/template": "^7.10.4",
+ "@babel/types": "^7.11.0",
+ "lodash": "^4.17.19"
+ }
+ },
+ "@babel/helper-optimise-call-expression": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz",
+ "integrity": "sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-replace-supers": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz",
+ "integrity": "sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-member-expression-to-functions": "^7.10.4",
+ "@babel/helper-optimise-call-expression": "^7.10.4",
+ "@babel/traverse": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-simple-access": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz",
+ "integrity": "sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw==",
+ "dev": true,
+ "requires": {
+ "@babel/template": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-split-export-declaration": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz",
+ "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.11.0"
+ }
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
+ "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==",
+ "dev": true
+ },
+ "@babel/helpers": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.10.4.tgz",
+ "integrity": "sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA==",
+ "dev": true,
+ "requires": {
+ "@babel/template": "^7.10.4",
+ "@babel/traverse": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/highlight": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
+ "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^1.9.0"
+ }
+ },
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ }
+ },
+ "color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dev": true,
+ "requires": {
+ "color-name": "1.1.3"
+ }
+ },
+ "color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+ "dev": true
+ },
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+ "dev": true
+ },
+ "has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "@babel/parser": {
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz",
+ "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==",
+ "dev": true
+ },
+ "@babel/template": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz",
+ "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/parser": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/traverse": {
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.5.tgz",
+ "integrity": "sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/generator": "^7.11.5",
+ "@babel/helper-function-name": "^7.10.4",
+ "@babel/helper-split-export-declaration": "^7.11.0",
+ "@babel/parser": "^7.11.5",
+ "@babel/types": "^7.11.5",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0",
+ "lodash": "^4.17.19"
+ }
+ },
+ "@babel/types": {
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz",
+ "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "lodash": "^4.17.19",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "@istanbuljs/load-nyc-config": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
+ "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==",
+ "dev": true,
+ "requires": {
+ "camelcase": "^5.3.1",
+ "find-up": "^4.1.0",
+ "get-package-type": "^0.1.0",
+ "js-yaml": "^3.13.1",
+ "resolve-from": "^5.0.0"
+ },
+ "dependencies": {
+ "find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ }
+ },
+ "locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "requires": {
+ "p-locate": "^4.1.0"
+ }
+ },
+ "p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "requires": {
+ "p-try": "^2.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "requires": {
+ "p-limit": "^2.2.0"
+ }
+ }
+ }
+ },
+ "@istanbuljs/schema": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.2.tgz",
+ "integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==",
+ "dev": true
+ },
+ "@types/chai": {
+ "version": "4.2.12",
+ "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.2.12.tgz",
+ "integrity": "sha512-aN5IAC8QNtSUdQzxu7lGBgYAOuU1tmRU4c9dIq5OKGf/SBVjXo+ffM2wEjudAWbgpOhy60nLoAGH1xm8fpCKFQ==",
+ "dev": true
+ },
+ "@types/color-name": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
+ "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==",
+ "dev": true
+ },
+ "@types/mocha": {
+ "version": "8.0.3",
+ "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-8.0.3.tgz",
+ "integrity": "sha512-vyxR57nv8NfcU0GZu8EUXZLTbCMupIUwy95LJ6lllN+JRPG25CwMHoB1q5xKh8YKhQnHYRAn4yW2yuHbf/5xgg==",
+ "dev": true
+ },
+ "@types/prop-types": {
+ "version": "15.7.3",
+ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz",
+ "integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==",
+ "dev": true
+ },
+ "@types/react": {
+ "version": "16.9.49",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.49.tgz",
+ "integrity": "sha512-DtLFjSj0OYAdVLBbyjhuV9CdGVHCkHn2R+xr3XkBvK2rS1Y1tkc14XSGjYgm5Fjjr90AxH9tiSzc1pCFMGO06g==",
+ "dev": true,
+ "requires": {
+ "@types/prop-types": "*",
+ "csstype": "^3.0.2"
+ }
+ },
+ "aggregate-error": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
+ "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
+ "dev": true,
+ "requires": {
+ "clean-stack": "^2.0.0",
+ "indent-string": "^4.0.0"
+ }
+ },
+ "ansi-colors": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
+ "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
+ "dev": true
+ },
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+ "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+ "dev": true,
+ "requires": {
+ "@types/color-name": "^1.1.1",
+ "color-convert": "^2.0.1"
+ }
+ },
+ "anymatch": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz",
+ "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==",
+ "dev": true,
+ "requires": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ }
+ },
+ "append-transform": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz",
+ "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==",
+ "dev": true,
+ "requires": {
+ "default-require-extensions": "^3.0.0"
+ }
+ },
+ "archy": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz",
+ "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=",
+ "dev": true
+ },
+ "arg": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
+ "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
+ "dev": true
+ },
+ "argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "dev": true,
+ "requires": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "array.prototype.map": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/array.prototype.map/-/array.prototype.map-1.0.2.tgz",
+ "integrity": "sha512-Az3OYxgsa1g7xDYp86l0nnN4bcmuEITGe1rbdEBVkrqkzMgDcbdQ2R7r41pNzti+4NMces3H8gMmuioZUilLgw==",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.17.0-next.1",
+ "es-array-method-boxes-properly": "^1.0.0",
+ "is-string": "^1.0.4"
+ }
+ },
+ "assertion-error": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
+ "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
+ "dev": true
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
+ "dev": true
+ },
+ "binary-extensions": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz",
+ "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==",
+ "dev": true
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dev": true,
+ "requires": {
+ "fill-range": "^7.0.1"
+ }
+ },
+ "browser-stdout": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
+ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
+ "dev": true
+ },
+ "buffer-from": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
+ "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
+ "dev": true
+ },
+ "caching-transform": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz",
+ "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==",
+ "dev": true,
+ "requires": {
+ "hasha": "^5.0.0",
+ "make-dir": "^3.0.0",
+ "package-hash": "^4.0.0",
+ "write-file-atomic": "^3.0.0"
+ }
+ },
+ "camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "dev": true
+ },
+ "chai": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz",
+ "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==",
+ "dev": true,
+ "requires": {
+ "assertion-error": "^1.1.0",
+ "check-error": "^1.0.2",
+ "deep-eql": "^3.0.1",
+ "get-func-name": "^2.0.0",
+ "pathval": "^1.1.0",
+ "type-detect": "^4.0.5"
+ }
+ },
+ "chalk": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
+ "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "check-error": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
+ "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=",
+ "dev": true
+ },
+ "chokidar": {
+ "version": "3.4.2",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz",
+ "integrity": "sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==",
+ "dev": true,
+ "requires": {
+ "anymatch": "~3.1.1",
+ "braces": "~3.0.2",
+ "fsevents": "~2.1.2",
+ "glob-parent": "~5.1.0",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.4.0"
+ }
+ },
+ "clean-stack": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
+ "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
+ "dev": true
+ },
+ "cliui": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
+ "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
+ "dev": true,
+ "requires": {
+ "string-width": "^3.1.0",
+ "strip-ansi": "^5.2.0",
+ "wrap-ansi": "^5.1.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+ "dev": true
+ },
+ "string-width": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+ "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+ "dev": true,
+ "requires": {
+ "emoji-regex": "^7.0.1",
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^5.1.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+ "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^4.1.0"
+ }
+ }
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "commondir": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
+ "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
+ "dev": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+ "dev": true
+ },
+ "convert-source-map": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz",
+ "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "~5.1.1"
+ },
+ "dependencies": {
+ "safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "dev": true
+ }
+ }
+ },
+ "cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dev": true,
+ "requires": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ }
+ },
+ "csstype": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.3.tgz",
+ "integrity": "sha512-jPl+wbWPOWJ7SXsWyqGRk3lGecbar0Cb0OvZF/r/ZU011R4YqiRehgkQ9p4eQfo9DSDLqLL3wHwfxeJiuIsNag==",
+ "dev": true
+ },
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "decamelize": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
+ "dev": true
+ },
+ "deep-eql": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz",
+ "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==",
+ "dev": true,
+ "requires": {
+ "type-detect": "^4.0.0"
+ }
+ },
+ "default-require-extensions": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz",
+ "integrity": "sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg==",
+ "dev": true,
+ "requires": {
+ "strip-bom": "^4.0.0"
+ }
+ },
+ "define-properties": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
+ "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
+ "dev": true,
+ "requires": {
+ "object-keys": "^1.0.12"
+ }
+ },
+ "diff": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
+ "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
+ "dev": true
+ },
+ "emoji-regex": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
+ "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
+ "dev": true
+ },
+ "es-abstract": {
+ "version": "1.17.6",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz",
+ "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==",
+ "dev": true,
+ "requires": {
+ "es-to-primitive": "^1.2.1",
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "has-symbols": "^1.0.1",
+ "is-callable": "^1.2.0",
+ "is-regex": "^1.1.0",
+ "object-inspect": "^1.7.0",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.0",
+ "string.prototype.trimend": "^1.0.1",
+ "string.prototype.trimstart": "^1.0.1"
+ }
+ },
+ "es-array-method-boxes-properly": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz",
+ "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==",
+ "dev": true
+ },
+ "es-get-iterator": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.0.tgz",
+ "integrity": "sha512-UfrmHuWQlNMTs35e1ypnvikg6jCz3SK8v8ImvmDsh36fCVUR1MqoFDiyn0/k52C8NqO3YsO8Oe0azeesNuqSsQ==",
+ "dev": true,
+ "requires": {
+ "es-abstract": "^1.17.4",
+ "has-symbols": "^1.0.1",
+ "is-arguments": "^1.0.4",
+ "is-map": "^2.0.1",
+ "is-set": "^2.0.1",
+ "is-string": "^1.0.5",
+ "isarray": "^2.0.5"
+ }
+ },
+ "es-to-primitive": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
+ "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
+ "dev": true,
+ "requires": {
+ "is-callable": "^1.1.4",
+ "is-date-object": "^1.0.1",
+ "is-symbol": "^1.0.2"
+ }
+ },
+ "es6-error": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz",
+ "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==",
+ "dev": true
+ },
+ "escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true
+ },
+ "esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "dev": true
+ },
+ "fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dev": true,
+ "requires": {
+ "to-regex-range": "^5.0.1"
+ }
+ },
+ "find-cache-dir": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz",
+ "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==",
+ "dev": true,
+ "requires": {
+ "commondir": "^1.0.1",
+ "make-dir": "^3.0.2",
+ "pkg-dir": "^4.1.0"
+ }
+ },
+ "find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ }
+ },
+ "flat": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz",
+ "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==",
+ "dev": true,
+ "requires": {
+ "is-buffer": "~2.0.3"
+ }
+ },
+ "foreground-child": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz",
+ "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==",
+ "dev": true,
+ "requires": {
+ "cross-spawn": "^7.0.0",
+ "signal-exit": "^3.0.2"
+ }
+ },
+ "fromentries": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.2.1.tgz",
+ "integrity": "sha512-Xu2Qh8yqYuDhQGOhD5iJGninErSfI9A3FrriD3tjUgV5VbJFeH8vfgZ9HnC6jWN80QDVNQK5vmxRAmEAp7Mevw==",
+ "dev": true
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+ "dev": true
+ },
+ "fsevents": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
+ "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
+ "dev": true,
+ "optional": true
+ },
+ "function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+ "dev": true
+ },
+ "gensync": {
+ "version": "1.0.0-beta.1",
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz",
+ "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==",
+ "dev": true
+ },
+ "get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "dev": true
+ },
+ "get-func-name": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz",
+ "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=",
+ "dev": true
+ },
+ "get-package-type": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz",
+ "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==",
+ "dev": true
+ },
+ "glob": {
+ "version": "7.1.6",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
+ "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "glob-parent": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
+ "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==",
+ "dev": true,
+ "requires": {
+ "is-glob": "^4.0.1"
+ }
+ },
+ "globals": {
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+ "dev": true
+ },
+ "graceful-fs": {
+ "version": "4.2.4",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
+ "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
+ "dev": true
+ },
+ "growl": {
+ "version": "1.10.5",
+ "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz",
+ "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==",
+ "dev": true
+ },
+ "has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1"
+ }
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true
+ },
+ "has-symbols": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
+ "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==",
+ "dev": true
+ },
+ "hasha": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.0.tgz",
+ "integrity": "sha512-2W+jKdQbAdSIrggA8Q35Br8qKadTrqCTC8+XZvBWepKDK6m9XkX6Iz1a2yh2KP01kzAR/dpuMeUnocoLYDcskw==",
+ "dev": true,
+ "requires": {
+ "is-stream": "^2.0.0",
+ "type-fest": "^0.8.0"
+ }
+ },
+ "he": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
+ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
+ "dev": true
+ },
+ "html-escaper": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
+ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
+ "dev": true
+ },
+ "imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
+ "dev": true
+ },
+ "indent-string": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
+ "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
+ "dev": true
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "dev": true,
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true
+ },
+ "is-arguments": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz",
+ "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==",
+ "dev": true
+ },
+ "is-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "dev": true,
+ "requires": {
+ "binary-extensions": "^2.0.0"
+ }
+ },
+ "is-buffer": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz",
+ "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==",
+ "dev": true
+ },
+ "is-callable": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.1.tgz",
+ "integrity": "sha512-wliAfSzx6V+6WfMOmus1xy0XvSgf/dlStkvTfq7F0g4bOIW0PSUbnyse3NhDwdyYS1ozfUtAAySqTws3z9Eqgg==",
+ "dev": true
+ },
+ "is-date-object": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz",
+ "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==",
+ "dev": true
+ },
+ "is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+ "dev": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+ "dev": true
+ },
+ "is-glob": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
+ "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^2.1.1"
+ }
+ },
+ "is-map": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.1.tgz",
+ "integrity": "sha512-T/S49scO8plUiAOA2DBTBG3JHpn1yiw0kRp6dgiZ0v2/6twi5eiB0rHtHFH9ZIrvlWc6+4O+m4zg5+Z833aXgw==",
+ "dev": true
+ },
+ "is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true
+ },
+ "is-plain-obj": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
+ "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=",
+ "dev": true
+ },
+ "is-regex": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz",
+ "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==",
+ "dev": true,
+ "requires": {
+ "has-symbols": "^1.0.1"
+ }
+ },
+ "is-set": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.1.tgz",
+ "integrity": "sha512-eJEzOtVyenDs1TMzSQ3kU3K+E0GUS9sno+F0OBT97xsgcJsF9nXMBtkT9/kut5JEpM7oL7X/0qxR17K3mcwIAA==",
+ "dev": true
+ },
+ "is-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz",
+ "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==",
+ "dev": true
+ },
+ "is-string": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz",
+ "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==",
+ "dev": true
+ },
+ "is-symbol": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz",
+ "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==",
+ "dev": true,
+ "requires": {
+ "has-symbols": "^1.0.1"
+ }
+ },
+ "is-typedarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
+ "dev": true
+ },
+ "is-windows": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
+ "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
+ "dev": true
+ },
+ "isarray": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
+ "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
+ "dev": true
+ },
+ "isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+ "dev": true
+ },
+ "istanbul-lib-coverage": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz",
+ "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==",
+ "dev": true
+ },
+ "istanbul-lib-hook": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz",
+ "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==",
+ "dev": true,
+ "requires": {
+ "append-transform": "^2.0.0"
+ }
+ },
+ "istanbul-lib-instrument": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz",
+ "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==",
+ "dev": true,
+ "requires": {
+ "@babel/core": "^7.7.5",
+ "@istanbuljs/schema": "^0.1.2",
+ "istanbul-lib-coverage": "^3.0.0",
+ "semver": "^6.3.0"
+ }
+ },
+ "istanbul-lib-processinfo": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.2.tgz",
+ "integrity": "sha512-kOwpa7z9hme+IBPZMzQ5vdQj8srYgAtaRqeI48NGmAQ+/5yKiHLV0QbYqQpxsdEF0+w14SoB8YbnHKcXE2KnYw==",
+ "dev": true,
+ "requires": {
+ "archy": "^1.0.0",
+ "cross-spawn": "^7.0.0",
+ "istanbul-lib-coverage": "^3.0.0-alpha.1",
+ "make-dir": "^3.0.0",
+ "p-map": "^3.0.0",
+ "rimraf": "^3.0.0",
+ "uuid": "^3.3.3"
+ }
+ },
+ "istanbul-lib-report": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz",
+ "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==",
+ "dev": true,
+ "requires": {
+ "istanbul-lib-coverage": "^3.0.0",
+ "make-dir": "^3.0.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "istanbul-lib-source-maps": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz",
+ "integrity": "sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg==",
+ "dev": true,
+ "requires": {
+ "debug": "^4.1.1",
+ "istanbul-lib-coverage": "^3.0.0",
+ "source-map": "^0.6.1"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "istanbul-reports": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.2.tgz",
+ "integrity": "sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw==",
+ "dev": true,
+ "requires": {
+ "html-escaper": "^2.0.0",
+ "istanbul-lib-report": "^3.0.0"
+ }
+ },
+ "iterate-iterator": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/iterate-iterator/-/iterate-iterator-1.0.1.tgz",
+ "integrity": "sha512-3Q6tudGN05kbkDQDI4CqjaBf4qf85w6W6GnuZDtUVYwKgtC1q8yxYX7CZed7N+tLzQqS6roujWvszf13T+n9aw==",
+ "dev": true
+ },
+ "iterate-value": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/iterate-value/-/iterate-value-1.0.2.tgz",
+ "integrity": "sha512-A6fMAio4D2ot2r/TYzr4yUWrmwNdsN5xL7+HUiyACE4DXm+q8HtPcnFTp+NnW3k4N05tZ7FVYFFb2CR13NxyHQ==",
+ "dev": true,
+ "requires": {
+ "es-get-iterator": "^1.0.2",
+ "iterate-iterator": "^1.0.1"
+ }
+ },
+ "js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "dev": true
+ },
+ "js-yaml": {
+ "version": "3.14.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz",
+ "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==",
+ "dev": true,
+ "requires": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ }
+ },
+ "jsesc": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
+ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
+ "dev": true
+ },
+ "json5": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz",
+ "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==",
+ "dev": true,
+ "requires": {
+ "minimist": "^1.2.5"
+ }
+ },
+ "locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "requires": {
+ "p-locate": "^5.0.0"
+ }
+ },
+ "lodash": {
+ "version": "4.17.20",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
+ "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
+ "dev": true
+ },
+ "lodash.flattendeep": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz",
+ "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=",
+ "dev": true
+ },
+ "log-symbols": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz",
+ "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==",
+ "dev": true,
+ "requires": {
+ "chalk": "^4.0.0"
+ }
+ },
+ "loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "dev": true,
+ "requires": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ }
+ },
+ "make-dir": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
+ "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
+ "dev": true,
+ "requires": {
+ "semver": "^6.0.0"
+ }
+ },
+ "make-error": {
+ "version": "1.3.6",
+ "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
+ "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
+ "dev": true
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "minimist": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
+ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
+ "dev": true
+ },
+ "mocha": {
+ "version": "8.1.3",
+ "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.1.3.tgz",
+ "integrity": "sha512-ZbaYib4hT4PpF4bdSO2DohooKXIn4lDeiYqB+vTmCdr6l2woW0b6H3pf5x4sM5nwQMru9RvjjHYWVGltR50ZBw==",
+ "dev": true,
+ "requires": {
+ "ansi-colors": "4.1.1",
+ "browser-stdout": "1.3.1",
+ "chokidar": "3.4.2",
+ "debug": "4.1.1",
+ "diff": "4.0.2",
+ "escape-string-regexp": "4.0.0",
+ "find-up": "5.0.0",
+ "glob": "7.1.6",
+ "growl": "1.10.5",
+ "he": "1.2.0",
+ "js-yaml": "3.14.0",
+ "log-symbols": "4.0.0",
+ "minimatch": "3.0.4",
+ "ms": "2.1.2",
+ "object.assign": "4.1.0",
+ "promise.allsettled": "1.0.2",
+ "serialize-javascript": "4.0.0",
+ "strip-json-comments": "3.0.1",
+ "supports-color": "7.1.0",
+ "which": "2.0.2",
+ "wide-align": "1.1.3",
+ "workerpool": "6.0.0",
+ "yargs": "13.3.2",
+ "yargs-parser": "13.1.2",
+ "yargs-unparser": "1.6.1"
+ }
+ },
+ "moq.ts": {
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/moq.ts/-/moq.ts-6.4.0.tgz",
+ "integrity": "sha512-g9siyKOvYGVhfDCl9mpLptch93egRC3yXIbPLssxukOROl368XBB+6M7YjLTkjVRHbKbpJBD6P7od+Ky/0xWIw==",
+ "dev": true,
+ "requires": {
+ "tslib": "^2.0.0"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "node-preload": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz",
+ "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==",
+ "dev": true,
+ "requires": {
+ "process-on-spawn": "^1.0.0"
+ }
+ },
+ "normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true
+ },
+ "nyc": {
+ "version": "15.1.0",
+ "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz",
+ "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==",
+ "dev": true,
+ "requires": {
+ "@istanbuljs/load-nyc-config": "^1.0.0",
+ "@istanbuljs/schema": "^0.1.2",
+ "caching-transform": "^4.0.0",
+ "convert-source-map": "^1.7.0",
+ "decamelize": "^1.2.0",
+ "find-cache-dir": "^3.2.0",
+ "find-up": "^4.1.0",
+ "foreground-child": "^2.0.0",
+ "get-package-type": "^0.1.0",
+ "glob": "^7.1.6",
+ "istanbul-lib-coverage": "^3.0.0",
+ "istanbul-lib-hook": "^3.0.0",
+ "istanbul-lib-instrument": "^4.0.0",
+ "istanbul-lib-processinfo": "^2.0.2",
+ "istanbul-lib-report": "^3.0.0",
+ "istanbul-lib-source-maps": "^4.0.0",
+ "istanbul-reports": "^3.0.2",
+ "make-dir": "^3.0.0",
+ "node-preload": "^0.2.1",
+ "p-map": "^3.0.0",
+ "process-on-spawn": "^1.0.0",
+ "resolve-from": "^5.0.0",
+ "rimraf": "^3.0.0",
+ "signal-exit": "^3.0.2",
+ "spawn-wrap": "^2.0.0",
+ "test-exclude": "^6.0.0",
+ "yargs": "^15.0.2"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
+ "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
+ "dev": true
+ },
+ "cliui": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
+ "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
+ "dev": true,
+ "requires": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.0",
+ "wrap-ansi": "^6.2.0"
+ }
+ },
+ "emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
+ "find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ }
+ },
+ "is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true
+ },
+ "locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "requires": {
+ "p-locate": "^4.1.0"
+ }
+ },
+ "p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "requires": {
+ "p-try": "^2.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "requires": {
+ "p-limit": "^2.2.0"
+ }
+ },
+ "string-width": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
+ "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
+ "dev": true,
+ "requires": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
+ "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^5.0.0"
+ }
+ },
+ "wrap-ansi": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+ "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ }
+ },
+ "yargs": {
+ "version": "15.4.1",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
+ "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
+ "dev": true,
+ "requires": {
+ "cliui": "^6.0.0",
+ "decamelize": "^1.2.0",
+ "find-up": "^4.1.0",
+ "get-caller-file": "^2.0.1",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^2.0.0",
+ "set-blocking": "^2.0.0",
+ "string-width": "^4.2.0",
+ "which-module": "^2.0.0",
+ "y18n": "^4.0.0",
+ "yargs-parser": "^18.1.2"
+ }
+ },
+ "yargs-parser": {
+ "version": "18.1.3",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
+ "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
+ "dev": true,
+ "requires": {
+ "camelcase": "^5.0.0",
+ "decamelize": "^1.2.0"
+ }
+ }
+ }
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
+ "dev": true
+ },
+ "object-inspect": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz",
+ "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==",
+ "dev": true
+ },
+ "object-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+ "dev": true
+ },
+ "object.assign": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz",
+ "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.2",
+ "function-bind": "^1.1.1",
+ "has-symbols": "^1.0.0",
+ "object-keys": "^1.0.11"
+ }
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "dev": true,
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "p-limit": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.0.2.tgz",
+ "integrity": "sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg==",
+ "dev": true,
+ "requires": {
+ "p-try": "^2.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "requires": {
+ "p-limit": "^3.0.2"
+ }
+ },
+ "p-map": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz",
+ "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==",
+ "dev": true,
+ "requires": {
+ "aggregate-error": "^3.0.0"
+ }
+ },
+ "p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "dev": true
+ },
+ "package-hash": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz",
+ "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.15",
+ "hasha": "^5.0.0",
+ "lodash.flattendeep": "^4.4.0",
+ "release-zalgo": "^1.0.0"
+ }
+ },
+ "path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+ "dev": true
+ },
+ "path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true
+ },
+ "path-parse": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
+ "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
+ "dev": true
+ },
+ "pathval": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz",
+ "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=",
+ "dev": true
+ },
+ "picomatch": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
+ "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
+ "dev": true
+ },
+ "pkg-dir": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
+ "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
+ "dev": true,
+ "requires": {
+ "find-up": "^4.0.0"
+ },
+ "dependencies": {
+ "find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ }
+ },
+ "locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "requires": {
+ "p-locate": "^4.1.0"
+ }
+ },
+ "p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "requires": {
+ "p-try": "^2.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "requires": {
+ "p-limit": "^2.2.0"
+ }
+ }
+ }
+ },
+ "process-on-spawn": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz",
+ "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==",
+ "dev": true,
+ "requires": {
+ "fromentries": "^1.2.0"
+ }
+ },
+ "promise.allsettled": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/promise.allsettled/-/promise.allsettled-1.0.2.tgz",
+ "integrity": "sha512-UpcYW5S1RaNKT6pd+s9jp9K9rlQge1UXKskec0j6Mmuq7UJCvlS2J2/s/yuPN8ehftf9HXMxWlKiPbGGUzpoRg==",
+ "dev": true,
+ "requires": {
+ "array.prototype.map": "^1.0.1",
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.17.0-next.1",
+ "function-bind": "^1.1.1",
+ "iterate-value": "^1.0.0"
+ }
+ },
+ "prop-types": {
+ "version": "15.7.2",
+ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz",
+ "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==",
+ "dev": true,
+ "requires": {
+ "loose-envify": "^1.4.0",
+ "object-assign": "^4.1.1",
+ "react-is": "^16.8.1"
+ }
+ },
+ "randombytes": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
+ "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "^5.1.0"
+ }
+ },
+ "react": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react/-/react-16.13.1.tgz",
+ "integrity": "sha512-YMZQQq32xHLX0bz5Mnibv1/LHb3Sqzngu7xstSM+vrkE5Kzr9xE0yMByK5kMoTK30YVJE61WfbxIFFvfeDKT1w==",
+ "dev": true,
+ "requires": {
+ "loose-envify": "^1.1.0",
+ "object-assign": "^4.1.1",
+ "prop-types": "^15.6.2"
+ }
+ },
+ "react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
+ "dev": true
+ },
+ "readdirp": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz",
+ "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==",
+ "dev": true,
+ "requires": {
+ "picomatch": "^2.2.1"
+ }
+ },
+ "release-zalgo": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz",
+ "integrity": "sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA=",
+ "dev": true,
+ "requires": {
+ "es6-error": "^4.0.1"
+ }
+ },
+ "require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
+ "dev": true
+ },
+ "require-main-filename": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
+ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
+ "dev": true
+ },
+ "resolve": {
+ "version": "1.17.0",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz",
+ "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==",
+ "dev": true,
+ "requires": {
+ "path-parse": "^1.0.6"
+ }
+ },
+ "resolve-from": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+ "dev": true
+ },
+ "rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "dev": true,
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "dev": true
+ },
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ },
+ "serialize-javascript": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz",
+ "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==",
+ "dev": true,
+ "requires": {
+ "randombytes": "^2.1.0"
+ }
+ },
+ "set-blocking": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
+ "dev": true
+ },
+ "shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "requires": {
+ "shebang-regex": "^3.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true
+ },
+ "signal-exit": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
+ "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "dev": true
+ },
+ "source-map-support": {
+ "version": "0.5.19",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz",
+ "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==",
+ "dev": true,
+ "requires": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "spawn-wrap": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz",
+ "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==",
+ "dev": true,
+ "requires": {
+ "foreground-child": "^2.0.0",
+ "is-windows": "^1.0.2",
+ "make-dir": "^3.0.0",
+ "rimraf": "^3.0.0",
+ "signal-exit": "^3.0.2",
+ "which": "^2.0.1"
+ }
+ },
+ "sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
+ "dev": true
+ },
+ "string-width": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+ "dev": true,
+ "requires": {
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^4.0.0"
+ }
+ },
+ "string.prototype.trimend": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz",
+ "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.17.5"
+ }
+ },
+ "string.prototype.trimstart": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz",
+ "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.17.5"
+ }
+ },
+ "strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^3.0.0"
+ }
+ },
+ "strip-bom": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz",
+ "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==",
+ "dev": true
+ },
+ "strip-json-comments": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz",
+ "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+ "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ },
+ "test-exclude": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
+ "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==",
+ "dev": true,
+ "requires": {
+ "@istanbuljs/schema": "^0.1.2",
+ "glob": "^7.1.4",
+ "minimatch": "^3.0.4"
+ }
+ },
+ "to-fast-properties": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
+ "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=",
+ "dev": true
+ },
+ "to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "requires": {
+ "is-number": "^7.0.0"
+ }
+ },
+ "ts-node": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.0.0.tgz",
+ "integrity": "sha512-/TqB4SnererCDR/vb4S/QvSZvzQMJN8daAslg7MeaiHvD8rDZsSfXmNeNumyZZzMned72Xoq/isQljYSt8Ynfg==",
+ "dev": true,
+ "requires": {
+ "arg": "^4.1.0",
+ "diff": "^4.0.1",
+ "make-error": "^1.1.1",
+ "source-map-support": "^0.5.17",
+ "yn": "3.1.1"
+ }
+ },
+ "tslib": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.1.tgz",
+ "integrity": "sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ==",
+ "dev": true
+ },
+ "type-detect": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
+ "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
+ "dev": true
+ },
+ "type-fest": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
+ "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
+ "dev": true
+ },
+ "typedarray-to-buffer": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
+ "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
+ "dev": true,
+ "requires": {
+ "is-typedarray": "^1.0.0"
+ }
+ },
+ "typescript": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.0.2.tgz",
+ "integrity": "sha512-e4ERvRV2wb+rRZ/IQeb3jm2VxBsirQLpQhdxplZ2MEzGvDkkMmPglecnNDfSUBivMjP93vRbngYYDQqQ/78bcQ==",
+ "dev": true
+ },
+ "uuid": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
+ "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
+ "dev": true
+ },
+ "which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ },
+ "which-module": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
+ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
+ "dev": true
+ },
+ "wide-align": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
+ "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
+ "dev": true,
+ "requires": {
+ "string-width": "^1.0.2 || 2"
+ }
+ },
+ "workerpool": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.0.0.tgz",
+ "integrity": "sha512-fU2OcNA/GVAJLLyKUoHkAgIhKb0JoCpSjLC/G2vYKxUjVmQwGbRVeoPJ1a8U4pnVofz4AQV5Y/NEw8oKqxEBtA==",
+ "dev": true
+ },
+ "wrap-ansi": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
+ "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.0",
+ "string-width": "^3.0.0",
+ "strip-ansi": "^5.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^1.9.0"
+ }
+ },
+ "color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dev": true,
+ "requires": {
+ "color-name": "1.1.3"
+ }
+ },
+ "color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+ "dev": true
+ },
+ "string-width": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+ "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+ "dev": true,
+ "requires": {
+ "emoji-regex": "^7.0.1",
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^5.1.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+ "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^4.1.0"
+ }
+ }
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+ "dev": true
+ },
+ "write-file-atomic": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz",
+ "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==",
+ "dev": true,
+ "requires": {
+ "imurmurhash": "^0.1.4",
+ "is-typedarray": "^1.0.0",
+ "signal-exit": "^3.0.2",
+ "typedarray-to-buffer": "^3.1.5"
+ }
+ },
+ "y18n": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
+ "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
+ "dev": true
+ },
+ "yargs": {
+ "version": "13.3.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz",
+ "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==",
+ "dev": true,
+ "requires": {
+ "cliui": "^5.0.0",
+ "find-up": "^3.0.0",
+ "get-caller-file": "^2.0.1",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^2.0.0",
+ "set-blocking": "^2.0.0",
+ "string-width": "^3.0.0",
+ "which-module": "^2.0.0",
+ "y18n": "^4.0.0",
+ "yargs-parser": "^13.1.2"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+ "dev": true
+ },
+ "find-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^3.0.0"
+ }
+ },
+ "locate-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+ "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+ "dev": true,
+ "requires": {
+ "p-locate": "^3.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "requires": {
+ "p-try": "^2.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+ "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+ "dev": true,
+ "requires": {
+ "p-limit": "^2.0.0"
+ }
+ },
+ "path-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+ "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
+ "dev": true
+ },
+ "string-width": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+ "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+ "dev": true,
+ "requires": {
+ "emoji-regex": "^7.0.1",
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^5.1.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+ "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^4.1.0"
+ }
+ }
+ }
+ },
+ "yargs-parser": {
+ "version": "13.1.2",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz",
+ "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==",
+ "dev": true,
+ "requires": {
+ "camelcase": "^5.0.0",
+ "decamelize": "^1.2.0"
+ }
+ },
+ "yargs-unparser": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.1.tgz",
+ "integrity": "sha512-qZV14lK9MWsGCmcr7u5oXGH0dbGqZAIxTDrWXZDo5zUr6b6iUmelNKO6x6R1dQT24AH3LgRxJpr8meWy2unolA==",
+ "dev": true,
+ "requires": {
+ "camelcase": "^5.3.1",
+ "decamelize": "^1.2.0",
+ "flat": "^4.1.0",
+ "is-plain-obj": "^1.1.0",
+ "yargs": "^14.2.3"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+ "dev": true
+ },
+ "find-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^3.0.0"
+ }
+ },
+ "locate-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+ "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+ "dev": true,
+ "requires": {
+ "p-locate": "^3.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "requires": {
+ "p-try": "^2.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+ "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+ "dev": true,
+ "requires": {
+ "p-limit": "^2.0.0"
+ }
+ },
+ "path-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+ "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
+ "dev": true
+ },
+ "string-width": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+ "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+ "dev": true,
+ "requires": {
+ "emoji-regex": "^7.0.1",
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^5.1.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+ "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^4.1.0"
+ }
+ },
+ "yargs": {
+ "version": "14.2.3",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-14.2.3.tgz",
+ "integrity": "sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg==",
+ "dev": true,
+ "requires": {
+ "cliui": "^5.0.0",
+ "decamelize": "^1.2.0",
+ "find-up": "^3.0.0",
+ "get-caller-file": "^2.0.1",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^2.0.0",
+ "set-blocking": "^2.0.0",
+ "string-width": "^3.0.0",
+ "which-module": "^2.0.0",
+ "y18n": "^4.0.0",
+ "yargs-parser": "^15.0.1"
+ }
+ },
+ "yargs-parser": {
+ "version": "15.0.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.1.tgz",
+ "integrity": "sha512-0OAMV2mAZQrs3FkNpDQcBk1x5HXb8X4twADss4S0Iuk+2dGnLOE/fRHrsYm542GduMveyA77OF4wrNJuanRCWw==",
+ "dev": true,
+ "requires": {
+ "camelcase": "^5.0.0",
+ "decamelize": "^1.2.0"
+ }
+ }
+ }
+ },
+ "yn": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
+ "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
+ "dev": true
+ }
+ }
+}
diff --git a/tests/Avalonia.DesignerSupport.Tests/Remote/HtmlTransport/webapp/package.json b/tests/Avalonia.DesignerSupport.Tests/Remote/HtmlTransport/webapp/package.json
new file mode 100644
index 0000000000..dbb12e192a
--- /dev/null
+++ b/tests/Avalonia.DesignerSupport.Tests/Remote/HtmlTransport/webapp/package.json
@@ -0,0 +1,26 @@
+{
+ "name": "simple-test",
+ "version": "1.0.0",
+ "main": "index.js",
+ "scripts": {
+ "test": "mocha -r ts-node/register ./**/*Tests.ts",
+ "coverage": "nyc -r text -e .ts -x \"./*Tests.ts\" npm run test"
+ },
+ "type": "module",
+ "keywords": [],
+ "author": "",
+ "license": "MIT",
+ "dependencies": {},
+ "devDependencies": {
+ "@types/chai": "4.2.12",
+ "@types/mocha": "8.0.3",
+ "@types/react": "^16.3.14",
+ "chai": "^4.2.0",
+ "mocha": "^8.1.3",
+ "moq.ts": "^6.4.0",
+ "nyc": "^15.1.0",
+ "react": "^16.3.2",
+ "ts-node": "^9.0.0",
+ "typescript": "^4.0.2"
+ }
+}
diff --git a/tests/Avalonia.DesignerSupport.Tests/Remote/HtmlTransport/webapp/tsconfig.json b/tests/Avalonia.DesignerSupport.Tests/Remote/HtmlTransport/webapp/tsconfig.json
new file mode 100644
index 0000000000..fdb82879fc
--- /dev/null
+++ b/tests/Avalonia.DesignerSupport.Tests/Remote/HtmlTransport/webapp/tsconfig.json
@@ -0,0 +1,12 @@
+{
+ "compilerOptions": {
+ "module": "commonjs",
+ "target": "es5",
+ "sourceMap": true,
+ "strict": true,
+ "esModuleInterop": true
+ },
+ "exclude": [
+ "node_modules"
+ ]
+}
diff --git a/tests/Avalonia.Direct2D1.RenderTests/Avalonia.Direct2D1.RenderTests.csproj b/tests/Avalonia.Direct2D1.RenderTests/Avalonia.Direct2D1.RenderTests.csproj
index 1cfc1a6ab8..c59e59be63 100644
--- a/tests/Avalonia.Direct2D1.RenderTests/Avalonia.Direct2D1.RenderTests.csproj
+++ b/tests/Avalonia.Direct2D1.RenderTests/Avalonia.Direct2D1.RenderTests.csproj
@@ -27,4 +27,5 @@
+
diff --git a/tests/Avalonia.Direct2D1.UnitTests/Avalonia.Direct2D1.UnitTests.csproj b/tests/Avalonia.Direct2D1.UnitTests/Avalonia.Direct2D1.UnitTests.csproj
index e346ce944d..42229ba456 100644
--- a/tests/Avalonia.Direct2D1.UnitTests/Avalonia.Direct2D1.UnitTests.csproj
+++ b/tests/Avalonia.Direct2D1.UnitTests/Avalonia.Direct2D1.UnitTests.csproj
@@ -7,6 +7,7 @@
+
@@ -22,4 +23,4 @@
-
\ No newline at end of file
+
diff --git a/tests/Avalonia.Input.UnitTests/InputElement_Focus.cs b/tests/Avalonia.Input.UnitTests/InputElement_Focus.cs
index 09fae7207f..8b8f2fa775 100644
--- a/tests/Avalonia.Input.UnitTests/InputElement_Focus.cs
+++ b/tests/Avalonia.Input.UnitTests/InputElement_Focus.cs
@@ -121,5 +121,202 @@ namespace Avalonia.Input.UnitTests
Assert.False(target2.Classes.Contains(":focus-visible"));
}
}
+
+ [Fact]
+ public void Control_FocusWithin_PseudoClass_Should_Be_Applied()
+ {
+ using (UnitTestApplication.Start(TestServices.RealFocus))
+ {
+ var target1 = new Decorator();
+ var target2 = new Decorator();
+ var root = new TestRoot
+ {
+ Child = new StackPanel
+ {
+ Children =
+ {
+ target1,
+ target2
+ }
+ }
+ };
+
+ target1.ApplyTemplate();
+ target2.ApplyTemplate();
+
+ FocusManager.Instance?.Focus(target1);
+ Assert.True(target1.IsFocused);
+ Assert.True(target1.Classes.Contains(":focus-within"));
+ Assert.True(target1.IsKeyboardFocusWithin);
+ Assert.True(root.Child.Classes.Contains(":focus-within"));
+ Assert.True(root.Child.IsKeyboardFocusWithin);
+ Assert.True(root.Classes.Contains(":focus-within"));
+ Assert.True(root.IsKeyboardFocusWithin);
+ }
+ }
+
+ [Fact]
+ public void Control_FocusWithin_PseudoClass_Should_Be_Applied_and_Removed()
+ {
+ using (UnitTestApplication.Start(TestServices.RealFocus))
+ {
+ var target1 = new Decorator();
+ var target2 = new Decorator();
+ var panel1 = new Panel { Children = { target1 } };
+ var panel2 = new Panel { Children = { target2 } };
+ var root = new TestRoot
+ {
+ Child = new StackPanel
+ {
+ Children =
+ {
+ panel1,
+ panel2
+ }
+ }
+ };
+
+ target1.ApplyTemplate();
+ target2.ApplyTemplate();
+
+ FocusManager.Instance?.Focus(target1);
+ Assert.True(target1.IsFocused);
+ Assert.True(target1.Classes.Contains(":focus-within"));
+ Assert.True(target1.IsKeyboardFocusWithin);
+ Assert.True(panel1.Classes.Contains(":focus-within"));
+ Assert.True(panel1.IsKeyboardFocusWithin);
+ Assert.True(root.Child.Classes.Contains(":focus-within"));
+ Assert.True(root.Child.IsKeyboardFocusWithin);
+ Assert.True(root.Classes.Contains(":focus-within"));
+ Assert.True(root.IsKeyboardFocusWithin);
+
+ FocusManager.Instance?.Focus(target2);
+
+ Assert.False(target1.IsFocused);
+ Assert.False(target1.Classes.Contains(":focus-within"));
+ Assert.False(target1.IsKeyboardFocusWithin);
+ Assert.False(panel1.Classes.Contains(":focus-within"));
+ Assert.False(panel1.IsKeyboardFocusWithin);
+ Assert.True(root.Child.Classes.Contains(":focus-within"));
+ Assert.True(root.Child.IsKeyboardFocusWithin);
+ Assert.True(root.Classes.Contains(":focus-within"));
+ Assert.True(root.IsKeyboardFocusWithin);
+
+ Assert.True(target2.IsFocused);
+ Assert.True(target2.Classes.Contains(":focus-within"));
+ Assert.True(target2.IsKeyboardFocusWithin);
+ Assert.True(panel2.Classes.Contains(":focus-within"));
+ Assert.True(panel2.IsKeyboardFocusWithin);
+ }
+ }
+
+ [Fact]
+ public void Control_FocusWithin_Pseudoclass_Should_Be_Removed_When_Removed_From_Tree()
+ {
+ using (UnitTestApplication.Start(TestServices.RealFocus))
+ {
+ var target1 = new Decorator();
+ var target2 = new Decorator();
+ var root = new TestRoot
+ {
+ Child = new StackPanel
+ {
+ Children =
+ {
+ target1,
+ target2
+ }
+ }
+ };
+
+ target1.ApplyTemplate();
+ target2.ApplyTemplate();
+
+ FocusManager.Instance?.Focus(target1);
+ Assert.True(target1.IsFocused);
+ Assert.True(target1.Classes.Contains(":focus-within"));
+ Assert.True(target1.IsKeyboardFocusWithin);
+ Assert.True(root.Child.Classes.Contains(":focus-within"));
+ Assert.True(root.Child.IsKeyboardFocusWithin);
+ Assert.True(root.Classes.Contains(":focus-within"));
+ Assert.True(root.IsKeyboardFocusWithin);
+
+ Assert.Equal(KeyboardDevice.Instance.FocusedElement, target1);
+
+ root.Child = null;
+
+ Assert.Null(KeyboardDevice.Instance.FocusedElement);
+
+ Assert.False(target1.IsFocused);
+ Assert.False(target1.Classes.Contains(":focus-within"));
+ Assert.False(target1.IsKeyboardFocusWithin);
+ Assert.False(root.Classes.Contains(":focus-within"));
+ Assert.False(root.IsKeyboardFocusWithin);
+ }
+ }
+
+ [Fact]
+ public void Control_FocusWithin_Pseudoclass_Should_Be_Removed_Focus_Moves_To_Different_Root()
+ {
+ using (UnitTestApplication.Start(TestServices.RealFocus))
+ {
+ var target1 = new Decorator();
+ var target2 = new Decorator();
+
+ var root1 = new TestRoot
+ {
+ Child = new StackPanel
+ {
+ Children =
+ {
+ target1,
+ }
+ }
+ };
+
+ var root2 = new TestRoot
+ {
+ Child = new StackPanel
+ {
+ Children =
+ {
+ target2,
+ }
+ }
+ };
+
+ target1.ApplyTemplate();
+ target2.ApplyTemplate();
+
+ FocusManager.Instance?.Focus(target1);
+ Assert.True(target1.IsFocused);
+ Assert.True(target1.Classes.Contains(":focus-within"));
+ Assert.True(target1.IsKeyboardFocusWithin);
+ Assert.True(root1.Child.Classes.Contains(":focus-within"));
+ Assert.True(root1.Child.IsKeyboardFocusWithin);
+ Assert.True(root1.Classes.Contains(":focus-within"));
+ Assert.True(root1.IsKeyboardFocusWithin);
+
+ Assert.Equal(KeyboardDevice.Instance.FocusedElement, target1);
+
+ FocusManager.Instance?.Focus(target2);
+
+ Assert.False(target1.IsFocused);
+ Assert.False(target1.Classes.Contains(":focus-within"));
+ Assert.False(target1.IsKeyboardFocusWithin);
+ Assert.False(root1.Child.Classes.Contains(":focus-within"));
+ Assert.False(root1.Child.IsKeyboardFocusWithin);
+ Assert.False(root1.Classes.Contains(":focus-within"));
+ Assert.False(root1.IsKeyboardFocusWithin);
+
+ Assert.True(target2.IsFocused);
+ Assert.True(target2.Classes.Contains(":focus-within"));
+ Assert.True(target2.IsKeyboardFocusWithin);
+ Assert.True(root2.Child.Classes.Contains(":focus-within"));
+ Assert.True(root2.Child.IsKeyboardFocusWithin);
+ Assert.True(root2.Classes.Contains(":focus-within"));
+ Assert.True(root2.IsKeyboardFocusWithin);
+ }
+ }
}
}
diff --git a/tests/Avalonia.Layout.UnitTests/Avalonia.Layout.UnitTests.csproj b/tests/Avalonia.Layout.UnitTests/Avalonia.Layout.UnitTests.csproj
index 463bc50008..74cc6e292b 100644
--- a/tests/Avalonia.Layout.UnitTests/Avalonia.Layout.UnitTests.csproj
+++ b/tests/Avalonia.Layout.UnitTests/Avalonia.Layout.UnitTests.csproj
@@ -8,6 +8,7 @@
+
diff --git a/tests/Avalonia.Layout.UnitTests/LayoutableTests.cs b/tests/Avalonia.Layout.UnitTests/LayoutableTests.cs
index 44a5af94b9..a8aa0bbf0e 100644
--- a/tests/Avalonia.Layout.UnitTests/LayoutableTests.cs
+++ b/tests/Avalonia.Layout.UnitTests/LayoutableTests.cs
@@ -112,7 +112,7 @@ namespace Avalonia.Layout.UnitTests
root.Measure(Size.Infinity);
root.Arrange(new Rect(root.DesiredSize));
- target.ResetCalls();
+ target.Invocations.Clear();
control.InvalidateMeasure();
control.InvalidateMeasure();
@@ -133,7 +133,7 @@ namespace Avalonia.Layout.UnitTests
root.Measure(Size.Infinity);
root.Arrange(new Rect(root.DesiredSize));
- target.ResetCalls();
+ target.Invocations.Clear();
control.InvalidateArrange();
control.InvalidateArrange();
@@ -163,7 +163,7 @@ namespace Avalonia.Layout.UnitTests
Assert.False(control.IsMeasureValid);
Assert.True(root.IsMeasureValid);
- target.ResetCalls();
+ target.Invocations.Clear();
root.Child = control;
diff --git a/tests/Avalonia.Layout.UnitTests/LayoutableTests_EffectiveViewportChanged.cs b/tests/Avalonia.Layout.UnitTests/LayoutableTests_EffectiveViewportChanged.cs
index 504e3fa585..f1cec24516 100644
--- a/tests/Avalonia.Layout.UnitTests/LayoutableTests_EffectiveViewportChanged.cs
+++ b/tests/Avalonia.Layout.UnitTests/LayoutableTests_EffectiveViewportChanged.cs
@@ -15,7 +15,9 @@ namespace Avalonia.Layout.UnitTests
[Fact]
public async Task EffectiveViewportChanged_Not_Raised_When_Control_Added_To_Tree()
{
+#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
await RunOnUIThread.Execute(async () =>
+#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
{
var root = CreateRoot();
var target = new Canvas();
diff --git a/tests/Avalonia.Layout.UnitTests/ShapeLayoutTests.cs b/tests/Avalonia.Layout.UnitTests/ShapeLayoutTests.cs
deleted file mode 100644
index 2ccd6fb04c..0000000000
--- a/tests/Avalonia.Layout.UnitTests/ShapeLayoutTests.cs
+++ /dev/null
@@ -1,113 +0,0 @@
-using System.Collections.Generic;
-using Avalonia.Controls;
-using Avalonia.Controls.Shapes;
-using Avalonia.Media;
-using Avalonia.Platform;
-using Avalonia.UnitTests;
-using Xunit;
-
-namespace Avalonia.Layout.UnitTests
-
-{
- public class ShapeLayoutTests : TestWithServicesBase
- {
-
- public ShapeLayoutTests()
- {
- AvaloniaLocator.CurrentMutable
- .Bind().ToSingleton();
- }
-
- [Fact]
- public void Shape_Transformation_Calculation_Should_Be_Deferred_To_Arrange_When_Strech_Is_Fill_And_Aviable_Size_Is_Infinite()
- {
- var shape = new Polygon()
- {
- Points = new List
- {
- new Point(0, 0),
- new Point(10, 5),
- new Point(0, 10)
- },
- Stretch = Stretch.Fill
- };
-
- var availableSize = new Size(double.PositiveInfinity, double.PositiveInfinity);
- shape.Measure(availableSize);
- Geometry postMeasureGeometry = shape.RenderedGeometry;
- Transform postMeasureTransform = postMeasureGeometry.Transform;
-
- var finalSize = new Size(100, 50);
- var finalRect = new Rect(finalSize);
- shape.Arrange(finalRect);
-
- Geometry postArrangeGeometry = shape.RenderedGeometry;
- Transform postArrangeTransform = postArrangeGeometry.Transform;
-
- Assert.NotEqual(postMeasureGeometry, postArrangeGeometry);
- Assert.NotEqual(postMeasureTransform, postArrangeTransform);
- Assert.Equal(finalSize, shape.Bounds.Size);
- }
-
- [Fact]
- public void Shape_Transformation_Calculation_Should_Not_Be_Deferred_To_Arrange_When_Strech_Is_Fill_And_Aviable_Size_Is_Finite()
- {
- var shape = new Polygon()
- {
- Points = new List
- {
- new Point(0, 0),
- new Point(10, 5),
- new Point(0, 10)
- },
- Stretch = Stretch.Fill
- };
-
- var availableSize = new Size(100, 50);
- shape.Measure(availableSize);
- Geometry postMeasureGeometry = shape.RenderedGeometry;
- Transform postMeasureTransform = postMeasureGeometry.Transform;
-
- var finalRect = new Rect(availableSize);
- shape.Arrange(finalRect);
-
- Geometry postArrangeGeometry = shape.RenderedGeometry;
- Transform postArrangeTransform = postArrangeGeometry.Transform;
-
- Assert.Equal(postMeasureGeometry, postArrangeGeometry);
- Assert.Equal(postMeasureTransform, postArrangeTransform);
- Assert.Equal(availableSize, shape.Bounds.Size);
- }
-
- [Fact]
- public void Shape_Transformation_Calculation_Should_Not_Be_Deferred_To_Arrange_When_Strech_Is_None()
- {
- var shape = new Polygon()
- {
- Points = new List
- {
- new Point(0, 0),
- new Point(10, 5),
- new Point(0, 10)
- },
- Stretch = Stretch.None
- };
-
- var availableSize = new Size(double.PositiveInfinity, double.PositiveInfinity);
- shape.Measure(availableSize);
- Geometry postMeasureGeometry = shape.RenderedGeometry;
- Transform postMeasureTransform = postMeasureGeometry.Transform;
-
- var finalSize = new Size(100, 50);
- var finalRect = new Rect(finalSize);
- shape.Arrange(finalRect);
-
- Geometry postArrangeGeometry = shape.RenderedGeometry;
- Transform postArrangeTransform = postArrangeGeometry.Transform;
-
- Assert.Equal(postMeasureGeometry, postArrangeGeometry);
- Assert.Equal(postMeasureTransform, postArrangeTransform);
- Assert.Equal(finalSize, shape.Bounds.Size);
- }
- }
-}
diff --git a/tests/Avalonia.LeakTests/Avalonia.LeakTests.csproj b/tests/Avalonia.LeakTests/Avalonia.LeakTests.csproj
index 27f3223c6c..d49a859b89 100644
--- a/tests/Avalonia.LeakTests/Avalonia.LeakTests.csproj
+++ b/tests/Avalonia.LeakTests/Avalonia.LeakTests.csproj
@@ -7,6 +7,7 @@
+
@@ -25,4 +26,4 @@
-
\ No newline at end of file
+
diff --git a/tests/Avalonia.LeakTests/ControlTests.cs b/tests/Avalonia.LeakTests/ControlTests.cs
index 0c7b966f29..b03ae00cfe 100644
--- a/tests/Avalonia.LeakTests/ControlTests.cs
+++ b/tests/Avalonia.LeakTests/ControlTests.cs
@@ -460,7 +460,7 @@ namespace Avalonia.LeakTests
AttachShowAndDetachContextMenu(window);
- Mock.Get(window.PlatformImpl).ResetCalls();
+ Mock.Get(window.PlatformImpl).Invocations.Clear();
dotMemory.Check(memory =>
Assert.Equal(initialMenuCount, memory.GetObjects(where => where.Type.Is()).ObjectsCount));
dotMemory.Check(memory =>
@@ -505,7 +505,7 @@ namespace Avalonia.LeakTests
BuildAndShowContextMenu(window);
BuildAndShowContextMenu(window);
- Mock.Get(window.PlatformImpl).ResetCalls();
+ Mock.Get(window.PlatformImpl).Invocations.Clear();
dotMemory.Check(memory =>
Assert.Equal(initialMenuCount, memory.GetObjects(where => where.Type.Is()).ObjectsCount));
dotMemory.Check(memory =>
@@ -601,8 +601,9 @@ namespace Avalonia.LeakTests
{
public bool DrawFps { get; set; }
public bool DrawDirtyRects { get; set; }
+#pragma warning disable CS0067
public event EventHandler SceneInvalidated;
-
+#pragma warning restore CS0067
public void AddDirty(IVisual visual)
{
}
diff --git a/tests/Avalonia.Markup.UnitTests/Avalonia.Markup.UnitTests.csproj b/tests/Avalonia.Markup.UnitTests/Avalonia.Markup.UnitTests.csproj
index ec5b2f0ed1..7d1285c025 100644
--- a/tests/Avalonia.Markup.UnitTests/Avalonia.Markup.UnitTests.csproj
+++ b/tests/Avalonia.Markup.UnitTests/Avalonia.Markup.UnitTests.csproj
@@ -10,6 +10,7 @@
+
diff --git a/tests/Avalonia.Markup.UnitTests/Data/MultiBindingTests.cs b/tests/Avalonia.Markup.UnitTests/Data/MultiBindingTests.cs
index 64f5eb2a0e..b87922aa1e 100644
--- a/tests/Avalonia.Markup.UnitTests/Data/MultiBindingTests.cs
+++ b/tests/Avalonia.Markup.UnitTests/Data/MultiBindingTests.cs
@@ -157,6 +157,29 @@ namespace Avalonia.Markup.UnitTests.Data
Assert.Equal("1,2,Fallback", target.Text);
}
+ [Fact]
+ public void MultiBinding_Without_StringFormat_And_Converter()
+ {
+ var source = new { A = 1, B = 2, C = 3 };
+ var target = new ItemsControl { };
+
+ var binding = new MultiBinding
+ {
+ Bindings = new[]
+ {
+ new Binding { Path = "A", Source = source },
+ new Binding { Path = "B", Source = source },
+ new Binding { Path = "C", Source = source },
+ },
+ };
+
+ target.Bind(ItemsControl.ItemsProperty, binding);
+ Assert.Equal(target.ItemCount, 3);
+ Assert.Equal(target.Items.ElementAt(0), source.A);
+ Assert.Equal(target.Items.ElementAt(1), source.B);
+ Assert.Equal(target.Items.ElementAt(2), source.C);
+ }
+
private class ConcatConverter : IMultiValueConverter
{
public object Convert(IList values, Type targetType, object parameter, CultureInfo culture)
diff --git a/tests/Avalonia.Markup.UnitTests/Extensions/IEnummerableExtension.cs b/tests/Avalonia.Markup.UnitTests/Extensions/IEnummerableExtension.cs
new file mode 100644
index 0000000000..0d9e2969e1
--- /dev/null
+++ b/tests/Avalonia.Markup.UnitTests/Extensions/IEnummerableExtension.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections;
+
+namespace Avalonia.Markup.UnitTests
+{
+ internal static class IEnumerableExtensions
+ {
+ public static object ElementAt(this IEnumerable source, int index)
+ {
+ var i = -1;
+ var enumerator = source.GetEnumerator();
+
+ while (enumerator.MoveNext() && ++i < index);
+ if (i == index)
+ {
+ return enumerator.Current;
+ }
+ throw new ArgumentOutOfRangeException(nameof(index));
+ }
+ }
+}
diff --git a/tests/Avalonia.Markup.UnitTests/Parsers/ExpressionObserverBuilderTests_AttachedProperty.cs b/tests/Avalonia.Markup.UnitTests/Parsers/ExpressionObserverBuilderTests_AttachedProperty.cs
index 45cf28773f..7c48a975ef 100644
--- a/tests/Avalonia.Markup.UnitTests/Parsers/ExpressionObserverBuilderTests_AttachedProperty.cs
+++ b/tests/Avalonia.Markup.UnitTests/Parsers/ExpressionObserverBuilderTests_AttachedProperty.cs
@@ -129,7 +129,7 @@ namespace Avalonia.Markup.UnitTests.Parsers
{
var data = new Class1();
- Assert.Throws(() => ExpressionObserverBuilder.Build(data, "(Owner)", typeResolver: _typeResolver));
+ Assert.Throws(() => ExpressionObserverBuilder.Build(data, "(Owner.)", typeResolver: _typeResolver));
}
[Fact]
diff --git a/tests/Avalonia.Markup.UnitTests/Parsers/ExpressionObserverBuilderTests_Negation.cs b/tests/Avalonia.Markup.UnitTests/Parsers/ExpressionObserverBuilderTests_Negation.cs
index 0be3bbbb9f..0028502eeb 100644
--- a/tests/Avalonia.Markup.UnitTests/Parsers/ExpressionObserverBuilderTests_Negation.cs
+++ b/tests/Avalonia.Markup.UnitTests/Parsers/ExpressionObserverBuilderTests_Negation.cs
@@ -168,10 +168,23 @@ namespace Avalonia.Markup.UnitTests.Parsers
private class Test : INotifyDataErrorInfo
{
+ private string _dataValidationError;
+
public bool Foo { get; set; }
public object Bar { get; set; }
- public string DataValidationError { get; set; }
+ public string DataValidationError
+ {
+ get => _dataValidationError;
+ set
+ {
+ if (value == _dataValidationError)
+ return;
+ _dataValidationError = value;
+ ErrorsChanged?
+ .Invoke(this, new DataErrorsChangedEventArgs(nameof(DataValidationError)));
+ }
+ }
public bool HasErrors => !string.IsNullOrWhiteSpace(DataValidationError);
public event EventHandler ErrorsChanged;
diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Avalonia.Markup.Xaml.UnitTests.csproj b/tests/Avalonia.Markup.Xaml.UnitTests/Avalonia.Markup.Xaml.UnitTests.csproj
index ad3592294d..44b604197d 100644
--- a/tests/Avalonia.Markup.Xaml.UnitTests/Avalonia.Markup.Xaml.UnitTests.csproj
+++ b/tests/Avalonia.Markup.Xaml.UnitTests/Avalonia.Markup.Xaml.UnitTests.csproj
@@ -10,6 +10,7 @@
+
diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/BindingExtensionTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/BindingExtensionTests.cs
index 9ea2cd643a..20ed22e84f 100644
--- a/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/BindingExtensionTests.cs
+++ b/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/BindingExtensionTests.cs
@@ -84,6 +84,54 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
}
}
+ [Fact]
+ public void SupportCastToTypeInExpression()
+ {
+ using (UnitTestApplication.Start(TestServices.StyledWindow))
+ {
+ var xaml = @"
+
+
+";
+ var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
+ var contentControl = window.FindControl("contentControl");
+
+ var dataContext = new TestDataContext
+ {
+ StringProperty = "foobar"
+ };
+
+ window.DataContext = dataContext;
+
+ Assert.Equal(dataContext.StringProperty, contentControl.Content);
+ }
+ }
+
+ [Fact]
+ public void SupportCastToTypeInExpression_DifferentTypeEvaluatesToNull()
+ {
+ using (UnitTestApplication.Start(TestServices.StyledWindow))
+ {
+ var xaml = @"
+
+
+";
+ var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
+ var contentControl = window.FindControl("contentControl");
+
+ var dataContext = "foo";
+
+ window.DataContext = dataContext;
+
+ Assert.Equal(null, contentControl.Content);
+ }
+ }
private class FooBar
{
public object Foo { get; } = null;
diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/CompiledBindingExtensionTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/CompiledBindingExtensionTests.cs
index 8a82ad048b..6f549a4ffa 100644
--- a/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/CompiledBindingExtensionTests.cs
+++ b/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/CompiledBindingExtensionTests.cs
@@ -1,13 +1,16 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
+using System.Globalization;
using System.Reactive.Subjects;
using System.Text;
using System.Threading.Tasks;
using Avalonia.Controls;
using Avalonia.Controls.Presenters;
+using Avalonia.Data.Converters;
using Avalonia.Data.Core;
using Avalonia.Markup.Data;
+using Avalonia.Media;
using Avalonia.UnitTests;
using XamlX;
using Xunit;
@@ -372,7 +375,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
";
- Assert.Throws(() => AvaloniaRuntimeXamlLoader.Load(xaml));
+ ThrowsXamlTransformException(() => AvaloniaRuntimeXamlLoader.Load(xaml));
}
}
@@ -390,7 +393,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
";
- Assert.Throws(() => AvaloniaRuntimeXamlLoader.Load(xaml));
+ ThrowsXamlTransformException(() => AvaloniaRuntimeXamlLoader.Load(xaml));
}
}
@@ -447,7 +450,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
";
- Assert.Throws(() => AvaloniaRuntimeXamlLoader.Load(xaml));
+ ThrowsXamlTransformException(() => AvaloniaRuntimeXamlLoader.Load(xaml));
}
}
@@ -534,7 +537,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
}
[Fact]
- public void ResolvesSourceBindingLongForm()
+ public void Binds_To_Source()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
@@ -557,6 +560,124 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
}
}
+ [Fact]
+ public void Binds_To_Source_StaticResource()
+ {
+ using (UnitTestApplication.Start(TestServices.StyledWindow))
+ {
+ var xaml = @"
+
+
+
+
+
+";
+
+ var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
+ var textBlock = window.FindControl("textBlock");
+
+ Assert.Equal("foobar", textBlock.Text);
+ }
+ }
+
+ [Fact]
+ public void Binds_To_Source_StaticResource1()
+ {
+ using (UnitTestApplication.Start(TestServices.StyledWindow))
+ {
+ var xaml = @"
+
+
+
+ test
+
+
+";
+
+ var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
+ var textBlock = window.FindControl("textBlock");
+
+ Assert.Equal("foobar", textBlock.Text);
+ }
+ }
+
+ [Fact]
+ public void Binds_To_Source_StaticResource_In_ResourceDictionary()
+ {
+ using (UnitTestApplication.Start(TestServices.StyledWindow))
+ {
+ var xaml = @"
+
+
+
+
+
+
+
+";
+
+ var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
+ var textBlock = window.FindControl("textBlock");
+
+ Assert.Equal("foobar", textBlock.Text);
+ }
+ }
+
+ [Fact]
+ public void Binds_To_Source_StaticResource_In_ResourceDictionary1()
+ {
+ using (UnitTestApplication.Start(TestServices.StyledWindow))
+ {
+ var xaml = @"
+
+
+
+
+ test
+
+
+
+";
+
+ var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
+ var textBlock = window.FindControl("textBlock");
+
+ Assert.Equal("foobar", textBlock.Text);
+ }
+ }
+
+ [Fact]
+ public void Binds_To_Source_xStatic()
+ {
+ using (UnitTestApplication.Start(TestServices.StyledWindow))
+ {
+ var xaml = @"
+
+
+";
+
+ var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
+ var contentControl = window.FindControl("contentControl");
+
+ Assert.Equal(Brushes.Red.Color, contentControl.Content);
+ }
+ }
+
[Fact]
public void CompilesBindingWhenRequested()
{
@@ -597,7 +718,49 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
x:CompileBindings='true'>
";
- Assert.Throws(() => AvaloniaRuntimeXamlLoader.Load(xaml));
+ ThrowsXamlParseException(() => AvaloniaRuntimeXamlLoader.Load(xaml));
+ }
+ }
+
+ [Fact]
+ public void SupportParentInPath()
+ {
+ using (UnitTestApplication.Start(TestServices.StyledWindow))
+ {
+ var xaml = @"
+
+
+";
+ var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
+ var contentControl = window.FindControl("contentControl");
+
+ Assert.Equal("foo", contentControl.Content);
+ }
+ }
+
+ [Fact]
+ public void SupportConverterWithParameter()
+ {
+ using (UnitTestApplication.Start(TestServices.StyledWindow))
+ {
+ var xaml = @"
+
+
+";
+
+ var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
+ var textBlock = window.FindControl("textBlock");
+
+ window.DataContext = new TestDataContext() { StringProperty = "Foo" };
+
+ Assert.Equal("Foo+Bar", textBlock.Text);
}
}
@@ -613,26 +776,218 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
x:DataType='local:TestDataContext'
x:CompileBindings='notabool'>
";
- Assert.Throws(() => AvaloniaRuntimeXamlLoader.Load(xaml));
+ ThrowsXamlParseException(() => AvaloniaRuntimeXamlLoader.Load(xaml));
+ }
+ }
+
+ [Fact]
+ public void SupportCastToTypeInExpression()
+ {
+ using (UnitTestApplication.Start(TestServices.StyledWindow))
+ {
+ var xaml = @"
+
+
+";
+ var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
+ var contentControl = window.FindControl("contentControl");
+
+ var dataContext = new TestDataContext();
+
+ window.DataContext = dataContext;
+
+ Assert.Equal(dataContext, contentControl.Content);
}
}
- }
+ [Fact]
+ public void SupportCastToTypeInExpression_DifferentTypeEvaluatesToNull()
+ {
+ using (UnitTestApplication.Start(TestServices.StyledWindow))
+ {
+ var xaml = @"
+
+
+";
+ var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
+ var contentControl = window.FindControl("contentControl");
+
+ var dataContext = "foo";
+
+ window.DataContext = dataContext;
+
+ Assert.Equal(null, contentControl.Content);
+ }
+ }
+
+ [Fact]
+ public void SupportCastToTypeInExpressionWithProperty()
+ {
+ using (UnitTestApplication.Start(TestServices.StyledWindow))
+ {
+ var xaml = @"
+
+
+";
+ var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
+ var contentControl = window.FindControl("contentControl");
+
+ var dataContext = new TestDataContext
+ {
+ StringProperty = "foobar"
+ };
+
+ window.DataContext = dataContext;
+
+ Assert.Equal(dataContext.StringProperty, contentControl.Content);
+ }
+ }
+
+ [Fact]
+ public void SupportCastToTypeInExpressionWithProperty1()
+ {
+ using (UnitTestApplication.Start(TestServices.StyledWindow))
+ {
+ var xaml = @"
+
+
+";
+ var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
+ var contentControl = window.FindControl("contentControl");
+
+ var dataContext = new TestDataContext
+ {
+ StringProperty = "foobar"
+ };
+
+ window.DataContext = dataContext;
+
+ Assert.Equal(dataContext.StringProperty, contentControl.Content);
+ }
+ }
+
+ [Fact]
+ public void SupportCastToTypeInExpressionWithPropertyIndexer()
+ {
+ using (UnitTestApplication.Start(TestServices.StyledWindow))
+ {
+ var xaml = @"
+
+
+";
+ var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
+ var contentControl = window.FindControl("contentControl");
+
+ var data = new TestData()
+ {
+ StringProperty = "Foo"
+ };
+ var dataContext = new TestDataContext
+ {
+ ObjectsArrayProperty = new object[] { data }
+ };
+
+ window.DataContext = dataContext;
+
+ Assert.Equal(data.StringProperty, contentControl.Content);
+ }
+ }
+
+ [Fact]
+ public void SupportCastToTypeInExpressionWithProperty_DifferentTypeEvaluatesToNull()
+ {
+ using (UnitTestApplication.Start(TestServices.StyledWindow))
+ {
+ var xaml = @"
+
+
+";
+ var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
+ var contentControl = window.FindControl("contentControl");
+
+ var dataContext = new TestDataContext
+ {
+ StringProperty = "foobar"
+ };
+
+ window.DataContext = dataContext;
+
+ Assert.Equal(dataContext.StringProperty, contentControl.Content);
+
+ window.DataContext = "foo";
+
+ Assert.Equal(null, contentControl.Content);
+ }
+ }
+
+ void Throws(string type, Action cb)
+ {
+ try
+ {
+ cb();
+ }
+ catch (Exception e) when (e.GetType().Name == type)
+ {
+ return;
+ }
+
+ throw new Exception("Expected " + type);
+ }
+
+ void ThrowsXamlParseException(Action cb) => Throws("XamlParseException", cb);
+ void ThrowsXamlTransformException(Action cb) => Throws("XamlTransformException", cb);
+ }
+
public interface INonIntegerIndexer
{
- string this[string key] {get; set;}
+ string this[string key] { get; set; }
}
public interface INonIntegerIndexerDerived : INonIntegerIndexer
- {}
+ { }
public interface IHasProperty
{
- string StringProperty {get; set; }
+ string StringProperty { get; set; }
}
public interface IHasPropertyDerived : IHasProperty
- {}
+ { }
+
+ public class AppendConverter : IValueConverter
+ {
+ public static IValueConverter Instance { get; } = new AppendConverter();
+
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ => string.Format("{0}+{1}", value, parameter);
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ => throw new NotImplementedException();
+
+ }
+
+ public class TestData
+ {
+ public string StringProperty { get; set; }
+ }
public class TestDataContext : IHasPropertyDerived
{
@@ -646,6 +1001,8 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
public string[] ArrayProperty { get; set; }
+ public object[] ObjectsArrayProperty { get; set; }
+
public List ListProperty { get; set; } = new List();
public NonIntegerIndexer NonIntegerIndexerProperty { get; set; } = new NonIntegerIndexer();
diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/DynamicResourceExtensionTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/DynamicResourceExtensionTests.cs
index 47a73cb360..9152131ab3 100644
--- a/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/DynamicResourceExtensionTests.cs
+++ b/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/DynamicResourceExtensionTests.cs
@@ -345,6 +345,23 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
Assert.Equal(0xff506070, brush.Color.ToUint32());
}
+ [Fact]
+ public void DynamicResource_Can_Be_Assigned_To_Resource_Property_In_Application()
+ {
+ var xaml = @"
+
+
+ #ff506070
+
+
+";
+
+ var application = (Application)AvaloniaRuntimeXamlLoader.Load(xaml);
+ var brush = (SolidColorBrush)application.Resources["brush"];
+
+ Assert.Equal(0xff506070, brush.Color.ToUint32());
+ }
[Fact]
public void DynamicResource_Can_Be_Assigned_To_ItemTemplate_Property()
diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/ShapeTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/ShapeTests.cs
new file mode 100644
index 0000000000..bd577e84f8
--- /dev/null
+++ b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/ShapeTests.cs
@@ -0,0 +1,24 @@
+using Avalonia.Controls;
+using Avalonia.Media;
+using Xunit;
+
+namespace Avalonia.Markup.Xaml.UnitTests.Xaml
+{
+ public class ShapeTests : XamlTestBase
+ {
+ [Fact]
+ public void Can_Specify_DashStyle_In_XAML()
+ {
+ var xaml = @"
+
+
+
+
+";
+
+ var target = AvaloniaRuntimeXamlLoader.Parse(xaml);
+
+ Assert.NotNull(target);
+ }
+ }
+}
diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/XamlIlTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/XamlIlTests.cs
index 67e46d25c3..77a4932ccc 100644
--- a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/XamlIlTests.cs
+++ b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/XamlIlTests.cs
@@ -295,8 +295,27 @@ namespace Avalonia.Markup.Xaml.UnitTests
Assert.Equal("Test", templated.Text);
}
}
+
+ [Fact]
+ public void Should_Work_With_Base_Property()
+ {
+ var parsed = (ListBox)AvaloniaRuntimeXamlLoader.Load(@"
+
+
+
+
+
+
+");
+
+ Assert.NotNull(parsed.ItemTemplate);
+ }
}
-
+
public class XamlIlBugTestsEventHandlerCodeBehind : Window
{
public object SavedContext;
diff --git a/tests/Avalonia.ReactiveUI.UnitTests/Avalonia.ReactiveUI.UnitTests.csproj b/tests/Avalonia.ReactiveUI.UnitTests/Avalonia.ReactiveUI.UnitTests.csproj
index d162a2abe0..95e10d7a2f 100644
--- a/tests/Avalonia.ReactiveUI.UnitTests/Avalonia.ReactiveUI.UnitTests.csproj
+++ b/tests/Avalonia.ReactiveUI.UnitTests/Avalonia.ReactiveUI.UnitTests.csproj
@@ -1,6 +1,7 @@
netcoreapp3.1
+ false
diff --git a/tests/Avalonia.ReactiveUI.UnitTests/AvaloniaActivationForViewFetcherTest.cs b/tests/Avalonia.ReactiveUI.UnitTests/AvaloniaActivationForViewFetcherTest.cs
index fda8503135..c66a3c4ba1 100644
--- a/tests/Avalonia.ReactiveUI.UnitTests/AvaloniaActivationForViewFetcherTest.cs
+++ b/tests/Avalonia.ReactiveUI.UnitTests/AvaloniaActivationForViewFetcherTest.cs
@@ -74,44 +74,26 @@ namespace Avalonia.ReactiveUI.UnitTests
{
public ActivatableWindow()
{
- InitializeComponent();
- Assert.IsType(Content);
+ Content = new Border();
this.WhenActivated(disposables => { });
}
-
- private void InitializeComponent()
- {
- AvaloniaRuntimeXamlLoader.Load(@"
-
-
-", null, this);
- }
}
public class ActivatableUserControl : ReactiveUserControl
{
public ActivatableUserControl()
{
- InitializeComponent();
- Assert.IsType(Content);
+ Content = new Border();
this.WhenActivated(disposables => { });
}
-
- private void InitializeComponent()
- {
- AvaloniaRuntimeXamlLoader.Load(@"
-
-
-", null, this);
- }
}
- public AvaloniaActivationForViewFetcherTest()
- {
- Locator.CurrentMutable.RegisterConstant(
- new AvaloniaActivationForViewFetcher(),
- typeof(IActivationForViewFetcher));
- }
+ public AvaloniaActivationForViewFetcherTest() =>
+ Locator
+ .CurrentMutable
+ .RegisterConstant(
+ new AvaloniaActivationForViewFetcher(),
+ typeof(IActivationForViewFetcher));
[Fact]
public void Visual_Element_Is_Activated_And_Deactivated()
diff --git a/tests/Avalonia.ReactiveUI.UnitTests/ReactiveUserControlTest.cs b/tests/Avalonia.ReactiveUI.UnitTests/ReactiveUserControlTest.cs
index b57bb242bd..4dd60e21c5 100644
--- a/tests/Avalonia.ReactiveUI.UnitTests/ReactiveUserControlTest.cs
+++ b/tests/Avalonia.ReactiveUI.UnitTests/ReactiveUserControlTest.cs
@@ -1,3 +1,4 @@
+using System.Reactive.Disposables;
using Avalonia.Controls;
using Avalonia.UnitTests;
using ReactiveUI;
@@ -8,14 +9,37 @@ namespace Avalonia.ReactiveUI.UnitTests
{
public class ReactiveUserControlTest
{
- public class ExampleViewModel : ReactiveObject { }
+ public class ExampleViewModel : ReactiveObject, IActivatableViewModel
+ {
+ public bool IsActive { get; private set; }
+
+ public ViewModelActivator Activator { get; } = new ViewModelActivator();
+
+ public ExampleViewModel() => this.WhenActivated(disposables =>
+ {
+ IsActive = true;
+ Disposable
+ .Create(() => IsActive = false)
+ .DisposeWith(disposables);
+ });
+ }
public class ExampleView : ReactiveUserControl { }
+ public ReactiveUserControlTest() =>
+ Locator
+ .CurrentMutable
+ .RegisterConstant(
+ new AvaloniaActivationForViewFetcher(),
+ typeof(IActivationForViewFetcher));
+
[Fact]
public void Data_Context_Should_Stay_In_Sync_With_Reactive_User_Control_View_Model()
{
+ var root = new TestRoot();
var view = new ExampleView();
+ root.Child = view;
+
var viewModel = new ExampleViewModel();
Assert.Null(view.ViewModel);
@@ -26,6 +50,126 @@ namespace Avalonia.ReactiveUI.UnitTests
view.DataContext = null;
Assert.Null(view.ViewModel);
Assert.Null(view.DataContext);
+
+ view.ViewModel = viewModel;
+ Assert.Equal(viewModel, view.ViewModel);
+ Assert.Equal(viewModel, view.DataContext);
+
+ view.ViewModel = null;
+ Assert.Null(view.ViewModel);
+ Assert.Null(view.DataContext);
+ }
+
+ [Fact]
+ public void Should_Start_With_NotNull_Activated_ViewModel()
+ {
+ var root = new TestRoot();
+ var view = new ExampleView {ViewModel = new ExampleViewModel()};
+
+ Assert.False(view.ViewModel.IsActive);
+
+ root.Child = view;
+
+ Assert.NotNull(view.ViewModel);
+ Assert.NotNull(view.DataContext);
+ Assert.True(view.ViewModel.IsActive);
+
+ root.Child = null;
+
+ Assert.NotNull(view.ViewModel);
+ Assert.NotNull(view.DataContext);
+ Assert.False(view.ViewModel.IsActive);
+ }
+
+ [Fact]
+ public void Should_Start_With_NotNull_Activated_DataContext()
+ {
+ var root = new TestRoot();
+ var view = new ExampleView {DataContext = new ExampleViewModel()};
+
+ Assert.False(view.ViewModel.IsActive);
+
+ root.Child = view;
+
+ Assert.NotNull(view.ViewModel);
+ Assert.NotNull(view.DataContext);
+ Assert.True(view.ViewModel.IsActive);
+
+ root.Child = null;
+
+ Assert.NotNull(view.ViewModel);
+ Assert.NotNull(view.DataContext);
+ Assert.False(view.ViewModel.IsActive);
+ }
+
+ [Fact]
+ public void Should_Inherit_DataContext()
+ {
+ var vm1 = new ExampleViewModel();
+ var vm2 = new ExampleViewModel();
+ var view = new ExampleView();
+ var root = new TestRoot(view);
+
+ Assert.Null(view.DataContext);
+ Assert.Null(view.ViewModel);
+
+ root.DataContext = vm1;
+
+ Assert.Same(vm1, view.DataContext);
+ Assert.Same(vm1, view.ViewModel);
+
+ root.DataContext = null;
+
+ Assert.Null(view.DataContext);
+ Assert.Null(view.ViewModel);
+
+ root.DataContext = vm2;
+
+ Assert.Same(vm2, view.DataContext);
+ Assert.Same(vm2, view.ViewModel);
+ }
+
+ [Fact]
+ public void Should_Not_Overlap_Change_Notifications()
+ {
+ var vm1 = new ExampleViewModel();
+ var vm2 = new ExampleViewModel();
+
+ var view1 = new ExampleView();
+ var view2 = new ExampleView();
+
+ Assert.Null(view1.DataContext);
+ Assert.Null(view2.DataContext);
+ Assert.Null(view1.ViewModel);
+ Assert.Null(view2.ViewModel);
+
+ view1.DataContext = vm1;
+
+ Assert.Same(vm1, view1.DataContext);
+ Assert.Same(vm1, view1.ViewModel);
+ Assert.Null(view2.DataContext);
+ Assert.Null(view2.ViewModel);
+
+ view2.DataContext = vm2;
+
+ Assert.Same(vm1, view1.DataContext);
+ Assert.Same(vm1, view1.ViewModel);
+ Assert.Same(vm2, view2.DataContext);
+ Assert.Same(vm2, view2.ViewModel);
+
+ view1.ViewModel = null;
+
+ Assert.Null(view1.DataContext);
+ Assert.Null(view1.ViewModel);
+ Assert.Same(vm2, view2.DataContext);
+ Assert.Same(vm2, view2.ViewModel);
+
+ view2.ViewModel = null;
+
+ Assert.Null(view1.DataContext);
+ Assert.Null(view2.DataContext);
+ Assert.Null(view1.ViewModel);
+ Assert.Null(view2.ViewModel);
}
}
-}
\ No newline at end of file
+}
diff --git a/tests/Avalonia.ReactiveUI.UnitTests/ReactiveWindowTest.cs b/tests/Avalonia.ReactiveUI.UnitTests/ReactiveWindowTest.cs
index 3a5c562a59..18a8a33f09 100644
--- a/tests/Avalonia.ReactiveUI.UnitTests/ReactiveWindowTest.cs
+++ b/tests/Avalonia.ReactiveUI.UnitTests/ReactiveWindowTest.cs
@@ -1,4 +1,4 @@
-using Avalonia.Controls;
+using System.Reactive.Disposables;
using Avalonia.UnitTests;
using ReactiveUI;
using Splat;
@@ -8,10 +8,30 @@ namespace Avalonia.ReactiveUI.UnitTests
{
public class ReactiveWindowTest
{
- public class ExampleViewModel : ReactiveObject { }
+ public class ExampleViewModel : ReactiveObject, IActivatableViewModel
+ {
+ public bool IsActive { get; private set; }
+
+ public ViewModelActivator Activator { get; } = new ViewModelActivator();
+
+ public ExampleViewModel() => this.WhenActivated(disposables =>
+ {
+ IsActive = true;
+ Disposable
+ .Create(() => IsActive = false)
+ .DisposeWith(disposables);
+ });
+ }
public class ExampleWindow : ReactiveWindow { }
+ public ReactiveWindowTest() =>
+ Locator
+ .CurrentMutable
+ .RegisterConstant(
+ new AvaloniaActivationForViewFetcher(),
+ typeof(IActivationForViewFetcher));
+
[Fact]
public void Data_Context_Should_Stay_In_Sync_With_Reactive_Window_View_Model()
{
@@ -19,16 +39,73 @@ namespace Avalonia.ReactiveUI.UnitTests
{
var view = new ExampleWindow();
var viewModel = new ExampleViewModel();
+ view.Show();
+
Assert.Null(view.ViewModel);
+ Assert.Null(view.DataContext);
view.DataContext = viewModel;
- Assert.Equal(view.ViewModel, viewModel);
- Assert.Equal(view.DataContext, viewModel);
+ Assert.Equal(viewModel, view.ViewModel);
+ Assert.Equal(viewModel, view.DataContext);
view.DataContext = null;
Assert.Null(view.ViewModel);
Assert.Null(view.DataContext);
+
+ view.ViewModel = viewModel;
+ Assert.Equal(viewModel, view.ViewModel);
+ Assert.Equal(viewModel, view.DataContext);
+
+ view.ViewModel = null;
+ Assert.Null(view.ViewModel);
+ Assert.Null(view.DataContext);
+ }
+ }
+
+ [Fact]
+ public void Should_Start_With_NotNull_Activated_ViewModel()
+ {
+ using (UnitTestApplication.Start(TestServices.StyledWindow))
+ {
+ var view = new ExampleWindow { ViewModel = new ExampleViewModel() };
+
+ Assert.False(view.ViewModel.IsActive);
+
+ view.Show();
+
+ Assert.NotNull(view.ViewModel);
+ Assert.NotNull(view.DataContext);
+ Assert.True(view.ViewModel.IsActive);
+
+ view.Close();
+
+ Assert.NotNull(view.ViewModel);
+ Assert.NotNull(view.DataContext);
+ Assert.False(view.ViewModel.IsActive);
+ }
+ }
+
+ [Fact]
+ public void Should_Start_With_NotNull_Activated_DataContext()
+ {
+ using (UnitTestApplication.Start(TestServices.StyledWindow))
+ {
+ var view = new ExampleWindow { DataContext = new ExampleViewModel() };
+
+ Assert.False(view.ViewModel.IsActive);
+
+ view.Show();
+
+ Assert.NotNull(view.ViewModel);
+ Assert.NotNull(view.DataContext);
+ Assert.True(view.ViewModel.IsActive);
+
+ view.Close();
+
+ Assert.NotNull(view.ViewModel);
+ Assert.NotNull(view.DataContext);
+ Assert.False(view.ViewModel.IsActive);
}
}
}
-}
\ No newline at end of file
+}
diff --git a/tests/Avalonia.RenderTests/Controls/TextBlockTests.cs b/tests/Avalonia.RenderTests/Controls/TextBlockTests.cs
index ab769e4ff0..53a2959848 100644
--- a/tests/Avalonia.RenderTests/Controls/TextBlockTests.cs
+++ b/tests/Avalonia.RenderTests/Controls/TextBlockTests.cs
@@ -40,5 +40,59 @@ namespace Avalonia.Direct2D1.RenderTests.Controls
await RenderToFile(target);
CompareImages();
}
+
+
+ [Win32Fact("Has text")]
+ public async Task RestrictedHeight_VerticalAlign()
+ {
+ IControl text(VerticalAlignment verticalAlingnment, bool clip = true, bool restrictHeight = true)
+ {
+ return new Border()
+ {
+ BorderBrush = Brushes.Blue,
+ BorderThickness = new Thickness(1),
+ VerticalAlignment = VerticalAlignment.Center,
+ HorizontalAlignment = HorizontalAlignment.Center,
+ Height = restrictHeight ? 20 : double.NaN,
+ Margin = new Thickness(1),
+ Child = new TextBlock
+ {
+ FontFamily = new FontFamily("Courier New"),
+ Background = Brushes.Red,
+ FontSize = 24,
+ Foreground = Brushes.Black,
+ Text = "L",
+ VerticalAlignment = verticalAlingnment,
+ ClipToBounds = clip
+ }
+ };
+ }
+ Decorator target = new Decorator
+ {
+ Padding = new Thickness(8),
+ Width = 180,
+ Height = 80,
+
+ Child = new StackPanel()
+ {
+ Orientation = Orientation.Horizontal,
+ Children =
+ {
+ text(VerticalAlignment.Stretch, restrictHeight: false),
+ text(VerticalAlignment.Center),
+ text(VerticalAlignment.Stretch),
+ text(VerticalAlignment.Top),
+ text(VerticalAlignment.Bottom),
+ text(VerticalAlignment.Center, clip:false),
+ text(VerticalAlignment.Stretch, clip:false),
+ text(VerticalAlignment.Top, clip:false),
+ text(VerticalAlignment.Bottom, clip:false),
+ }
+ }
+ };
+
+ await RenderToFile(target);
+ CompareImages();
+ }
}
}
diff --git a/tests/Avalonia.RenderTests/Media/BitmapTests.cs b/tests/Avalonia.RenderTests/Media/BitmapTests.cs
index d52539c371..b629304b77 100644
--- a/tests/Avalonia.RenderTests/Media/BitmapTests.cs
+++ b/tests/Avalonia.RenderTests/Media/BitmapTests.cs
@@ -102,7 +102,9 @@ namespace Avalonia.Direct2D1.RenderTests.Media
[InlineData(PixelFormat.Bgra8888), InlineData(PixelFormat.Rgba8888)]
public void WriteableBitmapShouldBeUsable(PixelFormat fmt)
{
+#pragma warning disable CS0618 // Type or member is obsolete
var writeableBitmap = new WriteableBitmap(new PixelSize(256, 256), new Vector(96, 96), fmt);
+#pragma warning restore CS0618 // Type or member is obsolete
var data = new int[256 * 256];
for (int y = 0; y < 256; y++)
diff --git a/tests/Avalonia.RenderTests/Media/ConicGradientBrushTests.cs b/tests/Avalonia.RenderTests/Media/ConicGradientBrushTests.cs
new file mode 100644
index 0000000000..db69a0a028
--- /dev/null
+++ b/tests/Avalonia.RenderTests/Media/ConicGradientBrushTests.cs
@@ -0,0 +1,178 @@
+using Avalonia.Controls;
+using Avalonia.Media;
+using System.Threading.Tasks;
+using Xunit;
+
+#if AVALONIA_SKIA
+namespace Avalonia.Skia.RenderTests
+#else
+namespace Avalonia.Direct2D1.RenderTests.Media
+#endif
+{
+ public class ConicGradientBrushTests : TestBase
+ {
+ public ConicGradientBrushTests() : base(@"Media\ConicGradientBrush")
+ {
+ }
+
+ [Fact]
+ public async Task ConicGradientBrush_RedBlue()
+ {
+ Decorator target = new Decorator
+ {
+ Padding = new Thickness(8),
+ Width = 200,
+ Height = 200,
+ Child = new Border
+ {
+ Background = new ConicGradientBrush
+ {
+ GradientStops =
+ {
+ new GradientStop { Color = Colors.Red, Offset = 0 },
+ new GradientStop { Color = Colors.Blue, Offset = 1 }
+ }
+ }
+ }
+ };
+
+ await RenderToFile(target);
+ CompareImages();
+ }
+
+ [Fact]
+ public async Task ConicGradientBrush_RedBlue_Rotation()
+ {
+ Decorator target = new Decorator
+ {
+ Padding = new Thickness(8),
+ Width = 200,
+ Height = 200,
+ Child = new Border
+ {
+ Background = new ConicGradientBrush
+ {
+ GradientStops =
+ {
+ new GradientStop { Color = Colors.Red, Offset = 0 },
+ new GradientStop { Color = Colors.Blue, Offset = 1 }
+ },
+ Angle = 90
+ }
+ }
+ };
+
+ await RenderToFile(target);
+ CompareImages();
+ }
+
+ [Fact]
+ public async Task ConicGradientBrush_RedBlue_Center()
+ {
+ Decorator target = new Decorator
+ {
+ Padding = new Thickness(8),
+ Width = 200,
+ Height = 200,
+ Child = new Border
+ {
+ Background = new ConicGradientBrush
+ {
+ GradientStops =
+ {
+ new GradientStop { Color = Colors.Red, Offset = 0 },
+ new GradientStop { Color = Colors.Blue, Offset = 1 }
+ },
+ Center = new RelativePoint(0.25, 0.25, RelativeUnit.Relative)
+ }
+ }
+ };
+
+ await RenderToFile(target);
+ CompareImages();
+ }
+
+ [Fact]
+ public async Task ConicGradientBrush_RedBlue_Center_and_Rotation()
+ {
+ Decorator target = new Decorator
+ {
+ Padding = new Thickness(8),
+ Width = 200,
+ Height = 200,
+ Child = new Border
+ {
+ Background = new ConicGradientBrush
+ {
+ GradientStops =
+ {
+ new GradientStop { Color = Colors.Red, Offset = 0 },
+ new GradientStop { Color = Colors.Blue, Offset = 1 }
+ },
+ Center = new RelativePoint(0.25, 0.25, RelativeUnit.Relative),
+ Angle = 90
+ }
+ }
+ };
+
+ await RenderToFile(target);
+ CompareImages();
+ }
+
+ [Fact]
+ public async Task ConicGradientBrush_RedBlue_SoftEdge()
+ {
+ Decorator target = new Decorator
+ {
+ Padding = new Thickness(8),
+ Width = 200,
+ Height = 200,
+ Child = new Border
+ {
+ Background = new ConicGradientBrush
+ {
+ GradientStops =
+ {
+ new GradientStop { Color = Colors.Red, Offset = 0 },
+ new GradientStop { Color = Colors.Blue, Offset = 0.5 },
+ new GradientStop { Color = Colors.Red, Offset = 1 },
+ }
+ }
+ }
+ };
+
+ await RenderToFile(target);
+ CompareImages();
+ }
+
+ [Fact]
+ public async Task ConicGradientBrush_Umbrella()
+ {
+ Decorator target = new Decorator
+ {
+ Padding = new Thickness(8),
+ Width = 200,
+ Height = 200,
+ Child = new Border
+ {
+ Background = new ConicGradientBrush
+ {
+ GradientStops =
+ {
+ new GradientStop { Color = Colors.Red, Offset = 0 },
+ new GradientStop { Color = Colors.Yellow, Offset = 0.1667 },
+ new GradientStop { Color = Colors.Lime, Offset = 0.3333 },
+ new GradientStop { Color = Colors.Aqua, Offset = 0.5000 },
+ new GradientStop { Color = Colors.Blue, Offset = 0.6667 },
+ new GradientStop { Color = Colors.Magenta, Offset = 0.8333 },
+ new GradientStop { Color = Colors.Red, Offset = 1 },
+ }
+ }
+ }
+ };
+
+ await RenderToFile(target);
+ CompareImages();
+ }
+ }
+}
diff --git a/tests/Avalonia.RenderTests/Media/RadialGradientBrushTests.cs b/tests/Avalonia.RenderTests/Media/RadialGradientBrushTests.cs
index 9beb860bee..2941b8dc34 100644
--- a/tests/Avalonia.RenderTests/Media/RadialGradientBrushTests.cs
+++ b/tests/Avalonia.RenderTests/Media/RadialGradientBrushTests.cs
@@ -18,7 +18,7 @@ namespace Avalonia.Direct2D1.RenderTests.Media
public RadialGradientBrushTests() : base(@"Media\RadialGradientBrush")
{
}
-
+
[Fact]
public async Task RadialGradientBrush_RedBlue()
{
@@ -43,5 +43,127 @@ namespace Avalonia.Direct2D1.RenderTests.Media
await RenderToFile(target);
CompareImages();
}
+
+ ///
+ /// Tests using a GradientOrigin that falls inside of the circle described by Center/Radius.
+ ///
+ [Fact]
+ public async Task RadialGradientBrush_RedBlue_Offset_Inside()
+ {
+ Decorator target = new Decorator
+ {
+ Padding = new Thickness(8),
+ Width = 200,
+ Height = 200,
+ Child = new Border
+ {
+ Background = new RadialGradientBrush
+ {
+ GradientStops =
+ {
+ new GradientStop { Color = Colors.Red, Offset = 0 },
+ new GradientStop { Color = Colors.Blue, Offset = 1 }
+ },
+ GradientOrigin = new RelativePoint(0.25, 0.25, RelativeUnit.Relative)
+ }
+ }
+ };
+
+ await RenderToFile(target);
+ CompareImages();
+ }
+
+ ///
+ /// Tests using a GradientOrigin that falls outside of the circle described by Center/Radius.
+ ///
+ [Fact]
+ public async Task RadialGradientBrush_RedBlue_Offset_Outside()
+ {
+ Decorator target = new Decorator
+ {
+ Padding = new Thickness(8),
+ Width = 200,
+ Height = 200,
+ Child = new Border
+ {
+ Background = new RadialGradientBrush
+ {
+ GradientStops =
+ {
+ new GradientStop { Color = Colors.Red, Offset = 0 },
+ new GradientStop { Color = Colors.Blue, Offset = 1 }
+ },
+ GradientOrigin = new RelativePoint(0.1, 0.1, RelativeUnit.Relative)
+ }
+ }
+ };
+
+ await RenderToFile(target);
+ CompareImages();
+ }
+
+ ///
+ /// Tests using a GradientOrigin that falls inside of the circle described by Center/Radius.
+ ///
+ [Fact]
+ public async Task RadialGradientBrush_RedGreenBlue_Offset_Inside()
+ {
+ Decorator target = new Decorator
+ {
+ Padding = new Thickness(8),
+ Width = 200,
+ Height = 200,
+ Child = new Border
+ {
+ Background = new RadialGradientBrush
+ {
+ GradientStops =
+ {
+ new GradientStop { Color = Colors.Red, Offset = 0 },
+ new GradientStop { Color = Colors.Green, Offset = 0.5 },
+ new GradientStop { Color = Colors.Blue, Offset = 1 }
+ },
+ GradientOrigin = new RelativePoint(0.25, 0.25, RelativeUnit.Relative),
+ Center = new RelativePoint(0.5, 0.5, RelativeUnit.Relative),
+ Radius = 0.5
+ }
+ }
+ };
+
+ await RenderToFile(target);
+ CompareImages();
+ }
+
+ ///
+ /// Tests using a GradientOrigin that falls outside of the circle described by Center/Radius.
+ ///
+ [Fact]
+ public async Task RadialGradientBrush_RedGreenBlue_Offset_Outside()
+ {
+ Decorator target = new Decorator
+ {
+ Padding = new Thickness(8),
+ Width = 200,
+ Height = 200,
+ Child = new Border
+ {
+ Background = new RadialGradientBrush
+ {
+ GradientStops =
+ {
+ new GradientStop { Color = Colors.Red, Offset = 0 },
+ new GradientStop { Color = Colors.Green, Offset = 0.25 },
+ new GradientStop { Color = Colors.Blue, Offset = 1 }
+ },
+ GradientOrigin = new RelativePoint(0.1, 0.1, RelativeUnit.Relative),
+ Center = new RelativePoint(0.5, 0.5, RelativeUnit.Relative),
+ Radius = 0.5
+ }
+ }
+ };
+
+ await RenderToFile(target);
+ CompareImages();
+ }
}
}
diff --git a/tests/Avalonia.Skia.RenderTests/Avalonia.Skia.RenderTests.csproj b/tests/Avalonia.Skia.RenderTests/Avalonia.Skia.RenderTests.csproj
index 65df5e7cb0..14d0f4debf 100644
--- a/tests/Avalonia.Skia.RenderTests/Avalonia.Skia.RenderTests.csproj
+++ b/tests/Avalonia.Skia.RenderTests/Avalonia.Skia.RenderTests.csproj
@@ -29,4 +29,5 @@
+
diff --git a/tests/Avalonia.Skia.UnitTests/Avalonia.Skia.UnitTests.csproj b/tests/Avalonia.Skia.UnitTests/Avalonia.Skia.UnitTests.csproj
index 584eaf6fa9..ef69865e32 100644
--- a/tests/Avalonia.Skia.UnitTests/Avalonia.Skia.UnitTests.csproj
+++ b/tests/Avalonia.Skia.UnitTests/Avalonia.Skia.UnitTests.csproj
@@ -8,6 +8,7 @@
+
@@ -23,4 +24,4 @@
-
\ No newline at end of file
+
diff --git a/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextFormatterTests.cs b/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextFormatterTests.cs
index adcc79e029..7f9713930a 100644
--- a/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextFormatterTests.cs
+++ b/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextFormatterTests.cs
@@ -293,6 +293,34 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
}
}
+ [Fact]
+ public void Wrap_Should_Not_Produce_Empty_Lines()
+ {
+ using (Start())
+ {
+ const string text = "012345";
+
+ var defaultProperties = new GenericTextRunProperties(Typeface.Default);
+ var paragraphProperties = new GenericTextParagraphProperties(defaultProperties, textWrapping: TextWrapping.Wrap);
+ var textSource = new SingleBufferTextSource(text, defaultProperties);
+ var formatter = new TextFormatterImpl();
+
+ var textSourceIndex = 0;
+
+ while (textSourceIndex < text.Length)
+ {
+ var textLine =
+ formatter.FormatLine(textSource, textSourceIndex, 3, paragraphProperties);
+
+ Assert.NotEqual(0, textLine.TextRange.Length);
+
+ textSourceIndex += textLine.TextRange.Length;
+ }
+
+ Assert.Equal(text.Length, textSourceIndex);
+ }
+ }
+
public static IDisposable Start()
{
var disposable = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface
diff --git a/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLayoutTests.cs b/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLayoutTests.cs
index f3e1c37705..f7bc75c05d 100644
--- a/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLayoutTests.cs
+++ b/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLayoutTests.cs
@@ -417,7 +417,6 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
[Theory]
[InlineData("abcde\r\n", 7)] // Carriage Return + Line Feed
- [InlineData("abcde\n\r", 7)] // This isn't valid but we somehow have to support it.
[InlineData("abcde\u000A", 6)] // Line Feed
[InlineData("abcde\u000B", 6)] // Vertical Tab
[InlineData("abcde\u000C", 6)] // Form Feed
@@ -575,6 +574,45 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
}
}
+ [Fact]
+ public void Should_Process_Multiple_NewLines_Properly()
+ {
+ using (Start())
+ {
+ var text = "123\r\n\r\n456\r\n\r\n";
+ var layout = new TextLayout(
+ text,
+ Typeface.Default,
+ 12.0f,
+ Brushes.Black);
+
+ Assert.Equal(5, layout.TextLines.Count);
+
+ Assert.Equal("123\r\n", layout.TextLines[0].TextRuns[0].Text);
+ Assert.Equal("\r\n", layout.TextLines[1].TextRuns[0].Text);
+ Assert.Equal("456\r\n", layout.TextLines[2].TextRuns[0].Text);
+ Assert.Equal("\r\n", layout.TextLines[3].TextRuns[0].Text);
+ }
+ }
+
+ [Fact]
+ public void Should_Wrap_Min_OneCharacter_EveryLine()
+ {
+ using (Start())
+ {
+ var layout = new TextLayout(
+ s_singleLineText,
+ Typeface.Default,
+ 12,
+ Brushes.Black,
+ textWrapping: TextWrapping.Wrap,
+ maxWidth: 3);
+
+ //every character should be new line as there not enough space for even one character
+ Assert.Equal(s_singleLineText.Length, layout.TextLines.Count);
+ }
+ }
+
private static IDisposable Start()
{
var disposable = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface
diff --git a/tests/Avalonia.Styling.UnitTests/Avalonia.Styling.UnitTests.csproj b/tests/Avalonia.Styling.UnitTests/Avalonia.Styling.UnitTests.csproj
index 2b7f6263a7..a07ec050a6 100644
--- a/tests/Avalonia.Styling.UnitTests/Avalonia.Styling.UnitTests.csproj
+++ b/tests/Avalonia.Styling.UnitTests/Avalonia.Styling.UnitTests.csproj
@@ -11,6 +11,7 @@
+
diff --git a/tests/Avalonia.Styling.UnitTests/ResourceDictionaryTests.cs b/tests/Avalonia.Styling.UnitTests/ResourceDictionaryTests.cs
index 84b0d09b61..d91d1fab9e 100644
--- a/tests/Avalonia.Styling.UnitTests/ResourceDictionaryTests.cs
+++ b/tests/Avalonia.Styling.UnitTests/ResourceDictionaryTests.cs
@@ -108,7 +108,7 @@ namespace Avalonia.Styling.UnitTests
var target = new ResourceDictionary { { "foo", "bar" } };
((IResourceProvider)target).AddOwner(host.Object);
- host.ResetCalls();
+ host.Invocations.Clear();
((IResourceProvider)target).RemoveOwner(host.Object);
host.Verify(x => x.NotifyHostedResourcesChanged(It.IsAny()));
@@ -120,7 +120,7 @@ namespace Avalonia.Styling.UnitTests
var host = new Mock();
var target = new ResourceDictionary(host.Object);
- host.ResetCalls();
+ host.Invocations.Clear();
target.Add("foo", "bar");
host.Verify(x => x.NotifyHostedResourcesChanged(It.IsAny()));
@@ -132,7 +132,7 @@ namespace Avalonia.Styling.UnitTests
var host = new Mock();
var target = new ResourceDictionary(host.Object);
- host.ResetCalls();
+ host.Invocations.Clear();
target.MergedDictionaries.Add(new ResourceDictionary
{
{ "foo", "bar" },
@@ -149,7 +149,7 @@ namespace Avalonia.Styling.UnitTests
var host = new Mock();
var target = new ResourceDictionary(host.Object);
- host.ResetCalls();
+ host.Invocations.Clear();
target.MergedDictionaries.Add(new ResourceDictionary());
host.Verify(
@@ -169,7 +169,7 @@ namespace Avalonia.Styling.UnitTests
}
};
- host.ResetCalls();
+ host.Invocations.Clear();
target.MergedDictionaries.RemoveAt(0);
host.Verify(
@@ -189,7 +189,7 @@ namespace Avalonia.Styling.UnitTests
}
};
- host.ResetCalls();
+ host.Invocations.Clear();
((IResourceDictionary)target.MergedDictionaries[0]).Add("foo", "bar");
host.Verify(
diff --git a/tests/Avalonia.Styling.UnitTests/SelectorTests_Child.cs b/tests/Avalonia.Styling.UnitTests/SelectorTests_Child.cs
index 8ae556cc6f..d011c16ebb 100644
--- a/tests/Avalonia.Styling.UnitTests/SelectorTests_Child.cs
+++ b/tests/Avalonia.Styling.UnitTests/SelectorTests_Child.cs
@@ -1,12 +1,7 @@
-using System;
using System.Collections.Generic;
-using System.Linq;
-using System.Reactive;
using System.Reactive.Linq;
using System.Threading.Tasks;
-using Avalonia.Collections;
using Avalonia.Controls;
-using Avalonia.Data;
using Avalonia.LogicalTree;
using Xunit;
@@ -85,76 +80,6 @@ namespace Avalonia.Styling.UnitTests
get => Parent;
set => ((ISetLogicalParent)this).SetParent(value);
}
-
- public void ClearValue(AvaloniaProperty property)
- {
- throw new NotImplementedException();
- }
-
- public void ClearValue(AvaloniaProperty property)
- {
- throw new NotImplementedException();
- }
-
- public void AddInheritanceChild(IAvaloniaObject child)
- {
- throw new NotImplementedException();
- }
-
- public void RemoveInheritanceChild(IAvaloniaObject child)
- {
- throw new NotImplementedException();
- }
-
- public void InheritanceParentChanged(StyledPropertyBase property, IAvaloniaObject oldParent, IAvaloniaObject newParent)
- {
- throw new NotImplementedException();
- }
-
- public void InheritedPropertyChanged(AvaloniaProperty property, Optional oldValue, Optional newValue)
- {
- throw new NotImplementedException();
- }
-
- public void ClearValue(StyledPropertyBase property)
- {
- throw new NotImplementedException();
- }
-
- public void ClearValue(DirectPropertyBase property)
- {
- throw new NotImplementedException();
- }
-
- public T GetValue(StyledPropertyBase property)
- {
- throw new NotImplementedException();
- }
-
- public T GetValue(DirectPropertyBase property)
- {
- throw new NotImplementedException();
- }
-
- public void SetValue(StyledPropertyBase property, T value, BindingPriority priority = BindingPriority.LocalValue)
- {
- throw new NotImplementedException();
- }
-
- public void SetValue(DirectPropertyBase property, T value)
- {
- throw new NotImplementedException();
- }
-
- public IDisposable Bind(StyledPropertyBase property, IObservable> source, BindingPriority priority = BindingPriority.LocalValue)
- {
- throw new NotImplementedException();
- }
-
- public IDisposable Bind(DirectPropertyBase property, IObservable> source)
- {
- throw new NotImplementedException();
- }
}
public class TestLogical1 : TestLogical
diff --git a/tests/Avalonia.Styling.UnitTests/SelectorTests_Descendent.cs b/tests/Avalonia.Styling.UnitTests/SelectorTests_Descendent.cs
index 81485f0345..aacf2ce223 100644
--- a/tests/Avalonia.Styling.UnitTests/SelectorTests_Descendent.cs
+++ b/tests/Avalonia.Styling.UnitTests/SelectorTests_Descendent.cs
@@ -1,11 +1,7 @@
-using System;
using System.Linq;
-using System.Reactive;
using System.Reactive.Linq;
using System.Threading.Tasks;
-using Avalonia.Collections;
using Avalonia.Controls;
-using Avalonia.Data;
using Avalonia.LogicalTree;
using Xunit;
@@ -115,76 +111,6 @@ namespace Avalonia.Styling.UnitTests
get => Parent;
set => ((ISetLogicalParent)this).SetParent(value);
}
-
- public void ClearValue(AvaloniaProperty property)
- {
- throw new NotImplementedException();
- }
-
- public void ClearValue(AvaloniaProperty