diff --git a/.gitignore b/.gitignore
index d16287cfb4..d965a09574 100644
--- a/.gitignore
+++ b/.gitignore
@@ -161,3 +161,5 @@ tools/
.nuget
artifacts/
nuget
+Avalonia.XBuild.sln
+project.lock.json
diff --git a/Avalonia.sln b/Avalonia.sln
index 241ba1383c..4e897b86c7 100644
--- a/Avalonia.sln
+++ b/Avalonia.sln
@@ -128,6 +128,9 @@ EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCatalog", "samples\ControlCatalog\ControlCatalog.csproj", "{D0A739B9-3C68-4BA6-A328-41606954B6BD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCatalog.Desktop", "samples\ControlCatalog.Desktop\ControlCatalog.Desktop.csproj", "{2B888490-D14A-4BCA-AB4B-48676FA93C9B}"
+ ProjectSection(ProjectDependencies) = postProject
+ {BB1F7BB5-6AD4-4776-94D9-C09D0A972658} = {BB1F7BB5-6AD4-4776-94D9-C09D0A972658}
+ EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCatalog.iOS", "samples\ControlCatalog.iOS\ControlCatalog.iOS.csproj", "{57E0455D-D565-44BB-B069-EE1AA20F8337}"
EndProject
@@ -153,19 +156,35 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RenderTest", "samples\Rende
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCatalog.Android", "samples\ControlCatalog.Android\ControlCatalog.Android.csproj", "{29132311-1848-4FD6-AE0C-4FF841151BD3}"
EndProject
+Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Avalonia.Win32.Shared", "src\Windows\Avalonia.Win32\Avalonia.Win32.Shared.shproj", "{9DEFC6B7-845B-4D8F-AFC0-D32BF0032B8C}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Win32.NetStandard", "src\Windows\Avalonia.Win32.NetStandard\Avalonia.Win32.NetStandard.csproj", "{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.DotNetCoreRuntime", "src\Avalonia.DotNetCoreRuntime\Avalonia.DotNetCoreRuntime.csproj", "{7863EA94-F0FB-4386-BF8C-E5BFA761560A}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Skia.Desktop.NetStandard", "src\Skia\Avalonia.Skia.Desktop.NetStandard\Avalonia.Skia.Desktop.NetStandard.csproj", "{7D2D3083-71DD-4CC9-8907-39A0D86FB322}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Gtk3", "src\Gtk\Avalonia.Gtk3\Avalonia.Gtk3.csproj", "{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}"
+EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
src\Skia\Avalonia.Skia\Avalonia.Skia.projitems*{2f59f3d0-748d-4652-b01e-e0d954756308}*SharedItemsImports = 13
src\Shared\RenderHelpers\RenderHelpers.projitems*{3c4c0cb4-0c0f-4450-a37b-148c84ff905f}*SharedItemsImports = 13
src\Shared\RenderHelpers\RenderHelpers.projitems*{3e908f67-5543-4879-a1dc-08eace79b3cd}*SharedItemsImports = 4
+ src\Windows\Avalonia.Win32\Avalonia.Win32.Shared.projitems*{40759a76-d0f2-464e-8000-6ff0f5c4bd7c}*SharedItemsImports = 4
src\Shared\PlatformSupport\PlatformSupport.projitems*{4488ad85-1495-4809-9aa4-ddfe0a48527e}*SharedItemsImports = 4
src\Shared\RenderHelpers\RenderHelpers.projitems*{47be08a7-5985-410b-9ffc-2264b8ea595f}*SharedItemsImports = 4
src\Skia\Avalonia.Skia\Avalonia.Skia.projitems*{47be08a7-5985-410b-9ffc-2264b8ea595f}*SharedItemsImports = 4
tests\Avalonia.RenderTests\Avalonia.RenderTests.projitems*{48840edd-24bf-495d-911e-2eb12ae75d3b}*SharedItemsImports = 13
src\Shared\PlatformSupport\PlatformSupport.projitems*{4a1abb09-9047-4bd5-a4ad-a055e52c5ee0}*SharedItemsImports = 4
+ src\Shared\PlatformSupport\PlatformSupport.projitems*{7863ea94-f0fb-4386-bf8c-e5bfa761560a}*SharedItemsImports = 4
src\Shared\PlatformSupport\PlatformSupport.projitems*{7b92af71-6287-4693-9dcb-bd5b6e927e23}*SharedItemsImports = 4
+ src\Shared\RenderHelpers\RenderHelpers.projitems*{7d2d3083-71dd-4cc9-8907-39a0d86fb322}*SharedItemsImports = 4
+ src\Skia\Avalonia.Skia\Avalonia.Skia.projitems*{7d2d3083-71dd-4cc9-8907-39a0d86fb322}*SharedItemsImports = 4
+ src\Windows\Avalonia.Win32\Avalonia.Win32.Shared.projitems*{811a76cf-1cf6-440f-963b-bbe31bd72a82}*SharedItemsImports = 4
src\Shared\RenderHelpers\RenderHelpers.projitems*{925dd807-b651-475f-9f7c-cbeb974ce43d}*SharedItemsImports = 4
src\Skia\Avalonia.Skia\Avalonia.Skia.projitems*{925dd807-b651-475f-9f7c-cbeb974ce43d}*SharedItemsImports = 4
+ src\Windows\Avalonia.Win32\Avalonia.Win32.Shared.projitems*{9defc6b7-845b-4d8f-afc0-d32bf0032b8c}*SharedItemsImports = 13
src\Shared\RenderHelpers\RenderHelpers.projitems*{bd43f7c0-396b-4aa1-bad9-dfde54d51298}*SharedItemsImports = 4
src\Skia\Avalonia.Skia\Avalonia.Skia.projitems*{bd43f7c0-396b-4aa1-bad9-dfde54d51298}*SharedItemsImports = 4
tests\Avalonia.RenderTests\Avalonia.RenderTests.projitems*{d35a9f3d-8bb0-496e-bf72-444038a7debb}*SharedItemsImports = 4
@@ -2295,6 +2314,164 @@ Global
{29132311-1848-4FD6-AE0C-4FF841151BD3}.Release|x86.ActiveCfg = Release|Any CPU
{29132311-1848-4FD6-AE0C-4FF841151BD3}.Release|x86.Build.0 = Release|Any CPU
{29132311-1848-4FD6-AE0C-4FF841151BD3}.Release|x86.Deploy.0 = Release|Any CPU
+ {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
+ {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
+ {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
+ {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU
+ {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU
+ {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Ad-Hoc|Mono.ActiveCfg = Release|Any CPU
+ {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Ad-Hoc|Mono.Build.0 = Release|Any CPU
+ {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU
+ {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Ad-Hoc|x86.Build.0 = Release|Any CPU
+ {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
+ {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.AppStore|Any CPU.Build.0 = Release|Any CPU
+ {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.AppStore|iPhone.ActiveCfg = Release|Any CPU
+ {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.AppStore|iPhone.Build.0 = Release|Any CPU
+ {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU
+ {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.AppStore|Mono.ActiveCfg = Release|Any CPU
+ {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.AppStore|Mono.Build.0 = Release|Any CPU
+ {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.AppStore|x86.ActiveCfg = Release|Any CPU
+ {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.AppStore|x86.Build.0 = Release|Any CPU
+ {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Debug|Mono.ActiveCfg = Debug|Any CPU
+ {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Debug|x86.Build.0 = Debug|Any CPU
+ {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Release|iPhone.Build.0 = Release|Any CPU
+ {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Release|Mono.ActiveCfg = Release|Any CPU
+ {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Release|x86.ActiveCfg = Release|Any CPU
+ {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Release|x86.Build.0 = Release|Any CPU
+ {7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
+ {7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
+ {7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
+ {7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU
+ {7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU
+ {7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Ad-Hoc|Mono.ActiveCfg = Release|Any CPU
+ {7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Ad-Hoc|Mono.Build.0 = Release|Any CPU
+ {7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU
+ {7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Ad-Hoc|x86.Build.0 = Release|Any CPU
+ {7863EA94-F0FB-4386-BF8C-E5BFA761560A}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
+ {7863EA94-F0FB-4386-BF8C-E5BFA761560A}.AppStore|Any CPU.Build.0 = Release|Any CPU
+ {7863EA94-F0FB-4386-BF8C-E5BFA761560A}.AppStore|iPhone.ActiveCfg = Release|Any CPU
+ {7863EA94-F0FB-4386-BF8C-E5BFA761560A}.AppStore|iPhone.Build.0 = Release|Any CPU
+ {7863EA94-F0FB-4386-BF8C-E5BFA761560A}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {7863EA94-F0FB-4386-BF8C-E5BFA761560A}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU
+ {7863EA94-F0FB-4386-BF8C-E5BFA761560A}.AppStore|Mono.ActiveCfg = Release|Any CPU
+ {7863EA94-F0FB-4386-BF8C-E5BFA761560A}.AppStore|Mono.Build.0 = Release|Any CPU
+ {7863EA94-F0FB-4386-BF8C-E5BFA761560A}.AppStore|x86.ActiveCfg = Release|Any CPU
+ {7863EA94-F0FB-4386-BF8C-E5BFA761560A}.AppStore|x86.Build.0 = Release|Any CPU
+ {7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Debug|Mono.ActiveCfg = Debug|Any CPU
+ {7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Debug|Mono.Build.0 = Debug|Any CPU
+ {7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Debug|x86.Build.0 = Debug|Any CPU
+ {7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Release|iPhone.Build.0 = Release|Any CPU
+ {7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Release|Mono.ActiveCfg = Release|Any CPU
+ {7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Release|Mono.Build.0 = Release|Any CPU
+ {7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Release|x86.ActiveCfg = Release|Any CPU
+ {7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Release|x86.Build.0 = Release|Any CPU
+ {7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
+ {7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
+ {7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
+ {7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU
+ {7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU
+ {7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Ad-Hoc|Mono.ActiveCfg = Release|Any CPU
+ {7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Ad-Hoc|Mono.Build.0 = Release|Any CPU
+ {7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU
+ {7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Ad-Hoc|x86.Build.0 = Release|Any CPU
+ {7D2D3083-71DD-4CC9-8907-39A0D86FB322}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
+ {7D2D3083-71DD-4CC9-8907-39A0D86FB322}.AppStore|Any CPU.Build.0 = Release|Any CPU
+ {7D2D3083-71DD-4CC9-8907-39A0D86FB322}.AppStore|iPhone.ActiveCfg = Release|Any CPU
+ {7D2D3083-71DD-4CC9-8907-39A0D86FB322}.AppStore|iPhone.Build.0 = Release|Any CPU
+ {7D2D3083-71DD-4CC9-8907-39A0D86FB322}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {7D2D3083-71DD-4CC9-8907-39A0D86FB322}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU
+ {7D2D3083-71DD-4CC9-8907-39A0D86FB322}.AppStore|Mono.ActiveCfg = Release|Any CPU
+ {7D2D3083-71DD-4CC9-8907-39A0D86FB322}.AppStore|Mono.Build.0 = Release|Any CPU
+ {7D2D3083-71DD-4CC9-8907-39A0D86FB322}.AppStore|x86.ActiveCfg = Release|Any CPU
+ {7D2D3083-71DD-4CC9-8907-39A0D86FB322}.AppStore|x86.Build.0 = Release|Any CPU
+ {7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Debug|Mono.ActiveCfg = Debug|Any CPU
+ {7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Debug|Mono.Build.0 = Debug|Any CPU
+ {7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Debug|x86.Build.0 = Debug|Any CPU
+ {7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Release|iPhone.Build.0 = Release|Any CPU
+ {7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Release|Mono.ActiveCfg = Release|Any CPU
+ {7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Release|Mono.Build.0 = Release|Any CPU
+ {7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Release|x86.ActiveCfg = Release|Any CPU
+ {7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Release|x86.Build.0 = Release|Any CPU
+ {BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
+ {BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
+ {BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
+ {BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU
+ {BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU
+ {BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Ad-Hoc|Mono.ActiveCfg = Release|Any CPU
+ {BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Ad-Hoc|Mono.Build.0 = Release|Any CPU
+ {BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU
+ {BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Ad-Hoc|x86.Build.0 = Release|Any CPU
+ {BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
+ {BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.AppStore|Any CPU.Build.0 = Release|Any CPU
+ {BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.AppStore|iPhone.ActiveCfg = Release|Any CPU
+ {BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.AppStore|iPhone.Build.0 = Release|Any CPU
+ {BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU
+ {BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.AppStore|Mono.ActiveCfg = Release|Any CPU
+ {BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.AppStore|Mono.Build.0 = Release|Any CPU
+ {BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.AppStore|x86.ActiveCfg = Release|Any CPU
+ {BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.AppStore|x86.Build.0 = Release|Any CPU
+ {BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Debug|Mono.ActiveCfg = Debug|Any CPU
+ {BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Debug|Mono.Build.0 = Debug|Any CPU
+ {BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Debug|x86.Build.0 = Debug|Any CPU
+ {BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Release|iPhone.Build.0 = Release|Any CPU
+ {BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Release|Mono.ActiveCfg = Release|Any CPU
+ {BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Release|Mono.Build.0 = Release|Any CPU
+ {BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Release|x86.ActiveCfg = Release|Any CPU
+ {BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -2347,5 +2524,9 @@ Global
{BD7F352C-6DC1-4740-BAF2-2D34A038728C} = {A0CC0258-D18C-4AB3-854F-7101680FC3F9}
{F1FDC5B0-4654-416F-AE69-E3E9BBD87801} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{29132311-1848-4FD6-AE0C-4FF841151BD3} = {9B9E3891-2366-4253-A952-D08BCEB71098}
+ {9DEFC6B7-845B-4D8F-AFC0-D32BF0032B8C} = {B39A8919-9F95-48FE-AD7B-76E08B509888}
+ {40759A76-D0F2-464E-8000-6FF0F5C4BD7C} = {B39A8919-9F95-48FE-AD7B-76E08B509888}
+ {7D2D3083-71DD-4CC9-8907-39A0D86FB322} = {3743B0F2-CC41-4F14-A8C8-267F579BF91E}
+ {BB1F7BB5-6AD4-4776-94D9-C09D0A972658} = {B9894058-278A-46B5-B6ED-AD613FCC03B3}
EndGlobalSection
EndGlobal
diff --git a/build.cake b/build.cake
index a4be2dc9e0..aa76c806ea 100644
--- a/build.cake
+++ b/build.cake
@@ -42,7 +42,7 @@ var AssemblyInfoPath = File("./src/Shared/SharedAssemblyInfo.cs");
var ReleasePlatform = "Any CPU";
var ReleaseConfiguration = "Release";
var MSBuildSolution = "./Avalonia.sln";
-var XBuildSolution = "./Avalonia.sln";
+var XBuildSolution = "./Avalonia.XBuild.sln";
///////////////////////////////////////////////////////////////////////////////
// PARAMETERS
@@ -69,7 +69,7 @@ var isNuGetRelease = isTagged && isReleasable;
// VERSION
///////////////////////////////////////////////////////////////////////////////
-var version = ParseAssemblyInfo(AssemblyInfoPath).AssemblyVersion;
+var version = Argument("force-nuget-version", ParseAssemblyInfo(AssemblyInfoPath).AssemblyVersion);
if (isRunningOnAppVeyor)
{
@@ -115,7 +115,9 @@ var buildDirs =
(DirectoryPath)Directory("./src/Skia/Avalonia.Skia.Android.TestApp/bin/" + dirSuffix) +
(DirectoryPath)Directory("./src/Skia/Avalonia.Skia.Android.TestApp/obj/" + dirSuffix) +
(DirectoryPath)Directory("./src/Skia/Avalonia.Skia.Desktop/bin/" + dirSuffixSkia) +
- (DirectoryPath)Directory("./src/Skia/Avalonia.Skia.Desktop/obj/" + dirSuffixSkia) +
+ (DirectoryPath)Directory("./src/Skia/Avalonia.Skia.Desktop/obj/" + dirSuffixSkia) +
+ (DirectoryPath)Directory("./src/Skia/Avalonia.Skia.Desktop.NetStandard/bin/" + dirSuffix) +
+ (DirectoryPath)Directory("./src/Skia/Avalonia.Skia.Desktop.NetStandard/obj/" + dirSuffix) +
(DirectoryPath)Directory("./src/Skia/Avalonia.Skia.iOS/bin/" + dirSuffixIOS) +
(DirectoryPath)Directory("./src/Skia/Avalonia.Skia.iOS/obj/" + dirSuffixIOS) +
(DirectoryPath)Directory("./src/Skia/Avalonia.Skia.iOS.TestApp/bin/" + dirSuffixIOS) +
@@ -273,6 +275,12 @@ var win32CoreLibrariesNuSpecContent = coreLibrariesFiles.Select((file) => {
};
});
+var netcoreappCoreLibrariesNuSpecContent = coreLibrariesFiles.Select((file) => {
+ return new NuSpecContent {
+ Source = file.FullPath, Target = "lib/netcoreapp1.0"
+ };
+});
+
var net45RuntimePlatformExtensions = new [] {".xml", ".dll"};
var net45RuntimePlatform = net45RuntimePlatformExtensions.Select(libSuffix => {
return new NuSpecContent {
@@ -281,6 +289,15 @@ var net45RuntimePlatform = net45RuntimePlatformExtensions.Select(libSuffix => {
};
});
+var netCoreRuntimePlatformExtensions = new [] {".xml", ".dll"};
+var netCoreRuntimePlatform = netCoreRuntimePlatformExtensions.Select(libSuffix => {
+ return new NuSpecContent {
+ Source = ((FilePath)File("./src/Avalonia.DotNetCoreRuntime/bin/" + dirSuffix + "/Avalonia.DotNetCoreRuntime" + libSuffix)).FullPath,
+ Target = "lib/netcoreapp1.0"
+ };
+});
+
+
var nuspecNuGetSettingsCore = new []
{
///////////////////////////////////////////////////////////////////////////////
@@ -294,9 +311,20 @@ var nuspecNuGetSettingsCore = new []
new NuSpecDependency() { Id = "Serilog", Version = SerilogVersion },
new NuSpecDependency() { Id = "Splat", Version = SplatVersion },
new NuSpecDependency() { Id = "Sprache", Version = SpracheVersion },
- new NuSpecDependency() { Id = "System.Reactive", Version = SystemReactiveVersion }
+ new NuSpecDependency() { Id = "System.Reactive", Version = SystemReactiveVersion },
+ new NuSpecDependency() { Id = "System.Threading.ThreadPool", TargetFramework = "netcoreapp1.0", Version = "4.3.0" },
+ //.NET Core
+ new NuSpecDependency() { Id = "NETStandard.Library", TargetFramework = "netcoreapp1.0", Version = "1.6.0" },
+ new NuSpecDependency() { Id = "Microsoft.NETCore.Portable.Compatibility", TargetFramework = "netcoreapp1.0", Version = "1.0.1" },
+ new NuSpecDependency() { Id = "Splat", TargetFramework = "netcoreapp1.0", Version = "2.0.0" },
+ new NuSpecDependency() { Id = "Serilog", TargetFramework = "netcoreapp1.0", Version = "2.3.0" },
+ new NuSpecDependency() { Id = "Sprache", TargetFramework = "netcoreapp1.0", Version = SpracheVersion },
+ new NuSpecDependency() { Id = "System.Reactive", TargetFramework = "netcoreapp1.0", Version = SystemReactiveVersion }
},
- Files = coreLibrariesNuSpecContent.Concat(win32CoreLibrariesNuSpecContent).Concat(net45RuntimePlatform).ToList(),
+ Files = coreLibrariesNuSpecContent
+ .Concat(win32CoreLibrariesNuSpecContent).Concat(net45RuntimePlatform)
+ .Concat(netcoreappCoreLibrariesNuSpecContent).Concat(netCoreRuntimePlatform)
+ .ToList(),
BasePath = Directory("./"),
OutputDirectory = nugetRoot
},
@@ -427,9 +455,10 @@ var nuspecNuGetSettingsDesktop = new []
},
Files = new []
{
- new NuSpecContent { Source = "Avalonia.Win32.dll", Target = "lib/net45" }
+ new NuSpecContent { Source = "Avalonia.Win32/bin/" + dirSuffix + "/Avalonia.Win32.dll", Target = "lib/net45" },
+ new NuSpecContent { Source = "Avalonia.Win32.NetStandard/bin/" + dirSuffix + "/Avalonia.Win32.dll", Target = "lib/netstandard1.1" }
},
- BasePath = Directory("./src/Windows/Avalonia.Win32/bin/" + dirSuffix),
+ BasePath = Directory("./src/Windows"),
OutputDirectory = nugetRoot
},
///////////////////////////////////////////////////////////////////////////////
@@ -471,6 +500,23 @@ var nuspecNuGetSettingsDesktop = new []
OutputDirectory = nugetRoot
},
///////////////////////////////////////////////////////////////////////////////
+ // Avalonia.Gtk3
+ ///////////////////////////////////////////////////////////////////////////////
+ new NuGetPackSettings()
+ {
+ Id = "Avalonia.Gtk3",
+ Dependencies = new []
+ {
+ new NuSpecDependency() { Id = "Avalonia", Version = version }
+ },
+ Files = new []
+ {
+ new NuSpecContent { Source = "Avalonia.Gtk3.dll", Target = "lib/netstandard1.1" }
+ },
+ BasePath = Directory("./src/Gtk/Avalonia.Gtk3/bin/" + dirSuffix),
+ OutputDirectory = nugetRoot
+ },
+ ///////////////////////////////////////////////////////////////////////////////
// Avalonia.Cairo
///////////////////////////////////////////////////////////////////////////////
new NuGetPackSettings()
@@ -496,13 +542,19 @@ var nuspecNuGetSettingsDesktop = new []
Dependencies = new []
{
new NuSpecDependency() { Id = "Avalonia", Version = version },
- new NuSpecDependency() { Id = "SkiaSharp", Version = SkiaSharpVersion }
+ new NuSpecDependency() { Id = "SkiaSharp", Version = SkiaSharpVersion },
+ //.NET Core
+ new NuSpecDependency() { Id = "Avalonia", TargetFramework = "netcoreapp1.0", Version = version },
+ new NuSpecDependency() { Id = "SkiaSharp", TargetFramework = "netcoreapp1.0", Version = SkiaSharpVersion },
+ new NuSpecDependency() { Id = "NETStandard.Library", TargetFramework = "netcoreapp1.0", Version = "1.6.0" },
+ new NuSpecDependency() { Id = "Microsoft.NETCore.Portable.Compatibility", TargetFramework = "netcoreapp1.0", Version = "1.0.1" }
},
Files = new []
{
- new NuSpecContent { Source = "Avalonia.Skia.Desktop.dll", Target = "lib/net45" }
+ new NuSpecContent { Source = "Avalonia.Skia.Desktop/bin/" + dirSuffixSkia + "/Avalonia.Skia.Desktop.dll", Target = "lib/net45" },
+ new NuSpecContent { Source = "Avalonia.Skia.Desktop.NetStandard/bin/" + dirSuffix + "/Avalonia.Skia.Desktop.dll", Target = "lib/netcoreapp1.0" }
},
- BasePath = Directory("./src/Skia/Avalonia.Skia.Desktop/bin/" + dirSuffixSkia),
+ BasePath = Directory("./src/Skia/"),
OutputDirectory = nugetRoot
},
///////////////////////////////////////////////////////////////////////////////
@@ -592,9 +644,46 @@ Task("Clean")
CleanDirectory(binRoot);
CleanDirectory(testsRoot);
});
+Task("Prepare-XBuild-Solution")
+ .Does(() =>
+{
+ var blacklistedProjects = new[]
+ {
+ "Avalonia.Win32.NetStandard",
+ "Avalonia.DotNetCoreRuntime",
+ "Avalonia.Skia.Desktop.NetStandard",
+ "Avalonia.Gtk3"
+ };
+ var blacklistedGuids = System.IO.File.ReadAllLines(MSBuildSolution)
+ .Where(l=>l.StartsWith("Project") && blacklistedProjects.Any(p=>l.Contains(p)))
+ .Select(l => l.Split(',').Select(part => part.Trim()).FirstOrDefault(part => part.StartsWith("\"{")))
+ .Where(g=>g!=null)
+ .Select(l=>l.Trim(new[]{'"', '}', '{'}).ToLower()).ToArray();
+
+ Console.WriteLine("Blacklisted guids are: " + string.Join(",", blacklistedGuids));
+ var removeUntilEndProject = false;
+
+ System.IO.File.WriteAllLines(XBuildSolution, System.IO.File.ReadAllLines(MSBuildSolution)
+ .Where(l =>
+ {
+ if(removeUntilEndProject)
+ {
+ if(l.StartsWith("EndProject"))
+ removeUntilEndProject = false;
+ return false;
+ }
+
+ var blacklist = blacklistedGuids.Any(g => l.ToLower().Contains(g));
+ if(blacklist && l.StartsWith("Project"))
+ removeUntilEndProject = true;
+
+ return !blacklist;
+ }));
+});
Task("Restore-NuGet-Packages")
.IsDependentOn("Clean")
+ .IsDependentOn("Prepare-XBuild-Solution")
.Does(() =>
{
var maxRetryCount = 5;
diff --git a/samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj b/samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj
index 53cb277233..ca5743dd5c 100644
--- a/samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj
+++ b/samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj
@@ -33,6 +33,9 @@
prompt
4
+
+
+
..\..\packages\Serilog.1.5.14\lib\net45\Serilog.dll
@@ -72,6 +75,10 @@
{FB05AC90-89BA-4F2F-A924-F37875FB547C}
Avalonia.Cairo
+
+ {bb1f7bb5-6ad4-4776-94d9-c09d0a972658}
+ Avalonia.Gtk3
+
{54F237D5-A70A-4752-9656-0C70B1A7B047}
Avalonia.Gtk
diff --git a/src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj b/src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj
index ebe268adcf..0e94cecc2d 100644
--- a/src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj
+++ b/src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj
@@ -72,9 +72,8 @@
..\..\..\packages\Splat.1.6.2\lib\monoandroid\Splat.dll
True
-
- ..\..\..\packages\Sprache.2.0.0.51\lib\portable-net4+netcore45+win8+wp8+sl5+MonoAndroid+Xamarin.iOS10+MonoTouch\Sprache.dll
- True
+
+ ..\..\..\packages\Sprache.2.1.0\lib\netstandard1.0\Sprache.dll
diff --git a/src/Android/Avalonia.AndroidTestApplication/packages.config b/src/Android/Avalonia.AndroidTestApplication/packages.config
index 470074798d..d353146747 100644
--- a/src/Android/Avalonia.AndroidTestApplication/packages.config
+++ b/src/Android/Avalonia.AndroidTestApplication/packages.config
@@ -2,7 +2,7 @@
-
+
@@ -19,6 +19,7 @@
+
\ No newline at end of file
diff --git a/src/Avalonia.Animation/Avalonia.Animation.csproj b/src/Avalonia.Animation/Avalonia.Animation.csproj
index d74f4d9c69..46aac81b5a 100644
--- a/src/Avalonia.Animation/Avalonia.Animation.csproj
+++ b/src/Avalonia.Animation/Avalonia.Animation.csproj
@@ -16,7 +16,7 @@
Profile7
v4.5
-
+
true
full
false
@@ -27,7 +27,7 @@
bin\Debug\Avalonia.Animation.XML
false
-
+
pdbonly
true
bin\Release\
diff --git a/src/Avalonia.Base/Avalonia.Base.csproj b/src/Avalonia.Base/Avalonia.Base.csproj
index 63f500270d..90550a12f2 100644
--- a/src/Avalonia.Base/Avalonia.Base.csproj
+++ b/src/Avalonia.Base/Avalonia.Base.csproj
@@ -18,7 +18,7 @@
-
+
true
full
false
@@ -29,7 +29,7 @@
bin\Debug\Avalonia.Base.XML
CS1591
-
+
pdbonly
true
bin\Release\
diff --git a/src/Avalonia.Controls/Avalonia.Controls.csproj b/src/Avalonia.Controls/Avalonia.Controls.csproj
index 5fc7329f97..c05e44b357 100644
--- a/src/Avalonia.Controls/Avalonia.Controls.csproj
+++ b/src/Avalonia.Controls/Avalonia.Controls.csproj
@@ -18,7 +18,7 @@
-
+
true
full
false
@@ -29,7 +29,7 @@
bin\Debug\Avalonia.Controls.XML
CS1591
-
+
pdbonly
true
bin\Release\
diff --git a/src/Avalonia.DesignerSupport/Avalonia.DesignerSupport.csproj b/src/Avalonia.DesignerSupport/Avalonia.DesignerSupport.csproj
index 478d0eaa57..d9174d6f36 100644
--- a/src/Avalonia.DesignerSupport/Avalonia.DesignerSupport.csproj
+++ b/src/Avalonia.DesignerSupport/Avalonia.DesignerSupport.csproj
@@ -18,7 +18,7 @@
-
+
true
full
false
@@ -29,7 +29,7 @@
bin\Debug\Avalonia.DesignerSupport.xml
CS1591
-
+
pdbonly
true
bin\Release\
diff --git a/src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj b/src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj
index 5381f55288..a56575dab7 100644
--- a/src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj
+++ b/src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj
@@ -18,7 +18,7 @@
-
+
true
full
false
@@ -29,7 +29,7 @@
bin\Debug\Avalonia.Diagnostics.XML
CS1591
-
+
pdbonly
true
bin\Release\
diff --git a/src/Avalonia.DotNetCoreRuntime/AppBuilder.cs b/src/Avalonia.DotNetCoreRuntime/AppBuilder.cs
new file mode 100644
index 0000000000..5a6b82573b
--- /dev/null
+++ b/src/Avalonia.DotNetCoreRuntime/AppBuilder.cs
@@ -0,0 +1,53 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Avalonia.Controls;
+using Avalonia.Platform;
+using Avalonia.Shared.PlatformSupport;
+
+namespace Avalonia
+{
+ public sealed class AppBuilder : AppBuilderBase
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public AppBuilder()
+ : base(new StandardRuntimePlatform(), () => StandardRuntimePlatformServices.Register())
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The instance.
+ public AppBuilder(Application app) : this()
+ {
+ Instance = app;
+ }
+
+ ///
+ /// Instructs the to use the best settings for the platform.
+ ///
+ /// An instance.
+ public AppBuilder UsePlatformDetect()
+ {
+ //We don't have the ability to load every assembly right now, so we are
+ //stuck with manual configuration here
+ //Helpers are extracted to separate methods to take the advantage of the fact
+ //that CLR doesn't try to load dependencies before referencing method is jitted
+ if (RuntimePlatform.GetRuntimeInfo().OperatingSystem == OperatingSystemType.WinNT)
+ LoadWin32();
+ else
+ LoadGtk3();
+ this.UseSkia();
+
+ return this;
+ }
+
+ void LoadWin32() => this.UseWin32();
+ void LoadGtk3() => this.UseGtk3();
+ }
+}
\ No newline at end of file
diff --git a/src/Avalonia.DotNetCoreRuntime/Avalonia.DotNetCoreRuntime.csproj b/src/Avalonia.DotNetCoreRuntime/Avalonia.DotNetCoreRuntime.csproj
new file mode 100644
index 0000000000..8a60d5d9c7
--- /dev/null
+++ b/src/Avalonia.DotNetCoreRuntime/Avalonia.DotNetCoreRuntime.csproj
@@ -0,0 +1,89 @@
+
+
+
+
+ 14.0
+ Debug
+ AnyCPU
+ {7863EA94-F0FB-4386-BF8C-E5BFA761560A}
+ Library
+ Properties
+ Avalonia.DotNetCoreRuntime
+ Avalonia.DotNetCoreRuntime
+ en-US
+ 512
+ {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+
+
+ v5.0
+
+
+ true
+ full
+ false
+ bin\Debug\
+ TRACE;DEBUG;NETSTANDARD
+ prompt
+ 4
+ bin\Debug\Avalonia.DotNetCoreRuntime.XML
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE;NETSTANDARD
+ prompt
+ 4
+ bin\Release\Avalonia.DotNetCoreRuntime.XML
+
+
+
+
+
+
+
+ SharedAssemblyInfo.cs
+
+
+
+
+
+
+
+ {b09b78d8-9b26-48b0-9149-d64a2f120f3f}
+ Avalonia.Base
+
+
+ {d2221c82-4a25-4583-9b43-d791e3f6820c}
+ Avalonia.Controls
+
+
+ {eb582467-6abb-43a1-b052-e981ba910e3a}
+ Avalonia.Visuals
+
+
+ {bb1f7bb5-6ad4-4776-94d9-c09d0a972658}
+ Avalonia.Gtk3
+
+
+ {7d2d3083-71dd-4cc9-8907-39a0d86fb322}
+ Avalonia.Skia.Desktop.NetStandard
+
+
+ {40759a76-d0f2-464e-8000-6ff0f5c4bd7c}
+ Avalonia.Win32.NetStandard
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Avalonia.DotNetCoreRuntime/NetCoreRuntimePlatform.cs b/src/Avalonia.DotNetCoreRuntime/NetCoreRuntimePlatform.cs
new file mode 100644
index 0000000000..b131488109
--- /dev/null
+++ b/src/Avalonia.DotNetCoreRuntime/NetCoreRuntimePlatform.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Avalonia.Shared.PlatformSupport
+{
+ internal partial class StandardRuntimePlatform
+ {
+ private static readonly Lazy Assemblies = new Lazy(LoadAssemblies);
+ public Assembly[] GetLoadedAssemblies() => Assemblies.Value;
+
+ static Assembly[] LoadAssemblies()
+ {
+
+ var rv = new List();
+ var entry = Assembly.GetEntryAssembly();
+ rv.Add(entry);
+ var queue = new Queue(entry.GetReferencedAssemblies());
+ var aset = new HashSet(queue.Select(r => r.ToString()));
+
+ while (queue.Count > 0)
+ {
+ Assembly asm;
+ try
+ {
+ asm = Assembly.Load(queue.Dequeue());
+ }
+ catch (Exception e)
+ {
+ Debug.Write(e.ToString());
+ continue;
+ }
+ rv.Add(asm);
+ foreach (var r in asm.GetReferencedAssemblies())
+ {
+ if (aset.Add(r.ToString()))
+ queue.Enqueue(r);
+ }
+ }
+ return rv.Distinct().ToArray();
+ }
+ }
+}
diff --git a/src/Avalonia.DotNetCoreRuntime/RuntimeInfo.cs b/src/Avalonia.DotNetCoreRuntime/RuntimeInfo.cs
new file mode 100644
index 0000000000..348c3f6e25
--- /dev/null
+++ b/src/Avalonia.DotNetCoreRuntime/RuntimeInfo.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+using Avalonia.Platform;
+
+
+namespace Avalonia.Shared.PlatformSupport
+{
+ internal partial class StandardRuntimePlatform
+ {
+ private static readonly Lazy Info = new Lazy(() =>
+ {
+ OperatingSystemType os;
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
+ os = OperatingSystemType.OSX;
+ else if(RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
+ os = OperatingSystemType.Linux;
+ else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ os = OperatingSystemType.WinNT;
+ else
+ throw new Exception("Unknown OS platform " + RuntimeInformation.OSDescription);
+
+ return new RuntimePlatformInfo
+ {
+ IsCoreClr = true,
+ IsDesktop = true,
+ IsDotNetFramework = false,
+ IsMono = false,
+ IsMobile = false,
+ IsUnix = os != OperatingSystemType.WinNT,
+ OperatingSystem = os,
+ };
+ });
+
+
+ public RuntimePlatformInfo GetRuntimeInfo() => Info.Value;
+ }
+}
diff --git a/src/Avalonia.DotNetCoreRuntime/project.json b/src/Avalonia.DotNetCoreRuntime/project.json
new file mode 100644
index 0000000000..d6ae90b33b
--- /dev/null
+++ b/src/Avalonia.DotNetCoreRuntime/project.json
@@ -0,0 +1,11 @@
+{
+ "supports": {},
+ "dependencies": {
+ "Microsoft.NETCore.Portable.Compatibility": "1.0.1",
+ "NETStandard.Library": "1.6.0",
+ "System.Threading.ThreadPool": "4.3.0"
+ },
+ "frameworks": {
+ "netstandard1.5": {}
+ }
+}
\ No newline at end of file
diff --git a/src/Avalonia.DotNetFrameworkRuntime/Avalonia.DotNetFrameworkRuntime.csproj b/src/Avalonia.DotNetFrameworkRuntime/Avalonia.DotNetFrameworkRuntime.csproj
index f11b67dcc9..e87ec0b5a7 100644
--- a/src/Avalonia.DotNetFrameworkRuntime/Avalonia.DotNetFrameworkRuntime.csproj
+++ b/src/Avalonia.DotNetFrameworkRuntime/Avalonia.DotNetFrameworkRuntime.csproj
@@ -13,7 +13,7 @@
512
-
+
true
full
false
@@ -23,7 +23,7 @@
4
bin\Debug\Avalonia.DotNetFrameworkRuntime.xml
-
+
pdbonly
true
bin\Release\
diff --git a/src/Avalonia.HtmlRenderer/Avalonia.HtmlRenderer.csproj b/src/Avalonia.HtmlRenderer/Avalonia.HtmlRenderer.csproj
index dd0a6f2cef..8f16bad64a 100644
--- a/src/Avalonia.HtmlRenderer/Avalonia.HtmlRenderer.csproj
+++ b/src/Avalonia.HtmlRenderer/Avalonia.HtmlRenderer.csproj
@@ -18,7 +18,7 @@
-
+
true
full
false
@@ -27,7 +27,7 @@
prompt
4
-
+
pdbonly
true
bin\Release\
diff --git a/src/Avalonia.Input/Avalonia.Input.csproj b/src/Avalonia.Input/Avalonia.Input.csproj
index 5e0fb50b67..c1ed34c1c7 100644
--- a/src/Avalonia.Input/Avalonia.Input.csproj
+++ b/src/Avalonia.Input/Avalonia.Input.csproj
@@ -18,7 +18,7 @@
-
+
true
full
false
@@ -29,7 +29,7 @@
bin\Debug\Avalonia.Input.XML
CS1591
-
+
pdbonly
true
bin\Release\
diff --git a/src/Avalonia.Interactivity/Avalonia.Interactivity.csproj b/src/Avalonia.Interactivity/Avalonia.Interactivity.csproj
index 499a55ef12..0d81690de0 100644
--- a/src/Avalonia.Interactivity/Avalonia.Interactivity.csproj
+++ b/src/Avalonia.Interactivity/Avalonia.Interactivity.csproj
@@ -18,7 +18,7 @@
-
+
true
full
false
@@ -29,7 +29,7 @@
bin\Debug\Avalonia.Interactivity.XML
CS1591
-
+
pdbonly
true
bin\Release\
diff --git a/src/Avalonia.Layout/Avalonia.Layout.csproj b/src/Avalonia.Layout/Avalonia.Layout.csproj
index 4bc27fc96b..41b545b5cb 100644
--- a/src/Avalonia.Layout/Avalonia.Layout.csproj
+++ b/src/Avalonia.Layout/Avalonia.Layout.csproj
@@ -18,7 +18,7 @@
-
+
true
full
false
@@ -29,7 +29,7 @@
bin\Debug\Avalonia.Layout.XML
CS1591
-
+
pdbonly
true
bin\Release\
diff --git a/src/Avalonia.Logging.Serilog/Avalonia.Logging.Serilog.csproj b/src/Avalonia.Logging.Serilog/Avalonia.Logging.Serilog.csproj
index e88dc86b00..0fb85db795 100644
--- a/src/Avalonia.Logging.Serilog/Avalonia.Logging.Serilog.csproj
+++ b/src/Avalonia.Logging.Serilog/Avalonia.Logging.Serilog.csproj
@@ -16,7 +16,7 @@
Profile7
v4.5
-
+
true
full
false
@@ -26,7 +26,7 @@
4
bin\Debug\Avalonia.Logging.Serilog.XML
-
+
pdbonly
true
bin\Release\
diff --git a/src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj b/src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj
index 4ef0502fa0..98cf115eaf 100644
--- a/src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj
+++ b/src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj
@@ -16,7 +16,7 @@
Profile259
v4.5
-
+
true
full
false
@@ -25,7 +25,7 @@
prompt
4
-
+
pdbonly
true
bin\Release\
diff --git a/src/Avalonia.Styling/Avalonia.Styling.csproj b/src/Avalonia.Styling/Avalonia.Styling.csproj
index 3566ed7268..d38406caa7 100644
--- a/src/Avalonia.Styling/Avalonia.Styling.csproj
+++ b/src/Avalonia.Styling/Avalonia.Styling.csproj
@@ -18,7 +18,7 @@
-
+
true
full
false
@@ -29,7 +29,7 @@
bin\Debug\Avalonia.Styling.XML
CS1591
-
+
pdbonly
true
bin\Release\
diff --git a/src/Avalonia.Themes.Default/Avalonia.Themes.Default.csproj b/src/Avalonia.Themes.Default/Avalonia.Themes.Default.csproj
index 578bb9cdff..26d168cb2a 100644
--- a/src/Avalonia.Themes.Default/Avalonia.Themes.Default.csproj
+++ b/src/Avalonia.Themes.Default/Avalonia.Themes.Default.csproj
@@ -18,7 +18,7 @@
-
+
true
full
false
@@ -28,7 +28,7 @@
4
bin\Debug\Avalonia.Themes.Default.XML
-
+
pdbonly
true
bin\Release\
diff --git a/src/Avalonia.Visuals/Avalonia.Visuals.csproj b/src/Avalonia.Visuals/Avalonia.Visuals.csproj
index d9736e4c6e..dd43f1d8f0 100644
--- a/src/Avalonia.Visuals/Avalonia.Visuals.csproj
+++ b/src/Avalonia.Visuals/Avalonia.Visuals.csproj
@@ -18,7 +18,7 @@
-
+
true
full
false
@@ -29,7 +29,7 @@
bin\Debug\Avalonia.Visuals.xml
CS1591
-
+
pdbonly
true
bin\Release\
diff --git a/src/Gtk/Avalonia.Gtk/Avalonia.Gtk.csproj b/src/Gtk/Avalonia.Gtk/Avalonia.Gtk.csproj
index 540e70cee0..07a9ab56ed 100644
--- a/src/Gtk/Avalonia.Gtk/Avalonia.Gtk.csproj
+++ b/src/Gtk/Avalonia.Gtk/Avalonia.Gtk.csproj
@@ -52,6 +52,7 @@
+
diff --git a/src/Gtk/Avalonia.Gtk/Input/GtkKeyboardDevice.cs b/src/Gtk/Avalonia.Gtk/Input/GtkKeyboardDevice.cs
index 4e88dcda9a..a97a6190f1 100644
--- a/src/Gtk/Avalonia.Gtk/Input/GtkKeyboardDevice.cs
+++ b/src/Gtk/Avalonia.Gtk/Input/GtkKeyboardDevice.cs
@@ -8,218 +8,11 @@ using System.Reflection;
using System.Text;
using Avalonia.Input;
+
namespace Avalonia.Gtk
{
public class GtkKeyboardDevice : KeyboardDevice
{
- private static readonly Dictionary KeyDic = new Dictionary
- {
- { Gdk.Key.Cancel, Key.Cancel },
- { Gdk.Key.BackSpace, Key.Back },
- { Gdk.Key.Tab, Key.Tab },
- { Gdk.Key.Linefeed, Key.LineFeed },
- { Gdk.Key.Clear, Key.Clear },
- { Gdk.Key.Return, Key.Return },
- { Gdk.Key.Pause, Key.Pause },
- //{ Gdk.Key.?, Key.CapsLock }
- //{ Gdk.Key.?, Key.HangulMode }
- //{ Gdk.Key.?, Key.JunjaMode }
- //{ Gdk.Key.?, Key.FinalMode }
- //{ Gdk.Key.?, Key.KanjiMode }
- { Gdk.Key.Escape, Key.Escape },
- //{ Gdk.Key.?, Key.ImeConvert }
- //{ Gdk.Key.?, Key.ImeNonConvert }
- //{ Gdk.Key.?, Key.ImeAccept }
- //{ Gdk.Key.?, Key.ImeModeChange }
- { Gdk.Key.space, Key.Space },
- { Gdk.Key.Prior, Key.Prior },
- //{ Gdk.Key.?, Key.PageDown }
- { Gdk.Key.End, Key.End },
- { Gdk.Key.Home, Key.Home },
- { Gdk.Key.Left, Key.Left },
- { Gdk.Key.Up, Key.Up },
- { Gdk.Key.Right, Key.Right },
- { Gdk.Key.Down, Key.Down },
- { Gdk.Key.Select, Key.Select },
- { Gdk.Key.Print, Key.Print },
- { Gdk.Key.Execute, Key.Execute },
- //{ Gdk.Key.?, Key.Snapshot }
- { Gdk.Key.Insert, Key.Insert },
- { Gdk.Key.Delete, Key.Delete },
- { Gdk.Key.Help, Key.Help },
- //{ Gdk.Key.?, Key.D0 }
- //{ Gdk.Key.?, Key.D1 }
- //{ Gdk.Key.?, Key.D2 }
- //{ Gdk.Key.?, Key.D3 }
- //{ Gdk.Key.?, Key.D4 }
- //{ Gdk.Key.?, Key.D5 }
- //{ Gdk.Key.?, Key.D6 }
- //{ Gdk.Key.?, Key.D7 }
- //{ Gdk.Key.?, Key.D8 }
- //{ Gdk.Key.?, Key.D9 }
- { Gdk.Key.A, Key.A },
- { Gdk.Key.B, Key.B },
- { Gdk.Key.C, Key.C },
- { Gdk.Key.D, Key.D },
- { Gdk.Key.E, Key.E },
- { Gdk.Key.F, Key.F },
- { Gdk.Key.G, Key.G },
- { Gdk.Key.H, Key.H },
- { Gdk.Key.I, Key.I },
- { Gdk.Key.J, Key.J },
- { Gdk.Key.K, Key.K },
- { Gdk.Key.L, Key.L },
- { Gdk.Key.M, Key.M },
- { Gdk.Key.N, Key.N },
- { Gdk.Key.O, Key.O },
- { Gdk.Key.P, Key.P },
- { Gdk.Key.Q, Key.Q },
- { Gdk.Key.R, Key.R },
- { Gdk.Key.S, Key.S },
- { Gdk.Key.T, Key.T },
- { Gdk.Key.U, Key.U },
- { Gdk.Key.V, Key.V },
- { Gdk.Key.W, Key.W },
- { Gdk.Key.X, Key.X },
- { Gdk.Key.Y, Key.Y },
- { Gdk.Key.Z, Key.Z },
- { Gdk.Key.a, Key.A },
- { Gdk.Key.b, Key.B },
- { Gdk.Key.c, Key.C },
- { Gdk.Key.d, Key.D },
- { Gdk.Key.e, Key.E },
- { Gdk.Key.f, Key.F },
- { Gdk.Key.g, Key.G },
- { Gdk.Key.h, Key.H },
- { Gdk.Key.i, Key.I },
- { Gdk.Key.j, Key.J },
- { Gdk.Key.k, Key.K },
- { Gdk.Key.l, Key.L },
- { Gdk.Key.m, Key.M },
- { Gdk.Key.n, Key.N },
- { Gdk.Key.o, Key.O },
- { Gdk.Key.p, Key.P },
- { Gdk.Key.q, Key.Q },
- { Gdk.Key.r, Key.R },
- { Gdk.Key.s, Key.S },
- { Gdk.Key.t, Key.T },
- { Gdk.Key.u, Key.U },
- { Gdk.Key.v, Key.V },
- { Gdk.Key.w, Key.W },
- { Gdk.Key.x, Key.X },
- { Gdk.Key.y, Key.Y },
- { Gdk.Key.z, Key.Z },
- //{ Gdk.Key.?, Key.LWin }
- //{ Gdk.Key.?, Key.RWin }
- //{ Gdk.Key.?, Key.Apps }
- //{ Gdk.Key.?, Key.Sleep }
- //{ Gdk.Key.?, Key.NumPad0 }
- //{ Gdk.Key.?, Key.NumPad1 }
- //{ Gdk.Key.?, Key.NumPad2 }
- //{ Gdk.Key.?, Key.NumPad3 }
- //{ Gdk.Key.?, Key.NumPad4 }
- //{ Gdk.Key.?, Key.NumPad5 }
- //{ Gdk.Key.?, Key.NumPad6 }
- //{ Gdk.Key.?, Key.NumPad7 }
- //{ Gdk.Key.?, Key.NumPad8 }
- //{ Gdk.Key.?, Key.NumPad9 }
- { Gdk.Key.multiply, Key.Multiply },
- //{ Gdk.Key.?, Key.Add }
- //{ Gdk.Key.?, Key.Separator }
- //{ Gdk.Key.?, Key.Subtract }
- //{ Gdk.Key.?, Key.Decimal }
- //{ Gdk.Key.?, Key.Divide }
- { Gdk.Key.F1, Key.F1 },
- { Gdk.Key.F2, Key.F2 },
- { Gdk.Key.F3, Key.F3 },
- { Gdk.Key.F4, Key.F4 },
- { Gdk.Key.F5, Key.F5 },
- { Gdk.Key.F6, Key.F6 },
- { Gdk.Key.F7, Key.F7 },
- { Gdk.Key.F8, Key.F8 },
- { Gdk.Key.F9, Key.F9 },
- { Gdk.Key.F10, Key.F10 },
- { Gdk.Key.F11, Key.F11 },
- { Gdk.Key.F12, Key.F12 },
- { Gdk.Key.L3, Key.F13 },
- { Gdk.Key.F14, Key.F14 },
- { Gdk.Key.L5, Key.F15 },
- { Gdk.Key.F16, Key.F16 },
- { Gdk.Key.F17, Key.F17 },
- { Gdk.Key.L8, Key.F18 },
- { Gdk.Key.L9, Key.F19 },
- { Gdk.Key.L10, Key.F20 },
- { Gdk.Key.R1, Key.F21 },
- { Gdk.Key.R2, Key.F22 },
- { Gdk.Key.F23, Key.F23 },
- { Gdk.Key.R4, Key.F24 },
- //{ Gdk.Key.?, Key.NumLock }
- //{ Gdk.Key.?, Key.Scroll }
- //{ Gdk.Key.?, Key.LeftShift }
- //{ Gdk.Key.?, Key.RightShift }
- //{ Gdk.Key.?, Key.LeftCtrl }
- //{ Gdk.Key.?, Key.RightCtrl }
- //{ Gdk.Key.?, Key.LeftAlt }
- //{ Gdk.Key.?, Key.RightAlt }
- //{ Gdk.Key.?, Key.BrowserBack }
- //{ Gdk.Key.?, Key.BrowserForward }
- //{ Gdk.Key.?, Key.BrowserRefresh }
- //{ Gdk.Key.?, Key.BrowserStop }
- //{ Gdk.Key.?, Key.BrowserSearch }
- //{ Gdk.Key.?, Key.BrowserFavorites }
- //{ Gdk.Key.?, Key.BrowserHome }
- //{ Gdk.Key.?, Key.VolumeMute }
- //{ Gdk.Key.?, Key.VolumeDown }
- //{ Gdk.Key.?, Key.VolumeUp }
- //{ Gdk.Key.?, Key.MediaNextTrack }
- //{ Gdk.Key.?, Key.MediaPreviousTrack }
- //{ Gdk.Key.?, Key.MediaStop }
- //{ Gdk.Key.?, Key.MediaPlayPause }
- //{ Gdk.Key.?, Key.LaunchMail }
- //{ Gdk.Key.?, Key.SelectMedia }
- //{ Gdk.Key.?, Key.LaunchApplication1 }
- //{ Gdk.Key.?, Key.LaunchApplication2 }
- //{ Gdk.Key.?, Key.OemSemicolon }
- //{ Gdk.Key.?, Key.OemPlus }
- //{ Gdk.Key.?, Key.OemComma }
- //{ Gdk.Key.?, Key.OemMinus }
- //{ Gdk.Key.?, Key.OemPeriod }
- //{ Gdk.Key.?, Key.Oem2 }
- //{ Gdk.Key.?, Key.OemTilde }
- //{ Gdk.Key.?, Key.AbntC1 }
- //{ Gdk.Key.?, Key.AbntC2 }
- //{ Gdk.Key.?, Key.Oem4 }
- //{ Gdk.Key.?, Key.OemPipe }
- //{ Gdk.Key.?, Key.OemCloseBrackets }
- //{ Gdk.Key.?, Key.Oem7 }
- //{ Gdk.Key.?, Key.Oem8 }
- //{ Gdk.Key.?, Key.Oem102 }
- //{ Gdk.Key.?, Key.ImeProcessed }
- //{ Gdk.Key.?, Key.System }
- //{ Gdk.Key.?, Key.OemAttn }
- //{ Gdk.Key.?, Key.OemFinish }
- //{ Gdk.Key.?, Key.DbeHiragana }
- //{ Gdk.Key.?, Key.OemAuto }
- //{ Gdk.Key.?, Key.DbeDbcsChar }
- //{ Gdk.Key.?, Key.OemBackTab }
- //{ Gdk.Key.?, Key.Attn }
- //{ Gdk.Key.?, Key.DbeEnterWordRegisterMode }
- //{ Gdk.Key.?, Key.DbeEnterImeConfigureMode }
- //{ Gdk.Key.?, Key.EraseEof }
- //{ Gdk.Key.?, Key.Play }
- //{ Gdk.Key.?, Key.Zoom }
- //{ Gdk.Key.?, Key.NoName }
- //{ Gdk.Key.?, Key.DbeEnterDialogConversionMode }
- //{ Gdk.Key.?, Key.OemClear }
- //{ Gdk.Key.?, Key.DeadCharProcessed }
- };
-
public new static GtkKeyboardDevice Instance { get; } = new GtkKeyboardDevice();
-
- public static Key ConvertKey(Gdk.Key key)
- {
- Key result;
- return KeyDic.TryGetValue(key, out result) ? result : Key.None;
- }
}
}
\ No newline at end of file
diff --git a/src/Gtk/Avalonia.Gtk/KeyTransform.cs b/src/Gtk/Avalonia.Gtk/KeyTransform.cs
new file mode 100644
index 0000000000..77de8d18a3
--- /dev/null
+++ b/src/Gtk/Avalonia.Gtk/KeyTransform.cs
@@ -0,0 +1,224 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Avalonia.Input;
+#if GTK3_PINVOKE
+using Avalonia.Gtk3;
+#else
+using GdkKey = Gdk.Key;
+#endif
+namespace Avalonia.Gtk.Common
+{
+ static class KeyTransform
+ {
+ private static readonly Dictionary KeyDic = new Dictionary
+ {
+ { GdkKey.Cancel, Key.Cancel },
+ { GdkKey.BackSpace, Key.Back },
+ { GdkKey.Tab, Key.Tab },
+ { GdkKey.Linefeed, Key.LineFeed },
+ { GdkKey.Clear, Key.Clear },
+ { GdkKey.Return, Key.Return },
+ { GdkKey.Pause, Key.Pause },
+ //{ GdkKey.?, Key.CapsLock }
+ //{ GdkKey.?, Key.HangulMode }
+ //{ GdkKey.?, Key.JunjaMode }
+ //{ GdkKey.?, Key.FinalMode }
+ //{ GdkKey.?, Key.KanjiMode }
+ { GdkKey.Escape, Key.Escape },
+ //{ GdkKey.?, Key.ImeConvert }
+ //{ GdkKey.?, Key.ImeNonConvert }
+ //{ GdkKey.?, Key.ImeAccept }
+ //{ GdkKey.?, Key.ImeModeChange }
+ { GdkKey.space, Key.Space },
+ { GdkKey.Prior, Key.Prior },
+ //{ GdkKey.?, Key.PageDown }
+ { GdkKey.End, Key.End },
+ { GdkKey.Home, Key.Home },
+ { GdkKey.Left, Key.Left },
+ { GdkKey.Up, Key.Up },
+ { GdkKey.Right, Key.Right },
+ { GdkKey.Down, Key.Down },
+ { GdkKey.Select, Key.Select },
+ { GdkKey.Print, Key.Print },
+ { GdkKey.Execute, Key.Execute },
+ //{ GdkKey.?, Key.Snapshot }
+ { GdkKey.Insert, Key.Insert },
+ { GdkKey.Delete, Key.Delete },
+ { GdkKey.Help, Key.Help },
+ //{ GdkKey.?, Key.D0 }
+ //{ GdkKey.?, Key.D1 }
+ //{ GdkKey.?, Key.D2 }
+ //{ GdkKey.?, Key.D3 }
+ //{ GdkKey.?, Key.D4 }
+ //{ GdkKey.?, Key.D5 }
+ //{ GdkKey.?, Key.D6 }
+ //{ GdkKey.?, Key.D7 }
+ //{ GdkKey.?, Key.D8 }
+ //{ GdkKey.?, Key.D9 }
+ { GdkKey.A, Key.A },
+ { GdkKey.B, Key.B },
+ { GdkKey.C, Key.C },
+ { GdkKey.D, Key.D },
+ { GdkKey.E, Key.E },
+ { GdkKey.F, Key.F },
+ { GdkKey.G, Key.G },
+ { GdkKey.H, Key.H },
+ { GdkKey.I, Key.I },
+ { GdkKey.J, Key.J },
+ { GdkKey.K, Key.K },
+ { GdkKey.L, Key.L },
+ { GdkKey.M, Key.M },
+ { GdkKey.N, Key.N },
+ { GdkKey.O, Key.O },
+ { GdkKey.P, Key.P },
+ { GdkKey.Q, Key.Q },
+ { GdkKey.R, Key.R },
+ { GdkKey.S, Key.S },
+ { GdkKey.T, Key.T },
+ { GdkKey.U, Key.U },
+ { GdkKey.V, Key.V },
+ { GdkKey.W, Key.W },
+ { GdkKey.X, Key.X },
+ { GdkKey.Y, Key.Y },
+ { GdkKey.Z, Key.Z },
+ { GdkKey.a, Key.A },
+ { GdkKey.b, Key.B },
+ { GdkKey.c, Key.C },
+ { GdkKey.d, Key.D },
+ { GdkKey.e, Key.E },
+ { GdkKey.f, Key.F },
+ { GdkKey.g, Key.G },
+ { GdkKey.h, Key.H },
+ { GdkKey.i, Key.I },
+ { GdkKey.j, Key.J },
+ { GdkKey.k, Key.K },
+ { GdkKey.l, Key.L },
+ { GdkKey.m, Key.M },
+ { GdkKey.n, Key.N },
+ { GdkKey.o, Key.O },
+ { GdkKey.p, Key.P },
+ { GdkKey.q, Key.Q },
+ { GdkKey.r, Key.R },
+ { GdkKey.s, Key.S },
+ { GdkKey.t, Key.T },
+ { GdkKey.u, Key.U },
+ { GdkKey.v, Key.V },
+ { GdkKey.w, Key.W },
+ { GdkKey.x, Key.X },
+ { GdkKey.y, Key.Y },
+ { GdkKey.z, Key.Z },
+ //{ GdkKey.?, Key.LWin }
+ //{ GdkKey.?, Key.RWin }
+ //{ GdkKey.?, Key.Apps }
+ //{ GdkKey.?, Key.Sleep }
+ //{ GdkKey.?, Key.NumPad0 }
+ //{ GdkKey.?, Key.NumPad1 }
+ //{ GdkKey.?, Key.NumPad2 }
+ //{ GdkKey.?, Key.NumPad3 }
+ //{ GdkKey.?, Key.NumPad4 }
+ //{ GdkKey.?, Key.NumPad5 }
+ //{ GdkKey.?, Key.NumPad6 }
+ //{ GdkKey.?, Key.NumPad7 }
+ //{ GdkKey.?, Key.NumPad8 }
+ //{ GdkKey.?, Key.NumPad9 }
+ { GdkKey.multiply, Key.Multiply },
+ //{ GdkKey.?, Key.Add }
+ //{ GdkKey.?, Key.Separator }
+ //{ GdkKey.?, Key.Subtract }
+ //{ GdkKey.?, Key.Decimal }
+ //{ GdkKey.?, Key.Divide }
+ { GdkKey.F1, Key.F1 },
+ { GdkKey.F2, Key.F2 },
+ { GdkKey.F3, Key.F3 },
+ { GdkKey.F4, Key.F4 },
+ { GdkKey.F5, Key.F5 },
+ { GdkKey.F6, Key.F6 },
+ { GdkKey.F7, Key.F7 },
+ { GdkKey.F8, Key.F8 },
+ { GdkKey.F9, Key.F9 },
+ { GdkKey.F10, Key.F10 },
+ { GdkKey.F11, Key.F11 },
+ { GdkKey.F12, Key.F12 },
+ { GdkKey.L3, Key.F13 },
+ { GdkKey.F14, Key.F14 },
+ { GdkKey.L5, Key.F15 },
+ { GdkKey.F16, Key.F16 },
+ { GdkKey.F17, Key.F17 },
+ { GdkKey.L8, Key.F18 },
+ { GdkKey.L9, Key.F19 },
+ { GdkKey.L10, Key.F20 },
+ { GdkKey.R1, Key.F21 },
+ { GdkKey.R2, Key.F22 },
+ { GdkKey.F23, Key.F23 },
+ { GdkKey.R4, Key.F24 },
+ //{ GdkKey.?, Key.NumLock }
+ //{ GdkKey.?, Key.Scroll }
+ //{ GdkKey.?, Key.LeftShift }
+ //{ GdkKey.?, Key.RightShift }
+ //{ GdkKey.?, Key.LeftCtrl }
+ //{ GdkKey.?, Key.RightCtrl }
+ //{ GdkKey.?, Key.LeftAlt }
+ //{ GdkKey.?, Key.RightAlt }
+ //{ GdkKey.?, Key.BrowserBack }
+ //{ GdkKey.?, Key.BrowserForward }
+ //{ GdkKey.?, Key.BrowserRefresh }
+ //{ GdkKey.?, Key.BrowserStop }
+ //{ GdkKey.?, Key.BrowserSearch }
+ //{ GdkKey.?, Key.BrowserFavorites }
+ //{ GdkKey.?, Key.BrowserHome }
+ //{ GdkKey.?, Key.VolumeMute }
+ //{ GdkKey.?, Key.VolumeDown }
+ //{ GdkKey.?, Key.VolumeUp }
+ //{ GdkKey.?, Key.MediaNextTrack }
+ //{ GdkKey.?, Key.MediaPreviousTrack }
+ //{ GdkKey.?, Key.MediaStop }
+ //{ GdkKey.?, Key.MediaPlayPause }
+ //{ GdkKey.?, Key.LaunchMail }
+ //{ GdkKey.?, Key.SelectMedia }
+ //{ GdkKey.?, Key.LaunchApplication1 }
+ //{ GdkKey.?, Key.LaunchApplication2 }
+ //{ GdkKey.?, Key.OemSemicolon }
+ //{ GdkKey.?, Key.OemPlus }
+ //{ GdkKey.?, Key.OemComma }
+ //{ GdkKey.?, Key.OemMinus }
+ //{ GdkKey.?, Key.OemPeriod }
+ //{ GdkKey.?, Key.Oem2 }
+ //{ GdkKey.?, Key.OemTilde }
+ //{ GdkKey.?, Key.AbntC1 }
+ //{ GdkKey.?, Key.AbntC2 }
+ //{ GdkKey.?, Key.Oem4 }
+ //{ GdkKey.?, Key.OemPipe }
+ //{ GdkKey.?, Key.OemCloseBrackets }
+ //{ GdkKey.?, Key.Oem7 }
+ //{ GdkKey.?, Key.Oem8 }
+ //{ GdkKey.?, Key.Oem102 }
+ //{ GdkKey.?, Key.ImeProcessed }
+ //{ GdkKey.?, Key.System }
+ //{ GdkKey.?, Key.OemAttn }
+ //{ GdkKey.?, Key.OemFinish }
+ //{ GdkKey.?, Key.DbeHiragana }
+ //{ GdkKey.?, Key.OemAuto }
+ //{ GdkKey.?, Key.DbeDbcsChar }
+ //{ GdkKey.?, Key.OemBackTab }
+ //{ GdkKey.?, Key.Attn }
+ //{ GdkKey.?, Key.DbeEnterWordRegisterMode }
+ //{ GdkKey.?, Key.DbeEnterImeConfigureMode }
+ //{ GdkKey.?, Key.EraseEof }
+ //{ GdkKey.?, Key.Play }
+ //{ GdkKey.?, Key.Zoom }
+ //{ GdkKey.?, Key.NoName }
+ //{ GdkKey.?, Key.DbeEnterDialogConversionMode }
+ //{ GdkKey.?, Key.OemClear }
+ //{ GdkKey.?, Key.DeadCharProcessed }
+ };
+
+ public static Key ConvertKey(GdkKey key)
+ {
+ Key result;
+ return KeyDic.TryGetValue(key, out result) ? result : Key.None;
+ }
+ }
+}
diff --git a/src/Gtk/Avalonia.Gtk/WindowImplBase.cs b/src/Gtk/Avalonia.Gtk/WindowImplBase.cs
index db4b5e9dde..4d7552aa72 100644
--- a/src/Gtk/Avalonia.Gtk/WindowImplBase.cs
+++ b/src/Gtk/Avalonia.Gtk/WindowImplBase.cs
@@ -267,7 +267,7 @@ namespace Avalonia.Gtk
GtkKeyboardDevice.Instance,
evnt.Time,
evnt.Type == EventType.KeyPress ? RawKeyEventType.KeyDown : RawKeyEventType.KeyUp,
- GtkKeyboardDevice.ConvertKey(evnt.Key), GetModifierKeys(evnt.State));
+ Common.KeyTransform.ConvertKey(evnt.Key), GetModifierKeys(evnt.State));
Input(e);
}
diff --git a/src/Gtk/Avalonia.Gtk3/.gitignore b/src/Gtk/Avalonia.Gtk3/.gitignore
new file mode 100644
index 0000000000..ddb0c6248b
--- /dev/null
+++ b/src/Gtk/Avalonia.Gtk3/.gitignore
@@ -0,0 +1 @@
+project.lock.json
\ No newline at end of file
diff --git a/src/Gtk/Avalonia.Gtk3/Avalonia.Gtk3.csproj b/src/Gtk/Avalonia.Gtk3/Avalonia.Gtk3.csproj
new file mode 100644
index 0000000000..fe0d10d184
--- /dev/null
+++ b/src/Gtk/Avalonia.Gtk3/Avalonia.Gtk3.csproj
@@ -0,0 +1,102 @@
+
+
+
+
+ 14.0
+ Debug
+ AnyCPU
+ {BB1F7BB5-6AD4-4776-94D9-C09D0A972658}
+ Library
+ Properties
+ Avalonia.Gtk3
+ Avalonia.Gtk3
+ en-US
+ 512
+ {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+
+
+ v5.0
+
+
+ true
+ full
+ false
+ bin\Debug\
+ TRACE;DEBUG;GTK3_PINVOKE
+ prompt
+ 4
+ true
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE;GTK3_PINVOKE
+ prompt
+ 4
+ true
+
+
+
+
+
+
+
+ KeyTransform.cs
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {B09B78D8-9B26-48B0-9149-D64A2F120F3F}
+ Avalonia.Base
+
+
+ {D2221C82-4A25-4583-9B43-D791E3F6820C}
+ Avalonia.Controls
+
+
+ {62024B2D-53EB-4638-B26B-85EEAA54866E}
+ Avalonia.Input
+
+
+ {6b0ed19d-a08b-461c-a9d9-a9ee40b0c06b}
+ Avalonia.Interactivity
+
+
+ {EB582467-6ABB-43A1-B052-E981BA910E3A}
+ Avalonia.SceneGraph
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Gtk/Avalonia.Gtk3/ClipboardImpl.cs b/src/Gtk/Avalonia.Gtk3/ClipboardImpl.cs
new file mode 100644
index 0000000000..333391a064
--- /dev/null
+++ b/src/Gtk/Avalonia.Gtk3/ClipboardImpl.cs
@@ -0,0 +1,53 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+using Avalonia.Gtk3.Interop;
+using Avalonia.Input.Platform;
+
+namespace Avalonia.Gtk3
+{
+ class ClipboardImpl : IClipboard
+ {
+
+ IntPtr GetClipboard() => Native.GtkClipboardGetForDisplay(Native.GdkGetDefaultDisplay(), IntPtr.Zero);
+
+ static void OnText(IntPtr clipboard, IntPtr utf8string, IntPtr userdata)
+ {
+ var handle = GCHandle.FromIntPtr(userdata);
+
+ ((TaskCompletionSource) handle.Target)
+ .TrySetResult(Utf8Buffer.StringFromPtr(utf8string));
+ handle.Free();
+ }
+
+ private static readonly Native.D.GtkClipboardTextReceivedFunc OnTextDelegate = OnText;
+
+ static ClipboardImpl()
+ {
+ GCHandle.Alloc(OnTextDelegate);
+ }
+
+ public Task GetTextAsync()
+ {
+ var tcs = new TaskCompletionSource();
+ Native.GtkClipboardRequestText(GetClipboard(), OnTextDelegate, GCHandle.ToIntPtr(GCHandle.Alloc(tcs)));
+ return tcs.Task;
+ }
+
+ public Task SetTextAsync(string text)
+ {
+ using (var buf = new Utf8Buffer(text))
+ Native.GtkClipboardSetText(GetClipboard(), buf, buf.ByteLen);
+ return Task.FromResult(0);
+ }
+
+ public Task ClearAsync()
+ {
+ Native.GtkClipboardRequestClear(GetClipboard());
+ return Task.FromResult(0);
+ }
+ }
+}
diff --git a/src/Gtk/Avalonia.Gtk3/CursorFactory.cs b/src/Gtk/Avalonia.Gtk3/CursorFactory.cs
new file mode 100644
index 0000000000..ac547b8bc2
--- /dev/null
+++ b/src/Gtk/Avalonia.Gtk3/CursorFactory.cs
@@ -0,0 +1,79 @@
+using System;
+using System.Collections.Generic;
+using Avalonia.Gtk3.Interop;
+using Avalonia.Input;
+using Avalonia.Platform;
+using CursorType = Avalonia.Gtk3.GdkCursorType;
+namespace Avalonia.Gtk3
+{
+ class CursorFactory : IStandardCursorFactory
+ {
+ private static readonly Dictionary CursorTypeMapping = new Dictionary
+
+ {
+ {StandardCursorType.AppStarting, CursorType.Watch},
+ {StandardCursorType.Arrow, CursorType.LeftPtr},
+ {StandardCursorType.Cross, CursorType.Cross},
+ {StandardCursorType.Hand, CursorType.Hand1},
+ {StandardCursorType.Ibeam, CursorType.Xterm},
+ {StandardCursorType.No, "gtk-cancel"},
+ {StandardCursorType.SizeAll, CursorType.Sizing},
+ //{ StandardCursorType.SizeNorthEastSouthWest, 32643 },
+ {StandardCursorType.SizeNorthSouth, CursorType.SbVDoubleArrow},
+ //{ StandardCursorType.SizeNorthWestSouthEast, 32642 },
+ {StandardCursorType.SizeWestEast, CursorType.SbHDoubleArrow},
+ {StandardCursorType.UpArrow, CursorType.BasedArrowUp},
+ {StandardCursorType.Wait, CursorType.Watch},
+ {StandardCursorType.Help, "gtk-help"},
+ {StandardCursorType.TopSide, CursorType.TopSide},
+ {StandardCursorType.BottomSize, CursorType.BottomSide},
+ {StandardCursorType.LeftSide, CursorType.LeftSide},
+ {StandardCursorType.RightSide, CursorType.RightSide},
+ {StandardCursorType.TopLeftCorner, CursorType.TopLeftCorner},
+ {StandardCursorType.TopRightCorner, CursorType.TopRightCorner},
+ {StandardCursorType.BottomLeftCorner, CursorType.BottomLeftCorner},
+ {StandardCursorType.BottomRightCorner, CursorType.BottomRightCorner}
+ };
+
+ private static readonly Dictionary Cache =
+ new Dictionary();
+
+ private IntPtr GetCursor(object desc)
+ {
+ IntPtr rv;
+ var name = desc as string;
+ if (name != null)
+ {
+ var theme = Native.GtkIconThemeGetDefault();
+ IntPtr icon, error;
+ using (var u = new Utf8Buffer(name))
+ icon = Native.GtkIconThemeLoadIcon(theme, u, 32, 0, out error);
+ rv = icon == IntPtr.Zero
+ ? Native.GdkCursorNew(GdkCursorType.XCursor)
+ : Native.GdkCursorNewFromPixbuf(Native.GdkGetDefaultDisplay(), icon, 0, 0);
+ }
+ else
+ {
+ rv = Native.GdkCursorNew((CursorType)desc);
+ }
+
+
+ return rv;
+ }
+
+ public IPlatformHandle GetCursor(StandardCursorType cursorType)
+ {
+ IPlatformHandle rv;
+ if (!Cache.TryGetValue(cursorType, out rv))
+ {
+ Cache[cursorType] =
+ rv =
+ new PlatformHandle(
+ GetCursor(CursorTypeMapping[cursorType]),
+ "GTKCURSOR");
+ }
+
+ return rv;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Gtk/Avalonia.Gtk3/FramebufferManager.cs b/src/Gtk/Avalonia.Gtk3/FramebufferManager.cs
new file mode 100644
index 0000000000..c2685e8791
--- /dev/null
+++ b/src/Gtk/Avalonia.Gtk3/FramebufferManager.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Avalonia.Controls.Platform.Surfaces;
+
+namespace Avalonia.Gtk3
+{
+ class FramebufferManager : IFramebufferPlatformSurface, IDisposable
+ {
+ private readonly TopLevelImpl _window;
+ private ImageSurfaceFramebuffer _fb;
+ public FramebufferManager(TopLevelImpl window)
+ {
+ _window = window;
+ }
+
+ public void Dispose()
+ {
+ _fb?.Deallocate();
+ }
+
+ public ILockedFramebuffer Lock()
+ {
+ if(_window.CurrentCairoContext == IntPtr.Zero)
+ throw new InvalidOperationException("Window is not in drawing state");
+
+ var ctx = _window.CurrentCairoContext;
+ var width = (int) _window.ClientSize.Width;
+ var height = (int) _window.ClientSize.Height;
+ if (_fb == null || _fb.Width != width ||
+ _fb.Height != height)
+ {
+ _fb?.Dispose();
+ _fb = new ImageSurfaceFramebuffer(width, height);
+ }
+ _fb.Prepare(ctx);
+ return _fb;
+ }
+ }
+}
diff --git a/src/Gtk/Avalonia.Gtk3/GdkCursor.cs b/src/Gtk/Avalonia.Gtk3/GdkCursor.cs
new file mode 100644
index 0000000000..48815e1273
--- /dev/null
+++ b/src/Gtk/Avalonia.Gtk3/GdkCursor.cs
@@ -0,0 +1,91 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Avalonia.Gtk3
+{
+ enum GdkCursorType
+ {
+ CursorIsPixmap = -1,
+ XCursor = 0,
+ Arrow = 2,
+ BasedArrowDown = 4,
+ BasedArrowUp = 6,
+ Boat = 8,
+ Bogosity = 10,
+ BottomLeftCorner = 12,
+ BottomRightCorner = 14,
+ BottomSide = 16,
+ BottomTee = 18,
+ BoxSpiral = 20,
+ CenterPtr = 22,
+ Circle = 24,
+ Clock = 26,
+ CoffeeMug = 28,
+ Cross = 30,
+ CrossReverse = 32,
+ Crosshair = 34,
+ DiamondCross = 36,
+ Dot = 38,
+ Dotbox = 40,
+ DoubleArrow = 42,
+ DraftLarge = 44,
+ DraftSmall = 46,
+ DrapedBox = 48,
+ Exchange = 50,
+ Fleur = 52,
+ Gobbler = 54,
+ Gumby = 56,
+ Hand1 = 58,
+ Hand2 = 60,
+ Heart = 62,
+ Icon = 64,
+ IronCross = 66,
+ LeftPtr = 68,
+ LeftSide = 70,
+ LeftTee = 72,
+ Leftbutton = 74,
+ LlAngle = 76,
+ LrAngle = 78,
+ Man = 80,
+ Middlebutton = 82,
+ Mouse = 84,
+ Pencil = 86,
+ Pirate = 88,
+ Plus = 90,
+ QuestionArrow = 92,
+ RightPtr = 94,
+ RightSide = 96,
+ RightTee = 98,
+ Rightbutton = 100,
+ RtlLogo = 102,
+ Sailboat = 104,
+ SbDownArrow = 106,
+ SbHDoubleArrow = 108,
+ SbLeftArrow = 110,
+ SbRightArrow = 112,
+ SbUpArrow = 114,
+ SbVDoubleArrow = 116,
+ Shuttle = 118,
+ Sizing = 120,
+ Spider = 122,
+ Spraycan = 124,
+ Star = 126,
+ Target = 128,
+ Tcross = 130,
+ TopLeftArrow = 132,
+ TopLeftCorner = 134,
+ TopRightCorner = 136,
+ TopSide = 138,
+ TopTee = 140,
+ Trek = 142,
+ UlAngle = 144,
+ Umbrella = 146,
+ UrAngle = 148,
+ Watch = 150,
+ Xterm = 152,
+ LastCursor = 153,
+ }
+}
\ No newline at end of file
diff --git a/src/Gtk/Avalonia.Gtk3/GdkKey.cs b/src/Gtk/Avalonia.Gtk3/GdkKey.cs
new file mode 100644
index 0000000000..b4a0f31b92
--- /dev/null
+++ b/src/Gtk/Avalonia.Gtk3/GdkKey.cs
@@ -0,0 +1,1347 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Avalonia.Gtk3
+{
+ enum GdkKey
+ {
+ space = 32,
+ exclam = 33,
+ quotedbl = 34,
+ numbersign = 35,
+ dollar = 36,
+ percent = 37,
+ ampersand = 38,
+ apostrophe = 39,
+ quoteright = 39,
+ parenleft = 40,
+ parenright = 41,
+ asterisk = 42,
+ plus = 43,
+ comma = 44,
+ minus = 45,
+ period = 46,
+ slash = 47,
+ Key_0 = 48,
+ Key_1 = 49,
+ Key_2 = 50,
+ Key_3 = 51,
+ Key_4 = 52,
+ Key_5 = 53,
+ Key_6 = 54,
+ Key_7 = 55,
+ Key_8 = 56,
+ Key_9 = 57,
+ colon = 58,
+ semicolon = 59,
+ less = 60,
+ equal = 61,
+ greater = 62,
+ question = 63,
+ at = 64,
+ A = 65,
+ B = 66,
+ C = 67,
+ D = 68,
+ E = 69,
+ F = 70,
+ G = 71,
+ H = 72,
+ I = 73,
+ J = 74,
+ K = 75,
+ L = 76,
+ M = 77,
+ N = 78,
+ O = 79,
+ P = 80,
+ Q = 81,
+ R = 82,
+ S = 83,
+ T = 84,
+ U = 85,
+ V = 86,
+ W = 87,
+ X = 88,
+ Y = 89,
+ Z = 90,
+ bracketleft = 91,
+ backslash = 92,
+ bracketright = 93,
+ asciicircum = 94,
+ underscore = 95,
+ grave = 96,
+ quoteleft = 96,
+ a = 97,
+ b = 98,
+ c = 99,
+ d = 100,
+ e = 101,
+ f = 102,
+ g = 103,
+ h = 104,
+ i = 105,
+ j = 106,
+ k = 107,
+ l = 108,
+ m = 109,
+ n = 110,
+ o = 111,
+ p = 112,
+ q = 113,
+ r = 114,
+ s = 115,
+ t = 116,
+ u = 117,
+ v = 118,
+ w = 119,
+ x = 120,
+ y = 121,
+ z = 122,
+ braceleft = 123,
+ bar = 124,
+ braceright = 125,
+ asciitilde = 126,
+ nobreakspace = 160,
+ exclamdown = 161,
+ cent = 162,
+ sterling = 163,
+ currency = 164,
+ yen = 165,
+ brokenbar = 166,
+ section = 167,
+ diaeresis = 168,
+ copyright = 169,
+ ordfeminine = 170,
+ guillemotleft = 171,
+ notsign = 172,
+ hyphen = 173,
+ registered = 174,
+ macron = 175,
+ degree = 176,
+ plusminus = 177,
+ twosuperior = 178,
+ threesuperior = 179,
+ acute = 180,
+ mu = 181,
+ paragraph = 182,
+ periodcentered = 183,
+ cedilla = 184,
+ onesuperior = 185,
+ masculine = 186,
+ guillemotright = 187,
+ onequarter = 188,
+ onehalf = 189,
+ threequarters = 190,
+ questiondown = 191,
+ Agrave = 192,
+ Aacute = 193,
+ Acircumflex = 194,
+ Atilde = 195,
+ Adiaeresis = 196,
+ Aring = 197,
+ AE = 198,
+ Ccedilla = 199,
+ Egrave = 200,
+ Eacute = 201,
+ Ecircumflex = 202,
+ Ediaeresis = 203,
+ Igrave = 204,
+ Iacute = 205,
+ Icircumflex = 206,
+ Idiaeresis = 207,
+ ETH = 208,
+ Eth = 208,
+ Ntilde = 209,
+ Ograve = 210,
+ Oacute = 211,
+ Ocircumflex = 212,
+ Otilde = 213,
+ Odiaeresis = 214,
+ multiply = 215,
+ Ooblique = 216,
+ Ugrave = 217,
+ Uacute = 218,
+ Ucircumflex = 219,
+ Udiaeresis = 220,
+ Yacute = 221,
+ THORN = 222,
+ Thorn = 222,
+ ssharp = 223,
+ agrave = 224,
+ aacute = 225,
+ acircumflex = 226,
+ atilde = 227,
+ adiaeresis = 228,
+ aring = 229,
+ ae = 230,
+ ccedilla = 231,
+ egrave = 232,
+ eacute = 233,
+ ecircumflex = 234,
+ ediaeresis = 235,
+ igrave = 236,
+ iacute = 237,
+ icircumflex = 238,
+ idiaeresis = 239,
+ eth = 240,
+ ntilde = 241,
+ ograve = 242,
+ oacute = 243,
+ ocircumflex = 244,
+ otilde = 245,
+ odiaeresis = 246,
+ division = 247,
+ oslash = 248,
+ ugrave = 249,
+ uacute = 250,
+ ucircumflex = 251,
+ udiaeresis = 252,
+ yacute = 253,
+ thorn = 254,
+ ydiaeresis = 255,
+ Aogonek = 417,
+ breve = 418,
+ Lstroke = 419,
+ Lcaron = 421,
+ Sacute = 422,
+ Scaron = 425,
+ Scedilla = 426,
+ Tcaron = 427,
+ Zacute = 428,
+ Zcaron = 430,
+ Zabovedot = 431,
+ aogonek = 433,
+ ogonek = 434,
+ lstroke = 435,
+ lcaron = 437,
+ sacute = 438,
+ caron = 439,
+ scaron = 441,
+ scedilla = 442,
+ tcaron = 443,
+ zacute = 444,
+ doubleacute = 445,
+ zcaron = 446,
+ zabovedot = 447,
+ Racute = 448,
+ Abreve = 451,
+ Lacute = 453,
+ Cacute = 454,
+ Ccaron = 456,
+ Eogonek = 458,
+ Ecaron = 460,
+ Dcaron = 463,
+ Dstroke = 464,
+ Nacute = 465,
+ Ncaron = 466,
+ Odoubleacute = 469,
+ Rcaron = 472,
+ Uring = 473,
+ Udoubleacute = 475,
+ Tcedilla = 478,
+ racute = 480,
+ abreve = 483,
+ lacute = 485,
+ cacute = 486,
+ ccaron = 488,
+ eogonek = 490,
+ ecaron = 492,
+ dcaron = 495,
+ dstroke = 496,
+ nacute = 497,
+ ncaron = 498,
+ odoubleacute = 501,
+ rcaron = 504,
+ uring = 505,
+ udoubleacute = 507,
+ tcedilla = 510,
+ abovedot = 511,
+ Hstroke = 673,
+ Hcircumflex = 678,
+ Iabovedot = 681,
+ Gbreve = 683,
+ Jcircumflex = 684,
+ hstroke = 689,
+ hcircumflex = 694,
+ idotless = 697,
+ gbreve = 699,
+ jcircumflex = 700,
+ Cabovedot = 709,
+ Ccircumflex = 710,
+ Gabovedot = 725,
+ Gcircumflex = 728,
+ Ubreve = 733,
+ Scircumflex = 734,
+ cabovedot = 741,
+ ccircumflex = 742,
+ gabovedot = 757,
+ gcircumflex = 760,
+ ubreve = 765,
+ scircumflex = 766,
+ kappa = 930,
+ kra = 930,
+ Rcedilla = 931,
+ Itilde = 933,
+ Lcedilla = 934,
+ Emacron = 938,
+ Gcedilla = 939,
+ Tslash = 940,
+ rcedilla = 947,
+ itilde = 949,
+ lcedilla = 950,
+ emacron = 954,
+ gcedilla = 955,
+ tslash = 956,
+ ENG = 957,
+ eng = 959,
+ Amacron = 960,
+ Iogonek = 967,
+ Eabovedot = 972,
+ Imacron = 975,
+ Ncedilla = 977,
+ Omacron = 978,
+ Kcedilla = 979,
+ Uogonek = 985,
+ Utilde = 989,
+ Umacron = 990,
+ amacron = 992,
+ iogonek = 999,
+ eabovedot = 1004,
+ imacron = 1007,
+ ncedilla = 1009,
+ omacron = 1010,
+ kcedilla = 1011,
+ uogonek = 1017,
+ utilde = 1021,
+ umacron = 1022,
+ overline = 1150,
+ kana_fullstop = 1185,
+ kana_openingbracket = 1186,
+ kana_closingbracket = 1187,
+ kana_comma = 1188,
+ kana_conjunctive = 1189,
+ kana_middledot = 1189,
+ kana_WO = 1190,
+ kana_a = 1191,
+ kana_i = 1192,
+ kana_u = 1193,
+ kana_e = 1194,
+ kana_o = 1195,
+ kana_ya = 1196,
+ kana_yu = 1197,
+ kana_yo = 1198,
+ kana_tsu = 1199,
+ kana_tu = 1199,
+ prolongedsound = 1200,
+ kana_A = 1201,
+ kana_I = 1202,
+ kana_U = 1203,
+ kana_E = 1204,
+ kana_O = 1205,
+ kana_KA = 1206,
+ kana_KI = 1207,
+ kana_KU = 1208,
+ kana_KE = 1209,
+ kana_KO = 1210,
+ kana_SA = 1211,
+ kana_SHI = 1212,
+ kana_SU = 1213,
+ kana_SE = 1214,
+ kana_SO = 1215,
+ kana_TA = 1216,
+ kana_CHI = 1217,
+ kana_TI = 1217,
+ kana_TSU = 1218,
+ kana_TU = 1218,
+ kana_TE = 1219,
+ kana_TO = 1220,
+ kana_NA = 1221,
+ kana_NI = 1222,
+ kana_NU = 1223,
+ kana_NE = 1224,
+ kana_NO = 1225,
+ kana_HA = 1226,
+ kana_HI = 1227,
+ kana_FU = 1228,
+ kana_HU = 1228,
+ kana_HE = 1229,
+ kana_HO = 1230,
+ kana_MA = 1231,
+ kana_MI = 1232,
+ kana_MU = 1233,
+ kana_ME = 1234,
+ kana_MO = 1235,
+ kana_YA = 1236,
+ kana_YU = 1237,
+ kana_YO = 1238,
+ kana_RA = 1239,
+ kana_RI = 1240,
+ kana_RU = 1241,
+ kana_RE = 1242,
+ kana_RO = 1243,
+ kana_WA = 1244,
+ kana_N = 1245,
+ voicedsound = 1246,
+ semivoicedsound = 1247,
+ Arabic_comma = 1452,
+ Arabic_semicolon = 1467,
+ Arabic_question_mark = 1471,
+ Arabic_hamza = 1473,
+ Arabic_maddaonalef = 1474,
+ Arabic_hamzaonalef = 1475,
+ Arabic_hamzaonwaw = 1476,
+ Arabic_hamzaunderalef = 1477,
+ Arabic_hamzaonyeh = 1478,
+ Arabic_alef = 1479,
+ Arabic_beh = 1480,
+ Arabic_tehmarbuta = 1481,
+ Arabic_teh = 1482,
+ Arabic_theh = 1483,
+ Arabic_jeem = 1484,
+ Arabic_hah = 1485,
+ Arabic_khah = 1486,
+ Arabic_dal = 1487,
+ Arabic_thal = 1488,
+ Arabic_ra = 1489,
+ Arabic_zain = 1490,
+ Arabic_seen = 1491,
+ Arabic_sheen = 1492,
+ Arabic_sad = 1493,
+ Arabic_dad = 1494,
+ Arabic_tah = 1495,
+ Arabic_zah = 1496,
+ Arabic_ain = 1497,
+ Arabic_ghain = 1498,
+ Arabic_tatweel = 1504,
+ Arabic_feh = 1505,
+ Arabic_qaf = 1506,
+ Arabic_kaf = 1507,
+ Arabic_lam = 1508,
+ Arabic_meem = 1509,
+ Arabic_noon = 1510,
+ Arabic_ha = 1511,
+ Arabic_heh = 1511,
+ Arabic_waw = 1512,
+ Arabic_alefmaksura = 1513,
+ Arabic_yeh = 1514,
+ Arabic_fathatan = 1515,
+ Arabic_dammatan = 1516,
+ Arabic_kasratan = 1517,
+ Arabic_fatha = 1518,
+ Arabic_damma = 1519,
+ Arabic_kasra = 1520,
+ Arabic_shadda = 1521,
+ Arabic_sukun = 1522,
+ Serbian_dje = 1697,
+ Macedonia_gje = 1698,
+ Cyrillic_io = 1699,
+ Ukrainian_ie = 1700,
+ Ukranian_je = 1700,
+ Macedonia_dse = 1701,
+ Ukrainian_i = 1702,
+ Ukranian_i = 1702,
+ Ukrainian_yi = 1703,
+ Ukranian_yi = 1703,
+ Cyrillic_je = 1704,
+ Serbian_je = 1704,
+ Cyrillic_lje = 1705,
+ Serbian_lje = 1705,
+ Cyrillic_nje = 1706,
+ Serbian_nje = 1706,
+ Serbian_tshe = 1707,
+ Macedonia_kje = 1708,
+ Byelorussian_shortu = 1710,
+ Cyrillic_dzhe = 1711,
+ Serbian_dze = 1711,
+ numerosign = 1712,
+ Serbian_DJE = 1713,
+ Macedonia_GJE = 1714,
+ Cyrillic_IO = 1715,
+ Ukrainian_IE = 1716,
+ Ukranian_JE = 1716,
+ Macedonia_DSE = 1717,
+ Ukrainian_I = 1718,
+ Ukranian_I = 1718,
+ Ukrainian_YI = 1719,
+ Ukranian_YI = 1719,
+ Cyrillic_JE = 1720,
+ Serbian_JE = 1720,
+ Cyrillic_LJE = 1721,
+ Serbian_LJE = 1721,
+ Cyrillic_NJE = 1722,
+ Serbian_NJE = 1722,
+ Serbian_TSHE = 1723,
+ Macedonia_KJE = 1724,
+ Byelorussian_SHORTU = 1726,
+ Cyrillic_DZHE = 1727,
+ Serbian_DZE = 1727,
+ Cyrillic_yu = 1728,
+ Cyrillic_a = 1729,
+ Cyrillic_be = 1730,
+ Cyrillic_tse = 1731,
+ Cyrillic_de = 1732,
+ Cyrillic_ie = 1733,
+ Cyrillic_ef = 1734,
+ Cyrillic_ghe = 1735,
+ Cyrillic_ha = 1736,
+ Cyrillic_i = 1737,
+ Cyrillic_shorti = 1738,
+ Cyrillic_ka = 1739,
+ Cyrillic_el = 1740,
+ Cyrillic_em = 1741,
+ Cyrillic_en = 1742,
+ Cyrillic_o = 1743,
+ Cyrillic_pe = 1744,
+ Cyrillic_ya = 1745,
+ Cyrillic_er = 1746,
+ Cyrillic_es = 1747,
+ Cyrillic_te = 1748,
+ Cyrillic_u = 1749,
+ Cyrillic_zhe = 1750,
+ Cyrillic_ve = 1751,
+ Cyrillic_softsign = 1752,
+ Cyrillic_yeru = 1753,
+ Cyrillic_ze = 1754,
+ Cyrillic_sha = 1755,
+ Cyrillic_e = 1756,
+ Cyrillic_shcha = 1757,
+ Cyrillic_che = 1758,
+ Cyrillic_hardsign = 1759,
+ Cyrillic_YU = 1760,
+ Cyrillic_A = 1761,
+ Cyrillic_BE = 1762,
+ Cyrillic_TSE = 1763,
+ Cyrillic_DE = 1764,
+ Cyrillic_IE = 1765,
+ Cyrillic_EF = 1766,
+ Cyrillic_GHE = 1767,
+ Cyrillic_HA = 1768,
+ Cyrillic_I = 1769,
+ Cyrillic_SHORTI = 1770,
+ Cyrillic_KA = 1771,
+ Cyrillic_EL = 1772,
+ Cyrillic_EM = 1773,
+ Cyrillic_EN = 1774,
+ Cyrillic_O = 1775,
+ Cyrillic_PE = 1776,
+ Cyrillic_YA = 1777,
+ Cyrillic_ER = 1778,
+ Cyrillic_ES = 1779,
+ Cyrillic_TE = 1780,
+ Cyrillic_U = 1781,
+ Cyrillic_ZHE = 1782,
+ Cyrillic_VE = 1783,
+ Cyrillic_SOFTSIGN = 1784,
+ Cyrillic_YERU = 1785,
+ Cyrillic_ZE = 1786,
+ Cyrillic_SHA = 1787,
+ Cyrillic_E = 1788,
+ Cyrillic_SHCHA = 1789,
+ Cyrillic_CHE = 1790,
+ Cyrillic_HARDSIGN = 1791,
+ Greek_ALPHAaccent = 1953,
+ Greek_EPSILONaccent = 1954,
+ Greek_ETAaccent = 1955,
+ Greek_IOTAaccent = 1956,
+ Greek_IOTAdiaeresis = 1957,
+ Greek_OMICRONaccent = 1959,
+ Greek_UPSILONaccent = 1960,
+ Greek_UPSILONdieresis = 1961,
+ Greek_OMEGAaccent = 1963,
+ Greek_accentdieresis = 1966,
+ Greek_horizbar = 1967,
+ Greek_alphaaccent = 1969,
+ Greek_epsilonaccent = 1970,
+ Greek_etaaccent = 1971,
+ Greek_iotaaccent = 1972,
+ Greek_iotadieresis = 1973,
+ Greek_iotaaccentdieresis = 1974,
+ Greek_omicronaccent = 1975,
+ Greek_upsilonaccent = 1976,
+ Greek_upsilondieresis = 1977,
+ Greek_upsilonaccentdieresis = 1978,
+ Greek_omegaaccent = 1979,
+ Greek_ALPHA = 1985,
+ Greek_BETA = 1986,
+ Greek_GAMMA = 1987,
+ Greek_DELTA = 1988,
+ Greek_EPSILON = 1989,
+ Greek_ZETA = 1990,
+ Greek_ETA = 1991,
+ Greek_THETA = 1992,
+ Greek_IOTA = 1993,
+ Greek_KAPPA = 1994,
+ Greek_LAMBDA = 1995,
+ Greek_LAMDA = 1995,
+ Greek_MU = 1996,
+ Greek_NU = 1997,
+ Greek_XI = 1998,
+ Greek_OMICRON = 1999,
+ Greek_PI = 2000,
+ Greek_RHO = 2001,
+ Greek_SIGMA = 2002,
+ Greek_TAU = 2004,
+ Greek_UPSILON = 2005,
+ Greek_PHI = 2006,
+ Greek_CHI = 2007,
+ Greek_PSI = 2008,
+ Greek_OMEGA = 2009,
+ Greek_alpha = 2017,
+ Greek_beta = 2018,
+ Greek_gamma = 2019,
+ Greek_delta = 2020,
+ Greek_epsilon = 2021,
+ Greek_zeta = 2022,
+ Greek_eta = 2023,
+ Greek_theta = 2024,
+ Greek_iota = 2025,
+ Greek_kappa = 2026,
+ Greek_lambda = 2027,
+ Greek_lamda = 2027,
+ Greek_mu = 2028,
+ Greek_nu = 2029,
+ Greek_xi = 2030,
+ Greek_omicron = 2031,
+ Greek_pi = 2032,
+ Greek_rho = 2033,
+ Greek_sigma = 2034,
+ Greek_finalsmallsigma = 2035,
+ Greek_tau = 2036,
+ Greek_upsilon = 2037,
+ Greek_phi = 2038,
+ Greek_chi = 2039,
+ Greek_psi = 2040,
+ Greek_omega = 2041,
+ leftradical = 2209,
+ topleftradical = 2210,
+ horizconnector = 2211,
+ topintegral = 2212,
+ botintegral = 2213,
+ vertconnector = 2214,
+ topleftsqbracket = 2215,
+ botleftsqbracket = 2216,
+ toprightsqbracket = 2217,
+ botrightsqbracket = 2218,
+ topleftparens = 2219,
+ botleftparens = 2220,
+ toprightparens = 2221,
+ botrightparens = 2222,
+ leftmiddlecurlybrace = 2223,
+ rightmiddlecurlybrace = 2224,
+ topleftsummation = 2225,
+ botleftsummation = 2226,
+ topvertsummationconnector = 2227,
+ botvertsummationconnector = 2228,
+ toprightsummation = 2229,
+ botrightsummation = 2230,
+ rightmiddlesummation = 2231,
+ lessthanequal = 2236,
+ notequal = 2237,
+ greaterthanequal = 2238,
+ integral = 2239,
+ therefore = 2240,
+ variation = 2241,
+ infinity = 2242,
+ nabla = 2245,
+ approximate = 2248,
+ similarequal = 2249,
+ ifonlyif = 2253,
+ implies = 2254,
+ identical = 2255,
+ radical = 2262,
+ includedin = 2266,
+ includes = 2267,
+ intersection = 2268,
+ union = 2269,
+ logicaland = 2270,
+ logicalor = 2271,
+ partialderivative = 2287,
+ function = 2294,
+ leftarrow = 2299,
+ uparrow = 2300,
+ rightarrow = 2301,
+ downarrow = 2302,
+ blank = 2527,
+ soliddiamond = 2528,
+ checkerboard = 2529,
+ ht = 2530,
+ ff = 2531,
+ cr = 2532,
+ lf = 2533,
+ nl = 2536,
+ vt = 2537,
+ lowrightcorner = 2538,
+ uprightcorner = 2539,
+ upleftcorner = 2540,
+ lowleftcorner = 2541,
+ crossinglines = 2542,
+ horizlinescan1 = 2543,
+ horizlinescan3 = 2544,
+ horizlinescan5 = 2545,
+ horizlinescan7 = 2546,
+ horizlinescan9 = 2547,
+ leftt = 2548,
+ rightt = 2549,
+ bott = 2550,
+ topt = 2551,
+ vertbar = 2552,
+ emspace = 2721,
+ enspace = 2722,
+ em3space = 2723,
+ em4space = 2724,
+ digitspace = 2725,
+ punctspace = 2726,
+ thinspace = 2727,
+ hairspace = 2728,
+ emdash = 2729,
+ endash = 2730,
+ signifblank = 2732,
+ ellipsis = 2734,
+ doubbaselinedot = 2735,
+ onethird = 2736,
+ twothirds = 2737,
+ onefifth = 2738,
+ twofifths = 2739,
+ threefifths = 2740,
+ fourfifths = 2741,
+ onesixth = 2742,
+ fivesixths = 2743,
+ careof = 2744,
+ figdash = 2747,
+ leftanglebracket = 2748,
+ decimalpoint = 2749,
+ rightanglebracket = 2750,
+ marker = 2751,
+ oneeighth = 2755,
+ threeeighths = 2756,
+ fiveeighths = 2757,
+ seveneighths = 2758,
+ trademark = 2761,
+ signaturemark = 2762,
+ trademarkincircle = 2763,
+ leftopentriangle = 2764,
+ rightopentriangle = 2765,
+ emopencircle = 2766,
+ emopenrectangle = 2767,
+ leftsinglequotemark = 2768,
+ rightsinglequotemark = 2769,
+ leftdoublequotemark = 2770,
+ rightdoublequotemark = 2771,
+ prescription = 2772,
+ minutes = 2774,
+ seconds = 2775,
+ latincross = 2777,
+ hexagram = 2778,
+ filledrectbullet = 2779,
+ filledlefttribullet = 2780,
+ filledrighttribullet = 2781,
+ emfilledcircle = 2782,
+ emfilledrect = 2783,
+ enopencircbullet = 2784,
+ enopensquarebullet = 2785,
+ openrectbullet = 2786,
+ opentribulletup = 2787,
+ opentribulletdown = 2788,
+ openstar = 2789,
+ enfilledcircbullet = 2790,
+ enfilledsqbullet = 2791,
+ filledtribulletup = 2792,
+ filledtribulletdown = 2793,
+ leftpointer = 2794,
+ rightpointer = 2795,
+ club = 2796,
+ diamond = 2797,
+ heart = 2798,
+ maltesecross = 2800,
+ dagger = 2801,
+ doubledagger = 2802,
+ checkmark = 2803,
+ ballotcross = 2804,
+ musicalsharp = 2805,
+ musicalflat = 2806,
+ malesymbol = 2807,
+ femalesymbol = 2808,
+ telephone = 2809,
+ telephonerecorder = 2810,
+ phonographcopyright = 2811,
+ caret = 2812,
+ singlelowquotemark = 2813,
+ doublelowquotemark = 2814,
+ cursor = 2815,
+ leftcaret = 2979,
+ rightcaret = 2982,
+ downcaret = 2984,
+ upcaret = 2985,
+ overbar = 3008,
+ downtack = 3010,
+ upshoe = 3011,
+ downstile = 3012,
+ underbar = 3014,
+ jot = 3018,
+ quad = 3020,
+ uptack = 3022,
+ circle = 3023,
+ upstile = 3027,
+ downshoe = 3030,
+ rightshoe = 3032,
+ leftshoe = 3034,
+ lefttack = 3036,
+ righttack = 3068,
+ hebrew_doublelowline = 3295,
+ hebrew_aleph = 3296,
+ hebrew_bet = 3297,
+ hebrew_beth = 3297,
+ hebrew_gimel = 3298,
+ hebrew_gimmel = 3298,
+ hebrew_dalet = 3299,
+ hebrew_daleth = 3299,
+ hebrew_he = 3300,
+ hebrew_waw = 3301,
+ hebrew_zain = 3302,
+ hebrew_zayin = 3302,
+ hebrew_chet = 3303,
+ hebrew_het = 3303,
+ hebrew_tet = 3304,
+ hebrew_teth = 3304,
+ hebrew_yod = 3305,
+ hebrew_finalkaph = 3306,
+ hebrew_kaph = 3307,
+ hebrew_lamed = 3308,
+ hebrew_finalmem = 3309,
+ hebrew_mem = 3310,
+ hebrew_finalnun = 3311,
+ hebrew_nun = 3312,
+ hebrew_samech = 3313,
+ hebrew_samekh = 3313,
+ hebrew_ayin = 3314,
+ hebrew_finalpe = 3315,
+ hebrew_pe = 3316,
+ hebrew_finalzade = 3317,
+ hebrew_finalzadi = 3317,
+ hebrew_zade = 3318,
+ hebrew_zadi = 3318,
+ hebrew_kuf = 3319,
+ hebrew_qoph = 3319,
+ hebrew_resh = 3320,
+ hebrew_shin = 3321,
+ hebrew_taf = 3322,
+ hebrew_taw = 3322,
+ Thai_kokai = 3489,
+ Thai_khokhai = 3490,
+ Thai_khokhuat = 3491,
+ Thai_khokhwai = 3492,
+ Thai_khokhon = 3493,
+ Thai_khorakhang = 3494,
+ Thai_ngongu = 3495,
+ Thai_chochan = 3496,
+ Thai_choching = 3497,
+ Thai_chochang = 3498,
+ Thai_soso = 3499,
+ Thai_chochoe = 3500,
+ Thai_yoying = 3501,
+ Thai_dochada = 3502,
+ Thai_topatak = 3503,
+ Thai_thothan = 3504,
+ Thai_thonangmontho = 3505,
+ Thai_thophuthao = 3506,
+ Thai_nonen = 3507,
+ Thai_dodek = 3508,
+ Thai_totao = 3509,
+ Thai_thothung = 3510,
+ Thai_thothahan = 3511,
+ Thai_thothong = 3512,
+ Thai_nonu = 3513,
+ Thai_bobaimai = 3514,
+ Thai_popla = 3515,
+ Thai_phophung = 3516,
+ Thai_fofa = 3517,
+ Thai_phophan = 3518,
+ Thai_fofan = 3519,
+ Thai_phosamphao = 3520,
+ Thai_moma = 3521,
+ Thai_yoyak = 3522,
+ Thai_rorua = 3523,
+ Thai_ru = 3524,
+ Thai_loling = 3525,
+ Thai_lu = 3526,
+ Thai_wowaen = 3527,
+ Thai_sosala = 3528,
+ Thai_sorusi = 3529,
+ Thai_sosua = 3530,
+ Thai_hohip = 3531,
+ Thai_lochula = 3532,
+ Thai_oang = 3533,
+ Thai_honokhuk = 3534,
+ Thai_paiyannoi = 3535,
+ Thai_saraa = 3536,
+ Thai_maihanakat = 3537,
+ Thai_saraaa = 3538,
+ Thai_saraam = 3539,
+ Thai_sarai = 3540,
+ Thai_saraii = 3541,
+ Thai_saraue = 3542,
+ Thai_sarauee = 3543,
+ Thai_sarau = 3544,
+ Thai_sarauu = 3545,
+ Thai_phinthu = 3546,
+ Thai_maihanakat_maitho = 3550,
+ Thai_baht = 3551,
+ Thai_sarae = 3552,
+ Thai_saraae = 3553,
+ Thai_sarao = 3554,
+ Thai_saraaimaimuan = 3555,
+ Thai_saraaimaimalai = 3556,
+ Thai_lakkhangyao = 3557,
+ Thai_maiyamok = 3558,
+ Thai_maitaikhu = 3559,
+ Thai_maiek = 3560,
+ Thai_maitho = 3561,
+ Thai_maitri = 3562,
+ Thai_maichattawa = 3563,
+ Thai_thanthakhat = 3564,
+ Thai_nikhahit = 3565,
+ Thai_leksun = 3568,
+ Thai_leknung = 3569,
+ Thai_leksong = 3570,
+ Thai_leksam = 3571,
+ Thai_leksi = 3572,
+ Thai_lekha = 3573,
+ Thai_lekhok = 3574,
+ Thai_lekchet = 3575,
+ Thai_lekpaet = 3576,
+ Thai_lekkao = 3577,
+ Hangul_Kiyeog = 3745,
+ Hangul_SsangKiyeog = 3746,
+ Hangul_KiyeogSios = 3747,
+ Hangul_Nieun = 3748,
+ Hangul_NieunJieuj = 3749,
+ Hangul_NieunHieuh = 3750,
+ Hangul_Dikeud = 3751,
+ Hangul_SsangDikeud = 3752,
+ Hangul_Rieul = 3753,
+ Hangul_RieulKiyeog = 3754,
+ Hangul_RieulMieum = 3755,
+ Hangul_RieulPieub = 3756,
+ Hangul_RieulSios = 3757,
+ Hangul_RieulTieut = 3758,
+ Hangul_RieulPhieuf = 3759,
+ Hangul_RieulHieuh = 3760,
+ Hangul_Mieum = 3761,
+ Hangul_Pieub = 3762,
+ Hangul_SsangPieub = 3763,
+ Hangul_PieubSios = 3764,
+ Hangul_Sios = 3765,
+ Hangul_SsangSios = 3766,
+ Hangul_Ieung = 3767,
+ Hangul_Jieuj = 3768,
+ Hangul_SsangJieuj = 3769,
+ Hangul_Cieuc = 3770,
+ Hangul_Khieuq = 3771,
+ Hangul_Tieut = 3772,
+ Hangul_Phieuf = 3773,
+ Hangul_Hieuh = 3774,
+ Hangul_A = 3775,
+ Hangul_AE = 3776,
+ Hangul_YA = 3777,
+ Hangul_YAE = 3778,
+ Hangul_EO = 3779,
+ Hangul_E = 3780,
+ Hangul_YEO = 3781,
+ Hangul_YE = 3782,
+ Hangul_O = 3783,
+ Hangul_WA = 3784,
+ Hangul_WAE = 3785,
+ Hangul_OE = 3786,
+ Hangul_YO = 3787,
+ Hangul_U = 3788,
+ Hangul_WEO = 3789,
+ Hangul_WE = 3790,
+ Hangul_WI = 3791,
+ Hangul_YU = 3792,
+ Hangul_EU = 3793,
+ Hangul_YI = 3794,
+ Hangul_I = 3795,
+ Hangul_J_Kiyeog = 3796,
+ Hangul_J_SsangKiyeog = 3797,
+ Hangul_J_KiyeogSios = 3798,
+ Hangul_J_Nieun = 3799,
+ Hangul_J_NieunJieuj = 3800,
+ Hangul_J_NieunHieuh = 3801,
+ Hangul_J_Dikeud = 3802,
+ Hangul_J_Rieul = 3803,
+ Hangul_J_RieulKiyeog = 3804,
+ Hangul_J_RieulMieum = 3805,
+ Hangul_J_RieulPieub = 3806,
+ Hangul_J_RieulSios = 3807,
+ Hangul_J_RieulTieut = 3808,
+ Hangul_J_RieulPhieuf = 3809,
+ Hangul_J_RieulHieuh = 3810,
+ Hangul_J_Mieum = 3811,
+ Hangul_J_Pieub = 3812,
+ Hangul_J_PieubSios = 3813,
+ Hangul_J_Sios = 3814,
+ Hangul_J_SsangSios = 3815,
+ Hangul_J_Ieung = 3816,
+ Hangul_J_Jieuj = 3817,
+ Hangul_J_Cieuc = 3818,
+ Hangul_J_Khieuq = 3819,
+ Hangul_J_Tieut = 3820,
+ Hangul_J_Phieuf = 3821,
+ Hangul_J_Hieuh = 3822,
+ Hangul_RieulYeorinHieuh = 3823,
+ Hangul_SunkyeongeumMieum = 3824,
+ Hangul_SunkyeongeumPieub = 3825,
+ Hangul_PanSios = 3826,
+ Hangul_KkogjiDalrinIeung = 3827,
+ Hangul_SunkyeongeumPhieuf = 3828,
+ Hangul_YeorinHieuh = 3829,
+ Hangul_AraeA = 3830,
+ Hangul_AraeAE = 3831,
+ Hangul_J_PanSios = 3832,
+ Hangul_J_KkogjiDalrinIeung = 3833,
+ Hangul_J_YeorinHieuh = 3834,
+ Korean_Won = 3839,
+ OE = 5052,
+ oe = 5053,
+ Ydiaeresis = 5054,
+ EcuSign = 8352,
+ ColonSign = 8353,
+ CruzeiroSign = 8354,
+ FFrancSign = 8355,
+ LiraSign = 8356,
+ MillSign = 8357,
+ NairaSign = 8358,
+ PesetaSign = 8359,
+ RupeeSign = 8360,
+ WonSign = 8361,
+ NewSheqelSign = 8362,
+ DongSign = 8363,
+ EuroSign = 8364,
+ Key_3270_Duplicate = 64769,
+ Key_3270_FieldMark = 64770,
+ Key_3270_Right2 = 64771,
+ Key_3270_Left2 = 64772,
+ Key_3270_BackTab = 64773,
+ Key_3270_EraseEOF = 64774,
+ Key_3270_EraseInput = 64775,
+ Key_3270_Reset = 64776,
+ Key_3270_Quit = 64777,
+ Key_3270_PA1 = 64778,
+ Key_3270_PA2 = 64779,
+ Key_3270_PA3 = 64780,
+ Key_3270_Test = 64781,
+ Key_3270_Attn = 64782,
+ Key_3270_CursorBlink = 64783,
+ Key_3270_AltCursor = 64784,
+ Key_3270_KeyClick = 64785,
+ Key_3270_Jump = 64786,
+ Key_3270_Ident = 64787,
+ Key_3270_Rule = 64788,
+ Key_3270_Copy = 64789,
+ Key_3270_Play = 64790,
+ Key_3270_Setup = 64791,
+ Key_3270_Record = 64792,
+ Key_3270_ChangeScreen = 64793,
+ Key_3270_DeleteWord = 64794,
+ Key_3270_ExSelect = 64795,
+ Key_3270_CursorSelect = 64796,
+ Key_3270_PrintScreen = 64797,
+ Key_3270_Enter = 64798,
+ ISO_Lock = 65025,
+ ISO_Level2_Latch = 65026,
+ ISO_Level3_Shift = 65027,
+ ISO_Level3_Latch = 65028,
+ ISO_Level3_Lock = 65029,
+ ISO_Group_Latch = 65030,
+ ISO_Group_Lock = 65031,
+ ISO_Next_Group = 65032,
+ ISO_Next_Group_Lock = 65033,
+ ISO_Prev_Group = 65034,
+ ISO_Prev_Group_Lock = 65035,
+ ISO_First_Group = 65036,
+ ISO_First_Group_Lock = 65037,
+ ISO_Last_Group = 65038,
+ ISO_Last_Group_Lock = 65039,
+ ISO_Left_Tab = 65056,
+ ISO_Move_Line_Up = 65057,
+ ISO_Move_Line_Down = 65058,
+ ISO_Partial_Line_Up = 65059,
+ ISO_Partial_Line_Down = 65060,
+ ISO_Partial_Space_Left = 65061,
+ ISO_Partial_Space_Right = 65062,
+ ISO_Set_Margin_Left = 65063,
+ ISO_Set_Margin_Right = 65064,
+ ISO_Release_Margin_Left = 65065,
+ ISO_Release_Margin_Right = 65066,
+ ISO_Release_Both_Margins = 65067,
+ ISO_Fast_Cursor_Left = 65068,
+ ISO_Fast_Cursor_Right = 65069,
+ ISO_Fast_Cursor_Up = 65070,
+ ISO_Fast_Cursor_Down = 65071,
+ ISO_Continuous_Underline = 65072,
+ ISO_Discontinuous_Underline = 65073,
+ ISO_Emphasize = 65074,
+ ISO_Center_Object = 65075,
+ ISO_Enter = 65076,
+ dead_grave = 65104,
+ dead_acute = 65105,
+ dead_circumflex = 65106,
+ dead_tilde = 65107,
+ dead_macron = 65108,
+ dead_breve = 65109,
+ dead_abovedot = 65110,
+ dead_diaeresis = 65111,
+ dead_abovering = 65112,
+ dead_doubleacute = 65113,
+ dead_caron = 65114,
+ dead_cedilla = 65115,
+ dead_ogonek = 65116,
+ dead_iota = 65117,
+ dead_voiced_sound = 65118,
+ dead_semivoiced_sound = 65119,
+ dead_belowdot = 65120,
+ AccessX_Enable = 65136,
+ AccessX_Feedback_Enable = 65137,
+ RepeatKeys_Enable = 65138,
+ SlowKeys_Enable = 65139,
+ BounceKeys_Enable = 65140,
+ StickyKeys_Enable = 65141,
+ MouseKeys_Enable = 65142,
+ MouseKeys_Accel_Enable = 65143,
+ Overlay1_Enable = 65144,
+ Overlay2_Enable = 65145,
+ AudibleBell_Enable = 65146,
+ First_Virtual_Screen = 65232,
+ Prev_Virtual_Screen = 65233,
+ Next_Virtual_Screen = 65234,
+ Last_Virtual_Screen = 65236,
+ Terminate_Server = 65237,
+ Pointer_Left = 65248,
+ Pointer_Right = 65249,
+ Pointer_Up = 65250,
+ Pointer_Down = 65251,
+ Pointer_UpLeft = 65252,
+ Pointer_UpRight = 65253,
+ Pointer_DownLeft = 65254,
+ Pointer_DownRight = 65255,
+ Pointer_Button_Dflt = 65256,
+ Pointer_Button1 = 65257,
+ Pointer_Button2 = 65258,
+ Pointer_Button3 = 65259,
+ Pointer_Button4 = 65260,
+ Pointer_Button5 = 65261,
+ Pointer_DblClick_Dflt = 65262,
+ Pointer_DblClick1 = 65263,
+ Pointer_DblClick2 = 65264,
+ Pointer_DblClick3 = 65265,
+ Pointer_DblClick4 = 65266,
+ Pointer_DblClick5 = 65267,
+ Pointer_Drag_Dflt = 65268,
+ Pointer_Drag1 = 65269,
+ Pointer_Drag2 = 65270,
+ Pointer_Drag3 = 65271,
+ Pointer_Drag4 = 65272,
+ Pointer_EnableKeys = 65273,
+ Pointer_Accelerate = 65274,
+ Pointer_DfltBtnNext = 65275,
+ Pointer_DfltBtnPrev = 65276,
+ Pointer_Drag5 = 65277,
+ BackSpace = 65288,
+ Tab = 65289,
+ Linefeed = 65290,
+ Clear = 65291,
+ Return = 65293,
+ Pause = 65299,
+ Scroll_Lock = 65300,
+ Sys_Req = 65301,
+ Escape = 65307,
+ Multi_key = 65312,
+ Kanji = 65313,
+ Muhenkan = 65314,
+ Henkan = 65315,
+ Henkan_Mode = 65315,
+ Romaji = 65316,
+ Hiragana = 65317,
+ Katakana = 65318,
+ Hiragana_Katakana = 65319,
+ Zenkaku = 65320,
+ Hankaku = 65321,
+ Zenkaku_Hankaku = 65322,
+ Touroku = 65323,
+ Massyo = 65324,
+ Kana_Lock = 65325,
+ Kana_Shift = 65326,
+ Eisu_Shift = 65327,
+ Eisu_toggle = 65328,
+ Hangul = 65329,
+ Hangul_Start = 65330,
+ Hangul_End = 65331,
+ Hangul_Hanja = 65332,
+ Hangul_Jamo = 65333,
+ Hangul_Romaja = 65334,
+ Codeinput = 65335,
+ Hangul_Codeinput = 65335,
+ Kanji_Bangou = 65335,
+ Hangul_Jeonja = 65336,
+ Hangul_Banja = 65337,
+ Hangul_PreHanja = 65338,
+ Hangul_PostHanja = 65339,
+ Hangul_SingleCandidate = 65340,
+ SingleCandidate = 65340,
+ Hangul_MultipleCandidate = 65341,
+ MultipleCandidate = 65341,
+ Zen_Koho = 65341,
+ Hangul_PreviousCandidate = 65342,
+ Mae_Koho = 65342,
+ PreviousCandidate = 65342,
+ Hangul_Special = 65343,
+ Home = 65360,
+ Left = 65361,
+ Up = 65362,
+ Right = 65363,
+ Down = 65364,
+ Page_Up = 65365,
+ Prior = 65365,
+ Next = 65366,
+ Page_Down = 65366,
+ End = 65367,
+ Begin = 65368,
+ Select = 65376,
+ Print = 65377,
+ Execute = 65378,
+ Insert = 65379,
+ Undo = 65381,
+ Redo = 65382,
+ Menu = 65383,
+ Find = 65384,
+ Cancel = 65385,
+ Help = 65386,
+ Break = 65387,
+ Arabic_switch = 65406,
+ Greek_switch = 65406,
+ Hangul_switch = 65406,
+ Hebrew_switch = 65406,
+ ISO_Group_Shift = 65406,
+ Mode_switch = 65406,
+ kana_switch = 65406,
+ script_switch = 65406,
+ Num_Lock = 65407,
+ KP_Space = 65408,
+ KP_Tab = 65417,
+ KP_Enter = 65421,
+ KP_F1 = 65425,
+ KP_F2 = 65426,
+ KP_F3 = 65427,
+ KP_F4 = 65428,
+ KP_Home = 65429,
+ KP_Left = 65430,
+ KP_Up = 65431,
+ KP_Right = 65432,
+ KP_Down = 65433,
+ KP_Page_Up = 65434,
+ KP_Prior = 65434,
+ KP_Next = 65435,
+ KP_Page_Down = 65435,
+ KP_End = 65436,
+ KP_Begin = 65437,
+ KP_Insert = 65438,
+ KP_Delete = 65439,
+ KP_Multiply = 65450,
+ KP_Add = 65451,
+ KP_Separator = 65452,
+ KP_Subtract = 65453,
+ KP_Decimal = 65454,
+ KP_Divide = 65455,
+ KP_0 = 65456,
+ KP_1 = 65457,
+ KP_2 = 65458,
+ KP_3 = 65459,
+ KP_4 = 65460,
+ KP_5 = 65461,
+ KP_6 = 65462,
+ KP_7 = 65463,
+ KP_8 = 65464,
+ KP_9 = 65465,
+ KP_Equal = 65469,
+ F1 = 65470,
+ F2 = 65471,
+ F3 = 65472,
+ F4 = 65473,
+ F5 = 65474,
+ F6 = 65475,
+ F7 = 65476,
+ F8 = 65477,
+ F9 = 65478,
+ F10 = 65479,
+ F11 = 65480,
+ L1 = 65480,
+ F12 = 65481,
+ L2 = 65481,
+ F13 = 65482,
+ L3 = 65482,
+ F14 = 65483,
+ L4 = 65483,
+ F15 = 65484,
+ L5 = 65484,
+ F16 = 65485,
+ L6 = 65485,
+ F17 = 65486,
+ L7 = 65486,
+ F18 = 65487,
+ L8 = 65487,
+ F19 = 65488,
+ L9 = 65488,
+ F20 = 65489,
+ L10 = 65489,
+ F21 = 65490,
+ R1 = 65490,
+ F22 = 65491,
+ R2 = 65491,
+ F23 = 65492,
+ R3 = 65492,
+ F24 = 65493,
+ R4 = 65493,
+ F25 = 65494,
+ R5 = 65494,
+ F26 = 65495,
+ R6 = 65495,
+ F27 = 65496,
+ R7 = 65496,
+ F28 = 65497,
+ R8 = 65497,
+ F29 = 65498,
+ R9 = 65498,
+ F30 = 65499,
+ R10 = 65499,
+ F31 = 65500,
+ R11 = 65500,
+ F32 = 65501,
+ R12 = 65501,
+ F33 = 65502,
+ R13 = 65502,
+ F34 = 65503,
+ R14 = 65503,
+ F35 = 65504,
+ R15 = 65504,
+ Shift_L = 65505,
+ Shift_R = 65506,
+ Control_L = 65507,
+ Control_R = 65508,
+ Caps_Lock = 65509,
+ Shift_Lock = 65510,
+ Meta_L = 65511,
+ Meta_R = 65512,
+ Alt_L = 65513,
+ Alt_R = 65514,
+ Super_L = 65515,
+ Super_R = 65516,
+ Hyper_L = 65517,
+ Hyper_R = 65518,
+ Delete = 65535,
+ VoidSymbol = 16777215,
+ }
+}
diff --git a/src/Gtk/Avalonia.Gtk3/Gtk3Platform.cs b/src/Gtk/Avalonia.Gtk3/Gtk3Platform.cs
new file mode 100644
index 0000000000..11209825dc
--- /dev/null
+++ b/src/Gtk/Avalonia.Gtk3/Gtk3Platform.cs
@@ -0,0 +1,116 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using Avalonia.Controls;
+using Avalonia.Controls.Platform;
+using Avalonia.Gtk3.Interop;
+using Avalonia.Input;
+using Avalonia.Input.Platform;
+using Avalonia.Platform;
+using Avalonia.Rendering;
+using Avalonia.Gtk3;
+
+namespace Avalonia.Gtk3
+{
+ public class Gtk3Platform : IWindowingPlatform, IPlatformSettings, IPlatformThreadingInterface
+ {
+ internal static readonly Gtk3Platform Instance = new Gtk3Platform();
+ internal static readonly MouseDevice Mouse = new MouseDevice();
+ internal static readonly KeyboardDevice Keyboard = new KeyboardDevice();
+ internal static IntPtr App { get; set; }
+ public static void Initialize()
+ {
+ Resolver.Resolve();
+ Native.GtkInit(0, IntPtr.Zero);
+ using (var utf = new Utf8Buffer("avalonia.app." + Guid.NewGuid()))
+ App = Native.GtkApplicationNew(utf, 0);
+ //Mark current thread as UI thread
+ s_tlsMarker = true;
+
+ AvaloniaLocator.CurrentMutable.Bind().ToConstant(Instance)
+ .Bind().ToSingleton()
+ .Bind().ToConstant(new CursorFactory())
+ .Bind().ToConstant(Keyboard)
+ .Bind().ToConstant(Mouse)
+ .Bind().ToConstant(Instance)
+ .Bind().ToConstant(Instance)
+ .Bind().ToSingleton()
+ .Bind().ToConstant(new DefaultRenderLoop(60))
+ .Bind().ToConstant(new PlatformIconLoader());
+
+ }
+
+ public IWindowImpl CreateWindow() => new WindowImpl();
+
+ public IEmbeddableWindowImpl CreateEmbeddableWindow()
+ {
+ throw new NotImplementedException();
+ }
+
+ public IPopupImpl CreatePopup() => new PopupImpl();
+
+
+
+ public Size DoubleClickSize => new Size(4, 4);
+
+ public TimeSpan DoubleClickTime => TimeSpan.FromMilliseconds(100); //STUB
+ public double RenderScalingFactor { get; } = 1;
+ public double LayoutScalingFactor { get; } = 1;
+
+ public void RunLoop(CancellationToken cancellationToken)
+ {
+ while (!cancellationToken.IsCancellationRequested)
+ Native.GtkMainIteration();
+ }
+
+ public IDisposable StartTimer(TimeSpan interval, Action tick)
+ {
+ return GlibTimeout.StarTimer((uint) interval.TotalMilliseconds, tick);
+ }
+
+ private bool _signaled = false;
+ object _lock = new object();
+
+ public void Signal()
+ {
+ lock(_lock)
+ if (!_signaled)
+ {
+ _signaled = true;
+ GlibTimeout.Add(0, () =>
+ {
+ lock (_lock)
+ {
+ _signaled = false;
+ }
+ Signaled?.Invoke();
+ return false;
+ });
+ }
+ }
+ public event Action Signaled;
+
+
+ [ThreadStatic]
+ private static bool s_tlsMarker;
+
+ public bool CurrentThreadIsLoopThread => s_tlsMarker;
+
+ }
+}
+
+namespace Avalonia
+{
+ public static class Gtk3AppBuilderExtensions
+ {
+ public static T UseGtk3(this AppBuilderBase builder, ICustomGtk3NativeLibraryResolver resolver = null)
+ where T : AppBuilderBase, new()
+ {
+ Resolver.Custom = resolver;
+ return builder.UseWindowingSubsystem(Gtk3Platform.Initialize, "GTK3");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Gtk/Avalonia.Gtk3/ImageSurfaceFramebuffer.cs b/src/Gtk/Avalonia.Gtk3/ImageSurfaceFramebuffer.cs
new file mode 100644
index 0000000000..a2b06d0d5e
--- /dev/null
+++ b/src/Gtk/Avalonia.Gtk3/ImageSurfaceFramebuffer.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Avalonia.Controls.Platform.Surfaces;
+using Avalonia.Gtk3.Interop;
+using Avalonia.Platform;
+
+
+namespace Avalonia.Gtk3
+{
+ class ImageSurfaceFramebuffer : ILockedFramebuffer
+ {
+ private IntPtr _context;
+ private IntPtr _surface;
+
+ public ImageSurfaceFramebuffer(int width, int height)
+ {
+ _surface = Native.CairoImageSurfaceCreate(1, width, height);
+ Width = width;
+ Height = height;
+ Address = Native.CairoImageSurfaceGetData(_surface);
+ RowBytes = Native.CairoImageSurfaceGetStride(_surface);
+ Native.CairoSurfaceFlush(_surface);
+ }
+
+ public void Prepare(IntPtr context)
+ {
+ _context = context;
+ }
+
+ public void Deallocate()
+ {
+ Native.CairoSurfaceDestroy(_surface);
+ _surface = IntPtr.Zero;
+ }
+
+ public void Dispose()
+ {
+ if(_context == IntPtr.Zero || _surface == IntPtr.Zero)
+ return;
+ Native.CairoSurfaceMarkDirty(_surface);
+ Native.CairoSetSourceSurface(_context, _surface, 0, 0);
+ Native.CairoPaint(_context);
+ _context = IntPtr.Zero;
+
+ }
+
+ public IntPtr Address { get; }
+ public int Width { get; }
+ public int Height { get; }
+ public int RowBytes { get; }
+
+ //TODO: Proper DPI detect
+ public Size Dpi => new Size(96, 96);
+
+ public PixelFormat Format => PixelFormat.Bgra8888;
+ }
+}
+
+
+
diff --git a/src/Gtk/Avalonia.Gtk3/Interop/DynLoader.cs b/src/Gtk/Avalonia.Gtk3/Interop/DynLoader.cs
new file mode 100644
index 0000000000..afe526e2c3
--- /dev/null
+++ b/src/Gtk/Avalonia.Gtk3/Interop/DynLoader.cs
@@ -0,0 +1,129 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+
+/*
+ * Source code imported from https://github.com/kekekeks/evhttp-sharp
+ * Source is provided under MIT license for Avalonia project and derived works
+ */
+
+
+namespace Avalonia.Gtk3.Interop
+{
+ internal interface IDynLoader
+ {
+ IntPtr LoadLibrary(string dll);
+ IntPtr GetProcAddress(IntPtr dll, string proc);
+
+ }
+
+ class UnixLoader : IDynLoader
+ {
+ // ReSharper disable InconsistentNaming
+ static class LinuxImports
+ {
+ [DllImport("libdl.so.2")]
+ private static extern IntPtr dlopen(string path, int flags);
+
+ [DllImport("libdl.so.2")]
+ private static extern IntPtr dlsym(IntPtr handle, string symbol);
+
+ [DllImport("libdl.so.2")]
+ private static extern IntPtr dlerror();
+
+ public static void Init()
+ {
+ DlOpen = dlopen;
+ DlSym = dlsym;
+ DlError = dlerror;
+ }
+ }
+ static class OsXImports
+ {
+
+
+ [DllImport("/usr/lib/libSystem.dylib")]
+ private static extern IntPtr dlopen(string path, int flags);
+
+ [DllImport("/usr/lib/libSystem.dylib")]
+ private static extern IntPtr dlsym(IntPtr handle, string symbol);
+
+ [DllImport("/usr/lib/libSystem.dylib")]
+ private static extern IntPtr dlerror();
+
+ public static void Init()
+ {
+ DlOpen = dlopen;
+ DlSym = dlsym;
+ DlError = dlerror;
+ }
+
+ }
+
+
+ [DllImport("libc")]
+ static extern int uname(IntPtr buf);
+
+ static UnixLoader()
+ {
+ var buffer = Marshal.AllocHGlobal(0x1000);
+ uname(buffer);
+ var unixName = Marshal.PtrToStringAnsi(buffer);
+ Marshal.FreeHGlobal(buffer);
+ if(unixName == "Darwin")
+ OsXImports.Init();
+ else
+ LinuxImports.Init();
+ }
+
+ private static Func DlOpen;
+ private static Func DlSym;
+ private static Func DlError;
+ // ReSharper restore InconsistentNaming
+
+ static string DlErrorString() => Marshal.PtrToStringAnsi(DlError());
+
+ public IntPtr LoadLibrary(string dll)
+ {
+ var handle = DlOpen(dll, 1);
+ if (handle == IntPtr.Zero)
+ throw new NativeException(DlErrorString());
+ return handle;
+ }
+
+ public IntPtr GetProcAddress(IntPtr dll, string proc)
+ {
+ var ptr = DlSym(dll, proc);
+ if (ptr == IntPtr.Zero)
+ throw new NativeException(DlErrorString());
+ return ptr;
+ }
+ }
+
+ internal class Win32Loader : IDynLoader
+ {
+ [DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
+ private static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
+
+ [DllImport("kernel32", EntryPoint = "LoadLibraryW", SetLastError = true, CharSet = CharSet.Unicode)]
+ private static extern IntPtr LoadLibrary(string lpszLib);
+
+ IntPtr IDynLoader.LoadLibrary(string dll)
+ {
+ var handle = LoadLibrary(dll);
+ if (handle != IntPtr.Zero)
+ return handle;
+ var err = Marshal.GetLastWin32Error();
+
+ throw new NativeException("Error loading " + dll + " error " + err);
+ }
+
+ IntPtr IDynLoader.GetProcAddress(IntPtr dll, string proc)
+ {
+ var ptr = GetProcAddress(dll, proc);
+ if (ptr == IntPtr.Zero)
+ throw new NativeException("Error " + Marshal.GetLastWin32Error());
+ return ptr;
+ }
+ }
+}
diff --git a/src/Gtk/Avalonia.Gtk3/Interop/GException.cs b/src/Gtk/Avalonia.Gtk3/Interop/GException.cs
new file mode 100644
index 0000000000..ab08df4ec3
--- /dev/null
+++ b/src/Gtk/Avalonia.Gtk3/Interop/GException.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Avalonia.Gtk3.Interop
+{
+ public class GException : Exception
+ {
+ [StructLayout(LayoutKind.Sequential)]
+ struct GError
+ {
+ UInt32 domain;
+ int code;
+ public IntPtr message;
+ };
+
+ static unsafe string GetError(IntPtr error)
+ {
+ if (error == IntPtr.Zero)
+ return "Unknown error";
+ return Utf8Buffer.StringFromPtr(((GError*) error)->message);
+ }
+
+ public GException(IntPtr error) : base(GetError(error))
+ {
+
+ }
+
+ }
+}
diff --git a/src/Gtk/Avalonia.Gtk3/Interop/GObject.cs b/src/Gtk/Avalonia.Gtk3/Interop/GObject.cs
new file mode 100644
index 0000000000..9ead1d2cb3
--- /dev/null
+++ b/src/Gtk/Avalonia.Gtk3/Interop/GObject.cs
@@ -0,0 +1,62 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Avalonia.Gtk3.Interop
+{
+ class GObject : SafeHandle
+ {
+ public GObject() : base(IntPtr.Zero, true)
+ {
+ }
+
+ public GObject(IntPtr handle, bool owned = true) : base(IntPtr.Zero, owned)
+ {
+ this.handle = handle;
+ }
+
+ protected override bool ReleaseHandle()
+ {
+ if (handle != IntPtr.Zero)
+ Native.GObjectUnref(handle);
+ handle = IntPtr.Zero;
+ return true;
+ }
+
+ public override bool IsInvalid => handle == IntPtr.Zero;
+ }
+
+ class GInputStream : GObject
+ {
+
+ }
+
+ class GtkWidget : GObject
+ {
+
+ }
+
+ class GtkWindow : GtkWidget
+ {
+
+ }
+
+ class GtkImContext : GObject
+ {
+
+ }
+
+ class GtkDialog : GtkWindow
+ {
+
+ }
+
+ class GtkFileChooser : GtkDialog
+ {
+
+ }
+}
+
diff --git a/src/Gtk/Avalonia.Gtk3/Interop/GlibTimeout.cs b/src/Gtk/Avalonia.Gtk3/Interop/GlibTimeout.cs
new file mode 100644
index 0000000000..9971d8881d
--- /dev/null
+++ b/src/Gtk/Avalonia.Gtk3/Interop/GlibTimeout.cs
@@ -0,0 +1,64 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Avalonia.Gtk3.Interop
+{
+ static class GlibTimeout
+ {
+ static bool Handler(IntPtr data)
+ {
+ var handle = GCHandle.FromIntPtr(data);
+ var cb = (Func) handle.Target;
+ if (!cb())
+ {
+ handle.Free();
+ return false;
+ }
+ return true;
+ }
+
+ private static readonly GCHandle PinnedHandle;
+ private static readonly Native.D.timeout_callback PinnedHandler;
+ static GlibTimeout()
+ {
+ PinnedHandler = Handler;
+
+ }
+
+
+ public static void Add(uint interval, Func callback)
+ {
+ var handle = GCHandle.Alloc(callback);
+ Native.GTimeoutAdd(interval, PinnedHandler, GCHandle.ToIntPtr(handle));
+ }
+
+ class Timer : IDisposable
+ {
+ public bool Stopped;
+ public void Dispose()
+ {
+
+ Stopped = true;
+ }
+ }
+
+ public static IDisposable StarTimer(uint interval, Action tick)
+ {
+ var timer = new Timer ();
+ GlibTimeout.Add(interval,
+ () =>
+ {
+ if (timer.Stopped)
+ return false;
+ tick();
+ return !timer.Stopped;
+ });
+
+ return timer;
+ }
+ }
+}
diff --git a/src/Gtk/Avalonia.Gtk3/Interop/ICustomGtk3NativeLibraryResolver.cs b/src/Gtk/Avalonia.Gtk3/Interop/ICustomGtk3NativeLibraryResolver.cs
new file mode 100644
index 0000000000..2f88b09896
--- /dev/null
+++ b/src/Gtk/Avalonia.Gtk3/Interop/ICustomGtk3NativeLibraryResolver.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Avalonia.Gtk3.Interop;
+
+namespace Avalonia.Gtk3
+{
+ public interface ICustomGtk3NativeLibraryResolver
+ {
+ string GetName(GtkDll dll);
+ string BasePath { get; }
+ bool TrySystemFirst { get; }
+ string Lookup(GtkDll dll);
+ }
+}
diff --git a/src/Gtk/Avalonia.Gtk3/Interop/Native.cs b/src/Gtk/Avalonia.Gtk3/Interop/Native.cs
new file mode 100644
index 0000000000..bf66ef0cbb
--- /dev/null
+++ b/src/Gtk/Avalonia.Gtk3/Interop/Native.cs
@@ -0,0 +1,571 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+using Avalonia.Controls;
+using gint8 = System.Byte;
+using gint16 = System.Int16;
+using gint32 = System.Int32;
+using gint = System.Int32;
+using guint16 = System.UInt16;
+using guint32 = System.UInt32;
+using guint = System.UInt32;
+using gdouble = System.Double;
+
+namespace Avalonia.Gtk3.Interop
+{
+ static class Native
+ {
+ public static class D
+ {
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+ public delegate IntPtr gtk_application_new(Utf8Buffer appId, int flags);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+ public delegate void gtk_main_iteration();
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+ public delegate GtkWindow gtk_window_new(GtkWindowType windowType);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+ public delegate IntPtr gtk_init(int argc, IntPtr argv);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+ public delegate void gtk_window_present(GtkWindow gtkWindow);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+ public delegate void gtk_widget_hide(GtkWidget gtkWidget);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+ public delegate void gtk_window_set_icon(GtkWindow window, Pixbuf pixbuf);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+ public delegate void gtk_window_set_modal(GtkWindow window, bool modal);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)] //No manual import
+ public delegate IntPtr gdk_get_native_handle(IntPtr gdkWindow);
+
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+ public delegate IntPtr gtk_widget_get_window(GtkWidget gtkWidget);
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+ public delegate IntPtr gtk_widget_get_screen(GtkWidget gtkWidget);
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+ public delegate IntPtr gtk_widget_set_double_buffered(GtkWidget gtkWidget, bool value);
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+ public delegate IntPtr gtk_widget_set_events(GtkWidget gtkWidget, uint flags);
+
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
+ public delegate int gdk_screen_get_height(IntPtr screen);
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
+ public delegate int gdk_screen_get_width(IntPtr screen);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
+ public delegate IntPtr gdk_display_get_default();
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
+ public delegate int gdk_window_get_origin(IntPtr gdkWindow, out int x, out int y);
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
+ public delegate void gdk_window_resize(IntPtr gtkWindow, int width, int height);
+
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+ public delegate void gtk_widget_realize(GtkWidget gtkWidget);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+ public delegate void gtk_window_set_title(GtkWindow gtkWindow, Utf8Buffer title);
+
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+ public delegate void gtk_window_set_decorated(GtkWindow gtkWindow, bool decorated);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+ public delegate void gtk_window_get_size(GtkWindow gtkWindow, out int width, out int height);
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+ public delegate void gtk_window_resize(GtkWindow gtkWindow, int width, int height);
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+ public delegate void gtk_widget_set_size_request(GtkWidget widget, int width, int height);
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+ public delegate void gtk_window_set_default_size(GtkWindow gtkWindow, int width, int height);
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+ public delegate void gtk_window_get_position(GtkWindow gtkWindow, out int x, out int y);
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+ public delegate void gtk_window_move(GtkWindow gtkWindow, int x, int y);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+ public delegate GtkFileChooser gtk_file_chooser_dialog_new(Utf8Buffer title, GtkWindow parent, GtkFileChooserAction action, IntPtr ignore);
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+ public unsafe delegate GSList* gtk_file_chooser_get_filenames(GtkFileChooser chooser);
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+ public delegate void gtk_file_chooser_set_select_multiple(GtkFileChooser chooser, bool allow);
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+ public delegate void gtk_file_chooser_set_filename(GtkFileChooser chooser, Utf8Buffer file);
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+ public delegate void gtk_dialog_add_button(GtkDialog raw, Utf8Buffer button_text, GtkResponseType response_id);
+
+
+
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)]
+ public delegate IntPtr cairo_image_surface_create(int format, int width, int height);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)]
+ public delegate IntPtr cairo_image_surface_get_data(IntPtr surface);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)]
+ public delegate int cairo_image_surface_get_stride(IntPtr surface);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)]
+ public delegate void cairo_surface_mark_dirty(IntPtr surface);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)]
+ public delegate void cairo_surface_flush(IntPtr surface);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)]
+ public delegate void cairo_surface_destroy(IntPtr surface);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)]
+ public delegate void cairo_set_source_surface(IntPtr cr, IntPtr surface, double x, double y);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)]
+ public delegate void cairo_paint(IntPtr context);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+ public delegate void gtk_widget_queue_draw_area(GtkWidget widget, int x, int y, int width, int height);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+ public delegate GtkImContext gtk_im_multicontext_new();
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+ public delegate IntPtr gtk_im_context_set_client_window(GtkImContext context, IntPtr window);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+ public delegate bool gtk_im_context_filter_keypress(GtkImContext context, IntPtr ev);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+ public delegate void gtk_widget_activate(GtkWidget widget);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
+ public delegate IntPtr gdk_screen_get_root_window(IntPtr screen);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
+ public delegate IntPtr gdk_cursor_new(GdkCursorType type);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
+ public delegate IntPtr gdk_window_get_pointer(IntPtr raw, out int x, out int y, out int mask);
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
+ public delegate void gtk_window_set_geometry_hints(GtkWindow window, IntPtr geometry_widget, ref GdkGeometry geometry, GdkWindowHints geom_mask);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
+ public delegate void gdk_window_invalidate_rect(IntPtr window, ref GdkRectangle rect, bool invalidate_children);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
+ public delegate void gdk_window_begin_move_drag(IntPtr window, gint button, gint root_x, gint root_y, guint32 timestamp);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
+ public delegate void gdk_window_begin_resize_drag(IntPtr window, WindowEdge edge, gint button, gint root_x, gint root_y, guint32 timestamp);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
+ public delegate void gdk_event_request_motions(IntPtr ev);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+ public delegate IntPtr gtk_clipboard_get_for_display(IntPtr display, IntPtr atom);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+ public delegate void gtk_clipboard_request_text(IntPtr clipboard, GtkClipboardTextReceivedFunc callback, IntPtr user_data);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+ public delegate void gtk_clipboard_set_text(IntPtr clipboard, Utf8Buffer text, int len);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+ public delegate void gtk_clipboard_clear(IntPtr clipboard);
+
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.GdkPixBuf)]
+ public delegate IntPtr gdk_pixbuf_new_from_file(Utf8Buffer filename, out IntPtr error);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+ public delegate IntPtr gtk_icon_theme_get_default();
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+ public delegate IntPtr gtk_icon_theme_load_icon(IntPtr icon_theme, Utf8Buffer icon_name, gint size, int flags,out IntPtr error);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
+ public delegate IntPtr gdk_cursor_new_from_pixbuf(IntPtr disp, IntPtr pixbuf, int x, int y);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
+ public delegate IntPtr gdk_window_set_cursor(IntPtr window, IntPtr cursor);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.GdkPixBuf)]
+ public delegate IntPtr gdk_pixbuf_new_from_stream(GInputStream stream, IntPtr cancel, out IntPtr error);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.GdkPixBuf)]
+ public delegate bool gdk_pixbuf_save_to_bufferv(Pixbuf pixbuf, out IntPtr buffer, out IntPtr buffer_size,
+ Utf8Buffer type, IntPtr option_keys, IntPtr option_values, out IntPtr error);
+
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gobject)]
+ public delegate void g_object_unref(IntPtr instance);
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gobject)]
+ public delegate void g_object_ref(GObject instance);
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gobject)]
+ public delegate ulong g_signal_connect_object(GObject instance, Utf8Buffer signal, IntPtr handler, IntPtr userData, int flags);
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gobject)]
+ public delegate ulong g_signal_handler_disconnect(GObject instance, ulong connectionId);
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Glib)]
+ public delegate ulong g_timeout_add(uint interval, timeout_callback callback, IntPtr data);
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Glib)]
+ public delegate ulong g_free(IntPtr data);
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Glib)]
+ public unsafe delegate void g_slist_free(GSList* data);
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gio)]
+ public delegate GInputStream g_memory_input_stream_new_from_data(IntPtr ptr, IntPtr len, IntPtr destroyCallback);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate bool signal_widget_draw(IntPtr gtkWidget, IntPtr cairoContext, IntPtr userData);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate bool signal_generic(IntPtr gtkWidget, IntPtr userData);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate bool signal_dialog_response(IntPtr gtkWidget, GtkResponseType response, IntPtr userData);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate bool signal_onevent(IntPtr gtkWidget, IntPtr ev, IntPtr userData);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate bool signal_commit(IntPtr gtkWidget, IntPtr utf8string, IntPtr userData);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate bool timeout_callback(IntPtr data);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void GtkClipboardTextReceivedFunc(IntPtr clipboard, IntPtr utf8string, IntPtr userdata);
+ }
+
+
+ public static D.gtk_window_set_decorated GtkWindowSetDecorated;
+ public static D.gtk_window_set_title GtkWindowSetTitle;
+ public static D.gtk_application_new GtkApplicationNew;
+ public static D.gtk_main_iteration GtkMainIteration;
+ public static D.gtk_window_new GtkWindowNew;
+ public static D.gtk_window_set_icon GtkWindowSetIcon;
+ public static D.gtk_window_set_modal GtkWindowSetModal;
+ public static D.gtk_init GtkInit;
+ public static D.gtk_window_present GtkWindowPresent;
+ public static D.gtk_widget_hide GtkWidgetHide;
+ public static D.gdk_get_native_handle GetNativeGdkWindowHandle;
+ public static D.gtk_widget_get_window GtkWidgetGetWindow;
+ public static D.gtk_widget_get_screen GtkWidgetGetScreen;
+ public static D.gtk_widget_realize GtkWidgetRealize;
+ public static D.gtk_window_get_size GtkWindowGetSize;
+ public static D.gtk_window_resize GtkWindowResize;
+ public static D.gdk_window_resize GdkWindowResize;
+ public static D.gtk_widget_set_size_request GtkWindowSetSizeRequest;
+ public static D.gtk_window_set_default_size GtkWindowSetDefaultSize;
+ public static D.gtk_window_get_position GtkWindowGetPosition;
+ public static D.gtk_window_move GtkWindowMove;
+ public static D.gtk_file_chooser_dialog_new GtkFileChooserDialogNew;
+ public static D.gtk_file_chooser_set_select_multiple GtkFileChooserSetSelectMultiple;
+ public static D.gtk_file_chooser_set_filename GtkFileChooserSetFilename;
+ public static D.gtk_file_chooser_get_filenames GtkFileChooserGetFilenames;
+ public static D.gtk_dialog_add_button GtkDialogAddButton;
+ public static D.g_object_unref GObjectUnref;
+ public static D.g_object_ref GObjectRef;
+ public static D.g_signal_connect_object GSignalConnectObject;
+ public static D.g_signal_handler_disconnect GSignalHandlerDisconnect;
+ public static D.g_timeout_add GTimeoutAdd;
+ public static D.g_free GFree;
+ public static D.g_slist_free GSlistFree;
+ public static D.g_memory_input_stream_new_from_data GMemoryInputStreamNewFromData;
+ public static D.gtk_widget_set_double_buffered GtkWidgetSetDoubleBuffered;
+ public static D.gtk_widget_set_events GtkWidgetSetEvents;
+ public static D.gdk_window_invalidate_rect GdkWindowInvalidateRect;
+ public static D.gtk_widget_queue_draw_area GtkWidgetQueueDrawArea;
+ public static D.gtk_widget_activate GtkWidgetActivate;
+ public static D.gtk_clipboard_get_for_display GtkClipboardGetForDisplay;
+ public static D.gtk_clipboard_request_text GtkClipboardRequestText;
+ public static D.gtk_clipboard_set_text GtkClipboardSetText;
+ public static D.gtk_clipboard_clear GtkClipboardRequestClear;
+
+
+ public static D.gtk_im_multicontext_new GtkImMulticontextNew;
+ public static D.gtk_im_context_filter_keypress GtkImContextFilterKeypress;
+ public static D.gtk_im_context_set_client_window GtkImContextSetClientWindow;
+
+ public static D.gdk_screen_get_height GdkScreenGetHeight;
+ public static D.gdk_display_get_default GdkGetDefaultDisplay;
+ public static D.gdk_screen_get_width GdkScreenGetWidth;
+ public static D.gdk_screen_get_root_window GdkScreenGetRootWindow;
+ public static D.gdk_cursor_new GdkCursorNew;
+ public static D.gdk_window_get_origin GdkWindowGetOrigin;
+ public static D.gdk_window_get_pointer GdkWindowGetPointer;
+ public static D.gdk_window_begin_move_drag GdkWindowBeginMoveDrag;
+ public static D.gdk_window_begin_resize_drag GdkWindowBeginResizeDrag;
+ public static D.gdk_event_request_motions GdkEventRequestMotions;
+
+ public static D.gdk_pixbuf_new_from_file GdkPixbufNewFromFile;
+ public static D.gtk_icon_theme_get_default GtkIconThemeGetDefault;
+ public static D.gtk_icon_theme_load_icon GtkIconThemeLoadIcon;
+ public static D.gdk_cursor_new_from_pixbuf GdkCursorNewFromPixbuf;
+ public static D.gdk_window_set_cursor GdkWindowSetCursor;
+ public static D.gdk_pixbuf_new_from_stream GdkPixbufNewFromStream;
+ public static D.gdk_pixbuf_save_to_bufferv GdkPixbufSaveToBufferv;
+
+ public static D.cairo_image_surface_create CairoImageSurfaceCreate;
+ public static D.cairo_image_surface_get_data CairoImageSurfaceGetData;
+ public static D.cairo_image_surface_get_stride CairoImageSurfaceGetStride;
+ public static D.cairo_surface_mark_dirty CairoSurfaceMarkDirty;
+ public static D.cairo_surface_flush CairoSurfaceFlush;
+ public static D.cairo_surface_destroy CairoSurfaceDestroy;
+ public static D.cairo_set_source_surface CairoSetSourceSurface;
+ public static D.cairo_paint CairoPaint;
+ }
+
+ public enum GtkWindowType
+ {
+ TopLevel,
+ Popup
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct GdkRectangle
+ {
+ public int X, Y, Width, Height;
+
+ public static GdkRectangle FromRect(Rect rect)
+ {
+ return new GdkRectangle
+ {
+ X = (int) rect.X,
+ Y = (int) rect.Y,
+ Width = (int) rect.Width,
+ Height = (int) rect.Height
+ };
+ }
+ }
+
+ enum GdkEventType
+ {
+ Nothing = -1,
+ Delete = 0,
+ Destroy = 1,
+ Expose = 2,
+ MotionNotify = 3,
+ ButtonPress = 4,
+ TwoButtonPress = 5,
+ ThreeButtonPress = 6,
+ ButtonRelease = 7,
+ KeyPress = 8,
+ KeyRelease = 9,
+ EnterNotify = 10,
+ LeaveNotify = 11,
+ FocusChange = 12,
+ Configure = 13,
+ Map = 14,
+ Unmap = 15,
+ PropertyNotify = 16,
+ SelectionClear = 17,
+ SelectionRequest = 18,
+ SelectionNotify = 19,
+ ProximityIn = 20,
+ ProximityOut = 21,
+ DragEnter = 22,
+ DragLeave = 23,
+ DragMotion = 24,
+ DragStatus = 25,
+ DropStart = 26,
+ DropFinished = 27,
+ ClientEvent = 28,
+ VisibilityNotify = 29,
+ NoExpose = 30,
+ Scroll = 31,
+ WindowState = 32,
+ Setting = 33,
+ OwnerChange = 34,
+ GrabBroken = 35,
+ }
+
+ enum GdkModifierType
+ {
+ ShiftMask = 1,
+ LockMask = 2,
+ ControlMask = 4,
+ Mod1Mask = 8,
+ Mod2Mask = 16,
+ Mod3Mask = 32,
+ Mod4Mask = 64,
+ Mod5Mask = 128,
+ Button1Mask = 256,
+ Button2Mask = 512,
+ Button3Mask = 1024,
+ Button4Mask = 2048,
+ Button5Mask = 4096,
+ SuperMask = 67108864,
+ HyperMask = 134217728,
+ MetaMask = 268435456,
+ ReleaseMask = 1073741824,
+ ModifierMask = ReleaseMask | Button5Mask | Button4Mask | Button3Mask | Button2Mask | Button1Mask | Mod5Mask | Mod4Mask | Mod3Mask | Mod2Mask | Mod1Mask | ControlMask | LockMask | ShiftMask,
+ None = 0,
+ }
+
+ enum GdkScrollDirection
+ {
+ Up,
+ Down,
+ Left,
+ Right,
+ Smooth
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ unsafe struct GdkEventButton
+ {
+ public GdkEventType type;
+ public IntPtr window;
+ public gint8 send_event;
+ public guint32 time;
+ public gdouble x;
+ public gdouble y;
+ public gdouble* axes;
+ public GdkModifierType state;
+ public guint button;
+ public IntPtr device;
+ public gdouble x_root, y_root;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ unsafe struct GdkEventMotion
+ {
+ public GdkEventType type;
+ public IntPtr window;
+ public gint8 send_event;
+ public guint32 time;
+ public gdouble x;
+ public gdouble y;
+ public gdouble* axes;
+ public GdkModifierType state;
+ public gint16 is_hint;
+ public IntPtr device;
+ public gdouble x_root, y_root;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ unsafe struct GdkEventScroll
+ {
+ public GdkEventType type;
+ public IntPtr window;
+ public gint8 send_event;
+ public guint32 time;
+ public gdouble x;
+ public gdouble y;
+ public GdkModifierType state;
+ public GdkScrollDirection direction;
+ public IntPtr device;
+ public gdouble x_root, y_root;
+ public gdouble delta_x;
+ public gdouble delta_y;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ unsafe struct GdkEventWindowState
+ {
+ public GdkEventType type;
+ public IntPtr window;
+ gint8 send_event;
+ public GdkWindowState changed_mask;
+ public GdkWindowState new_window_state;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ unsafe struct GdkEventKey
+ {
+ public GdkEventType type;
+ public IntPtr window;
+ public gint8 send_event;
+ public guint32 time;
+ public guint state;
+ public guint keyval;
+ public gint length;
+ public IntPtr pstring;
+ public guint16 hardware_keycode;
+ public byte group;
+ public guint is_modifier;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ unsafe struct GSList
+ {
+ public IntPtr Data;
+ public GSList* Next;
+ }
+
+ [Flags]
+ public enum GdkWindowState
+ {
+ Withdrawn = 1,
+ Iconified = 2,
+ Maximized = 4,
+ Sticky = 8,
+ Fullscreen = 16,
+ Above = 32,
+ Below = 64,
+ Focused = 128,
+ Ttiled = 256
+ }
+
+ public enum GtkResponseType
+ {
+ Help = -11,
+ Apply = -10,
+ No = -9,
+ Yes = -8,
+ Close = -7,
+ Cancel = -6,
+ Ok = -5,
+ DeleteEvent = -4,
+ Accept = -3,
+ Reject = -2,
+ None = -1,
+ }
+
+ public enum GtkFileChooserAction
+ {
+ Open,
+ Save,
+ SelectFolder,
+ CreateFolder,
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ struct GdkGeometry
+ {
+ gint min_width;
+ gint min_height;
+ gint max_width;
+ gint max_height;
+ gint base_width;
+ gint base_height;
+ gint width_inc;
+ gint height_inc;
+ gdouble min_aspect;
+ gdouble max_aspect;
+ gint win_gravity;
+ }
+
+ enum GdkWindowHints
+ {
+ GDK_HINT_POS = 1 << 0,
+ GDK_HINT_MIN_SIZE = 1 << 1,
+ GDK_HINT_MAX_SIZE = 1 << 2,
+ GDK_HINT_BASE_SIZE = 1 << 3,
+ GDK_HINT_ASPECT = 1 << 4,
+ GDK_HINT_RESIZE_INC = 1 << 5,
+ GDK_HINT_WIN_GRAVITY = 1 << 6,
+ GDK_HINT_USER_POS = 1 << 7,
+ GDK_HINT_USER_SIZE = 1 << 8
+ }
+}
diff --git a/src/Gtk/Avalonia.Gtk3/Interop/NativeException.cs b/src/Gtk/Avalonia.Gtk3/Interop/NativeException.cs
new file mode 100644
index 0000000000..43659f8f83
--- /dev/null
+++ b/src/Gtk/Avalonia.Gtk3/Interop/NativeException.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Avalonia.Gtk3.Interop
+{
+ public class NativeException : Exception
+ {
+ public NativeException()
+ {
+ }
+
+ public NativeException(string message) : base(message)
+ {
+ }
+
+ public NativeException(string message, Exception inner) : base(message, inner)
+ {
+ }
+
+ }
+}
diff --git a/src/Gtk/Avalonia.Gtk3/Interop/Pixbuf.cs b/src/Gtk/Avalonia.Gtk3/Interop/Pixbuf.cs
new file mode 100644
index 0000000000..1a0a772522
--- /dev/null
+++ b/src/Gtk/Avalonia.Gtk3/Interop/Pixbuf.cs
@@ -0,0 +1,68 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+using Avalonia.Platform;
+
+namespace Avalonia.Gtk3.Interop
+{
+ internal class Pixbuf : GObject, IWindowIconImpl
+ {
+ Pixbuf(IntPtr handle) : base(handle)
+ {
+
+ }
+
+ public static Pixbuf NewFromFile(string filename)
+ {
+ using (var ub = new Utf8Buffer(filename))
+ {
+ IntPtr err;
+ var rv = Native.GdkPixbufNewFromFile(ub, out err);
+ if(rv != IntPtr.Zero)
+ return new Pixbuf(rv);
+ throw new GException(err);
+ }
+ }
+
+ public static unsafe Pixbuf NewFromBytes(byte[] data)
+ {
+ fixed (void* bytes = data)
+ {
+ using (var stream = Native.GMemoryInputStreamNewFromData(new IntPtr(bytes), new IntPtr(data.Length), IntPtr.Zero))
+ {
+ IntPtr err;
+ var rv = Native.GdkPixbufNewFromStream(stream, IntPtr.Zero, out err);
+ if (rv != IntPtr.Zero)
+ return new Pixbuf(rv);
+ throw new GException(err);
+ }
+ }
+ }
+
+ public static Pixbuf NewFromStream(Stream s)
+ {
+ if (s is MemoryStream)
+ return NewFromBytes(((MemoryStream) s).ToArray());
+ var ms = new MemoryStream();
+ s.CopyTo(ms);
+ return NewFromBytes(ms.ToArray());
+ }
+
+ public void Save(Stream outputStream)
+ {
+ IntPtr buffer, bufferLen, error;
+ using (var png = new Utf8Buffer("png"))
+ if (!Native.GdkPixbufSaveToBufferv(this, out buffer, out bufferLen, png,
+ IntPtr.Zero, IntPtr.Zero, out error))
+ throw new GException(error);
+ var data = new byte[bufferLen.ToInt32()];
+ Marshal.Copy(buffer, data, 0, bufferLen.ToInt32());
+ Native.GFree(buffer);
+ outputStream.Write(data, 0, data.Length);
+ }
+ }
+}
diff --git a/src/Gtk/Avalonia.Gtk3/Interop/Resolver.cs b/src/Gtk/Avalonia.Gtk3/Interop/Resolver.cs
new file mode 100644
index 0000000000..c6b6326f80
--- /dev/null
+++ b/src/Gtk/Avalonia.Gtk3/Interop/Resolver.cs
@@ -0,0 +1,155 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+using Avalonia.Platform;
+
+namespace Avalonia.Gtk3.Interop
+{
+ internal class GtkImportAttribute : Attribute
+ {
+ public GtkDll Dll { get; set; }
+ public string Name { get; set; }
+ public bool Optional { get; set; }
+
+ public GtkImportAttribute(GtkDll dll, string name = null, bool optional = false)
+ {
+ Dll = dll;
+ Name = name;
+ Optional = optional;
+ }
+ }
+
+ public enum GtkDll
+ {
+ Gdk,
+ Gtk,
+ Glib,
+ Gio,
+ Gobject,
+ Cairo,
+ GdkPixBuf
+ }
+
+ static class Resolver
+ {
+ private static Lazy Platform =
+ new Lazy(
+ () => AvaloniaLocator.Current.GetService().GetRuntimeInfo().OperatingSystem);
+
+ public static ICustomGtk3NativeLibraryResolver Custom { get; set; }
+
+
+ static string FormatName(string name, int version = 0)
+ {
+ if (Platform.Value == OperatingSystemType.WinNT)
+ return "lib" + name + "-" + version + ".dll";
+ if (Platform.Value == OperatingSystemType.Linux)
+ return "lib" + name + ".so" + "." + version;
+ if (Platform.Value == OperatingSystemType.OSX)
+ return "lib" + name + "." + version + ".dylib";
+ throw new Exception("Unknown platform, use custom name resolver");
+ }
+
+
+
+ static string GetDllName(GtkDll dll)
+ {
+ var name = Custom?.GetName(dll);
+ if (name != null)
+ return name;
+
+ switch (dll)
+ {
+ case GtkDll.Cairo:
+ return FormatName("cairo", 2);
+ case GtkDll.Gdk:
+ return FormatName("gdk-3");
+ case GtkDll.Glib:
+ return FormatName("glib-2.0");
+ case GtkDll.Gio:
+ return FormatName("gio-2.0");
+ case GtkDll.Gtk:
+ return FormatName("gtk-3");
+ case GtkDll.Gobject:
+ return FormatName("gobject-2.0");
+ case GtkDll.GdkPixBuf:
+ return FormatName("gdk_pixbuf-2.0");
+ default:
+ throw new ArgumentException("Unknown lib: " + dll);
+ }
+ }
+
+ static IntPtr LoadDll(IDynLoader loader, GtkDll dll)
+ {
+
+ var exceptions = new List();
+
+ var name = GetDllName(dll);
+ if (Custom?.TrySystemFirst != false)
+ {
+ try
+ {
+ return loader.LoadLibrary(name);
+ }
+ catch (Exception e)
+ {
+ exceptions.Add(e);
+ }
+ }
+ var path = Custom?.Lookup(dll);
+ if (path == null && Custom?.BasePath != null)
+ path = Path.Combine(Custom.BasePath, name);
+
+ try
+ {
+ return loader.LoadLibrary(path);
+ }
+ catch (Exception e)
+ {
+ exceptions.Add(e);
+ }
+ throw new AggregateException("Unable to load " + dll, exceptions);
+ }
+
+ public static void Resolve(string basePath = null)
+ {
+ var loader = Platform.Value == OperatingSystemType.WinNT ? (IDynLoader)new Win32Loader() : new UnixLoader();
+
+ var dlls = Enum.GetValues(typeof(GtkDll)).Cast().ToDictionary(x => x, x => LoadDll(loader, x));
+
+ foreach (var fieldInfo in typeof(Native).GetTypeInfo().DeclaredFields)
+ {
+ var import = fieldInfo.FieldType.GetTypeInfo().GetCustomAttributes(typeof(GtkImportAttribute), true).Cast().FirstOrDefault();
+ if(import == null)
+ continue;
+ IntPtr lib = dlls[import.Dll];
+
+ var funcPtr = loader.GetProcAddress(lib, import.Name ?? fieldInfo.FieldType.Name);
+ fieldInfo.SetValue(null, Marshal.GetDelegateForFunctionPointer(funcPtr, fieldInfo.FieldType));
+ }
+
+ var nativeHandleNames = new[] { "gdk_win32_window_get_handle", "gdk_x11_window_get_xid", "gdk_quartz_window_get_nswindow" };
+ foreach (var name in nativeHandleNames)
+ {
+ try
+ {
+ Native.GetNativeGdkWindowHandle = (Native.D.gdk_get_native_handle)Marshal
+ .GetDelegateForFunctionPointer(loader.GetProcAddress(dlls[GtkDll.Gdk], name), typeof(Native.D.gdk_get_native_handle));
+ break;
+ }
+ catch { }
+ }
+ if (Native.GetNativeGdkWindowHandle == null)
+ throw new Exception($"Unable to locate any of [{string.Join(", ", nativeHandleNames)}] in libgdk");
+
+ }
+
+
+ }
+}
+
diff --git a/src/Gtk/Avalonia.Gtk3/Interop/Signal.cs b/src/Gtk/Avalonia.Gtk3/Interop/Signal.cs
new file mode 100644
index 0000000000..5f173000a2
--- /dev/null
+++ b/src/Gtk/Avalonia.Gtk3/Interop/Signal.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Avalonia.Gtk3.Interop
+{
+ class Signal
+ {
+ class ConnectedSignal : IDisposable
+ {
+ private readonly GObject _instance;
+ private GCHandle _handle;
+ private readonly ulong _id;
+
+ public ConnectedSignal(GObject instance, GCHandle handle, ulong id)
+ {
+ _instance = instance;
+ Native.GObjectRef(instance);
+ _handle = handle;
+ _id = id;
+ }
+
+ public void Dispose()
+ {
+ if (_handle.IsAllocated)
+ {
+ Native.GObjectUnref(_instance.DangerousGetHandle());
+ Native.GSignalHandlerDisconnect(_instance, _id);
+ _handle.Free();
+ }
+ }
+ }
+
+ public static IDisposable Connect(GObject obj, string name, T handler)
+ {
+ var handle = GCHandle.Alloc(handler);
+ var ptr = Marshal.GetFunctionPointerForDelegate((Delegate)(object)handler);
+ using (var utf = new Utf8Buffer(name))
+ {
+ var id = Native.GSignalConnectObject(obj, utf, ptr, IntPtr.Zero, 0);
+ if (id == 0)
+ throw new ArgumentException("Unable to connect to signal " + name);
+ return new ConnectedSignal(obj, handle, id);
+ }
+ }
+ }
+}
diff --git a/src/Gtk/Avalonia.Gtk3/Interop/Utf8Buffer.cs b/src/Gtk/Avalonia.Gtk3/Interop/Utf8Buffer.cs
new file mode 100644
index 0000000000..f108c291b8
--- /dev/null
+++ b/src/Gtk/Avalonia.Gtk3/Interop/Utf8Buffer.cs
@@ -0,0 +1,45 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace Avalonia.Gtk3.Interop
+{
+ class Utf8Buffer : SafeHandle
+ {
+ private GCHandle _gchandle;
+ private byte[] _data;
+
+ public Utf8Buffer(string s) : base(IntPtr.Zero, true)
+ {
+ _data = Encoding.UTF8.GetBytes(s);
+ _gchandle = GCHandle.Alloc(_data, GCHandleType.Pinned);
+ handle = _gchandle.AddrOfPinnedObject();
+ }
+
+ public int ByteLen => _data.Length;
+
+ protected override bool ReleaseHandle()
+ {
+ if (handle != IntPtr.Zero)
+ {
+ handle = IntPtr.Zero;
+ _data = null;
+ _gchandle.Free();
+ }
+ return true;
+ }
+
+ public override bool IsInvalid => handle == IntPtr.Zero;
+
+ public static unsafe string StringFromPtr(IntPtr s)
+ {
+ var pstr = (byte*)s;
+ int len;
+ for (len = 0; pstr[len] != 0; len++) ;
+ var bytes = new byte[len];
+ Marshal.Copy(s, bytes, 0, len);
+
+ return Encoding.UTF8.GetString(bytes, 0, len);
+ }
+ }
+}
diff --git a/src/Gtk/Avalonia.Gtk3/PlatformIconLoader.cs b/src/Gtk/Avalonia.Gtk3/PlatformIconLoader.cs
new file mode 100644
index 0000000000..b4e293cdff
--- /dev/null
+++ b/src/Gtk/Avalonia.Gtk3/PlatformIconLoader.cs
@@ -0,0 +1,20 @@
+using System.IO;
+using Avalonia.Gtk3.Interop;
+using Avalonia.Platform;
+
+namespace Avalonia.Gtk3
+{
+ class PlatformIconLoader : IPlatformIconLoader
+ {
+ public IWindowIconImpl LoadIcon(string fileName) => Pixbuf.NewFromFile(fileName);
+
+ public IWindowIconImpl LoadIcon(Stream stream) => Pixbuf.NewFromStream(stream);
+
+ public IWindowIconImpl LoadIcon(IBitmapImpl bitmap)
+ {
+ var ms = new MemoryStream();
+ bitmap.Save(ms);
+ return Pixbuf.NewFromBytes(ms.ToArray());
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Gtk/Avalonia.Gtk3/PopupImpl.cs b/src/Gtk/Avalonia.Gtk3/PopupImpl.cs
new file mode 100644
index 0000000000..5d23148b76
--- /dev/null
+++ b/src/Gtk/Avalonia.Gtk3/PopupImpl.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Avalonia.Gtk3.Interop;
+using Avalonia.Platform;
+
+namespace Avalonia.Gtk3
+{
+ class PopupImpl : TopLevelImpl, IPopupImpl
+ {
+ static GtkWindow CreateWindow()
+ {
+ var window = Native.GtkWindowNew(GtkWindowType.Popup);
+ return window;
+ }
+
+ public PopupImpl() : base(CreateWindow())
+ {
+ }
+ }
+}
diff --git a/src/Gtk/Avalonia.Gtk3/Properties/AssemblyInfo.cs b/src/Gtk/Avalonia.Gtk3/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..72e6388531
--- /dev/null
+++ b/src/Gtk/Avalonia.Gtk3/Properties/AssemblyInfo.cs
@@ -0,0 +1,30 @@
+using System.Resources;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Avalonia.Gtk3")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Avalonia.Gtk3")]
+[assembly: AssemblyCopyright("Copyright © 2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: NeutralResourcesLanguage("en")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/src/Gtk/Avalonia.Gtk3/README.md b/src/Gtk/Avalonia.Gtk3/README.md
new file mode 100644
index 0000000000..ea853bde75
--- /dev/null
+++ b/src/Gtk/Avalonia.Gtk3/README.md
@@ -0,0 +1,8 @@
+P/Invoke based GTK3 backend
+===========================
+
+Code is EXPERIMENTAL at this point. It also needs Direct2D/Skia for rendering.
+
+Windows GTK3 binaries aren't included in the repo, you need to download them from https://sourceforge.net/projects/gtk3win/
+
+On Linux it should work out of the box with system-provided GTK3. On OSX you should be able to wire GTK3 using DYLD_LIBRARY_PATH environment variable.
\ No newline at end of file
diff --git a/src/Gtk/Avalonia.Gtk3/SystemDialogs.cs b/src/Gtk/Avalonia.Gtk3/SystemDialogs.cs
new file mode 100644
index 0000000000..04c224ff5b
--- /dev/null
+++ b/src/Gtk/Avalonia.Gtk3/SystemDialogs.cs
@@ -0,0 +1,92 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Avalonia.Controls;
+using Avalonia.Controls.Platform;
+using Avalonia.Gtk3.Interop;
+using Avalonia.Input.Platform;
+using Avalonia.Platform;
+
+namespace Avalonia.Gtk3
+{
+ class SystemDialog : ISystemDialogImpl
+ {
+
+ unsafe static Task ShowDialog(string title, GtkWindow parent, GtkFileChooserAction action,
+ bool multiselect, string initialFileName)
+ {
+ GtkFileChooser dlg;
+ using (var name = title != null ? new Utf8Buffer(title) : null)
+ dlg = Native.GtkFileChooserDialogNew(name, parent, action, IntPtr.Zero);
+ if (multiselect)
+ Native.GtkFileChooserSetSelectMultiple(dlg, true);
+
+ Native.GtkWindowSetModal(dlg, true);
+ var tcs = new TaskCompletionSource();
+ List disposables = null;
+ Action dispose = () =>
+ {
+ foreach (var d in disposables)
+ d.Dispose();
+ disposables.Clear();
+ };
+ disposables = new List
+ {
+ Signal.Connect(dlg, "close", delegate
+ {
+ tcs.TrySetResult(null);
+ dispose();
+ return false;
+ }),
+ Signal.Connect(dlg, "response", (_, resp, __)=>
+ {
+ string[] result = null;
+ if (resp == GtkResponseType.Accept)
+ {
+ var rlst = new List();
+ var gs = Native.GtkFileChooserGetFilenames(dlg);
+ var cgs = gs;
+ while (cgs != null)
+ {
+ if (cgs->Data != IntPtr.Zero)
+ rlst.Add(Utf8Buffer.StringFromPtr(cgs->Data));
+ cgs = cgs->Next;
+ }
+ Native.GSlistFree(gs);
+ result = rlst.ToArray();
+ }
+ Native.GtkWidgetHide(dlg);
+ dispose();
+ tcs.TrySetResult(result);
+ return false;
+ }),
+ dlg
+ };
+ using (var open = new Utf8Buffer("Open"))
+ Native.GtkDialogAddButton(dlg, open, GtkResponseType.Accept);
+ using (var open = new Utf8Buffer("Cancel"))
+ Native.GtkDialogAddButton(dlg, open, GtkResponseType.Cancel);
+ if(initialFileName!=null)
+ using (var fn = new Utf8Buffer(initialFileName))
+ Native.GtkFileChooserSetFilename(dlg, fn);
+ Native.GtkWindowPresent(dlg);
+ return tcs.Task;
+ }
+
+ public Task ShowFileDialogAsync(FileDialog dialog, IWindowImpl parent)
+ {
+ return ShowDialog(dialog.Title, ((TopLevelImpl) parent)?.GtkWidget,
+ dialog is OpenFileDialog ? GtkFileChooserAction.Open : GtkFileChooserAction.Save,
+ (dialog as OpenFileDialog)?.AllowMultiple ?? false, dialog.InitialFileName);
+ }
+
+ public async Task ShowFolderDialogAsync(OpenFolderDialog dialog, IWindowImpl parent)
+ {
+ var res = await ShowDialog(dialog.Title, ((TopLevelImpl) parent)?.GtkWidget,
+ GtkFileChooserAction.SelectFolder, false, dialog.InitialDirectory);
+ return res?.FirstOrDefault();
+ }
+ }
+}
diff --git a/src/Gtk/Avalonia.Gtk3/TopLevelImpl.cs b/src/Gtk/Avalonia.Gtk3/TopLevelImpl.cs
new file mode 100644
index 0000000000..10ff735476
--- /dev/null
+++ b/src/Gtk/Avalonia.Gtk3/TopLevelImpl.cs
@@ -0,0 +1,334 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using Avalonia.Controls;
+using Avalonia.Gtk3.Interop;
+using Avalonia.Input;
+using Avalonia.Input.Raw;
+using Avalonia.Platform;
+
+namespace Avalonia.Gtk3
+{
+ abstract class TopLevelImpl : ITopLevelImpl, IPlatformHandle
+ {
+ public readonly GtkWindow GtkWidget;
+ private IInputRoot _inputRoot;
+ private readonly GtkImContext _imContext;
+ private readonly FramebufferManager _framebuffer;
+ protected readonly List Disposables = new List();
+ private Size _lastSize;
+ private Point _lastPosition;
+ private uint _lastKbdEvent;
+ private uint _lastSmoothScrollEvent;
+
+ public TopLevelImpl(GtkWindow gtkWidget)
+ {
+
+ GtkWidget = gtkWidget;
+ Disposables.Add(gtkWidget);
+ _framebuffer = new FramebufferManager(this);
+ _imContext = Native.GtkImMulticontextNew();
+ Disposables.Add(_imContext);
+ Native.GtkWidgetSetEvents(gtkWidget, 0xFFFFFE);
+ Disposables.Add(Signal.Connect(_imContext, "commit", OnCommit));
+ Connect("draw", OnDraw);
+ Connect("realize", OnRealized);
+ ConnectEvent("configure-event", OnConfigured);
+ ConnectEvent("button-press-event", OnButton);
+ ConnectEvent("button-release-event", OnButton);
+ ConnectEvent("motion-notify-event", OnMotion);
+ ConnectEvent("scroll-event", OnScroll);
+ ConnectEvent("window-state-event", OnStateChanged);
+ ConnectEvent("key-press-event", OnKeyEvent);
+ ConnectEvent("key-release-event", OnKeyEvent);
+ Connect("destroy", OnDestroy);
+ Native.GtkWidgetRealize(gtkWidget);
+ _lastSize = ClientSize;
+ }
+
+ private bool OnConfigured(IntPtr gtkwidget, IntPtr ev, IntPtr userdata)
+ {
+ var size = ClientSize;
+ if (_lastSize != size)
+ {
+ Resized?.Invoke(size);
+ _lastSize = size;
+ }
+ var pos = Position;
+ if (_lastPosition != pos)
+ {
+ PositionChanged?.Invoke(pos);
+ _lastPosition = pos;
+ }
+
+ return false;
+ }
+
+ private bool OnRealized(IntPtr gtkwidget, IntPtr userdata)
+ {
+ Native.GtkImContextSetClientWindow(_imContext, Native.GtkWidgetGetWindow(GtkWidget));
+ return false;
+ }
+
+ private bool OnDestroy(IntPtr gtkwidget, IntPtr userdata)
+ {
+ Closed?.Invoke();
+ return false;
+ }
+
+ private static InputModifiers GetModifierKeys(GdkModifierType state)
+ {
+ var rv = InputModifiers.None;
+ if (state.HasFlag(GdkModifierType.ControlMask))
+ rv |= InputModifiers.Control;
+ if (state.HasFlag(GdkModifierType.ShiftMask))
+ rv |= InputModifiers.Shift;
+ if (state.HasFlag(GdkModifierType.Mod1Mask))
+ rv |= InputModifiers.Control;
+ if (state.HasFlag(GdkModifierType.Button1Mask))
+ rv |= InputModifiers.LeftMouseButton;
+ if (state.HasFlag(GdkModifierType.Button2Mask))
+ rv |= InputModifiers.RightMouseButton;
+ if (state.HasFlag(GdkModifierType.Button3Mask))
+ rv |= InputModifiers.MiddleMouseButton;
+ return rv;
+ }
+
+ private unsafe bool OnButton(IntPtr w, IntPtr ev, IntPtr userdata)
+ {
+ var evnt = (GdkEventButton*)ev;
+ var e = new RawMouseEventArgs(
+ Gtk3Platform.Mouse,
+ evnt->time,
+ _inputRoot,
+ evnt->type == GdkEventType.ButtonRelease
+ ? evnt->button == 1
+ ? RawMouseEventType.LeftButtonUp
+ : evnt->button == 3 ? RawMouseEventType.RightButtonUp : RawMouseEventType.MiddleButtonUp
+ : evnt->button == 1
+ ? RawMouseEventType.LeftButtonDown
+ : evnt->button == 3 ? RawMouseEventType.RightButtonDown : RawMouseEventType.MiddleButtonDown,
+ new Point(evnt->x, evnt->y), GetModifierKeys(evnt->state));
+ Input?.Invoke(e);
+ return true;
+ }
+
+ protected virtual unsafe bool OnStateChanged(IntPtr w, IntPtr pev, IntPtr userData)
+ {
+ var ev = (GdkEventWindowState*) pev;
+ if (ev->changed_mask.HasFlag(GdkWindowState.Focused))
+ {
+ if(ev->new_window_state.HasFlag(GdkWindowState.Focused))
+ Activated?.Invoke();
+ else
+ Deactivated?.Invoke();
+ }
+ return true;
+ }
+
+ private unsafe bool OnMotion(IntPtr w, IntPtr ev, IntPtr userdata)
+ {
+ var evnt = (GdkEventMotion*)ev;
+ var position = new Point(evnt->x, evnt->y);
+ Native.GdkEventRequestMotions(ev);
+ var e = new RawMouseEventArgs(
+ Gtk3Platform.Mouse,
+ evnt->time,
+ _inputRoot,
+ RawMouseEventType.Move,
+ position, GetModifierKeys(evnt->state));
+ Input(e);
+
+ return true;
+ }
+ private unsafe bool OnScroll(IntPtr w, IntPtr ev, IntPtr userdata)
+ {
+ var evnt = (GdkEventScroll*)ev;
+
+ //Ignore duplicates
+ if (evnt->time - _lastSmoothScrollEvent < 10 && evnt->direction != GdkScrollDirection.Smooth)
+ return true;
+
+ var delta = new Vector();
+ const double step = (double) 1;
+ if (evnt->direction == GdkScrollDirection.Down)
+ delta = new Vector(0, -step);
+ else if (evnt->direction == GdkScrollDirection.Up)
+ delta = new Vector(0, step);
+ else if (evnt->direction == GdkScrollDirection.Right)
+ delta = new Vector(-step, 0);
+ else if (evnt->direction == GdkScrollDirection.Left)
+ delta = new Vector(step, 0);
+ else if (evnt->direction == GdkScrollDirection.Smooth)
+ {
+ delta = new Vector(-evnt->delta_x, -evnt->delta_y);
+ _lastSmoothScrollEvent = evnt->time;
+ }
+ var e = new RawMouseWheelEventArgs(Gtk3Platform.Mouse, evnt->time, _inputRoot,
+ new Point(evnt->x, evnt->y), delta, GetModifierKeys(evnt->state));
+ Input(e);
+ return true;
+ }
+
+ private unsafe bool OnKeyEvent(IntPtr w, IntPtr pev, IntPtr userData)
+ {
+ var evnt = (GdkEventKey*) pev;
+ _lastKbdEvent = evnt->time;
+ if (Native.GtkImContextFilterKeypress(_imContext, pev))
+ return true;
+ var e = new RawKeyEventArgs(
+ Gtk3Platform.Keyboard,
+ evnt->time,
+ evnt->type == GdkEventType.KeyPress ? RawKeyEventType.KeyDown : RawKeyEventType.KeyUp,
+ Avalonia.Gtk.Common.KeyTransform.ConvertKey((GdkKey)evnt->keyval), GetModifierKeys((GdkModifierType)evnt->state));
+ Input(e);
+ return true;
+ }
+
+ private unsafe bool OnCommit(IntPtr gtkwidget, IntPtr utf8string, IntPtr userdata)
+ {
+ Input(new RawTextInputEventArgs(Gtk3Platform.Keyboard, _lastKbdEvent, Utf8Buffer.StringFromPtr(utf8string)));
+ return true;
+ }
+
+ void ConnectEvent(string name, Native.D.signal_onevent handler)
+ => Disposables.Add(Signal.Connect(GtkWidget, name, handler));
+ void Connect(string name, T handler) => Disposables.Add(Signal.Connect(GtkWidget, name, handler));
+
+ internal IntPtr CurrentCairoContext { get; private set; }
+
+ private bool OnDraw(IntPtr gtkwidget, IntPtr cairocontext, IntPtr userdata)
+ {
+ CurrentCairoContext = cairocontext;
+ Paint?.Invoke(new Rect(ClientSize));
+ CurrentCairoContext = IntPtr.Zero;
+ return true;
+ }
+
+ public void Dispose()
+ {
+ Closed?.Invoke();
+ foreach(var d in Disposables.AsEnumerable().Reverse())
+ d.Dispose();
+ Disposables.Clear();
+ }
+
+ public Size MaxClientSize
+ {
+ get
+ {
+ var s = Native.GtkWidgetGetScreen(GtkWidget);
+ return new Size(Native.GdkScreenGetWidth(s), Native.GdkScreenGetHeight(s));
+ }
+ }
+
+
+ public double Scaling => 1; //TODO: Implement scaling
+ public IPlatformHandle Handle => this;
+
+ string IPlatformHandle.HandleDescriptor => "HWND";
+
+ public Action Activated { get; set; }
+ public Action Closed { get; set; }
+ public Action Deactivated { get; set; }
+ public Action Input { get; set; }
+ public Action Paint { get; set; }
+ public Action Resized { get; set; }
+ public Action ScalingChanged { get; set; } //TODO
+ public Action PositionChanged { get; set; }
+
+ public void Activate() => Native.GtkWidgetActivate(GtkWidget);
+
+ public void Invalidate(Rect rect)
+ {
+ if(GtkWidget.IsClosed)
+ return;
+ Native.GtkWidgetQueueDrawArea(GtkWidget, (int)rect.X, (int)rect.Y, (int)rect.Width, (int)rect.Height);
+ }
+
+ public void SetInputRoot(IInputRoot inputRoot) => _inputRoot = inputRoot;
+
+ public Point PointToClient(Point point)
+ {
+ int x, y;
+ Native.GdkWindowGetOrigin(Native.GtkWidgetGetWindow(GtkWidget), out x, out y);
+
+ return new Point(point.X - x, point.Y - y);
+ }
+
+ public Point PointToScreen(Point point)
+ {
+ int x, y;
+ Native.GdkWindowGetOrigin(Native.GtkWidgetGetWindow(GtkWidget), out x, out y);
+ return new Point(point.X + x, point.Y + y);
+ }
+
+ public void SetCursor(IPlatformHandle cursor)
+ {
+ if (GtkWidget.IsClosed)
+ return;
+ Native.GdkWindowSetCursor(Native.GtkWidgetGetWindow(GtkWidget), cursor?.Handle ?? IntPtr.Zero);
+ }
+
+ public void Show() => Native.GtkWindowPresent(GtkWidget);
+
+ public void Hide() => Native.GtkWidgetHide(GtkWidget);
+
+ void GetGlobalPointer(out int x, out int y)
+ {
+ int mask;
+ Native.GdkWindowGetPointer(Native.GdkScreenGetRootWindow(Native.GtkWidgetGetScreen(GtkWidget)),
+ out x, out y, out mask);
+ }
+
+ public void BeginMoveDrag()
+ {
+ int x, y;
+ GetGlobalPointer(out x, out y);
+ Native.GdkWindowBeginMoveDrag(Native.GtkWidgetGetWindow(GtkWidget), 1, x, y, 0);
+ }
+
+ public void BeginResizeDrag(WindowEdge edge)
+ {
+ int x, y;
+ GetGlobalPointer(out x, out y);
+ Native.GdkWindowBeginResizeDrag(Native.GtkWidgetGetWindow(GtkWidget), edge, 1, x, y, 0);
+ }
+
+
+ public Size ClientSize
+ {
+ get
+ {
+ if (GtkWidget.IsClosed)
+ return new Size();
+ int w, h;
+ Native.GtkWindowGetSize(GtkWidget, out w, out h);
+ return new Size(w, h);
+ }
+ set
+ {
+ if (GtkWidget.IsClosed)
+ return;
+ Native.GtkWindowResize(GtkWidget, (int)value.Width, (int)value.Height);
+ }
+ }
+
+ public Point Position
+ {
+ get
+ {
+ int x, y;
+ Native.GtkWindowGetPosition(GtkWidget, out x, out y);
+ return new Point(x, y);
+ }
+ set { Native.GtkWindowMove(GtkWidget, (int)value.X, (int)value.Y); }
+ }
+
+ IntPtr IPlatformHandle.Handle => Native.GetNativeGdkWindowHandle(Native.GtkWidgetGetWindow(GtkWidget));
+ public IEnumerable
-
- ..\..\..\packages\Sprache.2.0.0.51\lib\portable-net4+netcore45+win8+wp8+sl5+MonoAndroid+Xamarin.iOS10+MonoTouch\Sprache.dll
- True
+
+ ..\..\..\packages\Sprache.2.1.0\lib\netstandard1.0\Sprache.dll
..\..\..\packages\System.Reactive.Core.3.0.0\lib\netstandard1.1\System.Reactive.Core.dll
diff --git a/src/Markup/Avalonia.Markup.Xaml/packages.config b/src/Markup/Avalonia.Markup.Xaml/packages.config
index 762fe58c1f..7a9353bb05 100644
--- a/src/Markup/Avalonia.Markup.Xaml/packages.config
+++ b/src/Markup/Avalonia.Markup.Xaml/packages.config
@@ -1,9 +1,13 @@
-
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Shared/PlatformSupport/AssetLoader.cs b/src/Shared/PlatformSupport/AssetLoader.cs
index 4edb2fdd3c..8da663f554 100644
--- a/src/Shared/PlatformSupport/AssetLoader.cs
+++ b/src/Shared/PlatformSupport/AssetLoader.cs
@@ -138,7 +138,7 @@ namespace Avalonia.Shared.PlatformSupport
AssemblyDescriptor rv;
if (!AssemblyNameCache.TryGetValue(name, out rv))
{
- var loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies();
+ var loadedAssemblies = AvaloniaLocator.Current.GetService().GetLoadedAssemblies();
var match = loadedAssemblies.FirstOrDefault(a => a.GetName().Name == name);
if (match != null)
{
@@ -148,7 +148,9 @@ namespace Avalonia.Shared.PlatformSupport
{
// iOS does not support loading assemblies dynamically!
//
-#if !__IOS__
+#if NETSTANDARD
+ AssemblyNameCache[name] = rv = new AssemblyDescriptor(Assembly.Load(new AssemblyName(name)));
+#elif !__IOS__
AssemblyNameCache[name] = rv = new AssemblyDescriptor(Assembly.Load(name));
#endif
}
diff --git a/src/Shared/PlatformSupport/StandardRuntimePlatform.cs b/src/Shared/PlatformSupport/StandardRuntimePlatform.cs
index 5c02be7d5b..e2aafd562b 100644
--- a/src/Shared/PlatformSupport/StandardRuntimePlatform.cs
+++ b/src/Shared/PlatformSupport/StandardRuntimePlatform.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.Reactive.Disposables;
using System.Reflection;
using System.Resources;
using System.Threading;
@@ -12,12 +11,16 @@ namespace Avalonia.Shared.PlatformSupport
{
internal partial class StandardRuntimePlatform : IRuntimePlatform
{
+
+#if NETSTANDARD
+ public void PostThreadPoolItem(Action cb) => ThreadPool.QueueUserWorkItem(_ => cb(), null);
+#else
public Assembly[] GetLoadedAssemblies() => AppDomain.CurrentDomain.GetAssemblies();
public void PostThreadPoolItem(Action cb) => ThreadPool.UnsafeQueueUserWorkItem(_ => cb(), null);
+#endif
public IDisposable StartSystemTimer(TimeSpan interval, Action tick)
{
- var timer = new Timer(_ => tick(), null, interval, interval);
- return Disposable.Create(() => timer.Dispose());
+ return new Timer(_ => tick(), null, interval, interval);
}
diff --git a/src/Skia/Avalonia.Skia.Android/Avalonia.Skia.Android.csproj b/src/Skia/Avalonia.Skia.Android/Avalonia.Skia.Android.csproj
index 505b62ace9..ef950fe786 100644
--- a/src/Skia/Avalonia.Skia.Android/Avalonia.Skia.Android.csproj
+++ b/src/Skia/Avalonia.Skia.Android/Avalonia.Skia.Android.csproj
@@ -40,9 +40,8 @@
-
- ..\..\..\packages\SkiaSharp.1.54.1\lib\MonoAndroid\SkiaSharp.dll
- True
+
+ ..\..\..\packages\SkiaSharp.1.56.1-beta\lib\MonoAndroid\SkiaSharp.dll
diff --git a/src/Skia/Avalonia.Skia.Android/packages.config b/src/Skia/Avalonia.Skia.Android/packages.config
index 5aa479d8d2..0b3bfb071f 100644
--- a/src/Skia/Avalonia.Skia.Android/packages.config
+++ b/src/Skia/Avalonia.Skia.Android/packages.config
@@ -1,4 +1,4 @@
-
+
\ No newline at end of file
diff --git a/src/Skia/Avalonia.Skia.Desktop.NetStandard/Avalonia.Skia.Desktop.NetStandard.csproj b/src/Skia/Avalonia.Skia.Desktop.NetStandard/Avalonia.Skia.Desktop.NetStandard.csproj
new file mode 100644
index 0000000000..fde3375c43
--- /dev/null
+++ b/src/Skia/Avalonia.Skia.Desktop.NetStandard/Avalonia.Skia.Desktop.NetStandard.csproj
@@ -0,0 +1,91 @@
+
+
+
+
+ 14.0
+ Debug
+ AnyCPU
+ {7D2D3083-71DD-4CC9-8907-39A0D86FB322}
+ Library
+ Properties
+ Avalonia.Skia.Desktop
+ Avalonia.Skia.Desktop
+ en-US
+ 512
+ {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+
+
+ v5.0
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+ true
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+ true
+
+
+
+
+
+
+
+ Properties\SharedAssemblyInfo.cs
+
+
+ PlatformRenderInterfaceDesktop.cs
+
+
+
+
+ {b09b78d8-9b26-48b0-9149-d64a2f120f3f}
+ Avalonia.Base
+
+
+ {d2221c82-4a25-4583-9b43-d791e3f6820c}
+ Avalonia.Controls
+
+
+ {62024b2d-53eb-4638-b26b-85eeaa54866e}
+ Avalonia.Input
+
+
+ {6b0ed19d-a08b-461c-a9d9-a9ee40b0c06b}
+ Avalonia.Interactivity
+
+
+ {42472427-4774-4c81-8aff-9f27b8e31721}
+ Avalonia.Layout
+
+
+ {f1baa01a-f176-4c6a-b39d-5b40bb1b148f}
+ Avalonia.Styling
+
+
+ {eb582467-6abb-43a1-b052-e981ba910e3a}
+ Avalonia.Visuals
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Skia/Avalonia.Skia.Desktop.NetStandard/project.json b/src/Skia/Avalonia.Skia.Desktop.NetStandard/project.json
new file mode 100644
index 0000000000..8615e024b7
--- /dev/null
+++ b/src/Skia/Avalonia.Skia.Desktop.NetStandard/project.json
@@ -0,0 +1,11 @@
+{
+ "supports": {},
+ "dependencies": {
+ "Microsoft.NETCore.Portable.Compatibility": "1.0.1",
+ "NETStandard.Library": "1.6.0",
+ "SkiaSharp": "1.56.1-beta"
+ },
+ "frameworks": {
+ "netstandard1.3": {}
+ }
+}
\ No newline at end of file
diff --git a/src/Skia/Avalonia.Skia.Desktop/Avalonia.Skia.Desktop.csproj b/src/Skia/Avalonia.Skia.Desktop/Avalonia.Skia.Desktop.csproj
index 62586f750d..c07db0908f 100644
--- a/src/Skia/Avalonia.Skia.Desktop/Avalonia.Skia.Desktop.csproj
+++ b/src/Skia/Avalonia.Skia.Desktop/Avalonia.Skia.Desktop.csproj
@@ -57,9 +57,8 @@
MinimumRecommendedRules.ruleset
-
- ..\..\..\packages\SkiaSharp.1.54.1\lib\net45\SkiaSharp.dll
- True
+
+ ..\..\..\packages\SkiaSharp.1.56.1-beta\lib\net45\SkiaSharp.dll
@@ -115,12 +114,12 @@
-
+
This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
-
+
+
+
+
+
+ {d211e587-d8bc-45b9-95a4-f297c8fa5200}
+ Avalonia.Animation
+
+
+ {b09b78d8-9b26-48b0-9149-d64a2f120f3f}
+ Avalonia.Base
+
+
+ {d2221c82-4a25-4583-9b43-d791e3f6820c}
+ Avalonia.Controls
+
+
+ {62024b2d-53eb-4638-b26b-85eeaa54866e}
+ Avalonia.Input
+
+
+ {6b0ed19d-a08b-461c-a9d9-a9ee40b0c06b}
+ Avalonia.Interactivity
+
+
+ {42472427-4774-4c81-8aff-9f27b8e31721}
+ Avalonia.Layout
+
+
+ {f1baa01a-f176-4c6a-b39d-5b40bb1b148f}
+ Avalonia.Styling
+
+
+ {eb582467-6abb-43a1-b052-e981ba910e3a}
+ Avalonia.Visuals
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Windows/Avalonia.Win32.NetStandard/IconImpl.cs b/src/Windows/Avalonia.Win32.NetStandard/IconImpl.cs
new file mode 100644
index 0000000000..f21737027f
--- /dev/null
+++ b/src/Windows/Avalonia.Win32.NetStandard/IconImpl.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Avalonia.Platform;
+
+namespace Avalonia.Win32
+{
+ public class IconImpl : IWindowIconImpl
+ {
+ public IntPtr HIcon { get; set; }
+ public void Save(Stream outputStream)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/src/Windows/Avalonia.Win32.NetStandard/NativeWin32Platform.cs b/src/Windows/Avalonia.Win32.NetStandard/NativeWin32Platform.cs
new file mode 100644
index 0000000000..a269334be7
--- /dev/null
+++ b/src/Windows/Avalonia.Win32.NetStandard/NativeWin32Platform.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Avalonia.Platform;
+
+namespace Avalonia.Win32
+{
+ partial class Win32Platform
+ {
+ //TODO: An actual implementation
+ public IWindowIconImpl LoadIcon(string fileName) => new IconImpl();
+
+ public IWindowIconImpl LoadIcon(Stream stream) => new IconImpl();
+
+ public IWindowIconImpl LoadIcon(IBitmapImpl bitmap) => new IconImpl();
+ }
+}
diff --git a/src/Windows/Avalonia.Win32.NetStandard/Win32Exception.cs b/src/Windows/Avalonia.Win32.NetStandard/Win32Exception.cs
new file mode 100644
index 0000000000..45926a881d
--- /dev/null
+++ b/src/Windows/Avalonia.Win32.NetStandard/Win32Exception.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Avalonia.Win32.NetStandard
+{
+ class AvaloniaWin32Exception : Exception
+ {
+ }
+}
diff --git a/src/Windows/Avalonia.Win32.NetStandard/project.json b/src/Windows/Avalonia.Win32.NetStandard/project.json
new file mode 100644
index 0000000000..74e316ac12
--- /dev/null
+++ b/src/Windows/Avalonia.Win32.NetStandard/project.json
@@ -0,0 +1,11 @@
+{
+ "supports": {},
+ "dependencies": {
+ "Microsoft.NETCore.Portable.Compatibility": "1.0.1",
+ "NETStandard.Library": "1.6.0",
+ "System.Reactive.Core": "3.0.0"
+ },
+ "frameworks": {
+ "netstandard1.1": {}
+ }
+}
\ No newline at end of file
diff --git a/src/Windows/Avalonia.Win32/Avalonia.Win32.Shared.projitems b/src/Windows/Avalonia.Win32/Avalonia.Win32.Shared.projitems
new file mode 100644
index 0000000000..74a2b83efe
--- /dev/null
+++ b/src/Windows/Avalonia.Win32/Avalonia.Win32.Shared.projitems
@@ -0,0 +1,31 @@
+
+
+
+ $(MSBuildAllProjects);$(MSBuildThisFileFullPath)
+ true
+ 9defc6b7-845b-4d8f-afc0-d32bf0032b8c
+
+
+ Avalonia.Win32.Shared
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Properties\SharedAssemblyInfo.cs
+
+
+
\ No newline at end of file
diff --git a/src/Windows/Avalonia.Win32/Avalonia.Win32.Shared.shproj b/src/Windows/Avalonia.Win32/Avalonia.Win32.Shared.shproj
new file mode 100644
index 0000000000..676400f06d
--- /dev/null
+++ b/src/Windows/Avalonia.Win32/Avalonia.Win32.Shared.shproj
@@ -0,0 +1,13 @@
+
+
+
+ 9defc6b7-845b-4d8f-afc0-d32bf0032b8c
+ 14.0
+
+
+
+
+
+
+
+
diff --git a/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj b/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj
index 851233a19e..c05d2bf8cd 100644
--- a/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj
+++ b/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj
@@ -61,30 +61,13 @@
-
- Properties\SharedAssemblyInfo.cs
-
-
+
Component
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
@@ -125,8 +108,11 @@
-
+
+ Designer
+
+