diff --git a/Avalonia.sln.DotSettings b/Avalonia.sln.DotSettings
index 2c0a6b9dc8..b0692905e7 100644
--- a/Avalonia.sln.DotSettings
+++ b/Avalonia.sln.DotSettings
@@ -1,5 +1,4 @@
- True
ExplicitlyExcluded
ExplicitlyExcluded
ExplicitlyExcluded
@@ -39,4 +38,4 @@
<Policy Inspect="False" Prefix="" Suffix="" Style="AaBb" />
True
True
- True
\ No newline at end of file
+ True
diff --git a/Documentation/build.md b/Documentation/build.md
index a7d68eb599..9f5436e68e 100644
--- a/Documentation/build.md
+++ b/Documentation/build.md
@@ -6,6 +6,7 @@ Avalonia requires at least Visual Studio 2019 and .NET Core SDK 3.1 to build on
```
git clone https://github.com/AvaloniaUI/Avalonia.git
+cd Avalonia
git submodule update --init
```
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index fbd8507193..9fa79ec5ba 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -1,21 +1,28 @@
+variables:
+ MSBuildEnableWorkloadResolver: 'false'
+
jobs:
- job: Linux
pool:
- vmImage: 'ubuntu-16.04'
+ vmImage: 'ubuntu-20.04'
steps:
- - task: CmdLine@2
- displayName: 'Install Nuke'
+ - task: UseDotNet@2
+ displayName: 'Use .NET Core SDK 3.1.414'
inputs:
- script: |
- dotnet tool install --global Nuke.GlobalTool --version 0.24.0
+ version: 3.1.414
+
+ - task: UseDotNet@2
+ displayName: 'Use .NET Core SDK 6.0.100'
+ inputs:
+ version: 6.0.100
+
- task: CmdLine@2
- displayName: 'Run Nuke'
+ displayName: 'Run Build'
inputs:
script: |
- export PATH="$PATH:$HOME/.dotnet/tools"
dotnet --info
printenv
- nuke --target CiAzureLinux --configuration=Release
+ ./build.sh --target CiAzureLinux --configuration=Release
- task: PublishTestResults@2
inputs:
@@ -23,6 +30,7 @@ jobs:
testResultsFiles: '$(Build.SourcesDirectory)/artifacts/test-results/*.trx'
condition: not(canceled())
+
- job: macOS
variables:
SolutionDir: '$(Build.SourcesDirectory)'
@@ -30,10 +38,15 @@ jobs:
vmImage: 'macOS-10.15'
steps:
- task: UseDotNet@2
- displayName: 'Use .NET Core SDK 3.1.401'
+ displayName: 'Use .NET Core SDK 3.1.414'
inputs:
- version: 3.1.401
+ version: 3.1.414
+ - task: UseDotNet@2
+ displayName: 'Use .NET Core SDK 6.0.100'
+ inputs:
+ version: 6.0.100
+
- task: CmdLine@2
displayName: 'Install Mono 5.18'
inputs:
@@ -45,7 +58,8 @@ jobs:
displayName: 'Generate avalonia-native'
inputs:
script: |
- cd src/tools/MicroComGenerator; dotnet run -i ../../Avalonia.Native/avn.idl --cpp ../../../native/Avalonia.Native/inc/avalonia-native.h
+ export PATH="`pwd`/sdk:$PATH"
+ cd src/tools/MicroComGenerator; dotnet run -f net6.0 -i ../../Avalonia.Native/avn.idl --cpp ../../../native/Avalonia.Native/inc/avalonia-native.h
- task: Xcode@5
inputs:
@@ -58,13 +72,7 @@ jobs:
args: '-derivedDataPath ./'
- task: CmdLine@2
- displayName: 'Install Nuke'
- inputs:
- script: |
- dotnet tool install --global Nuke.GlobalTool --version 0.24.0
-
- - task: CmdLine@2
- displayName: 'Run Nuke'
+ displayName: 'Run Build'
inputs:
script: |
export COREHOST_TRACE=0
@@ -72,10 +80,8 @@ jobs:
export DOTNET_CLI_TELEMETRY_OPTOUT=1
which dotnet
dotnet --info
- export PATH="$PATH:$HOME/.dotnet/tools"
- dotnet --info
printenv
- nuke --target CiAzureOSX --configuration Release --skip-previewer
+ ./build.sh --target CiAzureOSX --configuration Release --skip-previewer
- task: PublishTestResults@2
inputs:
@@ -102,9 +108,14 @@ jobs:
SolutionDir: '$(Build.SourcesDirectory)'
steps:
- task: UseDotNet@2
- displayName: 'Use .NET Core SDK 3.1.401'
+ displayName: 'Use .NET Core SDK 3.1.414'
+ inputs:
+ version: 3.1.414
+
+ - task: UseDotNet@2
+ displayName: 'Use .NET Core SDK 6.0.100'
inputs:
- version: 3.1.401
+ version: 6.0.100
- task: CmdLine@2
displayName: 'Install Nuke'
diff --git a/build.sh b/build.sh
index bd162fab9b..9532b4fbe0 100755
--- a/build.sh
+++ b/build.sh
@@ -20,55 +20,11 @@ SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)
###########################################################################
BUILD_PROJECT_FILE="$SCRIPT_DIR/nukebuild/_build.csproj"
-TEMP_DIRECTORY="$SCRIPT_DIR//.tmp"
-
-DOTNET_GLOBAL_FILE="$SCRIPT_DIR//global.json"
-DOTNET_INSTALL_URL="https://raw.githubusercontent.com/dotnet/cli/master/scripts/obtain/dotnet-install.sh"
-DOTNET_CHANNEL="Current"
export DOTNET_CLI_TELEMETRY_OPTOUT=1
export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1
export NUGET_XMLDOC_MODE="skip"
-###########################################################################
-# EXECUTION
-###########################################################################
-
-function FirstJsonValue {
- perl -nle 'print $1 if m{"'$1'": "([^"\-]+)",?}' <<< ${@:2}
-}
-
-# 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
-
-# If dotnet is installed locally, and expected version is not set or installation matches the expected version
-if [[ -x "$(command -v dotnet)" && (-z ${DOTNET_VERSION+x} || $(dotnet --version) == "$DOTNET_VERSION") || "$SKIP_DOTNET_DOWNLOAD" == "1" ]]; then
- export DOTNET_EXE="$(command -v dotnet)"
-else
- DOTNET_DIRECTORY="$TEMP_DIRECTORY/dotnet-unix"
- export DOTNET_EXE="$DOTNET_DIRECTORY/dotnet"
-
- # Download install script
- DOTNET_INSTALL_FILE="$TEMP_DIRECTORY/dotnet-install.sh"
- mkdir -p "$TEMP_DIRECTORY"
- curl -Lsfo "$DOTNET_INSTALL_FILE" "$DOTNET_INSTALL_URL"
- chmod +x "$DOTNET_INSTALL_FILE"
-
- # Install by channel or version
- if [ -z ${DOTNET_VERSION+x} ]; then
- "$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --channel "$DOTNET_CHANNEL" --no-path
- else
- "$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --version "$DOTNET_VERSION" --no-path
- fi
-fi
-
-export PATH=$DOTNET_DIRECTORY:$PATH
-
-echo "Microsoft (R) .NET Core SDK version $("$DOTNET_EXE" --version)"
+dotnet --info
-"$DOTNET_EXE" run --project "$BUILD_PROJECT_FILE" -- ${BUILD_ARGUMENTS[@]}
+dotnet run --project "$BUILD_PROJECT_FILE" -- ${BUILD_ARGUMENTS[@]}
diff --git a/build/HarfBuzzSharp.props b/build/HarfBuzzSharp.props
index 13419eb173..16aab3911e 100644
--- a/build/HarfBuzzSharp.props
+++ b/build/HarfBuzzSharp.props
@@ -1,6 +1,6 @@
-
-
+
+
diff --git a/build/MicroCom.targets b/build/MicroCom.targets
index b48e377fd4..1ed388f689 100644
--- a/build/MicroCom.targets
+++ b/build/MicroCom.targets
@@ -15,7 +15,8 @@
Inputs="@(AvnComIdl);$(MSBuildThisFileDirectory)../src/tools/MicroComGenerator/**/*.cs"
Outputs="%(AvnComIdl.OutputFile)">
-
+
diff --git a/build/SharedVersion.props b/build/SharedVersion.props
index 75bada4bfc..7d75901288 100644
--- a/build/SharedVersion.props
+++ b/build/SharedVersion.props
@@ -17,7 +17,6 @@
git
$(MSBuildThisFileDirectory)\avalonia.snk
true
- $(DefineConstants);SIGNED_BUILD
diff --git a/build/SkiaSharp.props b/build/SkiaSharp.props
index f2e7df36cd..97b29a192d 100644
--- a/build/SkiaSharp.props
+++ b/build/SkiaSharp.props
@@ -1,6 +1,6 @@
-
-
+
+
diff --git a/build/SourceLink.props b/build/SourceLink.props
index 1e007e01eb..0f77c2a613 100644
--- a/build/SourceLink.props
+++ b/build/SourceLink.props
@@ -3,7 +3,7 @@
true
false
true
- embedded
+ full
$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb
diff --git a/global.json b/global.json
index b2b2da7c4f..e3e652761c 100644
--- a/global.json
+++ b/global.json
@@ -1,7 +1,7 @@
{
- "sdk": {
- "version": "3.1.401"
- },
+ "sdk": {
+ "version": "6.0.100"
+ },
"msbuild-sdks": {
"Microsoft.Build.Traversal": "1.0.43",
"MSBuild.Sdk.Extras": "2.0.54",
diff --git a/native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj b/native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj
index dba3ee6d31..85fcf20034 100644
--- a/native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj
+++ b/native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj
@@ -22,6 +22,7 @@
37E2330F21583241000CB7E2 /* KeyTransform.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37E2330E21583241000CB7E2 /* KeyTransform.mm */; };
520624B322973F4100C4DCEF /* menu.mm in Sources */ = {isa = PBXBuildFile; fileRef = 520624B222973F4100C4DCEF /* menu.mm */; };
522D5959258159C1006F7F7A /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 522D5958258159C1006F7F7A /* Carbon.framework */; };
+ 523484CA26EA688F00EA0C2C /* trayicon.mm in Sources */ = {isa = PBXBuildFile; fileRef = 523484C926EA688F00EA0C2C /* trayicon.mm */; };
5B21A982216530F500CEE36E /* cursor.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5B21A981216530F500CEE36E /* cursor.mm */; };
5B8BD94F215BFEA6005ED2A7 /* clipboard.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5B8BD94E215BFEA6005ED2A7 /* clipboard.mm */; };
AB00E4F72147CA920032A60A /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB00E4F62147CA920032A60A /* main.mm */; };
@@ -51,6 +52,8 @@
37E2330E21583241000CB7E2 /* KeyTransform.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = KeyTransform.mm; sourceTree = ""; };
520624B222973F4100C4DCEF /* menu.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = menu.mm; sourceTree = ""; };
522D5958258159C1006F7F7A /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = System/Library/Frameworks/Carbon.framework; sourceTree = SDKROOT; };
+ 523484C926EA688F00EA0C2C /* trayicon.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = trayicon.mm; sourceTree = ""; };
+ 523484CB26EA68AA00EA0C2C /* trayicon.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = trayicon.h; sourceTree = ""; };
5B21A981216530F500CEE36E /* cursor.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = cursor.mm; sourceTree = ""; };
5B8BD94E215BFEA6005ED2A7 /* clipboard.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = clipboard.mm; sourceTree = ""; };
5BF943652167AD1D009CAE35 /* cursor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = cursor.h; sourceTree = ""; };
@@ -114,6 +117,8 @@
AB00E4F62147CA920032A60A /* main.mm */,
37155CE3233C00EB0034DCE9 /* menu.h */,
520624B222973F4100C4DCEF /* menu.mm */,
+ 523484C926EA688F00EA0C2C /* trayicon.mm */,
+ 523484CB26EA68AA00EA0C2C /* trayicon.h */,
1A3E5EA723E9E83B00EDE661 /* rendertarget.mm */,
37A517B22159597E00FBA241 /* Screens.mm */,
37C09D8721580FE4006A6758 /* SystemDialogs.mm */,
@@ -204,6 +209,7 @@
1A1852DC23E05814008F0DED /* deadlock.mm in Sources */,
5B21A982216530F500CEE36E /* cursor.mm in Sources */,
37DDA9B0219330F8002E132B /* AvnString.mm in Sources */,
+ 523484CA26EA688F00EA0C2C /* trayicon.mm in Sources */,
AB8F7D6B21482D7F0057DBA5 /* platformthreading.mm in Sources */,
1A3E5EA823E9E83B00EDE661 /* rendertarget.mm in Sources */,
1A3E5EAE23E9FB1300EDE661 /* cgl.mm in Sources */,
diff --git a/native/Avalonia.Native/src/OSX/KeyTransform.mm b/native/Avalonia.Native/src/OSX/KeyTransform.mm
index 6b7d95b619..4817ad0ccf 100644
--- a/native/Avalonia.Native/src/OSX/KeyTransform.mm
+++ b/native/Avalonia.Native/src/OSX/KeyTransform.mm
@@ -222,6 +222,7 @@ std::map s_QwertyKeyMap =
{ 45, "n" },
{ 46, "m" },
{ 47, "." },
+ { 48, "\t" },
{ 49, " " },
{ 50, "`" },
{ 51, "" },
diff --git a/native/Avalonia.Native/src/OSX/common.h b/native/Avalonia.Native/src/OSX/common.h
index c082003ccf..8896fbe88b 100644
--- a/native/Avalonia.Native/src/OSX/common.h
+++ b/native/Avalonia.Native/src/OSX/common.h
@@ -22,6 +22,7 @@ extern AvnDragDropEffects ConvertDragDropEffects(NSDragOperation nsop);
extern IAvnCursorFactory* CreateCursorFactory();
extern IAvnGlDisplay* GetGlDisplay();
extern IAvnMenu* CreateAppMenu(IAvnMenuEvents* events);
+extern IAvnTrayIcon* CreateTrayIcon();
extern IAvnMenuItem* CreateAppMenuItem();
extern IAvnMenuItem* CreateAppMenuItemSeparator();
extern IAvnNativeControlHost* CreateNativeControlHost(NSView* parent);
diff --git a/native/Avalonia.Native/src/OSX/main.mm b/native/Avalonia.Native/src/OSX/main.mm
index 3e152a6125..eeaaecfdbd 100644
--- a/native/Avalonia.Native/src/OSX/main.mm
+++ b/native/Avalonia.Native/src/OSX/main.mm
@@ -303,6 +303,17 @@ public:
}
}
+ virtual HRESULT CreateTrayIcon (IAvnTrayIcon** ppv) override
+ {
+ START_COM_CALL;
+
+ @autoreleasepool
+ {
+ *ppv = ::CreateTrayIcon();
+ return S_OK;
+ }
+ }
+
virtual HRESULT CreateMenu (IAvnMenuEvents* cb, IAvnMenu** ppv) override
{
START_COM_CALL;
diff --git a/native/Avalonia.Native/src/OSX/trayicon.h b/native/Avalonia.Native/src/OSX/trayicon.h
new file mode 100644
index 0000000000..f94f9a871b
--- /dev/null
+++ b/native/Avalonia.Native/src/OSX/trayicon.h
@@ -0,0 +1,33 @@
+//
+// trayicon.h
+// Avalonia.Native.OSX
+//
+// Created by Dan Walmsley on 09/09/2021.
+// Copyright © 2021 Avalonia. All rights reserved.
+//
+
+#ifndef trayicon_h
+#define trayicon_h
+
+#include "common.h"
+
+class AvnTrayIcon : public ComSingleObject
+{
+private:
+ NSStatusItem* _native;
+
+public:
+ FORWARD_IUNKNOWN()
+
+ AvnTrayIcon();
+
+ ~AvnTrayIcon ();
+
+ virtual HRESULT SetIcon (void* data, size_t length) override;
+
+ virtual HRESULT SetMenu (IAvnMenu* menu) override;
+
+ virtual HRESULT SetIsVisible (bool isVisible) override;
+};
+
+#endif /* trayicon_h */
diff --git a/native/Avalonia.Native/src/OSX/trayicon.mm b/native/Avalonia.Native/src/OSX/trayicon.mm
new file mode 100644
index 0000000000..151990cfb1
--- /dev/null
+++ b/native/Avalonia.Native/src/OSX/trayicon.mm
@@ -0,0 +1,85 @@
+#include "common.h"
+#include "trayicon.h"
+#include "menu.h"
+
+extern IAvnTrayIcon* CreateTrayIcon()
+{
+ @autoreleasepool
+ {
+ return new AvnTrayIcon();
+ }
+}
+
+AvnTrayIcon::AvnTrayIcon()
+{
+ _native = [[NSStatusBar systemStatusBar] statusItemWithLength: NSSquareStatusItemLength];
+
+}
+
+AvnTrayIcon::~AvnTrayIcon()
+{
+ if(_native != nullptr)
+ {
+ [[_native statusBar] removeStatusItem:_native];
+ _native = nullptr;
+ }
+}
+
+HRESULT AvnTrayIcon::SetIcon (void* data, size_t length)
+{
+ START_COM_CALL;
+
+ @autoreleasepool
+ {
+ if(data != nullptr)
+ {
+ NSData *imageData = [NSData dataWithBytes:data length:length];
+ NSImage *image = [[NSImage alloc] initWithData:imageData];
+
+ NSSize originalSize = [image size];
+
+ NSSize size;
+ size.height = [[NSFont menuFontOfSize:0] pointSize] * 1.333333;
+
+ auto scaleFactor = size.height / originalSize.height;
+ size.width = originalSize.width * scaleFactor;
+
+ [image setSize: size];
+ [_native setImage:image];
+ }
+ else
+ {
+ [_native setImage:nullptr];
+ }
+ return S_OK;
+ }
+}
+
+HRESULT AvnTrayIcon::SetMenu (IAvnMenu* menu)
+{
+ START_COM_CALL;
+
+ @autoreleasepool
+ {
+ auto appMenu = dynamic_cast(menu);
+
+ if(appMenu != nullptr)
+ {
+ [_native setMenu:appMenu->GetNative()];
+ }
+ }
+
+ return S_OK;
+}
+
+HRESULT AvnTrayIcon::SetIsVisible(bool isVisible)
+{
+ START_COM_CALL;
+
+ @autoreleasepool
+ {
+ [_native setVisible:isVisible];
+ }
+
+ return S_OK;
+}
diff --git a/native/Avalonia.Native/src/OSX/window.h b/native/Avalonia.Native/src/OSX/window.h
index 3a54bd4b79..1dc091a48d 100644
--- a/native/Avalonia.Native/src/OSX/window.h
+++ b/native/Avalonia.Native/src/OSX/window.h
@@ -12,6 +12,7 @@ class WindowBaseImpl;
-(AvnPixelSize) getPixelSize;
-(AvnPlatformResizeReason) getResizeReason;
-(void) setResizeReason:(AvnPlatformResizeReason)reason;
++ (AvnPoint)toAvnPoint:(CGPoint)p;
@end
@interface AutoFitContentView : NSView
diff --git a/native/Avalonia.Native/src/OSX/window.mm b/native/Avalonia.Native/src/OSX/window.mm
index 9c6a0e6187..d5289f5229 100644
--- a/native/Avalonia.Native/src/OSX/window.mm
+++ b/native/Avalonia.Native/src/OSX/window.mm
@@ -52,7 +52,6 @@ public:
[Window setBackingType:NSBackingStoreBuffered];
[Window setOpaque:false];
- [Window setContentView: StandardContainer];
}
virtual HRESULT ObtainNSWindowHandle(void** ret) override
@@ -125,6 +124,8 @@ public:
SetPosition(lastPositionSet);
UpdateStyle();
+ [Window setContentView: StandardContainer];
+
[Window setTitle:_lastTitle];
if(ShouldTakeFocusOnShow() && activate)
@@ -205,7 +206,11 @@ public:
auto window = Window;
Window = nullptr;
- [window close];
+ try{
+ // Seems to throw sometimes on application exit.
+ [window close];
+ }
+ catch(NSException*){}
}
return S_OK;
@@ -231,6 +236,8 @@ public:
virtual HRESULT GetFrameSize(AvnSize* ret) override
{
+ START_COM_CALL;
+
@autoreleasepool
{
if(ret == nullptr)
@@ -321,6 +328,7 @@ public:
BaseEvents->Resized(AvnSize{x,y}, reason);
}
+ [StandardContainer setFrameSize:NSSize{x,y}];
[Window setContentSize:NSSize{x, y}];
}
@finally
@@ -641,6 +649,7 @@ private:
[Window setCanBecomeKeyAndMain];
[Window disableCursorRects];
[Window setTabbingMode:NSWindowTabbingModeDisallowed];
+ [Window setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
}
void HideOrShowTrafficLights ()
@@ -713,6 +722,13 @@ private:
if(cparent == nullptr)
return E_INVALIDARG;
+ // If one tries to show a child window with a minimized parent window, then the parent window will be
+ // restored but MacOS isn't kind enough to *tell* us that, so the window will be left in a non-interactive
+ // state. Detect this and explicitly restore the parent window ourselves to avoid this situation.
+ if (cparent->WindowState() == Minimized)
+ cparent->SetWindowState(Normal);
+
+ [Window setCollectionBehavior:NSWindowCollectionBehaviorFullScreenAuxiliary];
[cparent->Window addChildWindow:Window ordered:NSWindowAbove];
UpdateStyle();
@@ -1085,14 +1101,7 @@ private:
{
_fullScreenActive = true;
- [Window setHasShadow:YES];
- [Window setTitleVisibility:NSWindowTitleVisible];
- [Window setTitlebarAppearsTransparent:NO];
[Window setTitle:_lastTitle];
-
- Window.styleMask = Window.styleMask | NSWindowStyleMaskTitled | NSWindowStyleMaskResizable;
- Window.styleMask = Window.styleMask & ~NSWindowStyleMaskFullSizeContentView;
-
[Window toggleFullScreen:nullptr];
}
@@ -1204,6 +1213,7 @@ private:
}
_actualWindowState = _lastWindowState;
+ WindowEvents->WindowStateChanged(_actualWindowState);
}
@@ -1540,7 +1550,7 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
return pt;
}
-- (AvnPoint)toAvnPoint:(CGPoint)p
++ (AvnPoint)toAvnPoint:(CGPoint)p
{
AvnPoint result;
@@ -1597,7 +1607,7 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
}
auto localPoint = [self convertPoint:[event locationInWindow] toView:self];
- auto avnPoint = [self toAvnPoint:localPoint];
+ auto avnPoint = [AvnView toAvnPoint:localPoint];
auto point = [self translateLocalPoint:avnPoint];
AvnVector delta;
@@ -1665,6 +1675,7 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
switch(event.buttonNumber)
{
+ case 2:
case 3:
_isMiddlePressed = true;
[self mouseEvent:event withType:MiddleButtonDown];
@@ -1697,6 +1708,7 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
{
switch(event.buttonNumber)
{
+ case 2:
case 3:
_isMiddlePressed = false;
[self mouseEvent:event withType:MiddleButtonUp];
@@ -1940,7 +1952,7 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
- (NSDragOperation)triggerAvnDragEvent: (AvnDragEventType) type info: (id )info
{
auto localPoint = [self convertPoint:[info draggingLocation] toView:self];
- auto avnPoint = [self toAvnPoint:localPoint];
+ auto avnPoint = [AvnView toAvnPoint:localPoint];
auto point = [self translateLocalPoint:avnPoint];
auto modifiers = [self getModifiers:[[NSApp currentEvent] modifierFlags]];
NSDragOperation nsop = [info draggingSourceOperationMask];
@@ -2373,6 +2385,56 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
_parent->BaseEvents->PositionChanged(position);
}
}
+
+- (AvnPoint) translateLocalPoint:(AvnPoint)pt
+{
+ pt.Y = [self frame].size.height - pt.Y;
+ return pt;
+}
+
+- (void)sendEvent:(NSEvent *)event
+{
+ [super sendEvent:event];
+
+ /// This is to detect non-client clicks. This can only be done on Windows... not popups, hence the dynamic_cast.
+ if(_parent != nullptr && dynamic_cast(_parent.getRaw()) != nullptr)
+ {
+ switch(event.type)
+ {
+ case NSEventTypeLeftMouseDown:
+ {
+ AvnView* view = _parent->View;
+ NSPoint windowPoint = [event locationInWindow];
+ NSPoint viewPoint = [view convertPoint:windowPoint fromView:nil];
+
+ if (!NSPointInRect(viewPoint, view.bounds))
+ {
+ auto avnPoint = [AvnView toAvnPoint:windowPoint];
+ auto point = [self translateLocalPoint:avnPoint];
+ AvnVector delta;
+
+ _parent->BaseEvents->RawMouseEvent(NonClientLeftButtonDown, [event timestamp] * 1000, AvnInputModifiersNone, point, delta);
+ }
+ }
+ break;
+
+ case NSEventTypeMouseEntered:
+ {
+ _parent->UpdateCursor();
+ }
+ break;
+
+ case NSEventTypeMouseExited:
+ {
+ [[NSCursor arrowCursor] set];
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+}
@end
class PopupImpl : public virtual WindowBaseImpl, public IAvnPopup
diff --git a/nukebuild/_build.csproj b/nukebuild/_build.csproj
index e08ffd0413..b28d3eb700 100644
--- a/nukebuild/_build.csproj
+++ b/nukebuild/_build.csproj
@@ -15,6 +15,7 @@
+
@@ -36,10 +37,10 @@
-
-
-
-
+
+ MicroComGenerator\%(Filename)%(Extension)
+
+
diff --git a/packages/Avalonia/AvaloniaBuildTasks.targets b/packages/Avalonia/AvaloniaBuildTasks.targets
index 45a7f1aa44..d43a5c1624 100644
--- a/packages/Avalonia/AvaloniaBuildTasks.targets
+++ b/packages/Avalonia/AvaloniaBuildTasks.targets
@@ -42,12 +42,25 @@
- $(BuildAvaloniaResourcesDependsOn);AddAvaloniaResources;ResolveReferences
+ $(BuildAvaloniaResourcesDependsOn);AddAvaloniaResources;ResolveReferences;_GenerateAvaloniaResourcesDependencyCache
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -75,6 +88,7 @@
$(IntermediateOutputPath)/Avalonia/references
$(IntermediateOutputPath)/Avalonia/original.dll
false
+ false
+
Please read the [contribution guidelines](CONTRIBUTING.md) before submitting a pull request.
## Code of Conduct
@@ -71,11 +74,6 @@ For more information see the [.NET Foundation Code of Conduct](https://dotnetfou
Avalonia is licenced under the [MIT licence](licence.md).
-## Contributors
-
-This project exists thanks to all the people who contribute. [[Contribute](https://avaloniaui.net/contributing)].
-
-
### Backers
Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/Avalonia#backer)]
@@ -95,7 +93,8 @@ Support this project by becoming a sponsor. Your logo will show up here with a l
-
+
+
## .NET Foundation
diff --git a/samples/BindingDemo/BindingDemo.csproj b/samples/BindingDemo/BindingDemo.csproj
index d898b737a9..2c6ff74e5e 100644
--- a/samples/BindingDemo/BindingDemo.csproj
+++ b/samples/BindingDemo/BindingDemo.csproj
@@ -1,7 +1,7 @@
Exe
- netcoreapp3.1
+ net6.0
diff --git a/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj b/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj
index 3c2d2ee359..2d4fc45171 100644
--- a/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj
+++ b/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj
@@ -2,7 +2,7 @@
WinExe
- netcoreapp3.1
+ net6.0
true
diff --git a/samples/ControlCatalog/App.xaml b/samples/ControlCatalog/App.xaml
index 6aad44c0d5..6e57686e00 100644
--- a/samples/ControlCatalog/App.xaml
+++ b/samples/ControlCatalog/App.xaml
@@ -1,5 +1,8 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/ControlCatalog/App.xaml.cs b/samples/ControlCatalog/App.xaml.cs
index f3ec7b48aa..36b6fc2dcd 100644
--- a/samples/ControlCatalog/App.xaml.cs
+++ b/samples/ControlCatalog/App.xaml.cs
@@ -1,14 +1,21 @@
using System;
using Avalonia;
+using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
using Avalonia.Markup.Xaml.Styling;
using Avalonia.Styling;
+using ControlCatalog.ViewModels;
namespace ControlCatalog
{
public class App : Application
{
+ public App()
+ {
+ DataContext = new ApplicationViewModel();
+ }
+
private static readonly StyleInclude DataGridFluent = new StyleInclude(new Uri("avares://ControlCatalog/Styles"))
{
Source = new Uri("avares://Avalonia.Controls.DataGrid/Themes/Fluent.xaml")
@@ -97,7 +104,9 @@ namespace ControlCatalog
public override void OnFrameworkInitializationCompleted()
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktopLifetime)
+ {
desktopLifetime.MainWindow = new MainWindow();
+ }
else if (ApplicationLifetime is ISingleViewApplicationLifetime singleViewLifetime)
singleViewLifetime.MainView = new MainView();
diff --git a/samples/ControlCatalog/MainView.xaml b/samples/ControlCatalog/MainView.xaml
index 6537c470d5..f61b59e6cd 100644
--- a/samples/ControlCatalog/MainView.xaml
+++ b/samples/ControlCatalog/MainView.xaml
@@ -98,6 +98,7 @@
Transparent
Blur
AcrylicBlur
+ Mica
diff --git a/samples/ControlCatalog/MainWindow.xaml b/samples/ControlCatalog/MainWindow.xaml
index a107ee2163..375345f64e 100644
--- a/samples/ControlCatalog/MainWindow.xaml
+++ b/samples/ControlCatalog/MainWindow.xaml
@@ -12,6 +12,7 @@
ExtendClientAreaTitleBarHeightHint="{Binding TitleBarHeight}"
TransparencyLevelHint="{Binding TransparencyLevel}"
x:Name="MainWindow"
+ Background="Transparent"
x:Class="ControlCatalog.MainWindow" WindowState="{Binding WindowState, Mode=TwoWay}">
@@ -62,11 +63,11 @@
diff --git a/samples/ControlCatalog/MainWindow.xaml.cs b/samples/ControlCatalog/MainWindow.xaml.cs
index 2446c0e1c9..a9900471c5 100644
--- a/samples/ControlCatalog/MainWindow.xaml.cs
+++ b/samples/ControlCatalog/MainWindow.xaml.cs
@@ -35,6 +35,8 @@ namespace ControlCatalog
var mainMenu = this.FindControl