diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 9a0da4aa9b..78b9cff039 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -1,16 +1,31 @@
-This template is not intended to be prescriptive, but to help us review pull requests it would be useful if you included as much of the following information as possible:
+## What does the pull request do?
-- What does the pull request do?
-- What is the current behavior?
-- What is the updated/expected behavior with this PR?
-- How was the solution implemented (if it's not obvious)?
+Give a bit of background on the PR here, together with links to with related issues etc.
-Checklist:
+## What is the current behavior?
+
+If the PR is a fix, describe the current incorrect behavior, otherwise delete this section.
+
+## What is the updated/expected behavior with this PR?
+
+Describe how to test the PR.
+
+## How was the solution implemented (if it's not obvious)?
+
+Include any information that might be of use to a reviewer here.
+
+## Checklist
- [ ] Added unit tests (if possible)?
- [ ] Added XML documentation to any related classes?
- [ ] Consider submitting a PR to https://github.com/AvaloniaUI/Avaloniaui.net with user documentation
+## Breaking changes
+
+List any breaking changes here. When the PR is merged please add an entry to https://github.com/AvaloniaUI/Avalonia/wiki/Breaking-Changes
+
+## Fixed issues
+
If the pull request fixes issue(s) list them like this:
Fixes #123
diff --git a/.gitignore b/.gitignore
index 6ee6057d5f..2b2c9c3d0d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -195,3 +195,4 @@ Logs/
ModuleCache.noindex/
Build/Intermediates.noindex/
info.plist
+build-intermediate
diff --git a/.gitmodules b/.gitmodules
index 2d2a9ac497..22c56307b0 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,6 @@
[submodule "src/Markup/Avalonia.Markup.Xaml/PortableXaml/portable.xaml.github"]
path = src/Markup/Avalonia.Markup.Xaml/PortableXaml/portable.xaml.github
url = https://github.com/AvaloniaUI/Portable.Xaml.git
+[submodule "nukebuild/Numerge"]
+ path = nukebuild/Numerge
+ url = https://github.com/kekekeks/Numerge.git
diff --git a/.ncrunch/Avalonia.Desktop.v3.ncrunchproject b/.ncrunch/Avalonia.Desktop.v3.ncrunchproject
new file mode 100644
index 0000000000..319cd523ce
--- /dev/null
+++ b/.ncrunch/Avalonia.Desktop.v3.ncrunchproject
@@ -0,0 +1,5 @@
+
+
+ True
+
+
\ No newline at end of file
diff --git a/.ncrunch/Avalonia.net461.v3.ncrunchproject b/.ncrunch/Avalonia.net461.v3.ncrunchproject
new file mode 100644
index 0000000000..319cd523ce
--- /dev/null
+++ b/.ncrunch/Avalonia.net461.v3.ncrunchproject
@@ -0,0 +1,5 @@
+
+
+ True
+
+
\ No newline at end of file
diff --git a/.nuke b/.nuke
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index b0c0c807cb..0000000000
--- a/.travis.yml
+++ /dev/null
@@ -1,24 +0,0 @@
-language: csharp
-os:
- - linux
-dist: trusty
-osx_image: xcode8.3
-env:
- global:
- - DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1
- - DOTNET_CLI_TELEMETRY_OPTOUT=1
-mono:
- - 5.2.0
-dotnet: 2.1.200
-script:
- - sudo apt-get update
- - sudo apt-get install castxml
- - ./build.sh --target "Travis" --configuration "Release"
-notifications:
- email: false
- webhooks:
- urls:
- - https://webhooks.gitter.im/e/98f653320ef2b7506c05
- on_success: change
- on_failure: always
- on_start: never
diff --git a/Avalonia.sln b/Avalonia.sln
index df60ff4a75..2f7560049c 100644
--- a/Avalonia.sln
+++ b/Avalonia.sln
@@ -1,3 +1,4 @@
+
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27130.2027
@@ -130,6 +131,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Props", "Props", "{F3AC8BC1
ProjectSection(SolutionItems) = preProject
build\Base.props = build\Base.props
build\Binding.props = build\Binding.props
+ build\BuildTargets.targets = build\BuildTargets.targets
build\JetBrains.Annotations.props = build\JetBrains.Annotations.props
build\JetBrains.dotMemoryUnit.props = build\JetBrains.dotMemoryUnit.props
build\Magick.NET-Q16-AnyCPU.props = build\Magick.NET-Q16-AnyCPU.props
@@ -147,7 +149,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Props", "Props", "{F3AC8BC1
build\Splat.props = build\Splat.props
build\System.Memory.props = build\System.Memory.props
build\XUnit.props = build\XUnit.props
- build\BuildTargets.targets = build\BuildTargets.targets
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Targets", "Targets", "{4D6FAF79-58B4-482F-9122-0668C346364C}"
@@ -189,7 +190,15 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia", "packages\Avalon
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Desktop", "src\Avalonia.Desktop\Avalonia.Desktop.csproj", "{3C471044-3640-45E3-B1B2-16D2FF8399EE}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Build.Tasks", "src\Avalonia.Build.Tasks\Avalonia.Build.Tasks.csproj", "{BF28998D-072C-439A-AFBB-2FE5021241E0}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Build.Tasks", "src\Avalonia.Build.Tasks\Avalonia.Build.Tasks.csproj", "{BF28998D-072C-439A-AFBB-2FE5021241E0}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "_build", "nukebuild\_build.csproj", "{3F00BC43-5095-477F-93D8-E65B08179A00}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Animation.UnitTests", "tests\Avalonia.Animation.UnitTests\Avalonia.Animation.UnitTests.csproj", "{AF227847-E65C-4BE9-BCE9-B551357788E0}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.X11", "src\Avalonia.X11\Avalonia.X11.csproj", "{41B02319-965D-4945-8005-C1A3D1224165}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PlatformSanityChecks", "samples\PlatformSanityChecks\PlatformSanityChecks.csproj", "{D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}"
EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
@@ -1714,6 +1723,102 @@ Global
{BF28998D-072C-439A-AFBB-2FE5021241E0}.Release|iPhone.Build.0 = Release|Any CPU
{BF28998D-072C-439A-AFBB-2FE5021241E0}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{BF28998D-072C-439A-AFBB-2FE5021241E0}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {3F00BC43-5095-477F-93D8-E65B08179A00}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
+ {3F00BC43-5095-477F-93D8-E65B08179A00}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
+ {3F00BC43-5095-477F-93D8-E65B08179A00}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
+ {3F00BC43-5095-477F-93D8-E65B08179A00}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU
+ {3F00BC43-5095-477F-93D8-E65B08179A00}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {3F00BC43-5095-477F-93D8-E65B08179A00}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU
+ {3F00BC43-5095-477F-93D8-E65B08179A00}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
+ {3F00BC43-5095-477F-93D8-E65B08179A00}.AppStore|Any CPU.Build.0 = Release|Any CPU
+ {3F00BC43-5095-477F-93D8-E65B08179A00}.AppStore|iPhone.ActiveCfg = Release|Any CPU
+ {3F00BC43-5095-477F-93D8-E65B08179A00}.AppStore|iPhone.Build.0 = Release|Any CPU
+ {3F00BC43-5095-477F-93D8-E65B08179A00}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {3F00BC43-5095-477F-93D8-E65B08179A00}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU
+ {3F00BC43-5095-477F-93D8-E65B08179A00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3F00BC43-5095-477F-93D8-E65B08179A00}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3F00BC43-5095-477F-93D8-E65B08179A00}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {3F00BC43-5095-477F-93D8-E65B08179A00}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {3F00BC43-5095-477F-93D8-E65B08179A00}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {3F00BC43-5095-477F-93D8-E65B08179A00}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {3F00BC43-5095-477F-93D8-E65B08179A00}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3F00BC43-5095-477F-93D8-E65B08179A00}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3F00BC43-5095-477F-93D8-E65B08179A00}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {3F00BC43-5095-477F-93D8-E65B08179A00}.Release|iPhone.Build.0 = Release|Any CPU
+ {3F00BC43-5095-477F-93D8-E65B08179A00}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {3F00BC43-5095-477F-93D8-E65B08179A00}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {AF227847-E65C-4BE9-BCE9-B551357788E0}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
+ {AF227847-E65C-4BE9-BCE9-B551357788E0}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
+ {AF227847-E65C-4BE9-BCE9-B551357788E0}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
+ {AF227847-E65C-4BE9-BCE9-B551357788E0}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
+ {AF227847-E65C-4BE9-BCE9-B551357788E0}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {AF227847-E65C-4BE9-BCE9-B551357788E0}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {AF227847-E65C-4BE9-BCE9-B551357788E0}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
+ {AF227847-E65C-4BE9-BCE9-B551357788E0}.AppStore|Any CPU.Build.0 = Debug|Any CPU
+ {AF227847-E65C-4BE9-BCE9-B551357788E0}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
+ {AF227847-E65C-4BE9-BCE9-B551357788E0}.AppStore|iPhone.Build.0 = Debug|Any CPU
+ {AF227847-E65C-4BE9-BCE9-B551357788E0}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {AF227847-E65C-4BE9-BCE9-B551357788E0}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {AF227847-E65C-4BE9-BCE9-B551357788E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {AF227847-E65C-4BE9-BCE9-B551357788E0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {AF227847-E65C-4BE9-BCE9-B551357788E0}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {AF227847-E65C-4BE9-BCE9-B551357788E0}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {AF227847-E65C-4BE9-BCE9-B551357788E0}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {AF227847-E65C-4BE9-BCE9-B551357788E0}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {AF227847-E65C-4BE9-BCE9-B551357788E0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {AF227847-E65C-4BE9-BCE9-B551357788E0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {AF227847-E65C-4BE9-BCE9-B551357788E0}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {AF227847-E65C-4BE9-BCE9-B551357788E0}.Release|iPhone.Build.0 = Release|Any CPU
+ {AF227847-E65C-4BE9-BCE9-B551357788E0}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {AF227847-E65C-4BE9-BCE9-B551357788E0}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {41B02319-965D-4945-8005-C1A3D1224165}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
+ {41B02319-965D-4945-8005-C1A3D1224165}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
+ {41B02319-965D-4945-8005-C1A3D1224165}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
+ {41B02319-965D-4945-8005-C1A3D1224165}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
+ {41B02319-965D-4945-8005-C1A3D1224165}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {41B02319-965D-4945-8005-C1A3D1224165}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {41B02319-965D-4945-8005-C1A3D1224165}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
+ {41B02319-965D-4945-8005-C1A3D1224165}.AppStore|Any CPU.Build.0 = Debug|Any CPU
+ {41B02319-965D-4945-8005-C1A3D1224165}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
+ {41B02319-965D-4945-8005-C1A3D1224165}.AppStore|iPhone.Build.0 = Debug|Any CPU
+ {41B02319-965D-4945-8005-C1A3D1224165}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {41B02319-965D-4945-8005-C1A3D1224165}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {41B02319-965D-4945-8005-C1A3D1224165}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {41B02319-965D-4945-8005-C1A3D1224165}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {41B02319-965D-4945-8005-C1A3D1224165}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {41B02319-965D-4945-8005-C1A3D1224165}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {41B02319-965D-4945-8005-C1A3D1224165}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {41B02319-965D-4945-8005-C1A3D1224165}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {41B02319-965D-4945-8005-C1A3D1224165}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {41B02319-965D-4945-8005-C1A3D1224165}.Release|Any CPU.Build.0 = Release|Any CPU
+ {41B02319-965D-4945-8005-C1A3D1224165}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {41B02319-965D-4945-8005-C1A3D1224165}.Release|iPhone.Build.0 = Release|Any CPU
+ {41B02319-965D-4945-8005-C1A3D1224165}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {41B02319-965D-4945-8005-C1A3D1224165}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
+ {D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
+ {D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
+ {D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
+ {D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
+ {D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.AppStore|Any CPU.Build.0 = Debug|Any CPU
+ {D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
+ {D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.AppStore|iPhone.Build.0 = Debug|Any CPU
+ {D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Release|iPhone.Build.0 = Release|Any CPU
+ {D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -1767,6 +1872,9 @@ Global
{E1240B49-7B4B-4371-A00E-068778C5CF0B} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{D49233F8-F29C-47DD-9975-C4C9E4502720} = {E870DCD7-F46A-498D-83FC-D0FD13E0A11C}
{3C471044-3640-45E3-B1B2-16D2FF8399EE} = {E870DCD7-F46A-498D-83FC-D0FD13E0A11C}
+ {AF227847-E65C-4BE9-BCE9-B551357788E0} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
+ {41B02319-965D-4945-8005-C1A3D1224165} = {86C53C40-57AA-45B8-AD42-FAE0EFDF0F2B}
+ {D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B} = {9B9E3891-2366-4253-A952-D08BCEB71098}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {87366D66-1391-4D90-8999-95A620AD786A}
diff --git a/Avalonia.v3.ncrunchsolution b/Avalonia.v3.ncrunchsolution
index 1b5b0c8930..a2208a9a91 100644
--- a/Avalonia.v3.ncrunchsolution
+++ b/Avalonia.v3.ncrunchsolution
@@ -2,6 +2,7 @@
tests\TestFiles\**.*
+ src\Avalonia.Build.Tasks\bin\Debug\netstandard2.0\Avalonia.Build.Tasks.dll
True
.ncrunch
diff --git a/Directory.Build.props b/Directory.Build.props
index 50476c81f1..1f26df9bbc 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -1,5 +1,5 @@
- $(MSBuildThisFileDirectory)artifacts/nuget
+ $(MSBuildThisFileDirectory)build-intermediate/nuget
diff --git a/appveyor.yml b/appveyor.yml
deleted file mode 100644
index 484fb4586f..0000000000
--- a/appveyor.yml
+++ /dev/null
@@ -1,23 +0,0 @@
-os: Visual Studio 2017
-skip_branch_with_pr: true
-configuration:
-- Release
-environment:
- DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1
- DOTNET_CLI_TELEMETRY_OPTOUT: 1
- NUGET_API_URL: https://www.nuget.org/api/v2/package
- MYGET_API_KEY:
- secure: OtVfyN3ErqQrDTnWH2HDfJDlCiu/i4/X4wFmK3ZXXP7HmCiXYPSbTjMPwwdOxRaK
- MYGET_API_URL: https://www.myget.org/F/avalonia-ci/api/v2/package
-init:
-- ps: if (Test-Path env:nuget_address) {[System.IO.File]::AppendAllText("C:\Windows\System32\drivers\etc\hosts", "`n$($env:nuget_address)`tapi.nuget.org")}
-before_build:
-- git submodule update --init
-build_script:
-- ps: .\build.ps1 -Target "AppVeyor" -Configuration "$env:configuration"
-
-test: off
-artifacts:
- - path: artifacts\nuget\*.nupkg
- - path: artifacts\zip\*.zip
- - path: artifacts\inspectcode.xml
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index f6929f8dee..39333f37ba 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -11,19 +11,18 @@ jobs:
sudo apt-get install castxml
- task: CmdLine@2
- displayName: 'Install Cake'
+ displayName: 'Install Nuke'
inputs:
script: |
- dotnet tool install -g Cake.Tool --version 0.30.0
-
+ dotnet tool install --global Nuke.GlobalTool --version 0.12.3
- task: CmdLine@2
- displayName: 'Run Cake'
+ displayName: 'Run Nuke'
inputs:
script: |
export PATH="$PATH:$HOME/.dotnet/tools"
dotnet --info
printenv
- dotnet cake build.cake -target="Azure-Linux" -configuration="Release"
+ nuke --target CiAzureLinux --configuration=Release
- task: PublishTestResults@2
inputs:
@@ -39,6 +38,13 @@ jobs:
inputs:
version: '2.1.403'
+ - task: CmdLine@2
+ displayName: 'Install Mono 5.18'
+ inputs:
+ script: |
+ 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: Xcode@5
inputs:
actions: 'build'
@@ -52,16 +58,18 @@ jobs:
- task: CmdLine@2
displayName: 'Install CastXML'
inputs:
- script: brew install castxml
+ script: |
+ brew update
+ brew install castxml
- task: CmdLine@2
- displayName: 'Install Cake'
+ displayName: 'Install Nuke'
inputs:
script: |
- dotnet tool install -g Cake.Tool --version 0.30.0
+ dotnet tool install --global Nuke.GlobalTool --version 0.12.3
- task: CmdLine@2
- displayName: 'Run Cake'
+ displayName: 'Run Nuke'
inputs:
script: |
export COREHOST_TRACE=0
@@ -72,7 +80,7 @@ jobs:
export PATH="$PATH:$HOME/.dotnet/tools"
dotnet --info
printenv
- dotnet cake build.cake -target="Azure-OSX" -configuration="Release"
+ nuke --target CiAzureOSX --configuration Release
- task: PublishTestResults@2
inputs:
@@ -84,30 +92,30 @@ jobs:
inputs:
pathToPublish: '$(Build.SourcesDirectory)/Build/Products/Release/'
artifactName: 'Avalonia.Native.OSX'
- condition: and(succeeded(), eq(variables['system.pullrequest.isfork'], false))
+ condition: succeeded()
- task: PublishBuildArtifacts@1
inputs:
pathtoPublish: '$(Build.SourcesDirectory)/artifacts/nuget'
artifactName: 'NuGetOSX'
- condition: and(succeeded(), eq(variables['system.pullrequest.isfork'], false))
+ condition: succeeded()
- job: Windows
pool:
vmImage: 'vs2017-win2016'
steps:
- task: CmdLine@2
- displayName: 'Install Cake'
+ displayName: 'Install Nuke'
inputs:
script: |
- dotnet tool install -g Cake.Tool --version 0.30.0
+ dotnet tool install --global Nuke.GlobalTool --version 0.12.3
- task: CmdLine@2
- displayName: 'Run Cake'
+ displayName: 'Run Nuke'
inputs:
script: |
set PATH=%PATH%;%USERPROFILE%\.dotnet\tools
- dotnet cake build.cake -target="Azure-Windows" -configuration="Release"
+ nuke --target CiAzureWindows --configuration Release
- task: PublishTestResults@2
inputs:
@@ -119,10 +127,10 @@ jobs:
inputs:
pathtoPublish: '$(Build.SourcesDirectory)/artifacts/nuget'
artifactName: 'NuGet'
- condition: and(succeeded(), eq(variables['system.pullrequest.isfork'], false))
+ condition: succeeded()
- task: PublishBuildArtifacts@1
inputs:
pathToPublish: '$(Build.SourcesDirectory)/artifacts/zip'
artifactName: 'Samples'
- condition: and(succeeded(), eq(variables['system.pullrequest.isfork'], false))
+ condition: succeeded()
diff --git a/build.cake b/build.cake
deleted file mode 100644
index f10a12c4e6..0000000000
--- a/build.cake
+++ /dev/null
@@ -1,312 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-// TOOLS
-///////////////////////////////////////////////////////////////////////////////
-
-#tool "nuget:?package=NuGet.CommandLine&version=4.7.1"
-#tool "nuget:?package=JetBrains.ReSharper.CommandLineTools&version=2018.2.3"
-#tool "nuget:?package=xunit.runner.console&version=2.3.1"
-#tool "nuget:?package=JetBrains.dotMemoryUnit&version=3.0.20171219.105559"
-
-///////////////////////////////////////////////////////////////////////////////
-// USINGS
-///////////////////////////////////////////////////////////////////////////////
-
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Linq;
-
-///////////////////////////////////////////////////////////////////////////////
-// SCRIPTS
-///////////////////////////////////////////////////////////////////////////////
-
-#load "./parameters.cake"
-
-///////////////////////////////////////////////////////////////////////////////
-// SETUP
-///////////////////////////////////////////////////////////////////////////////
-
-Setup(context =>
-{
- var parameters = new Parameters(context);
-
- Information("Building version {0} of Avalonia ({1}) using version {2} of Cake.",
- parameters.Version,
- parameters.Configuration,
- typeof(ICakeContext).Assembly.GetName().Version.ToString());
-
- if (parameters.IsRunningOnAppVeyor)
- {
- Information("Repository Name: " + BuildSystem.AppVeyor.Environment.Repository.Name);
- Information("Repository Branch: " + BuildSystem.AppVeyor.Environment.Repository.Branch);
- }
- Information("Target:" + context.TargetTask.Name);
- Information("Configuration: " + parameters.Configuration);
- Information("IsLocalBuild: " + parameters.IsLocalBuild);
- Information("IsRunningOnUnix: " + parameters.IsRunningOnUnix);
- Information("IsRunningOnWindows: " + parameters.IsRunningOnWindows);
- Information("IsRunningOnAppVeyor: " + parameters.IsRunningOnAppVeyor);
- Information("IsRunnongOnAzure:" + parameters.IsRunningOnAzure);
- Information("IsPullRequest: " + parameters.IsPullRequest);
- Information("IsMainRepo: " + parameters.IsMainRepo);
- Information("IsMasterBranch: " + parameters.IsMasterBranch);
- Information("IsReleaseBranch: " + parameters.IsReleaseBranch);
- Information("IsTagged: " + parameters.IsTagged);
- Information("IsReleasable: " + parameters.IsReleasable);
- Information("IsMyGetRelease: " + parameters.IsMyGetRelease);
- Information("IsNuGetRelease: " + parameters.IsNuGetRelease);
-
- return parameters;
-});
-
-///////////////////////////////////////////////////////////////////////////////
-// TEARDOWN
-///////////////////////////////////////////////////////////////////////////////
-
-Teardown((context, buildContext) =>
-{
- Information("Finished running tasks.");
-});
-
-///////////////////////////////////////////////////////////////////////////////
-// TASKS
-///////////////////////////////////////////////////////////////////////////////
-
-Task("Clean-Impl")
- .Does(data =>
-{
- CleanDirectories(data.BuildDirs);
- CleanDirectory(data.ArtifactsDir);
- CleanDirectory(data.NugetRoot);
- CleanDirectory(data.ZipRoot);
- CleanDirectory(data.TestResultsRoot);
-});
-
-void DotNetCoreBuild(Parameters parameters)
-{
- var settings = new DotNetCoreBuildSettings
- {
- Configuration = parameters.Configuration,
- MSBuildSettings = new DotNetCoreMSBuildSettings
- {
- Properties =
- {
- { "PackageVersion", new [] { parameters.Version } }
- }
- }
- };
-
- DotNetCoreBuild(parameters.MSBuildSolution, settings);
-}
-
-Task("Build-Impl")
- .Does(data =>
-{
- if(data.IsRunningOnWindows)
- {
- MSBuild(data.MSBuildSolution, settings => {
- settings.SetConfiguration(data.Configuration);
- settings.SetVerbosity(Verbosity.Minimal);
- settings.WithProperty("iOSRoslynPathHackRequired", "true");
- settings.WithProperty("PackageVersion", data.Version);
- settings.UseToolVersion(MSBuildToolVersion.VS2017);
- settings.WithRestore();
- });
- }
- else
- {
- DotNetCoreBuild(data);
- }
-});
-
-void RunCoreTest(string project, Parameters parameters, bool coreOnly = false)
-{
- if(!project.EndsWith(".csproj"))
- project = System.IO.Path.Combine(project, System.IO.Path.GetFileName(project)+".csproj");
- Information("Running tests from " + project);
- var frameworks = new List(){"netcoreapp2.0"};
- foreach(var fw in frameworks)
- {
- if(!fw.StartsWith("netcoreapp") && coreOnly)
- continue;
- Information("Running for " + fw);
-
- var settings = new DotNetCoreTestSettings {
- Configuration = parameters.Configuration,
- Framework = fw,
- NoBuild = true,
- NoRestore = true
- };
-
- if (parameters.PublishTestResults)
- {
- settings.Logger = "trx";
- settings.ResultsDirectory = parameters.TestResultsRoot;
- }
-
- DotNetCoreTest(project, settings);
- }
-}
-
-Task("Run-Unit-Tests-Impl")
- .WithCriteria((context, data) => !data.SkipTests)
- .Does(data =>
-{
- RunCoreTest("./tests/Avalonia.Base.UnitTests", data, false);
- RunCoreTest("./tests/Avalonia.Controls.UnitTests", data, false);
- RunCoreTest("./tests/Avalonia.Input.UnitTests", data, false);
- RunCoreTest("./tests/Avalonia.Interactivity.UnitTests", data, false);
- RunCoreTest("./tests/Avalonia.Layout.UnitTests", data, false);
- RunCoreTest("./tests/Avalonia.Markup.UnitTests", data, false);
- RunCoreTest("./tests/Avalonia.Markup.Xaml.UnitTests", data, false);
- RunCoreTest("./tests/Avalonia.Styling.UnitTests", data, false);
- RunCoreTest("./tests/Avalonia.Visuals.UnitTests", data, false);
- RunCoreTest("./tests/Avalonia.Skia.UnitTests", data, false);
- RunCoreTest("./tests/Avalonia.ReactiveUI.UnitTests", data, false);
- if (data.IsRunningOnWindows)
- {
- RunCoreTest("./tests/Avalonia.Direct2D1.UnitTests", data, false);
- }
-});
-
-Task("Run-Designer-Tests-Impl")
- .WithCriteria((context, data) => !data.SkipTests)
- .Does(data =>
-{
- RunCoreTest("./tests/Avalonia.DesignerSupport.Tests", data, false);
-});
-
-Task("Run-Render-Tests-Impl")
- .WithCriteria((context, data) => !data.SkipTests)
- .WithCriteria((context, data) => data.IsRunningOnWindows)
- .Does(data =>
-{
- RunCoreTest("./tests/Avalonia.Skia.RenderTests/Avalonia.Skia.RenderTests.csproj", data, true);
- RunCoreTest("./tests/Avalonia.Direct2D1.RenderTests/Avalonia.Direct2D1.RenderTests.csproj", data, true);
-});
-
-Task("Run-Leak-Tests-Impl")
- .WithCriteria((context, data) => !data.SkipTests)
- .WithCriteria((context, data) => data.IsRunningOnWindows)
- .Does(() =>
-{
- var dotMemoryUnit = Context.Tools.Resolve("dotMemoryUnit.exe");
- var leakTestsExitCode = StartProcess(dotMemoryUnit, new ProcessSettings
- {
- Arguments = new ProcessArgumentBuilder()
- .Append(Context.Tools.Resolve("xunit.console.x86.exe").FullPath)
- .Append("--propagate-exit-code")
- .Append("--")
- .Append("tests\\Avalonia.LeakTests\\bin\\Release\\net461\\Avalonia.LeakTests.dll"),
- Timeout = 120000
- });
-
- if (leakTestsExitCode != 0)
- {
- throw new Exception("Leak Tests failed");
- }
-});
-
-Task("Zip-Files-Impl")
- .Does(data =>
-{
- Zip(data.BinRoot, data.ZipCoreArtifacts);
-
- Zip(data.NugetRoot, data.ZipNuGetArtifacts);
-
- Zip(data.ZipSourceControlCatalogDesktopDirs,
- data.ZipTargetControlCatalogDesktopDirs,
- GetFiles(data.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.dll") +
- GetFiles(data.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.config") +
- GetFiles(data.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.so") +
- GetFiles(data.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.dylib") +
- GetFiles(data.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.exe"));
-});
-
-void DotNetCorePack(Parameters parameters)
-{
- var settings = new DotNetCorePackSettings
- {
- Configuration = parameters.Configuration,
- MSBuildSettings = new DotNetCoreMSBuildSettings
- {
- Properties =
- {
- { "PackageVersion", new [] { parameters.Version } }
- }
- }
- };
-
- DotNetCorePack(parameters.MSBuildSolution, settings);
-}
-
-Task("Create-NuGet-Packages-Impl")
- .Does(data =>
-{
- if(data.IsRunningOnWindows)
- {
- MSBuild(data.MSBuildSolution, settings => {
- settings.SetConfiguration(data.Configuration);
- settings.SetVerbosity(Verbosity.Minimal);
- settings.WithProperty("iOSRoslynPathHackRequired", "true");
- settings.WithProperty("PackageVersion", data.Version);
- settings.UseToolVersion(MSBuildToolVersion.VS2017);
- settings.WithRestore();
- settings.WithTarget("Pack");
- });
- }
- else
- {
- DotNetCorePack(data);
- }
-});
-
-///////////////////////////////////////////////////////////////////////////////
-// TARGETS
-///////////////////////////////////////////////////////////////////////////////
-
-Task("Build")
- .IsDependentOn("Clean-Impl")
- .IsDependentOn("Build-Impl");
-
-Task("Run-Tests")
- .IsDependentOn("Build")
- .IsDependentOn("Run-Unit-Tests-Impl")
- .IsDependentOn("Run-Render-Tests-Impl")
- .IsDependentOn("Run-Designer-Tests-Impl")
- .IsDependentOn("Run-Leak-Tests-Impl");
-
-Task("Package")
- .IsDependentOn("Run-Tests")
- .IsDependentOn("Create-NuGet-Packages-Impl");
-
-Task("AppVeyor")
- .IsDependentOn("Package")
- .IsDependentOn("Zip-Files-Impl");
-
-Task("Travis")
- .IsDependentOn("Run-Tests");
-
-Task("Azure-Linux")
- .IsDependentOn("Run-Tests");
-
-Task("Azure-OSX")
- .IsDependentOn("Package")
- .IsDependentOn("Zip-Files-Impl");
-
-Task("Azure-Windows")
- .IsDependentOn("Package")
- .IsDependentOn("Zip-Files-Impl");
-
-///////////////////////////////////////////////////////////////////////////////
-// EXECUTE
-///////////////////////////////////////////////////////////////////////////////
-
-var target = Context.Argument("target", "Default");
-
-if (target == "Default")
-{
- target = Context.IsRunningOnWindows() ? "Package" : "Run-Tests";
-}
-
-RunTarget(target);
diff --git a/build.ps1 b/build.ps1
index 46696db2b2..57e2f80075 100644
--- a/build.ps1
+++ b/build.ps1
@@ -1,201 +1,69 @@
-##########################################################################
-# This is the Cake bootstrapper script for PowerShell.
-# This file was downloaded from https://github.com/cake-build/resources
-# Feel free to change this file to fit your needs.
-##########################################################################
-
-<#
-
-.SYNOPSIS
-This is a Powershell script to bootstrap a Cake build.
-
-.DESCRIPTION
-This Powershell script will download NuGet if missing, restore NuGet tools (including Cake)
-and execute your Cake build script with the parameters you provide.
-
-.PARAMETER Script
-The build script to execute.
-.PARAMETER Target
-The build script target to run.
-.PARAMETER Platform
-The build platform to use.
-.PARAMETER Configuration
-The build configuration to use.
-.PARAMETER Verbosity
-Specifies the amount of information to be displayed.
-.PARAMETER Experimental
-Tells Cake to use the latest Roslyn release.
-.PARAMETER WhatIf
-Performs a dry run of the build script.
-No tasks will be executed.
-.PARAMETER Mono
-Tells Cake to use the Mono scripting engine.
-.PARAMETER SkipToolPackageRestore
-Skips restoring of packages.
-.PARAMETER SkipTests
-Skips unit tests
-.PARAMETER ScriptArgs
-Remaining arguments are added here.
-
-.LINK
-http://cakebuild.net
-
-#>
-
[CmdletBinding()]
Param(
- [string]$Script = "build.cake",
- [string]$Target = "Default",
- [ValidateSet("Any CPU", "x86", "x64", "NetCoreOnly", "iPhone")]
- [string]$Platform = "Any CPU",
- [ValidateSet("Release", "Debug")]
- [string]$Configuration = "Release",
- [ValidateSet("Quiet", "Minimal", "Normal", "Verbose", "Diagnostic")]
- [string]$Verbosity = "Verbose",
- [switch]$Experimental,
- [Alias("DryRun","Noop")]
- [switch]$WhatIf,
- [switch]$Mono,
- [switch]$SkipToolPackageRestore,
+ #[switch]$CustomParam,
[Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)]
- [string[]]$ScriptArgs
+ [string[]]$BuildArguments
)
-[Reflection.Assembly]::LoadWithPartialName("System.Security") | Out-Null
-function MD5HashFile([string] $filePath)
-{
- if ([string]::IsNullOrEmpty($filePath) -or !(Test-Path $filePath -PathType Leaf))
- {
- return $null
- }
-
- [System.IO.Stream] $file = $null;
- [System.Security.Cryptography.MD5] $md5 = $null;
- try
- {
- $md5 = [System.Security.Cryptography.MD5]::Create()
- $file = [System.IO.File]::OpenRead($filePath)
- return [System.BitConverter]::ToString($md5.ComputeHash($file))
- }
- finally
- {
- if ($file -ne $null)
- {
- $file.Dispose()
- }
- }
-}
-
-Write-Host "Preparing to run build script..."
-
-if(!$PSScriptRoot){
- $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent
-}
+Write-Output "Windows PowerShell $($Host.Version)"
-$TOOLS_DIR = Join-Path $PSScriptRoot "tools"
-$NUGET_EXE = Join-Path $TOOLS_DIR "nuget.exe"
-$CAKE_EXE = Join-Path $TOOLS_DIR "Cake/Cake.exe"
-$NUGET_URL = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe"
-$PACKAGES_CONFIG = Join-Path $TOOLS_DIR "packages.config"
-$PACKAGES_CONFIG_MD5 = Join-Path $TOOLS_DIR "packages.config.md5sum"
+Set-StrictMode -Version 2.0; $ErrorActionPreference = "Stop"; $ConfirmPreference = "None"; trap { exit 1 }
+$PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent
-# Should we use mono?
-$UseMono = "";
-if($Mono.IsPresent) {
- Write-Verbose -Message "Using the Mono based scripting engine."
- $UseMono = "-mono"
-}
+###########################################################################
+# CONFIGURATION
+###########################################################################
-# Should we use the new Roslyn?
-$UseExperimental = "";
-if($Experimental.IsPresent -and !($Mono.IsPresent)) {
- Write-Verbose -Message "Using experimental version of Roslyn."
- $UseExperimental = "-experimental"
-}
+$BuildProjectFile = "$PSScriptRoot\nukebuild\_build.csproj"
+$TempDirectory = "$PSScriptRoot\\.tmp"
-# Is this a dry run?
-$UseDryRun = "";
-if($WhatIf.IsPresent) {
- $UseDryRun = "-dryrun"
-}
+$DotNetGlobalFile = "$PSScriptRoot\\global.json"
+$DotNetInstallUrl = "https://raw.githubusercontent.com/dotnet/cli/master/scripts/obtain/dotnet-install.ps1"
+$DotNetChannel = "Current"
-# Is this a dry run?
-$UseSkipTests = "";
-if($SkipTests.IsPresent) {
- $UseSkipTests = "-skip-tests"
-}
+$env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE = 1
+$env:DOTNET_CLI_TELEMETRY_OPTOUT = 1
+$env:NUGET_XMLDOC_MODE = "skip"
-# Make sure tools folder exists
-if ((Test-Path $PSScriptRoot) -and !(Test-Path $TOOLS_DIR)) {
- Write-Verbose -Message "Creating tools directory..."
- New-Item -Path $TOOLS_DIR -Type directory | out-null
-}
+###########################################################################
+# EXECUTION
+###########################################################################
-# Make sure that packages.config exist.
-if (!(Test-Path $PACKAGES_CONFIG)) {
- Write-Verbose -Message "Downloading packages.config..."
- try { (New-Object System.Net.WebClient).DownloadFile("http://cakebuild.net/download/bootstrapper/packages", $PACKAGES_CONFIG) } catch {
- Throw "Could not download packages.config."
- }
+function ExecSafe([scriptblock] $cmd) {
+ & $cmd
+ if ($LASTEXITCODE) { exit $LASTEXITCODE }
}
-# Try find NuGet.exe in path if not exists
-if (!(Test-Path $NUGET_EXE)) {
- Write-Verbose -Message "Trying to find nuget.exe in PATH..."
- $existingPaths = $Env:Path -Split ';' | Where-Object { (![string]::IsNullOrEmpty($_)) -and (Test-Path $_) }
- $NUGET_EXE_IN_PATH = Get-ChildItem -Path $existingPaths -Filter "nuget.exe" | Select -First 1
- if ($NUGET_EXE_IN_PATH -ne $null -and (Test-Path $NUGET_EXE_IN_PATH.FullName)) {
- Write-Verbose -Message "Found in PATH at $($NUGET_EXE_IN_PATH.FullName)."
- $NUGET_EXE = $NUGET_EXE_IN_PATH.FullName
+# If global.json exists, load expected version
+if (Test-Path $DotNetGlobalFile) {
+ $DotNetGlobal = $(Get-Content $DotNetGlobalFile | Out-String | ConvertFrom-Json)
+ if ($DotNetGlobal.PSObject.Properties["sdk"] -and $DotNetGlobal.sdk.PSObject.Properties["version"]) {
+ $DotNetVersion = $DotNetGlobal.sdk.version
}
}
-# Try download NuGet.exe if not exists
-if (!(Test-Path $NUGET_EXE)) {
- Write-Verbose -Message "Downloading NuGet.exe..."
- try {
- (New-Object System.Net.WebClient).DownloadFile($NUGET_URL, $NUGET_EXE)
- } catch {
- Throw "Could not download NuGet.exe."
- }
+# 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 `
+ (!(Test-Path variable:DotNetVersion) -or $(& dotnet --version) -eq $DotNetVersion)) {
+ $env:DOTNET_EXE = (Get-Command "dotnet").Path
}
-
-# Save nuget.exe path to environment to be available to child processed
-$ENV:NUGET_EXE = $NUGET_EXE
-
-# Restore tools from NuGet?
-if(-Not $SkipToolPackageRestore.IsPresent) {
- Push-Location
- Set-Location $TOOLS_DIR
-
- # Check for changes in packages.config and remove installed tools if true.
- [string] $md5Hash = MD5HashFile($PACKAGES_CONFIG)
- if((!(Test-Path $PACKAGES_CONFIG_MD5)) -Or
- ($md5Hash -ne (Get-Content $PACKAGES_CONFIG_MD5 ))) {
- Write-Verbose -Message "Missing or changed package.config hash..."
- Remove-Item * -Recurse -Exclude packages.config,nuget.exe
+else {
+ $DotNetDirectory = "$TempDirectory\dotnet-win"
+ $env:DOTNET_EXE = "$DotNetDirectory\dotnet.exe"
+
+ # Download install script
+ $DotNetInstallFile = "$TempDirectory\dotnet-install.ps1"
+ md -force $TempDirectory > $null
+ (New-Object System.Net.WebClient).DownloadFile($DotNetInstallUrl, $DotNetInstallFile)
+
+ # Install by channel or version
+ if (!(Test-Path variable:DotNetVersion)) {
+ ExecSafe { & $DotNetInstallFile -InstallDir $DotNetDirectory -Channel $DotNetChannel -NoPath }
+ } else {
+ ExecSafe { & $DotNetInstallFile -InstallDir $DotNetDirectory -Version $DotNetVersion -NoPath }
}
-
- Write-Verbose -Message "Restoring tools from NuGet..."
- $NuGetOutput = Invoke-Expression "&`"$NUGET_EXE`" install -ExcludeVersion -OutputDirectory `"$TOOLS_DIR`""
-
- if ($LASTEXITCODE -ne 0) {
- Throw "An error occured while restoring NuGet tools."
- }
- else
- {
- $md5Hash | Out-File $PACKAGES_CONFIG_MD5 -Encoding "ASCII"
- }
- Write-Verbose -Message ($NuGetOutput | out-string)
- Pop-Location
}
-# Make sure that Cake has been installed.
-if (!(Test-Path $CAKE_EXE)) {
- Throw "Could not find Cake.exe at $CAKE_EXE"
-}
+Write-Output "Microsoft (R) .NET Core SDK version $(& $env:DOTNET_EXE --version)"
-# Start Cake
-Write-Host "Running build script..."
-Invoke-Expression "& `"$CAKE_EXE`" `"$Script`" -target=`"$Target`" -platform=`"$Platform`" -configuration=`"$Configuration`" -verbosity=`"$Verbosity`" $UseSkipTests $UseMono $UseDryRun $UseExperimental $ScriptArgs"
-exit $LASTEXITCODE
\ No newline at end of file
+ExecSafe { & $env:DOTNET_EXE run --project $BuildProjectFile -- $BuildArguments }
diff --git a/build.sh b/build.sh
index 206a55d171..40b1c225a6 100755
--- a/build.sh
+++ b/build.sh
@@ -1,105 +1,72 @@
#!/usr/bin/env bash
-##########################################################################
-# This is the Cake bootstrapper script for Linux and OS X.
-# This file was downloaded from https://github.com/cake-build/resources
-# Feel free to change this file to fit your needs.
-##########################################################################
+echo $(bash --version 2>&1 | head -n 1)
-# Define directories.
-SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
-TOOLS_DIR=$SCRIPT_DIR/tools
-NUGET_EXE=$TOOLS_DIR/nuget.exe
-CAKE_EXE=$TOOLS_DIR/Cake/Cake.exe
-PACKAGES_CONFIG=$TOOLS_DIR/packages.config
-PACKAGES_CONFIG_MD5=$TOOLS_DIR/packages.config.md5sum
-
-# Define md5sum or md5 depending on Linux/OSX
-MD5_EXE=
-if [[ "$(uname -s)" == "Darwin" ]]; then
- MD5_EXE="md5 -r"
-else
- MD5_EXE="md5sum"
-fi
-
-# Define default arguments.
-SCRIPT="build.cake"
-TARGET="Default"
-CONFIGURATION="Release"
-PLATFORM="Any CPU"
-VERBOSITY="verbose"
-DRYRUN=
-SKIP_TESTS=
-SHOW_VERSION=false
-SCRIPT_ARGUMENTS=()
-
-# Parse arguments.
+#CUSTOMPARAM=0
+BUILD_ARGUMENTS=()
for i in "$@"; do
- case $1 in
- -s|--script) SCRIPT="$2"; shift ;;
- -t|--target) TARGET="$2"; shift ;;
- -p|--platform) PLATFORM="$2"; shift ;;
- -c|--configuration) CONFIGURATION="$2"; shift ;;
- --skip-tests) SKIP_TESTS="-skip-tests"; shift ;;
- -v|--verbosity) VERBOSITY="$2"; shift ;;
- -d|--dryrun) DRYRUN="-dryrun" ;;
- --version) SHOW_VERSION=true ;;
- --) shift; SCRIPT_ARGUMENTS+=("$@"); break ;;
- *) SCRIPT_ARGUMENTS+=("$1") ;;
+ case $(echo $1 | awk '{print tolower($0)}') in
+ # -custom-param) CUSTOMPARAM=1;;
+ *) BUILD_ARGUMENTS+=("$1") ;;
esac
shift
done
-# Make sure the tools folder exist.
-if [ ! -d "$TOOLS_DIR" ]; then
- mkdir "$TOOLS_DIR"
-fi
+set -eo pipefail
+SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)
-# Make sure that packages.config exist.
-if [ ! -f "$TOOLS_DIR/packages.config" ]; then
- echo "Downloading packages.config..."
- curl -Lsfo "$TOOLS_DIR/packages.config" http://cakebuild.net/download/bootstrapper/packages
- if [ $? -ne 0 ]; then
- echo "An error occured while downloading packages.config."
- exit 1
- fi
-fi
+###########################################################################
+# CONFIGURATION
+###########################################################################
-# Download NuGet if it does not exist.
-if [ ! -f "$NUGET_EXE" ]; then
- echo "Downloading NuGet..."
- curl -Lsfo "$NUGET_EXE" https://dist.nuget.org/win-x86-commandline/latest/nuget.exe
- if [ $? -ne 0 ]; then
- echo "An error occured while downloading nuget.exe."
- exit 1
- fi
-fi
+BUILD_PROJECT_FILE="$SCRIPT_DIR/nukebuild/_build.csproj"
+TEMP_DIRECTORY="$SCRIPT_DIR//.tmp"
-# Restore tools from NuGet.
-pushd "$TOOLS_DIR" >/dev/null
-if [ ! -f $PACKAGES_CONFIG_MD5 ] || [ "$( cat $PACKAGES_CONFIG_MD5 | sed 's/\r$//' )" != "$( $MD5_EXE $PACKAGES_CONFIG | awk '{ print $1 }' )" ]; then
- find . -type d ! -name . | xargs rm -rf
-fi
+DOTNET_GLOBAL_FILE="$SCRIPT_DIR//global.json"
+DOTNET_INSTALL_URL="https://raw.githubusercontent.com/dotnet/cli/master/scripts/obtain/dotnet-install.sh"
+DOTNET_CHANNEL="Current"
-mono "$NUGET_EXE" install -ExcludeVersion
-if [ $? -ne 0 ]; then
- echo "Could not restore NuGet packages."
- exit 1
-fi
+export DOTNET_CLI_TELEMETRY_OPTOUT=1
+export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1
+export NUGET_XMLDOC_MODE="skip"
-$MD5_EXE $PACKAGES_CONFIG | awk '{ print $1 }' >| $PACKAGES_CONFIG_MD5
+###########################################################################
+# EXECUTION
+###########################################################################
-popd >/dev/null
+function FirstJsonValue {
+ perl -nle 'print $1 if m{"'$1'": "([^"\-]+)",?}' <<< ${@:2}
+}
-# Make sure that Cake has been installed.
-if [ ! -f "$CAKE_EXE" ]; then
- echo "Could not find Cake.exe at '$CAKE_EXE'."
- exit 1
+# If global.json exists, load expected version
+if [ -f "$DOTNET_GLOBAL_FILE" ]; then
+ DOTNET_VERSION=$(FirstJsonValue "version" $(cat "$DOTNET_GLOBAL_FILE"))
+ if [ "$DOTNET_VERSION" == "" ]; then
+ unset DOTNET_VERSION
+ fi
fi
-# Start Cake
-if $SHOW_VERSION; then
- exec mono "$CAKE_EXE" -version
+# 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
+ export DOTNET_EXE="$(command -v dotnet)"
else
- exec mono "$CAKE_EXE" $SCRIPT -verbosity=$VERBOSITY -platform="$PLATFORM" -configuration="$CONFIGURATION" -target=$TARGET $DRYRUN $SKIP_TESTS "${SCRIPT_ARGUMENTS[@]}"
+ DOTNET_DIRECTORY="$TEMP_DIRECTORY/dotnet-unix"
+ export DOTNET_EXE="$DOTNET_DIRECTORY/dotnet"
+
+ # Download install script
+ DOTNET_INSTALL_FILE="$TEMP_DIRECTORY/dotnet-install.sh"
+ mkdir -p "$TEMP_DIRECTORY"
+ curl -Lsfo "$DOTNET_INSTALL_FILE" "$DOTNET_INSTALL_URL"
+ chmod +x "$DOTNET_INSTALL_FILE"
+
+ # Install by channel or version
+ if [ -z ${DOTNET_VERSION+x} ]; then
+ "$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --channel "$DOTNET_CHANNEL" --no-path
+ else
+ "$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --version "$DOTNET_VERSION" --no-path
+ fi
fi
+
+echo "Microsoft (R) .NET Core SDK version $("$DOTNET_EXE" --version)"
+
+"$DOTNET_EXE" run --project "$BUILD_PROJECT_FILE" -- ${BUILD_ARGUMENTS[@]}
diff --git a/build/Magick.NET-Q16-AnyCPU.props b/build/Magick.NET-Q16-AnyCPU.props
index 4e600a1c11..21d9cdcb1f 100644
--- a/build/Magick.NET-Q16-AnyCPU.props
+++ b/build/Magick.NET-Q16-AnyCPU.props
@@ -1,5 +1,5 @@
-
+
diff --git a/build/NetFX.props b/build/NetFX.props
index d8b2daf13a..4d2841714b 100644
--- a/build/NetFX.props
+++ b/build/NetFX.props
@@ -3,4 +3,9 @@
/usr/lib/mono/4.6.1-api
/Library/Frameworks/Mono.framework/Versions/Current/lib/mono/4.6.1-api
+
+ /usr/lib/mono/4.7-api/
+ /Library/Frameworks/Mono.framework/Versions/Current/lib/mono/4.7-api
+
+
diff --git a/build/ReferenceCoreLibraries.props b/build/ReferenceCoreLibraries.props
index bd9d6ad843..cffc2e0324 100644
--- a/build/ReferenceCoreLibraries.props
+++ b/build/ReferenceCoreLibraries.props
@@ -1,5 +1,4 @@
-
diff --git a/build/SkiaSharp.props b/build/SkiaSharp.props
index 35c979a95e..a43c99e978 100644
--- a/build/SkiaSharp.props
+++ b/build/SkiaSharp.props
@@ -1,6 +1,6 @@
-
-
+
+
diff --git a/build/UnitTests.NetFX.props b/build/UnitTests.NetFX.props
new file mode 100644
index 0000000000..e9a29d80fe
--- /dev/null
+++ b/build/UnitTests.NetFX.props
@@ -0,0 +1,8 @@
+
+
+
+
+ PreserveNewest
+
+
+
diff --git a/build/xunit.runner.mono.json b/build/xunit.runner.mono.json
new file mode 100644
index 0000000000..4fb88b54c6
--- /dev/null
+++ b/build/xunit.runner.mono.json
@@ -0,0 +1 @@
+{ "appDomain": "denied" }
diff --git a/cake.config b/cake.config
deleted file mode 100644
index 8089cd4084..0000000000
--- a/cake.config
+++ /dev/null
@@ -1,15 +0,0 @@
-; This is the default configuration file for Cake.
-; This file was downloaded from https://github.com/cake-build/resources
-
-[Nuget]
-Source=https://api.nuget.org/v3/index.json
-UseInProcessClient=true
-LoadDependencies=false
-
-[Paths]
-Tools=./tools
-Addins=./tools/Addins
-Modules=./tools/Modules
-
-[Settings]
-SkipVerification=false
diff --git a/global.json b/global.json
index d11e78bd7f..6d12c28846 100644
--- a/global.json
+++ b/global.json
@@ -1,7 +1,7 @@
{
"msbuild-sdks": {
"Microsoft.Build.Traversal": "1.0.43",
- "MSBuild.Sdk.Extras": "1.6.46",
+ "MSBuild.Sdk.Extras": "1.6.65",
"AggregatePackage.NuGet.Sdk" : "0.1.12"
}
}
diff --git a/native/Avalonia.Native/src/OSX/gl.mm b/native/Avalonia.Native/src/OSX/gl.mm
index a62098a074..083adc927d 100644
--- a/native/Avalonia.Native/src/OSX/gl.mm
+++ b/native/Avalonia.Native/src/OSX/gl.mm
@@ -208,9 +208,8 @@ public:
virtual ~AvnGlRenderingSession()
{
- glFlush();
[_context flushBuffer];
- [_context setView:nil];
+ [NSOpenGLContext clearCurrentContext];
CGLUnlockContext([_context CGLContextObj]);
[_view unlockFocus];
}
@@ -241,9 +240,8 @@ public:
auto gl = _context;
CGLLockContext([_context CGLContextObj]);
[gl setView: _view];
+ [gl update];
[gl makeCurrentContext];
- auto frame = [_view frame];
-
*ret = new AvnGlRenderingSession(_window, _view, gl);
return S_OK;
}
diff --git a/native/Avalonia.Native/src/OSX/window.mm b/native/Avalonia.Native/src/OSX/window.mm
index ae00bde780..ef5dcb5b2e 100644
--- a/native/Avalonia.Native/src/OSX/window.mm
+++ b/native/Avalonia.Native/src/OSX/window.mm
@@ -425,7 +425,7 @@ private:
[[Window parentWindow] removeChildWindow:Window];
WindowBaseImpl::Show();
- return SetWindowState(_lastWindowState);
+ return SetWindowState(Normal);
}
}
@@ -1184,6 +1184,25 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
}
}
+- (void)windowDidMiniaturize:(NSNotification *)notification
+{
+ auto parent = dynamic_cast(_parent.operator->());
+
+ if(parent != nullptr)
+ {
+ parent->WindowStateChanged();
+ }
+}
+
+- (void)windowDidDeminiaturize:(NSNotification *)notification
+{
+ auto parent = dynamic_cast(_parent.operator->());
+
+ if(parent != nullptr)
+ {
+ parent->WindowStateChanged();
+ }
+}
- (BOOL)windowShouldZoom:(NSWindow *)window toFrame:(NSRect)newFrame
{
diff --git a/nukebuild/.editorconfig b/nukebuild/.editorconfig
new file mode 100644
index 0000000000..d6009b3c0f
--- /dev/null
+++ b/nukebuild/.editorconfig
@@ -0,0 +1,8 @@
+# editorconfig.org
+
+# top-most EditorConfig file
+root = false
+
+# C# files
+[*.cs]
+dotnet_style_require_accessibility_modifiers = never
diff --git a/nukebuild/Build.cs b/nukebuild/Build.cs
new file mode 100644
index 0000000000..bb31034299
--- /dev/null
+++ b/nukebuild/Build.cs
@@ -0,0 +1,265 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Threading;
+using System.Xml.Linq;
+using Nuke.Common;
+using Nuke.Common.Git;
+using Nuke.Common.ProjectModel;
+using Nuke.Common.Tooling;
+using Nuke.Common.Tools.DotNet;
+using Nuke.Common.Tools.MSBuild;
+using Nuke.Common.Utilities;
+using static Nuke.Common.EnvironmentInfo;
+using static Nuke.Common.IO.FileSystemTasks;
+using static Nuke.Common.IO.PathConstruction;
+using static Nuke.Common.Tools.MSBuild.MSBuildTasks;
+using static Nuke.Common.Tools.DotNet.DotNetTasks;
+using static Nuke.Common.Tools.Xunit.XunitTasks;
+
+
+/*
+ Before editing this file, install support plugin for your IDE,
+ running and debugging a particular target (optionally without deps) would be way easier
+ ReSharper/Rider - https://plugins.jetbrains.com/plugin/10803-nuke-support
+ VSCode - https://marketplace.visualstudio.com/items?itemName=nuke.support
+
+ */
+
+partial class Build : NukeBuild
+{
+ BuildParameters Parameters { get; set; }
+ protected override void OnBuildInitialized()
+ {
+ Parameters = new BuildParameters(this);
+ Information("Building version {0} of Avalonia ({1}) using version {2} of Nuke.",
+ Parameters.Version,
+ Parameters.Configuration,
+ typeof(NukeBuild).Assembly.GetName().Version.ToString());
+
+ if (Parameters.IsLocalBuild)
+ {
+ Information("Repository Name: " + Parameters.RepositoryName);
+ Information("Repository Branch: " + Parameters.RepositoryBranch);
+ }
+ Information("Configuration: " + Parameters.Configuration);
+ Information("IsLocalBuild: " + Parameters.IsLocalBuild);
+ Information("IsRunningOnUnix: " + Parameters.IsRunningOnUnix);
+ Information("IsRunningOnWindows: " + Parameters.IsRunningOnWindows);
+ Information("IsRunningOnAzure:" + Parameters.IsRunningOnAzure);
+ Information("IsPullRequest: " + Parameters.IsPullRequest);
+ Information("IsMainRepo: " + Parameters.IsMainRepo);
+ Information("IsMasterBranch: " + Parameters.IsMasterBranch);
+ Information("IsReleaseBranch: " + Parameters.IsReleaseBranch);
+ Information("IsReleasable: " + Parameters.IsReleasable);
+ Information("IsMyGetRelease: " + Parameters.IsMyGetRelease);
+ Information("IsNuGetRelease: " + Parameters.IsNuGetRelease);
+
+ void ExecWait(string preamble, string command, string args)
+ {
+ Console.WriteLine(preamble);
+ Process.Start(new ProcessStartInfo(command, args) {UseShellExecute = false}).WaitForExit();
+ }
+ ExecWait("dotnet version:", "dotnet", "--version");
+ if (Parameters.IsRunningOnUnix)
+ ExecWait("Mono version:", "mono", "--version");
+
+
+ }
+
+ Target Clean => _ => _.Executes(() =>
+ {
+ DeleteDirectories(Parameters.BuildDirs);
+ EnsureCleanDirectories(Parameters.BuildDirs);
+ EnsureCleanDirectory(Parameters.ArtifactsDir);
+ EnsureCleanDirectory(Parameters.NugetIntermediateRoot);
+ EnsureCleanDirectory(Parameters.NugetRoot);
+ EnsureCleanDirectory(Parameters.ZipRoot);
+ EnsureCleanDirectory(Parameters.TestResultsRoot);
+ });
+
+ Target Compile => _ => _
+ .DependsOn(Clean)
+ .Executes(() =>
+ {
+
+ if (Parameters.IsRunningOnWindows)
+ MSBuild(Parameters.MSBuildSolution, c => c
+ .SetArgumentConfigurator(a => a.Add("/r"))
+ .SetConfiguration(Parameters.Configuration)
+ .SetVerbosity(MSBuildVerbosity.Minimal)
+ .AddProperty("PackageVersion", Parameters.Version)
+ .AddProperty("iOSRoslynPathHackRequired", "true")
+ .SetToolsVersion(MSBuildToolsVersion._15_0)
+ .AddTargets("Build")
+ );
+
+ else
+ DotNetBuild(Parameters.MSBuildSolution, c => c
+ .AddProperty("PackageVersion", Parameters.Version)
+ .SetConfiguration(Parameters.Configuration)
+ );
+ });
+
+ void RunCoreTest(string project)
+ {
+ if(!project.EndsWith(".csproj"))
+ project = System.IO.Path.Combine(project, System.IO.Path.GetFileName(project)+".csproj");
+ Information("Running tests from " + project);
+ XDocument xdoc;
+ using (var s = File.OpenRead(project))
+ xdoc = XDocument.Load(s);
+
+ List frameworks = null;
+ var targets = xdoc.Root.Descendants("TargetFrameworks").FirstOrDefault();
+ if (targets != null)
+ frameworks = targets.Value.Split(';').Where(f => !string.IsNullOrWhiteSpace(f)).ToList();
+ else
+ frameworks = new List {xdoc.Root.Descendants("TargetFramework").First().Value};
+
+ foreach(var fw in frameworks)
+ {
+ Information("Running for " + fw);
+ DotNetTest(c =>
+ {
+ c = c
+ .SetProjectFile(project)
+ .SetConfiguration(Parameters.Configuration)
+ .SetFramework(fw)
+ .EnableNoBuild()
+ .EnableNoRestore();
+ // NOTE: I can see that we could maybe add another extension method "Switch" or "If" to make this more convenient
+ if (Parameters.PublishTestResults)
+ c = c.SetLogger("trx").SetResultsDirectory(Parameters.TestResultsRoot);
+ return c;
+ });
+ }
+ }
+
+ Target RunCoreLibsTests => _ => _
+ .OnlyWhen(() => !Parameters.SkipTests)
+ .DependsOn(Compile)
+ .Executes(() =>
+ {
+ RunCoreTest("./tests/Avalonia.Animation.UnitTests");
+ RunCoreTest("./tests/Avalonia.Base.UnitTests");
+ RunCoreTest("./tests/Avalonia.Controls.UnitTests");
+ RunCoreTest("./tests/Avalonia.Input.UnitTests");
+ RunCoreTest("./tests/Avalonia.Interactivity.UnitTests");
+ RunCoreTest("./tests/Avalonia.Layout.UnitTests");
+ RunCoreTest("./tests/Avalonia.Markup.UnitTests");
+ RunCoreTest("./tests/Avalonia.Markup.Xaml.UnitTests");
+ RunCoreTest("./tests/Avalonia.Styling.UnitTests");
+ RunCoreTest("./tests/Avalonia.Visuals.UnitTests");
+ RunCoreTest("./tests/Avalonia.Skia.UnitTests");
+ RunCoreTest("./tests/Avalonia.ReactiveUI.UnitTests");
+ });
+
+ Target RunRenderTests => _ => _
+ .OnlyWhen(() => !Parameters.SkipTests)
+ .DependsOn(Compile)
+ .Executes(() =>
+ {
+ RunCoreTest("./tests/Avalonia.Skia.RenderTests/Avalonia.Skia.RenderTests.csproj");
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ RunCoreTest("./tests/Avalonia.Direct2D1.RenderTests/Avalonia.Direct2D1.RenderTests.csproj");
+ });
+
+ Target RunDesignerTests => _ => _
+ .OnlyWhen(() => !Parameters.SkipTests && Parameters.IsRunningOnWindows)
+ .DependsOn(Compile)
+ .Executes(() =>
+ {
+ RunCoreTest("./tests/Avalonia.DesignerSupport.Tests");
+ });
+
+ [PackageExecutable("JetBrains.dotMemoryUnit", "dotMemoryUnit.exe")] readonly Tool DotMemoryUnit;
+
+ Target RunLeakTests => _ => _
+ .OnlyWhen(() => !Parameters.SkipTests && Parameters.IsRunningOnWindows)
+ .DependsOn(Compile)
+ .Executes(() =>
+ {
+ var testAssembly = "tests\\Avalonia.LeakTests\\bin\\Release\\net461\\Avalonia.LeakTests.dll";
+ DotMemoryUnit(
+ $"{XunitPath.DoubleQuoteIfNeeded()} --propagate-exit-code -- {testAssembly}",
+ timeout: 120_000);
+ });
+
+ Target ZipFiles => _ => _
+ .After(CreateNugetPackages, Compile, RunCoreLibsTests, Package)
+ .Executes(() =>
+ {
+ var data = Parameters;
+ Zip(data.ZipCoreArtifacts, data.BinRoot);
+ Zip(data.ZipNuGetArtifacts, data.NugetRoot);
+ Zip(data.ZipTargetControlCatalogDesktopDir,
+ GlobFiles(data.ZipSourceControlCatalogDesktopDir, "*.dll").Concat(
+ GlobFiles(data.ZipSourceControlCatalogDesktopDir, "*.config")).Concat(
+ GlobFiles(data.ZipSourceControlCatalogDesktopDir, "*.so")).Concat(
+ GlobFiles(data.ZipSourceControlCatalogDesktopDir, "*.dylib")).Concat(
+ GlobFiles(data.ZipSourceControlCatalogDesktopDir, "*.exe")));
+ });
+
+ Target CreateIntermediateNugetPackages => _ => _
+ .DependsOn(Compile)
+ .After(RunTests)
+ .Executes(() =>
+ {
+ if (Parameters.IsRunningOnWindows)
+
+ MSBuild(Parameters.MSBuildSolution, c => c
+ .SetConfiguration(Parameters.Configuration)
+ .SetVerbosity(MSBuildVerbosity.Minimal)
+ .AddProperty("PackageVersion", Parameters.Version)
+ .AddProperty("iOSRoslynPathHackRequired", "true")
+ .SetToolsVersion(MSBuildToolsVersion._15_0)
+ .AddTargets("Pack"));
+ else
+ DotNetPack(Parameters.MSBuildSolution, c =>
+ c.SetConfiguration(Parameters.Configuration)
+ .AddProperty("PackageVersion", Parameters.Version));
+ });
+
+ Target CreateNugetPackages => _ => _
+ .DependsOn(CreateIntermediateNugetPackages)
+ .Executes(() =>
+ {
+ var config = Numerge.MergeConfiguration.LoadFile(RootDirectory / "nukebuild" / "numerge.config");
+ EnsureCleanDirectory(Parameters.NugetRoot);
+ if(!Numerge.NugetPackageMerger.Merge(Parameters.NugetIntermediateRoot, Parameters.NugetRoot, config,
+ new NumergeNukeLogger()))
+ throw new Exception("Package merge failed");
+ });
+
+ Target RunTests => _ => _
+ .DependsOn(RunCoreLibsTests)
+ .DependsOn(RunRenderTests)
+ .DependsOn(RunDesignerTests)
+ .DependsOn(RunLeakTests);
+
+ Target Package => _ => _
+ .DependsOn(RunTests)
+ .DependsOn(CreateNugetPackages);
+
+ Target CiAzureLinux => _ => _
+ .DependsOn(RunTests);
+
+ Target CiAzureOSX => _ => _
+ .DependsOn(Package)
+ .DependsOn(ZipFiles);
+
+ Target CiAzureWindows => _ => _
+ .DependsOn(Package)
+ .DependsOn(ZipFiles);
+
+
+ public static int Main() =>
+ RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
+ ? Execute(x => x.Package)
+ : Execute(x => x.RunTests);
+
+}
diff --git a/nukebuild/BuildParameters.cs b/nukebuild/BuildParameters.cs
new file mode 100644
index 0000000000..afd1950859
--- /dev/null
+++ b/nukebuild/BuildParameters.cs
@@ -0,0 +1,142 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Xml.Linq;
+using Nuke.Common;
+using Nuke.Common.BuildServers;
+using Nuke.Common.Execution;
+using Nuke.Common.IO;
+using static Nuke.Common.IO.FileSystemTasks;
+using static Nuke.Common.IO.PathConstruction;
+using static Nuke.Common.Tools.MSBuild.MSBuildTasks;
+
+public partial class Build
+{
+ [Parameter("configuration")]
+ public string Configuration { get; set; }
+
+ [Parameter("skip-tests")]
+ public bool SkipTests { get; set; }
+
+ [Parameter("force-nuget-version")]
+ public string ForceNugetVersion { get; set; }
+
+ public class BuildParameters
+ {
+ public string Configuration { get; }
+ public bool SkipTests { get; }
+ public string MainRepo { get; }
+ public string MasterBranch { get; }
+ public string RepositoryName { get; }
+ public string RepositoryBranch { get; }
+ public string ReleaseConfiguration { get; }
+ public string ReleaseBranchPrefix { get; }
+ public string MSBuildSolution { get; }
+ public bool IsLocalBuild { get; }
+ public bool IsRunningOnUnix { get; }
+ public bool IsRunningOnWindows { get; }
+ public bool IsRunningOnAzure { get; }
+ public bool IsPullRequest { get; }
+ public bool IsMainRepo { get; }
+ public bool IsMasterBranch { get; }
+ public bool IsReleaseBranch { get; }
+ public bool IsReleasable { get; }
+ public bool IsMyGetRelease { get; }
+ public bool IsNuGetRelease { get; }
+ public bool PublishTestResults { get; }
+ public string Version { get; }
+ public AbsolutePath ArtifactsDir { get; }
+ public AbsolutePath NugetIntermediateRoot { get; }
+ public AbsolutePath NugetRoot { get; }
+ public AbsolutePath ZipRoot { get; }
+ public AbsolutePath BinRoot { get; }
+ public AbsolutePath TestResultsRoot { get; }
+ public string DirSuffix { get; }
+ public List BuildDirs { get; }
+ public string FileZipSuffix { get; }
+ public AbsolutePath ZipCoreArtifacts { get; }
+ public AbsolutePath ZipNuGetArtifacts { get; }
+ public AbsolutePath ZipSourceControlCatalogDesktopDir { get; }
+ public AbsolutePath ZipTargetControlCatalogDesktopDir { get; }
+
+
+ public BuildParameters(Build b)
+ {
+ // ARGUMENTS
+ Configuration = b.Configuration ?? "Release";
+ SkipTests = b.SkipTests;
+
+ // CONFIGURATION
+ MainRepo = "https://github.com/AvaloniaUI/Avalonia";
+ MasterBranch = "refs/heads/master";
+ ReleaseBranchPrefix = "refs/heads/release/";
+ ReleaseConfiguration = "Release";
+ MSBuildSolution = RootDirectory / "dirs.proj";
+
+ // PARAMETERS
+ IsLocalBuild = Host == HostType.Console;
+ IsRunningOnUnix = Environment.OSVersion.Platform == PlatformID.Unix ||
+ Environment.OSVersion.Platform == PlatformID.MacOSX;
+ IsRunningOnWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
+ IsRunningOnAzure = Host == HostType.TeamServices ||
+ Environment.GetEnvironmentVariable("LOGNAME") == "vsts";
+
+ if (IsRunningOnAzure)
+ {
+ RepositoryName = TeamServices.Instance.RepositoryUri;
+ RepositoryBranch = TeamServices.Instance.SourceBranch;
+ IsPullRequest = TeamServices.Instance.PullRequestId.HasValue;
+ IsMainRepo = StringComparer.OrdinalIgnoreCase.Equals(MainRepo, TeamServices.Instance.RepositoryUri);
+ }
+ IsMainRepo =
+ StringComparer.OrdinalIgnoreCase.Equals(MainRepo,
+ RepositoryName);
+ IsMasterBranch = StringComparer.OrdinalIgnoreCase.Equals(MasterBranch,
+ RepositoryBranch);
+ IsReleaseBranch = RepositoryBranch?.StartsWith(ReleaseBranchPrefix, StringComparison.OrdinalIgnoreCase) ==
+ true;
+
+ IsReleasable = StringComparer.OrdinalIgnoreCase.Equals(ReleaseConfiguration, Configuration);
+ IsMyGetRelease = IsReleasable;
+ IsNuGetRelease = IsMainRepo && IsReleasable && IsReleaseBranch;
+
+ // VERSION
+ Version = b.ForceNugetVersion ?? GetVersion();
+
+ if (IsRunningOnAzure)
+ {
+ if (!IsNuGetRelease)
+ {
+ // Use AssemblyVersion with Build as version
+ Version += "-build" + Environment.GetEnvironmentVariable("BUILD_BUILDID") + "-beta";
+ }
+
+ PublishTestResults = true;
+ }
+
+ // DIRECTORIES
+ ArtifactsDir = RootDirectory / "artifacts";
+ NugetRoot = ArtifactsDir / "nuget";
+ NugetIntermediateRoot = RootDirectory / "build-intermediate" / "nuget";
+ ZipRoot = ArtifactsDir / "zip";
+ BinRoot = ArtifactsDir / "bin";
+ TestResultsRoot = ArtifactsDir / "test-results";
+ BuildDirs = GlobDirectories(RootDirectory, "**bin").Concat(GlobDirectories(RootDirectory, "**obj")).ToList();
+ DirSuffix = Configuration;
+ FileZipSuffix = Version + ".zip";
+ ZipCoreArtifacts = ZipRoot / ("Avalonia-" + FileZipSuffix);
+ ZipNuGetArtifacts = ZipRoot / ("Avalonia-NuGet-" + FileZipSuffix);
+ ZipSourceControlCatalogDesktopDir =
+ RootDirectory / ("samples/ControlCatalog.Desktop/bin/" + DirSuffix + "/net461");
+ ZipTargetControlCatalogDesktopDir = ZipRoot / ("ControlCatalog.Desktop-" + FileZipSuffix);
+ }
+
+ string GetVersion()
+ {
+ var xdoc = XDocument.Load(RootDirectory / "build/SharedVersion.props");
+ return xdoc.Descendants().First(x => x.Name.LocalName == "Version").Value;
+ }
+ }
+
+}
diff --git a/nukebuild/Numerge b/nukebuild/Numerge
new file mode 160000
index 0000000000..4464343aef
--- /dev/null
+++ b/nukebuild/Numerge
@@ -0,0 +1 @@
+Subproject commit 4464343aef5c8ab7a42fcb20a483a6058199f8b8
diff --git a/nukebuild/Shims.cs b/nukebuild/Shims.cs
new file mode 100644
index 0000000000..461d617643
--- /dev/null
+++ b/nukebuild/Shims.cs
@@ -0,0 +1,93 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.IO.Compression;
+using System.Linq;
+using Nuke.Common;
+using Nuke.Common.IO;
+using Numerge;
+
+public partial class Build
+{
+ static void Information(string info)
+ {
+ Logger.Info(info);
+ }
+
+ static void Information(string info, params object[] args)
+ {
+ Logger.Info(info, args);
+ }
+
+ private void Zip(PathConstruction.AbsolutePath target, params string[] paths) => Zip(target, paths.AsEnumerable());
+
+ private void Zip(PathConstruction.AbsolutePath target, IEnumerable paths)
+ {
+ var targetPath = target.ToString();
+ bool finished = false, atLeastOneFileAdded = false;
+ try
+ {
+ using (var targetStream = File.Create(targetPath))
+ using(var archive = new System.IO.Compression.ZipArchive(targetStream, ZipArchiveMode.Create))
+ {
+ void AddFile(string path, string relativePath)
+ {
+ var e = archive.CreateEntry(relativePath.Replace("\\", "/"), CompressionLevel.Optimal);
+ using (var entryStream = e.Open())
+ using (var fileStream = File.OpenRead(path))
+ fileStream.CopyTo(entryStream);
+ atLeastOneFileAdded = true;
+ }
+
+ foreach (var path in paths)
+ {
+ if (Directory.Exists(path))
+ {
+ var dirInfo = new DirectoryInfo(path);
+ var rootPath = Path.GetDirectoryName(dirInfo.FullName);
+ foreach(var fsEntry in dirInfo.EnumerateFileSystemInfos("*", SearchOption.AllDirectories))
+ {
+ if (fsEntry is FileInfo)
+ {
+ var relPath = Path.GetRelativePath(rootPath, fsEntry.FullName);
+ AddFile(fsEntry.FullName, relPath);
+ }
+ }
+ }
+ else if(File.Exists(path))
+ {
+ var name = Path.GetFileName(path);
+ AddFile(path, name);
+ }
+ }
+ }
+
+ finished = true;
+ }
+ finally
+ {
+ try
+ {
+ if (!finished || !atLeastOneFileAdded)
+ File.Delete(targetPath);
+ }
+ catch
+ {
+ //Ignore
+ }
+ }
+ }
+
+ class NumergeNukeLogger : INumergeLogger
+ {
+ public void Log(NumergeLogLevel level, string message)
+ {
+ if(level == NumergeLogLevel.Error)
+ Logger.Error(message);
+ else if (level == NumergeLogLevel.Warning)
+ Logger.Warn(message);
+ else
+ Logger.Info(message);
+ }
+ }
+}
diff --git a/nukebuild/_build.csproj b/nukebuild/_build.csproj
new file mode 100644
index 0000000000..e02acff007
--- /dev/null
+++ b/nukebuild/_build.csproj
@@ -0,0 +1,37 @@
+
+
+
+ Exe
+ netcoreapp2.0
+ false
+
+ False
+ CS0649;CS0169
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/nukebuild/_build.csproj.DotSettings b/nukebuild/_build.csproj.DotSettings
new file mode 100644
index 0000000000..9aac7d8e8d
--- /dev/null
+++ b/nukebuild/_build.csproj.DotSettings
@@ -0,0 +1,24 @@
+
+ False
+ Implicit
+ Implicit
+ ExpressionBody
+ 0
+ NEXT_LINE
+ True
+ False
+ 120
+ IF_OWNER_IS_SINGLE_LINE
+ WRAP_IF_LONG
+ False
+ <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
+ <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
diff --git a/nukebuild/numerge.config b/nukebuild/numerge.config
new file mode 100644
index 0000000000..e4e15d693d
--- /dev/null
+++ b/nukebuild/numerge.config
@@ -0,0 +1,23 @@
+{
+ "Packages":
+ [
+ {
+ "Id": "Avalonia",
+ "MergeAll": true,
+ "Exclude": ["Avalonia.Remote.Protocol"],
+ "IncomingIncludeAssetsOverride": "",
+ "Merge": [
+ {
+ "Id": "Avalonia.Build.Tasks",
+ "IgnoreMissingFrameworkBinaries": true,
+ "DoNotMergeDependencies": true
+ },
+ {
+ "Id": "Avalonia.DesktopRuntime",
+ "IgnoreMissingFrameworkBinaries": true,
+ "IgnoreMissingFrameworkDependencies": true
+ }
+ ]
+ }
+ ]
+}
diff --git a/packages/Avalonia/Avalonia.csproj b/packages/Avalonia/Avalonia.csproj
index 3033064594..489cb228aa 100644
--- a/packages/Avalonia/Avalonia.csproj
+++ b/packages/Avalonia/Avalonia.csproj
@@ -1,10 +1,10 @@
-
+
netstandard2.0;net461;netcoreapp2.0
-
+
@@ -40,10 +40,6 @@
true
build\
-
- true
- tools\
-
diff --git a/packages/Avalonia/Avalonia.props b/packages/Avalonia/Avalonia.props
index 30e3f93b5c..6f21971d3d 100644
--- a/packages/Avalonia/Avalonia.props
+++ b/packages/Avalonia/Avalonia.props
@@ -2,7 +2,7 @@
$(MSBuildThisFileDirectory)\..\tools\netcoreapp2.0\designer\Avalonia.Designer.HostApp.dll
$(MSBuildThisFileDirectory)\..\tools\net461\designer\Avalonia.Designer.HostApp.exe
- $(MSBuildThisFileDirectory)\..\tools\Avalonia.Build.Tasks.dll
+ $(MSBuildThisFileDirectory)\..\tools\netstandard2.0\Avalonia.Build.Tasks.dll
false
diff --git a/parameters.cake b/parameters.cake
deleted file mode 100644
index 4ef7e8e05a..0000000000
--- a/parameters.cake
+++ /dev/null
@@ -1,129 +0,0 @@
-using System.Xml.Linq;
-using System.Linq;
-
-public class Parameters
-{
- public string Configuration { get; private set; }
- public bool SkipTests { get; private set; }
- public string MainRepo { get; private set; }
- public string MasterBranch { get; private set; }
- public string ReleasePlatform { get; private set; }
- public string ReleaseConfiguration { get; private set; }
- public string ReleaseBranchPrefix { get; private set; }
- public string MSBuildSolution { get; private set; }
- public bool IsLocalBuild { get; private set; }
- public bool IsRunningOnUnix { get; private set; }
- public bool IsRunningOnWindows { get; private set; }
- public bool IsRunningOnAppVeyor { get; private set; }
- public bool IsRunningOnAzure { get; private set; }
- public bool IsPullRequest { get; private set; }
- public bool IsMainRepo { get; private set; }
- public bool IsMasterBranch { get; private set; }
- public bool IsReleaseBranch { get; private set; }
- public bool IsTagged { get; private set; }
- public bool IsReleasable { get; private set; }
- public bool IsMyGetRelease { get; private set; }
- public bool IsNuGetRelease { get; private set; }
- public bool PublishTestResults { get; private set; }
- public string Version { get; private set; }
- public DirectoryPath ArtifactsDir { get; private set; }
- public DirectoryPath NugetRoot { get; private set; }
- public DirectoryPath ZipRoot { get; private set; }
- public DirectoryPath BinRoot { get; private set; }
- public DirectoryPath TestResultsRoot { get; private set; }
- public string DirSuffix { get; private set; }
- public DirectoryPathCollection BuildDirs { get; private set; }
- public string FileZipSuffix { get; private set; }
- public FilePath ZipCoreArtifacts { get; private set; }
- public FilePath ZipNuGetArtifacts { get; private set; }
- public DirectoryPath ZipSourceControlCatalogDesktopDirs { get; private set; }
- public FilePath ZipTargetControlCatalogDesktopDirs { get; private set; }
-
- public Parameters(ICakeContext context)
- {
- var buildSystem = context.BuildSystem();
-
- // ARGUMENTS
- Configuration = context.Argument("configuration", "Release");
- SkipTests = context.HasArgument("skip-tests");
-
- // CONFIGURATION
- MainRepo = "https://github.com/AvaloniaUI/Avalonia";
- MasterBranch = "master";
- ReleaseBranchPrefix = "refs/heads/release/";
- ReleaseConfiguration = "Release";
- MSBuildSolution = "./dirs.proj";
-
- // PARAMETERS
- IsLocalBuild = buildSystem.IsLocalBuild;
- IsRunningOnUnix = context.IsRunningOnUnix();
- IsRunningOnWindows = context.IsRunningOnWindows();
- IsRunningOnAppVeyor = buildSystem.AppVeyor.IsRunningOnAppVeyor;
- IsRunningOnAzure = buildSystem.IsRunningOnVSTS || buildSystem.IsRunningOnTFS || context.EnvironmentVariable("LOGNAME") == "vsts";
-
- IsPullRequest = buildSystem.AppVeyor.Environment.PullRequest.IsPullRequest;
- IsMainRepo = StringComparer.OrdinalIgnoreCase.Equals(MainRepo, context.EnvironmentVariable("BUILD_REPOSITORY_URI"));
- IsMasterBranch = StringComparer.OrdinalIgnoreCase.Equals(MasterBranch, context.EnvironmentVariable("BUILD_SOURCEBRANCHNAME"));
- IsReleaseBranch = (context.EnvironmentVariable("BUILD_SOURCEBRANCH")??"").StartsWith(ReleaseBranchPrefix, StringComparison.OrdinalIgnoreCase);
- IsTagged = buildSystem.AppVeyor.Environment.Repository.Tag.IsTag
- && !string.IsNullOrWhiteSpace(buildSystem.AppVeyor.Environment.Repository.Tag.Name);
- IsReleasable = StringComparer.OrdinalIgnoreCase.Equals(ReleaseConfiguration, Configuration);
- IsMyGetRelease = !IsTagged && IsReleasable;
- IsNuGetRelease = IsMainRepo && IsReleasable && IsReleaseBranch;
-
- // VERSION
- Version = context.Argument("force-nuget-version", GetVersion());
-
- if (IsRunningOnAppVeyor)
- {
- string tagVersion = null;
- if (IsTagged)
- {
- var tag = buildSystem.AppVeyor.Environment.Repository.Tag.Name;
- var nugetReleasePrefix = "nuget-release-";
- IsNuGetRelease = IsTagged && IsReleasable && tag.StartsWith(nugetReleasePrefix);
- if(IsNuGetRelease)
- tagVersion = tag.Substring(nugetReleasePrefix.Length);
- }
- if(tagVersion != null)
- {
- Version = tagVersion;
- }
- else
- {
- // Use AssemblyVersion with Build as version
- Version += "-build" + context.EnvironmentVariable("APPVEYOR_BUILD_NUMBER") + "-beta";
- }
- }
- else if (IsRunningOnAzure)
- {
- if(!IsNuGetRelease)
- {
- // Use AssemblyVersion with Build as version
- Version += "-build" + context.EnvironmentVariable("BUILD_BUILDID") + "-beta";
- }
-
- PublishTestResults = true;
- }
-
- // DIRECTORIES
- ArtifactsDir = (DirectoryPath)context.Directory("./artifacts");
- NugetRoot = ArtifactsDir.Combine("nuget");
- ZipRoot = ArtifactsDir.Combine("zip");
- BinRoot = ArtifactsDir.Combine("bin");
- TestResultsRoot = ArtifactsDir.Combine("test-results");
- BuildDirs = context.GetDirectories("**/bin") + context.GetDirectories("**/obj");
- DirSuffix = Configuration;
- FileZipSuffix = Version + ".zip";
- ZipCoreArtifacts = ZipRoot.CombineWithFilePath("Avalonia-" + FileZipSuffix);
- ZipNuGetArtifacts = ZipRoot.CombineWithFilePath("Avalonia-NuGet-" + FileZipSuffix);
- ZipSourceControlCatalogDesktopDirs = (DirectoryPath)context.Directory("./samples/ControlCatalog.Desktop/bin/" + DirSuffix + "/net461");
- ZipTargetControlCatalogDesktopDirs = ZipRoot.CombineWithFilePath("ControlCatalog.Desktop-" + FileZipSuffix);
- }
-
- private static string GetVersion()
- {
- var xdoc = XDocument.Load("./build/SharedVersion.props");
- return xdoc.Descendants().First(x => x.Name.LocalName == "Version").Value;
- }
-}
diff --git a/readme.md b/readme.md
index 9d113cf2ef..12f683bd55 100644
--- a/readme.md
+++ b/readme.md
@@ -2,9 +2,9 @@
# Avalonia
-| Gitter Chat | Build Status (Win, Linux, OSX) | Appveyor Build Status | Open Collective |
-|---|---|---|---|
-| [](https://gitter.im/AvaloniaUI/Avalonia?utm_campaign=pr-badge&utm_content=badge&utm_medium=badge&utm_source=badge) | [](https://dev.azure.com/AvaloniaUI/AvaloniaUI/_build/latest?definitionId=4) | [](https://ci.appveyor.com/project/AvaloniaUI/Avalonia/branch/master) | [](#backers) [](#sponsors) |
+| Gitter Chat | Build Status (Win, Linux, OSX) | Open Collective | NuGet | MyGet |
+|---|---|---|---|---|
+| [](https://gitter.im/AvaloniaUI/Avalonia?utm_campaign=pr-badge&utm_content=badge&utm_medium=badge&utm_source=badge) | [](https://dev.azure.com/AvaloniaUI/AvaloniaUI/_build/latest?definitionId=4) | [](#backers) [](#sponsors) | [](https://www.nuget.org/packages/Avalonia) | [](https://www.myget.org/gallery/avalonia-ci) |
## About
diff --git a/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj b/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj
index 7e2c707e91..589f41c06b 100644
--- a/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj
+++ b/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj
@@ -9,6 +9,7 @@
+
diff --git a/samples/ControlCatalog.NetCore/Program.cs b/samples/ControlCatalog.NetCore/Program.cs
index 1f53dedc14..57c8b700df 100644
--- a/samples/ControlCatalog.NetCore/Program.cs
+++ b/samples/ControlCatalog.NetCore/Program.cs
@@ -23,6 +23,7 @@ namespace ControlCatalog.NetCore
break;
}
}
+
if (args.Contains("--fbdev"))
AppBuilder.Configure().InitializeWithLinuxFramebuffer(tl =>
{
@@ -30,7 +31,12 @@ namespace ControlCatalog.NetCore
System.Threading.ThreadPool.QueueUserWorkItem(_ => ConsoleSilencer());
});
else
- BuildAvaloniaApp().Start();
+ BuildAvaloniaApp().Start(AppMain, args);
+ }
+
+ static void AppMain(Application app, string[] args)
+ {
+ app.Run(new MainWindow());
}
///
@@ -46,4 +52,4 @@ namespace ControlCatalog.NetCore
Console.ReadKey(true);
}
}
-}
\ No newline at end of file
+}
diff --git a/samples/ControlCatalog/DecoratedWindow.xaml b/samples/ControlCatalog/DecoratedWindow.xaml
index 37014255cc..cb6016b324 100644
--- a/samples/ControlCatalog/DecoratedWindow.xaml
+++ b/samples/ControlCatalog/DecoratedWindow.xaml
@@ -1,9 +1,8 @@
-
+ xmlns:local="clr-namespace:ControlCatalog" HasSystemDecorations="False" Name="Window">
@@ -20,7 +19,13 @@
- Hello world!
+
+ Hello world!
+
+ Decorated
+
+ CanResize
+
diff --git a/samples/ControlCatalog/MainView.xaml b/samples/ControlCatalog/MainView.xaml
index 0f7f2e80a8..2ddb5887e5 100644
--- a/samples/ControlCatalog/MainView.xaml
+++ b/samples/ControlCatalog/MainView.xaml
@@ -32,10 +32,10 @@
+
-
diff --git a/samples/ControlCatalog/Pages/DialogsPage.xaml b/samples/ControlCatalog/Pages/DialogsPage.xaml
index 1e4e9fef1c..2bd9a39300 100644
--- a/samples/ControlCatalog/Pages/DialogsPage.xaml
+++ b/samples/ControlCatalog/Pages/DialogsPage.xaml
@@ -6,6 +6,7 @@
+
diff --git a/samples/ControlCatalog/Pages/DialogsPage.xaml.cs b/samples/ControlCatalog/Pages/DialogsPage.xaml.cs
index e380c677c9..e2e9fbd21c 100644
--- a/samples/ControlCatalog/Pages/DialogsPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/DialogsPage.xaml.cs
@@ -31,15 +31,22 @@ namespace ControlCatalog.Pages
}.ShowAsync(GetWindow());
};
this.FindControl
+ public class ColorAnimator : Animator
+ {
+ // Opto-electronic conversion function for the sRGB color space
+ // Takes a gamma-encoded sRGB value and converts it to a linear sRGB value
+ private static double OECF_sRGB(double linear)
+ {
+ // IEC 61966-2-1:1999
+ return linear <= 0.0031308d ? linear * 12.92d : (double)(Math.Pow(linear, 1.0d / 2.4d) * 1.055d - 0.055d);
+ }
+
+ // Electro-optical conversion function for the sRGB color space
+ // Takes a linear sRGB value and converts it to a gamma-encoded sRGB value
+ private static double EOCF_sRGB(double srgb)
+ {
+ // IEC 61966-2-1:1999
+ return srgb <= 0.04045d ? srgb / 12.92d : (double)Math.Pow((srgb + 0.055d) / 1.055d, 2.4d);
+ }
+
+ public override Color Interpolate(double progress, Color oldValue, Color newValue)
+ {
+ // normalize sRGB values.
+ var oldA = oldValue.A / 255d;
+ var oldR = oldValue.R / 255d;
+ var oldG = oldValue.G / 255d;
+ var oldB = oldValue.B / 255d;
+
+ var newA = newValue.A / 255d;
+ var newR = newValue.R / 255d;
+ var newG = newValue.G / 255d;
+ var newB = newValue.B / 255d;
+
+ // convert from sRGB to linear
+ oldR = EOCF_sRGB(oldR);
+ oldG = EOCF_sRGB(oldG);
+ oldB = EOCF_sRGB(oldB);
+
+ newR = EOCF_sRGB(newR);
+ newG = EOCF_sRGB(newG);
+ newB = EOCF_sRGB(newB);
+
+ // compute the interpolated color in linear space
+ var a = oldA + progress * (newA - oldA);
+ var r = oldR + progress * (newR - oldR);
+ var g = oldG + progress * (newG - oldG);
+ var b = oldB + progress * (newB - oldB);
+
+ // convert back to sRGB in the [0..255] range
+ a = a * 255d;
+ r = OECF_sRGB(r) * 255d;
+ g = OECF_sRGB(g) * 255d;
+ b = OECF_sRGB(b) * 255d;
+
+ return new Color((byte)Math.Round(a), (byte)Math.Round(r), (byte)Math.Round(g), (byte)Math.Round(b));
+ }
+ }
+}
diff --git a/src/Avalonia.Visuals/Animation/Animators/CornerRadiusAnimator.cs b/src/Avalonia.Visuals/Animation/Animators/CornerRadiusAnimator.cs
new file mode 100644
index 0000000000..8129bd38de
--- /dev/null
+++ b/src/Avalonia.Visuals/Animation/Animators/CornerRadiusAnimator.cs
@@ -0,0 +1,27 @@
+using System;
+using Avalonia.Logging;
+using Avalonia.Media;
+
+namespace Avalonia.Animation.Animators
+{
+ ///
+ /// Animator that handles properties.
+ ///
+ public class CornerRadiusAnimator : Animator
+ {
+ public override CornerRadius Interpolate(double progress, CornerRadius oldValue, CornerRadius newValue)
+ {
+ var deltaTL = newValue.TopLeft - oldValue.TopLeft;
+ var deltaTR = newValue.TopRight - oldValue.TopRight;
+ var deltaBR = newValue.BottomRight - oldValue.BottomRight;
+ var deltaBL = newValue.BottomLeft - oldValue.BottomLeft;
+
+ var nTL = progress * deltaTL + oldValue.TopLeft;
+ var nTR = progress * deltaTR + oldValue.TopRight;
+ var nBR = progress * deltaBR + oldValue.BottomRight;
+ var nBL = progress * deltaBL + oldValue.BottomLeft;
+
+ return new CornerRadius(nTL, nTR, nBR, nBL);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Avalonia.Visuals/Animation/Animators/PointAnimator.cs b/src/Avalonia.Visuals/Animation/Animators/PointAnimator.cs
new file mode 100644
index 0000000000..793691e5ac
--- /dev/null
+++ b/src/Avalonia.Visuals/Animation/Animators/PointAnimator.cs
@@ -0,0 +1,17 @@
+using System;
+using Avalonia.Logging;
+using Avalonia.Media;
+
+namespace Avalonia.Animation.Animators
+{
+ ///
+ /// Animator that handles properties.
+ ///
+ public class PointAnimator : Animator
+ {
+ public override Point Interpolate(double progress, Point oldValue, Point newValue)
+ {
+ return ((newValue - oldValue) * progress) + oldValue;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Avalonia.Visuals/Animation/Animators/RectAnimator.cs b/src/Avalonia.Visuals/Animation/Animators/RectAnimator.cs
new file mode 100644
index 0000000000..b2d3ec2996
--- /dev/null
+++ b/src/Avalonia.Visuals/Animation/Animators/RectAnimator.cs
@@ -0,0 +1,23 @@
+using System;
+using Avalonia.Logging;
+using Avalonia.Media;
+
+namespace Avalonia.Animation.Animators
+{
+ ///
+ /// Animator that handles properties.
+ ///
+ public class RectAnimator : Animator
+ {
+ public override Rect Interpolate(double progress, Rect oldValue, Rect newValue)
+ {
+ var deltaPos = newValue.Position - oldValue.Position;
+ var deltaSize = newValue.Size - oldValue.Size;
+
+ var newPos = (deltaPos * progress) + oldValue.Position;
+ var newSize = (deltaSize * progress) + oldValue.Size;
+
+ return new Rect(newPos, newSize);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Avalonia.Visuals/Animation/Animators/SizeAnimator.cs b/src/Avalonia.Visuals/Animation/Animators/SizeAnimator.cs
new file mode 100644
index 0000000000..bb4f343e4a
--- /dev/null
+++ b/src/Avalonia.Visuals/Animation/Animators/SizeAnimator.cs
@@ -0,0 +1,17 @@
+using System;
+using Avalonia.Logging;
+using Avalonia.Media;
+
+namespace Avalonia.Animation.Animators
+{
+ ///
+ /// Animator that handles properties.
+ ///
+ public class SizeAnimator : Animator
+ {
+ public override Size Interpolate(double progress, Size oldValue, Size newValue)
+ {
+ return ((newValue - oldValue) * progress) + oldValue;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Avalonia.Visuals/Animation/Animators/SolidColorBrushAnimator.cs b/src/Avalonia.Visuals/Animation/Animators/SolidColorBrushAnimator.cs
new file mode 100644
index 0000000000..8776d3a7b7
--- /dev/null
+++ b/src/Avalonia.Visuals/Animation/Animators/SolidColorBrushAnimator.cs
@@ -0,0 +1,74 @@
+using System;
+using System.Reactive.Disposables;
+using Avalonia.Logging;
+using Avalonia.Media;
+using Avalonia.Media.Immutable;
+
+namespace Avalonia.Animation.Animators
+{
+ ///
+ /// Animator that handles .
+ ///
+ public class SolidColorBrushAnimator : Animator
+ {
+ ColorAnimator _colorAnimator;
+
+ void InitializeColorAnimator()
+ {
+ _colorAnimator = new ColorAnimator();
+
+ foreach (AnimatorKeyFrame keyframe in this)
+ {
+ _colorAnimator.Add(keyframe);
+ }
+
+ _colorAnimator.Property = SolidColorBrush.ColorProperty;
+ }
+
+ public override IDisposable Apply(Animation animation, Animatable control, IClock clock, IObservable match, Action onComplete)
+ {
+ foreach (var keyframe in this)
+ {
+ if (keyframe.Value as ISolidColorBrush == null)
+ return Disposable.Empty;
+
+ // Preprocess keyframe values to Color if the xaml parser converts them to ISCB.
+ if (keyframe.Value.GetType() == typeof(ImmutableSolidColorBrush))
+ {
+ keyframe.Value = ((ImmutableSolidColorBrush)keyframe.Value).Color;
+ }
+ }
+
+ // Add SCB if the target prop is empty.
+ if (control.GetValue(Property) == null)
+ control.SetValue(Property, new SolidColorBrush(Colors.Transparent));
+
+ var targetVal = control.GetValue(Property);
+
+ // Continue if target prop is not empty & is a SolidColorBrush derivative.
+ if (typeof(ISolidColorBrush).IsAssignableFrom(targetVal.GetType()))
+ {
+ if (_colorAnimator == null)
+ InitializeColorAnimator();
+
+ SolidColorBrush finalTarget;
+
+ // If it's ISCB, change it back to SCB.
+ if (targetVal.GetType() == typeof(ImmutableSolidColorBrush))
+ {
+ var col = (ImmutableSolidColorBrush)targetVal;
+ targetVal = new SolidColorBrush(col.Color);
+ control.SetValue(Property, targetVal);
+ }
+
+ finalTarget = targetVal as SolidColorBrush;
+
+ return _colorAnimator.Apply(animation, finalTarget, clock ?? control.Clock, match, onComplete);
+ }
+
+ return Disposable.Empty;
+ }
+
+ public override SolidColorBrush Interpolate(double p, SolidColorBrush o, SolidColorBrush n) => null;
+ }
+}
diff --git a/src/Avalonia.Visuals/Animation/Animators/ThicknessAnimator.cs b/src/Avalonia.Visuals/Animation/Animators/ThicknessAnimator.cs
new file mode 100644
index 0000000000..a6ae95ce3f
--- /dev/null
+++ b/src/Avalonia.Visuals/Animation/Animators/ThicknessAnimator.cs
@@ -0,0 +1,17 @@
+using System;
+using Avalonia.Logging;
+using Avalonia.Media;
+
+namespace Avalonia.Animation.Animators
+{
+ ///
+ /// Animator that handles properties.
+ ///
+ public class ThicknessAnimator : Animator
+ {
+ public override Thickness Interpolate(double progress, Thickness oldValue, Thickness newValue)
+ {
+ return ((newValue - oldValue) * progress) + oldValue;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Avalonia.Visuals/Animation/TransformAnimator.cs b/src/Avalonia.Visuals/Animation/Animators/TransformAnimator.cs
similarity index 75%
rename from src/Avalonia.Visuals/Animation/TransformAnimator.cs
rename to src/Avalonia.Visuals/Animation/Animators/TransformAnimator.cs
index 64b3ebd626..e7be272f13 100644
--- a/src/Avalonia.Visuals/Animation/TransformAnimator.cs
+++ b/src/Avalonia.Visuals/Animation/Animators/TransformAnimator.cs
@@ -2,14 +2,14 @@
using Avalonia.Logging;
using Avalonia.Media;
-namespace Avalonia.Animation
+namespace Avalonia.Animation.Animators
{
///
/// Animator that handles properties.
///
public class TransformAnimator : Animator
{
- DoubleAnimator childAnimator;
+ DoubleAnimator _doubleAnimator;
///
public override IDisposable Apply(Animation animation, Animatable control, IClock clock, IObservable obsMatch, Action onComplete)
@@ -27,7 +27,7 @@ namespace Avalonia.Animation
// default RenderTransform order.
normalTransform.Children.Add(new ScaleTransform());
- normalTransform.Children.Add(new SkewTransform());
+ normalTransform.Children.Add(new SkewTransform());
normalTransform.Children.Add(new RotateTransform());
normalTransform.Children.Add(new TranslateTransform());
@@ -36,15 +36,22 @@ namespace Avalonia.Animation
var renderTransformType = ctrl.RenderTransform.GetType();
- if (childAnimator == null)
+ if (_doubleAnimator == null)
{
- InitializeChildAnimator();
+ _doubleAnimator = new DoubleAnimator();
+
+ foreach (AnimatorKeyFrame keyframe in this)
+ {
+ _doubleAnimator.Add(keyframe);
+ }
+
+ _doubleAnimator.Property = Property;
}
// It's a transform object so let's target that.
if (renderTransformType == Property.OwnerType)
{
- return childAnimator.Apply(animation, ctrl.RenderTransform, clock ?? control.Clock, obsMatch, onComplete);
+ return _doubleAnimator.Apply(animation, ctrl.RenderTransform, clock ?? control.Clock, obsMatch, onComplete);
}
// It's a TransformGroup and try finding the target there.
else if (renderTransformType == typeof(TransformGroup))
@@ -53,7 +60,7 @@ namespace Avalonia.Animation
{
if (transform.GetType() == Property.OwnerType)
{
- return childAnimator.Apply(animation, transform, clock ?? control.Clock, obsMatch, onComplete);
+ return _doubleAnimator.Apply(animation, transform, clock ?? control.Clock, obsMatch, onComplete);
}
}
}
@@ -73,19 +80,7 @@ namespace Avalonia.Animation
return null;
}
- void InitializeChildAnimator()
- {
- childAnimator = new DoubleAnimator();
-
- foreach (AnimatorKeyFrame keyframe in this)
- {
- childAnimator.Add(keyframe);
- }
-
- childAnimator.Property = Property;
- }
-
- ///
- protected override double DoInterpolation(double time, double neutralValue) => 0;
+ ///
+ public override double Interpolate(double p, double o, double n) => 0;
}
}
diff --git a/src/Avalonia.Visuals/Animation/Animators/VectorAnimator.cs b/src/Avalonia.Visuals/Animation/Animators/VectorAnimator.cs
new file mode 100644
index 0000000000..e1ffb60971
--- /dev/null
+++ b/src/Avalonia.Visuals/Animation/Animators/VectorAnimator.cs
@@ -0,0 +1,17 @@
+using System;
+using Avalonia.Logging;
+using Avalonia.Media;
+
+namespace Avalonia.Animation.Animators
+{
+ ///
+ /// Animator that handles properties.
+ ///
+ public class VectorAnimator : Animator
+ {
+ public override Vector Interpolate(double progress, Vector oldValue, Vector newValue)
+ {
+ return ((newValue - oldValue) * progress) + oldValue;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Avalonia.Visuals/Animation/CrossFade.cs b/src/Avalonia.Visuals/Animation/CrossFade.cs
index d5ddf1c7f5..6b8cb8b755 100644
--- a/src/Avalonia.Visuals/Animation/CrossFade.cs
+++ b/src/Avalonia.Visuals/Animation/CrossFade.cs
@@ -21,7 +21,7 @@ namespace Avalonia.Animation
/// Initializes a new instance of the class.
///
public CrossFade()
- :this(TimeSpan.Zero)
+ : this(TimeSpan.Zero)
{
}
@@ -33,30 +33,40 @@ namespace Avalonia.Animation
{
_fadeOutAnimation = new Animation
{
- new KeyFrame
- (
- new Setter
+ Children =
+ {
+ new KeyFrame()
{
- Property = Visual.OpacityProperty,
- Value = 0d
+ Setters =
+ {
+ new Setter
+ {
+ Property = Visual.OpacityProperty,
+ Value = 0d
+ }
+ },
+ Cue = new Cue(1d)
}
- )
- {
- Cue = new Cue(1d)
+
}
};
_fadeInAnimation = new Animation
{
- new KeyFrame
- (
- new Setter
+ Children =
+ {
+ new KeyFrame()
{
- Property = Visual.OpacityProperty,
- Value = 0d
+ Setters =
+ {
+ new Setter
+ {
+ Property = Visual.OpacityProperty,
+ Value = 0d
+ }
+ },
+ Cue = new Cue(0d)
}
- )
- {
- Cue = new Cue(0d)
+
}
};
_fadeOutAnimation.Duration = _fadeInAnimation.Duration = duration;
diff --git a/src/Avalonia.Visuals/Animation/PageSlide.cs b/src/Avalonia.Visuals/Animation/PageSlide.cs
index c5d43068c1..0aa85035ae 100644
--- a/src/Avalonia.Visuals/Animation/PageSlide.cs
+++ b/src/Avalonia.Visuals/Animation/PageSlide.cs
@@ -74,34 +74,36 @@ namespace Avalonia.Animation
var distance = Orientation == SlideAxis.Horizontal ? parent.Bounds.Width : parent.Bounds.Height;
var translateProperty = Orientation == SlideAxis.Horizontal ? TranslateTransform.XProperty : TranslateTransform.YProperty;
-
- // TODO: Implement relevant transition logic here (or discard this class)
- // in favor of XAML based transition for pages
if (from != null)
{
var animation = new Animation
{
- new KeyFrame
- (
- new Setter
- {
- Property = translateProperty,
- Value = 0d
- }
- )
+ Children =
{
- Cue = new Cue(0d)
- },
- new KeyFrame
- (
- new Setter
+ new KeyFrame
{
- Property = translateProperty,
- Value = forward ? -distance : distance
- }
- )
- {
- Cue = new Cue(1d)
+ Setters =
+ {
+ new Setter
+ {
+ Property = translateProperty,
+ Value = 0d
+ }
+ },
+ Cue = new Cue(0d)
+ },
+ new KeyFrame
+ {
+ Setters =
+ {
+ new Setter
+ {
+ Property = translateProperty,
+ Value = forward ? -distance : distance
+ }
+ },
+ Cue = new Cue(1d)
+ }
}
};
animation.Duration = Duration;
@@ -113,29 +115,34 @@ namespace Avalonia.Animation
to.IsVisible = true;
var animation = new Animation
{
+ Children =
+ {
- new KeyFrame
- (
- new Setter
+ new KeyFrame
{
- Property = translateProperty,
- Value = forward ? distance : -distance
- }
- )
- {
- Cue = new Cue(0d)
- },
- new KeyFrame
- (
- new Setter
+ Setters =
+ {
+ new Setter
+ {
+ Property = translateProperty,
+ Value = forward ? distance : -distance
+ }
+ },
+ Cue = new Cue(0d)
+ },
+ new KeyFrame
{
- Property = translateProperty,
- Value = 0d
+ Setters =
+ {
+ new Setter
+ {
+ Property = translateProperty,
+ Value = 0d
+ }
+ },
+ Cue = new Cue(1d)
}
- )
- {
- Cue = new Cue(1d)
- },
+ }
};
animation.Duration = Duration;
tasks.Add(animation.RunAsync(to));
diff --git a/src/Avalonia.Visuals/Animation/Transitions/CornerRadiusTransition.cs b/src/Avalonia.Visuals/Animation/Transitions/CornerRadiusTransition.cs
new file mode 100644
index 0000000000..4b6703133d
--- /dev/null
+++ b/src/Avalonia.Visuals/Animation/Transitions/CornerRadiusTransition.cs
@@ -0,0 +1,36 @@
+// Copyright (c) The Avalonia Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using System;
+using System.Reactive.Linq;
+
+namespace Avalonia.Animation
+{
+ ///
+ /// Transition class that handles with type.
+ ///
+ public class CornerRadiusTransition : Transition
+ {
+ ///
+ public override IObservable DoTransition(IObservable progress, CornerRadius oldValue, CornerRadius newValue)
+ {
+ return progress
+ .Select(p =>
+ {
+ var f = Easing.Ease(p);
+
+ var deltaTL = newValue.TopLeft - oldValue.TopLeft;
+ var deltaTR = newValue.TopRight - oldValue.TopRight;
+ var deltaBR = newValue.BottomRight - oldValue.BottomRight;
+ var deltaBL = newValue.BottomLeft - oldValue.BottomLeft;
+
+ var nTL = f * deltaTL + oldValue.TopLeft;
+ var nTR = f * deltaTR + oldValue.TopRight;
+ var nBR = f * deltaBR + oldValue.BottomRight;
+ var nBL = f * deltaBL + oldValue.BottomLeft;
+
+ return new CornerRadius(nTL, nTR, nBR, nBL);
+ });
+ }
+ }
+}
diff --git a/src/Avalonia.Visuals/Animation/PointTransition.cs b/src/Avalonia.Visuals/Animation/Transitions/PointTransition.cs
similarity index 74%
rename from src/Avalonia.Visuals/Animation/PointTransition.cs
rename to src/Avalonia.Visuals/Animation/Transitions/PointTransition.cs
index a883c517dd..ea0000f960 100644
--- a/src/Avalonia.Visuals/Animation/PointTransition.cs
+++ b/src/Avalonia.Visuals/Animation/Transitions/PointTransition.cs
@@ -14,16 +14,11 @@ namespace Avalonia.Animation
///
public override IObservable DoTransition(IObservable progress, Point oldValue, Point newValue)
{
- var deltaX = newValue.X - oldValue.Y;
- var deltaY = newValue.X - oldValue.Y;
-
return progress
.Select(p =>
{
var f = Easing.Ease(p);
- var nX = f * deltaX + oldValue.X;
- var nY = f * deltaY + oldValue.Y;
- return new Point(nX, nY);
+ return ((newValue - oldValue) * f) + oldValue;
});
}
}
diff --git a/src/Avalonia.Visuals/Animation/Transitions/SizeTransition.cs b/src/Avalonia.Visuals/Animation/Transitions/SizeTransition.cs
new file mode 100644
index 0000000000..5de59edc53
--- /dev/null
+++ b/src/Avalonia.Visuals/Animation/Transitions/SizeTransition.cs
@@ -0,0 +1,25 @@
+// Copyright (c) The Avalonia Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using System;
+using System.Reactive.Linq;
+
+namespace Avalonia.Animation
+{
+ ///
+ /// Transition class that handles with type.
+ ///
+ public class SizeTransition : Transition
+ {
+ ///
+ public override IObservable DoTransition(IObservable progress, Size oldValue, Size newValue)
+ {
+ return progress
+ .Select(p =>
+ {
+ var f = Easing.Ease(p);
+ return ((newValue - oldValue) * f) + oldValue;
+ });
+ }
+ }
+}
diff --git a/src/Avalonia.Visuals/Animation/ThicknessTransition.cs b/src/Avalonia.Visuals/Animation/Transitions/ThicknessTransition.cs
similarity index 57%
rename from src/Avalonia.Visuals/Animation/ThicknessTransition.cs
rename to src/Avalonia.Visuals/Animation/Transitions/ThicknessTransition.cs
index 6c2ca22b74..e6b5e8904b 100644
--- a/src/Avalonia.Visuals/Animation/ThicknessTransition.cs
+++ b/src/Avalonia.Visuals/Animation/Transitions/ThicknessTransition.cs
@@ -14,20 +14,11 @@ namespace Avalonia.Animation
///
public override IObservable DoTransition(IObservable progress, Thickness oldValue, Thickness newValue)
{
- var deltaL = newValue.Left - oldValue.Left;
- var deltaT = newValue.Top - oldValue.Top;
- var deltaR = newValue.Right - oldValue.Right;
- var deltaB = newValue.Bottom - oldValue.Bottom;
-
return progress
- .Select(p =>
+ .Select(p =>
{
var f = Easing.Ease(p);
- var nL = f * deltaL + oldValue.Left;
- var nT = f * deltaT + oldValue.Right;
- var nR = f * deltaR + oldValue.Top;
- var nB = f * deltaB + oldValue.Bottom;
- return new Thickness(nL, nT, nR, nB);
+ return ((newValue - oldValue) * f) + oldValue;
});
}
}
diff --git a/src/Avalonia.Visuals/Animation/Transitions/VectorTransition.cs b/src/Avalonia.Visuals/Animation/Transitions/VectorTransition.cs
new file mode 100644
index 0000000000..5271c1378b
--- /dev/null
+++ b/src/Avalonia.Visuals/Animation/Transitions/VectorTransition.cs
@@ -0,0 +1,25 @@
+// Copyright (c) The Avalonia Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using System;
+using System.Reactive.Linq;
+
+namespace Avalonia.Animation
+{
+ ///
+ /// Transition class that handles with type.
+ ///
+ public class VectorTransition : Transition
+ {
+ ///
+ public override IObservable DoTransition(IObservable progress, Vector oldValue, Vector newValue)
+ {
+ return progress
+ .Select(p =>
+ {
+ var f = Easing.Ease(p);
+ return ((newValue - oldValue) * f) + oldValue;
+ });
+ }
+ }
+}
diff --git a/src/Avalonia.Visuals/Avalonia.Visuals.csproj b/src/Avalonia.Visuals/Avalonia.Visuals.csproj
index 85836a785f..2cc7741bbb 100644
--- a/src/Avalonia.Visuals/Avalonia.Visuals.csproj
+++ b/src/Avalonia.Visuals/Avalonia.Visuals.csproj
@@ -2,7 +2,6 @@
netstandard2.0
Avalonia
- false
diff --git a/src/Avalonia.Visuals/CornerRadius.cs b/src/Avalonia.Visuals/CornerRadius.cs
index 2d41acb5bc..09163a2dac 100644
--- a/src/Avalonia.Visuals/CornerRadius.cs
+++ b/src/Avalonia.Visuals/CornerRadius.cs
@@ -3,12 +3,18 @@
using System;
using System.Globalization;
+using Avalonia.Animation.Animators;
using Avalonia.Utilities;
namespace Avalonia
{
public struct CornerRadius
{
+ static CornerRadius()
+ {
+ Animation.Animation.RegisterAnimator(prop => typeof(CornerRadius).IsAssignableFrom(prop.PropertyType));
+ }
+
public CornerRadius(double uniformRadius)
{
TopLeft = TopRight = BottomLeft = BottomRight = uniformRadius;
diff --git a/src/Avalonia.Visuals/Matrix.cs b/src/Avalonia.Visuals/Matrix.cs
index cdaaa2b4b4..d083a2aaf8 100644
--- a/src/Avalonia.Visuals/Matrix.cs
+++ b/src/Avalonia.Visuals/Matrix.cs
@@ -293,13 +293,13 @@ namespace Avalonia
/// The inverted matrix.
public Matrix Invert()
{
- if (GetDeterminant() == 0)
+ double d = GetDeterminant();
+
+ if (d == 0)
{
throw new InvalidOperationException("Transform is not invertible.");
}
- double d = GetDeterminant();
-
return new Matrix(
_m22 / d,
-_m12 / d,
diff --git a/src/Avalonia.Visuals/Media/Brush.cs b/src/Avalonia.Visuals/Media/Brush.cs
index c2c041f073..f36cd88537 100644
--- a/src/Avalonia.Visuals/Media/Brush.cs
+++ b/src/Avalonia.Visuals/Media/Brush.cs
@@ -3,6 +3,7 @@
using System;
using System.ComponentModel;
+using Avalonia.Animation;
namespace Avalonia.Media
{
@@ -10,7 +11,7 @@ namespace Avalonia.Media
/// Describes how an area is painted.
///
[TypeConverter(typeof(BrushConverter))]
- public abstract class Brush : AvaloniaObject, IMutableBrush
+ public abstract class Brush : Animatable, IMutableBrush
{
///
/// Defines the property.
diff --git a/src/Avalonia.Visuals/Media/Color.cs b/src/Avalonia.Visuals/Media/Color.cs
index 8294934751..a37463a0f0 100644
--- a/src/Avalonia.Visuals/Media/Color.cs
+++ b/src/Avalonia.Visuals/Media/Color.cs
@@ -3,6 +3,8 @@
using System;
using System.Globalization;
+using Avalonia.Animation;
+using Avalonia.Animation.Animators;
namespace Avalonia.Media
{
@@ -11,6 +13,11 @@ namespace Avalonia.Media
///
public readonly struct Color
{
+ static Color()
+ {
+ Animation.Animation.RegisterAnimator(prop => typeof(Color).IsAssignableFrom(prop.PropertyType));
+ }
+
///
/// Gets or sets the Alpha component of the color.
///
diff --git a/src/Avalonia.Visuals/Media/DrawingContext.cs b/src/Avalonia.Visuals/Media/DrawingContext.cs
index 6b19167381..e7d6df5a93 100644
--- a/src/Avalonia.Visuals/Media/DrawingContext.cs
+++ b/src/Avalonia.Visuals/Media/DrawingContext.cs
@@ -2,23 +2,26 @@ using System;
using System.Collections.Generic;
using Avalonia.Media.Imaging;
using Avalonia.Platform;
+using Avalonia.Threading;
using Avalonia.Visuals.Media.Imaging;
namespace Avalonia.Media
{
public sealed class DrawingContext : IDisposable
{
+ private readonly bool _ownsImpl;
private int _currentLevel;
- static readonly Stack> StateStackPool = new Stack>();
- static readonly Stack> TransformStackPool = new Stack>();
+ private static ThreadSafeObjectPool> StateStackPool { get; } =
+ ThreadSafeObjectPool>.Default;
- private Stack _states = StateStackPool.Count == 0 ? new Stack() : StateStackPool.Pop();
+ private static ThreadSafeObjectPool> TransformStackPool { get; } =
+ ThreadSafeObjectPool>.Default;
- private Stack _transformContainers = TransformStackPool.Count == 0
- ? new Stack()
- : TransformStackPool.Pop();
+ private Stack _states = StateStackPool.Get();
+
+ private Stack _transformContainers = TransformStackPool.Get();
readonly struct TransformContainer
{
@@ -35,6 +38,13 @@ namespace Avalonia.Media
public DrawingContext(IDrawingContextImpl impl)
{
PlatformImpl = impl;
+ _ownsImpl = true;
+ }
+
+ public DrawingContext(IDrawingContextImpl impl, bool ownsImpl)
+ {
+ _ownsImpl = ownsImpl;
+ PlatformImpl = impl;
}
public IDrawingContextImpl PlatformImpl { get; }
@@ -299,11 +309,14 @@ namespace Avalonia.Media
{
while (_states.Count != 0)
_states.Peek().Dispose();
- StateStackPool.Push(_states);
+ StateStackPool.Return(_states);
_states = null;
- TransformStackPool.Push(_transformContainers);
+ if (_transformContainers.Count != 0)
+ throw new InvalidOperationException("Transform container stack is non-empty");
+ TransformStackPool.Return(_transformContainers);
_transformContainers = null;
- PlatformImpl.Dispose();
+ if (_ownsImpl)
+ PlatformImpl.Dispose();
}
private static bool PenIsVisible(Pen pen)
diff --git a/src/Avalonia.Visuals/Media/FontFamily.cs b/src/Avalonia.Visuals/Media/FontFamily.cs
index 16dba573fd..5c152cd8a0 100644
--- a/src/Avalonia.Visuals/Media/FontFamily.cs
+++ b/src/Avalonia.Visuals/Media/FontFamily.cs
@@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using Avalonia.Media.Fonts;
+using Avalonia.Platform;
namespace Avalonia.Media
{
@@ -40,9 +41,10 @@ namespace Avalonia.Media
///
/// The name of the .
/// The source of font resources.
- public FontFamily(string name, Uri source) : this(name)
+ ///
+ public FontFamily(string name, Uri source, Uri baseUri = null) : this(name)
{
- Key = new FontFamilyKey(source);
+ Key = new FontFamilyKey(source, baseUri);
}
///
@@ -50,6 +52,12 @@ namespace Avalonia.Media
///
public static FontFamily Default => new FontFamily(String.Empty);
+ ///
+ /// Represents all font families in the system. This can be an expensive call depending on platform implementation.
+ ///
+ public static IEnumerable SystemFontFamilies =>
+ AvaloniaLocator.Current.GetService().InstalledFontNames.Select(name => new FontFamily(name));
+
///
/// Gets the primary family name of the font family.
///
@@ -87,11 +95,12 @@ namespace Avalonia.Media
/// Parses a string.
///
/// The string.
+ ///
///
///
/// Specified family is not supported.
///
- public static FontFamily Parse(string s)
+ public static FontFamily Parse(string s, Uri baseUri = null)
{
if (string.IsNullOrEmpty(s))
{
@@ -112,7 +121,13 @@ namespace Avalonia.Media
case 2:
{
- return new FontFamily(segments[1], new Uri(segments[0], UriKind.RelativeOrAbsolute));
+ var uri = segments[0].StartsWith("/")
+ ? new Uri(segments[0], UriKind.Relative)
+ : new Uri(segments[0], UriKind.RelativeOrAbsolute);
+
+ return uri.IsAbsoluteUri
+ ? new FontFamily(segments[1], uri)
+ : new FontFamily(segments[1], uri, baseUri);
}
default:
diff --git a/src/Avalonia.Visuals/Media/Fonts/FontFamilyKey.cs b/src/Avalonia.Visuals/Media/Fonts/FontFamilyKey.cs
index 90ccac0e46..76ee2b7aad 100644
--- a/src/Avalonia.Visuals/Media/Fonts/FontFamilyKey.cs
+++ b/src/Avalonia.Visuals/Media/Fonts/FontFamilyKey.cs
@@ -2,7 +2,6 @@
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
-using System.Linq;
namespace Avalonia.Media.Fonts
{
@@ -12,48 +11,26 @@ namespace Avalonia.Media.Fonts
public class FontFamilyKey
{
///
- /// Creates a new instance of and extracts and from given
+ /// Creates a new instance of
///
///
- public FontFamilyKey(Uri source)
+ ///
+ public FontFamilyKey(Uri source, Uri baseUri = null)
{
- if (source == null)
- {
- throw new ArgumentNullException(nameof(source));
- }
+ Source = source ?? throw new ArgumentNullException(nameof(source));
- if (source.AbsolutePath.Contains(".ttf"))
- {
- var filePathWithoutExtension = source.AbsolutePath.Replace(".ttf", string.Empty);
- var fileNameWithoutExtension = filePathWithoutExtension.Split('.').Last();
- FileName = fileNameWithoutExtension + ".ttf";
- Location = new Uri(source.OriginalString.Replace("." + FileName, string.Empty), UriKind.RelativeOrAbsolute);
- }
- else
- {
- if (source.AbsolutePath.Contains(".otf"))
- {
- var filePathWithoutExtension = source.AbsolutePath.Replace(".otf", string.Empty);
- var fileNameWithoutExtension = filePathWithoutExtension.Split('.').Last();
- FileName = fileNameWithoutExtension + ".otf";
- Location = new Uri(source.OriginalString.Replace("." + FileName, string.Empty), UriKind.RelativeOrAbsolute);
- }
- else
- {
- Location = source;
- }
- }
+ BaseUri = baseUri;
}
///
- /// Location of stored font asset that belongs to a
+ /// Source of stored font asset that belongs to a
///
- public Uri Location { get; }
+ public Uri Source { get; }
///
- /// Optional filename for a font asset that belongs to a
+ /// A base URI to use if is relative
///
- public string FileName { get; }
+ public Uri BaseUri { get; }
///
/// Returns a hash code for this instance.
@@ -67,14 +44,14 @@ namespace Avalonia.Media.Fonts
{
var hash = (int)2166136261;
- if (Location != null)
+ if (Source != null)
{
- hash = (hash * 16777619) ^ Location.GetHashCode();
+ hash = (hash * 16777619) ^ Source.GetHashCode();
}
- if (FileName != null)
+ if (BaseUri != null)
{
- hash = (hash * 16777619) ^ FileName.GetHashCode();
+ hash = (hash * 16777619) ^ BaseUri.GetHashCode();
}
return hash;
@@ -95,12 +72,12 @@ namespace Avalonia.Media.Fonts
return false;
}
- if (Location != other.Location)
+ if (Source != other.Source)
{
return false;
}
- if (FileName != other.FileName)
+ if (BaseUri != other.BaseUri)
{
return false;
}
@@ -116,16 +93,12 @@ namespace Avalonia.Media.Fonts
///
public override string ToString()
{
- if (FileName == null)
+ if (!Source.IsAbsoluteUri && BaseUri != null)
{
- return Location.PathAndQuery;
+ return BaseUri.Authority + Source;
}
- var builder = new UriBuilder(Location);
-
- builder.Path += "." + FileName;
-
- return builder.ToString();
+ return Source.ToString();
}
}
}
diff --git a/src/Avalonia.Visuals/Media/Fonts/FontFamilyLoader.cs b/src/Avalonia.Visuals/Media/Fonts/FontFamilyLoader.cs
index 166eb4a661..063fe8f20d 100644
--- a/src/Avalonia.Visuals/Media/Fonts/FontFamilyLoader.cs
+++ b/src/Avalonia.Visuals/Media/Fonts/FontFamilyLoader.cs
@@ -4,7 +4,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Reflection;
using Avalonia.Platform;
namespace Avalonia.Media.Fonts
@@ -18,23 +17,35 @@ namespace Avalonia.Media.Fonts
s_assetLoader = AvaloniaLocator.Current.GetService();
}
+ ///
+ /// Loads all font assets that belong to the specified
+ ///
+ ///
+ ///
public static IEnumerable LoadFontAssets(FontFamilyKey fontFamilyKey)
{
- return fontFamilyKey.FileName != null
- ? GetFontAssetsByFileName(fontFamilyKey.Location, fontFamilyKey.FileName)
- : GetFontAssetsByLocation(fontFamilyKey.Location);
+ var sourceWithoutArguments = fontFamilyKey.Source.OriginalString.Split('?').First();
+
+ if (sourceWithoutArguments.EndsWith(".ttf")
+ || sourceWithoutArguments.EndsWith(".otf"))
+ {
+ return GetFontAssetsByExpression(fontFamilyKey);
+ }
+
+ return GetFontAssetsBySource(fontFamilyKey);
}
///
/// Searches for font assets at a given location and returns a quantity of found assets
///
- ///
+ ///
///
- private static IEnumerable GetFontAssetsByLocation(Uri location)
+ private static IEnumerable GetFontAssetsBySource(FontFamilyKey fontFamilyKey)
{
- var availableAssets = s_assetLoader.GetAssets(location, null);
+ var availableAssets = s_assetLoader.GetAssets(fontFamilyKey.Source, fontFamilyKey.BaseUri);
- var matchingAssets = availableAssets.Where(x => x.AbsolutePath.EndsWith(".ttf") || x.AbsolutePath.EndsWith(".otf"));
+ var matchingAssets =
+ availableAssets.Where(x => x.AbsolutePath.EndsWith(".ttf") || x.AbsolutePath.EndsWith(".otf"));
return matchingAssets;
}
@@ -43,20 +54,73 @@ namespace Avalonia.Media.Fonts
/// Searches for font assets at a given location and only accepts assets that fit to a given filename expression.
/// File names can target multiple files with * wildcard. For example "FontFile*.ttf"
///
- ///
- ///
+ ///
///
- private static IEnumerable GetFontAssetsByFileName(Uri location, string fileName)
+ private static IEnumerable GetFontAssetsByExpression(FontFamilyKey fontFamilyKey)
{
- var availableResources = s_assetLoader.GetAssets(location, null);
+ var fileName = GetFileName(fontFamilyKey, out var fileExtension, out var location);
- var compareTo = location.AbsolutePath + "." + fileName.Split('*').First();
+ var availableResources = s_assetLoader.GetAssets(location, fontFamilyKey.BaseUri);
- var matchingResources =
- availableResources.Where(x => x.AbsolutePath.Contains(compareTo) && (x.AbsolutePath.EndsWith(".ttf") || x.AbsolutePath.EndsWith(".otf")));
+ string compareTo;
+
+ if (fontFamilyKey.Source.IsAbsoluteUri)
+ {
+ if (fontFamilyKey.Source.Scheme == "resm")
+ {
+ compareTo = location.AbsolutePath + "." + fileName.Split('*').First();
+ }
+ else
+ {
+ compareTo = location.AbsolutePath + fileName.Split('*').First();
+ }
+ }
+ else
+ {
+ compareTo = location.AbsolutePath + fileName.Split('*').First();
+ }
+
+ var matchingResources = availableResources.Where(
+ x => x.AbsolutePath.Contains(compareTo)
+ && x.AbsolutePath.EndsWith(fileExtension));
return matchingResources;
}
+ private static string GetFileName(FontFamilyKey fontFamilyKey, out string fileExtension, out Uri location)
+ {
+ if (fontFamilyKey.Source.IsAbsoluteUri && fontFamilyKey.Source.Scheme == "resm")
+ {
+ fileExtension = "." + fontFamilyKey.Source.AbsolutePath.Split('.').LastOrDefault();
+
+ var fileName = fontFamilyKey.Source.LocalPath.Replace(fileExtension, string.Empty).Split('.').LastOrDefault();
+
+ location = new Uri(fontFamilyKey.Source.AbsoluteUri.Replace("." + fileName + fileExtension, string.Empty), UriKind.RelativeOrAbsolute);
+
+ return fileName;
+ }
+
+ var pathSegments = fontFamilyKey.Source.OriginalString.Split('/');
+
+ var fileNameWithExtension = pathSegments.Last();
+
+ var fileNameSegments = fileNameWithExtension.Split('.');
+
+ fileExtension = "." + fileNameSegments.Last();
+
+ if (fontFamilyKey.BaseUri != null)
+ {
+ var relativePath = fontFamilyKey.Source.OriginalString
+ .Replace(fileNameWithExtension, string.Empty);
+
+ location = new Uri(fontFamilyKey.BaseUri, relativePath);
+ }
+ else
+ {
+ location = new Uri(fontFamilyKey.Source.AbsolutePath.Replace(fileNameWithExtension, string.Empty));
+ }
+
+ return fileNameSegments.First();
+ }
}
}
diff --git a/src/Avalonia.Visuals/Media/GradientStop.cs b/src/Avalonia.Visuals/Media/GradientStop.cs
index 00d96a0b3c..25a6eb10dc 100644
--- a/src/Avalonia.Visuals/Media/GradientStop.cs
+++ b/src/Avalonia.Visuals/Media/GradientStop.cs
@@ -11,13 +11,13 @@ namespace Avalonia.Media
///
/// Describes the property.
///
- public static StyledProperty OffsetProperty =
+ public static readonly StyledProperty OffsetProperty =
AvaloniaProperty.Register(nameof(Offset));
///
/// Describes the property.
///
- public static StyledProperty ColorProperty =
+ public static readonly StyledProperty ColorProperty =
AvaloniaProperty.Register(nameof(Color));
///
diff --git a/src/Avalonia.Visuals/Media/Imaging/Bitmap.cs b/src/Avalonia.Visuals/Media/Imaging/Bitmap.cs
index 0ad826f5a9..8dd75d2374 100644
--- a/src/Avalonia.Visuals/Media/Imaging/Bitmap.cs
+++ b/src/Avalonia.Visuals/Media/Imaging/Bitmap.cs
@@ -75,7 +75,7 @@ namespace Avalonia.Media.Imaging
public Vector Dpi => PlatformImpl.Item.Dpi;
///
- public Size Size => PlatformImpl.Item.PixelSize.ToSize(Dpi);
+ public Size Size => PlatformImpl.Item.PixelSize.ToSizeWithDpi(Dpi);
///
public PixelSize PixelSize => PlatformImpl.Item.PixelSize;
diff --git a/src/Avalonia.Visuals/Media/PixelPoint.cs b/src/Avalonia.Visuals/Media/PixelPoint.cs
new file mode 100644
index 0000000000..995781ee9f
--- /dev/null
+++ b/src/Avalonia.Visuals/Media/PixelPoint.cs
@@ -0,0 +1,201 @@
+// Copyright (c) The Avalonia Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using System;
+using System.Globalization;
+using Avalonia.Utilities;
+
+namespace Avalonia
+{
+ ///
+ /// Represents a point in device pixels.
+ ///
+ public readonly struct PixelPoint
+ {
+ ///
+ /// A point representing 0,0.
+ ///
+ public static readonly PixelPoint Origin = new PixelPoint(0, 0);
+
+ ///
+ /// Initializes a new instance of the structure.
+ ///
+ /// The X co-ordinate.
+ /// The Y co-ordinate.
+ public PixelPoint(int x, int y)
+ {
+ X = x;
+ Y = y;
+ }
+
+ ///
+ /// Gets the X co-ordinate.
+ ///
+ public int X { get; }
+
+ ///
+ /// Gets the Y co-ordinate.
+ ///
+ public int Y { get; }
+
+ ///
+ /// Checks for equality between two s.
+ ///
+ /// The first point.
+ /// The second point.
+ /// True if the points are equal; otherwise false.
+ public static bool operator ==(PixelPoint left, PixelPoint right)
+ {
+ return left.X == right.X && left.Y == right.Y;
+ }
+
+ ///
+ /// Checks for inequality between two s.
+ ///
+ /// The first point.
+ /// The second point.
+ /// True if the points are unequal; otherwise false.
+ public static bool operator !=(PixelPoint left, PixelPoint right)
+ {
+ return !(left == right);
+ }
+
+ ///
+ /// Parses a string.
+ ///
+ /// The string.
+ /// The .
+ public static PixelPoint Parse(string s)
+ {
+ using (var tokenizer = new StringTokenizer(s, CultureInfo.InvariantCulture, exceptionMessage: "Invalid PixelPoint"))
+ {
+ return new PixelPoint(
+ tokenizer.ReadInt32(),
+ tokenizer.ReadInt32());
+ }
+ }
+
+ ///
+ /// Checks for equality between a point and an object.
+ ///
+ /// The object.
+ ///
+ /// True if is a point that equals the current point.
+ ///
+ public override bool Equals(object obj)
+ {
+ if (obj is PixelPoint other)
+ {
+ return this == other;
+ }
+
+ return false;
+ }
+
+ ///
+ /// Returns a hash code for a .
+ ///
+ /// The hash code.
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 17;
+ hash = (hash * 23) + X.GetHashCode();
+ hash = (hash * 23) + Y.GetHashCode();
+ return hash;
+ }
+ }
+
+ ///
+ /// Returns a new with the same Y co-ordinate and the specified X co-ordinate.
+ ///
+ /// The X co-ordinate.
+ /// The new .
+ public PixelPoint WithX(int x) => new PixelPoint(x, Y);
+
+ ///
+ /// Returns a new with the same X co-ordinate and the specified Y co-ordinate.
+ ///
+ /// The Y co-ordinate.
+ /// The new .
+ public PixelPoint WithY(int y) => new PixelPoint(X, y);
+
+ ///
+ /// Converts the to a device-independent using the
+ /// specified scaling factor.
+ ///
+ /// The scaling factor.
+ /// The device-independent point.
+ public Point ToPoint(double scale) => new Point(X / scale, Y / scale);
+
+ ///
+ /// Converts the to a device-independent using the
+ /// specified scaling factor.
+ ///
+ /// The scaling factor.
+ /// The device-independent point.
+ public Point ToPoint(Vector scale) => new Point(X / scale.X, Y / scale.Y);
+
+ ///
+ /// Converts the to a device-independent using the
+ /// specified dots per inch (DPI).
+ ///
+ /// The dots per inch of the device.
+ /// The device-independent point.
+ public Point ToPointWithDpi(double dpi) => ToPoint(dpi / 96);
+
+ ///
+ /// Converts the to a device-independent using the
+ /// specified dots per inch (DPI).
+ ///
+ /// The dots per inch of the device.
+ /// The device-independent point.
+ public Point ToPointWithDpi(Vector dpi) => ToPoint(new Vector(dpi.X / 96, dpi.Y / 96));
+
+ ///
+ /// Converts a to device pixels using the specified scaling factor.
+ ///
+ /// The point.
+ /// The scaling factor.
+ /// The device-independent point.
+ public static PixelPoint FromPoint(Point point, double scale) => new PixelPoint(
+ (int)(point.X * scale),
+ (int)(point.Y * scale));
+
+ ///
+ /// Converts a to device pixels using the specified scaling factor.
+ ///
+ /// The point.
+ /// The scaling factor.
+ /// The device-independent point.
+ public static PixelPoint FromPoint(Point point, Vector scale) => new PixelPoint(
+ (int)(point.X * scale.X),
+ (int)(point.Y * scale.Y));
+
+ ///
+ /// Converts a to device pixels using the specified dots per inch (DPI).
+ ///
+ /// The point.
+ /// The dots per inch of the device.
+ /// The device-independent point.
+ public static PixelPoint FromPointWithDpi(Point point, double dpi) => FromPoint(point, dpi / 96);
+
+ ///
+ /// Converts a to device pixels using the specified dots per inch (DPI).
+ ///
+ /// The point.
+ /// The dots per inch of the device.
+ /// The device-independent point.
+ public static PixelPoint FromPointWithDpi(Point point, Vector dpi) => FromPoint(point, new Vector(dpi.X / 96, dpi.Y / 96));
+
+ ///
+ /// Returns the string representation of the point.
+ ///
+ /// The string representation of the point.
+ public override string ToString()
+ {
+ return string.Format(CultureInfo.InvariantCulture, "{0}, {1}", X, Y);
+ }
+ }
+}
diff --git a/src/Avalonia.Visuals/Media/PixelRect.cs b/src/Avalonia.Visuals/Media/PixelRect.cs
new file mode 100644
index 0000000000..9c8e5ad1c4
--- /dev/null
+++ b/src/Avalonia.Visuals/Media/PixelRect.cs
@@ -0,0 +1,436 @@
+// Copyright (c) The Avalonia Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using System;
+using System.Globalization;
+using Avalonia.Utilities;
+
+namespace Avalonia
+{
+ ///
+ /// Represents a rectangle in device pixels.
+ ///
+ public readonly struct PixelRect
+ {
+ ///
+ /// An empty rectangle.
+ ///
+ public static readonly PixelRect Empty = default;
+
+ ///
+ /// Initializes a new instance of the structure.
+ ///
+ /// The X position.
+ /// The Y position.
+ /// The width.
+ /// The height.
+ public PixelRect(int x, int y, int width, int height)
+ {
+ X = x;
+ Y = y;
+ Width = width;
+ Height = height;
+ }
+
+ ///
+ /// Initializes a new instance of the structure.
+ ///
+ /// The size of the rectangle.
+ public PixelRect(PixelSize size)
+ {
+ X = 0;
+ Y = 0;
+ Width = size.Width;
+ Height = size.Height;
+ }
+
+ ///
+ /// Initializes a new instance of the structure.
+ ///
+ /// The position of the rectangle.
+ /// The size of the rectangle.
+ public PixelRect(PixelPoint position, PixelSize size)
+ {
+ X = position.X;
+ Y = position.Y;
+ Width = size.Width;
+ Height = size.Height;
+ }
+
+ ///
+ /// Initializes a new instance of the structure.
+ ///
+ /// The top left position of the rectangle.
+ /// The bottom right position of the rectangle.
+ public PixelRect(PixelPoint topLeft, PixelPoint bottomRight)
+ {
+ X = topLeft.X;
+ Y = topLeft.Y;
+ Width = bottomRight.X - topLeft.X;
+ Height = bottomRight.Y - topLeft.Y;
+ }
+
+ ///
+ /// Gets the X position.
+ ///
+ public int X { get; }
+
+ ///
+ /// Gets the Y position.
+ ///
+ public int Y { get; }
+
+ ///
+ /// Gets the width.
+ ///
+ public int Width { get; }
+
+ ///
+ /// Gets the height.
+ ///
+ public int Height { get; }
+
+ ///
+ /// Gets the position of the rectangle.
+ ///
+ public PixelPoint Position => new PixelPoint(X, Y);
+
+ ///
+ /// Gets the size of the rectangle.
+ ///
+ public PixelSize Size => new PixelSize(Width, Height);
+
+ ///
+ /// Gets the right position of the rectangle.
+ ///
+ public int Right => X + Width;
+
+ ///
+ /// Gets the bottom position of the rectangle.
+ ///
+ public int Bottom => Y + Height;
+
+ ///
+ /// Gets the top left point of the rectangle.
+ ///
+ public PixelPoint TopLeft => new PixelPoint(X, Y);
+
+ ///
+ /// Gets the top right point of the rectangle.
+ ///
+ public PixelPoint TopRight => new PixelPoint(Right, Y);
+
+ ///
+ /// Gets the bottom left point of the rectangle.
+ ///
+ public PixelPoint BottomLeft => new PixelPoint(X, Bottom);
+
+ ///
+ /// Gets the bottom right point of the rectangle.
+ ///
+ public PixelPoint BottomRight => new PixelPoint(Right, Bottom);
+
+ ///
+ /// Gets the center point of the rectangle.
+ ///
+ public PixelPoint Center => new PixelPoint(X + (Width / 2), Y + (Height / 2));
+
+ ///
+ /// Gets a value that indicates whether the rectangle is empty.
+ ///
+ public bool IsEmpty => Width == 0 && Height == 0;
+
+ ///
+ /// Checks for equality between two s.
+ ///
+ /// The first rect.
+ /// The second rect.
+ /// True if the rects are equal; otherwise false.
+ public static bool operator ==(PixelRect left, PixelRect right)
+ {
+ return left.Position == right.Position && left.Size == right.Size;
+ }
+
+ ///
+ /// Checks for inequality between two s.
+ ///
+ /// The first rect.
+ /// The second rect.
+ /// True if the rects are unequal; otherwise false.
+ public static bool operator !=(PixelRect left, PixelRect right)
+ {
+ return !(left == right);
+ }
+
+ ///
+ /// Determines whether a point in in the bounds of the rectangle.
+ ///
+ /// The point.
+ /// true if the point is in the bounds of the rectangle; otherwise false.
+ public bool Contains(PixelPoint p)
+ {
+ return p.X >= X && p.X <= Right && p.Y >= Y && p.Y <= Bottom;
+ }
+
+ ///
+ /// Determines whether the rectangle fully contains another rectangle.
+ ///
+ /// The rectangle.
+ /// true if the rectangle is fully contained; otherwise false.
+ public bool Contains(PixelRect r)
+ {
+ return Contains(r.TopLeft) && Contains(r.BottomRight);
+ }
+
+ ///
+ /// Centers another rectangle in this rectangle.
+ ///
+ /// The rectangle to center.
+ /// The centered rectangle.
+ public PixelRect CenterRect(PixelRect rect)
+ {
+ return new PixelRect(
+ X + ((Width - rect.Width) / 2),
+ Y + ((Height - rect.Height) / 2),
+ rect.Width,
+ rect.Height);
+ }
+
+ ///
+ /// Returns a boolean indicating whether the given object is equal to this rectangle.
+ ///
+ /// The object to compare against.
+ /// True if the object is equal to this rectangle; false otherwise.
+ public override bool Equals(object obj)
+ {
+ if (obj is PixelRect other)
+ {
+ return this == other;
+ }
+
+ return false;
+ }
+
+ ///
+ /// Returns the hash code for this instance.
+ ///
+ /// The hash code.
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 17;
+ hash = (hash * 23) + X.GetHashCode();
+ hash = (hash * 23) + Y.GetHashCode();
+ hash = (hash * 23) + Width.GetHashCode();
+ hash = (hash * 23) + Height.GetHashCode();
+ return hash;
+ }
+ }
+
+ ///
+ /// Gets the intersection of two rectangles.
+ ///
+ /// The other rectangle.
+ /// The intersection.
+ public PixelRect Intersect(PixelRect rect)
+ {
+ var newLeft = (rect.X > X) ? rect.X : X;
+ var newTop = (rect.Y > Y) ? rect.Y : Y;
+ var newRight = (rect.Right < Right) ? rect.Right : Right;
+ var newBottom = (rect.Bottom < Bottom) ? rect.Bottom : Bottom;
+
+ if ((newRight > newLeft) && (newBottom > newTop))
+ {
+ return new PixelRect(newLeft, newTop, newRight - newLeft, newBottom - newTop);
+ }
+ else
+ {
+ return Empty;
+ }
+ }
+
+ ///
+ /// Determines whether a rectangle intersects with this rectangle.
+ ///
+ /// The other rectangle.
+ ///
+ /// True if the specified rectangle intersects with this one; otherwise false.
+ ///
+ public bool Intersects(PixelRect rect)
+ {
+ return (rect.X < Right) && (X < rect.Right) && (rect.Y < Bottom) && (Y < rect.Bottom);
+ }
+
+ ///
+ /// Gets the union of two rectangles.
+ ///
+ /// The other rectangle.
+ /// The union.
+ public PixelRect Union(PixelRect rect)
+ {
+ if (IsEmpty)
+ {
+ return rect;
+ }
+ else if (rect.IsEmpty)
+ {
+ return this;
+ }
+ else
+ {
+ var x1 = Math.Min(X, rect.X);
+ var x2 = Math.Max(Right, rect.Right);
+ var y1 = Math.Min(Y, rect.Y);
+ var y2 = Math.Max(Bottom, rect.Bottom);
+
+ return new PixelRect(new PixelPoint(x1, y1), new PixelPoint(x2, y2));
+ }
+ }
+
+ ///
+ /// Returns a new with the specified X position.
+ ///
+ /// The x position.
+ /// The new .
+ public PixelRect WithX(int x)
+ {
+ return new PixelRect(x, Y, Width, Height);
+ }
+
+ ///
+ /// Returns a new with the specified Y position.
+ ///
+ /// The y position.
+ /// The new .
+ public PixelRect WithY(int y)
+ {
+ return new PixelRect(X, y, Width, Height);
+ }
+
+ ///
+ /// Returns a new with the specified width.
+ ///
+ /// The width.
+ /// The new .
+ public PixelRect WithWidth(int width)
+ {
+ return new PixelRect(X, Y, width, Height);
+ }
+
+ ///
+ /// Returns a new with the specified height.
+ ///
+ /// The height.
+ /// The new .
+ public PixelRect WithHeight(int height)
+ {
+ return new PixelRect(X, Y, Width, Height);
+ }
+
+ ///
+ /// Converts the to a device-independent using the
+ /// specified scaling factor.
+ ///
+ /// The scaling factor.
+ /// The device-independent rect.
+ public Rect ToRect(double scale) => new Rect(Position.ToPoint(scale), Size.ToSize(scale));
+
+ ///
+ /// Converts the to a device-independent using the
+ /// specified scaling factor.
+ ///
+ /// The scaling factor.
+ /// The device-independent rect.
+ public Rect ToRect(Vector scale) => new Rect(Position.ToPoint(scale), Size.ToSize(scale));
+
+ ///
+ /// Converts the to a device-independent using the
+ /// specified dots per inch (DPI).
+ ///
+ /// The dots per inch of the device.
+ /// The device-independent rect.
+ public Rect ToRectWithDpi(double dpi) => new Rect(Position.ToPointWithDpi(dpi), Size.ToSizeWithDpi(dpi));
+
+ ///
+ /// Converts the to a device-independent using the
+ /// specified dots per inch (DPI).
+ ///
+ /// The dots per inch of the device.
+ /// The device-independent rect.
+ public Rect ToRectWithDpi(Vector dpi) => new Rect(Position.ToPointWithDpi(dpi), Size.ToSizeWithDpi(dpi));
+
+ ///
+ /// Converts a to device pixels using the specified scaling factor.
+ ///
+ /// The rect.
+ /// The scaling factor.
+ /// The device-independent rect.
+ public static PixelRect FromRect(Rect rect, double scale) => new PixelRect(
+ PixelPoint.FromPoint(rect.Position, scale),
+ PixelSize.FromSize(rect.Size, scale));
+
+ ///
+ /// Converts a to device pixels using the specified scaling factor.
+ ///
+ /// The rect.
+ /// The scaling factor.
+ /// The device-independent point.
+ public static PixelRect FromRect(Rect rect, Vector scale) => new PixelRect(
+ PixelPoint.FromPoint(rect.Position, scale),
+ PixelSize.FromSize(rect.Size, scale));
+
+ ///
+ /// Converts a to device pixels using the specified dots per inch (DPI).
+ ///
+ /// The rect.
+ /// The dots per inch of the device.
+ /// The device-independent point.
+ public static PixelRect FromRectWithDpi(Rect rect, double dpi) => new PixelRect(
+ PixelPoint.FromPointWithDpi(rect.Position, dpi),
+ PixelSize.FromSizeWithDpi(rect.Size, dpi));
+
+ ///
+ /// Converts a to device pixels using the specified dots per inch (DPI).
+ ///
+ /// The rect.
+ /// The dots per inch of the device.
+ /// The device-independent point.
+ public static PixelRect FromRectWithDpi(Rect rect, Vector dpi) => new PixelRect(
+ PixelPoint.FromPointWithDpi(rect.Position, dpi),
+ PixelSize.FromSizeWithDpi(rect.Size, dpi));
+
+ ///
+ /// Returns the string representation of the rectangle.
+ ///
+ /// The string representation of the rectangle.
+ public override string ToString()
+ {
+ return string.Format(
+ CultureInfo.InvariantCulture,
+ "{0}, {1}, {2}, {3}",
+ X,
+ Y,
+ Width,
+ Height);
+ }
+
+ ///
+ /// Parses a string.
+ ///
+ /// The string.
+ /// The parsed .
+ public static PixelRect Parse(string s)
+ {
+ using (var tokenizer = new StringTokenizer(s, CultureInfo.InvariantCulture, exceptionMessage: "Invalid PixelRect"))
+ {
+ return new PixelRect(
+ tokenizer.ReadInt32(),
+ tokenizer.ReadInt32(),
+ tokenizer.ReadInt32(),
+ tokenizer.ReadInt32()
+ );
+ }
+ }
+ }
+}
diff --git a/src/Avalonia.Visuals/Media/PixelSize.cs b/src/Avalonia.Visuals/Media/PixelSize.cs
index 6785b51716..b903b804f9 100644
--- a/src/Avalonia.Visuals/Media/PixelSize.cs
+++ b/src/Avalonia.Visuals/Media/PixelSize.cs
@@ -72,7 +72,7 @@ namespace Avalonia
/// The .
public static PixelSize Parse(string s)
{
- using (var tokenizer = new StringTokenizer(s, CultureInfo.InvariantCulture, exceptionMessage: "Invalid Size"))
+ using (var tokenizer = new StringTokenizer(s, CultureInfo.InvariantCulture, exceptionMessage: "Invalid PixelSize"))
{
return new PixelSize(
tokenizer.ReadInt32(),
@@ -126,13 +126,29 @@ namespace Avalonia
/// The new .
public PixelSize WithHeight(int height) => new PixelSize(Width, height);
+ ///
+ /// Converts the to a device-independent using the
+ /// specified scaling factor.
+ ///
+ /// The scaling factor.
+ /// The device-independent size.
+ public Size ToSize(double scale) => new Size(Width / scale, Height / scale);
+
+ ///
+ /// Converts the to a device-independent using the
+ /// specified scaling factor.
+ ///
+ /// The scaling factor.
+ /// The device-independent size.
+ public Size ToSize(Vector scale) => new Size(Width / scale.X, Height / scale.Y);
+
///
/// Converts the to a device-independent using the
/// specified dots per inch (DPI).
///
/// The dots per inch.
/// The device-independent size.
- public Size ToSize(double dpi) => new Size(Width / (dpi / 96), Height / (dpi / 96));
+ public Size ToSizeWithDpi(double dpi) => ToSize(dpi / 96);
///
/// Converts the to a device-independent using the
@@ -140,7 +156,27 @@ namespace Avalonia
///
/// The dots per inch.
/// The device-independent size.
- public Size ToSize(Vector dpi) => new Size(Width / (dpi.X / 96), Height / (dpi.Y / 96));
+ public Size ToSizeWithDpi(Vector dpi) => ToSize(new Vector(dpi.X / 96, dpi.Y / 96));
+
+ ///
+ /// Converts a to device pixels using the specified scaling factor.
+ ///
+ /// The size.
+ /// The scaling factor.
+ /// The device-independent size.
+ public static PixelSize FromSize(Size size, double scale) => new PixelSize(
+ (int)Math.Ceiling(size.Width * scale),
+ (int)Math.Ceiling(size.Height * scale));
+
+ ///
+ /// Converts a to device pixels using the specified scaling factor.
+ ///
+ /// The size.
+ /// The scaling factor.
+ /// The device-independent size.
+ public static PixelSize FromSize(Size size, Vector scale) => new PixelSize(
+ (int)Math.Ceiling(size.Width * scale.X),
+ (int)Math.Ceiling(size.Height * scale.Y));
///
/// Converts a to device pixels using the specified dots per inch (DPI).
@@ -148,9 +184,7 @@ namespace Avalonia
/// The size.
/// The dots per inch.
/// The device-independent size.
- public static PixelSize FromSize(Size size, double dpi) => new PixelSize(
- (int)(size.Width * (dpi / 96)),
- (int)(size.Height * (dpi / 96)));
+ public static PixelSize FromSizeWithDpi(Size size, double dpi) => FromSize(size, dpi / 96);
///
/// Converts a to device pixels using the specified dots per inch (DPI).
@@ -158,9 +192,7 @@ namespace Avalonia
/// The size.
/// The dots per inch.
/// The device-independent size.
- public static PixelSize FromSize(Size size, Vector dpi) => new PixelSize(
- (int)Math.Ceiling(size.Width * (dpi.X / 96)),
- (int)Math.Ceiling(size.Height * (dpi.Y / 96)));
+ public static PixelSize FromSizeWithDpi(Size size, Vector dpi) => FromSize(size, new Vector(dpi.X / 96, dpi.Y / 96));
///
/// Returns the string representation of the size.
diff --git a/src/Avalonia.Visuals/Media/SolidColorBrush.cs b/src/Avalonia.Visuals/Media/SolidColorBrush.cs
index 32b87df56b..bacb9e4ad7 100644
--- a/src/Avalonia.Visuals/Media/SolidColorBrush.cs
+++ b/src/Avalonia.Visuals/Media/SolidColorBrush.cs
@@ -1,6 +1,8 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
+using Avalonia.Animation;
+using Avalonia.Animation.Animators;
using Avalonia.Media.Immutable;
namespace Avalonia.Media
@@ -18,6 +20,7 @@ namespace Avalonia.Media
static SolidColorBrush()
{
+ Animation.Animation.RegisterAnimator(prop => typeof(IBrush).IsAssignableFrom(prop.PropertyType));
AffectsRender(ColorProperty);
}
diff --git a/src/Avalonia.Visuals/Media/Transform.cs b/src/Avalonia.Visuals/Media/Transform.cs
index 677514763c..7a70657ce0 100644
--- a/src/Avalonia.Visuals/Media/Transform.cs
+++ b/src/Avalonia.Visuals/Media/Transform.cs
@@ -3,6 +3,7 @@
using System;
using Avalonia.Animation;
+using Avalonia.Animation.Animators;
using Avalonia.VisualTree;
namespace Avalonia.Media
diff --git a/src/Avalonia.Visuals/Media/Typeface.cs b/src/Avalonia.Visuals/Media/Typeface.cs
index 6dde2bb591..37ac0953bf 100644
--- a/src/Avalonia.Visuals/Media/Typeface.cs
+++ b/src/Avalonia.Visuals/Media/Typeface.cs
@@ -7,7 +7,7 @@ namespace Avalonia.Media
///
public class Typeface
{
- public static Typeface Default = new Typeface(FontFamily.Default);
+ public static readonly Typeface Default = new Typeface(FontFamily.Default);
///
/// Initializes a new instance of the class.
diff --git a/src/Avalonia.Visuals/Platform/IPlatformRenderInterface.cs b/src/Avalonia.Visuals/Platform/IPlatformRenderInterface.cs
index aacdef0538..3a1f79e32a 100644
--- a/src/Avalonia.Visuals/Platform/IPlatformRenderInterface.cs
+++ b/src/Avalonia.Visuals/Platform/IPlatformRenderInterface.cs
@@ -13,6 +13,11 @@ namespace Avalonia.Platform
///
public interface IPlatformRenderInterface
{
+ ///
+ /// Get all installed fonts in the system
+ ///
+ IEnumerable InstalledFontNames { get; }
+
///
/// Creates a formatted text implementation.
///
diff --git a/src/Avalonia.Visuals/Point.cs b/src/Avalonia.Visuals/Point.cs
index e74094fe50..0d3e354615 100644
--- a/src/Avalonia.Visuals/Point.cs
+++ b/src/Avalonia.Visuals/Point.cs
@@ -2,6 +2,7 @@
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System.Globalization;
+using Avalonia.Animation.Animators;
using Avalonia.Utilities;
namespace Avalonia
@@ -11,6 +12,11 @@ namespace Avalonia
///
public readonly struct Point
{
+ static Point()
+ {
+ Animation.Animation.RegisterAnimator(prop => typeof(Point).IsAssignableFrom(prop.PropertyType));
+ }
+
///
/// The X position.
///
@@ -133,7 +139,7 @@ namespace Avalonia
/// Point to multiply
/// Factor
/// Points having its coordinates multiplied
- public static Point operator *(Point p, double k) => new Point(p.X*k, p.Y*k);
+ public static Point operator *(Point p, double k) => new Point(p.X * k, p.Y * k);
///
/// Multiplies a point by a factor coordinate-wise
@@ -141,7 +147,7 @@ namespace Avalonia
/// Point to multiply
/// Factor
/// Points having its coordinates multiplied
- public static Point operator *(double k, Point p) => new Point(p.X*k, p.Y*k);
+ public static Point operator *(double k, Point p) => new Point(p.X * k, p.Y * k);
///
/// Divides a point by a factor coordinate-wise
@@ -149,8 +155,8 @@ namespace Avalonia
/// Point to divide by
/// Factor
/// Points having its coordinates divided
- public static Point operator /(Point p, double k) => new Point(p.X/k, p.Y/k);
-
+ public static Point operator /(Point p, double k) => new Point(p.X / k, p.Y / k);
+
///
/// Applies a matrix to a point.
///
diff --git a/src/Avalonia.Visuals/Rect.cs b/src/Avalonia.Visuals/Rect.cs
index 63d34b474b..530a47729f 100644
--- a/src/Avalonia.Visuals/Rect.cs
+++ b/src/Avalonia.Visuals/Rect.cs
@@ -3,6 +3,7 @@
using System;
using System.Globalization;
+using Avalonia.Animation.Animators;
using Avalonia.Utilities;
namespace Avalonia
@@ -12,6 +13,11 @@ namespace Avalonia
///
public readonly struct Rect
{
+ static Rect()
+ {
+ Animation.Animation.RegisterAnimator(prop => typeof(Rect).IsAssignableFrom(prop.PropertyType));
+ }
+
///
/// An empty rectangle.
///
diff --git a/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs b/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs
index b48efaa34e..60e624948e 100644
--- a/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs
+++ b/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs
@@ -29,6 +29,7 @@ namespace Avalonia.Rendering
private readonly ISceneBuilder _sceneBuilder;
private bool _running;
+ private bool _disposed;
private volatile IRef _scene;
private DirtyVisuals _dirty;
private IRef _overlay;
@@ -99,6 +100,9 @@ namespace Avalonia.Rendering
///
public string DebugFramesPath { get; set; }
+ ///
+ public event EventHandler SceneInvalidated;
+
///
/// Gets the render layers.
///
@@ -122,15 +126,34 @@ namespace Avalonia.Rendering
{
lock (_sceneLock)
{
+ if (_disposed)
+ return;
+ _disposed = true;
var scene = _scene;
_scene = null;
scene?.Dispose();
}
Stop();
+ DisposeRenderTarget();
+ }
+
+ void DisposeRenderTarget()
+ {
+ using (var l = _lock.TryLock())
+ {
+ if(l == null)
+ {
+ // We are still trying to render on the render thread, try again a bit later
+ DispatcherTimer.RunOnce(DisposeRenderTarget, TimeSpan.FromMilliseconds(50),
+ DispatcherPriority.Background);
+ return;
+ }
- Layers.Clear();
- RenderTarget?.Dispose();
+ Layers.Clear();
+ RenderTarget?.Dispose();
+ RenderTarget = null;
+ }
}
///
@@ -152,7 +175,8 @@ namespace Avalonia.Rendering
var t = (IRenderLoopTask)this;
if(t.NeedsUpdate)
UpdateScene();
- Render(true);
+ if(_scene?.Item != null)
+ Render(true);
}
///
@@ -336,16 +360,34 @@ namespace Avalonia.Rendering
private void RenderToLayers(Scene scene)
{
- if (scene.Layers.HasDirty)
+ foreach (var layer in scene.Layers)
{
- foreach (var layer in scene.Layers)
- {
- var renderTarget = Layers[layer.LayerRoot].Bitmap;
- var node = (VisualNode)scene.FindNode(layer.LayerRoot);
+ var renderLayer = Layers[layer.LayerRoot];
+ if (layer.Dirty.IsEmpty && !renderLayer.IsEmpty)
+ continue;
+ var renderTarget = renderLayer.Bitmap;
+ var node = (VisualNode)scene.FindNode(layer.LayerRoot);
- if (node != null)
+ if (node != null)
+ {
+ using (var context = renderTarget.Item.CreateDrawingContext(this))
{
- using (var context = renderTarget.Item.CreateDrawingContext(this))
+ if (renderLayer.IsEmpty)
+ {
+ // Render entire layer root node
+ context.Clear(Colors.Transparent);
+ context.Transform = Matrix.Identity;
+ context.PushClip(node.ClipBounds);
+ Render(context, node, layer.LayerRoot, node.ClipBounds);
+ context.PopClip();
+ if (DrawDirtyRects)
+ {
+ _dirtyRectsDisplay.Add(node.ClipBounds);
+ }
+
+ renderLayer.IsEmpty = false;
+ }
+ else
{
foreach (var rect in layer.Dirty)
{
@@ -364,6 +406,7 @@ namespace Avalonia.Rendering
}
}
}
+
}
private void RenderOverlay(Scene scene, IDrawingContextImpl parentContent)
@@ -442,6 +485,8 @@ namespace Avalonia.Rendering
Dispatcher.UIThread.VerifyAccess();
lock (_sceneLock)
{
+ if (_disposed)
+ return;
if (_scene?.Item.Generation > _lastSceneId)
return;
}
@@ -470,6 +515,21 @@ namespace Avalonia.Rendering
oldScene?.Dispose();
}
+ if (SceneInvalidated != null)
+ {
+ var rect = new Rect();
+
+ foreach (var layer in scene.Layers)
+ {
+ foreach (var dirty in layer.Dirty)
+ {
+ rect = rect.Union(dirty);
+ }
+ }
+
+ SceneInvalidated(this, new SceneInvalidatedEventArgs((IRenderRoot)_root, rect));
+ }
+
_dirty.Clear();
}
else
diff --git a/src/Avalonia.Visuals/Rendering/IRenderRoot.cs b/src/Avalonia.Visuals/Rendering/IRenderRoot.cs
index 2b364e5d22..044911ca95 100644
--- a/src/Avalonia.Visuals/Rendering/IRenderRoot.cs
+++ b/src/Avalonia.Visuals/Rendering/IRenderRoot.cs
@@ -41,15 +41,15 @@ namespace Avalonia.Rendering
///
/// Converts a point from screen to client coordinates.
///
- /// The point in screen coordinates.
+ /// The point in screen device coordinates.
/// The point in client coordinates.
- Point PointToClient(Point point);
+ Point PointToClient(PixelPoint point);
///
/// Converts a point from client to screen coordinates.
///
/// The point in client coordinates.
- /// The point in screen coordinates.
- Point PointToScreen(Point point);
+ /// The point in screen device coordinates.
+ PixelPoint PointToScreen(Point point);
}
}
diff --git a/src/Avalonia.Visuals/Rendering/IRenderer.cs b/src/Avalonia.Visuals/Rendering/IRenderer.cs
index 9085e63aa9..36a1f7d220 100644
--- a/src/Avalonia.Visuals/Rendering/IRenderer.cs
+++ b/src/Avalonia.Visuals/Rendering/IRenderer.cs
@@ -18,11 +18,20 @@ namespace Avalonia.Rendering
bool DrawFps { get; set; }
///
- /// Gets or sets a value indicating whether the renderer should a visual representation
+ /// Gets or sets a value indicating whether the renderer should draw a visual representation
/// of its dirty rectangles.
///
bool DrawDirtyRects { get; set; }
+ ///
+ /// Raised when a portion of the scene has been invalidated.
+ ///
+ ///
+ /// Indicates that the underlying low-level scene information has been updated. Used to
+ /// signal that an update to the current pointer-over state may be required.
+ ///
+ event EventHandler SceneInvalidated;
+
///
/// Mark a visual as dirty and needing re-rendering.
///
@@ -63,4 +72,4 @@ namespace Avalonia.Rendering
///
void Stop();
}
-}
\ No newline at end of file
+}
diff --git a/src/Avalonia.Visuals/Rendering/ImmediateRenderer.cs b/src/Avalonia.Visuals/Rendering/ImmediateRenderer.cs
index 08f3803e9b..21129e38af 100644
--- a/src/Avalonia.Visuals/Rendering/ImmediateRenderer.cs
+++ b/src/Avalonia.Visuals/Rendering/ImmediateRenderer.cs
@@ -42,6 +42,9 @@ namespace Avalonia.Rendering
///
public bool DrawDirtyRects { get; set; }
+ ///
+ public event EventHandler SceneInvalidated;
+
///
public void Paint(Rect rect)
{
@@ -81,6 +84,8 @@ namespace Avalonia.Rendering
_renderTarget.Dispose();
_renderTarget = null;
}
+
+ SceneInvalidated?.Invoke(this, new SceneInvalidatedEventArgs((IRenderRoot)_root, rect));
}
///
@@ -266,7 +271,14 @@ namespace Avalonia.Rendering
if (clipToBounds)
{
- clipRect = clipRect.Intersect(new Rect(visual.Bounds.Size));
+ if (visual.RenderTransform != null)
+ {
+ clipRect = new Rect(visual.Bounds.Size);
+ }
+ else
+ {
+ clipRect = clipRect.Intersect(new Rect(visual.Bounds.Size));
+ }
}
using (context.PushPostTransform(m))
diff --git a/src/Avalonia.Visuals/Rendering/RenderLayer.cs b/src/Avalonia.Visuals/Rendering/RenderLayer.cs
index cd09bdee10..d6676e25ff 100644
--- a/src/Avalonia.Visuals/Rendering/RenderLayer.cs
+++ b/src/Avalonia.Visuals/Rendering/RenderLayer.cs
@@ -7,39 +7,39 @@ namespace Avalonia.Rendering
{
public class RenderLayer
{
- private readonly IDrawingContextImpl _drawingContext;
-
public RenderLayer(
IDrawingContextImpl drawingContext,
Size size,
double scaling,
IVisual layerRoot)
{
- _drawingContext = drawingContext;
Bitmap = RefCountable.Create(drawingContext.CreateLayer(size));
Size = size;
Scaling = scaling;
LayerRoot = layerRoot;
+ IsEmpty = true;
}
public IRef Bitmap { get; private set; }
+ public bool IsEmpty { get; set; }
public double Scaling { get; private set; }
public Size Size { get; private set; }
public IVisual LayerRoot { get; }
- public void ResizeBitmap(Size size, double scaling)
+ public void RecreateBitmap(IDrawingContextImpl drawingContext, Size size, double scaling)
{
if (Size != size || Scaling != scaling)
{
- var resized = RefCountable.Create(_drawingContext.CreateLayer(size));
+ var resized = RefCountable.Create(drawingContext.CreateLayer(size));
using (var context = resized.Item.CreateDrawingContext(null))
{
context.Clear(Colors.Transparent);
- context.DrawImage(Bitmap, 1, new Rect(Size), new Rect(Size));
Bitmap.Dispose();
Bitmap = resized;
+ Scaling = scaling;
Size = size;
+ IsEmpty = true;
}
}
}
diff --git a/src/Avalonia.Visuals/Rendering/RenderLayers.cs b/src/Avalonia.Visuals/Rendering/RenderLayers.cs
index 9b0ce944e7..0ff7862ab6 100644
--- a/src/Avalonia.Visuals/Rendering/RenderLayers.cs
+++ b/src/Avalonia.Visuals/Rendering/RenderLayers.cs
@@ -29,11 +29,11 @@ namespace Avalonia.Rendering
}
else
{
- layer.ResizeBitmap(scene.Size, scene.Scaling);
+ layer.RecreateBitmap(context, scene.Size, scene.Scaling);
}
}
- for (var i = _inner.Count - 1; i >= 0; --i)
+ for (var i = 0; i < _inner.Count;)
{
var layer = _inner[i];
@@ -43,6 +43,8 @@ namespace Avalonia.Rendering
_inner.RemoveAt(i);
_index.Remove(layer.LayerRoot);
}
+ else
+ i++;
}
}
diff --git a/src/Avalonia.Visuals/Rendering/SceneGraph/Scene.cs b/src/Avalonia.Visuals/Rendering/SceneGraph/Scene.cs
index ffa0b0bcc5..ad4c475d89 100644
--- a/src/Avalonia.Visuals/Rendering/SceneGraph/Scene.cs
+++ b/src/Avalonia.Visuals/Rendering/SceneGraph/Scene.cs
@@ -160,7 +160,7 @@ namespace Avalonia.Rendering.SceneGraph
private IEnumerable HitTest(IVisualNode node, Point p, Rect? clip, Func filter)
{
- if (filter?.Invoke(node.Visual) != false)
+ if (filter?.Invoke(node.Visual) != false && node.Visual.IsAttachedToVisualTree)
{
var clipped = false;
@@ -186,7 +186,7 @@ namespace Avalonia.Rendering.SceneGraph
}
}
- if (node.HitTest(p) && node.Visual.IsAttachedToVisualTree)
+ if (node.HitTest(p))
{
yield return node.Visual;
}
diff --git a/src/Avalonia.Visuals/Rendering/SceneGraph/VisualNode.cs b/src/Avalonia.Visuals/Rendering/SceneGraph/VisualNode.cs
index 8000d413ea..159c3cd0fa 100644
--- a/src/Avalonia.Visuals/Rendering/SceneGraph/VisualNode.cs
+++ b/src/Avalonia.Visuals/Rendering/SceneGraph/VisualNode.cs
@@ -220,6 +220,7 @@ namespace Avalonia.Rendering.SceneGraph
Transform = Transform,
ClipBounds = ClipBounds,
ClipToBounds = ClipToBounds,
+ LayoutBounds = LayoutBounds,
GeometryClip = GeometryClip,
_opacity = Opacity,
OpacityMask = OpacityMask,
diff --git a/src/Avalonia.Visuals/Rendering/SceneInvalidatedEventArgs.cs b/src/Avalonia.Visuals/Rendering/SceneInvalidatedEventArgs.cs
new file mode 100644
index 0000000000..40cb9f3356
--- /dev/null
+++ b/src/Avalonia.Visuals/Rendering/SceneInvalidatedEventArgs.cs
@@ -0,0 +1,36 @@
+// Copyright (c) The Avalonia Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using System;
+
+namespace Avalonia.Rendering
+{
+ ///
+ /// Provides data for the event.
+ ///
+ public class SceneInvalidatedEventArgs : EventArgs
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The render root that has been updated.
+ /// The updated area.
+ public SceneInvalidatedEventArgs(
+ IRenderRoot root,
+ Rect dirtyRect)
+ {
+ RenderRoot = root;
+ DirtyRect = dirtyRect;
+ }
+
+ ///
+ /// Gets the invalidated area.
+ ///
+ public Rect DirtyRect { get; }
+
+ ///
+ /// Gets the render root that has been invalidated.
+ ///
+ public IRenderRoot RenderRoot { get; }
+ }
+}
diff --git a/src/Avalonia.Visuals/Size.cs b/src/Avalonia.Visuals/Size.cs
index 8057571bf1..782c5ea67b 100644
--- a/src/Avalonia.Visuals/Size.cs
+++ b/src/Avalonia.Visuals/Size.cs
@@ -3,6 +3,7 @@
using System;
using System.Globalization;
+using Avalonia.Animation.Animators;
using Avalonia.Utilities;
namespace Avalonia
@@ -12,6 +13,11 @@ namespace Avalonia
///
public readonly struct Size
{
+ static Size()
+ {
+ Animation.Animation.RegisterAnimator(prop => typeof(Size).IsAssignableFrom(prop.PropertyType));
+ }
+
///
/// A size representing infinity.
///
diff --git a/src/Avalonia.Visuals/Thickness.cs b/src/Avalonia.Visuals/Thickness.cs
index 3e70ecafb1..830ee4666e 100644
--- a/src/Avalonia.Visuals/Thickness.cs
+++ b/src/Avalonia.Visuals/Thickness.cs
@@ -3,6 +3,8 @@
using System;
using System.Globalization;
+using Avalonia.Animation;
+using Avalonia.Animation.Animators;
using Avalonia.Utilities;
namespace Avalonia
@@ -12,6 +14,11 @@ namespace Avalonia
///
public readonly struct Thickness
{
+ static Thickness()
+ {
+ Animation.Animation.RegisterAnimator(prop => typeof(Thickness).IsAssignableFrom(prop.PropertyType));
+ }
+
///
/// The thickness on the left.
///
@@ -134,6 +141,36 @@ namespace Avalonia
a.Bottom + b.Bottom);
}
+ ///
+ /// Subtracts two Thicknesses.
+ ///
+ /// The first thickness.
+ /// The second thickness.
+ /// The equality.
+ public static Thickness operator -(Thickness a, Thickness b)
+ {
+ return new Thickness(
+ a.Left - b.Left,
+ a.Top - b.Top,
+ a.Right - b.Right,
+ a.Bottom - b.Bottom);
+ }
+
+ ///
+ /// Multiplies a Thickness to a scalar.
+ ///
+ /// The thickness.
+ /// The scalar.
+ /// The equality.
+ public static Thickness operator *(Thickness a, double b)
+ {
+ return new Thickness(
+ a.Left * b,
+ a.Top * b,
+ a.Right * b,
+ a.Bottom * b);
+ }
+
///
/// Adds a Thickness to a Size.
///
@@ -169,7 +206,7 @@ namespace Avalonia
{
using (var tokenizer = new StringTokenizer(s, CultureInfo.InvariantCulture, exceptionMessage: "Invalid Thickness"))
{
- if(tokenizer.TryReadDouble(out var a))
+ if (tokenizer.TryReadDouble(out var a))
{
if (tokenizer.TryReadDouble(out var b))
{
diff --git a/src/Avalonia.Visuals/Vector.cs b/src/Avalonia.Visuals/Vector.cs
index c2db17cd86..2f1690184d 100644
--- a/src/Avalonia.Visuals/Vector.cs
+++ b/src/Avalonia.Visuals/Vector.cs
@@ -3,6 +3,7 @@
using System;
using System.Globalization;
+using Avalonia.Animation.Animators;
using JetBrains.Annotations;
namespace Avalonia
@@ -12,6 +13,11 @@ namespace Avalonia
///
public readonly struct Vector
{
+ static Vector()
+ {
+ Animation.Animation.RegisterAnimator(prop => typeof(Vector).IsAssignableFrom(prop.PropertyType));
+ }
+
///
/// The X vector.
///
@@ -60,7 +66,7 @@ namespace Avalonia
/// The dot product
public static double operator *(Vector a, Vector b)
{
- return a.X*b.X + a.Y*b.Y;
+ return a.X * b.X + a.Y * b.Y;
}
///
@@ -88,7 +94,7 @@ namespace Avalonia
///
/// Length of the vector
///
- public double Length => Math.Sqrt(X*X + Y*Y);
+ public double Length => Math.Sqrt(X * X + Y * Y);
///
/// Negates a vector.
diff --git a/src/Avalonia.Visuals/VisualExtensions.cs b/src/Avalonia.Visuals/VisualExtensions.cs
index 7c5d011ce8..650921a985 100644
--- a/src/Avalonia.Visuals/VisualExtensions.cs
+++ b/src/Avalonia.Visuals/VisualExtensions.cs
@@ -18,10 +18,12 @@ namespace Avalonia
/// The visual.
/// The point in screen coordinates.
/// The point in client coordinates.
- public static Point PointToClient(this IVisual visual, Point point)
+ public static Point PointToClient(this IVisual visual, PixelPoint point)
{
- var p = GetRootAndPosition(visual);
- return p.Item1.PointToClient(point - p.Item2);
+ var (root, offset) = GetRootAndPosition(visual);
+ var screenOffset = PixelPoint.FromPoint((Point)offset, root.RenderScaling);
+ var screenPoint = new PixelPoint(point.X - screenOffset.X, point.Y - screenOffset.Y);
+ return root.PointToClient(screenPoint);
}
///
@@ -30,7 +32,7 @@ namespace Avalonia
/// The visual.
/// The point in client coordinates.
/// The point in screen coordinates.
- public static Point PointToScreen(this IVisual visual, Point point)
+ public static PixelPoint PointToScreen(this IVisual visual, Point point)
{
var p = GetRootAndPosition(visual);
return p.Item1.PointToScreen(point + p.Item2);
diff --git a/src/Avalonia.X11/Avalonia.X11.csproj b/src/Avalonia.X11/Avalonia.X11.csproj
new file mode 100644
index 0000000000..087ba017ae
--- /dev/null
+++ b/src/Avalonia.X11/Avalonia.X11.csproj
@@ -0,0 +1,14 @@
+
+
+
+ netstandard2.0
+ true
+
+
+
+
+
+
+
+
+
diff --git a/src/Avalonia.X11/Keysyms.cs b/src/Avalonia.X11/Keysyms.cs
new file mode 100644
index 0000000000..651a06f574
--- /dev/null
+++ b/src/Avalonia.X11/Keysyms.cs
@@ -0,0 +1,2108 @@
+// ReSharper disable UnusedMember.Global
+// ReSharper disable IdentifierTypo
+// ReSharper disable CommentTypo
+namespace Avalonia.X11
+{
+ enum X11Key
+ {
+ VoidSymbol = 0xffffff /* Void symbol */,
+ BackSpace = 0xff08 /* Back space, back char */,
+ Tab = 0xff09,
+ Linefeed = 0xff0a /* Linefeed, LF */,
+ Clear = 0xff0b,
+ Return = 0xff0d /* Return, enter */,
+ Pause = 0xff13 /* Pause, hold */,
+ Scroll_Lock = 0xff14,
+ Sys_Req = 0xff15,
+ Escape = 0xff1b,
+ Delete = 0xffff /* Delete, rubout */,
+ Multi_key = 0xff20 /* Multi-key character compose */,
+ Codeinput = 0xff37,
+ SingleCandidate = 0xff3c,
+ MultipleCandidate = 0xff3d,
+ PreviousCandidate = 0xff3e,
+ Kanji = 0xff21 /* Kanji, Kanji convert */,
+ Muhenkan = 0xff22 /* Cancel Conversion */,
+ Henkan_Mode = 0xff23 /* Start/Stop Conversion */,
+ Henkan = 0xff23 /* Alias for Henkan_Mode */,
+ Romaji = 0xff24 /* to Romaji */,
+ Hiragana = 0xff25 /* to Hiragana */,
+ Katakana = 0xff26 /* to Katakana */,
+ Hiragana_Katakana = 0xff27 /* Hiragana/Katakana toggle */,
+ Zenkaku = 0xff28 /* to Zenkaku */,
+ Hankaku = 0xff29 /* to Hankaku */,
+ Zenkaku_Hankaku = 0xff2a /* Zenkaku/Hankaku toggle */,
+ Touroku = 0xff2b /* Add to Dictionary */,
+ Massyo = 0xff2c /* Delete from Dictionary */,
+ Kana_Lock = 0xff2d /* Kana Lock */,
+ Kana_Shift = 0xff2e /* Kana Shift */,
+ Eisu_Shift = 0xff2f /* Alphanumeric Shift */,
+ Eisu_toggle = 0xff30 /* Alphanumeric toggle */,
+ Kanji_Bangou = 0xff37 /* Codeinput */,
+ Zen_Koho = 0xff3d /* Multiple/All Candidate(s) */,
+ Mae_Koho = 0xff3e /* Previous Candidate */,
+ Home = 0xff50,
+ Left = 0xff51 /* Move left, left arrow */,
+ Up = 0xff52 /* Move up, up arrow */,
+ Right = 0xff53 /* Move right, right arrow */,
+ Down = 0xff54 /* Move down, down arrow */,
+ Prior = 0xff55 /* Prior, previous */,
+ Page_Up = 0xff55,
+ Next = 0xff56 /* Next */,
+ Page_Down = 0xff56,
+ End = 0xff57 /* EOL */,
+ Begin = 0xff58 /* BOL */,
+ Select = 0xff60 /* Select, mark */,
+ Print = 0xff61,
+ Execute = 0xff62 /* Execute, run, do */,
+ Insert = 0xff63 /* Insert, insert here */,
+ Undo = 0xff65,
+ Redo = 0xff66 /* Redo, again */,
+ Menu = 0xff67,
+ Find = 0xff68 /* Find, search */,
+ Cancel = 0xff69 /* Cancel, stop, abort, exit */,
+ Help = 0xff6a /* Help */,
+ Break = 0xff6b,
+ Mode_switch = 0xff7e /* Character set switch */,
+ script_switch = 0xff7e /* Alias for mode_switch */,
+ Num_Lock = 0xff7f,
+ KP_Space = 0xff80 /* Space */,
+ KP_Tab = 0xff89,
+ KP_Enter = 0xff8d /* Enter */,
+ KP_F1 = 0xff91 /* PF1, KP_A, ... */,
+ KP_F2 = 0xff92,
+ KP_F3 = 0xff93,
+ KP_F4 = 0xff94,
+ KP_Home = 0xff95,
+ KP_Left = 0xff96,
+ KP_Up = 0xff97,
+ KP_Right = 0xff98,
+ KP_Down = 0xff99,
+ KP_Prior = 0xff9a,
+ KP_Page_Up = 0xff9a,
+ KP_Next = 0xff9b,
+ KP_Page_Down = 0xff9b,
+ KP_End = 0xff9c,
+ KP_Begin = 0xff9d,
+ KP_Insert = 0xff9e,
+ KP_Delete = 0xff9f,
+ KP_Equal = 0xffbd /* Equals */,
+ KP_Multiply = 0xffaa,
+ KP_Add = 0xffab,
+ KP_Separator = 0xffac /* Separator, often comma */,
+ KP_Subtract = 0xffad,
+ KP_Decimal = 0xffae,
+ KP_Divide = 0xffaf,
+ KP_0 = 0xffb0,
+ KP_1 = 0xffb1,
+ KP_2 = 0xffb2,
+ KP_3 = 0xffb3,
+ KP_4 = 0xffb4,
+ KP_5 = 0xffb5,
+ KP_6 = 0xffb6,
+ KP_7 = 0xffb7,
+ KP_8 = 0xffb8,
+ KP_9 = 0xffb9,
+ F1 = 0xffbe,
+ F2 = 0xffbf,
+ F3 = 0xffc0,
+ F4 = 0xffc1,
+ F5 = 0xffc2,
+ F6 = 0xffc3,
+ F7 = 0xffc4,
+ F8 = 0xffc5,
+ F9 = 0xffc6,
+ F10 = 0xffc7,
+ F11 = 0xffc8,
+ L1 = 0xffc8,
+ F12 = 0xffc9,
+ L2 = 0xffc9,
+ F13 = 0xffca,
+ L3 = 0xffca,
+ F14 = 0xffcb,
+ L4 = 0xffcb,
+ F15 = 0xffcc,
+ L5 = 0xffcc,
+ F16 = 0xffcd,
+ L6 = 0xffcd,
+ F17 = 0xffce,
+ L7 = 0xffce,
+ F18 = 0xffcf,
+ L8 = 0xffcf,
+ F19 = 0xffd0,
+ L9 = 0xffd0,
+ F20 = 0xffd1,
+ L10 = 0xffd1,
+ F21 = 0xffd2,
+ R1 = 0xffd2,
+ F22 = 0xffd3,
+ R2 = 0xffd3,
+ F23 = 0xffd4,
+ R3 = 0xffd4,
+ F24 = 0xffd5,
+ R4 = 0xffd5,
+ F25 = 0xffd6,
+ R5 = 0xffd6,
+ F26 = 0xffd7,
+ R6 = 0xffd7,
+ F27 = 0xffd8,
+ R7 = 0xffd8,
+ F28 = 0xffd9,
+ R8 = 0xffd9,
+ F29 = 0xffda,
+ R9 = 0xffda,
+ F30 = 0xffdb,
+ R10 = 0xffdb,
+ F31 = 0xffdc,
+ R11 = 0xffdc,
+ F32 = 0xffdd,
+ R12 = 0xffdd,
+ F33 = 0xffde,
+ R13 = 0xffde,
+ F34 = 0xffdf,
+ R14 = 0xffdf,
+ F35 = 0xffe0,
+ R15 = 0xffe0,
+ Shift_L = 0xffe1 /* Left shift */,
+ Shift_R = 0xffe2 /* Right shift */,
+ Control_L = 0xffe3 /* Left control */,
+ Control_R = 0xffe4 /* Right control */,
+ Caps_Lock = 0xffe5 /* Caps lock */,
+ Shift_Lock = 0xffe6 /* Shift lock */,
+ Meta_L = 0xffe7 /* Left meta */,
+ Meta_R = 0xffe8 /* Right meta */,
+ Alt_L = 0xffe9 /* Left alt */,
+ Alt_R = 0xffea /* Right alt */,
+ Super_L = 0xffeb /* Left super */,
+ Super_R = 0xffec /* Right super */,
+ Hyper_L = 0xffed /* Left hyper */,
+ Hyper_R = 0xffee /* Right hyper */,
+ ISO_Lock = 0xfe01,
+ ISO_Level2_Latch = 0xfe02,
+ ISO_Level3_Shift = 0xfe03,
+ ISO_Level3_Latch = 0xfe04,
+ ISO_Level3_Lock = 0xfe05,
+ ISO_Level5_Shift = 0xfe11,
+ ISO_Level5_Latch = 0xfe12,
+ ISO_Level5_Lock = 0xfe13,
+ ISO_Group_Shift = 0xff7e /* Alias for mode_switch */,
+ ISO_Group_Latch = 0xfe06,
+ ISO_Group_Lock = 0xfe07,
+ ISO_Next_Group = 0xfe08,
+ ISO_Next_Group_Lock = 0xfe09,
+ ISO_Prev_Group = 0xfe0a,
+ ISO_Prev_Group_Lock = 0xfe0b,
+ ISO_First_Group = 0xfe0c,
+ ISO_First_Group_Lock = 0xfe0d,
+ ISO_Last_Group = 0xfe0e,
+ ISO_Last_Group_Lock = 0xfe0f,
+ ISO_Left_Tab = 0xfe20,
+ ISO_Move_Line_Up = 0xfe21,
+ ISO_Move_Line_Down = 0xfe22,
+ ISO_Partial_Line_Up = 0xfe23,
+ ISO_Partial_Line_Down = 0xfe24,
+ ISO_Partial_Space_Left = 0xfe25,
+ ISO_Partial_Space_Right = 0xfe26,
+ ISO_Set_Margin_Left = 0xfe27,
+ ISO_Set_Margin_Right = 0xfe28,
+ ISO_Release_Margin_Left = 0xfe29,
+ ISO_Release_Margin_Right = 0xfe2a,
+ ISO_Release_Both_Margins = 0xfe2b,
+ ISO_Fast_Cursor_Left = 0xfe2c,
+ ISO_Fast_Cursor_Right = 0xfe2d,
+ ISO_Fast_Cursor_Up = 0xfe2e,
+ ISO_Fast_Cursor_Down = 0xfe2f,
+ ISO_Continuous_Underline = 0xfe30,
+ ISO_Discontinuous_Underline = 0xfe31,
+ ISO_Emphasize = 0xfe32,
+ ISO_Center_Object = 0xfe33,
+ ISO_Enter = 0xfe34,
+ dead_grave = 0xfe50,
+ dead_acute = 0xfe51,
+ dead_circumflex = 0xfe52,
+ dead_tilde = 0xfe53,
+ dead_perispomeni = 0xfe53 /* alias for dead_tilde */,
+ dead_macron = 0xfe54,
+ dead_breve = 0xfe55,
+ dead_abovedot = 0xfe56,
+ dead_diaeresis = 0xfe57,
+ dead_abovering = 0xfe58,
+ dead_doubleacute = 0xfe59,
+ dead_caron = 0xfe5a,
+ dead_cedilla = 0xfe5b,
+ dead_ogonek = 0xfe5c,
+ dead_iota = 0xfe5d,
+ dead_voiced_sound = 0xfe5e,
+ dead_semivoiced_sound = 0xfe5f,
+ dead_belowdot = 0xfe60,
+ dead_hook = 0xfe61,
+ dead_horn = 0xfe62,
+ dead_stroke = 0xfe63,
+ dead_abovecomma = 0xfe64,
+ dead_psili = 0xfe64 /* alias for dead_abovecomma */,
+ dead_abovereversedcomma = 0xfe65,
+ dead_dasia = 0xfe65 /* alias for dead_abovereversedcomma */,
+ dead_doublegrave = 0xfe66,
+ dead_belowring = 0xfe67,
+ dead_belowmacron = 0xfe68,
+ dead_belowcircumflex = 0xfe69,
+ dead_belowtilde = 0xfe6a,
+ dead_belowbreve = 0xfe6b,
+ dead_belowdiaeresis = 0xfe6c,
+ dead_invertedbreve = 0xfe6d,
+ dead_belowcomma = 0xfe6e,
+ dead_currency = 0xfe6f,
+ dead_lowline = 0xfe90,
+ dead_aboveverticalline = 0xfe91,
+ dead_belowverticalline = 0xfe92,
+ dead_longsolidusoverlay = 0xfe93,
+ dead_a = 0xfe80,
+ dead_A = 0xfe81,
+ dead_e = 0xfe82,
+ dead_E = 0xfe83,
+ dead_i = 0xfe84,
+ dead_I = 0xfe85,
+ dead_o = 0xfe86,
+ dead_O = 0xfe87,
+ dead_u = 0xfe88,
+ dead_U = 0xfe89,
+ dead_small_schwa = 0xfe8a,
+ dead_capital_schwa = 0xfe8b,
+ dead_greek = 0xfe8c,
+ First_Virtual_Screen = 0xfed0,
+ Prev_Virtual_Screen = 0xfed1,
+ Next_Virtual_Screen = 0xfed2,
+ Last_Virtual_Screen = 0xfed4,
+ Terminate_Server = 0xfed5,
+ AccessX_Enable = 0xfe70,
+ AccessX_Feedback_Enable = 0xfe71,
+ RepeatKeys_Enable = 0xfe72,
+ SlowKeys_Enable = 0xfe73,
+ BounceKeys_Enable = 0xfe74,
+ StickyKeys_Enable = 0xfe75,
+ MouseKeys_Enable = 0xfe76,
+ MouseKeys_Accel_Enable = 0xfe77,
+ Overlay1_Enable = 0xfe78,
+ Overlay2_Enable = 0xfe79,
+ AudibleBell_Enable = 0xfe7a,
+ Pointer_Left = 0xfee0,
+ Pointer_Right = 0xfee1,
+ Pointer_Up = 0xfee2,
+ Pointer_Down = 0xfee3,
+ Pointer_UpLeft = 0xfee4,
+ Pointer_UpRight = 0xfee5,
+ Pointer_DownLeft = 0xfee6,
+ Pointer_DownRight = 0xfee7,
+ Pointer_Button_Dflt = 0xfee8,
+ Pointer_Button1 = 0xfee9,
+ Pointer_Button2 = 0xfeea,
+ Pointer_Button3 = 0xfeeb,
+ Pointer_Button4 = 0xfeec,
+ Pointer_Button5 = 0xfeed,
+ Pointer_DblClick_Dflt = 0xfeee,
+ Pointer_DblClick1 = 0xfeef,
+ Pointer_DblClick2 = 0xfef0,
+ Pointer_DblClick3 = 0xfef1,
+ Pointer_DblClick4 = 0xfef2,
+ Pointer_DblClick5 = 0xfef3,
+ Pointer_Drag_Dflt = 0xfef4,
+ Pointer_Drag1 = 0xfef5,
+ Pointer_Drag2 = 0xfef6,
+ Pointer_Drag3 = 0xfef7,
+ Pointer_Drag4 = 0xfef8,
+ Pointer_Drag5 = 0xfefd,
+ Pointer_EnableKeys = 0xfef9,
+ Pointer_Accelerate = 0xfefa,
+ Pointer_DfltBtnNext = 0xfefb,
+ Pointer_DfltBtnPrev = 0xfefc,
+ ch = 0xfea0,
+ Ch = 0xfea1,
+ CH = 0xfea2,
+ c_h = 0xfea3,
+ C_h = 0xfea4,
+ C_H = 0xfea5,
+ XK_3270_Duplicate = 0xfd01,
+ XK_3270_FieldMark = 0xfd02,
+ XK_3270_Right2 = 0xfd03,
+ XK_3270_Left2 = 0xfd04,
+ XK_3270_BackTab = 0xfd05,
+ XK_3270_EraseEOF = 0xfd06,
+ XK_3270_EraseInput = 0xfd07,
+ XK_3270_Reset = 0xfd08,
+ XK_3270_Quit = 0xfd09,
+ XK_3270_PA1 = 0xfd0a,
+ XK_3270_PA2 = 0xfd0b,
+ XK_3270_PA3 = 0xfd0c,
+ XK_3270_Test = 0xfd0d,
+ XK_3270_Attn = 0xfd0e,
+ XK_3270_CursorBlink = 0xfd0f,
+ XK_3270_AltCursor = 0xfd10,
+ XK_3270_KeyClick = 0xfd11,
+ XK_3270_Jump = 0xfd12,
+ XK_3270_Ident = 0xfd13,
+ XK_3270_Rule = 0xfd14,
+ XK_3270_Copy = 0xfd15,
+ XK_3270_Play = 0xfd16,
+ XK_3270_Setup = 0xfd17,
+ XK_3270_Record = 0xfd18,
+ XK_3270_ChangeScreen = 0xfd19,
+ XK_3270_DeleteWord = 0xfd1a,
+ XK_3270_ExSelect = 0xfd1b,
+ XK_3270_CursorSelect = 0xfd1c,
+ XK_3270_PrintScreen = 0xfd1d,
+ XK_3270_Enter = 0xfd1e,
+ space = 0x0020 /* U+0020 SPACE */,
+ exclam = 0x0021 /* U+0021 EXCLAMATION MARK */,
+ quotedbl = 0x0022 /* U+0022 QUOTATION MARK */,
+ numbersign = 0x0023 /* U+0023 NUMBER SIGN */,
+ dollar = 0x0024 /* U+0024 DOLLAR SIGN */,
+ percent = 0x0025 /* U+0025 PERCENT SIGN */,
+ ampersand = 0x0026 /* U+0026 AMPERSAND */,
+ apostrophe = 0x0027 /* U+0027 APOSTROPHE */,
+ quoteright = 0x0027 /* deprecated */,
+ parenleft = 0x0028 /* U+0028 LEFT PARENTHESIS */,
+ parenright = 0x0029 /* U+0029 RIGHT PARENTHESIS */,
+ asterisk = 0x002a /* U+002A ASTERISK */,
+ plus = 0x002b /* U+002B PLUS SIGN */,
+ comma = 0x002c /* U+002C COMMA */,
+ minus = 0x002d /* U+002D HYPHEN-MINUS */,
+ period = 0x002e /* U+002E FULL STOP */,
+ slash = 0x002f /* U+002F SOLIDUS */,
+ XK_0 = 0x0030 /* U+0030 DIGIT ZERO */,
+ XK_1 = 0x0031 /* U+0031 DIGIT ONE */,
+ XK_2 = 0x0032 /* U+0032 DIGIT TWO */,
+ XK_3 = 0x0033 /* U+0033 DIGIT THREE */,
+ XK_4 = 0x0034 /* U+0034 DIGIT FOUR */,
+ XK_5 = 0x0035 /* U+0035 DIGIT FIVE */,
+ XK_6 = 0x0036 /* U+0036 DIGIT SIX */,
+ XK_7 = 0x0037 /* U+0037 DIGIT SEVEN */,
+ XK_8 = 0x0038 /* U+0038 DIGIT EIGHT */,
+ XK_9 = 0x0039 /* U+0039 DIGIT NINE */,
+ colon = 0x003a /* U+003A COLON */,
+ semicolon = 0x003b /* U+003B SEMICOLON */,
+ less = 0x003c /* U+003C LESS-THAN SIGN */,
+ equal = 0x003d /* U+003D EQUALS SIGN */,
+ greater = 0x003e /* U+003E GREATER-THAN SIGN */,
+ question = 0x003f /* U+003F QUESTION MARK */,
+ at = 0x0040 /* U+0040 COMMERCIAL AT */,
+ A = 0x0041 /* U+0041 LATIN CAPITAL LETTER A */,
+ B = 0x0042 /* U+0042 LATIN CAPITAL LETTER B */,
+ C = 0x0043 /* U+0043 LATIN CAPITAL LETTER C */,
+ D = 0x0044 /* U+0044 LATIN CAPITAL LETTER D */,
+ E = 0x0045 /* U+0045 LATIN CAPITAL LETTER E */,
+ F = 0x0046 /* U+0046 LATIN CAPITAL LETTER F */,
+ G = 0x0047 /* U+0047 LATIN CAPITAL LETTER G */,
+ H = 0x0048 /* U+0048 LATIN CAPITAL LETTER H */,
+ I = 0x0049 /* U+0049 LATIN CAPITAL LETTER I */,
+ J = 0x004a /* U+004A LATIN CAPITAL LETTER J */,
+ K = 0x004b /* U+004B LATIN CAPITAL LETTER K */,
+ L = 0x004c /* U+004C LATIN CAPITAL LETTER L */,
+ M = 0x004d /* U+004D LATIN CAPITAL LETTER M */,
+ N = 0x004e /* U+004E LATIN CAPITAL LETTER N */,
+ O = 0x004f /* U+004F LATIN CAPITAL LETTER O */,
+ P = 0x0050 /* U+0050 LATIN CAPITAL LETTER P */,
+ Q = 0x0051 /* U+0051 LATIN CAPITAL LETTER Q */,
+ R = 0x0052 /* U+0052 LATIN CAPITAL LETTER R */,
+ S = 0x0053 /* U+0053 LATIN CAPITAL LETTER S */,
+ T = 0x0054 /* U+0054 LATIN CAPITAL LETTER T */,
+ U = 0x0055 /* U+0055 LATIN CAPITAL LETTER U */,
+ V = 0x0056 /* U+0056 LATIN CAPITAL LETTER V */,
+ W = 0x0057 /* U+0057 LATIN CAPITAL LETTER W */,
+ X = 0x0058 /* U+0058 LATIN CAPITAL LETTER X */,
+ Y = 0x0059 /* U+0059 LATIN CAPITAL LETTER Y */,
+ Z = 0x005a /* U+005A LATIN CAPITAL LETTER Z */,
+ bracketleft = 0x005b /* U+005B LEFT SQUARE BRACKET */,
+ backslash = 0x005c /* U+005C REVERSE SOLIDUS */,
+ bracketright = 0x005d /* U+005D RIGHT SQUARE BRACKET */,
+ asciicircum = 0x005e /* U+005E CIRCUMFLEX ACCENT */,
+ underscore = 0x005f /* U+005F LOW LINE */,
+ grave = 0x0060 /* U+0060 GRAVE ACCENT */,
+ quoteleft = 0x0060 /* deprecated */,
+ a = 0x0061 /* U+0061 LATIN SMALL LETTER A */,
+ b = 0x0062 /* U+0062 LATIN SMALL LETTER B */,
+ c = 0x0063 /* U+0063 LATIN SMALL LETTER C */,
+ d = 0x0064 /* U+0064 LATIN SMALL LETTER D */,
+ e = 0x0065 /* U+0065 LATIN SMALL LETTER E */,
+ f = 0x0066 /* U+0066 LATIN SMALL LETTER F */,
+ g = 0x0067 /* U+0067 LATIN SMALL LETTER G */,
+ h = 0x0068 /* U+0068 LATIN SMALL LETTER H */,
+ i = 0x0069 /* U+0069 LATIN SMALL LETTER I */,
+ j = 0x006a /* U+006A LATIN SMALL LETTER J */,
+ k = 0x006b /* U+006B LATIN SMALL LETTER K */,
+ l = 0x006c /* U+006C LATIN SMALL LETTER L */,
+ m = 0x006d /* U+006D LATIN SMALL LETTER M */,
+ n = 0x006e /* U+006E LATIN SMALL LETTER N */,
+ o = 0x006f /* U+006F LATIN SMALL LETTER O */,
+ p = 0x0070 /* U+0070 LATIN SMALL LETTER P */,
+ q = 0x0071 /* U+0071 LATIN SMALL LETTER Q */,
+ r = 0x0072 /* U+0072 LATIN SMALL LETTER R */,
+ s = 0x0073 /* U+0073 LATIN SMALL LETTER S */,
+ t = 0x0074 /* U+0074 LATIN SMALL LETTER T */,
+ u = 0x0075 /* U+0075 LATIN SMALL LETTER U */,
+ v = 0x0076 /* U+0076 LATIN SMALL LETTER V */,
+ w = 0x0077 /* U+0077 LATIN SMALL LETTER W */,
+ x = 0x0078 /* U+0078 LATIN SMALL LETTER X */,
+ y = 0x0079 /* U+0079 LATIN SMALL LETTER Y */,
+ z = 0x007a /* U+007A LATIN SMALL LETTER Z */,
+ braceleft = 0x007b /* U+007B LEFT CURLY BRACKET */,
+ bar = 0x007c /* U+007C VERTICAL LINE */,
+ braceright = 0x007d /* U+007D RIGHT CURLY BRACKET */,
+ asciitilde = 0x007e /* U+007E TILDE */,
+ nobreakspace = 0x00a0 /* U+00A0 NO-BREAK SPACE */,
+ exclamdown = 0x00a1 /* U+00A1 INVERTED EXCLAMATION MARK */,
+ cent = 0x00a2 /* U+00A2 CENT SIGN */,
+ sterling = 0x00a3 /* U+00A3 POUND SIGN */,
+ currency = 0x00a4 /* U+00A4 CURRENCY SIGN */,
+ yen = 0x00a5 /* U+00A5 YEN SIGN */,
+ brokenbar = 0x00a6 /* U+00A6 BROKEN BAR */,
+ section = 0x00a7 /* U+00A7 SECTION SIGN */,
+ diaeresis = 0x00a8 /* U+00A8 DIAERESIS */,
+ copyright = 0x00a9 /* U+00A9 COPYRIGHT SIGN */,
+ ordfeminine = 0x00aa /* U+00AA FEMININE ORDINAL INDICATOR */,
+ guillemotleft = 0x00ab /* U+00AB LEFT-POINTING DOUBLE ANGLE QUOTATION MARK */,
+ notsign = 0x00ac /* U+00AC NOT SIGN */,
+ hyphen = 0x00ad /* U+00AD SOFT HYPHEN */,
+ registered = 0x00ae /* U+00AE REGISTERED SIGN */,
+ macron = 0x00af /* U+00AF MACRON */,
+ degree = 0x00b0 /* U+00B0 DEGREE SIGN */,
+ plusminus = 0x00b1 /* U+00B1 PLUS-MINUS SIGN */,
+ twosuperior = 0x00b2 /* U+00B2 SUPERSCRIPT TWO */,
+ threesuperior = 0x00b3 /* U+00B3 SUPERSCRIPT THREE */,
+ acute = 0x00b4 /* U+00B4 ACUTE ACCENT */,
+ mu = 0x00b5 /* U+00B5 MICRO SIGN */,
+ paragraph = 0x00b6 /* U+00B6 PILCROW SIGN */,
+ periodcentered = 0x00b7 /* U+00B7 MIDDLE DOT */,
+ cedilla = 0x00b8 /* U+00B8 CEDILLA */,
+ onesuperior = 0x00b9 /* U+00B9 SUPERSCRIPT ONE */,
+ masculine = 0x00ba /* U+00BA MASCULINE ORDINAL INDICATOR */,
+ guillemotright = 0x00bb /* U+00BB RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK */,
+ onequarter = 0x00bc /* U+00BC VULGAR FRACTION ONE QUARTER */,
+ onehalf = 0x00bd /* U+00BD VULGAR FRACTION ONE HALF */,
+ threequarters = 0x00be /* U+00BE VULGAR FRACTION THREE QUARTERS */,
+ questiondown = 0x00bf /* U+00BF INVERTED QUESTION MARK */,
+ Agrave = 0x00c0 /* U+00C0 LATIN CAPITAL LETTER A WITH GRAVE */,
+ Aacute = 0x00c1 /* U+00C1 LATIN CAPITAL LETTER A WITH ACUTE */,
+ Acircumflex = 0x00c2 /* U+00C2 LATIN CAPITAL LETTER A WITH CIRCUMFLEX */,
+ Atilde = 0x00c3 /* U+00C3 LATIN CAPITAL LETTER A WITH TILDE */,
+ Adiaeresis = 0x00c4 /* U+00C4 LATIN CAPITAL LETTER A WITH DIAERESIS */,
+ Aring = 0x00c5 /* U+00C5 LATIN CAPITAL LETTER A WITH RING ABOVE */,
+ AE = 0x00c6 /* U+00C6 LATIN CAPITAL LETTER AE */,
+ Ccedilla = 0x00c7 /* U+00C7 LATIN CAPITAL LETTER C WITH CEDILLA */,
+ Egrave = 0x00c8 /* U+00C8 LATIN CAPITAL LETTER E WITH GRAVE */,
+ Eacute = 0x00c9 /* U+00C9 LATIN CAPITAL LETTER E WITH ACUTE */,
+ Ecircumflex = 0x00ca /* U+00CA LATIN CAPITAL LETTER E WITH CIRCUMFLEX */,
+ Ediaeresis = 0x00cb /* U+00CB LATIN CAPITAL LETTER E WITH DIAERESIS */,
+ Igrave = 0x00cc /* U+00CC LATIN CAPITAL LETTER I WITH GRAVE */,
+ Iacute = 0x00cd /* U+00CD LATIN CAPITAL LETTER I WITH ACUTE */,
+ Icircumflex = 0x00ce /* U+00CE LATIN CAPITAL LETTER I WITH CIRCUMFLEX */,
+ Idiaeresis = 0x00cf /* U+00CF LATIN CAPITAL LETTER I WITH DIAERESIS */,
+ ETH = 0x00d0 /* U+00D0 LATIN CAPITAL LETTER ETH */,
+ Eth = 0x00d0 /* deprecated */,
+ Ntilde = 0x00d1 /* U+00D1 LATIN CAPITAL LETTER N WITH TILDE */,
+ Ograve = 0x00d2 /* U+00D2 LATIN CAPITAL LETTER O WITH GRAVE */,
+ Oacute = 0x00d3 /* U+00D3 LATIN CAPITAL LETTER O WITH ACUTE */,
+ Ocircumflex = 0x00d4 /* U+00D4 LATIN CAPITAL LETTER O WITH CIRCUMFLEX */,
+ Otilde = 0x00d5 /* U+00D5 LATIN CAPITAL LETTER O WITH TILDE */,
+ Odiaeresis = 0x00d6 /* U+00D6 LATIN CAPITAL LETTER O WITH DIAERESIS */,
+ multiply = 0x00d7 /* U+00D7 MULTIPLICATION SIGN */,
+ Oslash = 0x00d8 /* U+00D8 LATIN CAPITAL LETTER O WITH STROKE */,
+ Ooblique = 0x00d8 /* U+00D8 LATIN CAPITAL LETTER O WITH STROKE */,
+ Ugrave = 0x00d9 /* U+00D9 LATIN CAPITAL LETTER U WITH GRAVE */,
+ Uacute = 0x00da /* U+00DA LATIN CAPITAL LETTER U WITH ACUTE */,
+ Ucircumflex = 0x00db /* U+00DB LATIN CAPITAL LETTER U WITH CIRCUMFLEX */,
+ Udiaeresis = 0x00dc /* U+00DC LATIN CAPITAL LETTER U WITH DIAERESIS */,
+ Yacute = 0x00dd /* U+00DD LATIN CAPITAL LETTER Y WITH ACUTE */,
+ THORN = 0x00de /* U+00DE LATIN CAPITAL LETTER THORN */,
+ Thorn = 0x00de /* deprecated */,
+ ssharp = 0x00df /* U+00DF LATIN SMALL LETTER SHARP S */,
+ agrave = 0x00e0 /* U+00E0 LATIN SMALL LETTER A WITH GRAVE */,
+ aacute = 0x00e1 /* U+00E1 LATIN SMALL LETTER A WITH ACUTE */,
+ acircumflex = 0x00e2 /* U+00E2 LATIN SMALL LETTER A WITH CIRCUMFLEX */,
+ atilde = 0x00e3 /* U+00E3 LATIN SMALL LETTER A WITH TILDE */,
+ adiaeresis = 0x00e4 /* U+00E4 LATIN SMALL LETTER A WITH DIAERESIS */,
+ aring = 0x00e5 /* U+00E5 LATIN SMALL LETTER A WITH RING ABOVE */,
+ ae = 0x00e6 /* U+00E6 LATIN SMALL LETTER AE */,
+ ccedilla = 0x00e7 /* U+00E7 LATIN SMALL LETTER C WITH CEDILLA */,
+ egrave = 0x00e8 /* U+00E8 LATIN SMALL LETTER E WITH GRAVE */,
+ eacute = 0x00e9 /* U+00E9 LATIN SMALL LETTER E WITH ACUTE */,
+ ecircumflex = 0x00ea /* U+00EA LATIN SMALL LETTER E WITH CIRCUMFLEX */,
+ ediaeresis = 0x00eb /* U+00EB LATIN SMALL LETTER E WITH DIAERESIS */,
+ igrave = 0x00ec /* U+00EC LATIN SMALL LETTER I WITH GRAVE */,
+ iacute = 0x00ed /* U+00ED LATIN SMALL LETTER I WITH ACUTE */,
+ icircumflex = 0x00ee /* U+00EE LATIN SMALL LETTER I WITH CIRCUMFLEX */,
+ idiaeresis = 0x00ef /* U+00EF LATIN SMALL LETTER I WITH DIAERESIS */,
+ eth = 0x00f0 /* U+00F0 LATIN SMALL LETTER ETH */,
+ ntilde = 0x00f1 /* U+00F1 LATIN SMALL LETTER N WITH TILDE */,
+ ograve = 0x00f2 /* U+00F2 LATIN SMALL LETTER O WITH GRAVE */,
+ oacute = 0x00f3 /* U+00F3 LATIN SMALL LETTER O WITH ACUTE */,
+ ocircumflex = 0x00f4 /* U+00F4 LATIN SMALL LETTER O WITH CIRCUMFLEX */,
+ otilde = 0x00f5 /* U+00F5 LATIN SMALL LETTER O WITH TILDE */,
+ odiaeresis = 0x00f6 /* U+00F6 LATIN SMALL LETTER O WITH DIAERESIS */,
+ division = 0x00f7 /* U+00F7 DIVISION SIGN */,
+ oslash = 0x00f8 /* U+00F8 LATIN SMALL LETTER O WITH STROKE */,
+ ooblique = 0x00f8 /* U+00F8 LATIN SMALL LETTER O WITH STROKE */,
+ ugrave = 0x00f9 /* U+00F9 LATIN SMALL LETTER U WITH GRAVE */,
+ uacute = 0x00fa /* U+00FA LATIN SMALL LETTER U WITH ACUTE */,
+ ucircumflex = 0x00fb /* U+00FB LATIN SMALL LETTER U WITH CIRCUMFLEX */,
+ udiaeresis = 0x00fc /* U+00FC LATIN SMALL LETTER U WITH DIAERESIS */,
+ yacute = 0x00fd /* U+00FD LATIN SMALL LETTER Y WITH ACUTE */,
+ thorn = 0x00fe /* U+00FE LATIN SMALL LETTER THORN */,
+ ydiaeresis = 0x00ff /* U+00FF LATIN SMALL LETTER Y WITH DIAERESIS */,
+ Aogonek = 0x01a1 /* U+0104 LATIN CAPITAL LETTER A WITH OGONEK */,
+ breve = 0x01a2 /* U+02D8 BREVE */,
+ Lstroke = 0x01a3 /* U+0141 LATIN CAPITAL LETTER L WITH STROKE */,
+ Lcaron = 0x01a5 /* U+013D LATIN CAPITAL LETTER L WITH CARON */,
+ Sacute = 0x01a6 /* U+015A LATIN CAPITAL LETTER S WITH ACUTE */,
+ Scaron = 0x01a9 /* U+0160 LATIN CAPITAL LETTER S WITH CARON */,
+ Scedilla = 0x01aa /* U+015E LATIN CAPITAL LETTER S WITH CEDILLA */,
+ Tcaron = 0x01ab /* U+0164 LATIN CAPITAL LETTER T WITH CARON */,
+ Zacute = 0x01ac /* U+0179 LATIN CAPITAL LETTER Z WITH ACUTE */,
+ Zcaron = 0x01ae /* U+017D LATIN CAPITAL LETTER Z WITH CARON */,
+ Zabovedot = 0x01af /* U+017B LATIN CAPITAL LETTER Z WITH DOT ABOVE */,
+ aogonek = 0x01b1 /* U+0105 LATIN SMALL LETTER A WITH OGONEK */,
+ ogonek = 0x01b2 /* U+02DB OGONEK */,
+ lstroke = 0x01b3 /* U+0142 LATIN SMALL LETTER L WITH STROKE */,
+ lcaron = 0x01b5 /* U+013E LATIN SMALL LETTER L WITH CARON */,
+ sacute = 0x01b6 /* U+015B LATIN SMALL LETTER S WITH ACUTE */,
+ caron = 0x01b7 /* U+02C7 CARON */,
+ scaron = 0x01b9 /* U+0161 LATIN SMALL LETTER S WITH CARON */,
+ scedilla = 0x01ba /* U+015F LATIN SMALL LETTER S WITH CEDILLA */,
+ tcaron = 0x01bb /* U+0165 LATIN SMALL LETTER T WITH CARON */,
+ zacute = 0x01bc /* U+017A LATIN SMALL LETTER Z WITH ACUTE */,
+ doubleacute = 0x01bd /* U+02DD DOUBLE ACUTE ACCENT */,
+ zcaron = 0x01be /* U+017E LATIN SMALL LETTER Z WITH CARON */,
+ zabovedot = 0x01bf /* U+017C LATIN SMALL LETTER Z WITH DOT ABOVE */,
+ Racute = 0x01c0 /* U+0154 LATIN CAPITAL LETTER R WITH ACUTE */,
+ Abreve = 0x01c3 /* U+0102 LATIN CAPITAL LETTER A WITH BREVE */,
+ Lacute = 0x01c5 /* U+0139 LATIN CAPITAL LETTER L WITH ACUTE */,
+ Cacute = 0x01c6 /* U+0106 LATIN CAPITAL LETTER C WITH ACUTE */,
+ Ccaron = 0x01c8 /* U+010C LATIN CAPITAL LETTER C WITH CARON */,
+ Eogonek = 0x01ca /* U+0118 LATIN CAPITAL LETTER E WITH OGONEK */,
+ Ecaron = 0x01cc /* U+011A LATIN CAPITAL LETTER E WITH CARON */,
+ Dcaron = 0x01cf /* U+010E LATIN CAPITAL LETTER D WITH CARON */,
+ Dstroke = 0x01d0 /* U+0110 LATIN CAPITAL LETTER D WITH STROKE */,
+ Nacute = 0x01d1 /* U+0143 LATIN CAPITAL LETTER N WITH ACUTE */,
+ Ncaron = 0x01d2 /* U+0147 LATIN CAPITAL LETTER N WITH CARON */,
+ Odoubleacute = 0x01d5 /* U+0150 LATIN CAPITAL LETTER O WITH DOUBLE ACUTE */,
+ Rcaron = 0x01d8 /* U+0158 LATIN CAPITAL LETTER R WITH CARON */,
+ Uring = 0x01d9 /* U+016E LATIN CAPITAL LETTER U WITH RING ABOVE */,
+ Udoubleacute = 0x01db /* U+0170 LATIN CAPITAL LETTER U WITH DOUBLE ACUTE */,
+ Tcedilla = 0x01de /* U+0162 LATIN CAPITAL LETTER T WITH CEDILLA */,
+ racute = 0x01e0 /* U+0155 LATIN SMALL LETTER R WITH ACUTE */,
+ abreve = 0x01e3 /* U+0103 LATIN SMALL LETTER A WITH BREVE */,
+ lacute = 0x01e5 /* U+013A LATIN SMALL LETTER L WITH ACUTE */,
+ cacute = 0x01e6 /* U+0107 LATIN SMALL LETTER C WITH ACUTE */,
+ ccaron = 0x01e8 /* U+010D LATIN SMALL LETTER C WITH CARON */,
+ eogonek = 0x01ea /* U+0119 LATIN SMALL LETTER E WITH OGONEK */,
+ ecaron = 0x01ec /* U+011B LATIN SMALL LETTER E WITH CARON */,
+ dcaron = 0x01ef /* U+010F LATIN SMALL LETTER D WITH CARON */,
+ dstroke = 0x01f0 /* U+0111 LATIN SMALL LETTER D WITH STROKE */,
+ nacute = 0x01f1 /* U+0144 LATIN SMALL LETTER N WITH ACUTE */,
+ ncaron = 0x01f2 /* U+0148 LATIN SMALL LETTER N WITH CARON */,
+ odoubleacute = 0x01f5 /* U+0151 LATIN SMALL LETTER O WITH DOUBLE ACUTE */,
+ rcaron = 0x01f8 /* U+0159 LATIN SMALL LETTER R WITH CARON */,
+ uring = 0x01f9 /* U+016F LATIN SMALL LETTER U WITH RING ABOVE */,
+ udoubleacute = 0x01fb /* U+0171 LATIN SMALL LETTER U WITH DOUBLE ACUTE */,
+ tcedilla = 0x01fe /* U+0163 LATIN SMALL LETTER T WITH CEDILLA */,
+ abovedot = 0x01ff /* U+02D9 DOT ABOVE */,
+ Hstroke = 0x02a1 /* U+0126 LATIN CAPITAL LETTER H WITH STROKE */,
+ Hcircumflex = 0x02a6 /* U+0124 LATIN CAPITAL LETTER H WITH CIRCUMFLEX */,
+ Iabovedot = 0x02a9 /* U+0130 LATIN CAPITAL LETTER I WITH DOT ABOVE */,
+ Gbreve = 0x02ab /* U+011E LATIN CAPITAL LETTER G WITH BREVE */,
+ Jcircumflex = 0x02ac /* U+0134 LATIN CAPITAL LETTER J WITH CIRCUMFLEX */,
+ hstroke = 0x02b1 /* U+0127 LATIN SMALL LETTER H WITH STROKE */,
+ hcircumflex = 0x02b6 /* U+0125 LATIN SMALL LETTER H WITH CIRCUMFLEX */,
+ idotless = 0x02b9 /* U+0131 LATIN SMALL LETTER DOTLESS I */,
+ gbreve = 0x02bb /* U+011F LATIN SMALL LETTER G WITH BREVE */,
+ jcircumflex = 0x02bc /* U+0135 LATIN SMALL LETTER J WITH CIRCUMFLEX */,
+ Cabovedot = 0x02c5 /* U+010A LATIN CAPITAL LETTER C WITH DOT ABOVE */,
+ Ccircumflex = 0x02c6 /* U+0108 LATIN CAPITAL LETTER C WITH CIRCUMFLEX */,
+ Gabovedot = 0x02d5 /* U+0120 LATIN CAPITAL LETTER G WITH DOT ABOVE */,
+ Gcircumflex = 0x02d8 /* U+011C LATIN CAPITAL LETTER G WITH CIRCUMFLEX */,
+ Ubreve = 0x02dd /* U+016C LATIN CAPITAL LETTER U WITH BREVE */,
+ Scircumflex = 0x02de /* U+015C LATIN CAPITAL LETTER S WITH CIRCUMFLEX */,
+ cabovedot = 0x02e5 /* U+010B LATIN SMALL LETTER C WITH DOT ABOVE */,
+ ccircumflex = 0x02e6 /* U+0109 LATIN SMALL LETTER C WITH CIRCUMFLEX */,
+ gabovedot = 0x02f5 /* U+0121 LATIN SMALL LETTER G WITH DOT ABOVE */,
+ gcircumflex = 0x02f8 /* U+011D LATIN SMALL LETTER G WITH CIRCUMFLEX */,
+ ubreve = 0x02fd /* U+016D LATIN SMALL LETTER U WITH BREVE */,
+ scircumflex = 0x02fe /* U+015D LATIN SMALL LETTER S WITH CIRCUMFLEX */,
+ kra = 0x03a2 /* U+0138 LATIN SMALL LETTER KRA */,
+ kappa = 0x03a2 /* deprecated */,
+ Rcedilla = 0x03a3 /* U+0156 LATIN CAPITAL LETTER R WITH CEDILLA */,
+ Itilde = 0x03a5 /* U+0128 LATIN CAPITAL LETTER I WITH TILDE */,
+ Lcedilla = 0x03a6 /* U+013B LATIN CAPITAL LETTER L WITH CEDILLA */,
+ Emacron = 0x03aa /* U+0112 LATIN CAPITAL LETTER E WITH MACRON */,
+ Gcedilla = 0x03ab /* U+0122 LATIN CAPITAL LETTER G WITH CEDILLA */,
+ Tslash = 0x03ac /* U+0166 LATIN CAPITAL LETTER T WITH STROKE */,
+ rcedilla = 0x03b3 /* U+0157 LATIN SMALL LETTER R WITH CEDILLA */,
+ itilde = 0x03b5 /* U+0129 LATIN SMALL LETTER I WITH TILDE */,
+ lcedilla = 0x03b6 /* U+013C LATIN SMALL LETTER L WITH CEDILLA */,
+ emacron = 0x03ba /* U+0113 LATIN SMALL LETTER E WITH MACRON */,
+ gcedilla = 0x03bb /* U+0123 LATIN SMALL LETTER G WITH CEDILLA */,
+ tslash = 0x03bc /* U+0167 LATIN SMALL LETTER T WITH STROKE */,
+ ENG = 0x03bd /* U+014A LATIN CAPITAL LETTER ENG */,
+ eng = 0x03bf /* U+014B LATIN SMALL LETTER ENG */,
+ Amacron = 0x03c0 /* U+0100 LATIN CAPITAL LETTER A WITH MACRON */,
+ Iogonek = 0x03c7 /* U+012E LATIN CAPITAL LETTER I WITH OGONEK */,
+ Eabovedot = 0x03cc /* U+0116 LATIN CAPITAL LETTER E WITH DOT ABOVE */,
+ Imacron = 0x03cf /* U+012A LATIN CAPITAL LETTER I WITH MACRON */,
+ Ncedilla = 0x03d1 /* U+0145 LATIN CAPITAL LETTER N WITH CEDILLA */,
+ Omacron = 0x03d2 /* U+014C LATIN CAPITAL LETTER O WITH MACRON */,
+ Kcedilla = 0x03d3 /* U+0136 LATIN CAPITAL LETTER K WITH CEDILLA */,
+ Uogonek = 0x03d9 /* U+0172 LATIN CAPITAL LETTER U WITH OGONEK */,
+ Utilde = 0x03dd /* U+0168 LATIN CAPITAL LETTER U WITH TILDE */,
+ Umacron = 0x03de /* U+016A LATIN CAPITAL LETTER U WITH MACRON */,
+ amacron = 0x03e0 /* U+0101 LATIN SMALL LETTER A WITH MACRON */,
+ iogonek = 0x03e7 /* U+012F LATIN SMALL LETTER I WITH OGONEK */,
+ eabovedot = 0x03ec /* U+0117 LATIN SMALL LETTER E WITH DOT ABOVE */,
+ imacron = 0x03ef /* U+012B LATIN SMALL LETTER I WITH MACRON */,
+ ncedilla = 0x03f1 /* U+0146 LATIN SMALL LETTER N WITH CEDILLA */,
+ omacron = 0x03f2 /* U+014D LATIN SMALL LETTER O WITH MACRON */,
+ kcedilla = 0x03f3 /* U+0137 LATIN SMALL LETTER K WITH CEDILLA */,
+ uogonek = 0x03f9 /* U+0173 LATIN SMALL LETTER U WITH OGONEK */,
+ utilde = 0x03fd /* U+0169 LATIN SMALL LETTER U WITH TILDE */,
+ umacron = 0x03fe /* U+016B LATIN SMALL LETTER U WITH MACRON */,
+ Wcircumflex = 0x1000174 /* U+0174 LATIN CAPITAL LETTER W WITH CIRCUMFLEX */,
+ wcircumflex = 0x1000175 /* U+0175 LATIN SMALL LETTER W WITH CIRCUMFLEX */,
+ Ycircumflex = 0x1000176 /* U+0176 LATIN CAPITAL LETTER Y WITH CIRCUMFLEX */,
+ ycircumflex = 0x1000177 /* U+0177 LATIN SMALL LETTER Y WITH CIRCUMFLEX */,
+ Babovedot = 0x1001e02 /* U+1E02 LATIN CAPITAL LETTER B WITH DOT ABOVE */,
+ babovedot = 0x1001e03 /* U+1E03 LATIN SMALL LETTER B WITH DOT ABOVE */,
+ Dabovedot = 0x1001e0a /* U+1E0A LATIN CAPITAL LETTER D WITH DOT ABOVE */,
+ dabovedot = 0x1001e0b /* U+1E0B LATIN SMALL LETTER D WITH DOT ABOVE */,
+ Fabovedot = 0x1001e1e /* U+1E1E LATIN CAPITAL LETTER F WITH DOT ABOVE */,
+ fabovedot = 0x1001e1f /* U+1E1F LATIN SMALL LETTER F WITH DOT ABOVE */,
+ Mabovedot = 0x1001e40 /* U+1E40 LATIN CAPITAL LETTER M WITH DOT ABOVE */,
+ mabovedot = 0x1001e41 /* U+1E41 LATIN SMALL LETTER M WITH DOT ABOVE */,
+ Pabovedot = 0x1001e56 /* U+1E56 LATIN CAPITAL LETTER P WITH DOT ABOVE */,
+ pabovedot = 0x1001e57 /* U+1E57 LATIN SMALL LETTER P WITH DOT ABOVE */,
+ Sabovedot = 0x1001e60 /* U+1E60 LATIN CAPITAL LETTER S WITH DOT ABOVE */,
+ sabovedot = 0x1001e61 /* U+1E61 LATIN SMALL LETTER S WITH DOT ABOVE */,
+ Tabovedot = 0x1001e6a /* U+1E6A LATIN CAPITAL LETTER T WITH DOT ABOVE */,
+ tabovedot = 0x1001e6b /* U+1E6B LATIN SMALL LETTER T WITH DOT ABOVE */,
+ Wgrave = 0x1001e80 /* U+1E80 LATIN CAPITAL LETTER W WITH GRAVE */,
+ wgrave = 0x1001e81 /* U+1E81 LATIN SMALL LETTER W WITH GRAVE */,
+ Wacute = 0x1001e82 /* U+1E82 LATIN CAPITAL LETTER W WITH ACUTE */,
+ wacute = 0x1001e83 /* U+1E83 LATIN SMALL LETTER W WITH ACUTE */,
+ Wdiaeresis = 0x1001e84 /* U+1E84 LATIN CAPITAL LETTER W WITH DIAERESIS */,
+ wdiaeresis = 0x1001e85 /* U+1E85 LATIN SMALL LETTER W WITH DIAERESIS */,
+ Ygrave = 0x1001ef2 /* U+1EF2 LATIN CAPITAL LETTER Y WITH GRAVE */,
+ ygrave = 0x1001ef3 /* U+1EF3 LATIN SMALL LETTER Y WITH GRAVE */,
+ OE = 0x13bc /* U+0152 LATIN CAPITAL LIGATURE OE */,
+ oe = 0x13bd /* U+0153 LATIN SMALL LIGATURE OE */,
+ Ydiaeresis = 0x13be /* U+0178 LATIN CAPITAL LETTER Y WITH DIAERESIS */,
+ overline = 0x047e /* U+203E OVERLINE */,
+ kana_fullstop = 0x04a1 /* U+3002 IDEOGRAPHIC FULL STOP */,
+ kana_openingbracket = 0x04a2 /* U+300C LEFT CORNER BRACKET */,
+ kana_closingbracket = 0x04a3 /* U+300D RIGHT CORNER BRACKET */,
+ kana_comma = 0x04a4 /* U+3001 IDEOGRAPHIC COMMA */,
+ kana_conjunctive = 0x04a5 /* U+30FB KATAKANA MIDDLE DOT */,
+ kana_middledot = 0x04a5 /* deprecated */,
+ kana_WO = 0x04a6 /* U+30F2 KATAKANA LETTER WO */,
+ kana_a = 0x04a7 /* U+30A1 KATAKANA LETTER SMALL A */,
+ kana_i = 0x04a8 /* U+30A3 KATAKANA LETTER SMALL I */,
+ kana_u = 0x04a9 /* U+30A5 KATAKANA LETTER SMALL U */,
+ kana_e = 0x04aa /* U+30A7 KATAKANA LETTER SMALL E */,
+ kana_o = 0x04ab /* U+30A9 KATAKANA LETTER SMALL O */,
+ kana_ya = 0x04ac /* U+30E3 KATAKANA LETTER SMALL YA */,
+ kana_yu = 0x04ad /* U+30E5 KATAKANA LETTER SMALL YU */,
+ kana_yo = 0x04ae /* U+30E7 KATAKANA LETTER SMALL YO */,
+ kana_tsu = 0x04af /* U+30C3 KATAKANA LETTER SMALL TU */,
+ kana_tu = 0x04af /* deprecated */,
+ prolongedsound = 0x04b0 /* U+30FC KATAKANA-HIRAGANA PROLONGED SOUND MARK */,
+ kana_A = 0x04b1 /* U+30A2 KATAKANA LETTER A */,
+ kana_I = 0x04b2 /* U+30A4 KATAKANA LETTER I */,
+ kana_U = 0x04b3 /* U+30A6 KATAKANA LETTER U */,
+ kana_E = 0x04b4 /* U+30A8 KATAKANA LETTER E */,
+ kana_O = 0x04b5 /* U+30AA KATAKANA LETTER O */,
+ kana_KA = 0x04b6 /* U+30AB KATAKANA LETTER KA */,
+ kana_KI = 0x04b7 /* U+30AD KATAKANA LETTER KI */,
+ kana_KU = 0x04b8 /* U+30AF KATAKANA LETTER KU */,
+ kana_KE = 0x04b9 /* U+30B1 KATAKANA LETTER KE */,
+ kana_KO = 0x04ba /* U+30B3 KATAKANA LETTER KO */,
+ kana_SA = 0x04bb /* U+30B5 KATAKANA LETTER SA */,
+ kana_SHI = 0x04bc /* U+30B7 KATAKANA LETTER SI */,
+ kana_SU = 0x04bd /* U+30B9 KATAKANA LETTER SU */,
+ kana_SE = 0x04be /* U+30BB KATAKANA LETTER SE */,
+ kana_SO = 0x04bf /* U+30BD KATAKANA LETTER SO */,
+ kana_TA = 0x04c0 /* U+30BF KATAKANA LETTER TA */,
+ kana_CHI = 0x04c1 /* U+30C1 KATAKANA LETTER TI */,
+ kana_TI = 0x04c1 /* deprecated */,
+ kana_TSU = 0x04c2 /* U+30C4 KATAKANA LETTER TU */,
+ kana_TU = 0x04c2 /* deprecated */,
+ kana_TE = 0x04c3 /* U+30C6 KATAKANA LETTER TE */,
+ kana_TO = 0x04c4 /* U+30C8 KATAKANA LETTER TO */,
+ kana_NA = 0x04c5 /* U+30CA KATAKANA LETTER NA */,
+ kana_NI = 0x04c6 /* U+30CB KATAKANA LETTER NI */,
+ kana_NU = 0x04c7 /* U+30CC KATAKANA LETTER NU */,
+ kana_NE = 0x04c8 /* U+30CD KATAKANA LETTER NE */,
+ kana_NO = 0x04c9 /* U+30CE KATAKANA LETTER NO */,
+ kana_HA = 0x04ca /* U+30CF KATAKANA LETTER HA */,
+ kana_HI = 0x04cb /* U+30D2 KATAKANA LETTER HI */,
+ kana_FU = 0x04cc /* U+30D5 KATAKANA LETTER HU */,
+ kana_HU = 0x04cc /* deprecated */,
+ kana_HE = 0x04cd /* U+30D8 KATAKANA LETTER HE */,
+ kana_HO = 0x04ce /* U+30DB KATAKANA LETTER HO */,
+ kana_MA = 0x04cf /* U+30DE KATAKANA LETTER MA */,
+ kana_MI = 0x04d0 /* U+30DF KATAKANA LETTER MI */,
+ kana_MU = 0x04d1 /* U+30E0 KATAKANA LETTER MU */,
+ kana_ME = 0x04d2 /* U+30E1 KATAKANA LETTER ME */,
+ kana_MO = 0x04d3 /* U+30E2 KATAKANA LETTER MO */,
+ kana_YA = 0x04d4 /* U+30E4 KATAKANA LETTER YA */,
+ kana_YU = 0x04d5 /* U+30E6 KATAKANA LETTER YU */,
+ kana_YO = 0x04d6 /* U+30E8 KATAKANA LETTER YO */,
+ kana_RA = 0x04d7 /* U+30E9 KATAKANA LETTER RA */,
+ kana_RI = 0x04d8 /* U+30EA KATAKANA LETTER RI */,
+ kana_RU = 0x04d9 /* U+30EB KATAKANA LETTER RU */,
+ kana_RE = 0x04da /* U+30EC KATAKANA LETTER RE */,
+ kana_RO = 0x04db /* U+30ED KATAKANA LETTER RO */,
+ kana_WA = 0x04dc /* U+30EF KATAKANA LETTER WA */,
+ kana_N = 0x04dd /* U+30F3 KATAKANA LETTER N */,
+ voicedsound = 0x04de /* U+309B KATAKANA-HIRAGANA VOICED SOUND MARK */,
+ semivoicedsound = 0x04df /* U+309C KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK */,
+ kana_switch = 0xff7e /* Alias for mode_switch */,
+ Farsi_0 = 0x10006f0 /* U+06F0 EXTENDED ARABIC-INDIC DIGIT ZERO */,
+ Farsi_1 = 0x10006f1 /* U+06F1 EXTENDED ARABIC-INDIC DIGIT ONE */,
+ Farsi_2 = 0x10006f2 /* U+06F2 EXTENDED ARABIC-INDIC DIGIT TWO */,
+ Farsi_3 = 0x10006f3 /* U+06F3 EXTENDED ARABIC-INDIC DIGIT THREE */,
+ Farsi_4 = 0x10006f4 /* U+06F4 EXTENDED ARABIC-INDIC DIGIT FOUR */,
+ Farsi_5 = 0x10006f5 /* U+06F5 EXTENDED ARABIC-INDIC DIGIT FIVE */,
+ Farsi_6 = 0x10006f6 /* U+06F6 EXTENDED ARABIC-INDIC DIGIT SIX */,
+ Farsi_7 = 0x10006f7 /* U+06F7 EXTENDED ARABIC-INDIC DIGIT SEVEN */,
+ Farsi_8 = 0x10006f8 /* U+06F8 EXTENDED ARABIC-INDIC DIGIT EIGHT */,
+ Farsi_9 = 0x10006f9 /* U+06F9 EXTENDED ARABIC-INDIC DIGIT NINE */,
+ Arabic_percent = 0x100066a /* U+066A ARABIC PERCENT SIGN */,
+ Arabic_superscript_alef = 0x1000670 /* U+0670 ARABIC LETTER SUPERSCRIPT ALEF */,
+ Arabic_tteh = 0x1000679 /* U+0679 ARABIC LETTER TTEH */,
+ Arabic_peh = 0x100067e /* U+067E ARABIC LETTER PEH */,
+ Arabic_tcheh = 0x1000686 /* U+0686 ARABIC LETTER TCHEH */,
+ Arabic_ddal = 0x1000688 /* U+0688 ARABIC LETTER DDAL */,
+ Arabic_rreh = 0x1000691 /* U+0691 ARABIC LETTER RREH */,
+ Arabic_comma = 0x05ac /* U+060C ARABIC COMMA */,
+ Arabic_fullstop = 0x10006d4 /* U+06D4 ARABIC FULL STOP */,
+ Arabic_0 = 0x1000660 /* U+0660 ARABIC-INDIC DIGIT ZERO */,
+ Arabic_1 = 0x1000661 /* U+0661 ARABIC-INDIC DIGIT ONE */,
+ Arabic_2 = 0x1000662 /* U+0662 ARABIC-INDIC DIGIT TWO */,
+ Arabic_3 = 0x1000663 /* U+0663 ARABIC-INDIC DIGIT THREE */,
+ Arabic_4 = 0x1000664 /* U+0664 ARABIC-INDIC DIGIT FOUR */,
+ Arabic_5 = 0x1000665 /* U+0665 ARABIC-INDIC DIGIT FIVE */,
+ Arabic_6 = 0x1000666 /* U+0666 ARABIC-INDIC DIGIT SIX */,
+ Arabic_7 = 0x1000667 /* U+0667 ARABIC-INDIC DIGIT SEVEN */,
+ Arabic_8 = 0x1000668 /* U+0668 ARABIC-INDIC DIGIT EIGHT */,
+ Arabic_9 = 0x1000669 /* U+0669 ARABIC-INDIC DIGIT NINE */,
+ Arabic_semicolon = 0x05bb /* U+061B ARABIC SEMICOLON */,
+ Arabic_question_mark = 0x05bf /* U+061F ARABIC QUESTION MARK */,
+ Arabic_hamza = 0x05c1 /* U+0621 ARABIC LETTER HAMZA */,
+ Arabic_maddaonalef = 0x05c2 /* U+0622 ARABIC LETTER ALEF WITH MADDA ABOVE */,
+ Arabic_hamzaonalef = 0x05c3 /* U+0623 ARABIC LETTER ALEF WITH HAMZA ABOVE */,
+ Arabic_hamzaonwaw = 0x05c4 /* U+0624 ARABIC LETTER WAW WITH HAMZA ABOVE */,
+ Arabic_hamzaunderalef = 0x05c5 /* U+0625 ARABIC LETTER ALEF WITH HAMZA BELOW */,
+ Arabic_hamzaonyeh = 0x05c6 /* U+0626 ARABIC LETTER YEH WITH HAMZA ABOVE */,
+ Arabic_alef = 0x05c7 /* U+0627 ARABIC LETTER ALEF */,
+ Arabic_beh = 0x05c8 /* U+0628 ARABIC LETTER BEH */,
+ Arabic_tehmarbuta = 0x05c9 /* U+0629 ARABIC LETTER TEH MARBUTA */,
+ Arabic_teh = 0x05ca /* U+062A ARABIC LETTER TEH */,
+ Arabic_theh = 0x05cb /* U+062B ARABIC LETTER THEH */,
+ Arabic_jeem = 0x05cc /* U+062C ARABIC LETTER JEEM */,
+ Arabic_hah = 0x05cd /* U+062D ARABIC LETTER HAH */,
+ Arabic_khah = 0x05ce /* U+062E ARABIC LETTER KHAH */,
+ Arabic_dal = 0x05cf /* U+062F ARABIC LETTER DAL */,
+ Arabic_thal = 0x05d0 /* U+0630 ARABIC LETTER THAL */,
+ Arabic_ra = 0x05d1 /* U+0631 ARABIC LETTER REH */,
+ Arabic_zain = 0x05d2 /* U+0632 ARABIC LETTER ZAIN */,
+ Arabic_seen = 0x05d3 /* U+0633 ARABIC LETTER SEEN */,
+ Arabic_sheen = 0x05d4 /* U+0634 ARABIC LETTER SHEEN */,
+ Arabic_sad = 0x05d5 /* U+0635 ARABIC LETTER SAD */,
+ Arabic_dad = 0x05d6 /* U+0636 ARABIC LETTER DAD */,
+ Arabic_tah = 0x05d7 /* U+0637 ARABIC LETTER TAH */,
+ Arabic_zah = 0x05d8 /* U+0638 ARABIC LETTER ZAH */,
+ Arabic_ain = 0x05d9 /* U+0639 ARABIC LETTER AIN */,
+ Arabic_ghain = 0x05da /* U+063A ARABIC LETTER GHAIN */,
+ Arabic_tatweel = 0x05e0 /* U+0640 ARABIC TATWEEL */,
+ Arabic_feh = 0x05e1 /* U+0641 ARABIC LETTER FEH */,
+ Arabic_qaf = 0x05e2 /* U+0642 ARABIC LETTER QAF */,
+ Arabic_kaf = 0x05e3 /* U+0643 ARABIC LETTER KAF */,
+ Arabic_lam = 0x05e4 /* U+0644 ARABIC LETTER LAM */,
+ Arabic_meem = 0x05e5 /* U+0645 ARABIC LETTER MEEM */,
+ Arabic_noon = 0x05e6 /* U+0646 ARABIC LETTER NOON */,
+ Arabic_ha = 0x05e7 /* U+0647 ARABIC LETTER HEH */,
+ Arabic_heh = 0x05e7 /* deprecated */,
+ Arabic_waw = 0x05e8 /* U+0648 ARABIC LETTER WAW */,
+ Arabic_alefmaksura = 0x05e9 /* U+0649 ARABIC LETTER ALEF MAKSURA */,
+ Arabic_yeh = 0x05ea /* U+064A ARABIC LETTER YEH */,
+ Arabic_fathatan = 0x05eb /* U+064B ARABIC FATHATAN */,
+ Arabic_dammatan = 0x05ec /* U+064C ARABIC DAMMATAN */,
+ Arabic_kasratan = 0x05ed /* U+064D ARABIC KASRATAN */,
+ Arabic_fatha = 0x05ee /* U+064E ARABIC FATHA */,
+ Arabic_damma = 0x05ef /* U+064F ARABIC DAMMA */,
+ Arabic_kasra = 0x05f0 /* U+0650 ARABIC KASRA */,
+ Arabic_shadda = 0x05f1 /* U+0651 ARABIC SHADDA */,
+ Arabic_sukun = 0x05f2 /* U+0652 ARABIC SUKUN */,
+ Arabic_madda_above = 0x1000653 /* U+0653 ARABIC MADDAH ABOVE */,
+ Arabic_hamza_above = 0x1000654 /* U+0654 ARABIC HAMZA ABOVE */,
+ Arabic_hamza_below = 0x1000655 /* U+0655 ARABIC HAMZA BELOW */,
+ Arabic_jeh = 0x1000698 /* U+0698 ARABIC LETTER JEH */,
+ Arabic_veh = 0x10006a4 /* U+06A4 ARABIC LETTER VEH */,
+ Arabic_keheh = 0x10006a9 /* U+06A9 ARABIC LETTER KEHEH */,
+ Arabic_gaf = 0x10006af /* U+06AF ARABIC LETTER GAF */,
+ Arabic_noon_ghunna = 0x10006ba /* U+06BA ARABIC LETTER NOON GHUNNA */,
+ Arabic_heh_doachashmee = 0x10006be /* U+06BE ARABIC LETTER HEH DOACHASHMEE */,
+ Farsi_yeh = 0x10006cc /* U+06CC ARABIC LETTER FARSI YEH */,
+ Arabic_farsi_yeh = 0x10006cc /* U+06CC ARABIC LETTER FARSI YEH */,
+ Arabic_yeh_baree = 0x10006d2 /* U+06D2 ARABIC LETTER YEH BARREE */,
+ Arabic_heh_goal = 0x10006c1 /* U+06C1 ARABIC LETTER HEH GOAL */,
+ Arabic_switch = 0xff7e /* Alias for mode_switch */,
+ Cyrillic_GHE_bar = 0x1000492 /* U+0492 CYRILLIC CAPITAL LETTER GHE WITH STROKE */,
+ Cyrillic_ghe_bar = 0x1000493 /* U+0493 CYRILLIC SMALL LETTER GHE WITH STROKE */,
+ Cyrillic_ZHE_descender = 0x1000496 /* U+0496 CYRILLIC CAPITAL LETTER ZHE WITH DESCENDER */,
+ Cyrillic_zhe_descender = 0x1000497 /* U+0497 CYRILLIC SMALL LETTER ZHE WITH DESCENDER */,
+ Cyrillic_KA_descender = 0x100049a /* U+049A CYRILLIC CAPITAL LETTER KA WITH DESCENDER */,
+ Cyrillic_ka_descender = 0x100049b /* U+049B CYRILLIC SMALL LETTER KA WITH DESCENDER */,
+ Cyrillic_KA_vertstroke = 0x100049c /* U+049C CYRILLIC CAPITAL LETTER KA WITH VERTICAL STROKE */,
+ Cyrillic_ka_vertstroke = 0x100049d /* U+049D CYRILLIC SMALL LETTER KA WITH VERTICAL STROKE */,
+ Cyrillic_EN_descender = 0x10004a2 /* U+04A2 CYRILLIC CAPITAL LETTER EN WITH DESCENDER */,
+ Cyrillic_en_descender = 0x10004a3 /* U+04A3 CYRILLIC SMALL LETTER EN WITH DESCENDER */,
+ Cyrillic_U_straight = 0x10004ae /* U+04AE CYRILLIC CAPITAL LETTER STRAIGHT U */,
+ Cyrillic_u_straight = 0x10004af /* U+04AF CYRILLIC SMALL LETTER STRAIGHT U */,
+ Cyrillic_U_straight_bar = 0x10004b0 /* U+04B0 CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE */,
+ Cyrillic_u_straight_bar = 0x10004b1 /* U+04B1 CYRILLIC SMALL LETTER STRAIGHT U WITH STROKE */,
+ Cyrillic_HA_descender = 0x10004b2 /* U+04B2 CYRILLIC CAPITAL LETTER HA WITH DESCENDER */,
+ Cyrillic_ha_descender = 0x10004b3 /* U+04B3 CYRILLIC SMALL LETTER HA WITH DESCENDER */,
+ Cyrillic_CHE_descender = 0x10004b6 /* U+04B6 CYRILLIC CAPITAL LETTER CHE WITH DESCENDER */,
+ Cyrillic_che_descender = 0x10004b7 /* U+04B7 CYRILLIC SMALL LETTER CHE WITH DESCENDER */,
+ Cyrillic_CHE_vertstroke = 0x10004b8 /* U+04B8 CYRILLIC CAPITAL LETTER CHE WITH VERTICAL STROKE */,
+ Cyrillic_che_vertstroke = 0x10004b9 /* U+04B9 CYRILLIC SMALL LETTER CHE WITH VERTICAL STROKE */,
+ Cyrillic_SHHA = 0x10004ba /* U+04BA CYRILLIC CAPITAL LETTER SHHA */,
+ Cyrillic_shha = 0x10004bb /* U+04BB CYRILLIC SMALL LETTER SHHA */,
+ Cyrillic_SCHWA = 0x10004d8 /* U+04D8 CYRILLIC CAPITAL LETTER SCHWA */,
+ Cyrillic_schwa = 0x10004d9 /* U+04D9 CYRILLIC SMALL LETTER SCHWA */,
+ Cyrillic_I_macron = 0x10004e2 /* U+04E2 CYRILLIC CAPITAL LETTER I WITH MACRON */,
+ Cyrillic_i_macron = 0x10004e3 /* U+04E3 CYRILLIC SMALL LETTER I WITH MACRON */,
+ Cyrillic_O_bar = 0x10004e8 /* U+04E8 CYRILLIC CAPITAL LETTER BARRED O */,
+ Cyrillic_o_bar = 0x10004e9 /* U+04E9 CYRILLIC SMALL LETTER BARRED O */,
+ Cyrillic_U_macron = 0x10004ee /* U+04EE CYRILLIC CAPITAL LETTER U WITH MACRON */,
+ Cyrillic_u_macron = 0x10004ef /* U+04EF CYRILLIC SMALL LETTER U WITH MACRON */,
+ Serbian_dje = 0x06a1 /* U+0452 CYRILLIC SMALL LETTER DJE */,
+ Macedonia_gje = 0x06a2 /* U+0453 CYRILLIC SMALL LETTER GJE */,
+ Cyrillic_io = 0x06a3 /* U+0451 CYRILLIC SMALL LETTER IO */,
+ Ukrainian_ie = 0x06a4 /* U+0454 CYRILLIC SMALL LETTER UKRAINIAN IE */,
+ Ukranian_je = 0x06a4 /* deprecated */,
+ Macedonia_dse = 0x06a5 /* U+0455 CYRILLIC SMALL LETTER DZE */,
+ Ukrainian_i = 0x06a6 /* U+0456 CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I */,
+ Ukranian_i = 0x06a6 /* deprecated */,
+ Ukrainian_yi = 0x06a7 /* U+0457 CYRILLIC SMALL LETTER YI */,
+ Ukranian_yi = 0x06a7 /* deprecated */,
+ Cyrillic_je = 0x06a8 /* U+0458 CYRILLIC SMALL LETTER JE */,
+ Serbian_je = 0x06a8 /* deprecated */,
+ Cyrillic_lje = 0x06a9 /* U+0459 CYRILLIC SMALL LETTER LJE */,
+ Serbian_lje = 0x06a9 /* deprecated */,
+ Cyrillic_nje = 0x06aa /* U+045A CYRILLIC SMALL LETTER NJE */,
+ Serbian_nje = 0x06aa /* deprecated */,
+ Serbian_tshe = 0x06ab /* U+045B CYRILLIC SMALL LETTER TSHE */,
+ Macedonia_kje = 0x06ac /* U+045C CYRILLIC SMALL LETTER KJE */,
+ Ukrainian_ghe_with_upturn = 0x06ad /* U+0491 CYRILLIC SMALL LETTER GHE WITH UPTURN */,
+ Byelorussian_shortu = 0x06ae /* U+045E CYRILLIC SMALL LETTER SHORT U */,
+ Cyrillic_dzhe = 0x06af /* U+045F CYRILLIC SMALL LETTER DZHE */,
+ Serbian_dze = 0x06af /* deprecated */,
+ numerosign = 0x06b0 /* U+2116 NUMERO SIGN */,
+ Serbian_DJE = 0x06b1 /* U+0402 CYRILLIC CAPITAL LETTER DJE */,
+ Macedonia_GJE = 0x06b2 /* U+0403 CYRILLIC CAPITAL LETTER GJE */,
+ Cyrillic_IO = 0x06b3 /* U+0401 CYRILLIC CAPITAL LETTER IO */,
+ Ukrainian_IE = 0x06b4 /* U+0404 CYRILLIC CAPITAL LETTER UKRAINIAN IE */,
+ Ukranian_JE = 0x06b4 /* deprecated */,
+ Macedonia_DSE = 0x06b5 /* U+0405 CYRILLIC CAPITAL LETTER DZE */,
+ Ukrainian_I = 0x06b6 /* U+0406 CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I */,
+ Ukranian_I = 0x06b6 /* deprecated */,
+ Ukrainian_YI = 0x06b7 /* U+0407 CYRILLIC CAPITAL LETTER YI */,
+ Ukranian_YI = 0x06b7 /* deprecated */,
+ Cyrillic_JE = 0x06b8 /* U+0408 CYRILLIC CAPITAL LETTER JE */,
+ Serbian_JE = 0x06b8 /* deprecated */,
+ Cyrillic_LJE = 0x06b9 /* U+0409 CYRILLIC CAPITAL LETTER LJE */,
+ Serbian_LJE = 0x06b9 /* deprecated */,
+ Cyrillic_NJE = 0x06ba /* U+040A CYRILLIC CAPITAL LETTER NJE */,
+ Serbian_NJE = 0x06ba /* deprecated */,
+ Serbian_TSHE = 0x06bb /* U+040B CYRILLIC CAPITAL LETTER TSHE */,
+ Macedonia_KJE = 0x06bc /* U+040C CYRILLIC CAPITAL LETTER KJE */,
+ Ukrainian_GHE_WITH_UPTURN = 0x06bd /* U+0490 CYRILLIC CAPITAL LETTER GHE WITH UPTURN */,
+ Byelorussian_SHORTU = 0x06be /* U+040E CYRILLIC CAPITAL LETTER SHORT U */,
+ Cyrillic_DZHE = 0x06bf /* U+040F CYRILLIC CAPITAL LETTER DZHE */,
+ Serbian_DZE = 0x06bf /* deprecated */,
+ Cyrillic_yu = 0x06c0 /* U+044E CYRILLIC SMALL LETTER YU */,
+ Cyrillic_a = 0x06c1 /* U+0430 CYRILLIC SMALL LETTER A */,
+ Cyrillic_be = 0x06c2 /* U+0431 CYRILLIC SMALL LETTER BE */,
+ Cyrillic_tse = 0x06c3 /* U+0446 CYRILLIC SMALL LETTER TSE */,
+ Cyrillic_de = 0x06c4 /* U+0434 CYRILLIC SMALL LETTER DE */,
+ Cyrillic_ie = 0x06c5 /* U+0435 CYRILLIC SMALL LETTER IE */,
+ Cyrillic_ef = 0x06c6 /* U+0444 CYRILLIC SMALL LETTER EF */,
+ Cyrillic_ghe = 0x06c7 /* U+0433 CYRILLIC SMALL LETTER GHE */,
+ Cyrillic_ha = 0x06c8 /* U+0445 CYRILLIC SMALL LETTER HA */,
+ Cyrillic_i = 0x06c9 /* U+0438 CYRILLIC SMALL LETTER I */,
+ Cyrillic_shorti = 0x06ca /* U+0439 CYRILLIC SMALL LETTER SHORT I */,
+ Cyrillic_ka = 0x06cb /* U+043A CYRILLIC SMALL LETTER KA */,
+ Cyrillic_el = 0x06cc /* U+043B CYRILLIC SMALL LETTER EL */,
+ Cyrillic_em = 0x06cd /* U+043C CYRILLIC SMALL LETTER EM */,
+ Cyrillic_en = 0x06ce /* U+043D CYRILLIC SMALL LETTER EN */,
+ Cyrillic_o = 0x06cf /* U+043E CYRILLIC SMALL LETTER O */,
+ Cyrillic_pe = 0x06d0 /* U+043F CYRILLIC SMALL LETTER PE */,
+ Cyrillic_ya = 0x06d1 /* U+044F CYRILLIC SMALL LETTER YA */,
+ Cyrillic_er = 0x06d2 /* U+0440 CYRILLIC SMALL LETTER ER */,
+ Cyrillic_es = 0x06d3 /* U+0441 CYRILLIC SMALL LETTER ES */,
+ Cyrillic_te = 0x06d4 /* U+0442 CYRILLIC SMALL LETTER TE */,
+ Cyrillic_u = 0x06d5 /* U+0443 CYRILLIC SMALL LETTER U */,
+ Cyrillic_zhe = 0x06d6 /* U+0436 CYRILLIC SMALL LETTER ZHE */,
+ Cyrillic_ve = 0x06d7 /* U+0432 CYRILLIC SMALL LETTER VE */,
+ Cyrillic_softsign = 0x06d8 /* U+044C CYRILLIC SMALL LETTER SOFT SIGN */,
+ Cyrillic_yeru = 0x06d9 /* U+044B CYRILLIC SMALL LETTER YERU */,
+ Cyrillic_ze = 0x06da /* U+0437 CYRILLIC SMALL LETTER ZE */,
+ Cyrillic_sha = 0x06db /* U+0448 CYRILLIC SMALL LETTER SHA */,
+ Cyrillic_e = 0x06dc /* U+044D CYRILLIC SMALL LETTER E */,
+ Cyrillic_shcha = 0x06dd /* U+0449 CYRILLIC SMALL LETTER SHCHA */,
+ Cyrillic_che = 0x06de /* U+0447 CYRILLIC SMALL LETTER CHE */,
+ Cyrillic_hardsign = 0x06df /* U+044A CYRILLIC SMALL LETTER HARD SIGN */,
+ Cyrillic_YU = 0x06e0 /* U+042E CYRILLIC CAPITAL LETTER YU */,
+ Cyrillic_A = 0x06e1 /* U+0410 CYRILLIC CAPITAL LETTER A */,
+ Cyrillic_BE = 0x06e2 /* U+0411 CYRILLIC CAPITAL LETTER BE */,
+ Cyrillic_TSE = 0x06e3 /* U+0426 CYRILLIC CAPITAL LETTER TSE */,
+ Cyrillic_DE = 0x06e4 /* U+0414 CYRILLIC CAPITAL LETTER DE */,
+ Cyrillic_IE = 0x06e5 /* U+0415 CYRILLIC CAPITAL LETTER IE */,
+ Cyrillic_EF = 0x06e6 /* U+0424 CYRILLIC CAPITAL LETTER EF */,
+ Cyrillic_GHE = 0x06e7 /* U+0413 CYRILLIC CAPITAL LETTER GHE */,
+ Cyrillic_HA = 0x06e8 /* U+0425 CYRILLIC CAPITAL LETTER HA */,
+ Cyrillic_I = 0x06e9 /* U+0418 CYRILLIC CAPITAL LETTER I */,
+ Cyrillic_SHORTI = 0x06ea /* U+0419 CYRILLIC CAPITAL LETTER SHORT I */,
+ Cyrillic_KA = 0x06eb /* U+041A CYRILLIC CAPITAL LETTER KA */,
+ Cyrillic_EL = 0x06ec /* U+041B CYRILLIC CAPITAL LETTER EL */,
+ Cyrillic_EM = 0x06ed /* U+041C CYRILLIC CAPITAL LETTER EM */,
+ Cyrillic_EN = 0x06ee /* U+041D CYRILLIC CAPITAL LETTER EN */,
+ Cyrillic_O = 0x06ef /* U+041E CYRILLIC CAPITAL LETTER O */,
+ Cyrillic_PE = 0x06f0 /* U+041F CYRILLIC CAPITAL LETTER PE */,
+ Cyrillic_YA = 0x06f1 /* U+042F CYRILLIC CAPITAL LETTER YA */,
+ Cyrillic_ER = 0x06f2 /* U+0420 CYRILLIC CAPITAL LETTER ER */,
+ Cyrillic_ES = 0x06f3 /* U+0421 CYRILLIC CAPITAL LETTER ES */,
+ Cyrillic_TE = 0x06f4 /* U+0422 CYRILLIC CAPITAL LETTER TE */,
+ Cyrillic_U = 0x06f5 /* U+0423 CYRILLIC CAPITAL LETTER U */,
+ Cyrillic_ZHE = 0x06f6 /* U+0416 CYRILLIC CAPITAL LETTER ZHE */,
+ Cyrillic_VE = 0x06f7 /* U+0412 CYRILLIC CAPITAL LETTER VE */,
+ Cyrillic_SOFTSIGN = 0x06f8 /* U+042C CYRILLIC CAPITAL LETTER SOFT SIGN */,
+ Cyrillic_YERU = 0x06f9 /* U+042B CYRILLIC CAPITAL LETTER YERU */,
+ Cyrillic_ZE = 0x06fa /* U+0417 CYRILLIC CAPITAL LETTER ZE */,
+ Cyrillic_SHA = 0x06fb /* U+0428 CYRILLIC CAPITAL LETTER SHA */,
+ Cyrillic_E = 0x06fc /* U+042D CYRILLIC CAPITAL LETTER E */,
+ Cyrillic_SHCHA = 0x06fd /* U+0429 CYRILLIC CAPITAL LETTER SHCHA */,
+ Cyrillic_CHE = 0x06fe /* U+0427 CYRILLIC CAPITAL LETTER CHE */,
+ Cyrillic_HARDSIGN = 0x06ff /* U+042A CYRILLIC CAPITAL LETTER HARD SIGN */,
+ Greek_ALPHAaccent = 0x07a1 /* U+0386 GREEK CAPITAL LETTER ALPHA WITH TONOS */,
+ Greek_EPSILONaccent = 0x07a2 /* U+0388 GREEK CAPITAL LETTER EPSILON WITH TONOS */,
+ Greek_ETAaccent = 0x07a3 /* U+0389 GREEK CAPITAL LETTER ETA WITH TONOS */,
+ Greek_IOTAaccent = 0x07a4 /* U+038A GREEK CAPITAL LETTER IOTA WITH TONOS */,
+ Greek_IOTAdieresis = 0x07a5 /* U+03AA GREEK CAPITAL LETTER IOTA WITH DIALYTIKA */,
+ Greek_IOTAdiaeresis = 0x07a5 /* old typo */,
+ Greek_OMICRONaccent = 0x07a7 /* U+038C GREEK CAPITAL LETTER OMICRON WITH TONOS */,
+ Greek_UPSILONaccent = 0x07a8 /* U+038E GREEK CAPITAL LETTER UPSILON WITH TONOS */,
+ Greek_UPSILONdieresis = 0x07a9 /* U+03AB GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA */,
+ Greek_OMEGAaccent = 0x07ab /* U+038F GREEK CAPITAL LETTER OMEGA WITH TONOS */,
+ Greek_accentdieresis = 0x07ae /* U+0385 GREEK DIALYTIKA TONOS */,
+ Greek_horizbar = 0x07af /* U+2015 HORIZONTAL BAR */,
+ Greek_alphaaccent = 0x07b1 /* U+03AC GREEK SMALL LETTER ALPHA WITH TONOS */,
+ Greek_epsilonaccent = 0x07b2 /* U+03AD GREEK SMALL LETTER EPSILON WITH TONOS */,
+ Greek_etaaccent = 0x07b3 /* U+03AE GREEK SMALL LETTER ETA WITH TONOS */,
+ Greek_iotaaccent = 0x07b4 /* U+03AF GREEK SMALL LETTER IOTA WITH TONOS */,
+ Greek_iotadieresis = 0x07b5 /* U+03CA GREEK SMALL LETTER IOTA WITH DIALYTIKA */,
+ Greek_iotaaccentdieresis = 0x07b6 /* U+0390 GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS */,
+ Greek_omicronaccent = 0x07b7 /* U+03CC GREEK SMALL LETTER OMICRON WITH TONOS */,
+ Greek_upsilonaccent = 0x07b8 /* U+03CD GREEK SMALL LETTER UPSILON WITH TONOS */,
+ Greek_upsilondieresis = 0x07b9 /* U+03CB GREEK SMALL LETTER UPSILON WITH DIALYTIKA */,
+ Greek_upsilonaccentdieresis = 0x07ba /* U+03B0 GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS */,
+ Greek_omegaaccent = 0x07bb /* U+03CE GREEK SMALL LETTER OMEGA WITH TONOS */,
+ Greek_ALPHA = 0x07c1 /* U+0391 GREEK CAPITAL LETTER ALPHA */,
+ Greek_BETA = 0x07c2 /* U+0392 GREEK CAPITAL LETTER BETA */,
+ Greek_GAMMA = 0x07c3 /* U+0393 GREEK CAPITAL LETTER GAMMA */,
+ Greek_DELTA = 0x07c4 /* U+0394 GREEK CAPITAL LETTER DELTA */,
+ Greek_EPSILON = 0x07c5 /* U+0395 GREEK CAPITAL LETTER EPSILON */,
+ Greek_ZETA = 0x07c6 /* U+0396 GREEK CAPITAL LETTER ZETA */,
+ Greek_ETA = 0x07c7 /* U+0397 GREEK CAPITAL LETTER ETA */,
+ Greek_THETA = 0x07c8 /* U+0398 GREEK CAPITAL LETTER THETA */,
+ Greek_IOTA = 0x07c9 /* U+0399 GREEK CAPITAL LETTER IOTA */,
+ Greek_KAPPA = 0x07ca /* U+039A GREEK CAPITAL LETTER KAPPA */,
+ Greek_LAMDA = 0x07cb /* U+039B GREEK CAPITAL LETTER LAMDA */,
+ Greek_LAMBDA = 0x07cb /* U+039B GREEK CAPITAL LETTER LAMDA */,
+ Greek_MU = 0x07cc /* U+039C GREEK CAPITAL LETTER MU */,
+ Greek_NU = 0x07cd /* U+039D GREEK CAPITAL LETTER NU */,
+ Greek_XI = 0x07ce /* U+039E GREEK CAPITAL LETTER XI */,
+ Greek_OMICRON = 0x07cf /* U+039F GREEK CAPITAL LETTER OMICRON */,
+ Greek_PI = 0x07d0 /* U+03A0 GREEK CAPITAL LETTER PI */,
+ Greek_RHO = 0x07d1 /* U+03A1 GREEK CAPITAL LETTER RHO */,
+ Greek_SIGMA = 0x07d2 /* U+03A3 GREEK CAPITAL LETTER SIGMA */,
+ Greek_TAU = 0x07d4 /* U+03A4 GREEK CAPITAL LETTER TAU */,
+ Greek_UPSILON = 0x07d5 /* U+03A5 GREEK CAPITAL LETTER UPSILON */,
+ Greek_PHI = 0x07d6 /* U+03A6 GREEK CAPITAL LETTER PHI */,
+ Greek_CHI = 0x07d7 /* U+03A7 GREEK CAPITAL LETTER CHI */,
+ Greek_PSI = 0x07d8 /* U+03A8 GREEK CAPITAL LETTER PSI */,
+ Greek_OMEGA = 0x07d9 /* U+03A9 GREEK CAPITAL LETTER OMEGA */,
+ Greek_alpha = 0x07e1 /* U+03B1 GREEK SMALL LETTER ALPHA */,
+ Greek_beta = 0x07e2 /* U+03B2 GREEK SMALL LETTER BETA */,
+ Greek_gamma = 0x07e3 /* U+03B3 GREEK SMALL LETTER GAMMA */,
+ Greek_delta = 0x07e4 /* U+03B4 GREEK SMALL LETTER DELTA */,
+ Greek_epsilon = 0x07e5 /* U+03B5 GREEK SMALL LETTER EPSILON */,
+ Greek_zeta = 0x07e6 /* U+03B6 GREEK SMALL LETTER ZETA */,
+ Greek_eta = 0x07e7 /* U+03B7 GREEK SMALL LETTER ETA */,
+ Greek_theta = 0x07e8 /* U+03B8 GREEK SMALL LETTER THETA */,
+ Greek_iota = 0x07e9 /* U+03B9 GREEK SMALL LETTER IOTA */,
+ Greek_kappa = 0x07ea /* U+03BA GREEK SMALL LETTER KAPPA */,
+ Greek_lamda = 0x07eb /* U+03BB GREEK SMALL LETTER LAMDA */,
+ Greek_lambda = 0x07eb /* U+03BB GREEK SMALL LETTER LAMDA */,
+ Greek_mu = 0x07ec /* U+03BC GREEK SMALL LETTER MU */,
+ Greek_nu = 0x07ed /* U+03BD GREEK SMALL LETTER NU */,
+ Greek_xi = 0x07ee /* U+03BE GREEK SMALL LETTER XI */,
+ Greek_omicron = 0x07ef /* U+03BF GREEK SMALL LETTER OMICRON */,
+ Greek_pi = 0x07f0 /* U+03C0 GREEK SMALL LETTER PI */,
+ Greek_rho = 0x07f1 /* U+03C1 GREEK SMALL LETTER RHO */,
+ Greek_sigma = 0x07f2 /* U+03C3 GREEK SMALL LETTER SIGMA */,
+ Greek_finalsmallsigma = 0x07f3 /* U+03C2 GREEK SMALL LETTER FINAL SIGMA */,
+ Greek_tau = 0x07f4 /* U+03C4 GREEK SMALL LETTER TAU */,
+ Greek_upsilon = 0x07f5 /* U+03C5 GREEK SMALL LETTER UPSILON */,
+ Greek_phi = 0x07f6 /* U+03C6 GREEK SMALL LETTER PHI */,
+ Greek_chi = 0x07f7 /* U+03C7 GREEK SMALL LETTER CHI */,
+ Greek_psi = 0x07f8 /* U+03C8 GREEK SMALL LETTER PSI */,
+ Greek_omega = 0x07f9 /* U+03C9 GREEK SMALL LETTER OMEGA */,
+ Greek_switch = 0xff7e /* Alias for mode_switch */,
+ leftradical = 0x08a1 /* U+23B7 RADICAL SYMBOL BOTTOM */,
+ topleftradical = 0x08a2 /*(U+250C BOX DRAWINGS LIGHT DOWN AND RIGHT)*/,
+ horizconnector = 0x08a3 /*(U+2500 BOX DRAWINGS LIGHT HORIZONTAL)*/,
+ topintegral = 0x08a4 /* U+2320 TOP HALF INTEGRAL */,
+ botintegral = 0x08a5 /* U+2321 BOTTOM HALF INTEGRAL */,
+ vertconnector = 0x08a6 /*(U+2502 BOX DRAWINGS LIGHT VERTICAL)*/,
+ topleftsqbracket = 0x08a7 /* U+23A1 LEFT SQUARE BRACKET UPPER CORNER */,
+ botleftsqbracket = 0x08a8 /* U+23A3 LEFT SQUARE BRACKET LOWER CORNER */,
+ toprightsqbracket = 0x08a9 /* U+23A4 RIGHT SQUARE BRACKET UPPER CORNER */,
+ botrightsqbracket = 0x08aa /* U+23A6 RIGHT SQUARE BRACKET LOWER CORNER */,
+ topleftparens = 0x08ab /* U+239B LEFT PARENTHESIS UPPER HOOK */,
+ botleftparens = 0x08ac /* U+239D LEFT PARENTHESIS LOWER HOOK */,
+ toprightparens = 0x08ad /* U+239E RIGHT PARENTHESIS UPPER HOOK */,
+ botrightparens = 0x08ae /* U+23A0 RIGHT PARENTHESIS LOWER HOOK */,
+ leftmiddlecurlybrace = 0x08af /* U+23A8 LEFT CURLY BRACKET MIDDLE PIECE */,
+ rightmiddlecurlybrace = 0x08b0 /* U+23AC RIGHT CURLY BRACKET MIDDLE PIECE */,
+ topleftsummation = 0x08b1,
+ botleftsummation = 0x08b2,
+ topvertsummationconnector = 0x08b3,
+ botvertsummationconnector = 0x08b4,
+ toprightsummation = 0x08b5,
+ botrightsummation = 0x08b6,
+ rightmiddlesummation = 0x08b7,
+ lessthanequal = 0x08bc /* U+2264 LESS-THAN OR EQUAL TO */,
+ notequal = 0x08bd /* U+2260 NOT EQUAL TO */,
+ greaterthanequal = 0x08be /* U+2265 GREATER-THAN OR EQUAL TO */,
+ integral = 0x08bf /* U+222B INTEGRAL */,
+ therefore = 0x08c0 /* U+2234 THEREFORE */,
+ variation = 0x08c1 /* U+221D PROPORTIONAL TO */,
+ infinity = 0x08c2 /* U+221E INFINITY */,
+ nabla = 0x08c5 /* U+2207 NABLA */,
+ approximate = 0x08c8 /* U+223C TILDE OPERATOR */,
+ similarequal = 0x08c9 /* U+2243 ASYMPTOTICALLY EQUAL TO */,
+ ifonlyif = 0x08cd /* U+21D4 LEFT RIGHT DOUBLE ARROW */,
+ implies = 0x08ce /* U+21D2 RIGHTWARDS DOUBLE ARROW */,
+ identical = 0x08cf /* U+2261 IDENTICAL TO */,
+ radical = 0x08d6 /* U+221A SQUARE ROOT */,
+ includedin = 0x08da /* U+2282 SUBSET OF */,
+ includes = 0x08db /* U+2283 SUPERSET OF */,
+ intersection = 0x08dc /* U+2229 INTERSECTION */,
+ union = 0x08dd /* U+222A UNION */,
+ logicaland = 0x08de /* U+2227 LOGICAL AND */,
+ logicalor = 0x08df /* U+2228 LOGICAL OR */,
+ partialderivative = 0x08ef /* U+2202 PARTIAL DIFFERENTIAL */,
+ function = 0x08f6 /* U+0192 LATIN SMALL LETTER F WITH HOOK */,
+ leftarrow = 0x08fb /* U+2190 LEFTWARDS ARROW */,
+ uparrow = 0x08fc /* U+2191 UPWARDS ARROW */,
+ rightarrow = 0x08fd /* U+2192 RIGHTWARDS ARROW */,
+ downarrow = 0x08fe /* U+2193 DOWNWARDS ARROW */,
+ blank = 0x09df,
+ soliddiamond = 0x09e0 /* U+25C6 BLACK DIAMOND */,
+ checkerboard = 0x09e1 /* U+2592 MEDIUM SHADE */,
+ ht = 0x09e2 /* U+2409 SYMBOL FOR HORIZONTAL TABULATION */,
+ ff = 0x09e3 /* U+240C SYMBOL FOR FORM FEED */,
+ cr = 0x09e4 /* U+240D SYMBOL FOR CARRIAGE RETURN */,
+ lf = 0x09e5 /* U+240A SYMBOL FOR LINE FEED */,
+ nl = 0x09e8 /* U+2424 SYMBOL FOR NEWLINE */,
+ vt = 0x09e9 /* U+240B SYMBOL FOR VERTICAL TABULATION */,
+ lowrightcorner = 0x09ea /* U+2518 BOX DRAWINGS LIGHT UP AND LEFT */,
+ uprightcorner = 0x09eb /* U+2510 BOX DRAWINGS LIGHT DOWN AND LEFT */,
+ upleftcorner = 0x09ec /* U+250C BOX DRAWINGS LIGHT DOWN AND RIGHT */,
+ lowleftcorner = 0x09ed /* U+2514 BOX DRAWINGS LIGHT UP AND RIGHT */,
+ crossinglines = 0x09ee /* U+253C BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL */,
+ horizlinescan1 = 0x09ef /* U+23BA HORIZONTAL SCAN LINE-1 */,
+ horizlinescan3 = 0x09f0 /* U+23BB HORIZONTAL SCAN LINE-3 */,
+ horizlinescan5 = 0x09f1 /* U+2500 BOX DRAWINGS LIGHT HORIZONTAL */,
+ horizlinescan7 = 0x09f2 /* U+23BC HORIZONTAL SCAN LINE-7 */,
+ horizlinescan9 = 0x09f3 /* U+23BD HORIZONTAL SCAN LINE-9 */,
+ leftt = 0x09f4 /* U+251C BOX DRAWINGS LIGHT VERTICAL AND RIGHT */,
+ rightt = 0x09f5 /* U+2524 BOX DRAWINGS LIGHT VERTICAL AND LEFT */,
+ bott = 0x09f6 /* U+2534 BOX DRAWINGS LIGHT UP AND HORIZONTAL */,
+ topt = 0x09f7 /* U+252C BOX DRAWINGS LIGHT DOWN AND HORIZONTAL */,
+ vertbar = 0x09f8 /* U+2502 BOX DRAWINGS LIGHT VERTICAL */,
+ emspace = 0x0aa1 /* U+2003 EM SPACE */,
+ enspace = 0x0aa2 /* U+2002 EN SPACE */,
+ em3space = 0x0aa3 /* U+2004 THREE-PER-EM SPACE */,
+ em4space = 0x0aa4 /* U+2005 FOUR-PER-EM SPACE */,
+ digitspace = 0x0aa5 /* U+2007 FIGURE SPACE */,
+ punctspace = 0x0aa6 /* U+2008 PUNCTUATION SPACE */,
+ thinspace = 0x0aa7 /* U+2009 THIN SPACE */,
+ hairspace = 0x0aa8 /* U+200A HAIR SPACE */,
+ emdash = 0x0aa9 /* U+2014 EM DASH */,
+ endash = 0x0aaa /* U+2013 EN DASH */,
+ signifblank = 0x0aac /*(U+2423 OPEN BOX)*/,
+ ellipsis = 0x0aae /* U+2026 HORIZONTAL ELLIPSIS */,
+ doubbaselinedot = 0x0aaf /* U+2025 TWO DOT LEADER */,
+ onethird = 0x0ab0 /* U+2153 VULGAR FRACTION ONE THIRD */,
+ twothirds = 0x0ab1 /* U+2154 VULGAR FRACTION TWO THIRDS */,
+ onefifth = 0x0ab2 /* U+2155 VULGAR FRACTION ONE FIFTH */,
+ twofifths = 0x0ab3 /* U+2156 VULGAR FRACTION TWO FIFTHS */,
+ threefifths = 0x0ab4 /* U+2157 VULGAR FRACTION THREE FIFTHS */,
+ fourfifths = 0x0ab5 /* U+2158 VULGAR FRACTION FOUR FIFTHS */,
+ onesixth = 0x0ab6 /* U+2159 VULGAR FRACTION ONE SIXTH */,
+ fivesixths = 0x0ab7 /* U+215A VULGAR FRACTION FIVE SIXTHS */,
+ careof = 0x0ab8 /* U+2105 CARE OF */,
+ figdash = 0x0abb /* U+2012 FIGURE DASH */,
+ leftanglebracket = 0x0abc /*(U+27E8 MATHEMATICAL LEFT ANGLE BRACKET)*/,
+ decimalpoint = 0x0abd /*(U+002E FULL STOP)*/,
+ rightanglebracket = 0x0abe /*(U+27E9 MATHEMATICAL RIGHT ANGLE BRACKET)*/,
+ marker = 0x0abf,
+ oneeighth = 0x0ac3 /* U+215B VULGAR FRACTION ONE EIGHTH */,
+ threeeighths = 0x0ac4 /* U+215C VULGAR FRACTION THREE EIGHTHS */,
+ fiveeighths = 0x0ac5 /* U+215D VULGAR FRACTION FIVE EIGHTHS */,
+ seveneighths = 0x0ac6 /* U+215E VULGAR FRACTION SEVEN EIGHTHS */,
+ trademark = 0x0ac9 /* U+2122 TRADE MARK SIGN */,
+ signaturemark = 0x0aca /*(U+2613 SALTIRE)*/,
+ trademarkincircle = 0x0acb,
+ leftopentriangle = 0x0acc /*(U+25C1 WHITE LEFT-POINTING TRIANGLE)*/,
+ rightopentriangle = 0x0acd /*(U+25B7 WHITE RIGHT-POINTING TRIANGLE)*/,
+ emopencircle = 0x0ace /*(U+25CB WHITE CIRCLE)*/,
+ emopenrectangle = 0x0acf /*(U+25AF WHITE VERTICAL RECTANGLE)*/,
+ leftsinglequotemark = 0x0ad0 /* U+2018 LEFT SINGLE QUOTATION MARK */,
+ rightsinglequotemark = 0x0ad1 /* U+2019 RIGHT SINGLE QUOTATION MARK */,
+ leftdoublequotemark = 0x0ad2 /* U+201C LEFT DOUBLE QUOTATION MARK */,
+ rightdoublequotemark = 0x0ad3 /* U+201D RIGHT DOUBLE QUOTATION MARK */,
+ prescription = 0x0ad4 /* U+211E PRESCRIPTION TAKE */,
+ permille = 0x0ad5 /* U+2030 PER MILLE SIGN */,
+ minutes = 0x0ad6 /* U+2032 PRIME */,
+ seconds = 0x0ad7 /* U+2033 DOUBLE PRIME */,
+ latincross = 0x0ad9 /* U+271D LATIN CROSS */,
+ hexagram = 0x0ada,
+ filledrectbullet = 0x0adb /*(U+25AC BLACK RECTANGLE)*/,
+ filledlefttribullet = 0x0adc /*(U+25C0 BLACK LEFT-POINTING TRIANGLE)*/,
+ filledrighttribullet = 0x0add /*(U+25B6 BLACK RIGHT-POINTING TRIANGLE)*/,
+ emfilledcircle = 0x0ade /*(U+25CF BLACK CIRCLE)*/,
+ emfilledrect = 0x0adf /*(U+25AE BLACK VERTICAL RECTANGLE)*/,
+ enopencircbullet = 0x0ae0 /*(U+25E6 WHITE BULLET)*/,
+ enopensquarebullet = 0x0ae1 /*(U+25AB WHITE SMALL SQUARE)*/,
+ openrectbullet = 0x0ae2 /*(U+25AD WHITE RECTANGLE)*/,
+ opentribulletup = 0x0ae3 /*(U+25B3 WHITE UP-POINTING TRIANGLE)*/,
+ opentribulletdown = 0x0ae4 /*(U+25BD WHITE DOWN-POINTING TRIANGLE)*/,
+ openstar = 0x0ae5 /*(U+2606 WHITE STAR)*/,
+ enfilledcircbullet = 0x0ae6 /*(U+2022 BULLET)*/,
+ enfilledsqbullet = 0x0ae7 /*(U+25AA BLACK SMALL SQUARE)*/,
+ filledtribulletup = 0x0ae8 /*(U+25B2 BLACK UP-POINTING TRIANGLE)*/,
+ filledtribulletdown = 0x0ae9 /*(U+25BC BLACK DOWN-POINTING TRIANGLE)*/,
+ leftpointer = 0x0aea /*(U+261C WHITE LEFT POINTING INDEX)*/,
+ rightpointer = 0x0aeb /*(U+261E WHITE RIGHT POINTING INDEX)*/,
+ club = 0x0aec /* U+2663 BLACK CLUB SUIT */,
+ diamond = 0x0aed /* U+2666 BLACK DIAMOND SUIT */,
+ heart = 0x0aee /* U+2665 BLACK HEART SUIT */,
+ maltesecross = 0x0af0 /* U+2720 MALTESE CROSS */,
+ dagger = 0x0af1 /* U+2020 DAGGER */,
+ doubledagger = 0x0af2 /* U+2021 DOUBLE DAGGER */,
+ checkmark = 0x0af3 /* U+2713 CHECK MARK */,
+ ballotcross = 0x0af4 /* U+2717 BALLOT X */,
+ musicalsharp = 0x0af5 /* U+266F MUSIC SHARP SIGN */,
+ musicalflat = 0x0af6 /* U+266D MUSIC FLAT SIGN */,
+ malesymbol = 0x0af7 /* U+2642 MALE SIGN */,
+ femalesymbol = 0x0af8 /* U+2640 FEMALE SIGN */,
+ telephone = 0x0af9 /* U+260E BLACK TELEPHONE */,
+ telephonerecorder = 0x0afa /* U+2315 TELEPHONE RECORDER */,
+ phonographcopyright = 0x0afb /* U+2117 SOUND RECORDING COPYRIGHT */,
+ caret = 0x0afc /* U+2038 CARET */,
+ singlelowquotemark = 0x0afd /* U+201A SINGLE LOW-9 QUOTATION MARK */,
+ doublelowquotemark = 0x0afe /* U+201E DOUBLE LOW-9 QUOTATION MARK */,
+ cursor = 0x0aff,
+ leftcaret = 0x0ba3 /*(U+003C LESS-THAN SIGN)*/,
+ rightcaret = 0x0ba6 /*(U+003E GREATER-THAN SIGN)*/,
+ downcaret = 0x0ba8 /*(U+2228 LOGICAL OR)*/,
+ upcaret = 0x0ba9 /*(U+2227 LOGICAL AND)*/,
+ overbar = 0x0bc0 /*(U+00AF MACRON)*/,
+ downtack = 0x0bc2 /* U+22A4 DOWN TACK */,
+ upshoe = 0x0bc3 /*(U+2229 INTERSECTION)*/,
+ downstile = 0x0bc4 /* U+230A LEFT FLOOR */,
+ underbar = 0x0bc6 /*(U+005F LOW LINE)*/,
+ jot = 0x0bca /* U+2218 RING OPERATOR */,
+ quad = 0x0bcc /* U+2395 APL FUNCTIONAL SYMBOL QUAD */,
+ uptack = 0x0bce /* U+22A5 UP TACK */,
+ circle = 0x0bcf /* U+25CB WHITE CIRCLE */,
+ upstile = 0x0bd3 /* U+2308 LEFT CEILING */,
+ downshoe = 0x0bd6 /*(U+222A UNION)*/,
+ rightshoe = 0x0bd8 /*(U+2283 SUPERSET OF)*/,
+ leftshoe = 0x0bda /*(U+2282 SUBSET OF)*/,
+ lefttack = 0x0bdc /* U+22A3 LEFT TACK */,
+ righttack = 0x0bfc /* U+22A2 RIGHT TACK */,
+ hebrew_doublelowline = 0x0cdf /* U+2017 DOUBLE LOW LINE */,
+ hebrew_aleph = 0x0ce0 /* U+05D0 HEBREW LETTER ALEF */,
+ hebrew_bet = 0x0ce1 /* U+05D1 HEBREW LETTER BET */,
+ hebrew_beth = 0x0ce1 /* deprecated */,
+ hebrew_gimel = 0x0ce2 /* U+05D2 HEBREW LETTER GIMEL */,
+ hebrew_gimmel = 0x0ce2 /* deprecated */,
+ hebrew_dalet = 0x0ce3 /* U+05D3 HEBREW LETTER DALET */,
+ hebrew_daleth = 0x0ce3 /* deprecated */,
+ hebrew_he = 0x0ce4 /* U+05D4 HEBREW LETTER HE */,
+ hebrew_waw = 0x0ce5 /* U+05D5 HEBREW LETTER VAV */,
+ hebrew_zain = 0x0ce6 /* U+05D6 HEBREW LETTER ZAYIN */,
+ hebrew_zayin = 0x0ce6 /* deprecated */,
+ hebrew_chet = 0x0ce7 /* U+05D7 HEBREW LETTER HET */,
+ hebrew_het = 0x0ce7 /* deprecated */,
+ hebrew_tet = 0x0ce8 /* U+05D8 HEBREW LETTER TET */,
+ hebrew_teth = 0x0ce8 /* deprecated */,
+ hebrew_yod = 0x0ce9 /* U+05D9 HEBREW LETTER YOD */,
+ hebrew_finalkaph = 0x0cea /* U+05DA HEBREW LETTER FINAL KAF */,
+ hebrew_kaph = 0x0ceb /* U+05DB HEBREW LETTER KAF */,
+ hebrew_lamed = 0x0cec /* U+05DC HEBREW LETTER LAMED */,
+ hebrew_finalmem = 0x0ced /* U+05DD HEBREW LETTER FINAL MEM */,
+ hebrew_mem = 0x0cee /* U+05DE HEBREW LETTER MEM */,
+ hebrew_finalnun = 0x0cef /* U+05DF HEBREW LETTER FINAL NUN */,
+ hebrew_nun = 0x0cf0 /* U+05E0 HEBREW LETTER NUN */,
+ hebrew_samech = 0x0cf1 /* U+05E1 HEBREW LETTER SAMEKH */,
+ hebrew_samekh = 0x0cf1 /* deprecated */,
+ hebrew_ayin = 0x0cf2 /* U+05E2 HEBREW LETTER AYIN */,
+ hebrew_finalpe = 0x0cf3 /* U+05E3 HEBREW LETTER FINAL PE */,
+ hebrew_pe = 0x0cf4 /* U+05E4 HEBREW LETTER PE */,
+ hebrew_finalzade = 0x0cf5 /* U+05E5 HEBREW LETTER FINAL TSADI */,
+ hebrew_finalzadi = 0x0cf5 /* deprecated */,
+ hebrew_zade = 0x0cf6 /* U+05E6 HEBREW LETTER TSADI */,
+ hebrew_zadi = 0x0cf6 /* deprecated */,
+ hebrew_qoph = 0x0cf7 /* U+05E7 HEBREW LETTER QOF */,
+ hebrew_kuf = 0x0cf7 /* deprecated */,
+ hebrew_resh = 0x0cf8 /* U+05E8 HEBREW LETTER RESH */,
+ hebrew_shin = 0x0cf9 /* U+05E9 HEBREW LETTER SHIN */,
+ hebrew_taw = 0x0cfa /* U+05EA HEBREW LETTER TAV */,
+ hebrew_taf = 0x0cfa /* deprecated */,
+ Hebrew_switch = 0xff7e /* Alias for mode_switch */,
+ Thai_kokai = 0x0da1 /* U+0E01 THAI CHARACTER KO KAI */,
+ Thai_khokhai = 0x0da2 /* U+0E02 THAI CHARACTER KHO KHAI */,
+ Thai_khokhuat = 0x0da3 /* U+0E03 THAI CHARACTER KHO KHUAT */,
+ Thai_khokhwai = 0x0da4 /* U+0E04 THAI CHARACTER KHO KHWAI */,
+ Thai_khokhon = 0x0da5 /* U+0E05 THAI CHARACTER KHO KHON */,
+ Thai_khorakhang = 0x0da6 /* U+0E06 THAI CHARACTER KHO RAKHANG */,
+ Thai_ngongu = 0x0da7 /* U+0E07 THAI CHARACTER NGO NGU */,
+ Thai_chochan = 0x0da8 /* U+0E08 THAI CHARACTER CHO CHAN */,
+ Thai_choching = 0x0da9 /* U+0E09 THAI CHARACTER CHO CHING */,
+ Thai_chochang = 0x0daa /* U+0E0A THAI CHARACTER CHO CHANG */,
+ Thai_soso = 0x0dab /* U+0E0B THAI CHARACTER SO SO */,
+ Thai_chochoe = 0x0dac /* U+0E0C THAI CHARACTER CHO CHOE */,
+ Thai_yoying = 0x0dad /* U+0E0D THAI CHARACTER YO YING */,
+ Thai_dochada = 0x0dae /* U+0E0E THAI CHARACTER DO CHADA */,
+ Thai_topatak = 0x0daf /* U+0E0F THAI CHARACTER TO PATAK */,
+ Thai_thothan = 0x0db0 /* U+0E10 THAI CHARACTER THO THAN */,
+ Thai_thonangmontho = 0x0db1 /* U+0E11 THAI CHARACTER THO NANGMONTHO */,
+ Thai_thophuthao = 0x0db2 /* U+0E12 THAI CHARACTER THO PHUTHAO */,
+ Thai_nonen = 0x0db3 /* U+0E13 THAI CHARACTER NO NEN */,
+ Thai_dodek = 0x0db4 /* U+0E14 THAI CHARACTER DO DEK */,
+ Thai_totao = 0x0db5 /* U+0E15 THAI CHARACTER TO TAO */,
+ Thai_thothung = 0x0db6 /* U+0E16 THAI CHARACTER THO THUNG */,
+ Thai_thothahan = 0x0db7 /* U+0E17 THAI CHARACTER THO THAHAN */,
+ Thai_thothong = 0x0db8 /* U+0E18 THAI CHARACTER THO THONG */,
+ Thai_nonu = 0x0db9 /* U+0E19 THAI CHARACTER NO NU */,
+ Thai_bobaimai = 0x0dba /* U+0E1A THAI CHARACTER BO BAIMAI */,
+ Thai_popla = 0x0dbb /* U+0E1B THAI CHARACTER PO PLA */,
+ Thai_phophung = 0x0dbc /* U+0E1C THAI CHARACTER PHO PHUNG */,
+ Thai_fofa = 0x0dbd /* U+0E1D THAI CHARACTER FO FA */,
+ Thai_phophan = 0x0dbe /* U+0E1E THAI CHARACTER PHO PHAN */,
+ Thai_fofan = 0x0dbf /* U+0E1F THAI CHARACTER FO FAN */,
+ Thai_phosamphao = 0x0dc0 /* U+0E20 THAI CHARACTER PHO SAMPHAO */,
+ Thai_moma = 0x0dc1 /* U+0E21 THAI CHARACTER MO MA */,
+ Thai_yoyak = 0x0dc2 /* U+0E22 THAI CHARACTER YO YAK */,
+ Thai_rorua = 0x0dc3 /* U+0E23 THAI CHARACTER RO RUA */,
+ Thai_ru = 0x0dc4 /* U+0E24 THAI CHARACTER RU */,
+ Thai_loling = 0x0dc5 /* U+0E25 THAI CHARACTER LO LING */,
+ Thai_lu = 0x0dc6 /* U+0E26 THAI CHARACTER LU */,
+ Thai_wowaen = 0x0dc7 /* U+0E27 THAI CHARACTER WO WAEN */,
+ Thai_sosala = 0x0dc8 /* U+0E28 THAI CHARACTER SO SALA */,
+ Thai_sorusi = 0x0dc9 /* U+0E29 THAI CHARACTER SO RUSI */,
+ Thai_sosua = 0x0dca /* U+0E2A THAI CHARACTER SO SUA */,
+ Thai_hohip = 0x0dcb /* U+0E2B THAI CHARACTER HO HIP */,
+ Thai_lochula = 0x0dcc /* U+0E2C THAI CHARACTER LO CHULA */,
+ Thai_oang = 0x0dcd /* U+0E2D THAI CHARACTER O ANG */,
+ Thai_honokhuk = 0x0dce /* U+0E2E THAI CHARACTER HO NOKHUK */,
+ Thai_paiyannoi = 0x0dcf /* U+0E2F THAI CHARACTER PAIYANNOI */,
+ Thai_saraa = 0x0dd0 /* U+0E30 THAI CHARACTER SARA A */,
+ Thai_maihanakat = 0x0dd1 /* U+0E31 THAI CHARACTER MAI HAN-AKAT */,
+ Thai_saraaa = 0x0dd2 /* U+0E32 THAI CHARACTER SARA AA */,
+ Thai_saraam = 0x0dd3 /* U+0E33 THAI CHARACTER SARA AM */,
+ Thai_sarai = 0x0dd4 /* U+0E34 THAI CHARACTER SARA I */,
+ Thai_saraii = 0x0dd5 /* U+0E35 THAI CHARACTER SARA II */,
+ Thai_saraue = 0x0dd6 /* U+0E36 THAI CHARACTER SARA UE */,
+ Thai_sarauee = 0x0dd7 /* U+0E37 THAI CHARACTER SARA UEE */,
+ Thai_sarau = 0x0dd8 /* U+0E38 THAI CHARACTER SARA U */,
+ Thai_sarauu = 0x0dd9 /* U+0E39 THAI CHARACTER SARA UU */,
+ Thai_phinthu = 0x0dda /* U+0E3A THAI CHARACTER PHINTHU */,
+ Thai_maihanakat_maitho = 0x0dde,
+ Thai_baht = 0x0ddf /* U+0E3F THAI CURRENCY SYMBOL BAHT */,
+ Thai_sarae = 0x0de0 /* U+0E40 THAI CHARACTER SARA E */,
+ Thai_saraae = 0x0de1 /* U+0E41 THAI CHARACTER SARA AE */,
+ Thai_sarao = 0x0de2 /* U+0E42 THAI CHARACTER SARA O */,
+ Thai_saraaimaimuan = 0x0de3 /* U+0E43 THAI CHARACTER SARA AI MAIMUAN */,
+ Thai_saraaimaimalai = 0x0de4 /* U+0E44 THAI CHARACTER SARA AI MAIMALAI */,
+ Thai_lakkhangyao = 0x0de5 /* U+0E45 THAI CHARACTER LAKKHANGYAO */,
+ Thai_maiyamok = 0x0de6 /* U+0E46 THAI CHARACTER MAIYAMOK */,
+ Thai_maitaikhu = 0x0de7 /* U+0E47 THAI CHARACTER MAITAIKHU */,
+ Thai_maiek = 0x0de8 /* U+0E48 THAI CHARACTER MAI EK */,
+ Thai_maitho = 0x0de9 /* U+0E49 THAI CHARACTER MAI THO */,
+ Thai_maitri = 0x0dea /* U+0E4A THAI CHARACTER MAI TRI */,
+ Thai_maichattawa = 0x0deb /* U+0E4B THAI CHARACTER MAI CHATTAWA */,
+ Thai_thanthakhat = 0x0dec /* U+0E4C THAI CHARACTER THANTHAKHAT */,
+ Thai_nikhahit = 0x0ded /* U+0E4D THAI CHARACTER NIKHAHIT */,
+ Thai_leksun = 0x0df0 /* U+0E50 THAI DIGIT ZERO */,
+ Thai_leknung = 0x0df1 /* U+0E51 THAI DIGIT ONE */,
+ Thai_leksong = 0x0df2 /* U+0E52 THAI DIGIT TWO */,
+ Thai_leksam = 0x0df3 /* U+0E53 THAI DIGIT THREE */,
+ Thai_leksi = 0x0df4 /* U+0E54 THAI DIGIT FOUR */,
+ Thai_lekha = 0x0df5 /* U+0E55 THAI DIGIT FIVE */,
+ Thai_lekhok = 0x0df6 /* U+0E56 THAI DIGIT SIX */,
+ Thai_lekchet = 0x0df7 /* U+0E57 THAI DIGIT SEVEN */,
+ Thai_lekpaet = 0x0df8 /* U+0E58 THAI DIGIT EIGHT */,
+ Thai_lekkao = 0x0df9 /* U+0E59 THAI DIGIT NINE */,
+ Hangul = 0xff31 /* Hangul start/stop(toggle) */,
+ Hangul_Start = 0xff32 /* Hangul start */,
+ Hangul_End = 0xff33 /* Hangul end, English start */,
+ Hangul_Hanja = 0xff34 /* Start Hangul->Hanja Conversion */,
+ Hangul_Jamo = 0xff35 /* Hangul Jamo mode */,
+ Hangul_Romaja = 0xff36 /* Hangul Romaja mode */,
+ Hangul_Codeinput = 0xff37 /* Hangul code input mode */,
+ Hangul_Jeonja = 0xff38 /* Jeonja mode */,
+ Hangul_Banja = 0xff39 /* Banja mode */,
+ Hangul_PreHanja = 0xff3a /* Pre Hanja conversion */,
+ Hangul_PostHanja = 0xff3b /* Post Hanja conversion */,
+ Hangul_SingleCandidate = 0xff3c /* Single candidate */,
+ Hangul_MultipleCandidate = 0xff3d /* Multiple candidate */,
+ Hangul_PreviousCandidate = 0xff3e /* Previous candidate */,
+ Hangul_Special = 0xff3f /* Special symbols */,
+ Hangul_switch = 0xff7e /* Alias for mode_switch */,
+ Hangul_Kiyeog = 0x0ea1,
+ Hangul_SsangKiyeog = 0x0ea2,
+ Hangul_KiyeogSios = 0x0ea3,
+ Hangul_Nieun = 0x0ea4,
+ Hangul_NieunJieuj = 0x0ea5,
+ Hangul_NieunHieuh = 0x0ea6,
+ Hangul_Dikeud = 0x0ea7,
+ Hangul_SsangDikeud = 0x0ea8,
+ Hangul_Rieul = 0x0ea9,
+ Hangul_RieulKiyeog = 0x0eaa,
+ Hangul_RieulMieum = 0x0eab,
+ Hangul_RieulPieub = 0x0eac,
+ Hangul_RieulSios = 0x0ead,
+ Hangul_RieulTieut = 0x0eae,
+ Hangul_RieulPhieuf = 0x0eaf,
+ Hangul_RieulHieuh = 0x0eb0,
+ Hangul_Mieum = 0x0eb1,
+ Hangul_Pieub = 0x0eb2,
+ Hangul_SsangPieub = 0x0eb3,
+ Hangul_PieubSios = 0x0eb4,
+ Hangul_Sios = 0x0eb5,
+ Hangul_SsangSios = 0x0eb6,
+ Hangul_Ieung = 0x0eb7,
+ Hangul_Jieuj = 0x0eb8,
+ Hangul_SsangJieuj = 0x0eb9,
+ Hangul_Cieuc = 0x0eba,
+ Hangul_Khieuq = 0x0ebb,
+ Hangul_Tieut = 0x0ebc,
+ Hangul_Phieuf = 0x0ebd,
+ Hangul_Hieuh = 0x0ebe,
+ Hangul_A = 0x0ebf,
+ Hangul_AE = 0x0ec0,
+ Hangul_YA = 0x0ec1,
+ Hangul_YAE = 0x0ec2,
+ Hangul_EO = 0x0ec3,
+ Hangul_E = 0x0ec4,
+ Hangul_YEO = 0x0ec5,
+ Hangul_YE = 0x0ec6,
+ Hangul_O = 0x0ec7,
+ Hangul_WA = 0x0ec8,
+ Hangul_WAE = 0x0ec9,
+ Hangul_OE = 0x0eca,
+ Hangul_YO = 0x0ecb,
+ Hangul_U = 0x0ecc,
+ Hangul_WEO = 0x0ecd,
+ Hangul_WE = 0x0ece,
+ Hangul_WI = 0x0ecf,
+ Hangul_YU = 0x0ed0,
+ Hangul_EU = 0x0ed1,
+ Hangul_YI = 0x0ed2,
+ Hangul_I = 0x0ed3,
+ Hangul_J_Kiyeog = 0x0ed4,
+ Hangul_J_SsangKiyeog = 0x0ed5,
+ Hangul_J_KiyeogSios = 0x0ed6,
+ Hangul_J_Nieun = 0x0ed7,
+ Hangul_J_NieunJieuj = 0x0ed8,
+ Hangul_J_NieunHieuh = 0x0ed9,
+ Hangul_J_Dikeud = 0x0eda,
+ Hangul_J_Rieul = 0x0edb,
+ Hangul_J_RieulKiyeog = 0x0edc,
+ Hangul_J_RieulMieum = 0x0edd,
+ Hangul_J_RieulPieub = 0x0ede,
+ Hangul_J_RieulSios = 0x0edf,
+ Hangul_J_RieulTieut = 0x0ee0,
+ Hangul_J_RieulPhieuf = 0x0ee1,
+ Hangul_J_RieulHieuh = 0x0ee2,
+ Hangul_J_Mieum = 0x0ee3,
+ Hangul_J_Pieub = 0x0ee4,
+ Hangul_J_PieubSios = 0x0ee5,
+ Hangul_J_Sios = 0x0ee6,
+ Hangul_J_SsangSios = 0x0ee7,
+ Hangul_J_Ieung = 0x0ee8,
+ Hangul_J_Jieuj = 0x0ee9,
+ Hangul_J_Cieuc = 0x0eea,
+ Hangul_J_Khieuq = 0x0eeb,
+ Hangul_J_Tieut = 0x0eec,
+ Hangul_J_Phieuf = 0x0eed,
+ Hangul_J_Hieuh = 0x0eee,
+ Hangul_RieulYeorinHieuh = 0x0eef,
+ Hangul_SunkyeongeumMieum = 0x0ef0,
+ Hangul_SunkyeongeumPieub = 0x0ef1,
+ Hangul_PanSios = 0x0ef2,
+ Hangul_KkogjiDalrinIeung = 0x0ef3,
+ Hangul_SunkyeongeumPhieuf = 0x0ef4,
+ Hangul_YeorinHieuh = 0x0ef5,
+ Hangul_AraeA = 0x0ef6,
+ Hangul_AraeAE = 0x0ef7,
+ Hangul_J_PanSios = 0x0ef8,
+ Hangul_J_KkogjiDalrinIeung = 0x0ef9,
+ Hangul_J_YeorinHieuh = 0x0efa,
+ Korean_Won = 0x0eff /*(U+20A9 WON SIGN)*/,
+ Armenian_ligature_ew = 0x1000587 /* U+0587 ARMENIAN SMALL LIGATURE ECH YIWN */,
+ Armenian_full_stop = 0x1000589 /* U+0589 ARMENIAN FULL STOP */,
+ Armenian_verjaket = 0x1000589 /* U+0589 ARMENIAN FULL STOP */,
+ Armenian_separation_mark = 0x100055d /* U+055D ARMENIAN COMMA */,
+ Armenian_but = 0x100055d /* U+055D ARMENIAN COMMA */,
+ Armenian_hyphen = 0x100058a /* U+058A ARMENIAN HYPHEN */,
+ Armenian_yentamna = 0x100058a /* U+058A ARMENIAN HYPHEN */,
+ Armenian_exclam = 0x100055c /* U+055C ARMENIAN EXCLAMATION MARK */,
+ Armenian_amanak = 0x100055c /* U+055C ARMENIAN EXCLAMATION MARK */,
+ Armenian_accent = 0x100055b /* U+055B ARMENIAN EMPHASIS MARK */,
+ Armenian_shesht = 0x100055b /* U+055B ARMENIAN EMPHASIS MARK */,
+ Armenian_question = 0x100055e /* U+055E ARMENIAN QUESTION MARK */,
+ Armenian_paruyk = 0x100055e /* U+055E ARMENIAN QUESTION MARK */,
+ Armenian_AYB = 0x1000531 /* U+0531 ARMENIAN CAPITAL LETTER AYB */,
+ Armenian_ayb = 0x1000561 /* U+0561 ARMENIAN SMALL LETTER AYB */,
+ Armenian_BEN = 0x1000532 /* U+0532 ARMENIAN CAPITAL LETTER BEN */,
+ Armenian_ben = 0x1000562 /* U+0562 ARMENIAN SMALL LETTER BEN */,
+ Armenian_GIM = 0x1000533 /* U+0533 ARMENIAN CAPITAL LETTER GIM */,
+ Armenian_gim = 0x1000563 /* U+0563 ARMENIAN SMALL LETTER GIM */,
+ Armenian_DA = 0x1000534 /* U+0534 ARMENIAN CAPITAL LETTER DA */,
+ Armenian_da = 0x1000564 /* U+0564 ARMENIAN SMALL LETTER DA */,
+ Armenian_YECH = 0x1000535 /* U+0535 ARMENIAN CAPITAL LETTER ECH */,
+ Armenian_yech = 0x1000565 /* U+0565 ARMENIAN SMALL LETTER ECH */,
+ Armenian_ZA = 0x1000536 /* U+0536 ARMENIAN CAPITAL LETTER ZA */,
+ Armenian_za = 0x1000566 /* U+0566 ARMENIAN SMALL LETTER ZA */,
+ Armenian_E = 0x1000537 /* U+0537 ARMENIAN CAPITAL LETTER EH */,
+ Armenian_e = 0x1000567 /* U+0567 ARMENIAN SMALL LETTER EH */,
+ Armenian_AT = 0x1000538 /* U+0538 ARMENIAN CAPITAL LETTER ET */,
+ Armenian_at = 0x1000568 /* U+0568 ARMENIAN SMALL LETTER ET */,
+ Armenian_TO = 0x1000539 /* U+0539 ARMENIAN CAPITAL LETTER TO */,
+ Armenian_to = 0x1000569 /* U+0569 ARMENIAN SMALL LETTER TO */,
+ Armenian_ZHE = 0x100053a /* U+053A ARMENIAN CAPITAL LETTER ZHE */,
+ Armenian_zhe = 0x100056a /* U+056A ARMENIAN SMALL LETTER ZHE */,
+ Armenian_INI = 0x100053b /* U+053B ARMENIAN CAPITAL LETTER INI */,
+ Armenian_ini = 0x100056b /* U+056B ARMENIAN SMALL LETTER INI */,
+ Armenian_LYUN = 0x100053c /* U+053C ARMENIAN CAPITAL LETTER LIWN */,
+ Armenian_lyun = 0x100056c /* U+056C ARMENIAN SMALL LETTER LIWN */,
+ Armenian_KHE = 0x100053d /* U+053D ARMENIAN CAPITAL LETTER XEH */,
+ Armenian_khe = 0x100056d /* U+056D ARMENIAN SMALL LETTER XEH */,
+ Armenian_TSA = 0x100053e /* U+053E ARMENIAN CAPITAL LETTER CA */,
+ Armenian_tsa = 0x100056e /* U+056E ARMENIAN SMALL LETTER CA */,
+ Armenian_KEN = 0x100053f /* U+053F ARMENIAN CAPITAL LETTER KEN */,
+ Armenian_ken = 0x100056f /* U+056F ARMENIAN SMALL LETTER KEN */,
+ Armenian_HO = 0x1000540 /* U+0540 ARMENIAN CAPITAL LETTER HO */,
+ Armenian_ho = 0x1000570 /* U+0570 ARMENIAN SMALL LETTER HO */,
+ Armenian_DZA = 0x1000541 /* U+0541 ARMENIAN CAPITAL LETTER JA */,
+ Armenian_dza = 0x1000571 /* U+0571 ARMENIAN SMALL LETTER JA */,
+ Armenian_GHAT = 0x1000542 /* U+0542 ARMENIAN CAPITAL LETTER GHAD */,
+ Armenian_ghat = 0x1000572 /* U+0572 ARMENIAN SMALL LETTER GHAD */,
+ Armenian_TCHE = 0x1000543 /* U+0543 ARMENIAN CAPITAL LETTER CHEH */,
+ Armenian_tche = 0x1000573 /* U+0573 ARMENIAN SMALL LETTER CHEH */,
+ Armenian_MEN = 0x1000544 /* U+0544 ARMENIAN CAPITAL LETTER MEN */,
+ Armenian_men = 0x1000574 /* U+0574 ARMENIAN SMALL LETTER MEN */,
+ Armenian_HI = 0x1000545 /* U+0545 ARMENIAN CAPITAL LETTER YI */,
+ Armenian_hi = 0x1000575 /* U+0575 ARMENIAN SMALL LETTER YI */,
+ Armenian_NU = 0x1000546 /* U+0546 ARMENIAN CAPITAL LETTER NOW */,
+ Armenian_nu = 0x1000576 /* U+0576 ARMENIAN SMALL LETTER NOW */,
+ Armenian_SHA = 0x1000547 /* U+0547 ARMENIAN CAPITAL LETTER SHA */,
+ Armenian_sha = 0x1000577 /* U+0577 ARMENIAN SMALL LETTER SHA */,
+ Armenian_VO = 0x1000548 /* U+0548 ARMENIAN CAPITAL LETTER VO */,
+ Armenian_vo = 0x1000578 /* U+0578 ARMENIAN SMALL LETTER VO */,
+ Armenian_CHA = 0x1000549 /* U+0549 ARMENIAN CAPITAL LETTER CHA */,
+ Armenian_cha = 0x1000579 /* U+0579 ARMENIAN SMALL LETTER CHA */,
+ Armenian_PE = 0x100054a /* U+054A ARMENIAN CAPITAL LETTER PEH */,
+ Armenian_pe = 0x100057a /* U+057A ARMENIAN SMALL LETTER PEH */,
+ Armenian_JE = 0x100054b /* U+054B ARMENIAN CAPITAL LETTER JHEH */,
+ Armenian_je = 0x100057b /* U+057B ARMENIAN SMALL LETTER JHEH */,
+ Armenian_RA = 0x100054c /* U+054C ARMENIAN CAPITAL LETTER RA */,
+ Armenian_ra = 0x100057c /* U+057C ARMENIAN SMALL LETTER RA */,
+ Armenian_SE = 0x100054d /* U+054D ARMENIAN CAPITAL LETTER SEH */,
+ Armenian_se = 0x100057d /* U+057D ARMENIAN SMALL LETTER SEH */,
+ Armenian_VEV = 0x100054e /* U+054E ARMENIAN CAPITAL LETTER VEW */,
+ Armenian_vev = 0x100057e /* U+057E ARMENIAN SMALL LETTER VEW */,
+ Armenian_TYUN = 0x100054f /* U+054F ARMENIAN CAPITAL LETTER TIWN */,
+ Armenian_tyun = 0x100057f /* U+057F ARMENIAN SMALL LETTER TIWN */,
+ Armenian_RE = 0x1000550 /* U+0550 ARMENIAN CAPITAL LETTER REH */,
+ Armenian_re = 0x1000580 /* U+0580 ARMENIAN SMALL LETTER REH */,
+ Armenian_TSO = 0x1000551 /* U+0551 ARMENIAN CAPITAL LETTER CO */,
+ Armenian_tso = 0x1000581 /* U+0581 ARMENIAN SMALL LETTER CO */,
+ Armenian_VYUN = 0x1000552 /* U+0552 ARMENIAN CAPITAL LETTER YIWN */,
+ Armenian_vyun = 0x1000582 /* U+0582 ARMENIAN SMALL LETTER YIWN */,
+ Armenian_PYUR = 0x1000553 /* U+0553 ARMENIAN CAPITAL LETTER PIWR */,
+ Armenian_pyur = 0x1000583 /* U+0583 ARMENIAN SMALL LETTER PIWR */,
+ Armenian_KE = 0x1000554 /* U+0554 ARMENIAN CAPITAL LETTER KEH */,
+ Armenian_ke = 0x1000584 /* U+0584 ARMENIAN SMALL LETTER KEH */,
+ Armenian_O = 0x1000555 /* U+0555 ARMENIAN CAPITAL LETTER OH */,
+ Armenian_o = 0x1000585 /* U+0585 ARMENIAN SMALL LETTER OH */,
+ Armenian_FE = 0x1000556 /* U+0556 ARMENIAN CAPITAL LETTER FEH */,
+ Armenian_fe = 0x1000586 /* U+0586 ARMENIAN SMALL LETTER FEH */,
+ Armenian_apostrophe = 0x100055a /* U+055A ARMENIAN APOSTROPHE */,
+ Georgian_an = 0x10010d0 /* U+10D0 GEORGIAN LETTER AN */,
+ Georgian_ban = 0x10010d1 /* U+10D1 GEORGIAN LETTER BAN */,
+ Georgian_gan = 0x10010d2 /* U+10D2 GEORGIAN LETTER GAN */,
+ Georgian_don = 0x10010d3 /* U+10D3 GEORGIAN LETTER DON */,
+ Georgian_en = 0x10010d4 /* U+10D4 GEORGIAN LETTER EN */,
+ Georgian_vin = 0x10010d5 /* U+10D5 GEORGIAN LETTER VIN */,
+ Georgian_zen = 0x10010d6 /* U+10D6 GEORGIAN LETTER ZEN */,
+ Georgian_tan = 0x10010d7 /* U+10D7 GEORGIAN LETTER TAN */,
+ Georgian_in = 0x10010d8 /* U+10D8 GEORGIAN LETTER IN */,
+ Georgian_kan = 0x10010d9 /* U+10D9 GEORGIAN LETTER KAN */,
+ Georgian_las = 0x10010da /* U+10DA GEORGIAN LETTER LAS */,
+ Georgian_man = 0x10010db /* U+10DB GEORGIAN LETTER MAN */,
+ Georgian_nar = 0x10010dc /* U+10DC GEORGIAN LETTER NAR */,
+ Georgian_on = 0x10010dd /* U+10DD GEORGIAN LETTER ON */,
+ Georgian_par = 0x10010de /* U+10DE GEORGIAN LETTER PAR */,
+ Georgian_zhar = 0x10010df /* U+10DF GEORGIAN LETTER ZHAR */,
+ Georgian_rae = 0x10010e0 /* U+10E0 GEORGIAN LETTER RAE */,
+ Georgian_san = 0x10010e1 /* U+10E1 GEORGIAN LETTER SAN */,
+ Georgian_tar = 0x10010e2 /* U+10E2 GEORGIAN LETTER TAR */,
+ Georgian_un = 0x10010e3 /* U+10E3 GEORGIAN LETTER UN */,
+ Georgian_phar = 0x10010e4 /* U+10E4 GEORGIAN LETTER PHAR */,
+ Georgian_khar = 0x10010e5 /* U+10E5 GEORGIAN LETTER KHAR */,
+ Georgian_ghan = 0x10010e6 /* U+10E6 GEORGIAN LETTER GHAN */,
+ Georgian_qar = 0x10010e7 /* U+10E7 GEORGIAN LETTER QAR */,
+ Georgian_shin = 0x10010e8 /* U+10E8 GEORGIAN LETTER SHIN */,
+ Georgian_chin = 0x10010e9 /* U+10E9 GEORGIAN LETTER CHIN */,
+ Georgian_can = 0x10010ea /* U+10EA GEORGIAN LETTER CAN */,
+ Georgian_jil = 0x10010eb /* U+10EB GEORGIAN LETTER JIL */,
+ Georgian_cil = 0x10010ec /* U+10EC GEORGIAN LETTER CIL */,
+ Georgian_char = 0x10010ed /* U+10ED GEORGIAN LETTER CHAR */,
+ Georgian_xan = 0x10010ee /* U+10EE GEORGIAN LETTER XAN */,
+ Georgian_jhan = 0x10010ef /* U+10EF GEORGIAN LETTER JHAN */,
+ Georgian_hae = 0x10010f0 /* U+10F0 GEORGIAN LETTER HAE */,
+ Georgian_he = 0x10010f1 /* U+10F1 GEORGIAN LETTER HE */,
+ Georgian_hie = 0x10010f2 /* U+10F2 GEORGIAN LETTER HIE */,
+ Georgian_we = 0x10010f3 /* U+10F3 GEORGIAN LETTER WE */,
+ Georgian_har = 0x10010f4 /* U+10F4 GEORGIAN LETTER HAR */,
+ Georgian_hoe = 0x10010f5 /* U+10F5 GEORGIAN LETTER HOE */,
+ Georgian_fi = 0x10010f6 /* U+10F6 GEORGIAN LETTER FI */,
+ Xabovedot = 0x1001e8a /* U+1E8A LATIN CAPITAL LETTER X WITH DOT ABOVE */,
+ Ibreve = 0x100012c /* U+012C LATIN CAPITAL LETTER I WITH BREVE */,
+ Zstroke = 0x10001b5 /* U+01B5 LATIN CAPITAL LETTER Z WITH STROKE */,
+ Gcaron = 0x10001e6 /* U+01E6 LATIN CAPITAL LETTER G WITH CARON */,
+ Ocaron = 0x10001d1 /* U+01D2 LATIN CAPITAL LETTER O WITH CARON */,
+ Obarred = 0x100019f /* U+019F LATIN CAPITAL LETTER O WITH MIDDLE TILDE */,
+ xabovedot = 0x1001e8b /* U+1E8B LATIN SMALL LETTER X WITH DOT ABOVE */,
+ ibreve = 0x100012d /* U+012D LATIN SMALL LETTER I WITH BREVE */,
+ zstroke = 0x10001b6 /* U+01B6 LATIN SMALL LETTER Z WITH STROKE */,
+ gcaron = 0x10001e7 /* U+01E7 LATIN SMALL LETTER G WITH CARON */,
+ ocaron = 0x10001d2 /* U+01D2 LATIN SMALL LETTER O WITH CARON */,
+ obarred = 0x1000275 /* U+0275 LATIN SMALL LETTER BARRED O */,
+ SCHWA = 0x100018f /* U+018F LATIN CAPITAL LETTER SCHWA */,
+ schwa = 0x1000259 /* U+0259 LATIN SMALL LETTER SCHWA */,
+ EZH = 0x10001b7 /* U+01B7 LATIN CAPITAL LETTER EZH */,
+ ezh = 0x1000292 /* U+0292 LATIN SMALL LETTER EZH */,
+ Lbelowdot = 0x1001e36 /* U+1E36 LATIN CAPITAL LETTER L WITH DOT BELOW */,
+ lbelowdot = 0x1001e37 /* U+1E37 LATIN SMALL LETTER L WITH DOT BELOW */,
+ Abelowdot = 0x1001ea0 /* U+1EA0 LATIN CAPITAL LETTER A WITH DOT BELOW */,
+ abelowdot = 0x1001ea1 /* U+1EA1 LATIN SMALL LETTER A WITH DOT BELOW */,
+ Ahook = 0x1001ea2 /* U+1EA2 LATIN CAPITAL LETTER A WITH HOOK ABOVE */,
+ ahook = 0x1001ea3 /* U+1EA3 LATIN SMALL LETTER A WITH HOOK ABOVE */,
+ Acircumflexacute = 0x1001ea4 /* U+1EA4 LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE */,
+ acircumflexacute = 0x1001ea5 /* U+1EA5 LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE */,
+ Acircumflexgrave = 0x1001ea6 /* U+1EA6 LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE */,
+ acircumflexgrave = 0x1001ea7 /* U+1EA7 LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE */,
+ Acircumflexhook = 0x1001ea8 /* U+1EA8 LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE */,
+ acircumflexhook = 0x1001ea9 /* U+1EA9 LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE */,
+ Acircumflextilde = 0x1001eaa /* U+1EAA LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE */,
+ acircumflextilde = 0x1001eab /* U+1EAB LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE */,
+ Acircumflexbelowdot = 0x1001eac /* U+1EAC LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW */,
+ acircumflexbelowdot = 0x1001ead /* U+1EAD LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW */,
+ Abreveacute = 0x1001eae /* U+1EAE LATIN CAPITAL LETTER A WITH BREVE AND ACUTE */,
+ abreveacute = 0x1001eaf /* U+1EAF LATIN SMALL LETTER A WITH BREVE AND ACUTE */,
+ Abrevegrave = 0x1001eb0 /* U+1EB0 LATIN CAPITAL LETTER A WITH BREVE AND GRAVE */,
+ abrevegrave = 0x1001eb1 /* U+1EB1 LATIN SMALL LETTER A WITH BREVE AND GRAVE */,
+ Abrevehook = 0x1001eb2 /* U+1EB2 LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE */,
+ abrevehook = 0x1001eb3 /* U+1EB3 LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE */,
+ Abrevetilde = 0x1001eb4 /* U+1EB4 LATIN CAPITAL LETTER A WITH BREVE AND TILDE */,
+ abrevetilde = 0x1001eb5 /* U+1EB5 LATIN SMALL LETTER A WITH BREVE AND TILDE */,
+ Abrevebelowdot = 0x1001eb6 /* U+1EB6 LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW */,
+ abrevebelowdot = 0x1001eb7 /* U+1EB7 LATIN SMALL LETTER A WITH BREVE AND DOT BELOW */,
+ Ebelowdot = 0x1001eb8 /* U+1EB8 LATIN CAPITAL LETTER E WITH DOT BELOW */,
+ ebelowdot = 0x1001eb9 /* U+1EB9 LATIN SMALL LETTER E WITH DOT BELOW */,
+ Ehook = 0x1001eba /* U+1EBA LATIN CAPITAL LETTER E WITH HOOK ABOVE */,
+ ehook = 0x1001ebb /* U+1EBB LATIN SMALL LETTER E WITH HOOK ABOVE */,
+ Etilde = 0x1001ebc /* U+1EBC LATIN CAPITAL LETTER E WITH TILDE */,
+ etilde = 0x1001ebd /* U+1EBD LATIN SMALL LETTER E WITH TILDE */,
+ Ecircumflexacute = 0x1001ebe /* U+1EBE LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE */,
+ ecircumflexacute = 0x1001ebf /* U+1EBF LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE */,
+ Ecircumflexgrave = 0x1001ec0 /* U+1EC0 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE */,
+ ecircumflexgrave = 0x1001ec1 /* U+1EC1 LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE */,
+ Ecircumflexhook = 0x1001ec2 /* U+1EC2 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE */,
+ ecircumflexhook = 0x1001ec3 /* U+1EC3 LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE */,
+ Ecircumflextilde = 0x1001ec4 /* U+1EC4 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE */,
+ ecircumflextilde = 0x1001ec5 /* U+1EC5 LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE */,
+ Ecircumflexbelowdot = 0x1001ec6 /* U+1EC6 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW */,
+ ecircumflexbelowdot = 0x1001ec7 /* U+1EC7 LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW */,
+ Ihook = 0x1001ec8 /* U+1EC8 LATIN CAPITAL LETTER I WITH HOOK ABOVE */,
+ ihook = 0x1001ec9 /* U+1EC9 LATIN SMALL LETTER I WITH HOOK ABOVE */,
+ Ibelowdot = 0x1001eca /* U+1ECA LATIN CAPITAL LETTER I WITH DOT BELOW */,
+ ibelowdot = 0x1001ecb /* U+1ECB LATIN SMALL LETTER I WITH DOT BELOW */,
+ Obelowdot = 0x1001ecc /* U+1ECC LATIN CAPITAL LETTER O WITH DOT BELOW */,
+ obelowdot = 0x1001ecd /* U+1ECD LATIN SMALL LETTER O WITH DOT BELOW */,
+ Ohook = 0x1001ece /* U+1ECE LATIN CAPITAL LETTER O WITH HOOK ABOVE */,
+ ohook = 0x1001ecf /* U+1ECF LATIN SMALL LETTER O WITH HOOK ABOVE */,
+ Ocircumflexacute = 0x1001ed0 /* U+1ED0 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE */,
+ ocircumflexacute = 0x1001ed1 /* U+1ED1 LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE */,
+ Ocircumflexgrave = 0x1001ed2 /* U+1ED2 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE */,
+ ocircumflexgrave = 0x1001ed3 /* U+1ED3 LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE */,
+ Ocircumflexhook = 0x1001ed4 /* U+1ED4 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE */,
+ ocircumflexhook = 0x1001ed5 /* U+1ED5 LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE */,
+ Ocircumflextilde = 0x1001ed6 /* U+1ED6 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE */,
+ ocircumflextilde = 0x1001ed7 /* U+1ED7 LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE */,
+ Ocircumflexbelowdot = 0x1001ed8 /* U+1ED8 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW */,
+ ocircumflexbelowdot = 0x1001ed9 /* U+1ED9 LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW */,
+ Ohornacute = 0x1001eda /* U+1EDA LATIN CAPITAL LETTER O WITH HORN AND ACUTE */,
+ ohornacute = 0x1001edb /* U+1EDB LATIN SMALL LETTER O WITH HORN AND ACUTE */,
+ Ohorngrave = 0x1001edc /* U+1EDC LATIN CAPITAL LETTER O WITH HORN AND GRAVE */,
+ ohorngrave = 0x1001edd /* U+1EDD LATIN SMALL LETTER O WITH HORN AND GRAVE */,
+ Ohornhook = 0x1001ede /* U+1EDE LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE */,
+ ohornhook = 0x1001edf /* U+1EDF LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE */,
+ Ohorntilde = 0x1001ee0 /* U+1EE0 LATIN CAPITAL LETTER O WITH HORN AND TILDE */,
+ ohorntilde = 0x1001ee1 /* U+1EE1 LATIN SMALL LETTER O WITH HORN AND TILDE */,
+ Ohornbelowdot = 0x1001ee2 /* U+1EE2 LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW */,
+ ohornbelowdot = 0x1001ee3 /* U+1EE3 LATIN SMALL LETTER O WITH HORN AND DOT BELOW */,
+ Ubelowdot = 0x1001ee4 /* U+1EE4 LATIN CAPITAL LETTER U WITH DOT BELOW */,
+ ubelowdot = 0x1001ee5 /* U+1EE5 LATIN SMALL LETTER U WITH DOT BELOW */,
+ Uhook = 0x1001ee6 /* U+1EE6 LATIN CAPITAL LETTER U WITH HOOK ABOVE */,
+ uhook = 0x1001ee7 /* U+1EE7 LATIN SMALL LETTER U WITH HOOK ABOVE */,
+ Uhornacute = 0x1001ee8 /* U+1EE8 LATIN CAPITAL LETTER U WITH HORN AND ACUTE */,
+ uhornacute = 0x1001ee9 /* U+1EE9 LATIN SMALL LETTER U WITH HORN AND ACUTE */,
+ Uhorngrave = 0x1001eea /* U+1EEA LATIN CAPITAL LETTER U WITH HORN AND GRAVE */,
+ uhorngrave = 0x1001eeb /* U+1EEB LATIN SMALL LETTER U WITH HORN AND GRAVE */,
+ Uhornhook = 0x1001eec /* U+1EEC LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE */,
+ uhornhook = 0x1001eed /* U+1EED LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE */,
+ Uhorntilde = 0x1001eee /* U+1EEE LATIN CAPITAL LETTER U WITH HORN AND TILDE */,
+ uhorntilde = 0x1001eef /* U+1EEF LATIN SMALL LETTER U WITH HORN AND TILDE */,
+ Uhornbelowdot = 0x1001ef0 /* U+1EF0 LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW */,
+ uhornbelowdot = 0x1001ef1 /* U+1EF1 LATIN SMALL LETTER U WITH HORN AND DOT BELOW */,
+ Ybelowdot = 0x1001ef4 /* U+1EF4 LATIN CAPITAL LETTER Y WITH DOT BELOW */,
+ ybelowdot = 0x1001ef5 /* U+1EF5 LATIN SMALL LETTER Y WITH DOT BELOW */,
+ Yhook = 0x1001ef6 /* U+1EF6 LATIN CAPITAL LETTER Y WITH HOOK ABOVE */,
+ yhook = 0x1001ef7 /* U+1EF7 LATIN SMALL LETTER Y WITH HOOK ABOVE */,
+ Ytilde = 0x1001ef8 /* U+1EF8 LATIN CAPITAL LETTER Y WITH TILDE */,
+ ytilde = 0x1001ef9 /* U+1EF9 LATIN SMALL LETTER Y WITH TILDE */,
+ Ohorn = 0x10001a0 /* U+01A0 LATIN CAPITAL LETTER O WITH HORN */,
+ ohorn = 0x10001a1 /* U+01A1 LATIN SMALL LETTER O WITH HORN */,
+ Uhorn = 0x10001af /* U+01AF LATIN CAPITAL LETTER U WITH HORN */,
+ uhorn = 0x10001b0 /* U+01B0 LATIN SMALL LETTER U WITH HORN */,
+ EcuSign = 0x10020a0 /* U+20A0 EURO-CURRENCY SIGN */,
+ ColonSign = 0x10020a1 /* U+20A1 COLON SIGN */,
+ CruzeiroSign = 0x10020a2 /* U+20A2 CRUZEIRO SIGN */,
+ FFrancSign = 0x10020a3 /* U+20A3 FRENCH FRANC SIGN */,
+ LiraSign = 0x10020a4 /* U+20A4 LIRA SIGN */,
+ MillSign = 0x10020a5 /* U+20A5 MILL SIGN */,
+ NairaSign = 0x10020a6 /* U+20A6 NAIRA SIGN */,
+ PesetaSign = 0x10020a7 /* U+20A7 PESETA SIGN */,
+ RupeeSign = 0x10020a8 /* U+20A8 RUPEE SIGN */,
+ WonSign = 0x10020a9 /* U+20A9 WON SIGN */,
+ NewSheqelSign = 0x10020aa /* U+20AA NEW SHEQEL SIGN */,
+ DongSign = 0x10020ab /* U+20AB DONG SIGN */,
+ EuroSign = 0x20ac /* U+20AC EURO SIGN */,
+ zerosuperior = 0x1002070 /* U+2070 SUPERSCRIPT ZERO */,
+ foursuperior = 0x1002074 /* U+2074 SUPERSCRIPT FOUR */,
+ fivesuperior = 0x1002075 /* U+2075 SUPERSCRIPT FIVE */,
+ sixsuperior = 0x1002076 /* U+2076 SUPERSCRIPT SIX */,
+ sevensuperior = 0x1002077 /* U+2077 SUPERSCRIPT SEVEN */,
+ eightsuperior = 0x1002078 /* U+2078 SUPERSCRIPT EIGHT */,
+ ninesuperior = 0x1002079 /* U+2079 SUPERSCRIPT NINE */,
+ zerosubscript = 0x1002080 /* U+2080 SUBSCRIPT ZERO */,
+ onesubscript = 0x1002081 /* U+2081 SUBSCRIPT ONE */,
+ twosubscript = 0x1002082 /* U+2082 SUBSCRIPT TWO */,
+ threesubscript = 0x1002083 /* U+2083 SUBSCRIPT THREE */,
+ foursubscript = 0x1002084 /* U+2084 SUBSCRIPT FOUR */,
+ fivesubscript = 0x1002085 /* U+2085 SUBSCRIPT FIVE */,
+ sixsubscript = 0x1002086 /* U+2086 SUBSCRIPT SIX */,
+ sevensubscript = 0x1002087 /* U+2087 SUBSCRIPT SEVEN */,
+ eightsubscript = 0x1002088 /* U+2088 SUBSCRIPT EIGHT */,
+ ninesubscript = 0x1002089 /* U+2089 SUBSCRIPT NINE */,
+ partdifferential = 0x1002202 /* U+2202 PARTIAL DIFFERENTIAL */,
+ emptyset = 0x1002205 /* U+2205 NULL SET */,
+ elementof = 0x1002208 /* U+2208 ELEMENT OF */,
+ notelementof = 0x1002209 /* U+2209 NOT AN ELEMENT OF */,
+ containsas = 0x100220B /* U+220B CONTAINS AS MEMBER */,
+ squareroot = 0x100221A /* U+221A SQUARE ROOT */,
+ cuberoot = 0x100221B /* U+221B CUBE ROOT */,
+ fourthroot = 0x100221C /* U+221C FOURTH ROOT */,
+ dintegral = 0x100222C /* U+222C DOUBLE INTEGRAL */,
+ tintegral = 0x100222D /* U+222D TRIPLE INTEGRAL */,
+ because = 0x1002235 /* U+2235 BECAUSE */,
+ approxeq = 0x1002248 /* U+2245 ALMOST EQUAL TO */,
+ notapproxeq = 0x1002247 /* U+2247 NOT ALMOST EQUAL TO */,
+ notidentical = 0x1002262 /* U+2262 NOT IDENTICAL TO */,
+ stricteq = 0x1002263 /* U+2263 STRICTLY EQUIVALENT TO */,
+ braille_dot_1 = 0xfff1,
+ braille_dot_2 = 0xfff2,
+ braille_dot_3 = 0xfff3,
+ braille_dot_4 = 0xfff4,
+ braille_dot_5 = 0xfff5,
+ braille_dot_6 = 0xfff6,
+ braille_dot_7 = 0xfff7,
+ braille_dot_8 = 0xfff8,
+ braille_dot_9 = 0xfff9,
+ braille_dot_10 = 0xfffa,
+ braille_blank = 0x1002800 /* U+2800 BRAILLE PATTERN BLANK */,
+ braille_dots_1 = 0x1002801 /* U+2801 BRAILLE PATTERN DOTS-1 */,
+ braille_dots_2 = 0x1002802 /* U+2802 BRAILLE PATTERN DOTS-2 */,
+ braille_dots_12 = 0x1002803 /* U+2803 BRAILLE PATTERN DOTS-12 */,
+ braille_dots_3 = 0x1002804 /* U+2804 BRAILLE PATTERN DOTS-3 */,
+ braille_dots_13 = 0x1002805 /* U+2805 BRAILLE PATTERN DOTS-13 */,
+ braille_dots_23 = 0x1002806 /* U+2806 BRAILLE PATTERN DOTS-23 */,
+ braille_dots_123 = 0x1002807 /* U+2807 BRAILLE PATTERN DOTS-123 */,
+ braille_dots_4 = 0x1002808 /* U+2808 BRAILLE PATTERN DOTS-4 */,
+ braille_dots_14 = 0x1002809 /* U+2809 BRAILLE PATTERN DOTS-14 */,
+ braille_dots_24 = 0x100280a /* U+280a BRAILLE PATTERN DOTS-24 */,
+ braille_dots_124 = 0x100280b /* U+280b BRAILLE PATTERN DOTS-124 */,
+ braille_dots_34 = 0x100280c /* U+280c BRAILLE PATTERN DOTS-34 */,
+ braille_dots_134 = 0x100280d /* U+280d BRAILLE PATTERN DOTS-134 */,
+ braille_dots_234 = 0x100280e /* U+280e BRAILLE PATTERN DOTS-234 */,
+ braille_dots_1234 = 0x100280f /* U+280f BRAILLE PATTERN DOTS-1234 */,
+ braille_dots_5 = 0x1002810 /* U+2810 BRAILLE PATTERN DOTS-5 */,
+ braille_dots_15 = 0x1002811 /* U+2811 BRAILLE PATTERN DOTS-15 */,
+ braille_dots_25 = 0x1002812 /* U+2812 BRAILLE PATTERN DOTS-25 */,
+ braille_dots_125 = 0x1002813 /* U+2813 BRAILLE PATTERN DOTS-125 */,
+ braille_dots_35 = 0x1002814 /* U+2814 BRAILLE PATTERN DOTS-35 */,
+ braille_dots_135 = 0x1002815 /* U+2815 BRAILLE PATTERN DOTS-135 */,
+ braille_dots_235 = 0x1002816 /* U+2816 BRAILLE PATTERN DOTS-235 */,
+ braille_dots_1235 = 0x1002817 /* U+2817 BRAILLE PATTERN DOTS-1235 */,
+ braille_dots_45 = 0x1002818 /* U+2818 BRAILLE PATTERN DOTS-45 */,
+ braille_dots_145 = 0x1002819 /* U+2819 BRAILLE PATTERN DOTS-145 */,
+ braille_dots_245 = 0x100281a /* U+281a BRAILLE PATTERN DOTS-245 */,
+ braille_dots_1245 = 0x100281b /* U+281b BRAILLE PATTERN DOTS-1245 */,
+ braille_dots_345 = 0x100281c /* U+281c BRAILLE PATTERN DOTS-345 */,
+ braille_dots_1345 = 0x100281d /* U+281d BRAILLE PATTERN DOTS-1345 */,
+ braille_dots_2345 = 0x100281e /* U+281e BRAILLE PATTERN DOTS-2345 */,
+ braille_dots_12345 = 0x100281f /* U+281f BRAILLE PATTERN DOTS-12345 */,
+ braille_dots_6 = 0x1002820 /* U+2820 BRAILLE PATTERN DOTS-6 */,
+ braille_dots_16 = 0x1002821 /* U+2821 BRAILLE PATTERN DOTS-16 */,
+ braille_dots_26 = 0x1002822 /* U+2822 BRAILLE PATTERN DOTS-26 */,
+ braille_dots_126 = 0x1002823 /* U+2823 BRAILLE PATTERN DOTS-126 */,
+ braille_dots_36 = 0x1002824 /* U+2824 BRAILLE PATTERN DOTS-36 */,
+ braille_dots_136 = 0x1002825 /* U+2825 BRAILLE PATTERN DOTS-136 */,
+ braille_dots_236 = 0x1002826 /* U+2826 BRAILLE PATTERN DOTS-236 */,
+ braille_dots_1236 = 0x1002827 /* U+2827 BRAILLE PATTERN DOTS-1236 */,
+ braille_dots_46 = 0x1002828 /* U+2828 BRAILLE PATTERN DOTS-46 */,
+ braille_dots_146 = 0x1002829 /* U+2829 BRAILLE PATTERN DOTS-146 */,
+ braille_dots_246 = 0x100282a /* U+282a BRAILLE PATTERN DOTS-246 */,
+ braille_dots_1246 = 0x100282b /* U+282b BRAILLE PATTERN DOTS-1246 */,
+ braille_dots_346 = 0x100282c /* U+282c BRAILLE PATTERN DOTS-346 */,
+ braille_dots_1346 = 0x100282d /* U+282d BRAILLE PATTERN DOTS-1346 */,
+ braille_dots_2346 = 0x100282e /* U+282e BRAILLE PATTERN DOTS-2346 */,
+ braille_dots_12346 = 0x100282f /* U+282f BRAILLE PATTERN DOTS-12346 */,
+ braille_dots_56 = 0x1002830 /* U+2830 BRAILLE PATTERN DOTS-56 */,
+ braille_dots_156 = 0x1002831 /* U+2831 BRAILLE PATTERN DOTS-156 */,
+ braille_dots_256 = 0x1002832 /* U+2832 BRAILLE PATTERN DOTS-256 */,
+ braille_dots_1256 = 0x1002833 /* U+2833 BRAILLE PATTERN DOTS-1256 */,
+ braille_dots_356 = 0x1002834 /* U+2834 BRAILLE PATTERN DOTS-356 */,
+ braille_dots_1356 = 0x1002835 /* U+2835 BRAILLE PATTERN DOTS-1356 */,
+ braille_dots_2356 = 0x1002836 /* U+2836 BRAILLE PATTERN DOTS-2356 */,
+ braille_dots_12356 = 0x1002837 /* U+2837 BRAILLE PATTERN DOTS-12356 */,
+ braille_dots_456 = 0x1002838 /* U+2838 BRAILLE PATTERN DOTS-456 */,
+ braille_dots_1456 = 0x1002839 /* U+2839 BRAILLE PATTERN DOTS-1456 */,
+ braille_dots_2456 = 0x100283a /* U+283a BRAILLE PATTERN DOTS-2456 */,
+ braille_dots_12456 = 0x100283b /* U+283b BRAILLE PATTERN DOTS-12456 */,
+ braille_dots_3456 = 0x100283c /* U+283c BRAILLE PATTERN DOTS-3456 */,
+ braille_dots_13456 = 0x100283d /* U+283d BRAILLE PATTERN DOTS-13456 */,
+ braille_dots_23456 = 0x100283e /* U+283e BRAILLE PATTERN DOTS-23456 */,
+ braille_dots_123456 = 0x100283f /* U+283f BRAILLE PATTERN DOTS-123456 */,
+ braille_dots_7 = 0x1002840 /* U+2840 BRAILLE PATTERN DOTS-7 */,
+ braille_dots_17 = 0x1002841 /* U+2841 BRAILLE PATTERN DOTS-17 */,
+ braille_dots_27 = 0x1002842 /* U+2842 BRAILLE PATTERN DOTS-27 */,
+ braille_dots_127 = 0x1002843 /* U+2843 BRAILLE PATTERN DOTS-127 */,
+ braille_dots_37 = 0x1002844 /* U+2844 BRAILLE PATTERN DOTS-37 */,
+ braille_dots_137 = 0x1002845 /* U+2845 BRAILLE PATTERN DOTS-137 */,
+ braille_dots_237 = 0x1002846 /* U+2846 BRAILLE PATTERN DOTS-237 */,
+ braille_dots_1237 = 0x1002847 /* U+2847 BRAILLE PATTERN DOTS-1237 */,
+ braille_dots_47 = 0x1002848 /* U+2848 BRAILLE PATTERN DOTS-47 */,
+ braille_dots_147 = 0x1002849 /* U+2849 BRAILLE PATTERN DOTS-147 */,
+ braille_dots_247 = 0x100284a /* U+284a BRAILLE PATTERN DOTS-247 */,
+ braille_dots_1247 = 0x100284b /* U+284b BRAILLE PATTERN DOTS-1247 */,
+ braille_dots_347 = 0x100284c /* U+284c BRAILLE PATTERN DOTS-347 */,
+ braille_dots_1347 = 0x100284d /* U+284d BRAILLE PATTERN DOTS-1347 */,
+ braille_dots_2347 = 0x100284e /* U+284e BRAILLE PATTERN DOTS-2347 */,
+ braille_dots_12347 = 0x100284f /* U+284f BRAILLE PATTERN DOTS-12347 */,
+ braille_dots_57 = 0x1002850 /* U+2850 BRAILLE PATTERN DOTS-57 */,
+ braille_dots_157 = 0x1002851 /* U+2851 BRAILLE PATTERN DOTS-157 */,
+ braille_dots_257 = 0x1002852 /* U+2852 BRAILLE PATTERN DOTS-257 */,
+ braille_dots_1257 = 0x1002853 /* U+2853 BRAILLE PATTERN DOTS-1257 */,
+ braille_dots_357 = 0x1002854 /* U+2854 BRAILLE PATTERN DOTS-357 */,
+ braille_dots_1357 = 0x1002855 /* U+2855 BRAILLE PATTERN DOTS-1357 */,
+ braille_dots_2357 = 0x1002856 /* U+2856 BRAILLE PATTERN DOTS-2357 */,
+ braille_dots_12357 = 0x1002857 /* U+2857 BRAILLE PATTERN DOTS-12357 */,
+ braille_dots_457 = 0x1002858 /* U+2858 BRAILLE PATTERN DOTS-457 */,
+ braille_dots_1457 = 0x1002859 /* U+2859 BRAILLE PATTERN DOTS-1457 */,
+ braille_dots_2457 = 0x100285a /* U+285a BRAILLE PATTERN DOTS-2457 */,
+ braille_dots_12457 = 0x100285b /* U+285b BRAILLE PATTERN DOTS-12457 */,
+ braille_dots_3457 = 0x100285c /* U+285c BRAILLE PATTERN DOTS-3457 */,
+ braille_dots_13457 = 0x100285d /* U+285d BRAILLE PATTERN DOTS-13457 */,
+ braille_dots_23457 = 0x100285e /* U+285e BRAILLE PATTERN DOTS-23457 */,
+ braille_dots_123457 = 0x100285f /* U+285f BRAILLE PATTERN DOTS-123457 */,
+ braille_dots_67 = 0x1002860 /* U+2860 BRAILLE PATTERN DOTS-67 */,
+ braille_dots_167 = 0x1002861 /* U+2861 BRAILLE PATTERN DOTS-167 */,
+ braille_dots_267 = 0x1002862 /* U+2862 BRAILLE PATTERN DOTS-267 */,
+ braille_dots_1267 = 0x1002863 /* U+2863 BRAILLE PATTERN DOTS-1267 */,
+ braille_dots_367 = 0x1002864 /* U+2864 BRAILLE PATTERN DOTS-367 */,
+ braille_dots_1367 = 0x1002865 /* U+2865 BRAILLE PATTERN DOTS-1367 */,
+ braille_dots_2367 = 0x1002866 /* U+2866 BRAILLE PATTERN DOTS-2367 */,
+ braille_dots_12367 = 0x1002867 /* U+2867 BRAILLE PATTERN DOTS-12367 */,
+ braille_dots_467 = 0x1002868 /* U+2868 BRAILLE PATTERN DOTS-467 */,
+ braille_dots_1467 = 0x1002869 /* U+2869 BRAILLE PATTERN DOTS-1467 */,
+ braille_dots_2467 = 0x100286a /* U+286a BRAILLE PATTERN DOTS-2467 */,
+ braille_dots_12467 = 0x100286b /* U+286b BRAILLE PATTERN DOTS-12467 */,
+ braille_dots_3467 = 0x100286c /* U+286c BRAILLE PATTERN DOTS-3467 */,
+ braille_dots_13467 = 0x100286d /* U+286d BRAILLE PATTERN DOTS-13467 */,
+ braille_dots_23467 = 0x100286e /* U+286e BRAILLE PATTERN DOTS-23467 */,
+ braille_dots_123467 = 0x100286f /* U+286f BRAILLE PATTERN DOTS-123467 */,
+ braille_dots_567 = 0x1002870 /* U+2870 BRAILLE PATTERN DOTS-567 */,
+ braille_dots_1567 = 0x1002871 /* U+2871 BRAILLE PATTERN DOTS-1567 */,
+ braille_dots_2567 = 0x1002872 /* U+2872 BRAILLE PATTERN DOTS-2567 */,
+ braille_dots_12567 = 0x1002873 /* U+2873 BRAILLE PATTERN DOTS-12567 */,
+ braille_dots_3567 = 0x1002874 /* U+2874 BRAILLE PATTERN DOTS-3567 */,
+ braille_dots_13567 = 0x1002875 /* U+2875 BRAILLE PATTERN DOTS-13567 */,
+ braille_dots_23567 = 0x1002876 /* U+2876 BRAILLE PATTERN DOTS-23567 */,
+ braille_dots_123567 = 0x1002877 /* U+2877 BRAILLE PATTERN DOTS-123567 */,
+ braille_dots_4567 = 0x1002878 /* U+2878 BRAILLE PATTERN DOTS-4567 */,
+ braille_dots_14567 = 0x1002879 /* U+2879 BRAILLE PATTERN DOTS-14567 */,
+ braille_dots_24567 = 0x100287a /* U+287a BRAILLE PATTERN DOTS-24567 */,
+ braille_dots_124567 = 0x100287b /* U+287b BRAILLE PATTERN DOTS-124567 */,
+ braille_dots_34567 = 0x100287c /* U+287c BRAILLE PATTERN DOTS-34567 */,
+ braille_dots_134567 = 0x100287d /* U+287d BRAILLE PATTERN DOTS-134567 */,
+ braille_dots_234567 = 0x100287e /* U+287e BRAILLE PATTERN DOTS-234567 */,
+ braille_dots_1234567 = 0x100287f /* U+287f BRAILLE PATTERN DOTS-1234567 */,
+ braille_dots_8 = 0x1002880 /* U+2880 BRAILLE PATTERN DOTS-8 */,
+ braille_dots_18 = 0x1002881 /* U+2881 BRAILLE PATTERN DOTS-18 */,
+ braille_dots_28 = 0x1002882 /* U+2882 BRAILLE PATTERN DOTS-28 */,
+ braille_dots_128 = 0x1002883 /* U+2883 BRAILLE PATTERN DOTS-128 */,
+ braille_dots_38 = 0x1002884 /* U+2884 BRAILLE PATTERN DOTS-38 */,
+ braille_dots_138 = 0x1002885 /* U+2885 BRAILLE PATTERN DOTS-138 */,
+ braille_dots_238 = 0x1002886 /* U+2886 BRAILLE PATTERN DOTS-238 */,
+ braille_dots_1238 = 0x1002887 /* U+2887 BRAILLE PATTERN DOTS-1238 */,
+ braille_dots_48 = 0x1002888 /* U+2888 BRAILLE PATTERN DOTS-48 */,
+ braille_dots_148 = 0x1002889 /* U+2889 BRAILLE PATTERN DOTS-148 */,
+ braille_dots_248 = 0x100288a /* U+288a BRAILLE PATTERN DOTS-248 */,
+ braille_dots_1248 = 0x100288b /* U+288b BRAILLE PATTERN DOTS-1248 */,
+ braille_dots_348 = 0x100288c /* U+288c BRAILLE PATTERN DOTS-348 */,
+ braille_dots_1348 = 0x100288d /* U+288d BRAILLE PATTERN DOTS-1348 */,
+ braille_dots_2348 = 0x100288e /* U+288e BRAILLE PATTERN DOTS-2348 */,
+ braille_dots_12348 = 0x100288f /* U+288f BRAILLE PATTERN DOTS-12348 */,
+ braille_dots_58 = 0x1002890 /* U+2890 BRAILLE PATTERN DOTS-58 */,
+ braille_dots_158 = 0x1002891 /* U+2891 BRAILLE PATTERN DOTS-158 */,
+ braille_dots_258 = 0x1002892 /* U+2892 BRAILLE PATTERN DOTS-258 */,
+ braille_dots_1258 = 0x1002893 /* U+2893 BRAILLE PATTERN DOTS-1258 */,
+ braille_dots_358 = 0x1002894 /* U+2894 BRAILLE PATTERN DOTS-358 */,
+ braille_dots_1358 = 0x1002895 /* U+2895 BRAILLE PATTERN DOTS-1358 */,
+ braille_dots_2358 = 0x1002896 /* U+2896 BRAILLE PATTERN DOTS-2358 */,
+ braille_dots_12358 = 0x1002897 /* U+2897 BRAILLE PATTERN DOTS-12358 */,
+ braille_dots_458 = 0x1002898 /* U+2898 BRAILLE PATTERN DOTS-458 */,
+ braille_dots_1458 = 0x1002899 /* U+2899 BRAILLE PATTERN DOTS-1458 */,
+ braille_dots_2458 = 0x100289a /* U+289a BRAILLE PATTERN DOTS-2458 */,
+ braille_dots_12458 = 0x100289b /* U+289b BRAILLE PATTERN DOTS-12458 */,
+ braille_dots_3458 = 0x100289c /* U+289c BRAILLE PATTERN DOTS-3458 */,
+ braille_dots_13458 = 0x100289d /* U+289d BRAILLE PATTERN DOTS-13458 */,
+ braille_dots_23458 = 0x100289e /* U+289e BRAILLE PATTERN DOTS-23458 */,
+ braille_dots_123458 = 0x100289f /* U+289f BRAILLE PATTERN DOTS-123458 */,
+ braille_dots_68 = 0x10028a0 /* U+28a0 BRAILLE PATTERN DOTS-68 */,
+ braille_dots_168 = 0x10028a1 /* U+28a1 BRAILLE PATTERN DOTS-168 */,
+ braille_dots_268 = 0x10028a2 /* U+28a2 BRAILLE PATTERN DOTS-268 */,
+ braille_dots_1268 = 0x10028a3 /* U+28a3 BRAILLE PATTERN DOTS-1268 */,
+ braille_dots_368 = 0x10028a4 /* U+28a4 BRAILLE PATTERN DOTS-368 */,
+ braille_dots_1368 = 0x10028a5 /* U+28a5 BRAILLE PATTERN DOTS-1368 */,
+ braille_dots_2368 = 0x10028a6 /* U+28a6 BRAILLE PATTERN DOTS-2368 */,
+ braille_dots_12368 = 0x10028a7 /* U+28a7 BRAILLE PATTERN DOTS-12368 */,
+ braille_dots_468 = 0x10028a8 /* U+28a8 BRAILLE PATTERN DOTS-468 */,
+ braille_dots_1468 = 0x10028a9 /* U+28a9 BRAILLE PATTERN DOTS-1468 */,
+ braille_dots_2468 = 0x10028aa /* U+28aa BRAILLE PATTERN DOTS-2468 */,
+ braille_dots_12468 = 0x10028ab /* U+28ab BRAILLE PATTERN DOTS-12468 */,
+ braille_dots_3468 = 0x10028ac /* U+28ac BRAILLE PATTERN DOTS-3468 */,
+ braille_dots_13468 = 0x10028ad /* U+28ad BRAILLE PATTERN DOTS-13468 */,
+ braille_dots_23468 = 0x10028ae /* U+28ae BRAILLE PATTERN DOTS-23468 */,
+ braille_dots_123468 = 0x10028af /* U+28af BRAILLE PATTERN DOTS-123468 */,
+ braille_dots_568 = 0x10028b0 /* U+28b0 BRAILLE PATTERN DOTS-568 */,
+ braille_dots_1568 = 0x10028b1 /* U+28b1 BRAILLE PATTERN DOTS-1568 */,
+ braille_dots_2568 = 0x10028b2 /* U+28b2 BRAILLE PATTERN DOTS-2568 */,
+ braille_dots_12568 = 0x10028b3 /* U+28b3 BRAILLE PATTERN DOTS-12568 */,
+ braille_dots_3568 = 0x10028b4 /* U+28b4 BRAILLE PATTERN DOTS-3568 */,
+ braille_dots_13568 = 0x10028b5 /* U+28b5 BRAILLE PATTERN DOTS-13568 */,
+ braille_dots_23568 = 0x10028b6 /* U+28b6 BRAILLE PATTERN DOTS-23568 */,
+ braille_dots_123568 = 0x10028b7 /* U+28b7 BRAILLE PATTERN DOTS-123568 */,
+ braille_dots_4568 = 0x10028b8 /* U+28b8 BRAILLE PATTERN DOTS-4568 */,
+ braille_dots_14568 = 0x10028b9 /* U+28b9 BRAILLE PATTERN DOTS-14568 */,
+ braille_dots_24568 = 0x10028ba /* U+28ba BRAILLE PATTERN DOTS-24568 */,
+ braille_dots_124568 = 0x10028bb /* U+28bb BRAILLE PATTERN DOTS-124568 */,
+ braille_dots_34568 = 0x10028bc /* U+28bc BRAILLE PATTERN DOTS-34568 */,
+ braille_dots_134568 = 0x10028bd /* U+28bd BRAILLE PATTERN DOTS-134568 */,
+ braille_dots_234568 = 0x10028be /* U+28be BRAILLE PATTERN DOTS-234568 */,
+ braille_dots_1234568 = 0x10028bf /* U+28bf BRAILLE PATTERN DOTS-1234568 */,
+ braille_dots_78 = 0x10028c0 /* U+28c0 BRAILLE PATTERN DOTS-78 */,
+ braille_dots_178 = 0x10028c1 /* U+28c1 BRAILLE PATTERN DOTS-178 */,
+ braille_dots_278 = 0x10028c2 /* U+28c2 BRAILLE PATTERN DOTS-278 */,
+ braille_dots_1278 = 0x10028c3 /* U+28c3 BRAILLE PATTERN DOTS-1278 */,
+ braille_dots_378 = 0x10028c4 /* U+28c4 BRAILLE PATTERN DOTS-378 */,
+ braille_dots_1378 = 0x10028c5 /* U+28c5 BRAILLE PATTERN DOTS-1378 */,
+ braille_dots_2378 = 0x10028c6 /* U+28c6 BRAILLE PATTERN DOTS-2378 */,
+ braille_dots_12378 = 0x10028c7 /* U+28c7 BRAILLE PATTERN DOTS-12378 */,
+ braille_dots_478 = 0x10028c8 /* U+28c8 BRAILLE PATTERN DOTS-478 */,
+ braille_dots_1478 = 0x10028c9 /* U+28c9 BRAILLE PATTERN DOTS-1478 */,
+ braille_dots_2478 = 0x10028ca /* U+28ca BRAILLE PATTERN DOTS-2478 */,
+ braille_dots_12478 = 0x10028cb /* U+28cb BRAILLE PATTERN DOTS-12478 */,
+ braille_dots_3478 = 0x10028cc /* U+28cc BRAILLE PATTERN DOTS-3478 */,
+ braille_dots_13478 = 0x10028cd /* U+28cd BRAILLE PATTERN DOTS-13478 */,
+ braille_dots_23478 = 0x10028ce /* U+28ce BRAILLE PATTERN DOTS-23478 */,
+ braille_dots_123478 = 0x10028cf /* U+28cf BRAILLE PATTERN DOTS-123478 */,
+ braille_dots_578 = 0x10028d0 /* U+28d0 BRAILLE PATTERN DOTS-578 */,
+ braille_dots_1578 = 0x10028d1 /* U+28d1 BRAILLE PATTERN DOTS-1578 */,
+ braille_dots_2578 = 0x10028d2 /* U+28d2 BRAILLE PATTERN DOTS-2578 */,
+ braille_dots_12578 = 0x10028d3 /* U+28d3 BRAILLE PATTERN DOTS-12578 */,
+ braille_dots_3578 = 0x10028d4 /* U+28d4 BRAILLE PATTERN DOTS-3578 */,
+ braille_dots_13578 = 0x10028d5 /* U+28d5 BRAILLE PATTERN DOTS-13578 */,
+ braille_dots_23578 = 0x10028d6 /* U+28d6 BRAILLE PATTERN DOTS-23578 */,
+ braille_dots_123578 = 0x10028d7 /* U+28d7 BRAILLE PATTERN DOTS-123578 */,
+ braille_dots_4578 = 0x10028d8 /* U+28d8 BRAILLE PATTERN DOTS-4578 */,
+ braille_dots_14578 = 0x10028d9 /* U+28d9 BRAILLE PATTERN DOTS-14578 */,
+ braille_dots_24578 = 0x10028da /* U+28da BRAILLE PATTERN DOTS-24578 */,
+ braille_dots_124578 = 0x10028db /* U+28db BRAILLE PATTERN DOTS-124578 */,
+ braille_dots_34578 = 0x10028dc /* U+28dc BRAILLE PATTERN DOTS-34578 */,
+ braille_dots_134578 = 0x10028dd /* U+28dd BRAILLE PATTERN DOTS-134578 */,
+ braille_dots_234578 = 0x10028de /* U+28de BRAILLE PATTERN DOTS-234578 */,
+ braille_dots_1234578 = 0x10028df /* U+28df BRAILLE PATTERN DOTS-1234578 */,
+ braille_dots_678 = 0x10028e0 /* U+28e0 BRAILLE PATTERN DOTS-678 */,
+ braille_dots_1678 = 0x10028e1 /* U+28e1 BRAILLE PATTERN DOTS-1678 */,
+ braille_dots_2678 = 0x10028e2 /* U+28e2 BRAILLE PATTERN DOTS-2678 */,
+ braille_dots_12678 = 0x10028e3 /* U+28e3 BRAILLE PATTERN DOTS-12678 */,
+ braille_dots_3678 = 0x10028e4 /* U+28e4 BRAILLE PATTERN DOTS-3678 */,
+ braille_dots_13678 = 0x10028e5 /* U+28e5 BRAILLE PATTERN DOTS-13678 */,
+ braille_dots_23678 = 0x10028e6 /* U+28e6 BRAILLE PATTERN DOTS-23678 */,
+ braille_dots_123678 = 0x10028e7 /* U+28e7 BRAILLE PATTERN DOTS-123678 */,
+ braille_dots_4678 = 0x10028e8 /* U+28e8 BRAILLE PATTERN DOTS-4678 */,
+ braille_dots_14678 = 0x10028e9 /* U+28e9 BRAILLE PATTERN DOTS-14678 */,
+ braille_dots_24678 = 0x10028ea /* U+28ea BRAILLE PATTERN DOTS-24678 */,
+ braille_dots_124678 = 0x10028eb /* U+28eb BRAILLE PATTERN DOTS-124678 */,
+ braille_dots_34678 = 0x10028ec /* U+28ec BRAILLE PATTERN DOTS-34678 */,
+ braille_dots_134678 = 0x10028ed /* U+28ed BRAILLE PATTERN DOTS-134678 */,
+ braille_dots_234678 = 0x10028ee /* U+28ee BRAILLE PATTERN DOTS-234678 */,
+ braille_dots_1234678 = 0x10028ef /* U+28ef BRAILLE PATTERN DOTS-1234678 */,
+ braille_dots_5678 = 0x10028f0 /* U+28f0 BRAILLE PATTERN DOTS-5678 */,
+ braille_dots_15678 = 0x10028f1 /* U+28f1 BRAILLE PATTERN DOTS-15678 */,
+ braille_dots_25678 = 0x10028f2 /* U+28f2 BRAILLE PATTERN DOTS-25678 */,
+ braille_dots_125678 = 0x10028f3 /* U+28f3 BRAILLE PATTERN DOTS-125678 */,
+ braille_dots_35678 = 0x10028f4 /* U+28f4 BRAILLE PATTERN DOTS-35678 */,
+ braille_dots_135678 = 0x10028f5 /* U+28f5 BRAILLE PATTERN DOTS-135678 */,
+ braille_dots_235678 = 0x10028f6 /* U+28f6 BRAILLE PATTERN DOTS-235678 */,
+ braille_dots_1235678 = 0x10028f7 /* U+28f7 BRAILLE PATTERN DOTS-1235678 */,
+ braille_dots_45678 = 0x10028f8 /* U+28f8 BRAILLE PATTERN DOTS-45678 */,
+ braille_dots_145678 = 0x10028f9 /* U+28f9 BRAILLE PATTERN DOTS-145678 */,
+ braille_dots_245678 = 0x10028fa /* U+28fa BRAILLE PATTERN DOTS-245678 */,
+ braille_dots_1245678 = 0x10028fb /* U+28fb BRAILLE PATTERN DOTS-1245678 */,
+ braille_dots_345678 = 0x10028fc /* U+28fc BRAILLE PATTERN DOTS-345678 */,
+ braille_dots_1345678 = 0x10028fd /* U+28fd BRAILLE PATTERN DOTS-1345678 */,
+ braille_dots_2345678 = 0x10028fe /* U+28fe BRAILLE PATTERN DOTS-2345678 */,
+ braille_dots_12345678 = 0x10028ff /* U+28ff BRAILLE PATTERN DOTS-12345678 */,
+ Sinh_ng = 0x1000d82 /* U+0D82 SINHALA ANUSVARAYA */,
+ Sinh_h2 = 0x1000d83 /* U+0D83 SINHALA VISARGAYA */,
+ Sinh_a = 0x1000d85 /* U+0D85 SINHALA AYANNA */,
+ Sinh_aa = 0x1000d86 /* U+0D86 SINHALA AAYANNA */,
+ Sinh_ae = 0x1000d87 /* U+0D87 SINHALA AEYANNA */,
+ Sinh_aee = 0x1000d88 /* U+0D88 SINHALA AEEYANNA */,
+ Sinh_i = 0x1000d89 /* U+0D89 SINHALA IYANNA */,
+ Sinh_ii = 0x1000d8a /* U+0D8A SINHALA IIYANNA */,
+ Sinh_u = 0x1000d8b /* U+0D8B SINHALA UYANNA */,
+ Sinh_uu = 0x1000d8c /* U+0D8C SINHALA UUYANNA */,
+ Sinh_ri = 0x1000d8d /* U+0D8D SINHALA IRUYANNA */,
+ Sinh_rii = 0x1000d8e /* U+0D8E SINHALA IRUUYANNA */,
+ Sinh_lu = 0x1000d8f /* U+0D8F SINHALA ILUYANNA */,
+ Sinh_luu = 0x1000d90 /* U+0D90 SINHALA ILUUYANNA */,
+ Sinh_e = 0x1000d91 /* U+0D91 SINHALA EYANNA */,
+ Sinh_ee = 0x1000d92 /* U+0D92 SINHALA EEYANNA */,
+ Sinh_ai = 0x1000d93 /* U+0D93 SINHALA AIYANNA */,
+ Sinh_o = 0x1000d94 /* U+0D94 SINHALA OYANNA */,
+ Sinh_oo = 0x1000d95 /* U+0D95 SINHALA OOYANNA */,
+ Sinh_au = 0x1000d96 /* U+0D96 SINHALA AUYANNA */,
+ Sinh_ka = 0x1000d9a /* U+0D9A SINHALA KAYANNA */,
+ Sinh_kha = 0x1000d9b /* U+0D9B SINHALA MAHA. KAYANNA */,
+ Sinh_ga = 0x1000d9c /* U+0D9C SINHALA GAYANNA */,
+ Sinh_gha = 0x1000d9d /* U+0D9D SINHALA MAHA. GAYANNA */,
+ Sinh_ng2 = 0x1000d9e /* U+0D9E SINHALA KANTAJA NAASIKYAYA */,
+ Sinh_nga = 0x1000d9f /* U+0D9F SINHALA SANYAKA GAYANNA */,
+ Sinh_ca = 0x1000da0 /* U+0DA0 SINHALA CAYANNA */,
+ Sinh_cha = 0x1000da1 /* U+0DA1 SINHALA MAHA. CAYANNA */,
+ Sinh_ja = 0x1000da2 /* U+0DA2 SINHALA JAYANNA */,
+ Sinh_jha = 0x1000da3 /* U+0DA3 SINHALA MAHA. JAYANNA */,
+ Sinh_nya = 0x1000da4 /* U+0DA4 SINHALA TAALUJA NAASIKYAYA */,
+ Sinh_jnya = 0x1000da5 /* U+0DA5 SINHALA TAALUJA SANYOOGA NAASIKYAYA */,
+ Sinh_nja = 0x1000da6 /* U+0DA6 SINHALA SANYAKA JAYANNA */,
+ Sinh_tta = 0x1000da7 /* U+0DA7 SINHALA TTAYANNA */,
+ Sinh_ttha = 0x1000da8 /* U+0DA8 SINHALA MAHA. TTAYANNA */,
+ Sinh_dda = 0x1000da9 /* U+0DA9 SINHALA DDAYANNA */,
+ Sinh_ddha = 0x1000daa /* U+0DAA SINHALA MAHA. DDAYANNA */,
+ Sinh_nna = 0x1000dab /* U+0DAB SINHALA MUURDHAJA NAYANNA */,
+ Sinh_ndda = 0x1000dac /* U+0DAC SINHALA SANYAKA DDAYANNA */,
+ Sinh_tha = 0x1000dad /* U+0DAD SINHALA TAYANNA */,
+ Sinh_thha = 0x1000dae /* U+0DAE SINHALA MAHA. TAYANNA */,
+ Sinh_dha = 0x1000daf /* U+0DAF SINHALA DAYANNA */,
+ Sinh_dhha = 0x1000db0 /* U+0DB0 SINHALA MAHA. DAYANNA */,
+ Sinh_na = 0x1000db1 /* U+0DB1 SINHALA DANTAJA NAYANNA */,
+ Sinh_ndha = 0x1000db3 /* U+0DB3 SINHALA SANYAKA DAYANNA */,
+ Sinh_pa = 0x1000db4 /* U+0DB4 SINHALA PAYANNA */,
+ Sinh_pha = 0x1000db5 /* U+0DB5 SINHALA MAHA. PAYANNA */,
+ Sinh_ba = 0x1000db6 /* U+0DB6 SINHALA BAYANNA */,
+ Sinh_bha = 0x1000db7 /* U+0DB7 SINHALA MAHA. BAYANNA */,
+ Sinh_ma = 0x1000db8 /* U+0DB8 SINHALA MAYANNA */,
+ Sinh_mba = 0x1000db9 /* U+0DB9 SINHALA AMBA BAYANNA */,
+ Sinh_ya = 0x1000dba /* U+0DBA SINHALA YAYANNA */,
+ Sinh_ra = 0x1000dbb /* U+0DBB SINHALA RAYANNA */,
+ Sinh_la = 0x1000dbd /* U+0DBD SINHALA DANTAJA LAYANNA */,
+ Sinh_va = 0x1000dc0 /* U+0DC0 SINHALA VAYANNA */,
+ Sinh_sha = 0x1000dc1 /* U+0DC1 SINHALA TAALUJA SAYANNA */,
+ Sinh_ssha = 0x1000dc2 /* U+0DC2 SINHALA MUURDHAJA SAYANNA */,
+ Sinh_sa = 0x1000dc3 /* U+0DC3 SINHALA DANTAJA SAYANNA */,
+ Sinh_ha = 0x1000dc4 /* U+0DC4 SINHALA HAYANNA */,
+ Sinh_lla = 0x1000dc5 /* U+0DC5 SINHALA MUURDHAJA LAYANNA */,
+ Sinh_fa = 0x1000dc6 /* U+0DC6 SINHALA FAYANNA */,
+ Sinh_al = 0x1000dca /* U+0DCA SINHALA AL-LAKUNA */,
+ Sinh_aa2 = 0x1000dcf /* U+0DCF SINHALA AELA-PILLA */,
+ Sinh_ae2 = 0x1000dd0 /* U+0DD0 SINHALA AEDA-PILLA */,
+ Sinh_aee2 = 0x1000dd1 /* U+0DD1 SINHALA DIGA AEDA-PILLA */,
+ Sinh_i2 = 0x1000dd2 /* U+0DD2 SINHALA IS-PILLA */,
+ Sinh_ii2 = 0x1000dd3 /* U+0DD3 SINHALA DIGA IS-PILLA */,
+ Sinh_u2 = 0x1000dd4 /* U+0DD4 SINHALA PAA-PILLA */,
+ Sinh_uu2 = 0x1000dd6 /* U+0DD6 SINHALA DIGA PAA-PILLA */,
+ Sinh_ru2 = 0x1000dd8 /* U+0DD8 SINHALA GAETTA-PILLA */,
+ Sinh_e2 = 0x1000dd9 /* U+0DD9 SINHALA KOMBUVA */,
+ Sinh_ee2 = 0x1000dda /* U+0DDA SINHALA DIGA KOMBUVA */,
+ Sinh_ai2 = 0x1000ddb /* U+0DDB SINHALA KOMBU DEKA */,
+ Sinh_o2 = 0x1000ddc /* U+0DDC SINHALA KOMBUVA HAA AELA-PILLA*/,
+ Sinh_oo2 = 0x1000ddd /* U+0DDD SINHALA KOMBUVA HAA DIGA AELA-PILLA*/,
+ Sinh_au2 = 0x1000dde /* U+0DDE SINHALA KOMBUVA HAA GAYANUKITTA */,
+ Sinh_lu2 = 0x1000ddf /* U+0DDF SINHALA GAYANUKITTA */,
+ Sinh_ruu2 = 0x1000df2 /* U+0DF2 SINHALA DIGA GAETTA-PILLA */,
+ Sinh_luu2 = 0x1000df3 /* U+0DF3 SINHALA DIGA GAYANUKITTA */,
+ Sinh_kunddaliya = 0x1000df4 /* U+0DF4 SINHALA KUNDDALIYA */
+ }
+}
diff --git a/src/Avalonia.X11/Stubs.cs b/src/Avalonia.X11/Stubs.cs
new file mode 100644
index 0000000000..ec694ba9a8
--- /dev/null
+++ b/src/Avalonia.X11/Stubs.cs
@@ -0,0 +1,17 @@
+using System;
+using System.IO;
+using System.Threading.Tasks;
+using Avalonia.Controls;
+using Avalonia.Controls.Platform;
+using Avalonia.Input;
+using Avalonia.Input.Platform;
+using Avalonia.Platform;
+
+namespace Avalonia.X11
+{
+ class PlatformSettingsStub : IPlatformSettings
+ {
+ public Size DoubleClickSize { get; } = new Size(2, 2);
+ public TimeSpan DoubleClickTime { get; } = TimeSpan.FromMilliseconds(500);
+ }
+}
diff --git a/src/Avalonia.X11/X11Atoms.cs b/src/Avalonia.X11/X11Atoms.cs
new file mode 100644
index 0000000000..db74a32b99
--- /dev/null
+++ b/src/Avalonia.X11/X11Atoms.cs
@@ -0,0 +1,207 @@
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// Copyright (c) 2006 Novell, Inc. (http://www.novell.com)
+//
+//
+
+using System;
+using System.Linq;
+using static Avalonia.X11.XLib;
+// ReSharper disable FieldCanBeMadeReadOnly.Global
+// ReSharper disable IdentifierTypo
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable CommentTypo
+// ReSharper disable ArrangeThisQualifier
+// ReSharper disable NotAccessedField.Global
+// ReSharper disable InconsistentNaming
+// ReSharper disable StringLiteralTypo
+#pragma warning disable 649
+
+namespace Avalonia.X11
+{
+
+ internal class X11Atoms
+ {
+
+// Our atoms
+ public readonly IntPtr AnyPropertyType = (IntPtr)0;
+ public readonly IntPtr XA_PRIMARY = (IntPtr)1;
+ public readonly IntPtr XA_SECONDARY = (IntPtr)2;
+ public readonly IntPtr XA_ARC = (IntPtr)3;
+ public readonly IntPtr XA_ATOM = (IntPtr)4;
+ public readonly IntPtr XA_BITMAP = (IntPtr)5;
+ public readonly IntPtr XA_CARDINAL = (IntPtr)6;
+ public readonly IntPtr XA_COLORMAP = (IntPtr)7;
+ public readonly IntPtr XA_CURSOR = (IntPtr)8;
+ public readonly IntPtr XA_CUT_BUFFER0 = (IntPtr)9;
+ public readonly IntPtr XA_CUT_BUFFER1 = (IntPtr)10;
+ public readonly IntPtr XA_CUT_BUFFER2 = (IntPtr)11;
+ public readonly IntPtr XA_CUT_BUFFER3 = (IntPtr)12;
+ public readonly IntPtr XA_CUT_BUFFER4 = (IntPtr)13;
+ public readonly IntPtr XA_CUT_BUFFER5 = (IntPtr)14;
+ public readonly IntPtr XA_CUT_BUFFER6 = (IntPtr)15;
+ public readonly IntPtr XA_CUT_BUFFER7 = (IntPtr)16;
+ public readonly IntPtr XA_DRAWABLE = (IntPtr)17;
+ public readonly IntPtr XA_FONT = (IntPtr)18;
+ public readonly IntPtr XA_INTEGER = (IntPtr)19;
+ public readonly IntPtr XA_PIXMAP = (IntPtr)20;
+ public readonly IntPtr XA_POINT = (IntPtr)21;
+ public readonly IntPtr XA_RECTANGLE = (IntPtr)22;
+ public readonly IntPtr XA_RESOURCE_MANAGER = (IntPtr)23;
+ public readonly IntPtr XA_RGB_COLOR_MAP = (IntPtr)24;
+ public readonly IntPtr XA_RGB_BEST_MAP = (IntPtr)25;
+ public readonly IntPtr XA_RGB_BLUE_MAP = (IntPtr)26;
+ public readonly IntPtr XA_RGB_DEFAULT_MAP = (IntPtr)27;
+ public readonly IntPtr XA_RGB_GRAY_MAP = (IntPtr)28;
+ public readonly IntPtr XA_RGB_GREEN_MAP = (IntPtr)29;
+ public readonly IntPtr XA_RGB_RED_MAP = (IntPtr)30;
+ public readonly IntPtr XA_STRING = (IntPtr)31;
+ public readonly IntPtr XA_VISUALID = (IntPtr)32;
+ public readonly IntPtr XA_WINDOW = (IntPtr)33;
+ public readonly IntPtr XA_WM_COMMAND = (IntPtr)34;
+ public readonly IntPtr XA_WM_HINTS = (IntPtr)35;
+ public readonly IntPtr XA_WM_CLIENT_MACHINE = (IntPtr)36;
+ public readonly IntPtr XA_WM_ICON_NAME = (IntPtr)37;
+ public readonly IntPtr XA_WM_ICON_SIZE = (IntPtr)38;
+ public readonly IntPtr XA_WM_NAME = (IntPtr)39;
+ public readonly IntPtr XA_WM_NORMAL_HINTS = (IntPtr)40;
+ public readonly IntPtr XA_WM_SIZE_HINTS = (IntPtr)41;
+ public readonly IntPtr XA_WM_ZOOM_HINTS = (IntPtr)42;
+ public readonly IntPtr XA_MIN_SPACE = (IntPtr)43;
+ public readonly IntPtr XA_NORM_SPACE = (IntPtr)44;
+ public readonly IntPtr XA_MAX_SPACE = (IntPtr)45;
+ public readonly IntPtr XA_END_SPACE = (IntPtr)46;
+ public readonly IntPtr XA_SUPERSCRIPT_X = (IntPtr)47;
+ public readonly IntPtr XA_SUPERSCRIPT_Y = (IntPtr)48;
+ public readonly IntPtr XA_SUBSCRIPT_X = (IntPtr)49;
+ public readonly IntPtr XA_SUBSCRIPT_Y = (IntPtr)50;
+ public readonly IntPtr XA_UNDERLINE_POSITION = (IntPtr)51;
+ public readonly IntPtr XA_UNDERLINE_THICKNESS = (IntPtr)52;
+ public readonly IntPtr XA_STRIKEOUT_ASCENT = (IntPtr)53;
+ public readonly IntPtr XA_STRIKEOUT_DESCENT = (IntPtr)54;
+ public readonly IntPtr XA_ITALIC_ANGLE = (IntPtr)55;
+ public readonly IntPtr XA_X_HEIGHT = (IntPtr)56;
+ public readonly IntPtr XA_QUAD_WIDTH = (IntPtr)57;
+ public readonly IntPtr XA_WEIGHT = (IntPtr)58;
+ public readonly IntPtr XA_POINT_SIZE = (IntPtr)59;
+ public readonly IntPtr XA_RESOLUTION = (IntPtr)60;
+ public readonly IntPtr XA_COPYRIGHT = (IntPtr)61;
+ public readonly IntPtr XA_NOTICE = (IntPtr)62;
+ public readonly IntPtr XA_FONT_NAME = (IntPtr)63;
+ public readonly IntPtr XA_FAMILY_NAME = (IntPtr)64;
+ public readonly IntPtr XA_FULL_NAME = (IntPtr)65;
+ public readonly IntPtr XA_CAP_HEIGHT = (IntPtr)66;
+ public readonly IntPtr XA_WM_CLASS = (IntPtr)67;
+ public readonly IntPtr XA_WM_TRANSIENT_FOR = (IntPtr)68;
+
+ public readonly IntPtr WM_PROTOCOLS;
+ public readonly IntPtr WM_DELETE_WINDOW;
+ public readonly IntPtr WM_TAKE_FOCUS;
+ public readonly IntPtr _NET_SUPPORTED;
+ public readonly IntPtr _NET_CLIENT_LIST;
+ public readonly IntPtr _NET_NUMBER_OF_DESKTOPS;
+ public readonly IntPtr _NET_DESKTOP_GEOMETRY;
+ public readonly IntPtr _NET_DESKTOP_VIEWPORT;
+ public readonly IntPtr _NET_CURRENT_DESKTOP;
+ public readonly IntPtr _NET_DESKTOP_NAMES;
+ public readonly IntPtr _NET_ACTIVE_WINDOW;
+ public readonly IntPtr _NET_WORKAREA;
+ public readonly IntPtr _NET_SUPPORTING_WM_CHECK;
+ public readonly IntPtr _NET_VIRTUAL_ROOTS;
+ public readonly IntPtr _NET_DESKTOP_LAYOUT;
+ public readonly IntPtr _NET_SHOWING_DESKTOP;
+ public readonly IntPtr _NET_CLOSE_WINDOW;
+ public readonly IntPtr _NET_MOVERESIZE_WINDOW;
+ public readonly IntPtr _NET_WM_MOVERESIZE;
+ public readonly IntPtr _NET_RESTACK_WINDOW;
+ public readonly IntPtr _NET_REQUEST_FRAME_EXTENTS;
+ public readonly IntPtr _NET_WM_NAME;
+ public readonly IntPtr _NET_WM_VISIBLE_NAME;
+ public readonly IntPtr _NET_WM_ICON_NAME;
+ public readonly IntPtr _NET_WM_VISIBLE_ICON_NAME;
+ public readonly IntPtr _NET_WM_DESKTOP;
+ public readonly IntPtr _NET_WM_WINDOW_TYPE;
+ public readonly IntPtr _NET_WM_STATE;
+ public readonly IntPtr _NET_WM_ALLOWED_ACTIONS;
+ public readonly IntPtr _NET_WM_STRUT;
+ public readonly IntPtr _NET_WM_STRUT_PARTIAL;
+ public readonly IntPtr _NET_WM_ICON_GEOMETRY;
+ public readonly IntPtr _NET_WM_ICON;
+ public readonly IntPtr _NET_WM_PID;
+ public readonly IntPtr _NET_WM_HANDLED_ICONS;
+ public readonly IntPtr _NET_WM_USER_TIME;
+ public readonly IntPtr _NET_FRAME_EXTENTS;
+ public readonly IntPtr _NET_WM_PING;
+ public readonly IntPtr _NET_WM_SYNC_REQUEST;
+ public readonly IntPtr _NET_SYSTEM_TRAY_S;
+ public readonly IntPtr _NET_SYSTEM_TRAY_ORIENTATION;
+ public readonly IntPtr _NET_SYSTEM_TRAY_OPCODE;
+ public readonly IntPtr _NET_WM_STATE_MAXIMIZED_HORZ;
+ public readonly IntPtr _NET_WM_STATE_MAXIMIZED_VERT;
+ public readonly IntPtr _XEMBED;
+ public readonly IntPtr _XEMBED_INFO;
+ public readonly IntPtr _MOTIF_WM_HINTS;
+ public readonly IntPtr _NET_WM_STATE_SKIP_TASKBAR;
+ public readonly IntPtr _NET_WM_STATE_ABOVE;
+ public readonly IntPtr _NET_WM_STATE_MODAL;
+ public readonly IntPtr _NET_WM_STATE_HIDDEN;
+ public readonly IntPtr _NET_WM_CONTEXT_HELP;
+ public readonly IntPtr _NET_WM_WINDOW_OPACITY;
+ public readonly IntPtr _NET_WM_WINDOW_TYPE_DESKTOP;
+ public readonly IntPtr _NET_WM_WINDOW_TYPE_DOCK;
+ public readonly IntPtr _NET_WM_WINDOW_TYPE_TOOLBAR;
+ public readonly IntPtr _NET_WM_WINDOW_TYPE_MENU;
+ public readonly IntPtr _NET_WM_WINDOW_TYPE_UTILITY;
+ public readonly IntPtr _NET_WM_WINDOW_TYPE_SPLASH;
+ public readonly IntPtr _NET_WM_WINDOW_TYPE_DIALOG;
+ public readonly IntPtr _NET_WM_WINDOW_TYPE_NORMAL;
+ public readonly IntPtr CLIPBOARD;
+ public readonly IntPtr CLIPBOARD_MANAGER;
+ public readonly IntPtr SAVE_TARGETS;
+ public readonly IntPtr MULTIPLE;
+ public readonly IntPtr PRIMARY;
+ public readonly IntPtr OEMTEXT;
+ public readonly IntPtr UNICODETEXT;
+ public readonly IntPtr TARGETS;
+ public readonly IntPtr UTF8_STRING;
+ public readonly IntPtr UTF16_STRING;
+ public readonly IntPtr ATOM_PAIR;
+
+
+ public X11Atoms(IntPtr display)
+ {
+
+ // make sure this array stays in sync with the statements below
+
+ var fields = typeof(X11Atoms).GetFields()
+ .Where(f => f.FieldType == typeof(IntPtr) && (IntPtr)f.GetValue(this) == IntPtr.Zero).ToArray();
+ var atomNames = fields.Select(f => f.Name).ToArray();
+
+ IntPtr[] atoms = new IntPtr [atomNames.Length];
+ ;
+
+ XInternAtoms(display, atomNames, atomNames.Length, true, atoms);
+
+ for (var c = 0; c < fields.Length; c++)
+ fields[c].SetValue(this, atoms[c]);
+ }
+ }
+}
diff --git a/src/Avalonia.X11/X11Clipboard.cs b/src/Avalonia.X11/X11Clipboard.cs
new file mode 100644
index 0000000000..cb9d3389e4
--- /dev/null
+++ b/src/Avalonia.X11/X11Clipboard.cs
@@ -0,0 +1,234 @@
+using System;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+using Avalonia.Input.Platform;
+using static Avalonia.X11.XLib;
+namespace Avalonia.X11
+{
+ class X11Clipboard : IClipboard
+ {
+ private readonly X11Info _x11;
+ private string _storedString;
+ private IntPtr _handle;
+ private TaskCompletionSource _requestedFormatsTcs;
+ private TaskCompletionSource _requestedTextTcs;
+ private readonly IntPtr[] _textAtoms;
+ private readonly IntPtr _avaloniaSaveTargetsAtom;
+
+ public X11Clipboard(AvaloniaX11Platform platform)
+ {
+ _x11 = platform.Info;
+ _handle = CreateEventWindow(platform, OnEvent);
+ _avaloniaSaveTargetsAtom = XInternAtom(_x11.Display, "AVALONIA_SAVE_TARGETS_PROPERTY_ATOM", false);
+ _textAtoms = new[]
+ {
+ _x11.Atoms.XA_STRING,
+ _x11.Atoms.OEMTEXT,
+ _x11.Atoms.UTF8_STRING,
+ _x11.Atoms.UTF16_STRING
+ }.Where(a => a != IntPtr.Zero).ToArray();
+ }
+
+ Encoding GetStringEncoding(IntPtr atom)
+ {
+ return (atom == _x11.Atoms.XA_STRING
+ || atom == _x11.Atoms.OEMTEXT)
+ ? Encoding.ASCII
+ : atom == _x11.Atoms.UTF8_STRING
+ ? Encoding.UTF8
+ : atom == _x11.Atoms.UTF16_STRING
+ ? Encoding.Unicode
+ : null;
+ }
+
+ private unsafe void OnEvent(XEvent ev)
+ {
+ if (ev.type == XEventName.SelectionRequest)
+ {
+ var sel = ev.SelectionRequestEvent;
+ var resp = new XEvent
+ {
+ SelectionEvent =
+ {
+ type = XEventName.SelectionNotify,
+ send_event = true,
+ display = _x11.Display,
+ selection = sel.selection,
+ target = sel.target,
+ requestor = sel.requestor,
+ time = sel.time,
+ property = IntPtr.Zero
+ }
+ };
+ if (sel.selection == _x11.Atoms.CLIPBOARD)
+ {
+ resp.SelectionEvent.property = WriteTargetToProperty(sel.target, sel.requestor, sel.property);
+ }
+
+ XSendEvent(_x11.Display, sel.requestor, false, new IntPtr((int)EventMask.NoEventMask), ref resp);
+ }
+
+ IntPtr WriteTargetToProperty(IntPtr target, IntPtr window, IntPtr property)
+ {
+ Encoding textEnc;
+ if (target == _x11.Atoms.TARGETS)
+ {
+ var atoms = _textAtoms;
+ atoms = atoms.Concat(new[] {_x11.Atoms.TARGETS, _x11.Atoms.MULTIPLE})
+ .ToArray();
+ XChangeProperty(_x11.Display, window, property,
+ target, 32, PropertyMode.Replace, atoms, atoms.Length);
+ return property;
+ }
+ else if(target == _x11.Atoms.SAVE_TARGETS && _x11.Atoms.SAVE_TARGETS != IntPtr.Zero)
+ {
+ return property;
+ }
+ else if ((textEnc = GetStringEncoding(target)) != null)
+ {
+
+ var data = textEnc.GetBytes(_storedString ?? "");
+ fixed (void* pdata = data)
+ XChangeProperty(_x11.Display, window, property, target, 8,
+ PropertyMode.Replace,
+ pdata, data.Length);
+ return property;
+ }
+ else if (target == _x11.Atoms.MULTIPLE && _x11.Atoms.MULTIPLE != IntPtr.Zero)
+ {
+ XGetWindowProperty(_x11.Display, window, property, IntPtr.Zero, new IntPtr(0x7fffffff), false,
+ _x11.Atoms.ATOM_PAIR, out _, out var actualFormat, out var nitems, out _, out var prop);
+ if (nitems == IntPtr.Zero)
+ return IntPtr.Zero;
+ if (actualFormat == 32)
+ {
+ var data = (IntPtr*)prop.ToPointer();
+ for (var c = 0; c < nitems.ToInt32(); c += 2)
+ {
+ var subTarget = data[c];
+ var subProp = data[c + 1];
+ var converted = WriteTargetToProperty(subTarget, window, subProp);
+ data[c + 1] = converted;
+ }
+
+ XChangeProperty(_x11.Display, window, property, _x11.Atoms.ATOM_PAIR, 32, PropertyMode.Replace,
+ prop.ToPointer(), nitems.ToInt32());
+ }
+
+ XFree(prop);
+
+ return property;
+ }
+ else
+ return IntPtr.Zero;
+ }
+
+ if (ev.type == XEventName.SelectionNotify && ev.SelectionEvent.selection == _x11.Atoms.CLIPBOARD)
+ {
+ var sel = ev.SelectionEvent;
+ if (sel.property == IntPtr.Zero)
+ {
+ _requestedFormatsTcs?.TrySetResult(null);
+ _requestedTextTcs?.TrySetResult(null);
+ }
+ XGetWindowProperty(_x11.Display, _handle, sel.property, IntPtr.Zero, new IntPtr (0x7fffffff), true, (IntPtr)Atom.AnyPropertyType,
+ out var actualAtom, out var actualFormat, out var nitems, out var bytes_after, out var prop);
+ Encoding textEnc = null;
+ if (nitems == IntPtr.Zero)
+ {
+ _requestedFormatsTcs?.TrySetResult(null);
+ _requestedTextTcs?.TrySetResult(null);
+ }
+ else
+ {
+ if (sel.property == _x11.Atoms.TARGETS)
+ {
+ if (actualFormat != 32)
+ _requestedFormatsTcs?.TrySetResult(null);
+ else
+ {
+ var formats = new IntPtr[nitems.ToInt32()];
+ Marshal.Copy(prop, formats, 0, formats.Length);
+ _requestedFormatsTcs?.TrySetResult(formats);
+ }
+ }
+ else if ((textEnc = GetStringEncoding(sel.property)) != null)
+ {
+ var text = textEnc.GetString((byte*)prop.ToPointer(), nitems.ToInt32());
+ _requestedTextTcs?.TrySetResult(text);
+ }
+ }
+
+ XFree(prop);
+ }
+ }
+
+ Task SendFormatRequest()
+ {
+ if (_requestedFormatsTcs == null || _requestedFormatsTcs.Task.IsCompleted)
+ _requestedFormatsTcs = new TaskCompletionSource();
+ XConvertSelection(_x11.Display, _x11.Atoms.CLIPBOARD, _x11.Atoms.TARGETS, _x11.Atoms.TARGETS, _handle,
+ IntPtr.Zero);
+ return _requestedFormatsTcs.Task;
+ }
+
+ Task SendTextRequest(IntPtr format)
+ {
+ if (_requestedTextTcs == null || _requestedFormatsTcs.Task.IsCompleted)
+ _requestedTextTcs = new TaskCompletionSource();
+ XConvertSelection(_x11.Display, _x11.Atoms.CLIPBOARD, format, format, _handle, IntPtr.Zero);
+ return _requestedTextTcs.Task;
+ }
+
+ public async Task GetTextAsync()
+ {
+ if (XGetSelectionOwner(_x11.Display, _x11.Atoms.CLIPBOARD) == IntPtr.Zero)
+ return null;
+ var res = await SendFormatRequest();
+ var target = _x11.Atoms.UTF8_STRING;
+ if (res != null)
+ {
+ var preferredFormats = new[] {_x11.Atoms.UTF16_STRING, _x11.Atoms.UTF8_STRING, _x11.Atoms.XA_STRING};
+ foreach (var pf in preferredFormats)
+ if (res.Contains(pf))
+ {
+ target = pf;
+ break;
+ }
+ }
+
+ return await SendTextRequest(target);
+ }
+
+ void StoreAtomsInClipboardManager(IntPtr[] atoms)
+ {
+ if (_x11.Atoms.CLIPBOARD_MANAGER != IntPtr.Zero && _x11.Atoms.SAVE_TARGETS != IntPtr.Zero)
+ {
+ var clipboardManager = XGetSelectionOwner(_x11.Display, _x11.Atoms.CLIPBOARD_MANAGER);
+ if (clipboardManager != IntPtr.Zero)
+ {
+ XChangeProperty(_x11.Display, _handle, _avaloniaSaveTargetsAtom, _x11.Atoms.XA_ATOM, 32,
+ PropertyMode.Replace,
+ atoms, atoms.Length);
+ XConvertSelection(_x11.Display, _x11.Atoms.CLIPBOARD_MANAGER, _x11.Atoms.SAVE_TARGETS,
+ _avaloniaSaveTargetsAtom, _handle, IntPtr.Zero);
+ }
+ }
+ }
+
+ public Task SetTextAsync(string text)
+ {
+ _storedString = text;
+ XSetSelectionOwner(_x11.Display, _x11.Atoms.CLIPBOARD, _handle, IntPtr.Zero);
+ StoreAtomsInClipboardManager(_textAtoms);
+ return Task.CompletedTask;
+ }
+
+ public Task ClearAsync()
+ {
+ return SetTextAsync(null);
+ }
+ }
+}
diff --git a/src/Avalonia.X11/X11CursorFactory.cs b/src/Avalonia.X11/X11CursorFactory.cs
new file mode 100644
index 0000000000..40b01117e3
--- /dev/null
+++ b/src/Avalonia.X11/X11CursorFactory.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Avalonia.Input;
+using Avalonia.Platform;
+
+namespace Avalonia.X11
+{
+ class X11CursorFactory : IStandardCursorFactory
+ {
+ private readonly IntPtr _display;
+ private Dictionary _cursors;
+
+ private static readonly Dictionary s_mapping =
+ new Dictionary
+ {
+ {StandardCursorType.Arrow, CursorFontShape.XC_top_left_arrow},
+ {StandardCursorType.Cross, CursorFontShape.XC_cross},
+ {StandardCursorType.Hand, CursorFontShape.XC_hand1},
+ {StandardCursorType.Help, CursorFontShape.XC_question_arrow},
+ {StandardCursorType.Ibeam, CursorFontShape.XC_xterm},
+ {StandardCursorType.No, CursorFontShape.XC_X_cursor},
+ {StandardCursorType.Wait, CursorFontShape.XC_watch},
+ {StandardCursorType.AppStarting, CursorFontShape.XC_watch},
+ {StandardCursorType.BottomSize, CursorFontShape.XC_bottom_side},
+ {StandardCursorType.DragCopy, CursorFontShape.XC_center_ptr},
+ {StandardCursorType.DragLink, CursorFontShape.XC_fleur},
+ {StandardCursorType.DragMove, CursorFontShape.XC_diamond_cross},
+ {StandardCursorType.LeftSide, CursorFontShape.XC_left_side},
+ {StandardCursorType.RightSide, CursorFontShape.XC_right_side},
+ {StandardCursorType.SizeAll, CursorFontShape.XC_sizing},
+ {StandardCursorType.TopSide, CursorFontShape.XC_top_side},
+ {StandardCursorType.UpArrow, CursorFontShape.XC_sb_up_arrow},
+ {StandardCursorType.BottomLeftCorner, CursorFontShape.XC_bottom_left_corner},
+ {StandardCursorType.BottomRightCorner, CursorFontShape.XC_bottom_right_corner},
+ {StandardCursorType.SizeNorthSouth, CursorFontShape.XC_sb_v_double_arrow},
+ {StandardCursorType.SizeWestEast, CursorFontShape.XC_sb_h_double_arrow},
+ {StandardCursorType.TopLeftCorner, CursorFontShape.XC_top_left_corner},
+ {StandardCursorType.TopRightCorner, CursorFontShape.XC_top_right_corner},
+ };
+
+ public X11CursorFactory(IntPtr display)
+ {
+ _display = display;
+ _cursors = Enum.GetValues(typeof(CursorFontShape)).Cast()
+ .ToDictionary(id => id, id => XLib.XCreateFontCursor(_display, id));
+ }
+
+ public IPlatformHandle GetCursor(StandardCursorType cursorType)
+ {
+ var handle = s_mapping.TryGetValue(cursorType, out var shape)
+ ? _cursors[shape]
+ : _cursors[CursorFontShape.XC_top_left_arrow];
+ return new PlatformHandle(handle, "XCURSOR");
+ }
+ }
+}
diff --git a/src/Avalonia.X11/X11Enums.cs b/src/Avalonia.X11/X11Enums.cs
new file mode 100644
index 0000000000..d97e1c42bb
--- /dev/null
+++ b/src/Avalonia.X11/X11Enums.cs
@@ -0,0 +1,110 @@
+using System;
+
+namespace Avalonia.X11
+{
+
+ public enum Status
+ {
+ Success = 0, /* everything's okay */
+ BadRequest = 1, /* bad request code */
+ BadValue = 2, /* int parameter out of range */
+ BadWindow = 3, /* parameter not a Window */
+ BadPixmap = 4, /* parameter not a Pixmap */
+ BadAtom = 5, /* parameter not an Atom */
+ BadCursor = 6, /* parameter not a Cursor */
+ BadFont = 7, /* parameter not a Font */
+ BadMatch = 8, /* parameter mismatch */
+ BadDrawable = 9, /* parameter not a Pixmap or Window */
+ BadAccess = 10, /* depending on context:
+ - key/button already grabbed
+ - attempt to free an illegal
+ cmap entry
+ - attempt to store into a read-only
+ color map entry.
+ - attempt to modify the access control
+ list from other than the local host.
+ */
+ BadAlloc = 11, /* insufficient resources */
+ BadColor = 12, /* no such colormap */
+ BadGC = 13, /* parameter not a GC */
+ BadIDChoice = 14, /* choice not in range or already used */
+ BadName = 15, /* font or color name doesn't exist */
+ BadLength = 16, /* Request length incorrect */
+ BadImplementation = 17, /* server is defective */
+
+ FirstExtensionError = 128,
+ LastExtensionError = 255,
+
+ }
+
+ [Flags]
+ public enum XEventMask : int
+ {
+ NoEventMask = 0,
+ KeyPressMask = (1 << 0),
+ KeyReleaseMask = (1 << 1),
+ ButtonPressMask = (1 << 2),
+ ButtonReleaseMask = (1 << 3),
+ EnterWindowMask = (1 << 4),
+ LeaveWindowMask = (1 << 5),
+ PointerMotionMask = (1 << 6),
+ PointerMotionHintMask = (1 << 7),
+ Button1MotionMask = (1 << 8),
+ Button2MotionMask = (1 << 9),
+ Button3MotionMask = (1 << 10),
+ Button4MotionMask = (1 << 11),
+ Button5MotionMask = (1 << 12),
+ ButtonMotionMask = (1 << 13),
+ KeymapStateMask = (1 << 14),
+ ExposureMask = (1 << 15),
+ VisibilityChangeMask = (1 << 16),
+ StructureNotifyMask = (1 << 17),
+ ResizeRedirectMask = (1 << 18),
+ SubstructureNotifyMask = (1 << 19),
+ SubstructureRedirectMask = (1 << 20),
+ FocusChangeMask = (1 << 21),
+ PropertyChangeMask = (1 << 22),
+ ColormapChangeMask = (1 << 23),
+ OwnerGrabButtonMask = (1 << 24)
+ }
+
+ [Flags]
+ public enum XModifierMask
+ {
+ ShiftMask = (1 << 0),
+ LockMask = (1 << 1),
+ ControlMask = (1 << 2),
+ Mod1Mask = (1 << 3),
+ Mod2Mask = (1 << 4),
+ Mod3Mask = (1 << 5),
+ Mod4Mask = (1 << 6),
+ Mod5Mask = (1 << 7),
+ Button1Mask = (1 << 8),
+ Button2Mask = (1 << 9),
+ Button3Mask = (1 << 10),
+ Button4Mask = (1 << 11),
+ Button5Mask = (1 << 12),
+ AnyModifier = (1 << 15)
+
+ }
+
+ [Flags]
+ public enum XCreateWindowFlags
+ {
+ CWBackPixmap = (1 << 0),
+ CWBackPixel = (1 << 1),
+ CWBorderPixmap = (1 << 2),
+ CWBorderPixel = (1 << 3),
+ CWBitGravity = (1 << 4),
+ CWWinGravity = (1 << 5),
+ CWBackingStore = (1 << 6),
+ CWBackingPlanes = (1 << 7),
+ CWBackingPixel = (1 << 8),
+ CWOverrideRedirect = (1 << 9),
+ CWSaveUnder = (1 << 10),
+ CWEventMask = (1 << 11),
+ CWDontPropagate = (1 << 12),
+ CWColormap = (1 << 13),
+ CWCursor = (1 << 14),
+ }
+}
diff --git a/src/Avalonia.X11/X11Exception.cs b/src/Avalonia.X11/X11Exception.cs
new file mode 100644
index 0000000000..2ac5a31d9b
--- /dev/null
+++ b/src/Avalonia.X11/X11Exception.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Avalonia.X11
+{
+ public class X11Exception : Exception
+ {
+ public X11Exception(string message) : base(message)
+ {
+
+ }
+ }
+}
diff --git a/src/Avalonia.X11/X11Framebuffer.cs b/src/Avalonia.X11/X11Framebuffer.cs
new file mode 100644
index 0000000000..00288f300d
--- /dev/null
+++ b/src/Avalonia.X11/X11Framebuffer.cs
@@ -0,0 +1,59 @@
+using System;
+using System.IO;
+using Avalonia.Platform;
+using SkiaSharp;
+using static Avalonia.X11.XLib;
+namespace Avalonia.X11
+{
+ class X11Framebuffer : ILockedFramebuffer
+ {
+ private readonly IntPtr _display;
+ private readonly IntPtr _xid;
+ private readonly int _depth;
+ private IUnmanagedBlob _blob;
+
+ public X11Framebuffer(IntPtr display, IntPtr xid, int depth, int width, int height, double factor)
+ {
+ _display = display;
+ _xid = xid;
+ _depth = depth;
+ Size = new PixelSize(width, height);
+ RowBytes = width * 4;
+ Dpi = new Vector(96, 96) * factor;
+ Format = PixelFormat.Bgra8888;
+ _blob = AvaloniaLocator.Current.GetService().AllocBlob(RowBytes * height);
+ Address = _blob.Address;
+ }
+
+ public void Dispose()
+ {
+ var image = new XImage();
+ int bitsPerPixel = 32;
+ image.width = Size.Width;
+ image.height = Size.Height;
+ image.format = 2; //ZPixmap;
+ image.data = Address;
+ image.byte_order = 0;// LSBFirst;
+ image.bitmap_unit = bitsPerPixel;
+ image.bitmap_bit_order = 0;// LSBFirst;
+ image.bitmap_pad = bitsPerPixel;
+ image.depth = _depth;
+ image.bytes_per_line = RowBytes;
+ image.bits_per_pixel = bitsPerPixel;
+ XLockDisplay(_display);
+ XInitImage(ref image);
+ var gc = XCreateGC(_display, _xid, 0, IntPtr.Zero);
+ XPutImage(_display, _xid, gc, ref image, 0, 0, 0, 0, (uint) Size.Width, (uint) Size.Height);
+ XFreeGC(_display, gc);
+ XSync(_display, true);
+ XUnlockDisplay(_display);
+ _blob.Dispose();
+ }
+
+ public IntPtr Address { get; }
+ public PixelSize Size { get; }
+ public int RowBytes { get; }
+ public Vector Dpi { get; }
+ public PixelFormat Format { get; }
+ }
+}
diff --git a/src/Avalonia.X11/X11FramebufferSurface.cs b/src/Avalonia.X11/X11FramebufferSurface.cs
new file mode 100644
index 0000000000..70220cebcd
--- /dev/null
+++ b/src/Avalonia.X11/X11FramebufferSurface.cs
@@ -0,0 +1,29 @@
+using System;
+using Avalonia.Controls.Platform.Surfaces;
+using Avalonia.Platform;
+using static Avalonia.X11.XLib;
+namespace Avalonia.X11
+{
+ public class X11FramebufferSurface : IFramebufferPlatformSurface
+ {
+ private readonly IntPtr _display;
+ private readonly IntPtr _xid;
+ private readonly Func _scaling;
+
+ public X11FramebufferSurface(IntPtr display, IntPtr xid, Func scaling)
+ {
+ _display = display;
+ _xid = xid;
+ _scaling = scaling;
+ }
+
+ public ILockedFramebuffer Lock()
+ {
+ XLockDisplay(_display);
+ XGetGeometry(_display, _xid, out var root, out var x, out var y, out var width, out var height,
+ out var bw, out var d);
+ XUnlockDisplay(_display);
+ return new X11Framebuffer(_display, _xid, 24,width, height, _scaling());
+ }
+ }
+}
diff --git a/src/Avalonia.X11/X11IconLoader.cs b/src/Avalonia.X11/X11IconLoader.cs
new file mode 100644
index 0000000000..f0e75536d0
--- /dev/null
+++ b/src/Avalonia.X11/X11IconLoader.cs
@@ -0,0 +1,105 @@
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using Avalonia.Controls.Platform.Surfaces;
+using Avalonia.Media;
+using Avalonia.Media.Imaging;
+using Avalonia.Platform;
+using Avalonia.Utilities;
+using Avalonia.Visuals.Media.Imaging;
+using static Avalonia.X11.XLib;
+namespace Avalonia.X11
+{
+ class X11IconLoader : IPlatformIconLoader
+ {
+ private readonly X11Info _x11;
+
+ public X11IconLoader(X11Info x11)
+ {
+ _x11 = x11;
+ }
+
+ IWindowIconImpl LoadIcon(Bitmap bitmap)
+ {
+ var rv = new X11IconData(bitmap);
+ bitmap.Dispose();
+ return rv;
+ }
+
+ public IWindowIconImpl LoadIcon(string fileName) => LoadIcon(new Bitmap(fileName));
+
+ public IWindowIconImpl LoadIcon(Stream stream) => LoadIcon(new Bitmap(stream));
+
+ public IWindowIconImpl LoadIcon(IBitmapImpl bitmap)
+ {
+ var ms = new MemoryStream();
+ bitmap.Save(ms);
+ ms.Position = 0;
+ return LoadIcon(ms);
+ }
+ }
+
+ unsafe class X11IconData : IWindowIconImpl, IFramebufferPlatformSurface
+ {
+ private int _width;
+ private int _height;
+ private uint[] _bdata;
+ public UIntPtr[] Data { get; }
+
+ public X11IconData(Bitmap bitmap)
+ {
+ _width = Math.Min(bitmap.PixelSize.Width, 128);
+ _height = Math.Min(bitmap.PixelSize.Height, 128);
+ _bdata = new uint[_width * _height];
+ fixed (void* ptr = _bdata)
+ {
+ var iptr = (int*)ptr;
+ iptr[0] = _width;
+ iptr[1] = _height;
+ }
+ using(var rt = AvaloniaLocator.Current.GetService().CreateRenderTarget(new[]{this}))
+ using (var ctx = rt.CreateDrawingContext(null))
+ ctx.DrawImage(bitmap.PlatformImpl, 1, new Rect(bitmap.Size),
+ new Rect(0, 0, _width, _height));
+ Data = new UIntPtr[_width * _height + 2];
+ Data[0] = new UIntPtr((uint)_width);
+ Data[1] = new UIntPtr((uint)_height);
+ for (var y = 0; y < _height; y++)
+ {
+ var r = y * _width;
+ for (var x = 0; x < _width; x++)
+ Data[r + x] = new UIntPtr(_bdata[r + x]);
+ }
+
+ _bdata = null;
+ }
+
+ public void Save(Stream outputStream)
+ {
+ using (var wr =
+ new WriteableBitmap(new PixelSize(_width, _height), new Vector(96, 96), PixelFormat.Bgra8888))
+ {
+ using (var fb = wr.Lock())
+ {
+ var fbp = (uint*)fb.Address;
+ for (var y = 0; y < _height; y++)
+ {
+ var r = y * _width;
+ var fbr = y * fb.RowBytes / 4;
+ for (var x = 0; x < _width; x++)
+ fbp[fbr + x] = Data[r + x].ToUInt32();
+ }
+ }
+ wr.Save(outputStream);
+ }
+ }
+
+ public ILockedFramebuffer Lock()
+ {
+ var h = GCHandle.Alloc(_bdata, GCHandleType.Pinned);
+ return new LockedFramebuffer(h.AddrOfPinnedObject(), new PixelSize(_width, _height), _width * 4,
+ new Vector(96, 96), PixelFormat.Bgra8888,
+ () => h.Free());
+ }
+ }
+}
diff --git a/src/Avalonia.X11/X11Info.cs b/src/Avalonia.X11/X11Info.cs
new file mode 100644
index 0000000000..6e4b31fb5c
--- /dev/null
+++ b/src/Avalonia.X11/X11Info.cs
@@ -0,0 +1,85 @@
+using System;
+using System.Linq;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using JetBrains.Annotations;
+using static Avalonia.X11.XLib;
+// ReSharper disable UnusedAutoPropertyAccessor.Local
+namespace Avalonia.X11
+{
+ class X11Info
+ {
+ public IntPtr Display { get; }
+ public IntPtr DeferredDisplay { get; }
+ public int DefaultScreen { get; }
+ public IntPtr BlackPixel { get; }
+ public IntPtr RootWindow { get; }
+ public IntPtr DefaultRootWindow { get; }
+ public IntPtr DefaultCursor { get; }
+ public X11Atoms Atoms { get; }
+ public IntPtr Xim { get; }
+
+ public int RandrEventBase { get; }
+ public int RandrErrorBase { get; }
+
+ public Version RandrVersion { get; }
+
+ public int XInputOpcode { get; }
+ public int XInputEventBase { get; }
+ public int XInputErrorBase { get; }
+
+ public Version XInputVersion { get; }
+
+ public IntPtr LastActivityTimestamp { get; set; }
+
+ public unsafe X11Info(IntPtr display, IntPtr deferredDisplay)
+ {
+ Display = display;
+ DeferredDisplay = deferredDisplay;
+ DefaultScreen = XDefaultScreen(display);
+ BlackPixel = XBlackPixel(display, DefaultScreen);
+ RootWindow = XRootWindow(display, DefaultScreen);
+ DefaultCursor = XCreateFontCursor(display, CursorFontShape.XC_top_left_arrow);
+ DefaultRootWindow = XDefaultRootWindow(display);
+ Atoms = new X11Atoms(display);
+ //TODO: Open an actual XIM once we get support for preedit in our textbox
+ XSetLocaleModifiers("@im=none");
+ Xim = XOpenIM(display, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
+
+ try
+ {
+ if (XRRQueryExtension(display, out int randrEventBase, out var randrErrorBase) != 0)
+ {
+ RandrEventBase = randrEventBase;
+ RandrErrorBase = randrErrorBase;
+ if (XRRQueryVersion(display, out var major, out var minor) != 0)
+ RandrVersion = new Version(major, minor);
+ }
+ }
+ catch
+ {
+ //Ignore, randr is not supported
+ }
+
+ try
+ {
+ if (XQueryExtension(display, "XInputExtension",
+ out var xiopcode, out var xievent, out var xierror))
+ {
+ int major = 2, minor = 2;
+ if (XIQueryVersion(display, ref major, ref minor) == Status.Success)
+ {
+ XInputVersion = new Version(major, minor);
+ XInputOpcode = xiopcode;
+ XInputEventBase = xievent;
+ XInputErrorBase = xierror;
+ }
+ }
+ }
+ catch
+ {
+ //Ignore, XI is not supported
+ }
+ }
+ }
+}
diff --git a/src/Avalonia.X11/X11KeyTransform.cs b/src/Avalonia.X11/X11KeyTransform.cs
new file mode 100644
index 0000000000..26495111d1
--- /dev/null
+++ b/src/Avalonia.X11/X11KeyTransform.cs
@@ -0,0 +1,232 @@
+using System;
+using System.Collections.Generic;
+using Avalonia.Input;
+
+namespace Avalonia.X11
+{
+ static class X11KeyTransform
+ {
+ private static readonly Dictionary KeyDic = new Dictionary
+ {
+ {X11Key.Cancel, Key.Cancel},
+ {X11Key.BackSpace, Key.Back},
+ {X11Key.Tab, Key.Tab},
+ {X11Key.Linefeed, Key.LineFeed},
+ {X11Key.Clear, Key.Clear},
+ {X11Key.Return, Key.Return},
+ {X11Key.KP_Enter, Key.Return},
+ {X11Key.Pause, Key.Pause},
+ {X11Key.Caps_Lock, Key.CapsLock},
+ //{ X11Key.?, Key.HangulMode }
+ //{ X11Key.?, Key.JunjaMode }
+ //{ X11Key.?, Key.FinalMode }
+ //{ X11Key.?, Key.KanjiMode }
+ {X11Key.Escape, Key.Escape},
+ //{ X11Key.?, Key.ImeConvert }
+ //{ X11Key.?, Key.ImeNonConvert }
+ //{ X11Key.?, Key.ImeAccept }
+ //{ X11Key.?, Key.ImeModeChange }
+ {X11Key.space, Key.Space},
+ {X11Key.Prior, Key.Prior},
+ {X11Key.KP_Prior, Key.Prior},
+ {X11Key.Page_Down, Key.PageDown},
+ {X11Key.KP_Page_Down, Key.PageDown},
+ {X11Key.End, Key.End},
+ {X11Key.KP_End, Key.End},
+ {X11Key.Home, Key.Home},
+ {X11Key.KP_Home, Key.Home},
+ {X11Key.Left, Key.Left},
+ {X11Key.KP_Left, Key.Left},
+ {X11Key.Up, Key.Up},
+ {X11Key.KP_Up, Key.Up},
+ {X11Key.Right, Key.Right},
+ {X11Key.KP_Right, Key.Right},
+ {X11Key.Down, Key.Down},
+ {X11Key.KP_Down, Key.Down},
+ {X11Key.Select, Key.Select},
+ {X11Key.Print, Key.Print},
+ {X11Key.Execute, Key.Execute},
+ //{ X11Key.?, Key.Snapshot }
+ {X11Key.Insert, Key.Insert},
+ {X11Key.KP_Insert, Key.Insert},
+ {X11Key.Delete, Key.Delete},
+ {X11Key.KP_Delete, Key.Delete},
+ {X11Key.Help, Key.Help},
+ {X11Key.XK_0, Key.D0},
+ {X11Key.XK_1, Key.D1},
+ {X11Key.XK_2, Key.D2},
+ {X11Key.XK_3, Key.D3},
+ {X11Key.XK_4, Key.D4},
+ {X11Key.XK_5, Key.D5},
+ {X11Key.XK_6, Key.D6},
+ {X11Key.XK_7, Key.D7},
+ {X11Key.XK_8, Key.D8},
+ {X11Key.XK_9, Key.D9},
+ {X11Key.A, Key.A},
+ {X11Key.B, Key.B},
+ {X11Key.C, Key.C},
+ {X11Key.D, Key.D},
+ {X11Key.E, Key.E},
+ {X11Key.F, Key.F},
+ {X11Key.G, Key.G},
+ {X11Key.H, Key.H},
+ {X11Key.I, Key.I},
+ {X11Key.J, Key.J},
+ {X11Key.K, Key.K},
+ {X11Key.L, Key.L},
+ {X11Key.M, Key.M},
+ {X11Key.N, Key.N},
+ {X11Key.O, Key.O},
+ {X11Key.P, Key.P},
+ {X11Key.Q, Key.Q},
+ {X11Key.R, Key.R},
+ {X11Key.S, Key.S},
+ {X11Key.T, Key.T},
+ {X11Key.U, Key.U},
+ {X11Key.V, Key.V},
+ {X11Key.W, Key.W},
+ {X11Key.X, Key.X},
+ {X11Key.Y, Key.Y},
+ {X11Key.Z, Key.Z},
+ {X11Key.a, Key.A},
+ {X11Key.b, Key.B},
+ {X11Key.c, Key.C},
+ {X11Key.d, Key.D},
+ {X11Key.e, Key.E},
+ {X11Key.f, Key.F},
+ {X11Key.g, Key.G},
+ {X11Key.h, Key.H},
+ {X11Key.i, Key.I},
+ {X11Key.j, Key.J},
+ {X11Key.k, Key.K},
+ {X11Key.l, Key.L},
+ {X11Key.m, Key.M},
+ {X11Key.n, Key.N},
+ {X11Key.o, Key.O},
+ {X11Key.p, Key.P},
+ {X11Key.q, Key.Q},
+ {X11Key.r, Key.R},
+ {X11Key.s, Key.S},
+ {X11Key.t, Key.T},
+ {X11Key.u, Key.U},
+ {X11Key.v, Key.V},
+ {X11Key.w, Key.W},
+ {X11Key.x, Key.X},
+ {X11Key.y, Key.Y},
+ {X11Key.z, Key.Z},
+ //{ X11Key.?, Key.LWin }
+ //{ X11Key.?, Key.RWin }
+ {X11Key.Menu, Key.Apps},
+ //{ X11Key.?, Key.Sleep }
+ {X11Key.KP_0, Key.NumPad0},
+ {X11Key.KP_1, Key.NumPad1},
+ {X11Key.KP_2, Key.NumPad2},
+ {X11Key.KP_3, Key.NumPad3},
+ {X11Key.KP_4, Key.NumPad4},
+ {X11Key.KP_5, Key.NumPad5},
+ {X11Key.KP_6, Key.NumPad6},
+ {X11Key.KP_7, Key.NumPad7},
+ {X11Key.KP_8, Key.NumPad8},
+ {X11Key.KP_9, Key.NumPad9},
+ {X11Key.multiply, Key.Multiply},
+ {X11Key.KP_Multiply, Key.Multiply},
+ {X11Key.KP_Add, Key.Add},
+ //{ X11Key.?, Key.Separator }
+ {X11Key.KP_Subtract, Key.Subtract},
+ {X11Key.KP_Decimal, Key.Decimal},
+ {X11Key.KP_Divide, Key.Divide},
+ {X11Key.F1, Key.F1},
+ {X11Key.F2, Key.F2},
+ {X11Key.F3, Key.F3},
+ {X11Key.F4, Key.F4},
+ {X11Key.F5, Key.F5},
+ {X11Key.F6, Key.F6},
+ {X11Key.F7, Key.F7},
+ {X11Key.F8, Key.F8},
+ {X11Key.F9, Key.F9},
+ {X11Key.F10, Key.F10},
+ {X11Key.F11, Key.F11},
+ {X11Key.F12, Key.F12},
+ {X11Key.L3, Key.F13},
+ {X11Key.F14, Key.F14},
+ {X11Key.L5, Key.F15},
+ {X11Key.F16, Key.F16},
+ {X11Key.F17, Key.F17},
+ {X11Key.L8, Key.F18},
+ {X11Key.L9, Key.F19},
+ {X11Key.L10, Key.F20},
+ {X11Key.R1, Key.F21},
+ {X11Key.R2, Key.F22},
+ {X11Key.F23, Key.F23},
+ {X11Key.R4, Key.F24},
+ {X11Key.Num_Lock, Key.NumLock},
+ {X11Key.Scroll_Lock, Key.Scroll},
+ {X11Key.Shift_L, Key.LeftShift},
+ {X11Key.Shift_R, Key.RightShift},
+ {X11Key.Control_L, Key.LeftCtrl},
+ {X11Key.Control_R, Key.RightCtrl},
+ {X11Key.Alt_L, Key.LeftAlt},
+ {X11Key.Alt_R, Key.RightAlt},
+ //{ X11Key.?, Key.BrowserBack }
+ //{ X11Key.?, Key.BrowserForward }
+ //{ X11Key.?, Key.BrowserRefresh }
+ //{ X11Key.?, Key.BrowserStop }
+ //{ X11Key.?, Key.BrowserSearch }
+ //{ X11Key.?, Key.BrowserFavorites }
+ //{ X11Key.?, Key.BrowserHome }
+ //{ X11Key.?, Key.VolumeMute }
+ //{ X11Key.?, Key.VolumeDown }
+ //{ X11Key.?, Key.VolumeUp }
+ //{ X11Key.?, Key.MediaNextTrack }
+ //{ X11Key.?, Key.MediaPreviousTrack }
+ //{ X11Key.?, Key.MediaStop }
+ //{ X11Key.?, Key.MediaPlayPause }
+ //{ X11Key.?, Key.LaunchMail }
+ //{ X11Key.?, Key.SelectMedia }
+ //{ X11Key.?, Key.LaunchApplication1 }
+ //{ X11Key.?, Key.LaunchApplication2 }
+ {X11Key.semicolon, Key.OemSemicolon},
+ {X11Key.plus, Key.OemPlus},
+ {X11Key.equal, Key.OemPlus},
+ {X11Key.comma, Key.OemComma},
+ {X11Key.minus, Key.OemMinus},
+ {X11Key.period, Key.OemPeriod},
+ {X11Key.slash, Key.Oem2},
+ {X11Key.grave, Key.OemTilde},
+ //{ X11Key.?, Key.AbntC1 }
+ //{ X11Key.?, Key.AbntC2 }
+ {X11Key.bracketleft, Key.OemOpenBrackets},
+ {X11Key.backslash, Key.OemPipe},
+ {X11Key.bracketright, Key.OemCloseBrackets},
+ {X11Key.apostrophe, Key.OemQuotes},
+ //{ X11Key.?, Key.Oem8 }
+ //{ X11Key.?, Key.Oem102 }
+ //{ X11Key.?, Key.ImeProcessed }
+ //{ X11Key.?, Key.System }
+ //{ X11Key.?, Key.OemAttn }
+ //{ X11Key.?, Key.OemFinish }
+ //{ X11Key.?, Key.DbeHiragana }
+ //{ X11Key.?, Key.OemAuto }
+ //{ X11Key.?, Key.DbeDbcsChar }
+ //{ X11Key.?, Key.OemBackTab }
+ //{ X11Key.?, Key.Attn }
+ //{ X11Key.?, Key.DbeEnterWordRegisterMode }
+ //{ X11Key.?, Key.DbeEnterImeConfigureMode }
+ //{ X11Key.?, Key.EraseEof }
+ //{ X11Key.?, Key.Play }
+ //{ X11Key.?, Key.Zoom }
+ //{ X11Key.?, Key.NoName }
+ //{ X11Key.?, Key.DbeEnterDialogConversionMode }
+ //{ X11Key.?, Key.OemClear }
+ //{ X11Key.?, Key.DeadCharProcessed }
+ };
+
+ public static Key ConvertKey(IntPtr key)
+ {
+ var ikey = key.ToInt32();
+ Key result;
+ return KeyDic.TryGetValue((X11Key)ikey, out result) ? result : Key.None;
+ }
+}
+
+}
diff --git a/src/Avalonia.X11/X11Platform.cs b/src/Avalonia.X11/X11Platform.cs
new file mode 100644
index 0000000000..3b50dff5c8
--- /dev/null
+++ b/src/Avalonia.X11/X11Platform.cs
@@ -0,0 +1,93 @@
+using System;
+using System.Collections.Generic;
+using Avalonia.Controls;
+using Avalonia.Controls.Platform;
+using Avalonia.Gtk3;
+using Avalonia.Input;
+using Avalonia.Input.Platform;
+using Avalonia.OpenGL;
+using Avalonia.Platform;
+using Avalonia.Rendering;
+using Avalonia.X11;
+using static Avalonia.X11.XLib;
+namespace Avalonia.X11
+{
+ class AvaloniaX11Platform : IWindowingPlatform
+ {
+ private Lazy _keyboardDevice = new Lazy(() => new KeyboardDevice());
+ private Lazy _mouseDevice = new Lazy(() => new MouseDevice());
+ public KeyboardDevice KeyboardDevice => _keyboardDevice.Value;
+ public MouseDevice MouseDevice => _mouseDevice.Value;
+ public Dictionary> Windows = new Dictionary>();
+ public XI2Manager XI2;
+ public X11Info Info { get; private set; }
+ public IX11Screens X11Screens { get; private set; }
+ public IScreenImpl Screens { get; private set; }
+ public void Initialize()
+ {
+ XInitThreads();
+ Display = XOpenDisplay(IntPtr.Zero);
+ DeferredDisplay = XOpenDisplay(IntPtr.Zero);
+ if (Display == IntPtr.Zero)
+ throw new Exception("XOpenDisplay failed");
+ XError.Init();
+ Info = new X11Info(Display, DeferredDisplay);
+
+ AvaloniaLocator.CurrentMutable.BindToSelf(this)
+ .Bind().ToConstant(this)
+ .Bind().ToConstant(new X11PlatformThreading(this))
+ .Bind().ToConstant(new DefaultRenderTimer(60))
+ .Bind().ToConstant(new RenderLoop())
+ .Bind().ToConstant(new PlatformHotkeyConfiguration(InputModifiers.Control))
+ .Bind().ToFunc(() => KeyboardDevice)
+ .Bind().ToConstant(new X11CursorFactory(Display))
+ .Bind().ToConstant(new X11Clipboard(this))
+ .Bind().ToConstant(new PlatformSettingsStub())
+ .Bind().ToConstant(new X11IconLoader(Info))
+ .Bind().ToConstant(new Gtk3ForeignX11SystemDialog());
+
+ X11Screens = Avalonia.X11.X11Screens.Init(this);
+ Screens = new X11Screens(X11Screens);
+ if (Info.XInputVersion != null)
+ {
+ var xi2 = new XI2Manager();
+ if (xi2.Init(this))
+ XI2 = xi2;
+ }
+ EglGlPlatformFeature.TryInitialize();
+
+ }
+
+ public IntPtr DeferredDisplay { get; set; }
+ public IntPtr Display { get; set; }
+ public IWindowImpl CreateWindow()
+ {
+ return new X11Window(this, false);
+ }
+
+ public IEmbeddableWindowImpl CreateEmbeddableWindow()
+ {
+ throw new NotSupportedException();
+ }
+
+ public IPopupImpl CreatePopup()
+ {
+ return new X11Window(this, true);
+ }
+ }
+}
+
+namespace Avalonia
+{
+ public static class AvaloniaX11PlatformExtensions
+ {
+ public static T UseX11(this T builder) where T : AppBuilderBase, new()
+ {
+ builder.UseWindowingSubsystem(() => new AvaloniaX11Platform().Initialize());
+ return builder;
+ }
+
+ public static void InitializeX11Platform() => new AvaloniaX11Platform().Initialize();
+ }
+
+}
diff --git a/src/Avalonia.X11/X11PlatformThreading.cs b/src/Avalonia.X11/X11PlatformThreading.cs
new file mode 100644
index 0000000000..f66afc4a83
--- /dev/null
+++ b/src/Avalonia.X11/X11PlatformThreading.cs
@@ -0,0 +1,285 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Threading;
+using Avalonia.Platform;
+using Avalonia.Threading;
+using static Avalonia.X11.XLib;
+
+namespace Avalonia.X11
+{
+ unsafe class X11PlatformThreading : IPlatformThreadingInterface
+ {
+ private readonly AvaloniaX11Platform _platform;
+ private readonly IntPtr _display;
+ private readonly Dictionary> _eventHandlers;
+ private Thread _mainThread;
+
+ [StructLayout(LayoutKind.Explicit)]
+ struct epoll_data
+ {
+ [FieldOffset(0)]
+ public IntPtr ptr;
+ [FieldOffset(0)]
+ public int fd;
+ [FieldOffset(0)]
+ public uint u32;
+ [FieldOffset(0)]
+ public ulong u64;
+ }
+
+ private const int EPOLLIN = 1;
+ private const int EPOLL_CTL_ADD = 1;
+ private const int O_NONBLOCK = 2048;
+
+ [StructLayout(LayoutKind.Sequential)]
+ struct epoll_event
+ {
+ public uint events;
+ public epoll_data data;
+ }
+
+ [DllImport("libc")]
+ extern static int epoll_create1(int size);
+
+ [DllImport("libc")]
+ extern static int epoll_ctl(int epfd, int op, int fd, ref epoll_event __event);
+
+ [DllImport("libc")]
+ extern static int epoll_wait(int epfd, epoll_event* events, int maxevents, int timeout);
+
+ [DllImport("libc")]
+ extern static int pipe2(int* fds, int flags);
+ [DllImport("libc")]
+ extern static IntPtr write(int fd, void* buf, IntPtr count);
+
+ [DllImport("libc")]
+ extern static IntPtr read(int fd, void* buf, IntPtr count);
+
+ enum EventCodes
+ {
+ X11 = 1,
+ Signal =2
+ }
+
+ private int _sigread, _sigwrite;
+ private object _lock = new object();
+ private bool _signaled;
+ private DispatcherPriority _signaledPriority;
+ private int _epoll;
+ private Stopwatch _clock = Stopwatch.StartNew();
+
+ class X11Timer : IDisposable
+ {
+ private readonly X11PlatformThreading _parent;
+
+ public X11Timer(X11PlatformThreading parent, DispatcherPriority prio, TimeSpan interval, Action tick)
+ {
+ _parent = parent;
+ Priority = prio;
+ Tick = tick;
+ Interval = interval;
+ Reschedule();
+ }
+
+ public DispatcherPriority Priority { get; }
+ public TimeSpan NextTick { get; private set; }
+ public TimeSpan Interval { get; }
+ public Action Tick { get; }
+ public bool Disposed { get; private set; }
+
+ public void Reschedule()
+ {
+ NextTick = _parent._clock.Elapsed + Interval;
+ }
+
+ public void Dispose()
+ {
+ Disposed = true;
+ lock (_parent._lock)
+ _parent._timers.Remove(this);
+ }
+ }
+
+ List _timers = new List();
+
+ public X11PlatformThreading(AvaloniaX11Platform platform)
+ {
+ _platform = platform;
+ _display = platform.Display;
+ _eventHandlers = platform.Windows;
+ _mainThread = Thread.CurrentThread;
+ var fd = XLib.XConnectionNumber(_display);
+ var ev = new epoll_event()
+ {
+ events = EPOLLIN,
+ data = {u32 = (int)EventCodes.X11}
+ };
+ _epoll = epoll_create1(0);
+ if (_epoll == -1)
+ throw new X11Exception("epoll_create1 failed");
+
+ if (epoll_ctl(_epoll, EPOLL_CTL_ADD, fd, ref ev) == -1)
+ throw new X11Exception("Unable to attach X11 connection handle to epoll");
+
+ var fds = stackalloc int[2];
+ pipe2(fds, O_NONBLOCK);
+ _sigread = fds[0];
+ _sigwrite = fds[1];
+
+ ev = new epoll_event
+ {
+ events = EPOLLIN,
+ data = {u32 = (int)EventCodes.Signal}
+ };
+ if (epoll_ctl(_epoll, EPOLL_CTL_ADD, _sigread, ref ev) == -1)
+ throw new X11Exception("Unable to attach signal pipe to epoll");
+ }
+
+ int TimerComparer(X11Timer t1, X11Timer t2)
+ {
+ return t2.Priority - t1.Priority;
+ }
+
+ void CheckSignaled()
+ {
+ int buf = 0;
+ while (read(_sigread, &buf, new IntPtr(4)).ToInt64() > 0)
+ {
+ }
+
+ DispatcherPriority prio;
+ lock (_lock)
+ {
+ if (!_signaled)
+ return;
+ _signaled = false;
+ prio = _signaledPriority;
+ _signaledPriority = DispatcherPriority.MinValue;
+ }
+
+ Signaled?.Invoke(prio);
+ }
+
+ void HandleX11(CancellationToken cancellationToken)
+ {
+ while (true)
+ {
+ var pending = XPending(_display);
+ if (pending == 0)
+ break;
+ while (pending > 0)
+ {
+ if (cancellationToken.IsCancellationRequested)
+ return;
+ XNextEvent(_display, out var xev);
+ if (xev.type == XEventName.GenericEvent)
+ XGetEventData(_display, &xev.GenericEventCookie);
+ pending--;
+ try
+ {
+ if (xev.type == XEventName.GenericEvent)
+ {
+ if (_platform.XI2 != null && _platform.Info.XInputOpcode ==
+ xev.GenericEventCookie.extension)
+ {
+ _platform.XI2.OnEvent((XIEvent*)xev.GenericEventCookie.data);
+ }
+ }
+ else if (_eventHandlers.TryGetValue(xev.AnyEvent.window, out var handler))
+ handler(xev);
+ }
+ finally
+ {
+ if (xev.type == XEventName.GenericEvent && xev.GenericEventCookie.data != null)
+ XFreeEventData(_display, &xev.GenericEventCookie);
+ }
+ }
+ }
+ Dispatcher.UIThread.RunJobs();
+ }
+
+ public void RunLoop(CancellationToken cancellationToken)
+ {
+ var readyTimers = new List();
+ while (!cancellationToken.IsCancellationRequested)
+ {
+ var now = _clock.Elapsed;
+ TimeSpan? nextTick = null;
+ readyTimers.Clear();
+ lock(_timers)
+ foreach (var t in _timers)
+ {
+ if (nextTick == null || t.NextTick < nextTick.Value)
+ nextTick = t.NextTick;
+ if (t.NextTick < now)
+ readyTimers.Add(t);
+ }
+
+ readyTimers.Sort(TimerComparer);
+
+ foreach (var t in readyTimers)
+ {
+ if (cancellationToken.IsCancellationRequested)
+ return;
+ t.Tick();
+ if(!t.Disposed)
+ {
+ t.Reschedule();
+ if (nextTick == null || t.NextTick < nextTick.Value)
+ nextTick = t.NextTick;
+ }
+ }
+
+ if (cancellationToken.IsCancellationRequested)
+ return;
+ //Flush whatever requests were made to XServer
+ XFlush(_display);
+ epoll_event ev;
+ if (XPending(_display) == 0)
+ epoll_wait(_epoll, &ev, 1,
+ nextTick == null ? -1 : Math.Max(1, (int)(nextTick.Value - _clock.Elapsed).TotalMilliseconds));
+ if (cancellationToken.IsCancellationRequested)
+ return;
+ CheckSignaled();
+ HandleX11(cancellationToken);
+ }
+ }
+
+
+
+ public void Signal(DispatcherPriority priority)
+ {
+ lock (_lock)
+ {
+ if (priority > _signaledPriority)
+ _signaledPriority = priority;
+
+ if(_signaled)
+ return;
+ _signaled = true;
+ int buf = 0;
+ write(_sigwrite, &buf, new IntPtr(1));
+ }
+ }
+
+ public bool CurrentThreadIsLoopThread => Thread.CurrentThread == _mainThread;
+ public event Action Signaled;
+
+ public IDisposable StartTimer(DispatcherPriority priority, TimeSpan interval, Action tick)
+ {
+ if (_mainThread != Thread.CurrentThread)
+ throw new InvalidOperationException("StartTimer can be only called from UI thread");
+ if (interval <= TimeSpan.Zero)
+ throw new ArgumentException("Interval must be positive", nameof(interval));
+
+ // We assume that we are on the main thread and outside of epoll_wait, so there is no need for wakeup signal
+
+ var timer = new X11Timer(this, priority, interval, tick);
+ lock(_timers)
+ _timers.Add(timer);
+ return timer;
+ }
+ }
+}
diff --git a/src/Avalonia.X11/X11Screens.cs b/src/Avalonia.X11/X11Screens.cs
new file mode 100644
index 0000000000..f2a0520c10
--- /dev/null
+++ b/src/Avalonia.X11/X11Screens.cs
@@ -0,0 +1,252 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Runtime.InteropServices;
+using Avalonia.Platform;
+using static Avalonia.X11.XLib;
+using JetBrains.Annotations;
+
+namespace Avalonia.X11
+{
+ class X11Screens : IScreenImpl
+ {
+ private IX11Screens _impl;
+
+ public X11Screens(IX11Screens impl)
+ {
+ _impl = impl;
+ }
+
+ static unsafe X11Screen[] UpdateWorkArea(X11Info info, X11Screen[] screens)
+ {
+ var rect = default(PixelRect);
+ foreach (var s in screens)
+ {
+ rect = rect.Union(s.Bounds);
+ //Fallback value
+ s.WorkingArea = s.Bounds;
+ }
+
+ var res = XGetWindowProperty(info.Display,
+ info.RootWindow,
+ info.Atoms._NET_WORKAREA,
+ IntPtr.Zero,
+ new IntPtr(128),
+ false,
+ info.Atoms.AnyPropertyType,
+ out var type,
+ out var format,
+ out var count,
+ out var bytesAfter,
+ out var prop);
+
+ if (res != (int)Status.Success || type == IntPtr.Zero ||
+ format == 0 || bytesAfter.ToInt64() != 0 || count.ToInt64() % 4 != 0)
+ return screens;
+
+ var pwa = (IntPtr*)prop;
+ var wa = new PixelRect(pwa[0].ToInt32(), pwa[1].ToInt32(), pwa[2].ToInt32(), pwa[3].ToInt32());
+
+
+ foreach (var s in screens)
+ s.WorkingArea = s.Bounds.Intersect(wa);
+
+ XFree(prop);
+ return screens;
+ }
+
+ class Randr15ScreensImpl : IX11Screens
+ {
+ private readonly X11ScreensUserSettings _settings;
+ private X11Screen[] _cache;
+ private X11Info _x11;
+ private IntPtr _window;
+
+ public Randr15ScreensImpl(AvaloniaX11Platform platform, X11ScreensUserSettings settings)
+ {
+ _settings = settings;
+ _x11 = platform.Info;
+ _window = CreateEventWindow(platform, OnEvent);
+ XRRSelectInput(_x11.Display, _window, RandrEventMask.RRScreenChangeNotify);
+ }
+
+ private void OnEvent(XEvent ev)
+ {
+ // Invalidate cache on RRScreenChangeNotify
+ if ((int)ev.type == _x11.RandrEventBase + (int)RandrEvent.RRScreenChangeNotify)
+ _cache = null;
+ }
+
+ public unsafe X11Screen[] Screens
+ {
+ get
+ {
+ if (_cache != null)
+ return _cache;
+ var monitors = XRRGetMonitors(_x11.Display, _window, true, out var count);
+
+ var screens = new X11Screen[count];
+ for (var c = 0; c < count; c++)
+ {
+ var mon = monitors[c];
+ var namePtr = XGetAtomName(_x11.Display, mon.Name);
+ var name = Marshal.PtrToStringAnsi(namePtr);
+ XFree(namePtr);
+
+ var density = 1d;
+ if (_settings.NamedScaleFactors?.TryGetValue(name, out density) != true)
+ {
+ if (mon.MWidth == 0)
+ density = 1;
+ else
+ density = X11Screen.GuessPixelDensity(mon.Width, mon.MWidth);
+ }
+
+ density *= _settings.GlobalScaleFactor;
+
+ var bounds = new PixelRect(mon.X, mon.Y, mon.Width, mon.Height);
+ screens[c] = new X11Screen(bounds,
+ mon.Primary != 0,
+ name,
+ (mon.MWidth == 0 || mon.MHeight == 0) ? (Size?)null : new Size(mon.MWidth, mon.MHeight),
+ density);
+ }
+
+ XFree(new IntPtr(monitors));
+ _cache = UpdateWorkArea(_x11, screens);
+ return screens;
+ }
+ }
+ }
+
+ class FallbackScreensImpl : IX11Screens
+ {
+ public FallbackScreensImpl(X11Info info, X11ScreensUserSettings settings)
+ {
+ if (XGetGeometry(info.Display, info.RootWindow, out var geo))
+ {
+
+ Screens = UpdateWorkArea(info,
+ new[]
+ {
+ new X11Screen(new PixelRect(0, 0, geo.width, geo.height), true, "Default", null,
+ settings.GlobalScaleFactor)
+ });
+ }
+
+ Screens = new[] {new X11Screen(new PixelRect(0, 0, 1920, 1280), true, "Default", null, settings.GlobalScaleFactor)};
+ }
+
+ public X11Screen[] Screens { get; }
+ }
+
+ public static IX11Screens Init(AvaloniaX11Platform platform)
+ {
+ var info = platform.Info;
+ var settings = X11ScreensUserSettings.Detect();
+ var impl = (info.RandrVersion != null && info.RandrVersion >= new Version(1, 5))
+ ? new Randr15ScreensImpl(platform, settings)
+ : (IX11Screens)new FallbackScreensImpl(info, settings);
+
+ return impl;
+
+ }
+
+
+ public int ScreenCount => _impl.Screens.Length;
+
+ public Screen[] AllScreens =>
+ _impl.Screens.Select(s => new Screen(s.Bounds, s.WorkingArea, s.Primary)).ToArray();
+ }
+
+ interface IX11Screens
+ {
+ X11Screen[] Screens { get; }
+ }
+
+ class X11ScreensUserSettings
+ {
+ public double GlobalScaleFactor { get; set; } = 1;
+ public Dictionary NamedScaleFactors { get; set; }
+
+ static double? TryParse(string s)
+ {
+ if (s == null)
+ return null;
+ if (double.TryParse(s, NumberStyles.Any, CultureInfo.InvariantCulture, out var rv))
+ return rv;
+ return null;
+ }
+
+
+ public static X11ScreensUserSettings DetectEnvironment()
+ {
+ var globalFactor = Environment.GetEnvironmentVariable("AVALONIA_GLOBAL_SCALE_FACTOR");
+ var screenFactors = Environment.GetEnvironmentVariable("AVALONIA_SCREEN_SCALE_FACTORS");
+ if (globalFactor == null && screenFactors == null)
+ return null;
+
+ var rv = new X11ScreensUserSettings
+ {
+ GlobalScaleFactor = TryParse(globalFactor) ?? 1
+ };
+
+ try
+ {
+ if (!string.IsNullOrWhiteSpace(screenFactors))
+ {
+ rv.NamedScaleFactors = screenFactors.Split(';').Where(x => !string.IsNullOrWhiteSpace(x))
+ .Select(x => x.Split('=')).ToDictionary(x => x[0],
+ x => double.Parse(x[1], CultureInfo.InvariantCulture));
+ }
+ }
+ catch
+ {
+ //Ignore
+ }
+
+ return rv;
+ }
+
+
+ public static X11ScreensUserSettings Detect()
+ {
+ return DetectEnvironment() ?? new X11ScreensUserSettings();
+ }
+ }
+
+ class X11Screen
+ {
+ public bool Primary { get; }
+ public string Name { get; set; }
+ public PixelRect Bounds { get; set; }
+ public Size? PhysicalSize { get; set; }
+ public double PixelDensity { get; set; }
+ public PixelRect WorkingArea { get; set; }
+
+ public X11Screen(PixelRect bounds, bool primary,
+ string name, Size? physicalSize, double? pixelDensity)
+ {
+ Primary = primary;
+ Name = name;
+ Bounds = bounds;
+ if (physicalSize == null && pixelDensity == null)
+ {
+ PixelDensity = 1;
+ }
+ else if (pixelDensity == null)
+ {
+ PixelDensity = GuessPixelDensity(bounds.Width, physicalSize.Value.Width);
+ }
+ else
+ {
+ PixelDensity = pixelDensity.Value;
+ PhysicalSize = physicalSize;
+ }
+ }
+
+ public static double GuessPixelDensity(double pixelWidth, double mmWidth)
+ => Math.Max(1, Math.Round(pixelWidth / mmWidth * 25.4 / 96));
+ }
+}
diff --git a/src/Avalonia.X11/X11Structs.cs b/src/Avalonia.X11/X11Structs.cs
new file mode 100644
index 0000000000..0ae5c16aef
--- /dev/null
+++ b/src/Avalonia.X11/X11Structs.cs
@@ -0,0 +1,1886 @@
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software",, to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// Copyright (c) 2004 Novell, Inc.
+//
+// Authors:
+// Peter Bartok pbartok@novell.com
+//
+
+
+// NOT COMPLETE
+
+using System;
+using System.ComponentModel;
+using System.Collections;
+using System.Drawing;
+using System.Diagnostics;
+using System.Reflection;
+using System.Runtime.InteropServices;
+// ReSharper disable FieldCanBeMadeReadOnly.Global
+// ReSharper disable IdentifierTypo
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable CommentTypo
+// ReSharper disable ArrangeThisQualifier
+// ReSharper disable NotAccessedField.Global
+#pragma warning disable 649
+
+namespace Avalonia.X11 {
+ //
+ // In the structures below, fields of type long are mapped to IntPtr.
+ // This will work on all platforms where sizeof(long)==sizeof(void*), which
+ // is almost all platforms except WIN64.
+ //
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct XAnyEvent {
+ internal XEventName type;
+ internal IntPtr serial;
+ internal bool send_event;
+ internal IntPtr display;
+ internal IntPtr window;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct XKeyEvent {
+ internal XEventName type;
+ internal IntPtr serial;
+ internal bool send_event;
+ internal IntPtr display;
+ internal IntPtr window;
+ internal IntPtr root;
+ internal IntPtr subwindow;
+ internal IntPtr time;
+ internal int x;
+ internal int y;
+ internal int x_root;
+ internal int y_root;
+ internal XModifierMask state;
+ internal int keycode;
+ internal bool same_screen;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct XButtonEvent {
+ internal XEventName type;
+ internal IntPtr serial;
+ internal bool send_event;
+ internal IntPtr display;
+ internal IntPtr window;
+ internal IntPtr root;
+ internal IntPtr subwindow;
+ internal IntPtr time;
+ internal int x;
+ internal int y;
+ internal int x_root;
+ internal int y_root;
+ internal XModifierMask state;
+ internal int button;
+ internal bool same_screen;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct XMotionEvent {
+ internal XEventName type;
+ internal IntPtr serial;
+ internal bool send_event;
+ internal IntPtr display;
+ internal IntPtr window;
+ internal IntPtr root;
+ internal IntPtr subwindow;
+ internal IntPtr time;
+ internal int x;
+ internal int y;
+ internal int x_root;
+ internal int y_root;
+ internal XModifierMask state;
+ internal byte is_hint;
+ internal bool same_screen;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct XCrossingEvent {
+ internal XEventName type;
+ internal IntPtr serial;
+ internal bool send_event;
+ internal IntPtr display;
+ internal IntPtr window;
+ internal IntPtr root;
+ internal IntPtr subwindow;
+ internal IntPtr time;
+ internal int x;
+ internal int y;
+ internal int x_root;
+ internal int y_root;
+ internal NotifyMode mode;
+ internal NotifyDetail detail;
+ internal bool same_screen;
+ internal bool focus;
+ internal XModifierMask state;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct XFocusChangeEvent {
+ internal XEventName type;
+ internal IntPtr serial;
+ internal bool send_event;
+ internal IntPtr display;
+ internal IntPtr window;
+ internal int mode;
+ internal NotifyDetail detail;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct XKeymapEvent {
+ internal XEventName type;
+ internal IntPtr serial;
+ internal bool send_event;
+ internal IntPtr display;
+ internal IntPtr window;
+ internal byte key_vector0;
+ internal byte key_vector1;
+ internal byte key_vector2;
+ internal byte key_vector3;
+ internal byte key_vector4;
+ internal byte key_vector5;
+ internal byte key_vector6;
+ internal byte key_vector7;
+ internal byte key_vector8;
+ internal byte key_vector9;
+ internal byte key_vector10;
+ internal byte key_vector11;
+ internal byte key_vector12;
+ internal byte key_vector13;
+ internal byte key_vector14;
+ internal byte key_vector15;
+ internal byte key_vector16;
+ internal byte key_vector17;
+ internal byte key_vector18;
+ internal byte key_vector19;
+ internal byte key_vector20;
+ internal byte key_vector21;
+ internal byte key_vector22;
+ internal byte key_vector23;
+ internal byte key_vector24;
+ internal byte key_vector25;
+ internal byte key_vector26;
+ internal byte key_vector27;
+ internal byte key_vector28;
+ internal byte key_vector29;
+ internal byte key_vector30;
+ internal byte key_vector31;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct XExposeEvent {
+ internal XEventName type;
+ internal IntPtr serial;
+ internal bool send_event;
+ internal IntPtr display;
+ internal IntPtr window;
+ internal int x;
+ internal int y;
+ internal int width;
+ internal int height;
+ internal int count;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct XGraphicsExposeEvent {
+ internal XEventName type;
+ internal IntPtr serial;
+ internal bool send_event;
+ internal IntPtr display;
+ internal IntPtr drawable;
+ internal int x;
+ internal int y;
+ internal int width;
+ internal int height;
+ internal int count;
+ internal int major_code;
+ internal int minor_code;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct XNoExposeEvent {
+ internal XEventName type;
+ internal IntPtr serial;
+ internal bool send_event;
+ internal IntPtr display;
+ internal IntPtr drawable;
+ internal int major_code;
+ internal int minor_code;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct XVisibilityEvent {
+ internal XEventName type;
+ internal IntPtr serial;
+ internal bool send_event;
+ internal IntPtr display;
+ internal IntPtr window;
+ internal int state;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct XCreateWindowEvent {
+ internal XEventName type;
+ internal IntPtr serial;
+ internal bool send_event;
+ internal IntPtr display;
+ internal IntPtr parent;
+ internal IntPtr window;
+ internal int x;
+ internal int y;
+ internal int width;
+ internal int height;
+ internal int border_width;
+ internal bool override_redirect;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct XDestroyWindowEvent {
+ internal XEventName type;
+ internal IntPtr serial;
+ internal bool send_event;
+ internal IntPtr display;
+ internal IntPtr xevent;
+ internal IntPtr window;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct XUnmapEvent {
+ internal XEventName type;
+ internal IntPtr serial;
+ internal bool send_event;
+ internal IntPtr display;
+ internal IntPtr xevent;
+ internal IntPtr window;
+ internal bool from_configure;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct XMapEvent {
+ internal XEventName type;
+ internal IntPtr serial;
+ internal bool send_event;
+ internal IntPtr display;
+ internal IntPtr xevent;
+ internal IntPtr window;
+ internal bool override_redirect;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct XMapRequestEvent {
+ internal XEventName type;
+ internal IntPtr serial;
+ internal bool send_event;
+ internal IntPtr display;
+ internal IntPtr parent;
+ internal IntPtr window;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct XReparentEvent {
+ internal XEventName type;
+ internal IntPtr serial;
+ internal bool send_event;
+ internal IntPtr display;
+ internal IntPtr xevent;
+ internal IntPtr window;
+ internal IntPtr parent;
+ internal int x;
+ internal int y;
+ internal bool override_redirect;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct XConfigureEvent {
+ internal XEventName type;
+ internal IntPtr serial;
+ internal bool send_event;
+ internal IntPtr display;
+ internal IntPtr xevent;
+ internal IntPtr window;
+ internal int x;
+ internal int y;
+ internal int width;
+ internal int height;
+ internal int border_width;
+ internal IntPtr above;
+ internal bool override_redirect;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct XGravityEvent {
+ internal XEventName type;
+ internal IntPtr serial;
+ internal bool send_event;
+ internal IntPtr display;
+ internal IntPtr xevent;
+ internal IntPtr window;
+ internal int x;
+ internal int y;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct XResizeRequestEvent {
+ internal XEventName type;
+ internal IntPtr serial;
+ internal bool send_event;
+ internal IntPtr display;
+ internal IntPtr window;
+ internal int width;
+ internal int height;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct XConfigureRequestEvent {
+ internal XEventName type;
+ internal IntPtr serial;
+ internal bool send_event;
+ internal IntPtr display;
+ internal IntPtr parent;
+ internal IntPtr window;
+ internal int x;
+ internal int y;
+ internal int width;
+ internal int height;
+ internal int border_width;
+ internal IntPtr above;
+ internal int detail;
+ internal IntPtr value_mask;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct XCirculateEvent {
+ internal XEventName type;
+ internal IntPtr serial;
+ internal bool send_event;
+ internal IntPtr display;
+ internal IntPtr xevent;
+ internal IntPtr window;
+ internal int place;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct XCirculateRequestEvent {
+ internal XEventName type;
+ internal IntPtr serial;
+ internal bool send_event;
+ internal IntPtr display;
+ internal IntPtr parent;
+ internal IntPtr window;
+ internal int place;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct XPropertyEvent {
+ internal XEventName type;
+ internal IntPtr serial;
+ internal bool send_event;
+ internal IntPtr display;
+ internal IntPtr window;
+ internal IntPtr atom;
+ internal IntPtr time;
+ internal int state;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct XSelectionClearEvent {
+ internal XEventName type;
+ internal IntPtr serial;
+ internal bool send_event;
+ internal IntPtr display;
+ internal IntPtr window;
+ internal IntPtr selection;
+ internal IntPtr time;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct XSelectionRequestEvent {
+ internal XEventName type;
+ internal IntPtr serial;
+ internal bool send_event;
+ internal IntPtr display;
+ internal IntPtr owner;
+ internal IntPtr requestor;
+ internal IntPtr selection;
+ internal IntPtr target;
+ internal IntPtr property;
+ internal IntPtr time;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct XSelectionEvent {
+ internal XEventName type;
+ internal IntPtr serial;
+ internal bool send_event;
+ internal IntPtr display;
+ internal IntPtr requestor;
+ internal IntPtr selection;
+ internal IntPtr target;
+ internal IntPtr property;
+ internal IntPtr time;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct XColormapEvent {
+ internal XEventName type;
+ internal IntPtr serial;
+ internal bool send_event;
+ internal IntPtr display;
+ internal IntPtr window;
+ internal IntPtr colormap;
+ internal bool c_new;
+ internal int state;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct XClientMessageEvent {
+ internal XEventName type;
+ internal IntPtr serial;
+ internal bool send_event;
+ internal IntPtr display;
+ internal IntPtr window;
+ internal IntPtr message_type;
+ internal int format;
+ internal IntPtr ptr1;
+ internal IntPtr ptr2;
+ internal IntPtr ptr3;
+ internal IntPtr ptr4;
+ internal IntPtr ptr5;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct XMappingEvent {
+ internal XEventName type;
+ internal IntPtr serial;
+ internal bool send_event;
+ internal IntPtr display;
+ internal IntPtr window;
+ internal int request;
+ internal int first_keycode;
+ internal int count;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct XErrorEvent {
+ internal XEventName type;
+ internal IntPtr display;
+ internal IntPtr resourceid;
+ internal IntPtr serial;
+ internal byte error_code;
+ internal XRequest request_code;
+ internal byte minor_code;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct XEventPad {
+ internal IntPtr pad0;
+ internal IntPtr pad1;
+ internal IntPtr pad2;
+ internal IntPtr pad3;
+ internal IntPtr pad4;
+ internal IntPtr pad5;
+ internal IntPtr pad6;
+ internal IntPtr pad7;
+ internal IntPtr pad8;
+ internal IntPtr pad9;
+ internal IntPtr pad10;
+ internal IntPtr pad11;
+ internal IntPtr pad12;
+ internal IntPtr pad13;
+ internal IntPtr pad14;
+ internal IntPtr pad15;
+ internal IntPtr pad16;
+ internal IntPtr pad17;
+ internal IntPtr pad18;
+ internal IntPtr pad19;
+ internal IntPtr pad20;
+ internal IntPtr pad21;
+ internal IntPtr pad22;
+ internal IntPtr pad23;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal unsafe struct XGenericEventCookie
+ {
+ internal int type; /* of event. Always GenericEvent */
+ internal IntPtr serial; /* # of last request processed */
+ internal bool send_event; /* true if from SendEvent request */
+ internal IntPtr display; /* Display the event was read from */
+ internal int extension; /* major opcode of extension that caused the event */
+ internal int evtype; /* actual event type. */
+ internal uint cookie;
+ internal void* data;
+
+ public T GetEvent() where T : unmanaged
+ {
+ if (data == null)
+ throw new InvalidOperationException();
+ return *(T*)data;
+ }
+ }
+
+ [StructLayout(LayoutKind.Explicit)]
+ internal struct XEvent {
+ [ FieldOffset(0) ] internal XEventName type;
+ [ FieldOffset(0) ] internal XAnyEvent AnyEvent;
+ [ FieldOffset(0) ] internal XKeyEvent KeyEvent;
+ [ FieldOffset(0) ] internal XButtonEvent ButtonEvent;
+ [ FieldOffset(0) ] internal XMotionEvent MotionEvent;
+ [ FieldOffset(0) ] internal XCrossingEvent CrossingEvent;
+ [ FieldOffset(0) ] internal XFocusChangeEvent FocusChangeEvent;
+ [ FieldOffset(0) ] internal XExposeEvent ExposeEvent;
+ [ FieldOffset(0) ] internal XGraphicsExposeEvent GraphicsExposeEvent;
+ [ FieldOffset(0) ] internal XNoExposeEvent NoExposeEvent;
+ [ FieldOffset(0) ] internal XVisibilityEvent VisibilityEvent;
+ [ FieldOffset(0) ] internal XCreateWindowEvent CreateWindowEvent;
+ [ FieldOffset(0) ] internal XDestroyWindowEvent DestroyWindowEvent;
+ [ FieldOffset(0) ] internal XUnmapEvent UnmapEvent;
+ [ FieldOffset(0) ] internal XMapEvent MapEvent;
+ [ FieldOffset(0) ] internal XMapRequestEvent MapRequestEvent;
+ [ FieldOffset(0) ] internal XReparentEvent ReparentEvent;
+ [ FieldOffset(0) ] internal XConfigureEvent ConfigureEvent;
+ [ FieldOffset(0) ] internal XGravityEvent GravityEvent;
+ [ FieldOffset(0) ] internal XResizeRequestEvent ResizeRequestEvent;
+ [ FieldOffset(0) ] internal XConfigureRequestEvent ConfigureRequestEvent;
+ [ FieldOffset(0) ] internal XCirculateEvent CirculateEvent;
+ [ FieldOffset(0) ] internal XCirculateRequestEvent CirculateRequestEvent;
+ [ FieldOffset(0) ] internal XPropertyEvent PropertyEvent;
+ [ FieldOffset(0) ] internal XSelectionClearEvent SelectionClearEvent;
+ [ FieldOffset(0) ] internal XSelectionRequestEvent SelectionRequestEvent;
+ [ FieldOffset(0) ] internal XSelectionEvent SelectionEvent;
+ [ FieldOffset(0) ] internal XColormapEvent ColormapEvent;
+ [ FieldOffset(0) ] internal XClientMessageEvent ClientMessageEvent;
+ [ FieldOffset(0) ] internal XMappingEvent MappingEvent;
+ [ FieldOffset(0) ] internal XErrorEvent ErrorEvent;
+ [ FieldOffset(0) ] internal XKeymapEvent KeymapEvent;
+ [ FieldOffset(0) ] internal XGenericEventCookie GenericEventCookie;
+
+ //[MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=24)]
+ //[ FieldOffset(0) ] internal int[] pad;
+ [ FieldOffset(0) ] internal XEventPad Pad;
+ public override string ToString() {
+ switch (type)
+ {
+ case XEventName.ButtonPress:
+ case XEventName.ButtonRelease:
+ return ToString (ButtonEvent);
+ case XEventName.CirculateNotify:
+ case XEventName.CirculateRequest:
+ return ToString (CirculateEvent);
+ case XEventName.ClientMessage:
+ return ToString (ClientMessageEvent);
+ case XEventName.ColormapNotify:
+ return ToString (ColormapEvent);
+ case XEventName.ConfigureNotify:
+ return ToString (ConfigureEvent);
+ case XEventName.ConfigureRequest:
+ return ToString (ConfigureRequestEvent);
+ case XEventName.CreateNotify:
+ return ToString (CreateWindowEvent);
+ case XEventName.DestroyNotify:
+ return ToString (DestroyWindowEvent);
+ case XEventName.Expose:
+ return ToString (ExposeEvent);
+ case XEventName.FocusIn:
+ case XEventName.FocusOut:
+ return ToString (FocusChangeEvent);
+ case XEventName.GraphicsExpose:
+ return ToString (GraphicsExposeEvent);
+ case XEventName.GravityNotify:
+ return ToString (GravityEvent);
+ case XEventName.KeymapNotify:
+ return ToString (KeymapEvent);
+ case XEventName.MapNotify:
+ return ToString (MapEvent);
+ case XEventName.MappingNotify:
+ return ToString (MappingEvent);
+ case XEventName.MapRequest:
+ return ToString (MapRequestEvent);
+ case XEventName.MotionNotify:
+ return ToString (MotionEvent);
+ case XEventName.NoExpose:
+ return ToString (NoExposeEvent);
+ case XEventName.PropertyNotify:
+ return ToString (PropertyEvent);
+ case XEventName.ReparentNotify:
+ return ToString (ReparentEvent);
+ case XEventName.ResizeRequest:
+ return ToString (ResizeRequestEvent);
+ case XEventName.SelectionClear:
+ return ToString (SelectionClearEvent);
+ case XEventName.SelectionNotify:
+ return ToString (SelectionEvent);
+ case XEventName.SelectionRequest:
+ return ToString (SelectionRequestEvent);
+ case XEventName.UnmapNotify:
+ return ToString (UnmapEvent);
+ case XEventName.VisibilityNotify:
+ return ToString (VisibilityEvent);
+ case XEventName.EnterNotify:
+ case XEventName.LeaveNotify:
+ return ToString (CrossingEvent);
+ default:
+ return type.ToString ();
+ }
+ }
+
+ public static string ToString (object ev)
+ {
+ string result = string.Empty;
+ Type type = ev.GetType ();
+ FieldInfo [] fields = type.GetFields (System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Instance);
+ for (int i = 0; i < fields.Length; i++) {
+ if (result != string.Empty) {
+ result += ", ";
+ }
+ object value = fields [i].GetValue (ev);
+ result += fields [i].Name + "=" + (value == null ? "" : value.ToString ());
+ }
+ return type.Name + " (" + result + ")";
+ }
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct XSetWindowAttributes {
+ internal IntPtr background_pixmap;
+ internal IntPtr background_pixel;
+ internal IntPtr border_pixmap;
+ internal IntPtr border_pixel;
+ internal Gravity bit_gravity;
+ internal Gravity win_gravity;
+ internal int backing_store;
+ internal IntPtr backing_planes;
+ internal IntPtr backing_pixel;
+ internal bool save_under;
+ internal IntPtr event_mask;
+ internal IntPtr do_not_propagate_mask;
+ internal bool override_redirect;
+ internal IntPtr colormap;
+ internal IntPtr cursor;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct XWindowAttributes {
+ internal int x;
+ internal int y;
+ internal int width;
+ internal int height;
+ internal int border_width;
+ internal int depth;
+ internal IntPtr visual;
+ internal IntPtr root;
+ internal int c_class;
+ internal Gravity bit_gravity;
+ internal Gravity win_gravity;
+ internal int backing_store;
+ internal IntPtr backing_planes;
+ internal IntPtr backing_pixel;
+ internal bool save_under;
+ internal IntPtr colormap;
+ internal bool map_installed;
+ internal MapState map_state;
+ internal IntPtr all_event_masks;
+ internal IntPtr your_event_mask;
+ internal IntPtr do_not_propagate_mask;
+ internal bool override_direct;
+ internal IntPtr screen;
+
+ public override string ToString ()
+ {
+ return XEvent.ToString (this);
+ }
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct XTextProperty {
+ internal string value;
+ internal IntPtr encoding;
+ internal int format;
+ internal IntPtr nitems;
+ }
+
+ internal enum XWindowClass {
+ InputOutput = 1,
+ InputOnly = 2
+ }
+
+ internal enum XEventName {
+ KeyPress = 2,
+ KeyRelease = 3,
+ ButtonPress = 4,
+ ButtonRelease = 5,
+ MotionNotify = 6,
+ EnterNotify = 7,
+ LeaveNotify = 8,
+ FocusIn = 9,
+ FocusOut = 10,
+ KeymapNotify = 11,
+ Expose = 12,
+ GraphicsExpose = 13,
+ NoExpose = 14,
+ VisibilityNotify = 15,
+ CreateNotify = 16,
+ DestroyNotify = 17,
+ UnmapNotify = 18,
+ MapNotify = 19,
+ MapRequest = 20,
+ ReparentNotify = 21,
+ ConfigureNotify = 22,
+ ConfigureRequest = 23,
+ GravityNotify = 24,
+ ResizeRequest = 25,
+ CirculateNotify = 26,
+ CirculateRequest = 27,
+ PropertyNotify = 28,
+ SelectionClear = 29,
+ SelectionRequest = 30,
+ SelectionNotify = 31,
+ ColormapNotify = 32,
+ ClientMessage = 33,
+ MappingNotify = 34,
+ GenericEvent = 35,
+ LASTEvent
+ }
+
+ [Flags]
+ internal enum SetWindowValuemask {
+ Nothing = 0,
+ BackPixmap = 1,
+ BackPixel = 2,
+ BorderPixmap = 4,
+ BorderPixel = 8,
+ BitGravity = 16,
+ WinGravity = 32,
+ BackingStore = 64,
+ BackingPlanes = 128,
+ BackingPixel = 256,
+ OverrideRedirect = 512,
+ SaveUnder = 1024,
+ EventMask = 2048,
+ DontPropagate = 4096,
+ ColorMap = 8192,
+ Cursor = 16384
+ }
+
+ internal enum SendEventValues {
+ PointerWindow = 0,
+ InputFocus = 1
+ }
+
+ internal enum CreateWindowArgs {
+ CopyFromParent = 0,
+ ParentRelative = 1,
+ InputOutput = 1,
+ InputOnly = 2
+ }
+
+ internal enum Gravity {
+ ForgetGravity = 0,
+ NorthWestGravity= 1,
+ NorthGravity = 2,
+ NorthEastGravity= 3,
+ WestGravity = 4,
+ CenterGravity = 5,
+ EastGravity = 6,
+ SouthWestGravity= 7,
+ SouthGravity = 8,
+ SouthEastGravity= 9,
+ StaticGravity = 10
+ }
+
+ internal enum XKeySym : uint {
+ XK_BackSpace = 0xFF08,
+ XK_Tab = 0xFF09,
+ XK_Clear = 0xFF0B,
+ XK_Return = 0xFF0D,
+ XK_Home = 0xFF50,
+ XK_Left = 0xFF51,
+ XK_Up = 0xFF52,
+ XK_Right = 0xFF53,
+ XK_Down = 0xFF54,
+ XK_Page_Up = 0xFF55,
+ XK_Page_Down = 0xFF56,
+ XK_End = 0xFF57,
+ XK_Begin = 0xFF58,
+ XK_Menu = 0xFF67,
+ XK_Shift_L = 0xFFE1,
+ XK_Shift_R = 0xFFE2,
+ XK_Control_L = 0xFFE3,
+ XK_Control_R = 0xFFE4,
+ XK_Caps_Lock = 0xFFE5,
+ XK_Shift_Lock = 0xFFE6,
+ XK_Meta_L = 0xFFE7,
+ XK_Meta_R = 0xFFE8,
+ XK_Alt_L = 0xFFE9,
+ XK_Alt_R = 0xFFEA,
+ XK_Super_L = 0xFFEB,
+ XK_Super_R = 0xFFEC,
+ XK_Hyper_L = 0xFFED,
+ XK_Hyper_R = 0xFFEE,
+ }
+
+ [Flags]
+ internal enum EventMask {
+ NoEventMask = 0,
+ KeyPressMask = 1<<0,
+ KeyReleaseMask = 1<<1,
+ ButtonPressMask = 1<<2,
+ ButtonReleaseMask = 1<<3,
+ EnterWindowMask = 1<<4,
+ LeaveWindowMask = 1<<5,
+ PointerMotionMask = 1<<6,
+ PointerMotionHintMask = 1<<7,
+ Button1MotionMask = 1<<8,
+ Button2MotionMask = 1<<9,
+ Button3MotionMask = 1<<10,
+ Button4MotionMask = 1<<11,
+ Button5MotionMask = 1<<12,
+ ButtonMotionMask = 1<<13,
+ KeymapStateMask = 1<<14,
+ ExposureMask = 1<<15,
+ VisibilityChangeMask = 1<<16,
+ StructureNotifyMask = 1<<17,
+ ResizeRedirectMask = 1<<18,
+ SubstructureNotifyMask = 1<<19,
+ SubstructureRedirectMask= 1<<20,
+ FocusChangeMask = 1<<21,
+ PropertyChangeMask = 1<<22,
+ ColormapChangeMask = 1<<23,
+ OwnerGrabButtonMask = 1<<24
+ }
+
+ [Flags]
+ internal enum RandrEventMask
+ {
+ RRScreenChangeNotify = 1 << 0,
+
+/* V1.2 additions */
+ RRCrtcChangeNotifyMask = 1 << 1,
+ RROutputChangeNotifyMask = 1 << 2,
+ RROutputPropertyNotifyMask = 1 << 3,
+
+/* V1.4 additions */
+ RRProviderChangeNotifyMask = 1 << 4,
+ RRProviderPropertyNotifyMask = 1 << 5,
+ RRResourceChangeNotifyMask = 1 << 6,
+
+/* V1.6 additions */
+ RRLeaseNotifyMask = 1 << 7
+ }
+
+ internal enum RandrEvent
+ {
+ RRScreenChangeNotify = 0,
+
+ /* V1.2 additions */
+ RRNotify = 1
+ }
+
+ internal enum RandrRotate
+ {
+ /* used in the rotation field; rotation and reflection in 0.1 proto. */
+ RR_Rotate_0 = 1,
+ RR_Rotate_90 = 2,
+ RR_Rotate_180 = 4,
+ RR_Rotate_270 = 8
+ }
+
+ internal enum GrabMode {
+ GrabModeSync = 0,
+ GrabModeAsync = 1
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct XStandardColormap {
+ internal IntPtr colormap;
+ internal IntPtr red_max;
+ internal IntPtr red_mult;
+ internal IntPtr green_max;
+ internal IntPtr green_mult;
+ internal IntPtr blue_max;
+ internal IntPtr blue_mult;
+ internal IntPtr base_pixel;
+ internal IntPtr visualid;
+ internal IntPtr killid;
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack=2)]
+ internal struct XColor {
+ internal IntPtr pixel;
+ internal ushort red;
+ internal ushort green;
+ internal ushort blue;
+ internal byte flags;
+ internal byte pad;
+ }
+
+ internal enum Atom {
+ AnyPropertyType = 0,
+ XA_PRIMARY = 1,
+ XA_SECONDARY = 2,
+ XA_ARC = 3,
+ XA_ATOM = 4,
+ XA_BITMAP = 5,
+ XA_CARDINAL = 6,
+ XA_COLORMAP = 7,
+ XA_CURSOR = 8,
+ XA_CUT_BUFFER0 = 9,
+ XA_CUT_BUFFER1 = 10,
+ XA_CUT_BUFFER2 = 11,
+ XA_CUT_BUFFER3 = 12,
+ XA_CUT_BUFFER4 = 13,
+ XA_CUT_BUFFER5 = 14,
+ XA_CUT_BUFFER6 = 15,
+ XA_CUT_BUFFER7 = 16,
+ XA_DRAWABLE = 17,
+ XA_FONT = 18,
+ XA_INTEGER = 19,
+ XA_PIXMAP = 20,
+ XA_POINT = 21,
+ XA_RECTANGLE = 22,
+ XA_RESOURCE_MANAGER = 23,
+ XA_RGB_COLOR_MAP = 24,
+ XA_RGB_BEST_MAP = 25,
+ XA_RGB_BLUE_MAP = 26,
+ XA_RGB_DEFAULT_MAP = 27,
+ XA_RGB_GRAY_MAP = 28,
+ XA_RGB_GREEN_MAP = 29,
+ XA_RGB_RED_MAP = 30,
+ XA_STRING = 31,
+ XA_VISUALID = 32,
+ XA_WINDOW = 33,
+ XA_WM_COMMAND = 34,
+ XA_WM_HINTS = 35,
+ XA_WM_CLIENT_MACHINE = 36,
+ XA_WM_ICON_NAME = 37,
+ XA_WM_ICON_SIZE = 38,
+ XA_WM_NAME = 39,
+ XA_WM_NORMAL_HINTS = 40,
+ XA_WM_SIZE_HINTS = 41,
+ XA_WM_ZOOM_HINTS = 42,
+ XA_MIN_SPACE = 43,
+ XA_NORM_SPACE = 44,
+ XA_MAX_SPACE = 45,
+ XA_END_SPACE = 46,
+ XA_SUPERSCRIPT_X = 47,
+ XA_SUPERSCRIPT_Y = 48,
+ XA_SUBSCRIPT_X = 49,
+ XA_SUBSCRIPT_Y = 50,
+ XA_UNDERLINE_POSITION = 51,
+ XA_UNDERLINE_THICKNESS = 52,
+ XA_STRIKEOUT_ASCENT = 53,
+ XA_STRIKEOUT_DESCENT = 54,
+ XA_ITALIC_ANGLE = 55,
+ XA_X_HEIGHT = 56,
+ XA_QUAD_WIDTH = 57,
+ XA_WEIGHT = 58,
+ XA_POINT_SIZE = 59,
+ XA_RESOLUTION = 60,
+ XA_COPYRIGHT = 61,
+ XA_NOTICE = 62,
+ XA_FONT_NAME = 63,
+ XA_FAMILY_NAME = 64,
+ XA_FULL_NAME = 65,
+ XA_CAP_HEIGHT = 66,
+ XA_WM_CLASS = 67,
+ XA_WM_TRANSIENT_FOR = 68,
+
+ XA_LAST_PREDEFINED = 68
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct XScreen {
+ internal IntPtr ext_data;
+ internal IntPtr display;
+ internal IntPtr root;
+ internal int width;
+ internal int height;
+ internal int mwidth;
+ internal int mheight;
+ internal int ndepths;
+ internal IntPtr depths;
+ internal int root_depth;
+ internal IntPtr root_visual;
+ internal IntPtr default_gc;
+ internal IntPtr cmap;
+ internal IntPtr white_pixel;
+ internal IntPtr black_pixel;
+ internal int max_maps;
+ internal int min_maps;
+ internal int backing_store;
+ internal bool save_unders;
+ internal IntPtr root_input_mask;
+ }
+
+ [Flags]
+ internal enum ChangeWindowFlags {
+ CWX = 1<<0,
+ CWY = 1<<1,
+ CWWidth = 1<<2,
+ CWHeight = 1<<3,
+ CWBorderWidth = 1<<4,
+ CWSibling = 1<<5,
+ CWStackMode = 1<<6
+ }
+
+ internal enum StackMode {
+ Above = 0,
+ Below = 1,
+ TopIf = 2,
+ BottomIf = 3,
+ Opposite = 4
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct XWindowChanges {
+ internal int x;
+ internal int y;
+ internal int width;
+ internal int height;
+ internal int border_width;
+ internal IntPtr sibling;
+ internal StackMode stack_mode;
+ }
+
+ [Flags]
+ internal enum ColorFlags {
+ DoRed = 1<<0,
+ DoGreen = 1<<1,
+ DoBlue = 1<<2
+ }
+
+ internal enum NotifyMode {
+ NotifyNormal = 0,
+ NotifyGrab = 1,
+ NotifyUngrab = 2
+ }
+
+ internal enum NotifyDetail {
+ NotifyAncestor = 0,
+ NotifyVirtual = 1,
+ NotifyInferior = 2,
+ NotifyNonlinear = 3,
+ NotifyNonlinearVirtual = 4,
+ NotifyPointer = 5,
+ NotifyPointerRoot = 6,
+ NotifyDetailNone = 7
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct MotifWmHints {
+ internal IntPtr flags;
+ internal IntPtr functions;
+ internal IntPtr decorations;
+ internal IntPtr input_mode;
+ internal IntPtr status;
+
+ public override string ToString ()
+ {
+ return string.Format("MotifWmHints _transientChildren = new HashSet();
+ private X11Window _transientParent;
+ public object SyncRoot { get; } = new object();
+
+ class InputEventContainer
+ {
+ public RawInputEventArgs Event;
+ }
+ private readonly Queue _inputQueue = new Queue();
+ private InputEventContainer _lastEvent;
+
+ public X11Window(AvaloniaX11Platform platform, bool popup)
+ {
+ _platform = platform;
+ _popup = popup;
+ _x11 = platform.Info;
+ _mouse = platform.MouseDevice;
+ _keyboard = platform.KeyboardDevice;
+ _xic = XCreateIC(_x11.Xim, XNames.XNInputStyle, XIMProperties.XIMPreeditNothing | XIMProperties.XIMStatusNothing,
+ XNames.XNClientWindow, _handle, IntPtr.Zero);
+
+ XSetWindowAttributes attr = new XSetWindowAttributes();
+ var valueMask = default(SetWindowValuemask);
+
+ attr.backing_store = 1;
+ attr.bit_gravity = Gravity.NorthWestGravity;
+ attr.win_gravity = Gravity.NorthWestGravity;
+ valueMask |= SetWindowValuemask.BackPixel | SetWindowValuemask.BorderPixel
+ | SetWindowValuemask.BackPixmap | SetWindowValuemask.BackingStore
+ | SetWindowValuemask.BitGravity | SetWindowValuemask.WinGravity;
+
+ if (popup)
+ {
+ attr.override_redirect = true;
+ valueMask |= SetWindowValuemask.OverrideRedirect;
+ }
+
+ _handle = XCreateWindow(_x11.Display, _x11.RootWindow, 10, 10, 300, 200, 0,
+ 24,
+ (int)CreateWindowArgs.InputOutput, IntPtr.Zero,
+ new UIntPtr((uint)valueMask), ref attr);
+ _renderHandle = XCreateWindow(_x11.Display, _handle, 0, 0, 300, 200, 0, 24,
+ (int)CreateWindowArgs.InputOutput,
+ IntPtr.Zero,
+ new UIntPtr((uint)(SetWindowValuemask.BorderPixel | SetWindowValuemask.BitGravity |
+ SetWindowValuemask.WinGravity | SetWindowValuemask.BackingStore)), ref attr);
+
+ Handle = new PlatformHandle(_handle, "XID");
+ _realSize = new PixelSize(300, 200);
+ platform.Windows[_handle] = OnEvent;
+ XEventMask ignoredMask = XEventMask.SubstructureRedirectMask
+ | XEventMask.ResizeRedirectMask
+ | XEventMask.PointerMotionHintMask;
+ if (platform.XI2 != null)
+ ignoredMask |= platform.XI2.AddWindow(_handle, this);
+ var mask = new IntPtr(0xffffff ^ (int)ignoredMask);
+ XSelectInput(_x11.Display, _handle, mask);
+ var protocols = new[]
+ {
+ _x11.Atoms.WM_DELETE_WINDOW
+ };
+ XSetWMProtocols(_x11.Display, _handle, protocols, protocols.Length);
+ XChangeProperty(_x11.Display, _handle, _x11.Atoms._NET_WM_WINDOW_TYPE, _x11.Atoms.XA_ATOM,
+ 32, PropertyMode.Replace, new[] {_x11.Atoms._NET_WM_WINDOW_TYPE_NORMAL}, 1);
+
+ var feature = (EglGlPlatformFeature)AvaloniaLocator.Current.GetService();
+ var surfaces = new List
diff --git a/tests/Avalonia.Interactivity.UnitTests/Avalonia.Interactivity.UnitTests.csproj b/tests/Avalonia.Interactivity.UnitTests/Avalonia.Interactivity.UnitTests.csproj
index bc883d0251..6b19d81034 100644
--- a/tests/Avalonia.Interactivity.UnitTests/Avalonia.Interactivity.UnitTests.csproj
+++ b/tests/Avalonia.Interactivity.UnitTests/Avalonia.Interactivity.UnitTests.csproj
@@ -1,9 +1,12 @@
netcoreapp2.0
+ netcoreapp2.0;net47
Library
+ true
+
@@ -20,4 +23,4 @@
-
\ No newline at end of file
+
diff --git a/tests/Avalonia.LeakTests/ControlTests.cs b/tests/Avalonia.LeakTests/ControlTests.cs
index 4dcd98cb93..b7aa452a18 100644
--- a/tests/Avalonia.LeakTests/ControlTests.cs
+++ b/tests/Avalonia.LeakTests/ControlTests.cs
@@ -348,6 +348,7 @@ namespace Avalonia.LeakTests
{
public bool DrawFps { get; set; }
public bool DrawDirtyRects { get; set; }
+ public event EventHandler SceneInvalidated;
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 1680ecf798..aba5f2d469 100644
--- a/tests/Avalonia.Markup.UnitTests/Avalonia.Markup.UnitTests.csproj
+++ b/tests/Avalonia.Markup.UnitTests/Avalonia.Markup.UnitTests.csproj
@@ -1,9 +1,11 @@
- netcoreapp2.0
+ netcoreapp2.0;net47
Library
+ true
+
@@ -23,4 +25,4 @@
-
\ No newline at end of file
+
diff --git a/tests/Avalonia.Markup.UnitTests/Data/BindingTests_Converters.cs b/tests/Avalonia.Markup.UnitTests/Data/BindingTests_Converters.cs
index 123aadfda5..1ede4ee0b0 100644
--- a/tests/Avalonia.Markup.UnitTests/Data/BindingTests_Converters.cs
+++ b/tests/Avalonia.Markup.UnitTests/Data/BindingTests_Converters.cs
@@ -22,14 +22,14 @@ namespace Avalonia.Markup.UnitTests.Data
var target = new Binding(nameof(Class1.Foo))
{
- Converter = StringConverters.NullOrEmpty,
+ Converter = StringConverters.IsNullOrEmpty,
};
var expressionObserver = (BindingExpression)target.Initiate(
textBlock,
TextBlock.TextProperty).Observable;
- Assert.Same(StringConverters.NullOrEmpty, expressionObserver.Converter);
+ Assert.Same(StringConverters.IsNullOrEmpty, expressionObserver.Converter);
}
public class When_Binding_To_String
@@ -129,7 +129,7 @@ namespace Avalonia.Markup.UnitTests.Data
var target = new Binding(nameof(Class1.Foo))
{
- Converter = StringConverters.NotNullOrEmpty,
+ Converter = StringConverters.IsNotNullOrEmpty,
StringFormat = "Hello {0}",
};
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 735d5c421a..8b47bcec30 100644
--- a/tests/Avalonia.Markup.Xaml.UnitTests/Avalonia.Markup.Xaml.UnitTests.csproj
+++ b/tests/Avalonia.Markup.Xaml.UnitTests/Avalonia.Markup.Xaml.UnitTests.csproj
@@ -1,9 +1,11 @@
- netcoreapp2.0
+ netcoreapp2.0;net47
Library
+ true
+
@@ -36,4 +38,4 @@
-
\ No newline at end of file
+
diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Converters/ConverterTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/Converters/ConverterTests.cs
new file mode 100644
index 0000000000..6ffaaaee5c
--- /dev/null
+++ b/tests/Avalonia.Markup.Xaml.UnitTests/Converters/ConverterTests.cs
@@ -0,0 +1,23 @@
+using System;
+using Xunit;
+
+namespace Avalonia.Markup.Xaml.UnitTests.Converters
+{
+ public class ConverterTests
+ {
+ [Fact]
+ public void Bug_2228_Relative_Uris_Should_Be_Correctly_Parsed()
+ {
+ var testClass = typeof(TestClassWithUri);
+ var parsed = AvaloniaXamlLoader.Parse(
+ $"<{testClass.Name} xmlns='clr-namespace:{testClass.Namespace}' Uri='/test'/>", testClass.Assembly);
+
+ Assert.False(parsed.Uri.IsAbsoluteUri);
+ }
+ }
+
+ public class TestClassWithUri
+ {
+ public Uri Uri { get; set; }
+ }
+}
diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Converters/NullableConverterTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/Converters/NullableConverterTests.cs
new file mode 100644
index 0000000000..abe6fa84b0
--- /dev/null
+++ b/tests/Avalonia.Markup.Xaml.UnitTests/Converters/NullableConverterTests.cs
@@ -0,0 +1,31 @@
+using Avalonia.Controls;
+using Avalonia.UnitTests;
+using Xunit;
+
+namespace Avalonia.Markup.Xaml.UnitTests.Converters
+{
+ public class ClassWithNullableProperties
+ {
+ public Thickness? Thickness { get; set; }
+ public Orientation? Orientation { get; set; }
+ }
+
+ public class NullableConverterTests
+ {
+ [Fact]
+ public void Nullable_Types_Should_Still_Be_Converted_Properly()
+ {
+ using (UnitTestApplication.Start(TestServices.MockPlatformWrapper))
+ {
+ var xaml = @"";
+ var loader = new AvaloniaXamlLoader();
+ var data = (ClassWithNullableProperties)loader.Load(xaml, typeof(ClassWithNullableProperties).Assembly);
+ Assert.Equal(new Thickness(5), data.Thickness);
+ Assert.Equal(Orientation.Vertical, data.Orientation);
+ }
+ }
+ }
+}
diff --git a/tests/Avalonia.RenderTests/Controls/BorderTests.cs b/tests/Avalonia.RenderTests/Controls/BorderTests.cs
index c82d616094..4f4004e159 100644
--- a/tests/Avalonia.RenderTests/Controls/BorderTests.cs
+++ b/tests/Avalonia.RenderTests/Controls/BorderTests.cs
@@ -188,7 +188,7 @@ namespace Avalonia.Direct2D1.RenderTests.Controls
}
- [Fact]
+ [Win32Fact("Has text")]
public async Task Border_Centers_Content_Horizontally()
{
Decorator target = new Decorator
@@ -215,7 +215,7 @@ namespace Avalonia.Direct2D1.RenderTests.Controls
CompareImages();
}
- [Fact]
+ [Win32Fact("Has text")]
public async Task Border_Centers_Content_Vertically()
{
Decorator target = new Decorator
@@ -296,7 +296,7 @@ namespace Avalonia.Direct2D1.RenderTests.Controls
CompareImages();
}
- [Fact]
+ [Win32Fact("Has text")]
public async Task Border_Left_Aligns_Content()
{
Decorator target = new Decorator
@@ -323,7 +323,7 @@ namespace Avalonia.Direct2D1.RenderTests.Controls
CompareImages();
}
- [Fact]
+ [Win32Fact("Has text")]
public async Task Border_Right_Aligns_Content()
{
Decorator target = new Decorator
@@ -350,7 +350,7 @@ namespace Avalonia.Direct2D1.RenderTests.Controls
CompareImages();
}
- [Fact]
+ [Win32Fact("Has text")]
public async Task Border_Top_Aligns_Content()
{
Decorator target = new Decorator
@@ -377,7 +377,7 @@ namespace Avalonia.Direct2D1.RenderTests.Controls
CompareImages();
}
- [Fact]
+ [Win32Fact("Has text")]
public async Task Border_Bottom_Aligns_Content()
{
Decorator target = new Decorator
diff --git a/tests/Avalonia.RenderTests/Controls/TextBlockTests.cs b/tests/Avalonia.RenderTests/Controls/TextBlockTests.cs
index 8a8ed4cb4a..14f6f78a8d 100644
--- a/tests/Avalonia.RenderTests/Controls/TextBlockTests.cs
+++ b/tests/Avalonia.RenderTests/Controls/TextBlockTests.cs
@@ -20,7 +20,7 @@ namespace Avalonia.Direct2D1.RenderTests.Controls
{
}
- [Fact]
+ [Win32Fact("Has text")]
public async Task Wrapping_NoWrap()
{
Decorator target = new Decorator
diff --git a/tests/Avalonia.RenderTests/TestBase.cs b/tests/Avalonia.RenderTests/TestBase.cs
index 4c8abd85f7..2efd28c2d5 100644
--- a/tests/Avalonia.RenderTests/TestBase.cs
+++ b/tests/Avalonia.RenderTests/TestBase.cs
@@ -46,6 +46,7 @@ namespace Avalonia.Direct2D1.RenderTests
public TestBase(string outputPath)
{
+ outputPath = outputPath.Replace('\\', Path.DirectorySeparatorChar);
var testPath = GetTestsDirectory();
var testFiles = Path.Combine(testPath, "TestFiles");
#if AVALONIA_SKIA
diff --git a/tests/Avalonia.RenderTests/TestSkip.cs b/tests/Avalonia.RenderTests/TestSkip.cs
new file mode 100644
index 0000000000..75407332e3
--- /dev/null
+++ b/tests/Avalonia.RenderTests/TestSkip.cs
@@ -0,0 +1,21 @@
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using Xunit;
+
+#if AVALONIA_SKIA
+namespace Avalonia.Skia.RenderTests
+#else
+namespace Avalonia.Direct2D1.RenderTests
+#endif
+{
+ public class Win32Fact : FactAttribute
+ {
+ public Win32Fact(string message)
+ {
+ if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ Skip = message;
+ }
+ }
+}
+
diff --git a/tests/Avalonia.Styling.UnitTests/Avalonia.Styling.UnitTests.csproj b/tests/Avalonia.Styling.UnitTests/Avalonia.Styling.UnitTests.csproj
index e65dd848dd..3fd280f7ab 100644
--- a/tests/Avalonia.Styling.UnitTests/Avalonia.Styling.UnitTests.csproj
+++ b/tests/Avalonia.Styling.UnitTests/Avalonia.Styling.UnitTests.csproj
@@ -1,10 +1,12 @@
- netcoreapp2.0
+ netcoreapp2.0;net47
Library
CS0067
+ true
+
@@ -23,4 +25,4 @@
-
\ No newline at end of file
+
diff --git a/tests/Avalonia.Styling.UnitTests/SelectorTests_Child.cs b/tests/Avalonia.Styling.UnitTests/SelectorTests_Child.cs
index d837f2cb2f..0561837ad1 100644
--- a/tests/Avalonia.Styling.UnitTests/SelectorTests_Child.cs
+++ b/tests/Avalonia.Styling.UnitTests/SelectorTests_Child.cs
@@ -27,7 +27,7 @@ namespace Avalonia.Styling.UnitTests
var selector = default(Selector).OfType().Child().OfType();
- Assert.True(selector.Match(child).ImmediateResult);
+ Assert.Equal(SelectorMatchResult.AlwaysThisInstance, selector.Match(child).Result);
}
[Fact]
@@ -42,7 +42,7 @@ namespace Avalonia.Styling.UnitTests
var selector = default(Selector).OfType().Child().OfType();
- Assert.False(selector.Match(child).ImmediateResult);
+ Assert.Equal(SelectorMatchResult.NeverThisInstance, selector.Match(child).Result);
}
[Fact]
@@ -54,7 +54,7 @@ namespace Avalonia.Styling.UnitTests
child.LogicalParent = parent;
var selector = default(Selector).OfType().Class("foo").Child().OfType();
- var activator = selector.Match(child).ObservableResult;
+ var activator = selector.Match(child).Activator;
var result = new List();
Assert.False(await activator.Take(1));
@@ -70,7 +70,7 @@ namespace Avalonia.Styling.UnitTests
var control = new TestLogical3();
var selector = default(Selector).OfType().Child().OfType();
- Assert.False(selector.Match(control).ImmediateResult);
+ Assert.Equal(SelectorMatchResult.NeverThisInstance, selector.Match(control).Result);
}
[Fact]
diff --git a/tests/Avalonia.Styling.UnitTests/SelectorTests_Class.cs b/tests/Avalonia.Styling.UnitTests/SelectorTests_Class.cs
index 75599925b7..496998ecd9 100644
--- a/tests/Avalonia.Styling.UnitTests/SelectorTests_Class.cs
+++ b/tests/Avalonia.Styling.UnitTests/SelectorTests_Class.cs
@@ -40,9 +40,10 @@ namespace Avalonia.Styling.UnitTests
};
var target = default(Selector).Class("foo");
- var activator = target.Match(control).ObservableResult;
+ var match = target.Match(control);
- Assert.True(await activator.Take(1));
+ Assert.Equal(SelectorMatchResult.Sometimes, match.Result);
+ Assert.True(await match.Activator.Take(1));
}
[Fact]
@@ -54,9 +55,10 @@ namespace Avalonia.Styling.UnitTests
};
var target = default(Selector).Class("foo");
- var activator = target.Match(control).ObservableResult;
+ var match = target.Match(control);
- Assert.False(await activator.Take(1));
+ Assert.Equal(SelectorMatchResult.Sometimes, match.Result);
+ Assert.False(await match.Activator.Take(1));
}
[Fact]
@@ -69,9 +71,10 @@ namespace Avalonia.Styling.UnitTests
};
var target = default(Selector).Class("foo");
- var activator = target.Match(control).ObservableResult;
+ var match = target.Match(control);
- Assert.True(await activator.Take(1));
+ Assert.Equal(SelectorMatchResult.Sometimes, match.Result);
+ Assert.True(await match.Activator.Take(1));
}
[Fact]
@@ -80,7 +83,7 @@ namespace Avalonia.Styling.UnitTests
var control = new Control1();
var target = default(Selector).Class("foo");
- var activator = target.Match(control).ObservableResult;
+ var activator = target.Match(control).Activator;
Assert.False(await activator.Take(1));
control.Classes.Add("foo");
@@ -96,7 +99,7 @@ namespace Avalonia.Styling.UnitTests
};
var target = default(Selector).Class("foo");
- var activator = target.Match(control).ObservableResult;
+ var activator = target.Match(control).Activator;
Assert.True(await activator.Take(1));
control.Classes.Remove("foo");
@@ -108,7 +111,7 @@ namespace Avalonia.Styling.UnitTests
{
var control = new Control1();
var target = default(Selector).Class("foo").Class("bar");
- var activator = target.Match(control).ObservableResult;
+ var activator = target.Match(control).Activator;
Assert.False(await activator.Take(1));
control.Classes.Add("foo");
@@ -129,7 +132,7 @@ namespace Avalonia.Styling.UnitTests
};
var target = default(Selector).Class("foo");
- var activator = target.Match(control).ObservableResult;
+ var activator = target.Match(control).Activator;
var result = new List();
using (activator.Subscribe(x => result.Add(x)))
diff --git a/tests/Avalonia.Styling.UnitTests/SelectorTests_Descendent.cs b/tests/Avalonia.Styling.UnitTests/SelectorTests_Descendent.cs
index b75b59c212..56dad13186 100644
--- a/tests/Avalonia.Styling.UnitTests/SelectorTests_Descendent.cs
+++ b/tests/Avalonia.Styling.UnitTests/SelectorTests_Descendent.cs
@@ -26,7 +26,7 @@ namespace Avalonia.Styling.UnitTests
var selector = default(Selector).OfType().Descendant().OfType();
- Assert.True(selector.Match(child).ImmediateResult);
+ Assert.Equal(SelectorMatchResult.AlwaysThisInstance, selector.Match(child).Result);
}
[Fact]
@@ -41,7 +41,7 @@ namespace Avalonia.Styling.UnitTests
var selector = default(Selector).OfType().Descendant().OfType();
- Assert.True(selector.Match(child).ImmediateResult);
+ Assert.Equal(SelectorMatchResult.AlwaysThisInstance, selector.Match(child).Result);
}
[Fact]
@@ -56,7 +56,7 @@ namespace Avalonia.Styling.UnitTests
child.LogicalParent = parent;
var selector = default(Selector).OfType().Class("foo").Descendant().OfType();
- var activator = selector.Match(child).ObservableResult;
+ var activator = selector.Match(child).Activator;
Assert.True(await activator.Take(1));
}
@@ -74,7 +74,7 @@ namespace Avalonia.Styling.UnitTests
child.LogicalParent = parent;
var selector = default(Selector).OfType().Class("foo").Descendant().OfType();
- var activator = selector.Match(child).ObservableResult;
+ var activator = selector.Match(child).Activator;
Assert.False(await activator.Take(1));
}
@@ -90,7 +90,7 @@ namespace Avalonia.Styling.UnitTests
child.LogicalParent = parent;
var selector = default(Selector).OfType().Class("foo").Descendant().OfType();
- var activator = selector.Match(child).ObservableResult;
+ var activator = selector.Match(child).Activator;
Assert.False(await activator.Take(1));
parent.Classes.Add("foo");
diff --git a/tests/Avalonia.Styling.UnitTests/SelectorTests_Multiple.cs b/tests/Avalonia.Styling.UnitTests/SelectorTests_Multiple.cs
index 067b08b296..ba9b443d92 100644
--- a/tests/Avalonia.Styling.UnitTests/SelectorTests_Multiple.cs
+++ b/tests/Avalonia.Styling.UnitTests/SelectorTests_Multiple.cs
@@ -14,7 +14,7 @@ namespace Avalonia.Styling.UnitTests
public class SelectorTests_Multiple
{
[Fact]
- public void Template_Child_Of_Control_With_Two_Classes()
+ public void Named_Template_Child_Of_Control_With_Two_Classes()
{
var template = new FuncControlTemplate(parent =>
{
@@ -40,9 +40,10 @@ namespace Avalonia.Styling.UnitTests
var border = (Border)((IVisual)control).VisualChildren.Single();
var values = new List();
- var activator = selector.Match(border).ObservableResult;
+ var match = selector.Match(border);
- activator.Subscribe(x => values.Add(x));
+ Assert.Equal(SelectorMatchResult.Sometimes, match.Result);
+ match.Activator.Subscribe(x => values.Add(x));
Assert.Equal(new[] { false }, values);
control.Classes.AddRange(new[] { "foo", "bar" });
@@ -51,6 +52,77 @@ namespace Avalonia.Styling.UnitTests
Assert.Equal(new[] { false, true, false }, values);
}
+ [Fact]
+ public void Named_OfType_Template_Child_Of_Control_With_Two_Classes_Wrong_Type()
+ {
+ var template = new FuncControlTemplate(parent =>
+ {
+ return new Border
+ {
+ Name = "border",
+ };
+ });
+
+ var control = new Button
+ {
+ Template = template,
+ };
+
+ control.ApplyTemplate();
+
+ var selector = default(Selector)
+ .OfType()
+ .Class("foo")
+ .Class("bar")
+ .Template()
+ .OfType()
+ .Name("baz");
+
+ var border = (Border)((IVisual)control).VisualChildren.Single();
+ var values = new List();
+ var match = selector.Match(border);
+
+ Assert.Equal(SelectorMatchResult.NeverThisType, match.Result);
+ }
+
+ [Fact]
+ public void Named_Class_Template_Child_Of_Control()
+ {
+ var template = new FuncControlTemplate(parent =>
+ {
+ return new Border
+ {
+ Name = "border",
+ };
+ });
+
+ var control = new Button
+ {
+ Template = template,
+ };
+
+ control.ApplyTemplate();
+
+ var selector = default(Selector)
+ .OfType()
+ .Template()
+ .Name("border")
+ .Class("foo");
+
+ var border = (Border)((IVisual)control).VisualChildren.Single();
+ var values = new List();
+ var match = selector.Match(border);
+
+ Assert.Equal(SelectorMatchResult.Sometimes, match.Result);
+ match.Activator.Subscribe(x => values.Add(x));
+
+ Assert.Equal(new[] { false }, values);
+ border.Classes.AddRange(new[] { "foo" });
+ Assert.Equal(new[] { false, true }, values);
+ border.Classes.Remove("foo");
+ Assert.Equal(new[] { false, true, false }, values);
+ }
+
[Fact]
public void TargetType_OfType()
{
diff --git a/tests/Avalonia.Styling.UnitTests/SelectorTests_Name.cs b/tests/Avalonia.Styling.UnitTests/SelectorTests_Name.cs
index cb85e0adb0..1c8a3a406e 100644
--- a/tests/Avalonia.Styling.UnitTests/SelectorTests_Name.cs
+++ b/tests/Avalonia.Styling.UnitTests/SelectorTests_Name.cs
@@ -14,7 +14,7 @@ namespace Avalonia.Styling.UnitTests
var control = new Control1 { Name = "foo" };
var target = default(Selector).Name("foo");
- Assert.True(target.Match(control).ImmediateResult);
+ Assert.Equal(SelectorMatchResult.AlwaysThisInstance, target.Match(control).Result);
}
[Fact]
@@ -23,7 +23,7 @@ namespace Avalonia.Styling.UnitTests
var control = new Control1 { Name = "foo" };
var target = default(Selector).Name("bar");
- Assert.False(target.Match(control).ImmediateResult);
+ Assert.Equal(SelectorMatchResult.NeverThisInstance, target.Match(control).Result);
}
[Fact]
@@ -33,7 +33,7 @@ namespace Avalonia.Styling.UnitTests
var target = default(Selector).Name("foo");
var activator = target.Match(control);
- Assert.False(target.Match(control).ImmediateResult);
+ Assert.Equal(SelectorMatchResult.NeverThisInstance, target.Match(control).Result);
}
[Fact]
diff --git a/tests/Avalonia.Styling.UnitTests/SelectorTests_OfType.cs b/tests/Avalonia.Styling.UnitTests/SelectorTests_OfType.cs
index e413e70b2a..05f3544366 100644
--- a/tests/Avalonia.Styling.UnitTests/SelectorTests_OfType.cs
+++ b/tests/Avalonia.Styling.UnitTests/SelectorTests_OfType.cs
@@ -14,7 +14,7 @@ namespace Avalonia.Styling.UnitTests
var control = new Control1();
var target = default(Selector).OfType();
- Assert.True(target.Match(control).ImmediateResult);
+ Assert.Equal(SelectorMatchResult.AlwaysThisType, target.Match(control).Result);
}
[Fact]
@@ -23,7 +23,16 @@ namespace Avalonia.Styling.UnitTests
var control = new Control2();
var target = default(Selector).OfType();
- Assert.False(target.Match(control).ImmediateResult);
+ Assert.Equal(SelectorMatchResult.NeverThisType, target.Match(control).Result);
+ }
+
+ [Fact]
+ public void OfType_Class_Doesnt_Match_Control_Of_Wrong_Type()
+ {
+ var control = new Control2();
+ var target = default(Selector).OfType().Class("foo");
+
+ Assert.Equal(SelectorMatchResult.NeverThisType, target.Match(control).Result);
}
[Fact]
@@ -32,7 +41,7 @@ namespace Avalonia.Styling.UnitTests
var control = new Control1 { TemplatedParent = new Mock().Object };
var target = default(Selector).OfType();
- Assert.True(target.Match(control).ImmediateResult);
+ Assert.Equal(SelectorMatchResult.AlwaysThisType, target.Match(control).Result);
}
public class Control1 : TestControlBase
diff --git a/tests/Avalonia.Styling.UnitTests/SelectorTests_PropertyEquals.cs b/tests/Avalonia.Styling.UnitTests/SelectorTests_PropertyEquals.cs
index f90d124f2a..e1fb479e5c 100644
--- a/tests/Avalonia.Styling.UnitTests/SelectorTests_PropertyEquals.cs
+++ b/tests/Avalonia.Styling.UnitTests/SelectorTests_PropertyEquals.cs
@@ -16,7 +16,7 @@ namespace Avalonia.Styling.UnitTests
{
var control = new TextBlock();
var target = default(Selector).PropertyEquals(TextBlock.TextProperty, "foo");
- var activator = target.Match(control).ObservableResult;
+ var activator = target.Match(control).Activator;
Assert.False(await activator.Take(1));
control.Text = "foo";
@@ -25,6 +25,15 @@ namespace Avalonia.Styling.UnitTests
Assert.False(await activator.Take(1));
}
+ [Fact]
+ public void OfType_PropertyEquals_Doesnt_Match_Control_Of_Wrong_Type()
+ {
+ var control = new TextBlock();
+ var target = default(Selector).OfType().PropertyEquals(TextBlock.TextProperty, "foo");
+
+ Assert.Equal(SelectorMatchResult.NeverThisType, target.Match(control).Result);
+ }
+
[Fact]
public void PropertyEquals_Selector_Should_Have_Correct_String_Representation()
{
diff --git a/tests/Avalonia.Styling.UnitTests/SelectorTests_Template.cs b/tests/Avalonia.Styling.UnitTests/SelectorTests_Template.cs
index 5c34479eb2..c446902563 100644
--- a/tests/Avalonia.Styling.UnitTests/SelectorTests_Template.cs
+++ b/tests/Avalonia.Styling.UnitTests/SelectorTests_Template.cs
@@ -29,7 +29,7 @@ namespace Avalonia.Styling.UnitTests
.Template()
.OfType();
- Assert.True(selector.Match(border).ImmediateResult);
+ Assert.Equal(SelectorMatchResult.AlwaysThisInstance, selector.Match(border).Result);
}
[Fact]
@@ -47,7 +47,24 @@ namespace Avalonia.Styling.UnitTests
.Template()
.OfType();
- Assert.False(selector.Match(border).ImmediateResult);
+ Assert.Equal(SelectorMatchResult.NeverThisInstance, selector.Match(border).Result);
+ }
+
+ [Fact]
+ public void Control_In_Template_Of_Wrong_Type_Is_Not_Matched_With_Template_Selector()
+ {
+ var target = new Mock();
+ var templatedControl = target.As();
+ var styleable = target.As();
+ BuildVisualTree(target);
+
+ var border = (Border)target.Object.GetVisualChildren().Single();
+ var selector = default(Selector)
+ .OfType()
+ .Template()
+ .OfType();
+
+ Assert.Equal(SelectorMatchResult.NeverThisInstance, selector.Match(border).Result);
}
[Fact]
@@ -64,7 +81,7 @@ namespace Avalonia.Styling.UnitTests
.Template()
.OfType();
- Assert.True(selector.Match(textBlock).ImmediateResult);
+ Assert.Equal(SelectorMatchResult.AlwaysThisInstance, selector.Match(textBlock).Result);
}
[Fact]
@@ -80,7 +97,7 @@ namespace Avalonia.Styling.UnitTests
var selector = default(Selector).OfType(styleKey).Template().OfType();
- Assert.True(selector.Match(border).ImmediateResult);
+ Assert.Equal(SelectorMatchResult.AlwaysThisInstance, selector.Match(border).Result);
}
[Fact]
@@ -96,7 +113,7 @@ namespace Avalonia.Styling.UnitTests
styleable.Setup(x => x.Classes).Returns(new Classes("foo"));
var border = (Border)target.Object.VisualChildren.Single();
var selector = default(Selector).OfType(styleKey).Class("foo").Template().OfType();
- var activator = selector.Match(border).ObservableResult;
+ var activator = selector.Match(border).Activator;
Assert.True(await activator.Take(1));
}
@@ -112,7 +129,7 @@ namespace Avalonia.Styling.UnitTests
styleable.Setup(x => x.Classes).Returns(new Classes("bar"));
var border = (Border)target.Object.VisualChildren.Single();
var selector = default(Selector).OfType(templatedControl.Object.GetType()).Class("foo").Template().OfType();
- var activator = selector.Match(border).ObservableResult;
+ var activator = selector.Match(border).Activator;
Assert.False(await activator.Take(1));
}
@@ -128,7 +145,7 @@ namespace Avalonia.Styling.UnitTests
styleable.Setup(x => x.Classes).Returns(new Classes("foo"));
var border = (Border)target.Object.VisualChildren.Single();
var selector = default(Selector).OfType(templatedControl.Object.GetType()).Class("foo").Template().OfType();
- var activator = selector.Match(border).ObservableResult;
+ var activator = selector.Match(border).Activator;
var inccDebug = (INotifyCollectionChangedDebug)styleable.Object.Classes;
using (activator.Subscribe(_ => { }))
diff --git a/tests/Avalonia.UnitTests/MockPlatformRenderInterface.cs b/tests/Avalonia.UnitTests/MockPlatformRenderInterface.cs
index f8ad7e63f2..0e2abb314d 100644
--- a/tests/Avalonia.UnitTests/MockPlatformRenderInterface.cs
+++ b/tests/Avalonia.UnitTests/MockPlatformRenderInterface.cs
@@ -9,6 +9,8 @@ namespace Avalonia.UnitTests
{
public class MockPlatformRenderInterface : IPlatformRenderInterface
{
+ public IEnumerable InstalledFontNames => new string[0];
+
public IFormattedTextImpl CreateFormattedText(
string text,
Typeface typeface,
diff --git a/tests/Avalonia.UnitTests/TestRoot.cs b/tests/Avalonia.UnitTests/TestRoot.cs
index 972b1d78c0..370ddba410 100644
--- a/tests/Avalonia.UnitTests/TestRoot.cs
+++ b/tests/Avalonia.UnitTests/TestRoot.cs
@@ -90,9 +90,9 @@ namespace Avalonia.UnitTests
{
}
- public Point PointToClient(Point p) => p;
+ public Point PointToClient(PixelPoint p) => p.ToPoint(1);
- public Point PointToScreen(Point p) => p;
+ public PixelPoint PointToScreen(Point p) => PixelPoint.FromPoint(p, 1);
void INameScope.Register(string name, object element)
{
diff --git a/tests/Avalonia.UnitTests/TestTemplatedRoot.cs b/tests/Avalonia.UnitTests/TestTemplatedRoot.cs
index 2d896435a3..5d42699d3f 100644
--- a/tests/Avalonia.UnitTests/TestTemplatedRoot.cs
+++ b/tests/Avalonia.UnitTests/TestTemplatedRoot.cs
@@ -57,9 +57,9 @@ namespace Avalonia.UnitTests
throw new NotImplementedException();
}
- public Point PointToClient(Point p) => p;
+ public Point PointToClient(PixelPoint p) => p.ToPoint(1);
- public Point PointToScreen(Point p) => p;
+ public PixelPoint PointToScreen(Point p) => PixelPoint.FromPoint(p, 1);
void INameScope.Register(string name, object element)
{
diff --git a/tests/Avalonia.Visuals.UnitTests/Avalonia.Visuals.UnitTests.csproj b/tests/Avalonia.Visuals.UnitTests/Avalonia.Visuals.UnitTests.csproj
index 2b559c9c56..50c2e580b0 100644
--- a/tests/Avalonia.Visuals.UnitTests/Avalonia.Visuals.UnitTests.csproj
+++ b/tests/Avalonia.Visuals.UnitTests/Avalonia.Visuals.UnitTests.csproj
@@ -1,8 +1,11 @@
- netcoreapp2.0
+ netcoreapp2.0;net47
+ Library
+ true
+
@@ -21,4 +24,4 @@
-
\ No newline at end of file
+
diff --git a/tests/Avalonia.Visuals.UnitTests/Media/Fonts/FontFamilyKeyTests.cs b/tests/Avalonia.Visuals.UnitTests/Media/Fonts/FontFamilyKeyTests.cs
index 96464b5784..b57ba781ed 100644
--- a/tests/Avalonia.Visuals.UnitTests/Media/Fonts/FontFamilyKeyTests.cs
+++ b/tests/Avalonia.Visuals.UnitTests/Media/Fonts/FontFamilyKeyTests.cs
@@ -22,9 +22,7 @@ namespace Avalonia.Visuals.UnitTests.Media.Fonts
var fontFamilyKey = new FontFamilyKey(source);
- Assert.Equal(new Uri("resm:Avalonia.Visuals.UnitTests"), fontFamilyKey.Location);
-
- Assert.Null(fontFamilyKey.FileName);
+ Assert.Equal(new Uri("resm:Avalonia.Visuals.UnitTests"), fontFamilyKey.Source);
}
[Fact]
@@ -34,9 +32,7 @@ namespace Avalonia.Visuals.UnitTests.Media.Fonts
var fontFamilyKey = new FontFamilyKey(source);
- Assert.Equal(new Uri("resm:Avalonia.Visuals.UnitTests"), fontFamilyKey.Location);
-
- Assert.Equal("MyFont.ttf", fontFamilyKey.FileName);
+ Assert.Equal(new Uri("resm:Avalonia.Visuals.UnitTests.MyFont.ttf"), fontFamilyKey.Source);
}
}
}
diff --git a/tests/Avalonia.Visuals.UnitTests/Rendering/ImmediateRendererTests.cs b/tests/Avalonia.Visuals.UnitTests/Rendering/ImmediateRendererTests.cs
index 82294246b1..73e4a14539 100644
--- a/tests/Avalonia.Visuals.UnitTests/Rendering/ImmediateRendererTests.cs
+++ b/tests/Avalonia.Visuals.UnitTests/Rendering/ImmediateRendererTests.cs
@@ -1,8 +1,11 @@
using System.Collections.Generic;
using Avalonia.Collections;
+using Avalonia.Controls;
+using Avalonia.Layout;
using Avalonia.Media;
using Avalonia.Platform;
using Avalonia.Rendering;
+using Avalonia.UnitTests;
using Avalonia.VisualTree;
using Moq;
using Xunit;
@@ -94,5 +97,86 @@ namespace Avalonia.Visuals.UnitTests.Rendering
//then new position
Assert.Equal(new Rect(100, 100, 100, 100), invalidationCalls[2]);
}
+
+ [Fact]
+ public void Should_Render_Child_In_Parent_With_RenderTransform()
+ {
+ var targetMock = new Mock() { CallBase = true };
+ var target = targetMock.Object;
+ target.Width = 100;
+ target.Height = 50;
+ var child = new Panel()
+ {
+ RenderTransform = new RotateTransform() { Angle = 90 },
+ Children =
+ {
+ new Panel()
+ {
+ Children =
+ {
+ target
+ }
+ }
+ }
+ };
+
+ var visualTarget = targetMock.As();
+ int rendered = 0;
+ visualTarget.Setup(v => v.Render(It.IsAny())).Callback(() => rendered++);
+
+ var root = new TestRoot(child);
+ root.Renderer = new ImmediateRenderer(root);
+
+ root.LayoutManager.ExecuteInitialLayoutPass(root);
+
+ root.Measure(new Size(50, 100));
+ root.Arrange(new Rect(new Size(50, 100)));
+
+ root.Renderer.Paint(root.Bounds);
+
+ Assert.Equal(1, rendered);
+ }
+
+ [Fact]
+ public void Should_Render_Child_In_Parent_With_RenderTransform2()
+ {
+ var targetMock = new Mock() { CallBase = true };
+ var target = targetMock.Object;
+
+ target.Width = 100;
+ target.Height = 50;
+ target.HorizontalAlignment = HorizontalAlignment.Center;
+ target.VerticalAlignment = VerticalAlignment.Center;
+
+ var child = new Panel()
+ {
+ RenderTransform = new RotateTransform() { Angle = 90 },
+ Children =
+ {
+ new Panel()
+ {
+ Children =
+ {
+ target
+ }
+ }
+ }
+ };
+
+ var visualTarget = targetMock.As();
+ int rendered = 0;
+ visualTarget.Setup(v => v.Render(It.IsAny())).Callback(() => rendered++);
+
+ var root = new TestRoot(child);
+ root.Renderer = new ImmediateRenderer(root);
+
+ root.LayoutManager.ExecuteInitialLayoutPass(root);
+
+ root.Measure(new Size(300, 100));
+ root.Arrange(new Rect(new Size(300, 100)));
+ root.Renderer.Paint(root.Bounds);
+
+ Assert.Equal(1, rendered);
+ }
}
}
diff --git a/tests/Avalonia.Visuals.UnitTests/VisualTree/MockRenderInterface.cs b/tests/Avalonia.Visuals.UnitTests/VisualTree/MockRenderInterface.cs
index 92c12c6b9e..fec0f0831a 100644
--- a/tests/Avalonia.Visuals.UnitTests/VisualTree/MockRenderInterface.cs
+++ b/tests/Avalonia.Visuals.UnitTests/VisualTree/MockRenderInterface.cs
@@ -8,6 +8,8 @@ namespace Avalonia.Visuals.UnitTests.VisualTree
{
class MockRenderInterface : IPlatformRenderInterface
{
+ public IEnumerable InstalledFontNames => new string[0];
+
public IFormattedTextImpl CreateFormattedText(
string text,
Typeface typeface,
diff --git a/tools/packages.config b/tools/packages.config
deleted file mode 100644
index 05018882e8..0000000000
--- a/tools/packages.config
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-