diff --git a/Avalonia.sln b/Avalonia.sln index 0883e051c12..a95007bdc6e 100644 --- a/Avalonia.sln +++ b/Avalonia.sln @@ -80,13 +80,13 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Skia", "Skia", "{3743B0F2-C EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Android", "Android", "{7CF9789C-F1D3-4D0E-90E5-F1DF67A2753F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Android", "src\Android\Avalonia.Android\Avalonia.Android.csproj", "{7B92AF71-6287-4693-9DCB-BD5B6E927E23}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Android", "src\Android\Avalonia.Android\Avalonia.Android.csproj", "{7B92AF71-6287-4693-9DCB-BD5B6E927E23}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.AndroidTestApplication", "src\Android\Avalonia.AndroidTestApplication\Avalonia.AndroidTestApplication.csproj", "{FF69B927-C545-49AE-8E16-3D14D621AA12}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "iOS", "iOS", "{0CB0B92E-6CFF-4240-80A5-CCAFE75D91E1}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.iOS", "src\iOS\Avalonia.iOS\Avalonia.iOS.csproj", "{4488AD85-1495-4809-9AA4-DDFE0A48527E}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.iOS", "src\iOS\Avalonia.iOS\Avalonia.iOS.csproj", "{4488AD85-1495-4809-9AA4-DDFE0A48527E}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.iOSTestApplication", "src\iOS\Avalonia.iOSTestApplication\Avalonia.iOSTestApplication.csproj", "{8C923867-8A8F-4F6B-8B80-47D9E8436166}" EndProject @@ -164,7 +164,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.LinuxFramebuffer", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Direct3DInteropSample", "samples\interop\Direct3DInteropSample\Direct3DInteropSample.csproj", "{638580B0-7910-40EF-B674-DCB34DA308CD}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Win32.Interop", "src\Windows\Avalonia.Win32.Interop\Avalonia.Win32.Interop.csproj", "{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Win32.Interop", "src\Windows\Avalonia.Win32.Interop\Avalonia.Win32.Interop.csproj", "{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Skia.RenderTests", "tests\Avalonia.Skia.RenderTests\Avalonia.Skia.RenderTests.csproj", "{E1582370-37B3-403C-917F-8209551B1634}" EndProject @@ -178,17 +178,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Designer.HostApp", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Previewer", "samples\Previewer\Previewer.csproj", "{F40FC0A2-1BC3-401C-BFC1-928EC4D4A9CE}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "OSX", "OSX", "{A59C4C0A-64DF-4621-B450-2BA00D6F61E2}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.MonoMac", "src\OSX\Avalonia.MonoMac\Avalonia.MonoMac.csproj", "{CBFD5788-567D-401B-9DFA-74E4224025A0}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Designer.HostApp.NetFX", "src\tools\Avalonia.Designer.HostApp.NetFX\Avalonia.Designer.HostApp.NetFX.csproj", "{4ADA61C8-D191-428D-9066-EF4F0D86520F}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Skia.UnitTests", "tests\Avalonia.Skia.UnitTests\Avalonia.Skia.UnitTests.csproj", "{E1240B49-7B4B-4371-A00E-068778C5CF0B}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.OpenGL", "src\Avalonia.OpenGL\Avalonia.OpenGL.csproj", "{7CCAEFC4-135D-401D-BDDD-896B9B7D3569}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.OpenGL", "src\Avalonia.OpenGL\Avalonia.OpenGL.csproj", "{7CCAEFC4-135D-401D-BDDD-896B9B7D3569}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Native", "src\Avalonia.Native\Avalonia.Native.csproj", "{12A91A62-C064-42CA-9A8C-A1272F354388}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Native", "src\Avalonia.Native\Avalonia.Native.csproj", "{12A91A62-C064-42CA-9A8C-A1272F354388}" EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution @@ -1595,30 +1591,6 @@ Global {F40FC0A2-1BC3-401C-BFC1-928EC4D4A9CE}.Release|iPhone.Build.0 = Release|Any CPU {F40FC0A2-1BC3-401C-BFC1-928EC4D4A9CE}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU {F40FC0A2-1BC3-401C-BFC1-928EC4D4A9CE}.Release|iPhoneSimulator.Build.0 = Release|Any CPU - {CBFD5788-567D-401B-9DFA-74E4224025A0}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU - {CBFD5788-567D-401B-9DFA-74E4224025A0}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU - {CBFD5788-567D-401B-9DFA-74E4224025A0}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU - {CBFD5788-567D-401B-9DFA-74E4224025A0}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU - {CBFD5788-567D-401B-9DFA-74E4224025A0}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {CBFD5788-567D-401B-9DFA-74E4224025A0}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU - {CBFD5788-567D-401B-9DFA-74E4224025A0}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU - {CBFD5788-567D-401B-9DFA-74E4224025A0}.AppStore|Any CPU.Build.0 = Debug|Any CPU - {CBFD5788-567D-401B-9DFA-74E4224025A0}.AppStore|iPhone.ActiveCfg = Debug|Any CPU - {CBFD5788-567D-401B-9DFA-74E4224025A0}.AppStore|iPhone.Build.0 = Debug|Any CPU - {CBFD5788-567D-401B-9DFA-74E4224025A0}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {CBFD5788-567D-401B-9DFA-74E4224025A0}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU - {CBFD5788-567D-401B-9DFA-74E4224025A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CBFD5788-567D-401B-9DFA-74E4224025A0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CBFD5788-567D-401B-9DFA-74E4224025A0}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {CBFD5788-567D-401B-9DFA-74E4224025A0}.Debug|iPhone.Build.0 = Debug|Any CPU - {CBFD5788-567D-401B-9DFA-74E4224025A0}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {CBFD5788-567D-401B-9DFA-74E4224025A0}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU - {CBFD5788-567D-401B-9DFA-74E4224025A0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CBFD5788-567D-401B-9DFA-74E4224025A0}.Release|Any CPU.Build.0 = Release|Any CPU - {CBFD5788-567D-401B-9DFA-74E4224025A0}.Release|iPhone.ActiveCfg = Release|Any CPU - {CBFD5788-567D-401B-9DFA-74E4224025A0}.Release|iPhone.Build.0 = Release|Any CPU - {CBFD5788-567D-401B-9DFA-74E4224025A0}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU - {CBFD5788-567D-401B-9DFA-74E4224025A0}.Release|iPhoneSimulator.Build.0 = Release|Any CPU {4ADA61C8-D191-428D-9066-EF4F0D86520F}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU {4ADA61C8-D191-428D-9066-EF4F0D86520F}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU {4ADA61C8-D191-428D-9066-EF4F0D86520F}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU @@ -1765,7 +1737,6 @@ Global {E2999E4A-9086-401F-898C-AEB0AD38E676} = {9B9E3891-2366-4253-A952-D08BCEB71098} {050CC912-FF49-4A8B-B534-9544017446DD} = {4ED8B739-6F4E-4CD4-B993-545E6B5CE637} {F40FC0A2-1BC3-401C-BFC1-928EC4D4A9CE} = {9B9E3891-2366-4253-A952-D08BCEB71098} - {CBFD5788-567D-401B-9DFA-74E4224025A0} = {A59C4C0A-64DF-4621-B450-2BA00D6F61E2} {4ADA61C8-D191-428D-9066-EF4F0D86520F} = {4ED8B739-6F4E-4CD4-B993-545E6B5CE637} {E1240B49-7B4B-4371-A00E-068778C5CF0B} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B} EndGlobalSection diff --git a/azure-pipelines.yml b/azure-pipelines.yml new file mode 100644 index 00000000000..1eb7e226c8f --- /dev/null +++ b/azure-pipelines.yml @@ -0,0 +1,89 @@ +jobs: +- job: Linux + pool: + vmImage: 'ubuntu-16.04' + steps: + - task: CmdLine@2 + inputs: + script: | + sudo apt-get update + sudo apt-get install castxml + - task: CmdLine@2 + inputs: + script: | + dotnet tool install -g Cake.Tool --version 0.30.0 + + - script: | + export PATH="$PATH:$HOME/.dotnet/tools" + dotnet --info + printenv + dotnet cake build.cake -target="Azure-Linux" -configuration="Release" + +- job: macOS + pool: + vmImage: 'xcode9-macos10.13' + steps: + - task: DotNetCoreInstaller@0 + inputs: + version: '2.1.403' + - task: Xcode@5 + inputs: + actions: 'build' + scheme: '' + sdk: 'macosx10.13' + configuration: 'Release' + xcWorkspacePath: '**/*.xcodeproj/project.xcworkspace' + xcodeVersion: 'default' # Options: 8, 9, default, specifyPath + args: '-derivedDataPath ./' + - task: CmdLine@2 + inputs: + script: brew install castxml + - task: CmdLine@2 + inputs: + script: | + dotnet tool install -g Cake.Tool --version 0.30.0 + - script: | + export COREHOST_TRACE=0 + export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 + export DOTNET_CLI_TELEMETRY_OPTOUT=1 + which dotnet + dotnet --info + export PATH="$PATH:$HOME/.dotnet/tools" + dotnet --info + printenv + dotnet cake build.cake -target="Azure-OSX" -configuration="Release" + + - task: PublishBuildArtifacts@1 + inputs: + pathToPublish: '$(Build.SourcesDirectory)/Build/Products/Release/' + artifactName: 'Avalonia.Native.OSX' + - task: PublishBuildArtifacts@1 + inputs: + pathToPublish: '$(Build.SourcesDirectory)/artifacts/bin' + artifactName: 'BinariesOSX' + +- job: Windows + pool: + vmImage: 'vs2017-win2016' + steps: + - task: CmdLine@2 + inputs: + script: | + dotnet tool install -g Cake.Tool --version 0.30.0 + - task: CmdLine@2 + inputs: + script: | + set PATH=%PATH%;%USERPROFILE%\.dotnet\tools + dotnet cake build.cake -target="Azure-Windows" -configuration="Release" + - task: PublishBuildArtifacts@1 + inputs: + pathtoPublish: '$(Build.SourcesDirectory)/artifacts/nuget' + artifactName: 'NuGet' + - task: PublishBuildArtifacts@1 + inputs: + pathToPublish: '$(Build.SourcesDirectory)/artifacts/zip' + artifactName: 'Samples' + - task: PublishBuildArtifacts@1 + inputs: + pathToPublish: '$(Build.SourcesDirectory)/artifacts/bin' + artifactName: 'BinariesWindows' diff --git a/build.cake b/build.cake index d653e9da588..fbd915461f5 100644 --- a/build.cake +++ b/build.cake @@ -1,15 +1,9 @@ /////////////////////////////////////////////////////////////////////////////// -// ADDINS +// TOOLS /////////////////////////////////////////////////////////////////////////////// -#addin "nuget:?package=NuGet.Core&version=2.14.0" #tool "nuget:?package=NuGet.CommandLine&version=4.7.1" #tool "nuget:?package=JetBrains.ReSharper.CommandLineTools&version=2018.2.3" - -/////////////////////////////////////////////////////////////////////////////// -// TOOLS -/////////////////////////////////////////////////////////////////////////////// - #tool "nuget:?package=xunit.runner.console&version=2.3.1" #tool "nuget:?package=JetBrains.dotMemoryUnit&version=3.0.20171219.105559" @@ -21,7 +15,6 @@ using System; using System.Collections; using System.Collections.Generic; using System.Linq; -using NuGet; /////////////////////////////////////////////////////////////////////////////// // SCRIPTS @@ -71,6 +64,7 @@ Setup(context => Information("IsRunningOnUnix: " + parameters.IsRunningOnUnix); Information("IsRunningOnWindows: " + parameters.IsRunningOnWindows); Information("IsRunningOnAppVeyor: " + parameters.IsRunningOnAppVeyor); + Information("IsRunnongOnAzure:" + parameters.IsRunningOnAzure); Information("IsPullRequest: " + parameters.IsPullRequest); Information("IsMainRepo: " + parameters.IsMainRepo); Information("IsMasterBranch: " + parameters.IsMasterBranch); @@ -246,71 +240,6 @@ Task("Create-NuGet-Packages-Impl") } }); -Task("Publish-MyGet-Impl") - .WithCriteria((context, data) => !data.Parameters.IsLocalBuild) - .WithCriteria((context, data) => !data.Parameters.IsPullRequest) - .WithCriteria((context, data) => data.Parameters.IsMainRepo) - .WithCriteria((context, data) => data.Parameters.IsMasterBranch) - .WithCriteria((context, data) => data.Parameters.IsMyGetRelease) - .Does(data => -{ - var apiKey = EnvironmentVariable("MYGET_API_KEY"); - if(string.IsNullOrEmpty(apiKey)) - { - throw new InvalidOperationException("Could not resolve MyGet API key."); - } - - var apiUrl = EnvironmentVariable("MYGET_API_URL"); - if(string.IsNullOrEmpty(apiUrl)) - { - throw new InvalidOperationException("Could not resolve MyGet API url."); - } - - foreach(var nupkg in data.Packages.NugetPackages) - { - NuGetPush(nupkg, new NuGetPushSettings { - Source = apiUrl, - ApiKey = apiKey - }); - } -}) -.OnError(exception => -{ - Information("Publish-MyGet Task failed, but continuing with next Task..."); -}); - -Task("Publish-NuGet-Impl") - .WithCriteria((context, data) => !data.Parameters.IsLocalBuild) - .WithCriteria((context, data) => !data.Parameters.IsPullRequest) - .WithCriteria((context, data) => data.Parameters.IsMainRepo) - .WithCriteria((context, data) => data.Parameters.IsNuGetRelease) - .Does(data => -{ - var apiKey = EnvironmentVariable("NUGET_API_KEY"); - if(string.IsNullOrEmpty(apiKey)) - { - throw new InvalidOperationException("Could not resolve NuGet API key."); - } - - var apiUrl = EnvironmentVariable("NUGET_API_URL"); - if(string.IsNullOrEmpty(apiUrl)) - { - throw new InvalidOperationException("Could not resolve NuGet API url."); - } - - foreach(var nupkg in data.Packages.NugetPackages) - { - NuGetPush(nupkg, new NuGetPushSettings { - ApiKey = apiKey, - Source = apiUrl - }); - } -}) -.OnError(exception => -{ - Information("Publish-NuGet Task failed, but continuing with next Task..."); -}); - /////////////////////////////////////////////////////////////////////////////// // TARGETS /////////////////////////////////////////////////////////////////////////////// @@ -333,13 +262,24 @@ Task("Package") Task("AppVeyor") .IsDependentOn("Package") .IsDependentOn("Copy-Files-Impl") - .IsDependentOn("Zip-Files-Impl") - .IsDependentOn("Publish-MyGet-Impl") - .IsDependentOn("Publish-NuGet-Impl"); + .IsDependentOn("Zip-Files-Impl"); Task("Travis") .IsDependentOn("Run-Tests"); +Task("Azure-Linux") + .IsDependentOn("Run-Tests"); + +Task("Azure-OSX") + .IsDependentOn("Run-Tests") + .IsDependentOn("Copy-Files-Impl") + .IsDependentOn("Zip-Files-Impl"); + +Task("Azure-Windows") + .IsDependentOn("Package") + .IsDependentOn("Copy-Files-Impl") + .IsDependentOn("Zip-Files-Impl"); + /////////////////////////////////////////////////////////////////////////////// // EXECUTE /////////////////////////////////////////////////////////////////////////////// diff --git a/build/MonoMac.props b/build/MonoMac.props deleted file mode 100644 index 5cf19ef5035..00000000000 --- a/build/MonoMac.props +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/build/SharedVersion.props b/build/SharedVersion.props index 351583a1067..6ca65014b17 100644 --- a/build/SharedVersion.props +++ b/build/SharedVersion.props @@ -2,8 +2,8 @@ xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> Avalonia - 0.6.2 - Copyright 2016 © The AvaloniaUI Project + 0.7.0 + Copyright 2018 © The AvaloniaUI Project https://github.com/AvaloniaUI/Avalonia/blob/master/licence.md https://github.com/AvaloniaUI/Avalonia/ https://github.com/AvaloniaUI/Avalonia/ diff --git a/packages.cake b/packages.cake index fea45153f19..4d6b5f6771f 100644 --- a/packages.cake +++ b/packages.cake @@ -150,7 +150,7 @@ public class Packages nuspec.Symbols = false; nuspec.NoPackageAnalysis = true; nuspec.Description = "The Avalonia UI framework"; - nuspec.Copyright = "Copyright 2015"; + nuspec.Copyright = "Copyright 2018"; nuspec.Tags = new [] { "Avalonia" }; }); @@ -408,20 +408,6 @@ public class Packages BasePath = context.Directory("./src/Skia/Avalonia.Skia/bin/" + parameters.DirSuffix + "/netstandard2.0"), OutputDirectory = parameters.NugetRoot }, - new NuGetPackSettings() - { - Id = "Avalonia.MonoMac", - Dependencies = new DependencyBuilder(this) - { - new NuSpecDependency() { Id = "Avalonia", Version = parameters.Version } - }.Dep("MonoMac.NetStandard").ToArray(), - Files = new [] - { - new NuSpecContent { Source = "netstandard2.0/Avalonia.MonoMac.dll", Target = "lib/netstandard2.0" }, - }, - BasePath = context.Directory("./src/OSX/Avalonia.MonoMac/bin/" + parameters.DirSuffix), - OutputDirectory = parameters.NugetRoot - }, /////////////////////////////////////////////////////////////////////////////// // Avalonia.Desktop /////////////////////////////////////////////////////////////////////////////// @@ -434,7 +420,7 @@ public class Packages new NuSpecDependency() { Id = "Avalonia.Win32", Version = parameters.Version }, new NuSpecDependency() { Id = "Avalonia.Skia", Version = parameters.Version }, new NuSpecDependency() { Id = "Avalonia.Gtk3", Version = parameters.Version }, - new NuSpecDependency() { Id = "Avalonia.MonoMac", Version = parameters.Version } + new NuSpecDependency() { Id = "Avalonia.Native", Version = parameters.Version } }, Files = new NuSpecContent[] { @@ -460,7 +446,24 @@ public class Packages }, BasePath = context.Directory("./src/Linux/"), OutputDirectory = parameters.NugetRoot - } + }, + /////////////////////////////////////////////////////////////////////////////// + // Avalonia.Native + /////////////////////////////////////////////////////////////////////////////// + new NuGetPackSettings() + { + Id = "Avalonia.Native", + Dependencies = new [] + { + new NuSpecDependency() { Id = "Avalonia", Version = parameters.Version } + }, + Files = new [] + { + new NuSpecContent { Source = "Avalonia.Native.dll", Target = "lib/netstandard2.0" } + }, + BasePath = context.Directory("./src/Avalonia.Native/bin/" + parameters.DirSuffix + "/netstandard2.0"), + OutputDirectory = parameters.NugetRoot + }, }; var nuspecNuGetSettingInterop = new NuGetPackSettings() diff --git a/parameters.cake b/parameters.cake index 814c96da456..7db344c41cd 100644 --- a/parameters.cake +++ b/parameters.cake @@ -14,6 +14,7 @@ public class Parameters public bool IsRunningOnUnix { get; private set; } public bool IsRunningOnWindows { get; private set; } public bool IsRunningOnAppVeyor { get; private set; } + public bool IsRunningOnAzure { get; private set; } public bool IsPullRequest { get; private set; } public bool IsMainRepo { get; private set; } public bool IsMasterBranch { get; private set; } @@ -53,6 +54,8 @@ public class Parameters IsRunningOnUnix = context.IsRunningOnUnix(); IsRunningOnWindows = context.IsRunningOnWindows(); IsRunningOnAppVeyor = buildSystem.AppVeyor.IsRunningOnAppVeyor; + IsRunningOnAzure = buildSystem.IsRunningOnVSTS || buildSystem.IsRunningOnTFS || context.EnvironmentVariable("LOGNAME") == "vsts"; + IsPullRequest = buildSystem.AppVeyor.Environment.PullRequest.IsPullRequest; IsMainRepo = StringComparer.OrdinalIgnoreCase.Equals(MainRepo, buildSystem.AppVeyor.Environment.Repository.Name); IsMasterBranch = StringComparer.OrdinalIgnoreCase.Equals(MasterBranch, buildSystem.AppVeyor.Environment.Repository.Branch); @@ -85,6 +88,11 @@ public class Parameters Version += "-build" + context.EnvironmentVariable("APPVEYOR_BUILD_NUMBER") + "-beta"; } } + else if (IsRunningOnAzure) + { + // Use AssemblyVersion with Build as version + Version += "-build" + context.EnvironmentVariable("BUILD_BUILDID") + "-beta"; + } // DIRECTORIES ArtifactsDir = (DirectoryPath)context.Directory("./artifacts"); diff --git a/readme.md b/readme.md index f345cbd9df5..6be9d30f504 100644 --- a/readme.md +++ b/readme.md @@ -2,9 +2,9 @@ # Avalonia -| Gitter Chat | Windows Build Status | Linux/Mac Build Status | Open Collective | -|---|---|---|---| -| [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/AvaloniaUI/Avalonia?utm_campaign=pr-badge&utm_content=badge&utm_medium=badge&utm_source=badge) | [![Build status](https://ci.appveyor.com/api/projects/status/hubk3k0w9idyibfg/branch/master?svg=true)](https://ci.appveyor.com/project/AvaloniaUI/Avalonia/branch/master) | [![Build Status](https://travis-ci.org/AvaloniaUI/Avalonia.svg?branch=master)](https://travis-ci.org/AvaloniaUI/Avalonia) | [![Backers on Open Collective](https://opencollective.com/Avalonia/backers/badge.svg)](#backers) [![Sponsors on Open Collective](https://opencollective.com/Avalonia/sponsors/badge.svg)](#sponsors) | +| Gitter Chat | Build Status | Windows Build Status | Linux/Mac Build Status | Open Collective | +|---|---|---|---|---| +| [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/AvaloniaUI/Avalonia?utm_campaign=pr-badge&utm_content=badge&utm_medium=badge&utm_source=badge) | [![Build Status](https://dev.azure.com/AvaloniaUI/AvaloniaUI/_apis/build/status/AvaloniaUI.Avalonia)](https://dev.azure.com/AvaloniaUI/AvaloniaUI/_build/latest?definitionId=4) | [![Build status](https://ci.appveyor.com/api/projects/status/hubk3k0w9idyibfg/branch/master?svg=true)](https://ci.appveyor.com/project/AvaloniaUI/Avalonia/branch/master) | [![Build Status](https://travis-ci.org/AvaloniaUI/Avalonia.svg?branch=master)](https://travis-ci.org/AvaloniaUI/Avalonia) | [![Backers on Open Collective](https://opencollective.com/Avalonia/backers/badge.svg)](#backers) [![Sponsors on Open Collective](https://opencollective.com/Avalonia/sponsors/badge.svg)](#sponsors) | ## About diff --git a/src/Avalonia.DotNetCoreRuntime/AppBuilder.cs b/src/Avalonia.DotNetCoreRuntime/AppBuilder.cs index 5f1e8451349..87f8a8de8d0 100644 --- a/src/Avalonia.DotNetCoreRuntime/AppBuilder.cs +++ b/src/Avalonia.DotNetCoreRuntime/AppBuilder.cs @@ -43,7 +43,7 @@ public AppBuilder UsePlatformDetect() if (os == OperatingSystemType.WinNT) LoadWin32(); else if(os==OperatingSystemType.OSX) - LoadMonoMac(); + LoadAvaloniaNative(); else LoadGtk3(); this.UseSkia(); @@ -51,7 +51,7 @@ public AppBuilder UsePlatformDetect() return this; } - void LoadMonoMac() => this.UseMonoMac(); + void LoadAvaloniaNative() => this.UseAvaloniaNative(); void LoadWin32() => this.UseWin32(); void LoadGtk3() => this.UseGtk3(); } diff --git a/src/Avalonia.DotNetCoreRuntime/Avalonia.DotNetCoreRuntime.csproj b/src/Avalonia.DotNetCoreRuntime/Avalonia.DotNetCoreRuntime.csproj index 0aed0a97171..8b18a7e9f44 100644 --- a/src/Avalonia.DotNetCoreRuntime/Avalonia.DotNetCoreRuntime.csproj +++ b/src/Avalonia.DotNetCoreRuntime/Avalonia.DotNetCoreRuntime.csproj @@ -8,8 +8,8 @@ - + diff --git a/src/Avalonia.Native/Avalonia.Native.csproj b/src/Avalonia.Native/Avalonia.Native.csproj index 3f334cffd31..33463e27f64 100644 --- a/src/Avalonia.Native/Avalonia.Native.csproj +++ b/src/Avalonia.Native/Avalonia.Native.csproj @@ -19,4 +19,13 @@ + + + + + runtimes/osx/native/libAvaloniaNative.dylib + true + PreserveNewest + + diff --git a/src/OSX/Avalonia.MonoMac/AssemblyInfo.cs b/src/OSX/Avalonia.MonoMac/AssemblyInfo.cs deleted file mode 100644 index efabb7d1184..00000000000 --- a/src/OSX/Avalonia.MonoMac/AssemblyInfo.cs +++ /dev/null @@ -1,6 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text;using Avalonia.MonoMac; -using Avalonia.Platform; -[assembly: ExportWindowingSubsystem(OperatingSystemType.OSX, 1, "MonoMac", typeof(MonoMacPlatform), nameof(MonoMacPlatform.Initialize))] - diff --git a/src/OSX/Avalonia.MonoMac/Avalonia.MonoMac.csproj b/src/OSX/Avalonia.MonoMac/Avalonia.MonoMac.csproj deleted file mode 100644 index e675b433890..00000000000 --- a/src/OSX/Avalonia.MonoMac/Avalonia.MonoMac.csproj +++ /dev/null @@ -1,20 +0,0 @@ - - - netstandard2.0 - True - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/OSX/Avalonia.MonoMac/ClipboardImpl.cs b/src/OSX/Avalonia.MonoMac/ClipboardImpl.cs deleted file mode 100644 index 475083b4697..00000000000 --- a/src/OSX/Avalonia.MonoMac/ClipboardImpl.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.Threading.Tasks; -using Avalonia.Input.Platform; -using MonoMac.AppKit; - -namespace Avalonia.MonoMac -{ - class ClipboardImpl : IClipboard - { - public Task GetTextAsync() - { - return Task.FromResult(NSPasteboard.GeneralPasteboard.GetStringForType(NSPasteboard.NSStringType)); - } - - public Task SetTextAsync(string text) - { - NSPasteboard.GeneralPasteboard.ClearContents(); - if (text != null) - NSPasteboard.GeneralPasteboard.SetStringForType(text, NSPasteboard.NSStringType); - return Task.CompletedTask; - } - - public Task ClearAsync() - { - NSPasteboard.GeneralPasteboard.ClearContents(); - return Task.CompletedTask; - } - } -} - diff --git a/src/OSX/Avalonia.MonoMac/Cursor.cs b/src/OSX/Avalonia.MonoMac/Cursor.cs deleted file mode 100644 index fff2d92e63d..00000000000 --- a/src/OSX/Avalonia.MonoMac/Cursor.cs +++ /dev/null @@ -1,66 +0,0 @@ -using System; -using System.Collections.Generic; -using Avalonia.Input; -using Avalonia.Platform; -using MonoMac.AppKit; - -namespace Avalonia.MonoMac -{ - class Cursor : IPlatformHandle - { - - public NSCursor Native { get; } - - public IntPtr Handle => Native.Handle; - - public string HandleDescriptor => "NSCursor"; - - public Cursor(NSCursor native) - { - Native = native; - } - } - - class CursorFactoryStub : IStandardCursorFactory - { - Dictionary _cache; - - public CursorFactoryStub() - { - //TODO: Load diagonal cursors from webkit - //See https://stackoverflow.com/q/10733228 - _cache = new Dictionary() - { - [StandardCursorType.Arrow] = NSCursor.ArrowCursor, - [StandardCursorType.AppStarting] = NSCursor.ArrowCursor, //TODO - [StandardCursorType.BottomLeftCorner] = NSCursor.CrosshairCursor, //TODO - [StandardCursorType.BottomRightCorner] = NSCursor.CrosshairCursor, //TODO - [StandardCursorType.BottomSize] = NSCursor.ResizeDownCursor, - [StandardCursorType.Cross] = NSCursor.CrosshairCursor, - [StandardCursorType.Hand] = NSCursor.PointingHandCursor, - [StandardCursorType.Help] = NSCursor.ContextualMenuCursor, - [StandardCursorType.Ibeam] = NSCursor.IBeamCursor, - [StandardCursorType.LeftSide] = NSCursor.ResizeLeftCursor, - [StandardCursorType.No] = NSCursor.OperationNotAllowedCursor, - [StandardCursorType.RightSide] = NSCursor.ResizeRightCursor, - [StandardCursorType.SizeAll] = NSCursor.CrosshairCursor, //TODO - [StandardCursorType.SizeNorthSouth] = NSCursor.ResizeUpDownCursor, - [StandardCursorType.SizeWestEast] = NSCursor.ResizeLeftRightCursor, - [StandardCursorType.TopLeftCorner] = NSCursor.CrosshairCursor, //TODO - [StandardCursorType.TopRightCorner] = NSCursor.CrosshairCursor, //TODO - [StandardCursorType.TopSide] = NSCursor.ResizeUpCursor, - [StandardCursorType.UpArrow] = NSCursor.ResizeUpCursor, - [StandardCursorType.Wait] = NSCursor.ArrowCursor, //TODO - [StandardCursorType.DragMove] = NSCursor.DragCopyCursor, // TODO - [StandardCursorType.DragCopy] = NSCursor.DragCopyCursor, - [StandardCursorType.DragLink] = NSCursor.DragLinkCursor, - - }; - } - - public IPlatformHandle GetCursor(StandardCursorType cursorType) - { - return new Cursor(_cache[cursorType]); - } - } -} diff --git a/src/OSX/Avalonia.MonoMac/DragSource.cs b/src/OSX/Avalonia.MonoMac/DragSource.cs deleted file mode 100644 index 5d799d3fbe1..00000000000 --- a/src/OSX/Avalonia.MonoMac/DragSource.cs +++ /dev/null @@ -1,119 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reactive.Linq; -using System.Reactive.Subjects; -using System.Runtime.Serialization.Formatters.Binary; -using System.Threading.Tasks; -using Avalonia.Controls; -using Avalonia.Input; -using Avalonia.Input.Platform; -using Avalonia.Input.Raw; -using MonoMac.AppKit; -using MonoMac.CoreGraphics; -using MonoMac.Foundation; - -namespace Avalonia.MonoMac -{ - public class DragSource : NSDraggingSource, IPlatformDragSource - { - private const string NSPasteboardTypeString = "public.utf8-plain-text"; - private const string NSPasteboardTypeFileUrl = "public.file-url"; - - private readonly Subject _result = new Subject(); - private readonly IInputManager _inputManager; - private DragDropEffects _allowedEffects; - - public override bool IgnoreModifierKeysWhileDragging => false; - - public DragSource() - { - _inputManager = AvaloniaLocator.Current.GetService(); - } - - private string DataFormatToUTI(string s) - { - if (s == DataFormats.FileNames) - return NSPasteboardTypeFileUrl; - if (s == DataFormats.Text) - return NSPasteboardTypeString; - return s; - } - - private NSDraggingItem CreateDraggingItem(string format, object data) - { - var pasteboardItem = new NSPasteboardItem(); - NSData nsData; - if (data is string s) - { - if (format == DataFormats.FileNames) - s = new Uri(s).AbsoluteUri; // Ensure file uris... - nsData = NSData.FromString(s); - } - else if (data is Stream strm) - nsData = NSData.FromStream(strm); - else if (data is byte[] bytes) - nsData = NSData.FromArray(bytes); - else - { - BinaryFormatter bf = new BinaryFormatter(); - using (var ms = new MemoryStream()) - { - bf.Serialize(ms, data); - ms.Position = 0; - nsData = NSData.FromStream(ms); - } - } - pasteboardItem.SetDataForType(nsData, DataFormatToUTI(format)); - - NSPasteboardWriting writing = new NSPasteboardWriting(pasteboardItem.Handle); - - return new NSDraggingItem(writing); - } - - public IEnumerable CreateDraggingItems(string format, object data) - { - if (format == DataFormats.FileNames && data is IEnumerable files) - { - foreach (var file in files) - yield return CreateDraggingItem(format, file); - - yield break; - } - - yield return CreateDraggingItem(format, data); - } - - - public async Task DoDragDrop(IDataObject data, DragDropEffects allowedEffects) - { - // We need the TopLevelImpl + a mouse location so we just wait for the next event. - var mouseEv = await _inputManager.PreProcess.OfType().FirstAsync(); - var view = ((mouseEv.Root as TopLevel)?.PlatformImpl as TopLevelImpl)?.View; - if (view == null) - return DragDropEffects.None; - - // Prepare the source event: - var pt = view.TranslateLocalPoint(mouseEv.Position).ToMonoMacPoint(); - var ev = NSEvent.MouseEvent(NSEventType.LeftMouseDown, pt, 0, 0, 0, null, 0, 0, 0); - - _allowedEffects = allowedEffects; - var items = data.GetDataFormats().SelectMany(fmt => CreateDraggingItems(fmt, data.Get(fmt))).ToArray(); - view.BeginDraggingSession(items ,ev, this); - - return await _result; - } - - public override NSDragOperation DraggingSourceOperationMaskForLocal(bool flag) - { - return DraggingInfo.ConvertDragOperation(_allowedEffects); - } - - public override void DraggedImageEndedAtOperation(NSImage image, CGPoint screenPoint, NSDragOperation operation) - { - _result.OnNext(DraggingInfo.ConvertDragOperation(operation)); - _result.OnCompleted(); - } - } -} diff --git a/src/OSX/Avalonia.MonoMac/DraggingInfo.cs b/src/OSX/Avalonia.MonoMac/DraggingInfo.cs deleted file mode 100644 index 5ea7169a1e4..00000000000 --- a/src/OSX/Avalonia.MonoMac/DraggingInfo.cs +++ /dev/null @@ -1,89 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Avalonia.Input; -using MonoMac.AppKit; -using MonoMac.Foundation; - -namespace Avalonia.MonoMac -{ - class DraggingInfo : IDataObject - { - private readonly NSDraggingInfo _info; - - public DraggingInfo(NSDraggingInfo info) - { - _info = info; - } - - internal static NSDragOperation ConvertDragOperation(DragDropEffects d) - { - NSDragOperation result = NSDragOperation.None; - if (d.HasFlag(DragDropEffects.Copy)) - result |= NSDragOperation.Copy; - if (d.HasFlag(DragDropEffects.Link)) - result |= NSDragOperation.Link; - if (d.HasFlag(DragDropEffects.Move)) - result |= NSDragOperation.Move; - return result; - } - - internal static DragDropEffects ConvertDragOperation(NSDragOperation d) - { - DragDropEffects result = DragDropEffects.None; - if (d.HasFlag(NSDragOperation.Copy)) - result |= DragDropEffects.Copy; - if (d.HasFlag(NSDragOperation.Link)) - result |= DragDropEffects.Link; - if (d.HasFlag(NSDragOperation.Move)) - result |= DragDropEffects.Move; - return result; - } - - public Point Location => new Point(_info.DraggingLocation.X, _info.DraggingLocation.Y); - - public IEnumerable GetDataFormats() - { - return _info.DraggingPasteboard.Types.Select(NSTypeToWellknownType); - } - - private string NSTypeToWellknownType(string type) - { - if (type == NSPasteboard.NSStringType) - return DataFormats.Text; - if (type == NSPasteboard.NSFilenamesType) - return DataFormats.FileNames; - return type; - } - - public string GetText() - { - return _info.DraggingPasteboard.GetStringForType(NSPasteboard.NSStringType); - } - - public IEnumerable GetFileNames() - { - using(var fileNames = (NSArray)_info.DraggingPasteboard.GetPropertyListForType(NSPasteboard.NSFilenamesType)) - { - if (fileNames != null) - return NSArray.StringArrayFromHandle(fileNames.Handle); - } - - return Enumerable.Empty(); - } - - public bool Contains(string dataFormat) - { - return GetDataFormats().Any(f => f == dataFormat); - } - - public object Get(string dataFormat) - { - if (dataFormat == DataFormats.Text) - return GetText(); - if (dataFormat == DataFormats.FileNames) - return GetFileNames(); - - return _info.DraggingPasteboard.GetDataForType(dataFormat).ToArray(); - } - } -} diff --git a/src/OSX/Avalonia.MonoMac/EmulatedFramebuffer.cs b/src/OSX/Avalonia.MonoMac/EmulatedFramebuffer.cs deleted file mode 100644 index 4da67ae1ddd..00000000000 --- a/src/OSX/Avalonia.MonoMac/EmulatedFramebuffer.cs +++ /dev/null @@ -1,106 +0,0 @@ -using System; -using System.Runtime.InteropServices; -using Avalonia.Platform; -using Avalonia.Threading; -using MonoMac.AppKit; -using MonoMac.CoreGraphics; - -namespace Avalonia.MonoMac -{ - class EmulatedFramebuffer : ILockedFramebuffer - { - private readonly TopLevelImpl.TopLevelView _view; - private readonly CGSize _logicalSize; - private readonly bool _isDeferred; - private readonly IUnmanagedBlob _blob; - - [DllImport("libc")] - static extern void memset(IntPtr p, int c, IntPtr size); - - public EmulatedFramebuffer(TopLevelImpl.TopLevelView view) - { - _view = view; - - _isDeferred = !Dispatcher.UIThread.CheckAccess(); - _logicalSize = _view.LogicalSize; - var pixelSize = _view.PixelSize; - Width = (int)pixelSize.Width; - Height = (int)pixelSize.Height; - RowBytes = Width * 4; - Dpi = new Vector(96 * pixelSize.Width / _logicalSize.Width, 96 * pixelSize.Height / _logicalSize.Height); - Format = PixelFormat.Rgba8888; - var size = Height * RowBytes; - _blob = AvaloniaLocator.Current.GetService().AllocBlob(size); - memset(Address, 0, new IntPtr(size)); - } - - public void Dispose() - { - if (_blob.IsDisposed) - return; - var nfo = (int) CGBitmapFlags.ByteOrder32Big | (int) CGImageAlphaInfo.PremultipliedLast; - CGImage image = null; - try - { - using (var colorSpace = CGColorSpace.CreateDeviceRGB()) - using (var bContext = new CGBitmapContext(Address, Width, Height, 8, Width * 4, - colorSpace, (CGImageAlphaInfo)nfo)) - image = bContext.ToImage(); - lock (_view.SyncRoot) - { - if(!_isDeferred) - { - using (var nscontext = NSGraphicsContext.CurrentContext) - using (var context = nscontext.GraphicsPort) - { - context.SetFillColor(255, 255, 255, 255); - context.FillRect(new CGRect(default(CGPoint), _view.LogicalSize)); - context.TranslateCTM(0, _view.LogicalSize.Height - _logicalSize.Height); - context.DrawImage(new CGRect(default(CGPoint), _logicalSize), image); - context.Flush(); - nscontext.FlushGraphics(); - } - } - } - } - finally - { - if (image != null) - { - if (!_isDeferred) - image.Dispose(); - else - _view.SetBackBufferImage(new SavedImage(image, _logicalSize)); - } - _blob.Dispose(); - } - - - } - - public IntPtr Address => _blob.Address; - public int Width { get; } - public int Height { get; } - public int RowBytes { get; } - public Vector Dpi { get; } - public PixelFormat Format { get; } - } - - class SavedImage : IDisposable - { - public CGImage Image { get; private set; } - public CGSize LogicalSize { get; } - - public SavedImage(CGImage image, CGSize logicalSize) - { - Image = image; - LogicalSize = logicalSize; - } - - public void Dispose() - { - Image?.Dispose(); - Image = null; - } - } -} diff --git a/src/OSX/Avalonia.MonoMac/Helpers.cs b/src/OSX/Avalonia.MonoMac/Helpers.cs deleted file mode 100644 index 527eccafdc5..00000000000 --- a/src/OSX/Avalonia.MonoMac/Helpers.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using MonoMac.AppKit; -using MonoMac.CoreGraphics; - -namespace Avalonia.MonoMac -{ - static class Helpers - { - public static Point ToAvaloniaPoint(this CGPoint point) => new Point(point.X, point.Y); - public static CGPoint ToMonoMacPoint(this Point point) => new CGPoint(point.X, point.Y); - public static Size ToAvaloniaSize(this CGSize size) => new Size(size.Width, size.Height); - public static CGSize ToMonoMacSize(this Size size) => new CGSize(size.Width, size.Height); - public static Rect ToAvaloniaRect(this CGRect rect) => new Rect(rect.Left, rect.Top, rect.Width, rect.Height); - public static CGRect ToMonoMacRect(this Rect rect) => new CGRect(rect.X, rect.Y, rect.Width, rect.Height); - - public static Point ConvertPointY(this Point pt) - { - var sw = NSScreen.Screens[0].Frame; - var t = Math.Max(sw.Top, sw.Bottom); - return pt.WithY(t - pt.Y); - } - - public static CGPoint ConvertPointY(this CGPoint pt) - { - var sw = NSScreen.Screens[0].Frame; - var t = Math.Max(sw.Top, sw.Bottom); - return new CGPoint(pt.X, t - pt.Y); - } - - public static Rect ConvertRectY(this Rect rect) - { - return new Rect(rect.Position.WithY(rect.Y + rect.Height).ConvertPointY(), rect.Size); - } - - public static CGRect ConvertRectY(this CGRect rect) - { - return new CGRect(new CGPoint(rect.X, rect.Y + rect.Height).ConvertPointY(), rect.Size); - } - } -} diff --git a/src/OSX/Avalonia.MonoMac/KeyTransform.cs b/src/OSX/Avalonia.MonoMac/KeyTransform.cs deleted file mode 100644 index 4abd5a24f1f..00000000000 --- a/src/OSX/Avalonia.MonoMac/KeyTransform.cs +++ /dev/null @@ -1,267 +0,0 @@ -using System.Collections.Generic; -using Avalonia.Input; - -namespace Avalonia.MonoMac -{ - public static class KeyTransform - { - // See /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/Headers/Events.h - // ReSharper disable InconsistentNaming - // ReSharper disable UnusedMember.Local - private const int kVK_ANSI_A = 0x00; - private const int kVK_ANSI_S = 0x01; - private const int kVK_ANSI_D = 0x02; - private const int kVK_ANSI_F = 0x03; - private const int kVK_ANSI_H = 0x04; - private const int kVK_ANSI_G = 0x05; - private const int kVK_ANSI_Z = 0x06; - private const int kVK_ANSI_X = 0x07; - private const int kVK_ANSI_C = 0x08; - private const int kVK_ANSI_V = 0x09; - private const int kVK_ANSI_B = 0x0B; - private const int kVK_ANSI_Q = 0x0C; - private const int kVK_ANSI_W = 0x0D; - private const int kVK_ANSI_E = 0x0E; - private const int kVK_ANSI_R = 0x0F; - private const int kVK_ANSI_Y = 0x10; - private const int kVK_ANSI_T = 0x11; - private const int kVK_ANSI_1 = 0x12; - private const int kVK_ANSI_2 = 0x13; - private const int kVK_ANSI_3 = 0x14; - private const int kVK_ANSI_4 = 0x15; - private const int kVK_ANSI_6 = 0x16; - private const int kVK_ANSI_5 = 0x17; - private const int kVK_ANSI_Equal = 0x18; - private const int kVK_ANSI_9 = 0x19; - private const int kVK_ANSI_7 = 0x1A; - private const int kVK_ANSI_Minus = 0x1B; - private const int kVK_ANSI_8 = 0x1C; - private const int kVK_ANSI_0 = 0x1D; - private const int kVK_ANSI_RightBracket = 0x1E; - private const int kVK_ANSI_O = 0x1F; - private const int kVK_ANSI_U = 0x20; - private const int kVK_ANSI_LeftBracket = 0x21; - private const int kVK_ANSI_I = 0x22; - private const int kVK_ANSI_P = 0x23; - private const int kVK_ANSI_L = 0x25; - private const int kVK_ANSI_J = 0x26; - private const int kVK_ANSI_Quote = 0x27; - private const int kVK_ANSI_K = 0x28; - private const int kVK_ANSI_Semicolon = 0x29; - private const int kVK_ANSI_Backslash = 0x2A; - private const int kVK_ANSI_Comma = 0x2B; - private const int kVK_ANSI_Slash = 0x2C; - private const int kVK_ANSI_N = 0x2D; - private const int kVK_ANSI_M = 0x2E; - private const int kVK_ANSI_Period = 0x2F; - private const int kVK_ANSI_Grave = 0x32; - private const int kVK_ANSI_KeypadDecimal = 0x41; - private const int kVK_ANSI_KeypadMultiply = 0x43; - private const int kVK_ANSI_KeypadPlus = 0x45; - private const int kVK_ANSI_KeypadClear = 0x47; - private const int kVK_ANSI_KeypadDivide = 0x4B; - private const int kVK_ANSI_KeypadEnter = 0x4C; - private const int kVK_ANSI_KeypadMinus = 0x4E; - private const int kVK_ANSI_KeypadEquals = 0x51; - private const int kVK_ANSI_Keypad0 = 0x52; - private const int kVK_ANSI_Keypad1 = 0x53; - private const int kVK_ANSI_Keypad2 = 0x54; - private const int kVK_ANSI_Keypad3 = 0x55; - private const int kVK_ANSI_Keypad4 = 0x56; - private const int kVK_ANSI_Keypad5 = 0x57; - private const int kVK_ANSI_Keypad6 = 0x58; - private const int kVK_ANSI_Keypad7 = 0x59; - private const int kVK_ANSI_Keypad8 = 0x5B; - private const int kVK_ANSI_Keypad9 = 0x5C; - private const int kVK_Return = 0x24; - private const int kVK_Tab = 0x30; - private const int kVK_Space = 0x31; - private const int kVK_Delete = 0x33; - private const int kVK_Escape = 0x35; - private const int kVK_Command = 0x37; - private const int kVK_Shift = 0x38; - private const int kVK_CapsLock = 0x39; - private const int kVK_Option = 0x3A; - private const int kVK_Control = 0x3B; - private const int kVK_RightCommand = 0x36; - private const int kVK_RightShift = 0x3C; - private const int kVK_RightOption = 0x3D; - private const int kVK_RightControl = 0x3E; - private const int kVK_Function = 0x3F; - private const int kVK_F17 = 0x40; - private const int kVK_VolumeUp = 0x48; - private const int kVK_VolumeDown = 0x49; - private const int kVK_Mute = 0x4A; - private const int kVK_F18 = 0x4F; - private const int kVK_F19 = 0x50; - private const int kVK_F20 = 0x5A; - private const int kVK_F5 = 0x60; - private const int kVK_F6 = 0x61; - private const int kVK_F7 = 0x62; - private const int kVK_F3 = 0x63; - private const int kVK_F8 = 0x64; - private const int kVK_F9 = 0x65; - private const int kVK_F11 = 0x67; - private const int kVK_F13 = 0x69; - private const int kVK_F16 = 0x6A; - private const int kVK_F14 = 0x6B; - private const int kVK_F10 = 0x6D; - private const int kVK_F12 = 0x6F; - private const int kVK_F15 = 0x71; - private const int kVK_Help = 0x72; - private const int kVK_Home = 0x73; - private const int kVK_PageUp = 0x74; - private const int kVK_ForwardDelete = 0x75; - private const int kVK_F4 = 0x76; - private const int kVK_End = 0x77; - private const int kVK_F2 = 0x78; - private const int kVK_PageDown = 0x79; - private const int kVK_F1 = 0x7A; - private const int kVK_LeftArrow = 0x7B; - private const int kVK_RightArrow = 0x7C; - private const int kVK_DownArrow = 0x7D; - private const int kVK_UpArrow = 0x7E; - private const int kVK_ISO_Section = 0x0A; - private const int kVK_JIS_Yen = 0x5D; - private const int kVK_JIS_Underscore = 0x5E; - private const int kVK_JIS_KeypadComma = 0x5F; - private const int kVK_JIS_Eisu = 0x66; - private const int kVK_JIS_Kana = 0x68; - // ReSharper restore UnusedMember.Local - // ReSharper restore InconsistentNaming - //TODO: Map missing keys - static readonly Dictionary Keys = new Dictionary - { - [kVK_ANSI_A] = Key.A, - [kVK_ANSI_S] = Key.S, - [kVK_ANSI_D] = Key.D, - [kVK_ANSI_F] = Key.F, - [kVK_ANSI_H] = Key.H, - [kVK_ANSI_G] = Key.G, - [kVK_ANSI_Z] = Key.Z, - [kVK_ANSI_X] = Key.X, - [kVK_ANSI_C] = Key.C, - [kVK_ANSI_V] = Key.V, - [kVK_ANSI_B] = Key.B, - [kVK_ANSI_Q] = Key.Q, - [kVK_ANSI_W] = Key.W, - [kVK_ANSI_E] = Key.E, - [kVK_ANSI_R] = Key.R, - [kVK_ANSI_Y] = Key.Y, - [kVK_ANSI_T] = Key.T, - [kVK_ANSI_1] = Key.D1, - [kVK_ANSI_2] = Key.D2, - [kVK_ANSI_3] = Key.D3, - [kVK_ANSI_4] = Key.D4, - [kVK_ANSI_6] = Key.D6, - [kVK_ANSI_5] = Key.D5, - //[kVK_ANSI_Equal] = Key.?, - [kVK_ANSI_9] = Key.D9, - [kVK_ANSI_7] = Key.D7, - [kVK_ANSI_Minus] = Key.OemMinus, - [kVK_ANSI_8] = Key.D8, - [kVK_ANSI_0] = Key.D0, - [kVK_ANSI_RightBracket] = Key.OemCloseBrackets, - [kVK_ANSI_O] = Key.O, - [kVK_ANSI_U] = Key.U, - [kVK_ANSI_LeftBracket] = Key.OemOpenBrackets, - [kVK_ANSI_I] = Key.I, - [kVK_ANSI_P] = Key.P, - [kVK_ANSI_L] = Key.L, - [kVK_ANSI_J] = Key.J, - [kVK_ANSI_Quote] = Key.OemQuotes, - [kVK_ANSI_K] = Key.K, - [kVK_ANSI_Semicolon] = Key.OemSemicolon, - [kVK_ANSI_Backslash] = Key.OemBackslash, - [kVK_ANSI_Comma] = Key.OemComma, - //[kVK_ANSI_Slash] = Key.?, - [kVK_ANSI_N] = Key.N, - [kVK_ANSI_M] = Key.M, - [kVK_ANSI_Period] = Key.OemPeriod, - //[kVK_ANSI_Grave] = Key.?, - [kVK_ANSI_KeypadDecimal] = Key.Decimal, - [kVK_ANSI_KeypadMultiply] = Key.Multiply, - [kVK_ANSI_KeypadPlus] = Key.OemPlus, - [kVK_ANSI_KeypadClear] = Key.Clear, - [kVK_ANSI_KeypadDivide] = Key.Divide, - [kVK_ANSI_KeypadEnter] = Key.Enter, - [kVK_ANSI_KeypadMinus] = Key.OemMinus, - //[kVK_ANSI_KeypadEquals] = Key.?, - [kVK_ANSI_Keypad0] = Key.NumPad0, - [kVK_ANSI_Keypad1] = Key.NumPad1, - [kVK_ANSI_Keypad2] = Key.NumPad2, - [kVK_ANSI_Keypad3] = Key.NumPad3, - [kVK_ANSI_Keypad4] = Key.NumPad4, - [kVK_ANSI_Keypad5] = Key.NumPad5, - [kVK_ANSI_Keypad6] = Key.NumPad6, - [kVK_ANSI_Keypad7] = Key.NumPad7, - [kVK_ANSI_Keypad8] = Key.NumPad8, - [kVK_ANSI_Keypad9] = Key.NumPad9, - [kVK_Return] = Key.Return, - [kVK_Tab] = Key.Tab, - [kVK_Space] = Key.Space, - [kVK_Delete] = Key.Back, - [kVK_Escape] = Key.Escape, - [kVK_Command] = Key.LWin, - [kVK_Shift] = Key.LeftShift, - [kVK_CapsLock] = Key.CapsLock, - [kVK_Option] = Key.LeftAlt, - [kVK_Control] = Key.LeftCtrl, - [kVK_RightCommand] = Key.RWin, - [kVK_RightShift] = Key.RightShift, - [kVK_RightOption] = Key.RightAlt, - [kVK_RightControl] = Key.RightCtrl, - //[kVK_Function] = Key.?, - [kVK_F17] = Key.F17, - [kVK_VolumeUp] = Key.VolumeUp, - [kVK_VolumeDown] = Key.VolumeDown, - [kVK_Mute] = Key.VolumeMute, - [kVK_F18] = Key.F18, - [kVK_F19] = Key.F19, - [kVK_F20] = Key.F20, - [kVK_F5] = Key.F5, - [kVK_F6] = Key.F6, - [kVK_F7] = Key.F7, - [kVK_F3] = Key.F3, - [kVK_F8] = Key.F8, - [kVK_F9] = Key.F9, - [kVK_F11] = Key.F11, - [kVK_F13] = Key.F13, - [kVK_F16] = Key.F16, - [kVK_F14] = Key.F14, - [kVK_F10] = Key.F10, - [kVK_F12] = Key.F12, - [kVK_F15] = Key.F15, - [kVK_Help] = Key.Help, - [kVK_Home] = Key.Home, - [kVK_PageUp] = Key.PageUp, - [kVK_ForwardDelete] = Key.Delete, - [kVK_F4] = Key.F4, - [kVK_End] = Key.End, - [kVK_F2] = Key.F2, - [kVK_PageDown] = Key.PageDown, - [kVK_F1] = Key.F1, - [kVK_LeftArrow] = Key.Left, - [kVK_RightArrow] = Key.Right, - [kVK_DownArrow] = Key.Down, - [kVK_UpArrow] = Key.Up, - /* - [kVK_ISO_Section] = Key.?, - [kVK_JIS_Yen] = Key.?, - [kVK_JIS_Underscore] = Key.?, - [kVK_JIS_KeypadComma] = Key.?, - [kVK_JIS_Eisu] = Key.?, - [kVK_JIS_Kana] = Key.? - */ - }; - - - public static Key? TransformKeyCode(ushort code) - { - Key rv; - if (Keys.TryGetValue(code, out rv)) - return rv; - return null; - } - } -} diff --git a/src/OSX/Avalonia.MonoMac/MacScreen.cs b/src/OSX/Avalonia.MonoMac/MacScreen.cs deleted file mode 100644 index 3d5ab0769ff..00000000000 --- a/src/OSX/Avalonia.MonoMac/MacScreen.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using Avalonia.Platform; - -namespace Avalonia.MonoMac -{ - public class MacScreen : Screen - { - private readonly IntPtr handle; - - public MacScreen(Rect bounds, Rect workingArea, bool primary, IntPtr handle) : base(bounds, workingArea, primary) - { - this.handle = handle; - } - - public override int GetHashCode() - { - return (int)handle; - } - - public override bool Equals(object obj) - { - return (obj is MacScreen screen) ? this.handle == screen.handle : base.Equals(obj); - } - } -} \ No newline at end of file diff --git a/src/OSX/Avalonia.MonoMac/MonoMacPlatform.cs b/src/OSX/Avalonia.MonoMac/MonoMacPlatform.cs deleted file mode 100644 index 0d2d4d3f9cc..00000000000 --- a/src/OSX/Avalonia.MonoMac/MonoMacPlatform.cs +++ /dev/null @@ -1,140 +0,0 @@ -using System; -using System.Threading; -using Avalonia.Controls; -using Avalonia.Controls.Platform; -using Avalonia.Input; -using Avalonia.Input.Platform; -using Avalonia.Platform; -using Avalonia.Rendering; -using MonoMac.AppKit; -using MonoMac.Foundation; -using MonoMac.ObjCRuntime; - -namespace Avalonia.MonoMac -{ - public class MonoMacPlatform : IWindowingPlatform, IPlatformSettings - { - internal static MonoMacPlatform Instance { get; private set; } - internal readonly MouseDevice MouseDevice = new MouseDevice(); - readonly KeyboardDevice _keyboardDevice = new KeyboardDevice(); - internal static NSApplication App; - private static bool s_monoMacInitialized; - private static bool s_showInDock = true; - private static IRenderLoop s_renderLoop; - private static IRenderTimer s_renderTimer; - - void DoInitialize() - { - InitializeMonoMac(); - AvaloniaLocator.CurrentMutable - .Bind().ToTransient() - .Bind().ToSingleton() - .Bind().ToConstant(_keyboardDevice) - .Bind().ToConstant(MouseDevice) - .Bind().ToConstant(this) - .Bind().ToConstant(this) - .Bind().ToSingleton() - .Bind().ToSingleton() - .Bind().ToConstant(s_renderLoop) - .Bind().ToConstant(s_renderTimer) - .Bind().ToConstant(new PlatformHotkeyConfiguration(InputModifiers.Windows)) - .Bind().ToConstant(PlatformThreadingInterface.Instance) - /*.Bind().ToTransient()*/; - } - - public static void Initialize() - { - Instance = new MonoMacPlatform(); - Instance.DoInitialize(); - - } - - - /// - /// See "Using POSIX Threads in a Cocoa Application" section here: - /// https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Multithreading/CreatingThreads/CreatingThreads.html#//apple_ref/doc/uid/20000738-125024 - /// - class ThreadHelper : NSObject - { - private readonly AutoResetEvent _event = new AutoResetEvent(false); - private const string InitThreadingName = "initThreading"; - [Export(InitThreadingName)] - public void DoNothing() - { - _event.Set(); - } - - public static void InitializeCocoaThreadingLocks() - { - var helper = new ThreadHelper(); - var thread = new NSThread(helper, Selector.FromHandle(Selector.GetHandle(InitThreadingName)), new NSObject()); - thread.Start(); - helper._event.WaitOne(); - helper._event.Dispose(); - if (!NSThread.IsMultiThreaded) - { - throw new Exception("Unable to initialize Cocoa threading"); - } - } - } - - void InitializeMonoMac() - { - if(s_monoMacInitialized) - return; - NSApplication.Init(); - ThreadHelper.InitializeCocoaThreadingLocks(); - App = NSApplication.SharedApplication; - UpdateActivationPolicy(); - s_renderLoop = new RenderLoop(); - s_renderTimer = new RenderTimer(60); //TODO: use CVDisplayLink - s_monoMacInitialized = true; - } - - static void UpdateActivationPolicy() => App.ActivationPolicy = ShowInDock - ? NSApplicationActivationPolicy.Regular - : NSApplicationActivationPolicy.Accessory; - - public static bool ShowInDock - { - get => s_showInDock; - set - { - s_showInDock = value; - if (s_monoMacInitialized) - UpdateActivationPolicy(); - } - } - - public static bool UseDeferredRendering { get; set; } = true; - - public Size DoubleClickSize => new Size(4, 4); - public TimeSpan DoubleClickTime => TimeSpan.FromSeconds(NSEvent.DoubleClickInterval); - - public IWindowImpl CreateWindow() => new WindowImpl(); - - public IEmbeddableWindowImpl CreateEmbeddableWindow() - { - throw new PlatformNotSupportedException(); - } - - public IPopupImpl CreatePopup() - { - return new PopupImpl(); - } - } -} - - -namespace Avalonia -{ - public static class MonoMacPlatformExtensions - { - public static T UseMonoMac(this T builder, bool? useDeferredRendering = null) where T : AppBuilderBase, new() - { - if (useDeferredRendering.HasValue) - MonoMac.MonoMacPlatform.UseDeferredRendering = useDeferredRendering.Value; - return builder.UseWindowingSubsystem(MonoMac.MonoMacPlatform.Initialize, "MonoMac"); - } - } -} diff --git a/src/OSX/Avalonia.MonoMac/PlatformThreadingInterface.cs b/src/OSX/Avalonia.MonoMac/PlatformThreadingInterface.cs deleted file mode 100644 index 04a36d9f0f4..00000000000 --- a/src/OSX/Avalonia.MonoMac/PlatformThreadingInterface.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System; -using System.Threading; -using Avalonia.Platform; -using Avalonia.Threading; -using MonoMac.AppKit; -using MonoMac.CoreGraphics; -using MonoMac.Foundation; -using MonoMac.ObjCRuntime; - -namespace Avalonia.MonoMac -{ - class PlatformThreadingInterface : NSObject, IPlatformThreadingInterface - { - private bool _signaled; - private const string SignaledSelectorName = "avaloniauiSignaled"; - private readonly Selector _signaledSelector = new Selector(SignaledSelectorName); - public static PlatformThreadingInterface Instance { get; } = new PlatformThreadingInterface(); - public bool CurrentThreadIsLoopThread => NSThread.Current.IsMainThread; - - public event Action Signaled; - - public IDisposable StartTimer(DispatcherPriority priority, TimeSpan interval, Action tick) - => NSTimer.CreateRepeatingScheduledTimer(interval, () => tick()); - - public void Signal(DispatcherPriority prio) - { - lock (this) - { - if (_signaled) - return; - _signaled = true; - } - PerformSelector(_signaledSelector, NSThread.MainThread, this, false, - new[] - { - NSRunLoop.NSDefaultRunLoopMode, NSRunLoop.NSRunLoopEventTracking, NSRunLoop.NSRunLoopModalPanelMode, - NSRunLoop.NSRunLoopCommonModes, NSRunLoop.NSRunLoopConnectionReplyMode - }); - } - - [Export(SignaledSelectorName)] - public void CallSignaled() - { - lock (this) - { - if (!_signaled) - return; - _signaled = false; - } - Signaled?.Invoke(null); - } - - - public void RunLoop(CancellationToken cancellationToken) - { - NSApplication.SharedApplication.ActivateIgnoringOtherApps(true); - var app = NSApplication.SharedApplication; - cancellationToken.Register(() => - { - app.PostEvent(NSEvent.OtherEvent(NSEventType.ApplicationDefined, default(CGPoint), - default(NSEventModifierMask), 0, 0, null, 0, 0, 0), true); - }); - while (!cancellationToken.IsCancellationRequested) - { - var ev = app.NextEvent(NSEventMask.AnyEvent, NSDate.DistantFuture, NSRunLoop.NSDefaultRunLoopMode, true); - if (ev != null) - { - app.SendEvent(ev); - ev.Dispose(); - } - } - } - } -} diff --git a/src/OSX/Avalonia.MonoMac/PopupImpl.cs b/src/OSX/Avalonia.MonoMac/PopupImpl.cs deleted file mode 100644 index 267e47a6a04..00000000000 --- a/src/OSX/Avalonia.MonoMac/PopupImpl.cs +++ /dev/null @@ -1,30 +0,0 @@ -using Avalonia.Platform; -using MonoMac.AppKit; - -namespace Avalonia.MonoMac -{ - class PopupImpl : WindowBaseImpl, IPopupImpl - { - public PopupImpl() - { - UpdateStyle(); - Window.Level = NSWindowLevel.PopUpMenu; - } - - protected override NSWindowStyle GetStyle() - { - return NSWindowStyle.Borderless; - } - - protected override CustomWindow CreateCustomWindow() => new CustomPopupWindow(this); - - private class CustomPopupWindow : CustomWindow - { - public CustomPopupWindow(WindowBaseImpl impl) - : base(impl) - { } - - public override bool WorksWhenModal() => true; - } - } -} diff --git a/src/OSX/Avalonia.MonoMac/RenderTimer.cs b/src/OSX/Avalonia.MonoMac/RenderTimer.cs deleted file mode 100644 index f3c49828d63..00000000000 --- a/src/OSX/Avalonia.MonoMac/RenderTimer.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using Avalonia.Platform; -using Avalonia.Rendering; -using MonoMac.Foundation; - -namespace Avalonia.MonoMac -{ - //TODO: Switch to using CVDisplayLink - public class RenderTimer : DefaultRenderTimer - { - public RenderTimer(int framesPerSecond) : base(framesPerSecond) - { - } - - protected override IDisposable StartCore(Action tick) - { - return AvaloniaLocator.Current.GetService().StartSystemTimer( - TimeSpan.FromSeconds(1.0 / FramesPerSecond), - () => - { - using (new NSAutoreleasePool()) - { - tick?.Invoke(TimeSpan.FromMilliseconds(Environment.TickCount)); - } - }); - } - } -} diff --git a/src/OSX/Avalonia.MonoMac/ScreenImpl.cs b/src/OSX/Avalonia.MonoMac/ScreenImpl.cs deleted file mode 100644 index 46cd200cab4..00000000000 --- a/src/OSX/Avalonia.MonoMac/ScreenImpl.cs +++ /dev/null @@ -1,49 +0,0 @@ -using Avalonia.Platform; -using MonoMac.AppKit; -using MonoMac.Foundation; - -namespace Avalonia.MonoMac -{ - public class ScreenImpl : IScreenImpl - { - private const string NSApplicationDidChangeScreenParametersNotification = "NSApplicationDidChangeScreenParametersNotification"; - - public int ScreenCount - { - get => NSScreen.Screens.Length; - } - - private Screen[] _allScreens; - public Screen[] AllScreens - { - get - { - if (_allScreens == null) - { - NSScreen[] screens = NSScreen.Screens; - Screen[] s = new Screen[screens.Length]; - NSScreen primary = NSScreen.MainScreen; - for (int i = 0; i < screens.Length; i++) - { - Rect bounds = screens[i].Frame.ToAvaloniaRect().ConvertRectY(); - Rect workArea = screens[i].VisibleFrame.ToAvaloniaRect().ConvertRectY(); - s[i] = new MacScreen(bounds, workArea, i == 0, screens[i].Handle); - } - - _allScreens = s; - } - return _allScreens; - } - } - - public ScreenImpl() - { - NSNotificationCenter.DefaultCenter.AddObserver(NSApplicationDidChangeScreenParametersNotification, MonitorsChanged); - } - - private void MonitorsChanged(NSNotification notification) - { - _allScreens = null; - } - } -} diff --git a/src/OSX/Avalonia.MonoMac/Stubs.cs b/src/OSX/Avalonia.MonoMac/Stubs.cs deleted file mode 100644 index 188ceeaab17..00000000000 --- a/src/OSX/Avalonia.MonoMac/Stubs.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System.IO; -using Avalonia.Platform; - -namespace Avalonia.MonoMac -{ - // OSX doesn't have a concept of *window* icon. - // Icons in the title bar are only shown if there is - // an opened file (on disk) associated with the current window - // see http://stackoverflow.com/a/7038671/2231814 - class IconLoader : IPlatformIconLoader - { - class IconStub : IWindowIconImpl - { - private readonly IBitmapImpl _bitmap; - - public IconStub(IBitmapImpl bitmap) - { - _bitmap = bitmap; - } - - public void Save(Stream outputStream) - { - _bitmap.Save(outputStream); - } - } - - public IWindowIconImpl LoadIcon(string fileName) - { - return new IconStub( - AvaloniaLocator.Current.GetService().LoadBitmap(fileName)); - } - - public IWindowIconImpl LoadIcon(Stream stream) - { - return new IconStub( - AvaloniaLocator.Current.GetService().LoadBitmap(stream)); - } - - public IWindowIconImpl LoadIcon(IBitmapImpl bitmap) - { - var ms = new MemoryStream(); - bitmap.Save(ms); - ms.Seek(0, SeekOrigin.Begin); - return LoadIcon(ms); - } - } -} diff --git a/src/OSX/Avalonia.MonoMac/SystemDialogsImpl.cs b/src/OSX/Avalonia.MonoMac/SystemDialogsImpl.cs deleted file mode 100644 index 382311e28ac..00000000000 --- a/src/OSX/Avalonia.MonoMac/SystemDialogsImpl.cs +++ /dev/null @@ -1,89 +0,0 @@ -using System.Linq; -using System.Threading.Tasks; -using Avalonia.Controls; -using Avalonia.Controls.Platform; -using Avalonia.Platform; -using MonoMac.AppKit; -using MonoMac.Foundation; - -namespace Avalonia.MonoMac -{ - class SystemDialogsImpl : ISystemDialogImpl - { - - Task RunPanel(NSSavePanel panel, IWindowImpl parent) - { - var keyWindow = MonoMacPlatform.App.KeyWindow; - var tcs = new TaskCompletionSource(); - void OnComplete(int result) - { - if (result == 0) - tcs.SetResult(null); - else - { - if (panel is NSOpenPanel openPanel) - tcs.SetResult(openPanel.Urls.Select(url => url.AbsoluteString.Replace("file://", "")).ToArray()); - else - tcs.SetResult(new[] { panel.Url.AbsoluteString.Replace("file://", "") }); - } - panel.OrderOut(panel); - keyWindow?.MakeKeyAndOrderFront(keyWindow); - MonoMacPlatform.App.ActivateIgnoringOtherApps(true); - panel.Dispose(); - } - - if (parent != null) - { - var window = (WindowImpl)parent; - panel.BeginSheet(window.Window, OnComplete); - } - else - panel.Begin(OnComplete); - return tcs.Task; - } - - public Task ShowFileDialogAsync(FileDialog dialog, IWindowImpl parent) - { - /* NOTES - * DefaultFileExtension is not supported - * Named filters are not supported - */ - NSSavePanel panel; - if (dialog is OpenFileDialog openDialog) - { - var openPanel = new NSOpenPanel(); - panel = openPanel; - - openPanel.AllowsMultipleSelection = openDialog.AllowMultiple; - } - else - panel = new NSSavePanel(); - panel.Title = panel.Title; - if (dialog.InitialDirectory != null) - panel.DirectoryUrl = new NSUrl(dialog.InitialDirectory); - if (dialog.InitialFileName != null) - panel.NameFieldStringValue = dialog.InitialFileName; - if (dialog.Filters?.Count > 0) - panel.AllowedFileTypes = dialog.Filters.SelectMany(f => f.Extensions).Distinct().ToArray(); - - - return RunPanel(panel, parent); - } - - - - public async Task ShowFolderDialogAsync(OpenFolderDialog dialog, IWindowImpl parent) - { - var panel = new NSOpenPanel - { - Title = dialog.Title, - CanChooseDirectories = true, - CanCreateDirectories = true, - CanChooseFiles = false - }; - if (dialog.DefaultDirectory != null) - panel.DirectoryUrl = new NSUrl(dialog.DefaultDirectory); - return (await RunPanel(panel, parent))?.FirstOrDefault(); - } - } -} diff --git a/src/OSX/Avalonia.MonoMac/TopLevelImpl.cs b/src/OSX/Avalonia.MonoMac/TopLevelImpl.cs deleted file mode 100644 index fb4c5afc2de..00000000000 --- a/src/OSX/Avalonia.MonoMac/TopLevelImpl.cs +++ /dev/null @@ -1,505 +0,0 @@ -using System; -using System.Collections.Generic; -using Avalonia.Controls.Platform.Surfaces; -using Avalonia.Input; -using Avalonia.Input.Raw; -using Avalonia.Platform; -using Avalonia.Rendering; -using Avalonia.Threading; -using MonoMac.AppKit; -using MonoMac.CoreGraphics; -using MonoMac.Foundation; -using MonoMac.ObjCRuntime; - -namespace Avalonia.MonoMac -{ - abstract class TopLevelImpl : ITopLevelImpl, IFramebufferPlatformSurface - { - public TopLevelView View { get; } - private readonly IMouseDevice _mouse = AvaloniaLocator.Current.GetService(); - private readonly IDragDropDevice _dragDevice = AvaloniaLocator.Current.GetService(); - protected TopLevelImpl() - { - View = new TopLevelView(this); - } - - protected virtual void OnInput(RawInputEventArgs args) - { - Dispatcher.UIThread.RunJobs(DispatcherPriority.Input + 1); - Input?.Invoke(args); - } - - [Adopts("NSTextInputClient")] - public class TopLevelView : NSView - { - TopLevelImpl _tl; - bool _isLeftPressed, _isRightPressed, _isMiddlePressed; - private readonly IMouseDevice _mouse; - private readonly IKeyboardDevice _keyboard; - private NSTrackingArea _area; - private NSCursor _cursor; - private bool _nonUiRedrawQueued; - private bool _isMouseOver; - - public CGSize PixelSize { get; set; } - - public CGSize LogicalSize { get; set; } - - private SavedImage _backBuffer; - public object SyncRoot { get; } = new object(); - - public TopLevelView(TopLevelImpl tl) - { - _tl = tl; - _mouse = AvaloniaLocator.Current.GetService(); - _keyboard = AvaloniaLocator.Current.GetService(); - - RegisterForDraggedTypes(new string[] { - "public.data" // register for any kind of data. - }); - } - - protected override void Dispose(bool disposing) - { - if (disposing) - { - _backBuffer?.Dispose(); - _backBuffer = null; - } - base.Dispose(disposing); - } - - public override bool ConformsToProtocol(IntPtr protocol) - { - var rv = base.ConformsToProtocol(protocol); - return rv; - } - - public override bool IsOpaque => false; - - public override void DrawRect(CGRect dirtyRect) - { - lock (SyncRoot) - _nonUiRedrawQueued = false; - Dispatcher.UIThread.RunJobs(DispatcherPriority.Render); - lock (SyncRoot) - { - if (_backBuffer != null) - { - using (var context = NSGraphicsContext.CurrentContext.GraphicsPort) - { - context.SetFillColor(255, 255, 255, 255); - context.FillRect(new CGRect(default(CGPoint), LogicalSize)); - context.TranslateCTM(0, LogicalSize.Height - _backBuffer.LogicalSize.Height); - context.DrawImage(new CGRect(default(CGPoint), _backBuffer.LogicalSize), _backBuffer.Image); - context.Flush(); - NSGraphicsContext.CurrentContext.FlushGraphics(); - } - } - } - _tl.Paint?.Invoke(dirtyRect.ToAvaloniaRect()); - } - - public void SetBackBufferImage(SavedImage image) - { - lock (SyncRoot) - { - _backBuffer?.Dispose(); - _backBuffer = image; - if (image == null) - return; - - if (_nonUiRedrawQueued) - return; - _nonUiRedrawQueued = true; - Dispatcher.UIThread.Post( - () => - { - lock (SyncRoot) - { - if (!_nonUiRedrawQueued) - return; - _nonUiRedrawQueued = false; - } - SetNeedsDisplayInRect(Frame); - Display(); - }, DispatcherPriority.Render); - - } - } - - [Export("viewDidChangeBackingProperties:")] - public void ViewDidChangeBackingProperties() - { - _tl?.ScalingChanged?.Invoke(_tl.Scaling); - } - - void UpdateCursor() - { - ResetCursorRects(); - if (_cursor != null) - { - AddCursorRect(Frame, _cursor); - if (_isMouseOver) - _cursor.Set(); - } - } - - static readonly NSCursor ArrowCursor = NSCursor.ArrowCursor; - - public void SetCursor(NSCursor cursor) - { - _cursor = cursor ?? ArrowCursor; - UpdateCursor(); - } - - private NSDragOperation SendRawDragEvent(NSDraggingInfo sender, RawDragEventType type) - { - Action input = _tl.Input; - IDragDropDevice dragDevice = _tl._dragDevice; - IInputRoot root = _tl?.InputRoot; - if (root == null || dragDevice == null || input == null) - return NSDragOperation.None; - - var dragOp = DraggingInfo.ConvertDragOperation(sender.DraggingSourceOperationMask); - DraggingInfo info = new DraggingInfo(sender); - - var pt = TranslateLocalPoint(info.Location); - var args = new RawDragEvent(dragDevice, type, root, pt, info, dragOp, GetModifiers(NSEvent.CurrentModifierFlags)); - input(args); - return DraggingInfo.ConvertDragOperation(args.Effects); - } - - public override NSDragOperation DraggingEntered(NSDraggingInfo sender) - { - return SendRawDragEvent(sender, RawDragEventType.DragEnter); - } - - public override NSDragOperation DraggingUpdated(NSDraggingInfo sender) - { - return SendRawDragEvent(sender, RawDragEventType.DragOver); - } - - public override void DraggingExited(NSDraggingInfo sender) - { - SendRawDragEvent(sender, RawDragEventType.DragLeave); - } - - public override bool PrepareForDragOperation(NSDraggingInfo sender) - { - return SendRawDragEvent(sender, RawDragEventType.DragOver) != NSDragOperation.None; - } - - public override bool PerformDragOperation(NSDraggingInfo sender) - { - return SendRawDragEvent(sender, RawDragEventType.Drop) != NSDragOperation.None; - } - - - public override void SetFrameSize(CGSize newSize) - { - lock (SyncRoot) - { - base.SetFrameSize(newSize); - LogicalSize = Frame.Size; - PixelSize = ConvertSizeToBacking(LogicalSize); - } - - if (_area != null) - { - RemoveTrackingArea(_area); - _area.Dispose(); - } - _area = new NSTrackingArea(new CGRect(default(CGPoint), newSize), - NSTrackingAreaOptions.ActiveAlways | - NSTrackingAreaOptions.MouseMoved | - NSTrackingAreaOptions.EnabledDuringMouseDrag, this, null); - AddTrackingArea(_area); - UpdateCursor(); - _tl?.Resized?.Invoke(_tl.ClientSize); - Dispatcher.UIThread.RunJobs(DispatcherPriority.Layout); - } - - InputModifiers GetModifiers(NSEventModifierMask mod) - { - var rv = new InputModifiers(); - if (mod.HasFlag(NSEventModifierMask.ControlKeyMask)) - rv |= InputModifiers.Control; - if (mod.HasFlag(NSEventModifierMask.ShiftKeyMask)) - rv |= InputModifiers.Shift; - if (mod.HasFlag(NSEventModifierMask.AlternateKeyMask)) - rv |= InputModifiers.Alt; - if (mod.HasFlag(NSEventModifierMask.CommandKeyMask)) - rv |= InputModifiers.Windows; - - if (_isLeftPressed) - rv |= InputModifiers.LeftMouseButton; - if (_isMiddlePressed) - rv |= InputModifiers.MiddleMouseButton; - if (_isRightPressed) - rv |= InputModifiers.RightMouseButton; - return rv; - } - - public Point TranslateLocalPoint(Point pt) => pt.WithY(Bounds.Height - pt.Y); - - Vector GetDelta(NSEvent ev) - { - var rv = new Vector(ev.ScrollingDeltaX, ev.ScrollingDeltaY); - //TODO: Verify if handling of HasPreciseScrollingDeltas - // is required (touchpad or magic-mouse is needed) - return rv; - } - - uint GetTimeStamp(NSEvent ev) => (uint) (ev.Timestamp * 1000); - - void MouseEvent(NSEvent ev, RawMouseEventType type) - { - BecomeFirstResponder(); - var loc = TranslateLocalPoint(ConvertPointToView(ev.LocationInWindow, this).ToAvaloniaPoint()); - var ts = GetTimeStamp(ev); - var mod = GetModifiers(ev.ModifierFlags); - if (type == RawMouseEventType.Wheel) - { - var delta = GetDelta(ev); - // ReSharper disable CompareOfFloatsByEqualityOperator - if (delta.X == 0 && delta.Y == 0) - return; - // ReSharper restore CompareOfFloatsByEqualityOperator - _tl.OnInput(new RawMouseWheelEventArgs(_mouse, ts, _tl.InputRoot, loc, - delta, mod)); - } - else - _tl.OnInput(new RawMouseEventArgs(_mouse, ts, _tl.InputRoot, type, loc, mod)); - } - - public override void MouseMoved(NSEvent theEvent) - { - MouseEvent(theEvent, RawMouseEventType.Move); - base.MouseMoved(theEvent); - } - - public override void MouseDragged(NSEvent theEvent) - { - MouseEvent(theEvent, RawMouseEventType.Move); - base.MouseDragged(theEvent); - } - - public override void OtherMouseDragged(NSEvent theEvent) - { - MouseEvent(theEvent, RawMouseEventType.Move); - base.OtherMouseDragged(theEvent); - } - - public override void RightMouseDragged(NSEvent theEvent) - { - MouseEvent(theEvent, RawMouseEventType.Move); - base.RightMouseDragged(theEvent); - } - - public NSEvent LastMouseDownEvent { get; private set; } - - public override void MouseDown(NSEvent theEvent) - { - _isLeftPressed = true; - LastMouseDownEvent = theEvent; - MouseEvent(theEvent, RawMouseEventType.LeftButtonDown); - LastMouseDownEvent = null; - base.MouseDown(theEvent); - } - - public override void RightMouseDown(NSEvent theEvent) - { - _isRightPressed = true; - MouseEvent(theEvent, RawMouseEventType.RightButtonDown); - base.RightMouseDown(theEvent); - } - - public override void OtherMouseDown(NSEvent theEvent) - { - _isMiddlePressed = true; - MouseEvent(theEvent, RawMouseEventType.MiddleButtonDown); - base.OtherMouseDown(theEvent); - } - - public override void MouseUp(NSEvent theEvent) - { - _isLeftPressed = false; - MouseEvent(theEvent, RawMouseEventType.LeftButtonUp); - base.MouseUp(theEvent); - } - - public override void RightMouseUp(NSEvent theEvent) - { - _isRightPressed = false; - MouseEvent(theEvent, RawMouseEventType.RightButtonUp); - base.RightMouseUp(theEvent); - } - - public override void OtherMouseUp(NSEvent theEvent) - { - _isMiddlePressed = false; - MouseEvent(theEvent, RawMouseEventType.MiddleButtonUp); - base.OtherMouseUp(theEvent); - } - - public override void ScrollWheel(NSEvent theEvent) - { - MouseEvent(theEvent, RawMouseEventType.Wheel); - base.ScrollWheel(theEvent); - } - - public override void MouseExited(NSEvent theEvent) - { - _isMouseOver = false; - MouseEvent(theEvent, RawMouseEventType.LeaveWindow); - base.MouseExited(theEvent); - } - - public override void MouseEntered(NSEvent theEvent) - { - _isMouseOver = true; - base.MouseEntered(theEvent); - } - - void KeyboardEvent(RawKeyEventType type, NSEvent ev) - { - var code = KeyTransform.TransformKeyCode(ev.KeyCode); - if (!code.HasValue) - return; - _tl.OnInput(new RawKeyEventArgs(_keyboard, GetTimeStamp(ev), - type, code.Value, GetModifiers(ev.ModifierFlags))); - } - - public override void KeyDown(NSEvent theEvent) - { - KeyboardEvent(RawKeyEventType.KeyDown, theEvent); - InputContext.HandleEvent(theEvent); - base.KeyDown(theEvent); - } - - public override void KeyUp(NSEvent theEvent) - { - KeyboardEvent(RawKeyEventType.KeyUp, theEvent); - base.KeyUp(theEvent); - } - - - - #region NSTextInputClient - - public override bool AcceptsFirstResponder() => true; - - public bool HasMarkedText - { - [Export("hasMarkedText")] get => false; - } - - public NSRange MarkedRange - { - [Export("markedRange")] get => new NSRange(NSRange.NotFound, 0); - } - - public NSRange SelectedRange - { - [Export("selectedRange")] get => new NSRange(NSRange.NotFound, 0); - } - - [Export("setMarkedText:selectedRange:replacementRange:")] - public void SetMarkedText(NSString str, NSRange a1, NSRange a2) - { - - } - - [Export("unmarkText")] - public void UnmarkText() - { - - } - - public NSArray ValidAttributesForMarkedText - { - [Export("validAttributesForMarkedText")] get => new NSArray(); - } - - [Export("attributedSubstringForProposedRange:actualRange:")] - public NSAttributedString AttributedSubstringForProposedRange(NSRange range, IntPtr wat) - { - return new NSAttributedString(""); - } - - [Export("insertText:replacementRange:")] - public void InsertText(NSString str, NSRange range) - { - //TODO: timestamp - _tl.OnInput(new RawTextInputEventArgs(_keyboard, 0, str.ToString())); - } - - [Export("characterIndexForPoint:")] - public uint CharacterIndexForPoint(CGPoint pt) - { - return 0; - } - - [Export("firstRectForCharacterRange:actualRange:")] - public CGRect FirstRectForCharacterRange(NSRange range, IntPtr wat) - { - return new CGRect(); - } - - #endregion - } - - public IInputRoot InputRoot { get; private set; } - - public abstract Size ClientSize { get; } - - public double Scaling - { - get - { - if (View.Window == null) - return 1; - return View.Window.BackingScaleFactor; - } - } - - public IEnumerable Surfaces => new[] {this}; - public IMouseDevice MouseDevice => _mouse; - - public Action Input { get; set; } - public Action Paint { get; set; } - public Action Resized { get; set; } - public Action ScalingChanged { get; set; } - public Action Closed { get; set; } - - - public virtual void Dispose() - { - Closed?.Invoke(); - Closed = null; - View.Dispose(); - } - - public IRenderer CreateRenderer(IRenderRoot root) => - MonoMacPlatform.UseDeferredRendering - ? new DeferredRenderer(root, AvaloniaLocator.Current.GetService()) - : (IRenderer) new ImmediateRenderer(root); - - public void Invalidate(Rect rect) - { - if (!MonoMacPlatform.UseDeferredRendering) - View.SetNeedsDisplayInRect(View.Frame); - } - - public abstract Point PointToClient(Point point); - - public abstract Point PointToScreen(Point point); - - public void SetCursor(IPlatformHandle cursor) => View.SetCursor((cursor as Cursor)?.Native); - - public void SetInputRoot(IInputRoot inputRoot) => InputRoot = inputRoot; - - public ILockedFramebuffer Lock() => new EmulatedFramebuffer(View); - } -} diff --git a/src/OSX/Avalonia.MonoMac/WindowBaseImpl.cs b/src/OSX/Avalonia.MonoMac/WindowBaseImpl.cs deleted file mode 100644 index d3053a6af10..00000000000 --- a/src/OSX/Avalonia.MonoMac/WindowBaseImpl.cs +++ /dev/null @@ -1,208 +0,0 @@ -using System; -using Avalonia.Controls; -using Avalonia.Input.Raw; -using Avalonia.Platform; -using MonoMac.AppKit; -using MonoMac.CoreGraphics; -using MonoMac.Foundation; -using MonoMac.ObjCRuntime; - -namespace Avalonia.MonoMac -{ - class WindowBaseImpl : TopLevelImpl, IWindowBaseImpl - { - private readonly ManagedWindowResizeDragHelper _managedDrag; - public CustomWindow Window { get; private set; } - - private bool _closed; - - public WindowBaseImpl() - { - _managedDrag = new ManagedWindowResizeDragHelper(this, _ => { }, ResizeForManagedDrag); - // ReSharper disable once VirtualMemberCallInConstructor - Window = CreateCustomWindow(); - Window.StyleMask = NSWindowStyle.Titled; - Window.BackingType = NSBackingStore.Buffered; - Window.ContentView = View; - // ReSharper disable once VirtualMemberCallInConstructor - Window.Delegate = CreateWindowDelegate(); - } - - public class CustomWindow : NSWindow - { - readonly WindowBaseImpl _impl; - - public CustomWindow(WindowBaseImpl impl) - { - _impl = impl; - } - - public override void BecomeKeyWindow() - { - _impl.Activated?.Invoke(); - base.BecomeKeyWindow(); - } - - public override void ResignKeyWindow() - { - _impl.Deactivated?.Invoke(); - base.ResignKeyWindow(); - } - - private bool _canBecomeKeyAndMain; - public override bool CanBecomeKeyWindow => _canBecomeKeyAndMain; - public override bool CanBecomeMainWindow => _canBecomeKeyAndMain; - - public void SetCanBecomeKeyAndMain() => _canBecomeKeyAndMain = true; - } - - protected virtual CustomWindow CreateCustomWindow() => new CustomWindow(this); - protected virtual NSWindowDelegate CreateWindowDelegate() => new WindowBaseDelegate(this); - - public class WindowBaseDelegate : NSWindowDelegate - { - readonly WindowBaseImpl _impl; - public WindowBaseDelegate(WindowBaseImpl impl) - { - _impl = impl; - } - - public override void DidMoved(global::MonoMac.Foundation.NSNotification notification) - { - _impl.PositionChanged?.Invoke(_impl.Position); - } - - public override bool WindowShouldClose(NSObject sender) - { - bool? preventClose = _impl.Closing?.Invoke(); - return preventClose != true; - } - - public override void WillClose(global::MonoMac.Foundation.NSNotification notification) - { - _impl._closed = true; - _impl.Closed?.Invoke(); - } - - public override CGRect WillUseStandardFrame(NSWindow window, CGRect newFrame) - { - if (_impl is WindowImpl w && w.UndecoratedIsMaximized && w.UndecoratedLastUnmaximizedFrame.HasValue) - return w.UndecoratedLastUnmaximizedFrame.Value; - return window.Screen.VisibleFrame; - } - - public override bool ShouldZoom(NSWindow window, CGRect newFrame) - { - return true; - } - - public override void DidResize(NSNotification notification) - { - _impl.OnResized(); - } - } - - /// - /// As you can't combine NSWindowDelegate overrides and events this is a workaround - /// - protected virtual void OnResized() - { - } - - public Point Position - { - get => Window.Frame.ToAvaloniaRect().BottomLeft.ConvertPointY(); - set => Window.SetFrameTopLeftPoint(value.ToMonoMacPoint().ConvertPointY()); - } - - - protected virtual NSWindowStyle GetStyle() => NSWindowStyle.Borderless; - - protected void UpdateStyle() => Window.StyleMask = GetStyle(); - - - IPlatformHandle IWindowBaseImpl.Handle => new PlatformHandle(Window.Handle, "NSWindow"); - public Size MaxClientSize => NSScreen.Screens[0].Frame.ToAvaloniaRect().Size; - public Action PositionChanged { get; set; } - public Action Deactivated { get; set; } - public Action Activated { get; set; } - public Func Closing { get; set; } - - public override Size ClientSize => Window.ContentRectFor(Window.Frame).Size.ToAvaloniaSize(); - - - public void Show() => Window.MakeKeyAndOrderFront(Window); - - public void Hide() => Window?.OrderOut(Window); - - public void SetTopmost(bool value) => Window.Level = value ? NSWindowLevel.Floating : NSWindowLevel.Normal; - - public void BeginMoveDrag() - { - var ev = View.LastMouseDownEvent; - if (ev == null) - return; - var handle = Selector.GetHandle("performWindowDragWithEvent:"); - Messaging.void_objc_msgSend_IntPtr(Window.Handle, handle, ev.Handle); - } - - public void BeginResizeDrag(WindowEdge edge) - { - var screenPoint = NSEvent.CurrentMouseLocation.ConvertPointY().ToAvaloniaPoint(); - _managedDrag.BeginResizeDrag(edge, PointToClient(screenPoint)); - } - - protected override void OnInput(RawInputEventArgs args) - { - if (_managedDrag.PreprocessInputEvent(ref args)) - return; - base.OnInput(args); - } - - public void Activate() => Window.MakeKeyWindow(); - - public void ResizeForManagedDrag(Rect rc) - { - var frame = new CGRect(rc.X, rc.Position.ConvertPointY().Y - rc.Height, rc.Width, rc.Height); - Window.SetFrame(frame, true); - } - - public void Resize(Size clientSize) - { - var pos = Position; - Window.SetContentSize(clientSize.ToMonoMacSize()); - Position = pos; - } - - public void SetMinMaxSize(Size minSize, Size maxSize) - { - } - - public IScreenImpl Screen - { - get; - } = new ScreenImpl(); - - public override Point PointToClient(Point point) - { - var cocoaScreenPoint = point.ToMonoMacPoint().ConvertPointY(); - var cocoaViewPoint = Window.ConvertScreenToBase(cocoaScreenPoint).ToAvaloniaPoint(); - return View.TranslateLocalPoint(cocoaViewPoint); - } - - public override Point PointToScreen(Point point) - { - var cocoaViewPoint = View.TranslateLocalPoint(point).ToMonoMacPoint(); - var cocoaScreenPoint = Window.ConvertBaseToScreen(cocoaViewPoint); - return cocoaScreenPoint.ConvertPointY().ToAvaloniaPoint(); - } - - public override void Dispose() - { - if (!_closed) - Window.Close(); - Window.Dispose(); - base.Dispose(); - } - } -} diff --git a/src/OSX/Avalonia.MonoMac/WindowImpl.cs b/src/OSX/Avalonia.MonoMac/WindowImpl.cs deleted file mode 100644 index f276e07c991..00000000000 --- a/src/OSX/Avalonia.MonoMac/WindowImpl.cs +++ /dev/null @@ -1,176 +0,0 @@ -using System; -using Avalonia.Controls; -using Avalonia.Platform; -using Avalonia.Threading; -using MonoMac.AppKit; -using MonoMac.CoreGraphics; - -namespace Avalonia.MonoMac -{ - class WindowImpl : WindowBaseImpl, IWindowImpl - { - public bool IsDecorated = true; - public bool IsResizable = true; - public CGRect? UndecoratedLastUnmaximizedFrame; - - private WindowState _lastWindowState; - - public WindowImpl() - { - // Post UpdateStyle to UIThread otherwise for as yet unknown reason. - // The window becomes transparent to mouse clicks except a 100x100 square - // at the top left. (danwalmsley) - Dispatcher.UIThread.Post(() => - { - UpdateStyle(); - }); - - Window.SetCanBecomeKeyAndMain(); - } - - - protected override void OnResized() - { - var windowState = Window.IsMiniaturized ? WindowState.Minimized - : (IsZoomed ? WindowState.Maximized : WindowState.Normal); - - if (windowState != _lastWindowState) - { - _lastWindowState = windowState; - WindowStateChanged?.Invoke(windowState); - } - } - - public WindowState WindowState - { - get - { - if (Window.IsMiniaturized) - return WindowState.Minimized; - if (IsZoomed) - return WindowState.Maximized; - return WindowState.Normal; - } - set - { - if (value == WindowState.Maximized) - { - if (Window.IsMiniaturized) - Window.Deminiaturize(Window); - if (!IsZoomed) - DoZoom(); - } - else if (value.HasFlag(WindowState.Minimized)) - Window.Miniaturize(Window); - else - { - if (Window.IsMiniaturized) - Window.Deminiaturize(Window); - if (IsZoomed) - DoZoom(); - } - } - } - - public Action WindowStateChanged { get; set; } - - bool IsZoomed => IsDecorated ? Window.IsZoomed : UndecoratedIsMaximized; - - public bool UndecoratedIsMaximized => Window.Frame == Window.Screen.VisibleFrame; - - void DoZoom() - { - if (IsDecorated) - Window.PerformZoom(Window); - else - { - if (!UndecoratedIsMaximized) - UndecoratedLastUnmaximizedFrame = Window.Frame; - Window.Zoom(Window); - } - } - - public void SetIcon(IWindowIconImpl icon) - { - //No-OP, see http://stackoverflow.com/a/7038671/2231814 - } - - public void ShowTaskbarIcon(bool value) - { - //No-OP, there is no such this as taskbar in OSX - } - - protected override NSWindowStyle GetStyle() - { - var windowStyle = NSWindowStyle.Borderless; - - if (IsDecorated) - windowStyle |= NSWindowStyle.Closable | NSWindowStyle.Miniaturizable | NSWindowStyle.Titled; - - if (IsResizable) - windowStyle |= NSWindowStyle.Resizable; - - return windowStyle; - } - - public void SetSystemDecorations(bool enabled) - { - IsDecorated = enabled; - UpdateStyle(); - } - - public void CanResize(bool value) - { - IsResizable = value; - UpdateStyle(); - } - - public void SetTitle(string title) => Window.Title = title; - - class ModalDisposable : IDisposable - { - readonly WindowImpl _impl; - readonly IntPtr _modalSession; - bool disposed; - - public ModalDisposable(WindowImpl impl, IntPtr modalSession) - { - _impl = impl; - _modalSession = modalSession; - } - - public void Continue() - { - if (disposed) - return; - - var response = (NSRunResponse)NSApplication.SharedApplication.RunModalSession(_modalSession); - if (response == NSRunResponse.Continues) - { - Dispatcher.UIThread.Post(Continue, DispatcherPriority.ContextIdle); - } - else - { - Logging.Logger.Log(Logging.LogEventLevel.Debug, "MonoMac", this, "Modal session ended"); - } - } - - public void Dispose() - { - Logging.Logger.Log(Logging.LogEventLevel.Debug, "MonoMac", this, "ModalDisposable disposed"); - _impl.Window.OrderOut(_impl.Window); - NSApplication.SharedApplication.EndModalSession(_modalSession); - disposed = true; - } - } - - public IDisposable ShowDialog() - { - var session = NSApplication.SharedApplication.BeginModalSession(Window); - var disposable = new ModalDisposable(this, session); - Dispatcher.UIThread.Post(disposable.Continue, DispatcherPriority.ContextIdle); - - return disposable; - } - } -}