diff --git a/src/Avalonia.Native/Avalonia.Native.csproj b/src/Avalonia.Native/Avalonia.Native.csproj index 65c2a75b1c..1a2bdeef1e 100644 --- a/src/Avalonia.Native/Avalonia.Native.csproj +++ b/src/Avalonia.Native/Avalonia.Native.csproj @@ -19,8 +19,9 @@ - - + + + diff --git a/src/Avalonia.Native/CallbackBase.cs b/src/Avalonia.Native/CallbackBase.cs index 67c383f6ae..1356dd58ff 100644 --- a/src/Avalonia.Native/CallbackBase.cs +++ b/src/Avalonia.Native/CallbackBase.cs @@ -2,11 +2,13 @@ // Licensed under the MIT license. See licence.md file in the project root for full license information. using System; +using System.Runtime.ExceptionServices; using SharpGen.Runtime; +using Avalonia.Platform; namespace Avalonia.Native { - public class CallbackBase : SharpGen.Runtime.IUnknown + public class CallbackBase : SharpGen.Runtime.IUnknown, IExceptionCallback { private uint _refCount; private bool _disposed; @@ -76,5 +78,15 @@ namespace Avalonia.Native { } + + public void RaiseException(Exception e) + { + if (AvaloniaLocator.Current.GetService() is PlatformThreadingInterface threadingInterface) + { + threadingInterface.TerminateNativeApp(); + + threadingInterface.DispatchException(ExceptionDispatchInfo.Capture(e)); + } + } } } diff --git a/src/Avalonia.Native/PlatformThreadingInterface.cs b/src/Avalonia.Native/PlatformThreadingInterface.cs index 353124a9d1..5ddaf83ed4 100644 --- a/src/Avalonia.Native/PlatformThreadingInterface.cs +++ b/src/Avalonia.Native/PlatformThreadingInterface.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See licence.md file in the project root for full license information. using System; +using System.Runtime.ExceptionServices; using System.Threading; using Avalonia.Native.Interop; using Avalonia.Platform; @@ -43,6 +44,8 @@ namespace Avalonia.Native } readonly IAvnPlatformThreadingInterface _native; + private ExceptionDispatchInfo _exceptionDispatchInfo; + private CancellationTokenSource _exceptionCancellationSource; public PlatformThreadingInterface(IAvnPlatformThreadingInterface native) { @@ -57,32 +60,48 @@ namespace Avalonia.Native public void RunLoop(CancellationToken cancellationToken) { - if (cancellationToken.CanBeCanceled == false) - _native.RunLoop(null); - else + var l = new object(); + _exceptionCancellationSource = new CancellationTokenSource(); + + var compositeCancellation = CancellationTokenSource + .CreateLinkedTokenSource(cancellationToken, _exceptionCancellationSource.Token).Token; + + var cancellation = _native.CreateLoopCancellation(); + compositeCancellation.Register(() => { - var l = new object(); - var cancellation = _native.CreateLoopCancellation(); - cancellationToken.Register(() => + lock (l) { - lock (l) - { - cancellation?.Cancel(); - } - }); - try - { - _native.RunLoop(cancellation); + cancellation?.Cancel(); } - finally + }); + + try + { + _native.RunLoop(cancellation); + } + finally + { + lock (l) { - lock(l) - { - cancellation?.Dispose(); - cancellation = null; - } + cancellation?.Dispose(); + cancellation = null; } } + + if (_exceptionDispatchInfo != null) + { + _exceptionDispatchInfo.Throw(); + } + } + + public void DispatchException (ExceptionDispatchInfo exceptionInfo) + { + _exceptionDispatchInfo = exceptionInfo; + } + + public void TerminateNativeApp() + { + _exceptionCancellationSource?.Cancel(); } public void Signal(DispatcherPriority priority) diff --git a/src/Avalonia.X11/X11Framebuffer.cs b/src/Avalonia.X11/X11Framebuffer.cs index 00288f300d..94f930e9ec 100644 --- a/src/Avalonia.X11/X11Framebuffer.cs +++ b/src/Avalonia.X11/X11Framebuffer.cs @@ -14,6 +14,10 @@ namespace Avalonia.X11 public X11Framebuffer(IntPtr display, IntPtr xid, int depth, int width, int height, double factor) { + // HACK! Please fix renderer, should never ask for 0x0 bitmap. + width = Math.Max(1, width); + height = Math.Max(1, height); + _display = display; _xid = xid; _depth = depth; diff --git a/src/Avalonia.X11/X11Window.cs b/src/Avalonia.X11/X11Window.cs index 6ff5b96f12..919abae243 100644 --- a/src/Avalonia.X11/X11Window.cs +++ b/src/Avalonia.X11/X11Window.cs @@ -102,7 +102,7 @@ namespace Avalonia.X11 valueMask |= SetWindowValuemask.ColorMap; } - int defaultWidth = 300, defaultHeight = 200; + int defaultWidth = 0, defaultHeight = 0; if (!_popup && Screen != null) { @@ -117,6 +117,10 @@ namespace Avalonia.X11 } } + // check if the calculated size is zero then compensate to hardcoded resolution + defaultWidth = Math.Max(defaultWidth, 300); + defaultHeight = Math.Max(defaultHeight, 200); + _handle = XCreateWindow(_x11.Display, _x11.RootWindow, 10, 10, defaultWidth, defaultHeight, 0, depth, (int)CreateWindowArgs.InputOutput, @@ -133,7 +137,7 @@ namespace Avalonia.X11 _renderHandle = _handle; Handle = new PlatformHandle(_handle, "XID"); - _realSize = new PixelSize(300, 200); + _realSize = new PixelSize(defaultWidth, defaultHeight); platform.Windows[_handle] = OnEvent; XEventMask ignoredMask = XEventMask.SubstructureRedirectMask | XEventMask.ResizeRedirectMask diff --git a/src/Shared/PlatformSupport/StandardRuntimePlatform.cs b/src/Shared/PlatformSupport/StandardRuntimePlatform.cs index 8a5a725594..a23c31ca64 100644 --- a/src/Shared/PlatformSupport/StandardRuntimePlatform.cs +++ b/src/Shared/PlatformSupport/StandardRuntimePlatform.cs @@ -75,7 +75,7 @@ namespace Avalonia.Shared.PlatformSupport lock (_btlock) Backtraces.Remove(_backtrace); #endif - _plat.Free(_address, Size); + _plat?.Free(_address, Size); GC.RemoveMemoryPressure(Size); IsDisposed = true; _address = IntPtr.Zero;