diff --git a/.gitmodules b/.gitmodules
index 2d11fdfa9e1..032bc879cc5 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -4,3 +4,6 @@
[submodule "src/Markup/Avalonia.Markup.Xaml/XamlIl/xamlil.github"]
path = src/Markup/Avalonia.Markup.Xaml.Loader/xamlil.github
url = https://github.com/kekekeks/XamlX.git
+[submodule "nukebuild/il-repack"]
+ path = nukebuild/il-repack
+ url = https://github.com/Gillibald/il-repack
diff --git a/.nuke b/.nuke
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/.nuke/build.schema.json b/.nuke/build.schema.json
new file mode 100644
index 00000000000..5bbc3d69158
--- /dev/null
+++ b/.nuke/build.schema.json
@@ -0,0 +1,148 @@
+{
+ "$schema": "http://json-schema.org/draft-04/schema#",
+ "title": "Build Schema",
+ "$ref": "#/definitions/build",
+ "definitions": {
+ "build": {
+ "type": "object",
+ "properties": {
+ "Configuration": {
+ "type": "string",
+ "description": "configuration"
+ },
+ "Continue": {
+ "type": "boolean",
+ "description": "Indicates to continue a previously failed build attempt"
+ },
+ "ForceNugetVersion": {
+ "type": "string",
+ "description": "force-nuget-version"
+ },
+ "Help": {
+ "type": "boolean",
+ "description": "Shows the help text for this build assembly"
+ },
+ "Host": {
+ "type": "string",
+ "description": "Host for execution. Default is 'automatic'",
+ "enum": [
+ "AppVeyor",
+ "AzurePipelines",
+ "Bamboo",
+ "Bitbucket",
+ "Bitrise",
+ "GitHubActions",
+ "GitLab",
+ "Jenkins",
+ "Rider",
+ "SpaceAutomation",
+ "TeamCity",
+ "Terminal",
+ "TravisCI",
+ "VisualStudio",
+ "VSCode"
+ ]
+ },
+ "NoLogo": {
+ "type": "boolean",
+ "description": "Disables displaying the NUKE logo"
+ },
+ "Partition": {
+ "type": "string",
+ "description": "Partition to use on CI"
+ },
+ "Plan": {
+ "type": "boolean",
+ "description": "Shows the execution plan (HTML)"
+ },
+ "Profile": {
+ "type": "array",
+ "description": "Defines the profiles to load",
+ "items": {
+ "type": "string"
+ }
+ },
+ "Root": {
+ "type": "string",
+ "description": "Root directory during build execution"
+ },
+ "Skip": {
+ "type": "array",
+ "description": "List of targets to be skipped. Empty list skips all dependencies",
+ "items": {
+ "type": "string",
+ "enum": [
+ "CiAzureLinux",
+ "CiAzureOSX",
+ "CiAzureWindows",
+ "Clean",
+ "Compile",
+ "CompileHtmlPreviewer",
+ "CompileNative",
+ "CreateIntermediateNugetPackages",
+ "CreateNugetPackages",
+ "GenerateCppHeaders",
+ "Package",
+ "RunCoreLibsTests",
+ "RunDesignerTests",
+ "RunHtmlPreviewerTests",
+ "RunLeakTests",
+ "RunRenderTests",
+ "RunTests",
+ "ZipFiles"
+ ]
+ }
+ },
+ "SkipPreviewer": {
+ "type": "boolean",
+ "description": "skip-previewer"
+ },
+ "SkipTests": {
+ "type": "boolean",
+ "description": "skip-tests"
+ },
+ "Solution": {
+ "type": "string",
+ "description": "Path to a solution file that is automatically loaded. Default is Avalonia.sln"
+ },
+ "Target": {
+ "type": "array",
+ "description": "List of targets to be invoked. Default is '{default_target}'",
+ "items": {
+ "type": "string",
+ "enum": [
+ "CiAzureLinux",
+ "CiAzureOSX",
+ "CiAzureWindows",
+ "Clean",
+ "Compile",
+ "CompileHtmlPreviewer",
+ "CompileNative",
+ "CreateIntermediateNugetPackages",
+ "CreateNugetPackages",
+ "GenerateCppHeaders",
+ "Package",
+ "RunCoreLibsTests",
+ "RunDesignerTests",
+ "RunHtmlPreviewerTests",
+ "RunLeakTests",
+ "RunRenderTests",
+ "RunTests",
+ "ZipFiles"
+ ]
+ }
+ },
+ "Verbosity": {
+ "type": "string",
+ "description": "Logging verbosity during build execution. Default is 'Normal'",
+ "enum": [
+ "Minimal",
+ "Normal",
+ "Quiet",
+ "Verbose"
+ ]
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/.nuke/parameters.json b/.nuke/parameters.json
new file mode 100644
index 00000000000..42521bb7ddd
--- /dev/null
+++ b/.nuke/parameters.json
@@ -0,0 +1,4 @@
+{
+ "$schema": "./build.schema.json",
+ "Solution": ""
+}
\ No newline at end of file
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 497402fe4bb..c421ef657e5 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -12,9 +12,9 @@ jobs:
version: 3.1.414
- task: UseDotNet@2
- displayName: 'Use .NET Core SDK 6.0.100'
+ displayName: 'Use .NET Core SDK 6.0.200'
inputs:
- version: 6.0.100
+ version: 6.0.200
- task: CmdLine@2
displayName: 'Run Build'
@@ -43,9 +43,9 @@ jobs:
version: 3.1.414
- task: UseDotNet@2
- displayName: 'Use .NET Core SDK 6.0.100'
+ displayName: 'Use .NET Core SDK 6.0.200'
inputs:
- version: 6.0.100
+ version: 6.0.200
- task: CmdLine@2
displayName: 'Install Mono 5.18'
@@ -115,15 +115,15 @@ jobs:
version: 3.1.414
- task: UseDotNet@2
- displayName: 'Use .NET Core SDK 6.0.100'
+ displayName: 'Use .NET Core SDK 6.0.200'
inputs:
- version: 6.0.100
+ version: 6.0.200
- task: CmdLine@2
displayName: 'Install Nuke'
inputs:
script: |
- dotnet tool install --global Nuke.GlobalTool --version 0.24.0
+ dotnet tool install --global Nuke.GlobalTool --version 6.2.1
- task: CmdLine@2
displayName: 'Run Nuke'
diff --git a/build.cmd b/build.cmd
new file mode 100755
index 00000000000..b08cc590f4c
--- /dev/null
+++ b/build.cmd
@@ -0,0 +1,7 @@
+:; set -eo pipefail
+:; SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)
+:; ${SCRIPT_DIR}/build.sh "$@"
+:; exit $?
+
+@ECHO OFF
+powershell -ExecutionPolicy ByPass -NoProfile -File "%~dp0build.ps1" %*
diff --git a/build.ps1 b/build.ps1
index 985e8abcee9..997e5b423ff 100644
--- a/build.ps1
+++ b/build.ps1
@@ -1,13 +1,12 @@
[CmdletBinding()]
Param(
- #[switch]$CustomParam,
[Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)]
[string[]]$BuildArguments
)
-Write-Output "Windows PowerShell $($Host.Version)"
+Write-Output "PowerShell $($PSVersionTable.PSEdition) version $($PSVersionTable.PSVersion)"
-Set-StrictMode -Version 2.0; $ErrorActionPreference = "Stop"; $ConfirmPreference = "None"; trap { exit 1 }
+Set-StrictMode -Version 2.0; $ErrorActionPreference = "Stop"; $ConfirmPreference = "None"; trap { Write-Error $_ -ErrorAction Continue; exit 1 }
$PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent
###########################################################################
@@ -15,15 +14,15 @@ $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent
###########################################################################
$BuildProjectFile = "$PSScriptRoot\nukebuild\_build.csproj"
-$TempDirectory = "$PSScriptRoot\\.tmp"
+$TempDirectory = "$PSScriptRoot\\.nuke\temp"
$DotNetGlobalFile = "$PSScriptRoot\\global.json"
-$DotNetInstallUrl = "https://raw.githubusercontent.com/dotnet/cli/master/scripts/obtain/dotnet-install.ps1"
+$DotNetInstallUrl = "https://dot.net/v1/dotnet-install.ps1"
$DotNetChannel = "Current"
$env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE = 1
$env:DOTNET_CLI_TELEMETRY_OPTOUT = 1
-$env:NUGET_XMLDOC_MODE = "skip"
+$env:DOTNET_MULTILEVEL_LOOKUP = 0
###########################################################################
# EXECUTION
@@ -34,38 +33,37 @@ function ExecSafe([scriptblock] $cmd) {
if ($LASTEXITCODE) { exit $LASTEXITCODE }
}
-# If global.json exists, load expected version
-if (Test-Path $DotNetGlobalFile) {
- $DotNetGlobal = $(Get-Content $DotNetGlobalFile | Out-String | ConvertFrom-Json)
- if ($DotNetGlobal.PSObject.Properties["sdk"] -and $DotNetGlobal.sdk.PSObject.Properties["version"]) {
- $DotNetVersion = $DotNetGlobal.sdk.version
- }
-}
-
-# If dotnet is installed locally, and expected version is not set or installation matches the expected version
+# If dotnet CLI is installed globally and it matches requested version, use for execution
if ($null -ne (Get-Command "dotnet" -ErrorAction SilentlyContinue) -and `
- (!(Test-Path variable:DotNetVersion) -or $(& dotnet --version) -eq $DotNetVersion)) {
+ $(dotnet --version) -and $LASTEXITCODE -eq 0) {
$env:DOTNET_EXE = (Get-Command "dotnet").Path
}
else {
- $DotNetDirectory = "$TempDirectory\dotnet-win"
- $env:DOTNET_EXE = "$DotNetDirectory\dotnet.exe"
-
# Download install script
$DotNetInstallFile = "$TempDirectory\dotnet-install.ps1"
- mkdir -force $TempDirectory > $null
+ New-Item -ItemType Directory -Path $TempDirectory -Force | Out-Null
+ [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
(New-Object System.Net.WebClient).DownloadFile($DotNetInstallUrl, $DotNetInstallFile)
+ # If global.json exists, load expected version
+ if (Test-Path $DotNetGlobalFile) {
+ $DotNetGlobal = $(Get-Content $DotNetGlobalFile | Out-String | ConvertFrom-Json)
+ if ($DotNetGlobal.PSObject.Properties["sdk"] -and $DotNetGlobal.sdk.PSObject.Properties["version"]) {
+ $DotNetVersion = $DotNetGlobal.sdk.version
+ }
+ }
+
# Install by channel or version
+ $DotNetDirectory = "$TempDirectory\dotnet-win"
if (!(Test-Path variable:DotNetVersion)) {
- ExecSafe { & $DotNetInstallFile -InstallDir $DotNetDirectory -Channel $DotNetChannel -NoPath }
+ ExecSafe { & powershell $DotNetInstallFile -InstallDir $DotNetDirectory -Channel $DotNetChannel -NoPath }
} else {
- ExecSafe { & $DotNetInstallFile -InstallDir $DotNetDirectory -Version $DotNetVersion -NoPath }
+ ExecSafe { & powershell $DotNetInstallFile -InstallDir $DotNetDirectory -Version $DotNetVersion -NoPath }
}
-
- $env:PATH="$DotNetDirectory;$env:PATH"
+ $env:DOTNET_EXE = "$DotNetDirectory\dotnet.exe"
}
-Write-Output "Microsoft (R) .NET Core SDK version $(& $env:DOTNET_EXE --version)"
+Write-Output "Microsoft (R) .NET SDK version $(& $env:DOTNET_EXE --version)"
-ExecSafe { & $env:DOTNET_EXE run --project $BuildProjectFile -- $BuildArguments }
+ExecSafe { & $env:DOTNET_EXE build $BuildProjectFile /nodeReuse:false /p:UseSharedCompilation=false -nologo -clp:NoSummary --verbosity quiet }
+ExecSafe { & $env:DOTNET_EXE run --project $BuildProjectFile --no-build -- $BuildArguments }
diff --git a/build.sh b/build.sh
index 9532b4fbe01..76919a53517 100755
--- a/build.sh
+++ b/build.sh
@@ -1,16 +1,6 @@
#!/usr/bin/env bash
-echo $(bash --version 2>&1 | head -n 1)
-
-#CUSTOMPARAM=0
-BUILD_ARGUMENTS=()
-for i in "$@"; do
- case $(echo $1 | awk '{print tolower($0)}') in
- # -custom-param) CUSTOMPARAM=1;;
- *) BUILD_ARGUMENTS+=("$1") ;;
- esac
- shift
-done
+bash --version 2>&1 | head -n 1
set -eo pipefail
SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)
@@ -20,11 +10,53 @@ SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)
###########################################################################
BUILD_PROJECT_FILE="$SCRIPT_DIR/nukebuild/_build.csproj"
+TEMP_DIRECTORY="$SCRIPT_DIR//.nuke/temp"
+
+DOTNET_GLOBAL_FILE="$SCRIPT_DIR//global.json"
+DOTNET_INSTALL_URL="https://dot.net/v1/dotnet-install.sh"
+DOTNET_CHANNEL="Current"
export DOTNET_CLI_TELEMETRY_OPTOUT=1
export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1
-export NUGET_XMLDOC_MODE="skip"
+export DOTNET_MULTILEVEL_LOOKUP=0
-dotnet --info
+###########################################################################
+# EXECUTION
+###########################################################################
-dotnet run --project "$BUILD_PROJECT_FILE" -- ${BUILD_ARGUMENTS[@]}
+function FirstJsonValue {
+ perl -nle 'print $1 if m{"'"$1"'": "([^"]+)",?}' <<< "${@:2}"
+}
+
+# If dotnet CLI is installed globally and it matches requested version, use for execution
+if [ -x "$(command -v dotnet)" ] && dotnet --version &>/dev/null; then
+ export DOTNET_EXE="$(command -v dotnet)"
+else
+ # Download install script
+ DOTNET_INSTALL_FILE="$TEMP_DIRECTORY/dotnet-install.sh"
+ mkdir -p "$TEMP_DIRECTORY"
+ curl -Lsfo "$DOTNET_INSTALL_FILE" "$DOTNET_INSTALL_URL"
+ chmod +x "$DOTNET_INSTALL_FILE"
+
+ # If global.json exists, load expected version
+ if [[ -f "$DOTNET_GLOBAL_FILE" ]]; then
+ DOTNET_VERSION=$(FirstJsonValue "version" "$(cat "$DOTNET_GLOBAL_FILE")")
+ if [[ "$DOTNET_VERSION" == "" ]]; then
+ unset DOTNET_VERSION
+ fi
+ fi
+
+ # Install by channel or version
+ DOTNET_DIRECTORY="$TEMP_DIRECTORY/dotnet-unix"
+ if [[ -z ${DOTNET_VERSION+x} ]]; then
+ "$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --channel "$DOTNET_CHANNEL" --no-path
+ else
+ "$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --version "$DOTNET_VERSION" --no-path
+ fi
+ export DOTNET_EXE="$DOTNET_DIRECTORY/dotnet"
+fi
+
+echo "Microsoft (R) .NET SDK version $("$DOTNET_EXE" --version)"
+
+"$DOTNET_EXE" build "$BUILD_PROJECT_FILE" /nodeReuse:false /p:UseSharedCompilation=false -nologo -clp:NoSummary --verbosity quiet
+"$DOTNET_EXE" run --project "$BUILD_PROJECT_FILE" --no-build -- "$@"
diff --git a/build/JetBrains.dotMemoryUnit.props b/build/JetBrains.dotMemoryUnit.props
index 1713dead688..5d74d474cf3 100644
--- a/build/JetBrains.dotMemoryUnit.props
+++ b/build/JetBrains.dotMemoryUnit.props
@@ -1,5 +1,5 @@
-
+
diff --git a/build/SharedVersion.props b/build/SharedVersion.props
index af0d532330b..50a31c9a867 100644
--- a/build/SharedVersion.props
+++ b/build/SharedVersion.props
@@ -2,7 +2,7 @@
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
Avalonia
- 0.10.18
+ 0.10.19
Copyright 2022 © The AvaloniaUI Project
https://avaloniaui.net
https://github.com/AvaloniaUI/Avalonia/
diff --git a/global.json b/global.json
index bbafc1a317f..379330620d2 100644
--- a/global.json
+++ b/global.json
@@ -1,7 +1,7 @@
{
"sdk": {
- "version": "6.0.100",
- "rollForward": "latestFeature"
+ "version": "6.0.200",
+ "rollForward": "disable"
},
"msbuild-sdks": {
"Microsoft.Build.Traversal": "1.0.43",
diff --git a/native/Avalonia.Native/src/OSX/AvnWindow.mm b/native/Avalonia.Native/src/OSX/AvnWindow.mm
index 03bbed819a3..a545791aa84 100644
--- a/native/Avalonia.Native/src/OSX/AvnWindow.mm
+++ b/native/Avalonia.Native/src/OSX/AvnWindow.mm
@@ -43,7 +43,7 @@ -(void) setIsExtended:(bool)value;
-(bool) isDialog
{
- return _parent->IsDialog();
+ return _parent->IsModal();
}
-(double) getExtendedTitleBarHeight
@@ -170,9 +170,7 @@ -(CLASS_NAME*_Nonnull) initWithParent: (WindowBaseImpl*_Nonnull) parent content
_closed = false;
_isEnabled = true;
- [self backingScaleFactor];
[self setOpaque:NO];
- [self setBackgroundColor: [NSColor clearColor]];
_isExtended = false;
_isTransitioningToFullScreen = false;
@@ -224,9 +222,22 @@ - (void)windowWillClose:(NSNotification *_Nonnull)notification
}
}
+// From chromium:
+//
+// > The delegate or the window class should implement this method so that
+// > -[NSWindow isZoomed] can be then determined by whether or not the current
+// > window frame is equal to the zoomed frame.
+//
+// If we don't implement this, then isZoomed always returns true for a non-
+// resizable window ¯\_(ツ)_/¯
+- (NSRect)windowWillUseStandardFrame:(NSWindow*)window
+ defaultFrame:(NSRect)newFrame {
+ return newFrame;
+}
+
-(BOOL)canBecomeKeyWindow
{
- if(_canBecomeKeyWindow)
+ if(_canBecomeKeyWindow && !_closed)
{
// If the window has a child window being shown as a dialog then don't allow it to become the key window.
auto parent = dynamic_cast(_parent.getRaw());
@@ -262,10 +273,6 @@ -(bool)shouldTryToHandleEvents
-(void) setEnabled:(bool)enable
{
_isEnabled = enable;
-
- [[self standardWindowButton:NSWindowCloseButton] setEnabled:enable];
- [[self standardWindowButton:NSWindowMiniaturizeButton] setEnabled:enable];
- [[self standardWindowButton:NSWindowZoomButton] setEnabled:enable];
}
-(void)becomeKeyWindow
@@ -282,11 +289,16 @@ -(void)becomeKeyWindow
- (void)windowDidBecomeKey:(NSNotification *_Nonnull)notification
{
+ if (_parent == nullptr)
+ return;
+
_parent->BringToFront();
dispatch_async(dispatch_get_main_queue(), ^{
@try {
- [self invalidateShadow];
+ [self invalidateShadow];
+ if (self->_parent != nullptr)
+ self->_parent->BringToFront();
}
@finally{
}
@@ -381,10 +393,10 @@ - (void)windowDidEnterFullScreen:(NSNotification *_Nonnull)notification
- (BOOL)windowShouldZoom:(NSWindow *_Nonnull)window toFrame:(NSRect)newFrame
{
- return true;
+ return _parent->CanZoom();
}
--(void)resignKeyWindow
+-(void)windowDidResignKey:(NSNotification *)notification
{
if(_parent)
_parent->BaseEvents->Deactivated();
@@ -392,8 +404,6 @@ -(void)resignKeyWindow
[self showAppMenuOnly];
[self invalidateShadow];
-
- [super resignKeyWindow];
}
- (void)windowDidMove:(NSNotification *_Nonnull)notification
diff --git a/native/Avalonia.Native/src/OSX/PopupImpl.mm b/native/Avalonia.Native/src/OSX/PopupImpl.mm
index b29b44b6cc9..f5b9cc715ec 100644
--- a/native/Avalonia.Native/src/OSX/PopupImpl.mm
+++ b/native/Avalonia.Native/src/OSX/PopupImpl.mm
@@ -28,7 +28,7 @@
[Window setLevel:NSPopUpMenuWindowLevel];
}
protected:
- virtual NSWindowStyleMask GetStyle() override
+ virtual NSWindowStyleMask CalculateStyleMask() override
{
return NSWindowStyleMaskBorderless;
}
diff --git a/native/Avalonia.Native/src/OSX/WindowBaseImpl.h b/native/Avalonia.Native/src/OSX/WindowBaseImpl.h
index 2baf3b09b5f..30a06b409eb 100644
--- a/native/Avalonia.Native/src/OSX/WindowBaseImpl.h
+++ b/native/Avalonia.Native/src/OSX/WindowBaseImpl.h
@@ -90,22 +90,23 @@ BEGIN_INTERFACE_MAP()
virtual HRESULT CreateNativeControlHost(IAvnNativeControlHost **retOut) override;
- virtual HRESULT SetBlurEnabled(bool enable) override;
+ virtual HRESULT SetTransparencyMode(AvnWindowTransparencyMode mode) override;
virtual HRESULT BeginDragAndDropOperation(AvnDragDropEffects effects, AvnPoint point,
IAvnClipboard *clipboard, IAvnDndResultCallback *cb,
void *sourceHandle) override;
- virtual bool IsDialog();
+ virtual bool IsModal();
id GetWindowProtocol ();
virtual void BringToFront ();
+ virtual bool CanZoom() { return false; }
+
protected:
- virtual NSWindowStyleMask GetStyle();
-
- void UpdateStyle();
+ virtual NSWindowStyleMask CalculateStyleMask() = 0;
+ virtual void UpdateStyle();
private:
void CreateNSWindow (bool isDialog);
diff --git a/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm b/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm
index 7ce8a3b4b55..84469e0c30b 100644
--- a/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm
+++ b/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm
@@ -34,18 +34,14 @@
lastSize = NSSize { 100, 100 };
lastMaxSize = NSSize { CGFLOAT_MAX, CGFLOAT_MAX};
lastMinSize = NSSize { 0, 0 };
-
lastMenu = nullptr;
CreateNSWindow(usePanel);
[Window setContentView:StandardContainer];
- [Window setStyleMask:NSWindowStyleMaskBorderless];
[Window setBackingType:NSBackingStoreBuffered];
-
[Window setContentMinSize:lastMinSize];
[Window setContentMaxSize:lastMaxSize];
-
[Window setOpaque:false];
}
@@ -488,10 +484,11 @@
return S_OK;
}
-HRESULT WindowBaseImpl::SetBlurEnabled(bool enable) {
+HRESULT WindowBaseImpl::SetTransparencyMode(AvnWindowTransparencyMode mode) {
START_COM_CALL;
- [StandardContainer ShowBlur:enable];
+ [Window setBackgroundColor: (mode != Transparent ? [NSColor windowBackgroundColor] : [NSColor clearColor])];
+ [StandardContainer ShowBlur: mode == Blur];
return S_OK;
}
@@ -540,16 +537,12 @@
return S_OK;
}
-bool WindowBaseImpl::IsDialog() {
+bool WindowBaseImpl::IsModal() {
return false;
}
-NSWindowStyleMask WindowBaseImpl::GetStyle() {
- return NSWindowStyleMaskBorderless;
-}
-
void WindowBaseImpl::UpdateStyle() {
- [Window setStyleMask:GetStyle()];
+ [Window setStyleMask:CalculateStyleMask()];
}
void WindowBaseImpl::CleanNSWindow() {
@@ -560,21 +553,12 @@
}
}
-void WindowBaseImpl::CreateNSWindow(bool isDialog) {
- if (isDialog) {
- if (![Window isKindOfClass:[AvnPanel class]]) {
- CleanNSWindow();
-
- Window = [[AvnPanel alloc] initWithParent:this contentRect:NSRect{0, 0, lastSize} styleMask:GetStyle()];
-
- [Window setHidesOnDeactivate:false];
- }
+void WindowBaseImpl::CreateNSWindow(bool usePanel) {
+ if (usePanel) {
+ Window = [[AvnPanel alloc] initWithParent:this contentRect:NSRect{0, 0, lastSize} styleMask:NSWindowStyleMaskBorderless];
+ [Window setHidesOnDeactivate:false];
} else {
- if (![Window isKindOfClass:[AvnWindow class]]) {
- CleanNSWindow();
-
- Window = [[AvnWindow alloc] initWithParent:this contentRect:NSRect{0, 0, lastSize} styleMask:GetStyle()];
- }
+ Window = [[AvnWindow alloc] initWithParent:this contentRect:NSRect{0, 0, lastSize} styleMask:NSWindowStyleMaskBorderless];
}
}
diff --git a/native/Avalonia.Native/src/OSX/WindowImpl.h b/native/Avalonia.Native/src/OSX/WindowImpl.h
index b4b1d4e70b8..5140124a17f 100644
--- a/native/Avalonia.Native/src/OSX/WindowImpl.h
+++ b/native/Avalonia.Native/src/OSX/WindowImpl.h
@@ -23,7 +23,7 @@ class WindowImpl : public virtual WindowBaseImpl, public virtual IAvnWindow, pub
NSRect _preZoomSize;
bool _transitioningWindowState;
bool _isClientAreaExtended;
- bool _isDialog;
+ bool _isModal;
WindowImpl* _parent;
std::list _children;
AvnExtendClientAreaChromeHints _extendClientHints;
@@ -41,8 +41,6 @@ BEGIN_INTERFACE_MAP()
WindowImpl(IAvnWindowEvents* events, IAvnGlContext* gl);
- void HideOrShowTrafficLights ();
-
virtual HRESULT Show (bool activate, bool isDialog) override;
virtual HRESULT SetEnabled (bool enable) override;
@@ -91,16 +89,22 @@ BEGIN_INTERFACE_MAP()
virtual HRESULT SetWindowState (AvnWindowState state) override;
- virtual bool IsDialog() override;
+ virtual bool IsModal() override;
+
+ bool IsOwned();
virtual void BringToFront () override;
bool CanBecomeKeyWindow ();
+ bool CanZoom() override { return _isEnabled && _canResize; }
+
protected:
- virtual NSWindowStyleMask GetStyle() override;
+ virtual NSWindowStyleMask CalculateStyleMask() override;
+ void UpdateStyle () override;
private:
+ void ZOrderChildWindows();
void OnInitialiseNSWindow();
NSString *_lastTitle;
};
diff --git a/native/Avalonia.Native/src/OSX/WindowImpl.mm b/native/Avalonia.Native/src/OSX/WindowImpl.mm
index a6b14252094..bab000f4e4b 100644
--- a/native/Avalonia.Native/src/OSX/WindowImpl.mm
+++ b/native/Avalonia.Native/src/OSX/WindowImpl.mm
@@ -29,19 +29,6 @@
OnInitialiseNSWindow();
}
-void WindowImpl::HideOrShowTrafficLights() {
- if (Window == nil) {
- return;
- }
-
- bool wantsChrome = (_extendClientHints & AvnSystemChrome) || (_extendClientHints & AvnPreferSystemChrome);
- bool hasTrafficLights = _isClientAreaExtended ? wantsChrome : _decorations == SystemDecorationsFull;
-
- [[Window standardWindowButton:NSWindowCloseButton] setHidden:!hasTrafficLights];
- [[Window standardWindowButton:NSWindowMiniaturizeButton] setHidden:!hasTrafficLights];
- [[Window standardWindowButton:NSWindowZoomButton] setHidden:!hasTrafficLights];
-}
-
void WindowImpl::OnInitialiseNSWindow(){
[GetWindowProtocol() setCanBecomeKeyWindow:true];
@@ -62,12 +49,10 @@
START_COM_CALL;
@autoreleasepool {
- _isDialog = isDialog;
+ _isModal = isDialog;
WindowBaseImpl::Show(activate, isDialog);
-
- HideOrShowTrafficLights();
-
+ GetWindowState(&_actualWindowState);
return SetWindowState(_lastWindowState);
}
}
@@ -90,13 +75,13 @@
if(_parent != nullptr)
{
_parent->_children.remove(this);
-
- _parent->BringToFront();
}
auto cparent = dynamic_cast(parent);
_parent = cparent;
+
+ _isModal = _parent != nullptr;
if(_parent != nullptr && Window != nullptr){
// If one tries to show a child window with a minimized parent window, then the parent window will be
@@ -122,7 +107,7 @@
{
if ([Window isVisible] && ![Window isMiniaturized])
{
- if(IsDialog())
+ if(IsModal())
{
Activate();
}
@@ -133,9 +118,18 @@
}
[Window invalidateShadow];
+ ZOrderChildWindows();
+ }
+}
+
+void WindowImpl::ZOrderChildWindows()
+{
+ for(auto iterator = _children.begin(); iterator != _children.end(); iterator++)
+ {
+ auto window = (*iterator)->Window;
- for(auto iterator = _children.begin(); iterator != _children.end(); iterator++)
- {
+ // #9565: Only bring window to front if it's on the currently active space
+ if ([window isOnActiveSpace]) {
(*iterator)->BringToFront();
}
}
@@ -145,7 +139,7 @@
{
for(auto iterator = _children.begin(); iterator != _children.end(); iterator++)
{
- if((*iterator)->IsDialog())
+ if((*iterator)->IsModal())
{
return false;
}
@@ -156,10 +150,15 @@
void WindowImpl::StartStateTransition() {
_transitioningWindowState = true;
+ UpdateStyle();
}
void WindowImpl::EndStateTransition() {
_transitioningWindowState = false;
+ UpdateStyle();
+
+ // Ensure correct order of child windows after fullscreen transition.
+ ZOrderChildWindows();
}
SystemDecorations WindowImpl::Decorations() {
@@ -217,16 +216,12 @@
}
void WindowImpl::DoZoom() {
- switch (_decorations) {
- case SystemDecorationsNone:
- case SystemDecorationsBorderOnly:
- [Window setFrame:[Window screen].visibleFrame display:true];
- break;
-
-
- case SystemDecorationsFull:
- [Window performZoom:Window];
- break;
+ if (_decorations == SystemDecorationsNone ||
+ _decorations == SystemDecorationsBorderOnly ||
+ _canResize == false) {
+ [Window setFrame:[Window screen].visibleFrame display:true];
+ } else {
+ [Window performZoom:Window];
}
}
@@ -253,8 +248,6 @@
UpdateStyle();
- HideOrShowTrafficLights();
-
switch (_decorations) {
case SystemDecorationsNone:
[Window setHasShadow:NO];
@@ -282,10 +275,13 @@
case SystemDecorationsFull:
[Window setHasShadow:YES];
- [Window setTitleVisibility:NSWindowTitleVisible];
- [Window setTitlebarAppearsTransparent:NO];
[Window setTitle:_lastTitle];
+ if (!_isClientAreaExtended) {
+ [Window setTitleVisibility:NSWindowTitleVisible];
+ [Window setTitlebarAppearsTransparent:NO];
+ }
+
if (currentWindowState == Maximized) {
auto newFrame = [Window contentRectForFrameRect:[Window frame]].size;
@@ -411,9 +407,6 @@
}
[GetWindowProtocol() setIsExtended:enable];
-
- HideOrShowTrafficLights();
-
UpdateStyle();
}
@@ -561,18 +554,24 @@
}
}
-bool WindowImpl::IsDialog() {
- return _isDialog;
+bool WindowImpl::IsModal() {
+ return _isModal;
}
-NSWindowStyleMask WindowImpl::GetStyle() {
- unsigned long s = NSWindowStyleMaskBorderless;
-
- if(_actualWindowState == FullScreen)
- {
- s |= NSWindowStyleMaskFullScreen;
- }
+bool WindowImpl::IsOwned() {
+ return _parent != nullptr;
+}
+NSWindowStyleMask WindowImpl::CalculateStyleMask() {
+ // Use the current style mask and only clear the flags we're going to be modifying.
+ unsigned long s = [Window styleMask] &
+ ~(NSWindowStyleMaskFullSizeContentView |
+ NSWindowStyleMaskTitled |
+ NSWindowStyleMaskClosable |
+ NSWindowStyleMaskResizable |
+ NSWindowStyleMaskMiniaturizable |
+ NSWindowStyleMaskTexturedBackground);
+
switch (_decorations) {
case SystemDecorationsNone:
s = s | NSWindowStyleMaskFullSizeContentView;
@@ -585,13 +584,13 @@
case SystemDecorationsFull:
s = s | NSWindowStyleMaskTitled | NSWindowStyleMaskClosable;
- if (_canResize && _isEnabled) {
+ if ((_canResize && _isEnabled) || _transitioningWindowState) {
s = s | NSWindowStyleMaskResizable;
}
break;
}
- if (!IsDialog()) {
+ if (!IsOwned()) {
s |= NSWindowStyleMaskMiniaturizable;
}
@@ -600,3 +599,26 @@
}
return s;
}
+
+void WindowImpl::UpdateStyle() {
+ WindowBaseImpl::UpdateStyle();
+
+ if (Window == nil) {
+ return;
+ }
+
+ bool wantsChrome = (_extendClientHints & AvnSystemChrome) || (_extendClientHints & AvnPreferSystemChrome);
+ bool hasTrafficLights = (_decorations == SystemDecorationsFull) &&
+ (_isClientAreaExtended ? wantsChrome : true);
+
+ NSButton* closeButton = [Window standardWindowButton:NSWindowCloseButton];
+ NSButton* miniaturizeButton = [Window standardWindowButton:NSWindowMiniaturizeButton];
+ NSButton* zoomButton = [Window standardWindowButton:NSWindowZoomButton];
+
+ [closeButton setHidden:!hasTrafficLights];
+ [closeButton setEnabled:_isEnabled];
+ [miniaturizeButton setHidden:!hasTrafficLights];
+ [miniaturizeButton setEnabled:_isEnabled];
+ [zoomButton setHidden:!hasTrafficLights];
+ [zoomButton setEnabled:CanZoom()];
+}
diff --git a/native/Avalonia.Native/src/OSX/menu.h b/native/Avalonia.Native/src/OSX/menu.h
index ce46ac11e08..405938318c3 100644
--- a/native/Avalonia.Native/src/OSX/menu.h
+++ b/native/Avalonia.Native/src/OSX/menu.h
@@ -59,11 +59,20 @@ class AvnAppMenuItem : public ComSingleObject
void RaiseOnClicked();
};
+class AvnAppMenu;
+
+@interface AvnMenuDelegate : NSObject
+- (id) initWithParent: (AvnAppMenu*) parent;
+- (void) parentDestroyed;
+@end
+
+
class AvnAppMenu : public ComSingleObject
{
private:
AvnMenu* _native;
ComPtr _baseEvents;
+ AvnMenuDelegate* _delegate;
public:
FORWARD_IUNKNOWN()
@@ -83,12 +92,10 @@ class AvnAppMenu : public ComSingleObject
virtual HRESULT SetTitle (char* utf8String) override;
virtual HRESULT Clear () override;
+ virtual ~AvnAppMenu() override;
};
-@interface AvnMenuDelegate : NSObject
-- (id) initWithParent: (AvnAppMenu*) parent;
-@end
#endif
diff --git a/native/Avalonia.Native/src/OSX/menu.mm b/native/Avalonia.Native/src/OSX/menu.mm
index b05588a441e..cd1871de21f 100644
--- a/native/Avalonia.Native/src/OSX/menu.mm
+++ b/native/Avalonia.Native/src/OSX/menu.mm
@@ -292,8 +292,13 @@ - (void)didSelectItem:(nullable id)sender
AvnAppMenu::AvnAppMenu(IAvnMenuEvents* events)
{
_baseEvents = events;
- id del = [[AvnMenuDelegate alloc] initWithParent: this];
- _native = [[AvnMenu alloc] initWithDelegate: del];
+ _delegate = [[AvnMenuDelegate alloc] initWithParent: this];
+ _native = [[AvnMenu alloc] initWithDelegate: _delegate];
+}
+
+AvnAppMenu::~AvnAppMenu()
+{
+ [_delegate parentDestroyed];
}
@@ -394,7 +399,7 @@ - (void)didSelectItem:(nullable id)sender
@implementation AvnMenuDelegate
{
- ComPtr _parent;
+ AvnAppMenu* _parent;
}
- (id) initWithParent:(AvnAppMenu *)parent
{
@@ -402,6 +407,12 @@ - (id) initWithParent:(AvnAppMenu *)parent
_parent = parent;
return self;
}
+
+- (void) parentDestroyed
+{
+ _parent = nullptr;
+}
+
- (BOOL)menu:(NSMenu *)menu updateItem:(NSMenuItem *)item atIndex:(NSInteger)index shouldCancel:(BOOL)shouldCancel
{
if(shouldCancel)
@@ -416,17 +427,20 @@ - (NSInteger)numberOfItemsInMenu:(NSMenu *)menu
- (void)menuNeedsUpdate:(NSMenu *)menu
{
- _parent->RaiseNeedsUpdate();
+ if(_parent)
+ _parent->RaiseNeedsUpdate();
}
- (void)menuWillOpen:(NSMenu *)menu
{
- _parent->RaiseOpening();
+ if(_parent)
+ _parent->RaiseOpening();
}
- (void)menuDidClose:(NSMenu *)menu
{
- _parent->RaiseClosed();
+ if(_parent)
+ _parent->RaiseClosed();
}
@end
diff --git a/nukebuild/Build.cs b/nukebuild/Build.cs
index ddcbddaab31..b20c8d85e29 100644
--- a/nukebuild/Build.cs
+++ b/nukebuild/Build.cs
@@ -16,7 +16,6 @@
using Nuke.Common.Tools.Npm;
using Nuke.Common.Utilities;
using Nuke.Common.Utilities.Collections;
-using Pharmacist.Core;
using static Nuke.Common.EnvironmentInfo;
using static Nuke.Common.IO.FileSystemTasks;
using static Nuke.Common.IO.PathConstruction;
@@ -24,7 +23,7 @@
using static Nuke.Common.Tools.DotNet.DotNetTasks;
using static Nuke.Common.Tools.Xunit.XunitTasks;
using static Nuke.Common.Tools.VSWhere.VSWhereTasks;
-using System.IO.Compression;
+using MicroCom.CodeGenerator;
/*
Before editing this file, install support plugin for your IDE,
@@ -33,30 +32,14 @@ running and debugging a particular target (optionally without deps) would be way
VSCode - https://marketplace.visualstudio.com/items?itemName=nuke.support
*/
+using JetBrains.Annotations;
+using Nuke.Common.Tools.DotNet;
+// ReSharper disable ReturnValueOfPureMethodIsNotUsed
partial class Build : NukeBuild
{
[Solution("Avalonia.sln")] readonly Solution Solution;
- static Lazy MsBuildExe = new Lazy(() =>
- {
- if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
- return null;
-
- var msBuildDirectory = VSWhere("-latest -nologo -property installationPath -format value -prerelease").FirstOrDefault().Text;
-
- if (!string.IsNullOrWhiteSpace(msBuildDirectory))
- {
- string msBuildExe = Path.Combine(msBuildDirectory, @"MSBuild\Current\Bin\MSBuild.exe");
- if (!System.IO.File.Exists(msBuildExe))
- msBuildExe = Path.Combine(msBuildDirectory, @"MSBuild\15.0\Bin\MSBuild.exe");
-
- return msBuildExe;
- }
-
- return null;
- }, false);
-
BuildParameters Parameters { get; set; }
protected override void OnBuildInitialized()
{
@@ -89,26 +72,30 @@ void ExecWait(string preamble, string command, string args)
Console.WriteLine(preamble);
Process.Start(new ProcessStartInfo(command, args) {UseShellExecute = false}).WaitForExit();
}
- ExecWait("dotnet version:", "dotnet", "--version");
+ ExecWait("dotnet version:", "dotnet", "--info");
+ ExecWait("dotnet workloads:", "dotnet", "workload list");
+ Information("Processor count: " + Environment.ProcessorCount);
+ Information("Available RAM: " + GC.GetGCMemoryInfo().TotalAvailableMemoryBytes / 0x100000 + "MB");
}
- IReadOnlyCollection