diff --git a/native/Avalonia.Native/src/OSX/window.mm b/native/Avalonia.Native/src/OSX/window.mm
index 2073e130cb..d5289f5229 100644
--- a/native/Avalonia.Native/src/OSX/window.mm
+++ b/native/Avalonia.Native/src/OSX/window.mm
@@ -206,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;
@@ -724,6 +728,7 @@ private:
if (cparent->WindowState() == Minimized)
cparent->SetWindowState(Normal);
+ [Window setCollectionBehavior:NSWindowCollectionBehaviorFullScreenAuxiliary];
[cparent->Window addChildWindow:Window ordered:NSWindowAbove];
UpdateStyle();
diff --git a/packages/Avalonia/AvaloniaBuildTasks.targets b/packages/Avalonia/AvaloniaBuildTasks.targets
index 3f9ccb04eb..d43a5c1624 100644
--- a/packages/Avalonia/AvaloniaBuildTasks.targets
+++ b/packages/Avalonia/AvaloniaBuildTasks.targets
@@ -88,6 +88,7 @@
$(IntermediateOutputPath)/Avalonia/references$(IntermediateOutputPath)/Avalonia/original.dllfalse
+ false !string.IsNullOrWhiteSpace(l)).ToArray(),
ProjectDirectory, OutputPath, VerifyIl, outputImportance,
(SignAssembly && !DelaySign) ? AssemblyOriginatorKeyFile : null,
- EnableComInteropPatching, SkipXamlCompilation);
+ EnableComInteropPatching, SkipXamlCompilation, DebuggerLaunch);
if (!res.Success)
return false;
if (!res.WrittenFile)
@@ -87,5 +84,7 @@ namespace Avalonia.Build.Tasks
public IBuildEngine BuildEngine { get; set; }
public ITaskHost HostObject { get; set; }
+
+ public bool DebuggerLaunch { get; set; }
}
}
diff --git a/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs b/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs
index 508045dccb..593d79471e 100644
--- a/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs
+++ b/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs
@@ -1,13 +1,10 @@
using System;
-using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
-using System.Text;
using Avalonia.Markup.Xaml.XamlIl.CompilerExtensions;
using Microsoft.Build.Framework;
using Mono.Cecil;
-using Avalonia.Utilities;
using Mono.Cecil.Cil;
using Mono.Cecil.Rocks;
using XamlX;
@@ -44,16 +41,23 @@ namespace Avalonia.Build.Tasks
string projectDirectory,
string output, bool verifyIl, MessageImportance logImportance, string strongNameKey, bool patchCom,
bool skipXamlCompilation)
+ {
+ return Compile(engine, input, references, projectDirectory, output, verifyIl, logImportance, strongNameKey, patchCom, skipXamlCompilation, debuggerLaunch:false);
+ }
+
+ internal static CompileResult Compile(IBuildEngine engine, string input, string[] references,
+ string projectDirectory,
+ string output, bool verifyIl, MessageImportance logImportance, string strongNameKey, bool patchCom, bool skipXamlCompilation, bool debuggerLaunch)
{
var typeSystem = new CecilTypeSystem(references
.Where(r => !r.ToLowerInvariant().EndsWith("avalonia.build.tasks.dll"))
.Concat(new[] { input }), input);
-
+
var asm = typeSystem.TargetAssemblyDefinition;
if (!skipXamlCompilation)
{
- var compileRes = CompileCore(engine, typeSystem, projectDirectory, verifyIl, logImportance);
+ var compileRes = CompileCore(engine, typeSystem, projectDirectory, verifyIl, logImportance, debuggerLaunch);
if (compileRes == null && !patchCom)
return new CompileResult(true);
if (compileRes == false)
@@ -62,7 +66,7 @@ namespace Avalonia.Build.Tasks
if (patchCom)
ComInteropHelper.PatchAssembly(asm, typeSystem);
-
+
var writerParameters = new WriterParameters { WriteSymbols = asm.MainModule.HasSymbols };
if (!string.IsNullOrWhiteSpace(strongNameKey))
writerParameters.StrongNameKeyBlob = File.ReadAllBytes(strongNameKey);
@@ -70,13 +74,43 @@ namespace Avalonia.Build.Tasks
asm.Write(output, writerParameters);
return new CompileResult(true, true);
-
+
}
-
+
static bool? CompileCore(IBuildEngine engine, CecilTypeSystem typeSystem,
string projectDirectory, bool verifyIl,
- MessageImportance logImportance)
+ MessageImportance logImportance
+ , bool debuggerLaunch = false)
{
+ if (debuggerLaunch)
+ {
+ // According this https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.debugger.launch?view=net-6.0#remarks
+ // documentation, on not windows platform Debugger.Launch() always return true without running a debugger.
+ if (System.Diagnostics.Debugger.Launch())
+ {
+ // Set timeout at 1 minut.
+ var time = new System.Diagnostics.Stopwatch();
+ var timeout = TimeSpan.FromMinutes(1);
+ time.Start();
+
+ // wait for the debugger to be attacked or timeout.
+ while (!System.Diagnostics.Debugger.IsAttached && time.Elapsed < timeout)
+ {
+ engine.LogMessage($"[PID:{System.Diagnostics.Process.GetCurrentProcess().Id}] Wating attach debugger. Elapsed {time.Elapsed}...", MessageImportance.High);
+ System.Threading.Thread.Sleep(100);
+ }
+
+ time.Stop();
+ if (time.Elapsed >= timeout)
+ {
+ engine.LogMessage("Wating attach debugger timeout.", MessageImportance.Normal);
+ }
+ }
+ else
+ {
+ engine.LogMessage("Debugging cancelled.", MessageImportance.Normal);
+ }
+ }
var asm = typeSystem.TargetAssemblyDefinition;
var emres = new EmbeddedResources(asm);
var avares = new AvaloniaResources(asm, projectDirectory);
diff --git a/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs b/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs
index 2a42d99ac5..3a2fd68af5 100644
--- a/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs
+++ b/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs
@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
+using System.Runtime.CompilerServices;
using System.Threading;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
@@ -122,12 +123,23 @@ namespace Avalonia.Controls.ApplicationLifetimes
lifetimeEvents.ShutdownRequested += OnShutdownRequested;
_cts = new CancellationTokenSource();
- MainWindow?.Show();
+
+ // Note due to a bug in the JIT we wrap this in a method, otherwise MainWindow
+ // gets stuffed into a local var and can not be GCed until after the program stops.
+ // this method never exits until program end.
+ ShowMainWindow();
+
Dispatcher.UIThread.MainLoop(_cts.Token);
Environment.ExitCode = _exitCode;
return _exitCode;
}
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private void ShowMainWindow()
+ {
+ MainWindow?.Show();
+ }
+
public void Dispose()
{
if (_activeLifetime == this)
diff --git a/src/Avalonia.Controls/WindowBase.cs b/src/Avalonia.Controls/WindowBase.cs
index ee008efb04..5861d0452d 100644
--- a/src/Avalonia.Controls/WindowBase.cs
+++ b/src/Avalonia.Controls/WindowBase.cs
@@ -193,6 +193,12 @@ namespace Avalonia.Controls
try
{
IsVisible = false;
+
+ if (this is IFocusScope scope)
+ {
+ FocusManager.Instance?.RemoveFocusScope(scope);
+ }
+
base.HandleClosed();
}
finally
diff --git a/src/Avalonia.Input/ApiCompatBaseline.txt b/src/Avalonia.Input/ApiCompatBaseline.txt
index 98eb8598d8..270c5305e5 100644
--- a/src/Avalonia.Input/ApiCompatBaseline.txt
+++ b/src/Avalonia.Input/ApiCompatBaseline.txt
@@ -3,6 +3,7 @@ MembersMustExist : Member 'public Avalonia.Platform.IPlatformHandle Avalonia.Inp
MembersMustExist : Member 'public Avalonia.Interactivity.RoutedEvent Avalonia.Interactivity.RoutedEvent Avalonia.Input.Gestures.DoubleTappedEvent' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public Avalonia.Interactivity.RoutedEvent Avalonia.Interactivity.RoutedEvent Avalonia.Input.Gestures.RightTappedEvent' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public Avalonia.Interactivity.RoutedEvent Avalonia.Interactivity.RoutedEvent Avalonia.Input.Gestures.TappedEvent' does not exist in the implementation but it does exist in the contract.
+InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Input.IFocusManager.RemoveFocusScope(Avalonia.Input.IFocusScope)' is present in the implementation but not in the contract.
MembersMustExist : Member 'public Avalonia.Interactivity.RoutedEvent Avalonia.Interactivity.RoutedEvent Avalonia.Input.InputElement.DoubleTappedEvent' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public Avalonia.Interactivity.RoutedEvent Avalonia.Interactivity.RoutedEvent Avalonia.Input.InputElement.TappedEvent' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public void Avalonia.Input.InputElement.add_DoubleTapped(System.EventHandler)' does not exist in the implementation but it does exist in the contract.
@@ -10,4 +11,4 @@ MembersMustExist : Member 'public void Avalonia.Input.InputElement.add_Tapped(Sy
MembersMustExist : Member 'public void Avalonia.Input.InputElement.remove_DoubleTapped(System.EventHandler)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public void Avalonia.Input.InputElement.remove_Tapped(System.EventHandler)' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'Avalonia.Platform.IStandardCursorFactory' does not exist in the implementation but it does exist in the contract.
-Total Issues: 11
+Total Issues: 12
diff --git a/src/Avalonia.Input/FocusManager.cs b/src/Avalonia.Input/FocusManager.cs
index 1432092ba1..2efd33df1d 100644
--- a/src/Avalonia.Input/FocusManager.cs
+++ b/src/Avalonia.Input/FocusManager.cs
@@ -162,6 +162,22 @@ namespace Avalonia.Input
Focus(e);
}
+ public void RemoveFocusScope(IFocusScope scope)
+ {
+ scope = scope ?? throw new ArgumentNullException(nameof(scope));
+
+ if (_focusScopes.TryGetValue(scope, out _))
+ {
+ SetFocusedElement(scope, null);
+ _focusScopes.Remove(scope);
+ }
+
+ if (Scope == scope)
+ {
+ Scope = null;
+ }
+ }
+
public static bool GetIsFocusScope(IInputElement e) => e is IFocusScope;
///
diff --git a/src/Avalonia.Input/IFocusManager.cs b/src/Avalonia.Input/IFocusManager.cs
index e1b5087c3d..2510479a8e 100644
--- a/src/Avalonia.Input/IFocusManager.cs
+++ b/src/Avalonia.Input/IFocusManager.cs
@@ -35,5 +35,13 @@ namespace Avalonia.Input
/// when it activates, e.g. when a Window is activated.
///
void SetFocusScope(IFocusScope scope);
+
+ ///
+ /// Notifies the focus manager that a focus scope has been removed.
+ ///
+ /// The focus scope to be removed.
+ /// This should not be called by client code. It is called by an
+ /// when it deactivates or closes, e.g. when a Window is closed.
+ void RemoveFocusScope(IFocusScope scope);
}
}
diff --git a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/StaticResourceExtension.cs b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/StaticResourceExtension.cs
index 4ad68fc63e..db33b88cc3 100644
--- a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/StaticResourceExtension.cs
+++ b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/StaticResourceExtension.cs
@@ -5,6 +5,7 @@ using Avalonia.Controls;
using Avalonia.Markup.Data;
using Avalonia.Markup.Xaml.Converters;
using Avalonia.Markup.Xaml.XamlIl.Runtime;
+using Avalonia.Styling;
namespace Avalonia.Markup.Xaml.MarkupExtensions
{
@@ -33,6 +34,11 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions
_ => null,
};
+ if (provideTarget.TargetObject is Setter setter)
+ {
+ targetType = setter.Property.PropertyType;
+ }
+
// Look upwards though the ambient context for IResourceHosts and IResourceProviders
// which might be able to give us the resource.
foreach (var e in stack.Parents)
diff --git a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs
index f7ed2f215f..eaf6b47f42 100644
--- a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs
+++ b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs
@@ -193,7 +193,6 @@ namespace Avalonia.Win32
case WindowsMessage.WM_MBUTTONUP:
case WindowsMessage.WM_XBUTTONUP:
{
- shouldTakeFocus = ShouldTakeFocusOnClick;
if (ShouldIgnoreTouchEmulatedMessage())
{
break;
diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/StaticResourceExtensionTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/StaticResourceExtensionTests.cs
index fb3fd6d7d4..340eac0d4f 100644
--- a/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/StaticResourceExtensionTests.cs
+++ b/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/StaticResourceExtensionTests.cs
@@ -512,6 +512,33 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
var brush = (ISolidColorBrush)border.Background;
Assert.Equal(0xff506070, brush.Color.ToUint32());
}
+
+ [Fact]
+ public void Automatically_Converts_Color_To_SolidColorBrush_From_Setter()
+ {
+ using (StyledWindow())
+ {
+ var xaml = @"
+
+
+ #ff506070
+
+
+
+
+
+";
+
+ var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
+ var button = window.FindControl