diff --git a/samples/ControlCatalog.Android/ControlCatalog.Android.csproj b/samples/ControlCatalog.Android/ControlCatalog.Android.csproj index fa29610b18..41d6329d26 100644 --- a/samples/ControlCatalog.Android/ControlCatalog.Android.csproj +++ b/samples/ControlCatalog.Android/ControlCatalog.Android.csproj @@ -29,7 +29,7 @@ 4 True None - False + True False False armeabi;armeabi-v7a;x86 @@ -112,10 +112,6 @@ {7062ae20-5dcc-4442-9645-8195bdece63e} Avalonia.Diagnostics - - {4a1abb09-9047-4bd5-a4ad-a055e52c5ee0} - Avalonia.DotNetFrameworkRuntime - {5fb2b005-0a7f-4dad-add4-3ed01444e63d} Avalonia.HtmlRenderer diff --git a/src/Android/Avalonia.Android/ActivityTracker.cs b/src/Android/Avalonia.Android/ActivityTracker.cs new file mode 100644 index 0000000000..2ad1d9e361 --- /dev/null +++ b/src/Android/Avalonia.Android/ActivityTracker.cs @@ -0,0 +1,47 @@ +using Android.App; +using Android.OS; + +namespace Avalonia.Android +{ + internal class ActivityTracker : Java.Lang.Object, global::Android.App.Application.IActivityLifecycleCallbacks + { + public static Activity Current { get; private set; } + public void OnActivityCreated(Activity activity, Bundle savedInstanceState) + { + Current = activity; + } + + public void OnActivityDestroyed(Activity activity) + { + if (Current == activity) + Current = null; + } + + public void OnActivityPaused(Activity activity) + { + if (Current == activity) + Current = null; + } + + public void OnActivityResumed(Activity activity) + { + Current = activity; + } + + public void OnActivitySaveInstanceState(Activity activity, Bundle outState) + { + Current = activity; + } + + public void OnActivityStarted(Activity activity) + { + Current = activity; + } + + public void OnActivityStopped(Activity activity) + { + if (Current == activity) + Current = null; + } + } +} \ No newline at end of file diff --git a/src/Android/Avalonia.Android/AndroidPlatform.cs b/src/Android/Avalonia.Android/AndroidPlatform.cs index 5b3170a0c7..2089359c26 100644 --- a/src/Android/Avalonia.Android/AndroidPlatform.cs +++ b/src/Android/Avalonia.Android/AndroidPlatform.cs @@ -62,6 +62,8 @@ namespace Avalonia.Android .Bind().ToConstant(new AssetLoader(app.GetType().Assembly)); SkiaPlatform.Initialize(); + ((global::Android.App.Application) global::Android.App.Application.Context.ApplicationContext) + .RegisterActivityLifecycleCallbacks(new ActivityTracker()); } public IWindowImpl CreateWindow() @@ -76,7 +78,7 @@ namespace Avalonia.Android public IPopupImpl CreatePopup() { - throw new NotImplementedException(); + return new PopupImpl(); } } } \ No newline at end of file diff --git a/src/Android/Avalonia.Android/AppBuilder.cs b/src/Android/Avalonia.Android/AppBuilder.cs new file mode 100644 index 0000000000..6078e3bb98 --- /dev/null +++ b/src/Android/Avalonia.Android/AppBuilder.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using Android.App; +using Android.Content; +using Android.OS; +using Android.Runtime; +using Android.Views; +using Android.Widget; +using Avalonia.Controls; +using Avalonia.Platform; +using Avalonia.Shared.PlatformSupport; + +namespace Avalonia +{ + public sealed class AppBuilder : AppBuilderBase + { + public AppBuilder() : base(new StandardRuntimePlatform(), + builder => StandardRuntimePlatformServices.Register(builder.Instance?.GetType()?.Assembly)) + { + + } + } +} \ No newline at end of file diff --git a/src/Android/Avalonia.Android/Avalonia.Android.csproj b/src/Android/Avalonia.Android/Avalonia.Android.csproj index 0dfab3f518..3ee2f5af64 100644 --- a/src/Android/Avalonia.Android/Avalonia.Android.csproj +++ b/src/Android/Avalonia.Android/Avalonia.Android.csproj @@ -61,8 +61,10 @@ + + @@ -72,6 +74,7 @@ + diff --git a/src/Android/Avalonia.Android/AvaloniaActivity.cs b/src/Android/Avalonia.Android/AvaloniaActivity.cs index a9b04c882b..21ce555086 100644 --- a/src/Android/Avalonia.Android/AvaloniaActivity.cs +++ b/src/Android/Avalonia.Android/AvaloniaActivity.cs @@ -14,16 +14,17 @@ namespace Avalonia.Android { public abstract class AvaloniaActivity : Activity { - AvaloniaView _view; + + internal AvaloniaView View; object _content; protected override void OnCreate(Bundle savedInstanceState) { RequestWindowFeature(WindowFeatures.NoTitle); - _view = new AvaloniaView(this); + View = new AvaloniaView(this); if(_content != null) - _view.Content = _content; - SetContentView(_view); + View.Content = _content; + SetContentView(View); TakeKeyEvents(true); base.OnCreate(savedInstanceState); } @@ -37,14 +38,14 @@ namespace Avalonia.Android set { _content = value; - if (_view != null) - _view.Content = value; + if (View != null) + View.Content = value; } } public override bool DispatchKeyEvent(KeyEvent e) { - return _view.DispatchKeyEvent(e); + return View.DispatchKeyEvent(e); } } } \ No newline at end of file diff --git a/src/Android/Avalonia.Android/AvaloniaView.cs b/src/Android/Avalonia.Android/AvaloniaView.cs index 71eea14a1d..6c4274a6e4 100644 --- a/src/Android/Avalonia.Android/AvaloniaView.cs +++ b/src/Android/Avalonia.Android/AvaloniaView.cs @@ -10,6 +10,7 @@ using Android.Runtime; using Android.Views; using Android.Widget; using Avalonia.Android.Platform.SkiaPlatform; +using Avalonia.Controls; using Avalonia.Controls.Embedding; using Avalonia.Platform; @@ -23,7 +24,7 @@ namespace Avalonia.Android public AvaloniaView(Context context) : base(context) { _view = new ViewImpl(context); - AddView(_view); + AddView(_view.View); _root = new EmbeddableControlRoot(_view); _root.Prepare(); } @@ -36,7 +37,7 @@ namespace Avalonia.Android public override bool DispatchKeyEvent(KeyEvent e) { - return _view.DispatchKeyEvent(e); + return _view.View.DispatchKeyEvent(e); } class ViewImpl : TopLevelImpl, IEmbeddableWindowImpl @@ -45,8 +46,8 @@ namespace Avalonia.Android public ViewImpl(Context context) : base(context) { - Focusable = true; - FocusChange += ViewImpl_FocusChange; + View.Focusable = true; + View.FocusChange += ViewImpl_FocusChange; } private void ViewImpl_FocusChange(object sender, FocusChangeEventArgs e) @@ -54,6 +55,15 @@ namespace Avalonia.Android if(!e.HasFocus) LostFocus?.Invoke(); } + + protected override void OnResized(Size size) + { + MaxClientSize = size; + base.OnResized(size); + } + + public WindowState WindowState { get; set; } + public IDisposable ShowDialog() => null; } } } \ No newline at end of file diff --git a/src/Android/Avalonia.Android/Platform/SkiaPlatform/AndroidFramebuffer.cs b/src/Android/Avalonia.Android/Platform/SkiaPlatform/AndroidFramebuffer.cs index 982c79560b..55e729f5a2 100644 --- a/src/Android/Avalonia.Android/Platform/SkiaPlatform/AndroidFramebuffer.cs +++ b/src/Android/Avalonia.Android/Platform/SkiaPlatform/AndroidFramebuffer.cs @@ -12,7 +12,11 @@ namespace Avalonia.Android.Platform.SkiaPlatform public AndroidFramebuffer(Surface surface) { + if(surface == null) + throw new ArgumentNullException(nameof(surface)); _window = ANativeWindow_fromSurface(JNIEnv.Handle, surface.Handle); + if (_window == IntPtr.Zero) + throw new Exception("Unable to obtain ANativeWindow"); ANativeWindow_Buffer buffer; var rc = new ARect() { diff --git a/src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs b/src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs index 2213ebddcc..d2d5909815 100644 --- a/src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs +++ b/src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs @@ -18,14 +18,13 @@ namespace Avalonia.Android { public abstract class InvalidationAwareSurfaceView : SurfaceView, ISurfaceHolderCallback, IPlatformHandle { - private readonly Context _context; bool _invalidateQueued; readonly object _lock = new object(); private readonly Handler _handler; + public InvalidationAwareSurfaceView(Context context) : base(context) { - _context = context; Holder.AddCallback(this); _handler = new Handler(context.MainLooper); } @@ -38,13 +37,11 @@ namespace Avalonia.Android return; _handler.Post(() => { - lock (_lock) - { - _invalidateQueued = false; - } + if (Holder.Surface?.IsValid != true) + return; try { - Draw(); + DoDraw(); } catch (Exception e) { @@ -67,20 +64,29 @@ namespace Avalonia.Android public void SurfaceChanged(ISurfaceHolder holder, Format format, int width, int height) { Log.Info("AVALONIA", "Surface Changed"); - Draw(); + DoDraw(); } public void SurfaceCreated(ISurfaceHolder holder) { Log.Info("AVALONIA", "Surface Created"); - Draw(); + DoDraw(); } public void SurfaceDestroyed(ISurfaceHolder holder) { Log.Info("AVALONIA", "Surface Destroyed"); + } + protected void DoDraw() + { + lock (_lock) + { + _invalidateQueued = false; + } + Draw(); + } protected abstract void Draw(); public string HandleDescriptor => "SurfaceView"; } diff --git a/src/Android/Avalonia.Android/Platform/SkiaPlatform/PopupImpl.cs b/src/Android/Avalonia.Android/Platform/SkiaPlatform/PopupImpl.cs new file mode 100644 index 0000000000..e39ba2c121 --- /dev/null +++ b/src/Android/Avalonia.Android/Platform/SkiaPlatform/PopupImpl.cs @@ -0,0 +1,91 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using Android.App; +using Android.Content; +using Android.Graphics; +using Android.OS; +using Android.Runtime; +using Android.Views; +using Android.Widget; +using Avalonia.Platform; + +namespace Avalonia.Android.Platform.SkiaPlatform +{ + class PopupImpl : TopLevelImpl, IPopupImpl + { + private Point _position; + private bool _isAdded; + public PopupImpl() : base(ActivityTracker.Current, true) + { + } + + private Size _clientSize = new Size(1, 1); + public override Size ClientSize + { + get { return base.ClientSize; } + set + { + if(View == null) + return; + _clientSize = value; + UpdateParams(); + } + } + + public override Point Position + { + get { return _position; } + set + { + _position = value; + PositionChanged?.Invoke(_position); + UpdateParams(); + } + } + + WindowManagerLayoutParams CreateParams() => new WindowManagerLayoutParams(0, + WindowManagerFlags.NotTouchModal, Format.Translucent) + { + Gravity = GravityFlags.Left | GravityFlags.Top, + WindowAnimations = 0, + X = (int) _position.X, + Y = (int) _position.Y, + Width = Math.Max(1, (int) _clientSize.Width), + Height = Math.Max(1, (int) _clientSize.Height) + }; + + void UpdateParams() + { + if (_isAdded) + ActivityTracker.Current?.WindowManager?.UpdateViewLayout(View, CreateParams()); + } + + public override void Show() + { + if (_isAdded) + return; + ActivityTracker.Current.WindowManager.AddView(View, CreateParams()); + _isAdded = true; + } + + public override void Hide() + { + if (_isAdded) + { + var wm = View.Context.ApplicationContext.GetSystemService(Context.WindowService) + .JavaCast(); + wm.RemoveView(View); + _isAdded = false; + } + } + + public override void Dispose() + { + Hide(); + base.Dispose(); + } + } +} \ No newline at end of file diff --git a/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs index 26d2b0aad9..d34981b964 100644 --- a/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs +++ b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs @@ -9,42 +9,32 @@ using Avalonia.Input.Raw; using Avalonia.Platform; using System; using System.Collections.Generic; +using System.Reactive.Disposables; using Avalonia.Controls; using Avalonia.Controls.Platform.Surfaces; namespace Avalonia.Android.Platform.SkiaPlatform { - class TopLevelImpl : InvalidationAwareSurfaceView, IAndroidView, ITopLevelImpl, - ISurfaceHolderCallback, IFramebufferPlatformSurface + class TopLevelImpl : IAndroidView, ITopLevelImpl, IFramebufferPlatformSurface { - protected AndroidKeyboardEventsHelper _keyboardHelper; + private readonly AndroidKeyboardEventsHelper _keyboardHelper; + private readonly AndroidTouchEventsHelper _touchHelper; + private ViewImpl _view; - private AndroidTouchEventsHelper _touchHelper; - - public TopLevelImpl(Context context) : base(context) + public TopLevelImpl(Context context, bool placeOnTop = false) { + _view = new ViewImpl(context, this, placeOnTop); _keyboardHelper = new AndroidKeyboardEventsHelper(this); - _touchHelper = new AndroidTouchEventsHelper(this, () => InputRoot, p => GetAvaloniaPointFromEvent(p)); + _touchHelper = new AndroidTouchEventsHelper(this, () => InputRoot, + p => GetAvaloniaPointFromEvent(p)); - MaxClientSize = new Size(Resources.DisplayMetrics.WidthPixels, Resources.DisplayMetrics.HeightPixels); - ClientSize = MaxClientSize; + MaxClientSize = new Size(_view.Resources.DisplayMetrics.WidthPixels, + _view.Resources.DisplayMetrics.HeightPixels); } - - void ISurfaceHolderCallback.SurfaceChanged(ISurfaceHolder holder, Format format, int width, int height) - { - var newSize = new Size(width, height); - if (newSize != ClientSize) - { - MaxClientSize = newSize; - ClientSize = newSize; - Resized?.Invoke(ClientSize); - } - base.SurfaceChanged(holder, format, width, height); - } - + private bool _handleEvents; public bool HandleEvents @@ -56,17 +46,24 @@ namespace Avalonia.Android.Platform.SkiaPlatform _keyboardHelper.HandleEvents = _handleEvents; } } - public WindowState WindowState - { - get { return WindowState.Normal; } - set { } - } - + public virtual Point GetAvaloniaPointFromEvent(MotionEvent e) => new Point(e.GetX(), e.GetY()); public IInputRoot InputRoot { get; private set; } - public Size ClientSize { get; set; } + public virtual Size ClientSize + { + get + { + if (_view == null) + return new Size(0, 0); + return new Size(_view.Width, _view.Height); + } + set + { + + } + } public Action Closed { get; set; } @@ -74,7 +71,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform public Action Input { get; set; } - public Size MaxClientSize { get; private set; } + public Size MaxClientSize { get; protected set; } public Action Paint { get; set; } @@ -84,21 +81,21 @@ namespace Avalonia.Android.Platform.SkiaPlatform public Action PositionChanged { get; set; } - public View View => this; + public View View => _view; Action ITopLevelImpl.Activated { get; set; } - IPlatformHandle ITopLevelImpl.Handle => this; + IPlatformHandle ITopLevelImpl.Handle => _view; - public IEnumerable Surfaces => new object[] { this }; + public IEnumerable Surfaces => new object[] {this}; public void Activate() { } - public void Hide() + public virtual void Hide() { - this.Visibility = ViewStates.Invisible; + _view.Visibility = ViewStates.Invisible; } public void SetSystemDecorations(bool enabled) @@ -107,7 +104,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform public void Invalidate(Rect rect) { - if (Holder?.Surface?.IsValid == true) base.Invalidate(); + if (_view.Holder?.Surface?.IsValid == true) _view.Invalidate(); } public Point PointToClient(Point point) @@ -134,9 +131,9 @@ namespace Avalonia.Android.Platform.SkiaPlatform { } - public void Show() + public virtual void Show() { - this.Visibility = ViewStates.Visible; + _view.Visibility = ViewStates.Visible; } public void BeginMoveDrag() @@ -149,43 +146,80 @@ namespace Avalonia.Android.Platform.SkiaPlatform //Not supported } - public Point Position { get; set; } + public virtual Point Position { get; set; } public double Scaling => 1; - public IDisposable ShowDialog() + void Draw() { - throw new NotImplementedException(); + Paint?.Invoke(new Rect(new Point(0, 0), ClientSize)); } - public override bool DispatchTouchEvent(MotionEvent e) + public void SetIcon(IWindowIconImpl icon) { - bool callBase; - bool? result = _touchHelper.DispatchTouchEvent(e, out callBase); - bool baseResult = callBase ? base.DispatchTouchEvent(e) : false; - - return result != null ? result.Value : baseResult; + // No window icons for mobile platforms } - public override bool DispatchKeyEvent(KeyEvent e) + public virtual void Dispose() { - bool callBase; - bool? res = _keyboardHelper.DispatchKeyEvent(e, out callBase); - bool baseResult = callBase ? base.DispatchKeyEvent(e) : false; - - return res != null ? res.Value : baseResult; + _view.Dispose(); + _view = null; } - - protected override void Draw() + + protected virtual void OnResized(Size size) { - Paint?.Invoke(new Rect(new Point(0, 0), ClientSize)); + Resized?.Invoke(size); } - public void SetIcon(IWindowIconImpl icon) + class ViewImpl : InvalidationAwareSurfaceView, ISurfaceHolderCallback { - // No window icons for mobile platforms + private readonly TopLevelImpl _tl; + private Size _oldSize; + public ViewImpl(Context context, TopLevelImpl tl, bool placeOnTop) : base(context) + { + _tl = tl; + if (placeOnTop) + SetZOrderOnTop(true); + } + + protected override void Draw() + { + _tl.Draw(); + } + + public override bool DispatchTouchEvent(MotionEvent e) + { + bool callBase; + bool? result = _tl._touchHelper.DispatchTouchEvent(e, out callBase); + bool baseResult = callBase ? base.DispatchTouchEvent(e) : false; + + return result != null ? result.Value : baseResult; + } + + public override bool DispatchKeyEvent(KeyEvent e) + { + bool callBase; + bool? res = _tl._keyboardHelper.DispatchKeyEvent(e, out callBase); + bool baseResult = callBase ? base.DispatchKeyEvent(e) : false; + + return res != null ? res.Value : baseResult; + } + + + void ISurfaceHolderCallback.SurfaceChanged(ISurfaceHolder holder, Format format, int width, int height) + { + var newSize = new Size(width, height); + + if (newSize != _oldSize) + { + _oldSize = newSize; + _tl.OnResized(newSize); + } + + base.SurfaceChanged(holder, format, width, height); + } } - ILockedFramebuffer IFramebufferPlatformSurface.Lock()=>new AndroidFramebuffer(Holder.Surface); + ILockedFramebuffer IFramebufferPlatformSurface.Lock()=>new AndroidFramebuffer(_view.Holder.Surface); } } \ No newline at end of file diff --git a/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidKeyboardEventsHelper.cs b/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidKeyboardEventsHelper.cs index 7bac0ff814..ab990066de 100644 --- a/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidKeyboardEventsHelper.cs +++ b/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidKeyboardEventsHelper.cs @@ -12,7 +12,7 @@ using System.ComponentModel; namespace Avalonia.Android.Platform.Specific.Helpers { - public class AndroidKeyboardEventsHelper : IDisposable where TView : View, ITopLevelImpl, IAndroidView + public class AndroidKeyboardEventsHelper : IDisposable where TView :ITopLevelImpl, IAndroidView { private TView _view; private IInputElement _lastFocusedElement; @@ -90,7 +90,7 @@ namespace Avalonia.Android.Platform.Specific.Helpers private void TryShowHideKeyboard(IInputElement element, bool value) { - var input = _view.Context.GetSystemService(Context.InputMethodService).JavaCast(); + var input = _view.View.Context.GetSystemService(Context.InputMethodService).JavaCast(); if (value) { @@ -102,7 +102,7 @@ namespace Avalonia.Android.Platform.Specific.Helpers else { //hide keyboard - input.HideSoftInputFromWindow(_view.WindowToken, HideSoftInputFlags.None); + input.HideSoftInputFromWindow(_view.View.WindowToken, HideSoftInputFlags.None); } } diff --git a/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidTouchEventsHelper.cs b/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidTouchEventsHelper.cs index a448044ee6..702829b91c 100644 --- a/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidTouchEventsHelper.cs +++ b/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidTouchEventsHelper.cs @@ -8,7 +8,7 @@ using System; namespace Avalonia.Android.Platform.Specific.Helpers { - public class AndroidTouchEventsHelper : IDisposable where TView : View, ITopLevelImpl, IAndroidView + public class AndroidTouchEventsHelper : IDisposable where TView : ITopLevelImpl, IAndroidView { private TView _view; public bool HandleEvents { get; set; } @@ -63,10 +63,10 @@ namespace Avalonia.Android.Platform.Specific.Helpers //if point is in view otherwise it's possible avalonia not to find the proper window to dispatch the event _point = _getPointFunc(e); - double x = _view.GetX(); - double y = _view.GetY(); - double r = x + _view.Width; - double b = y + _view.Height; + double x = _view.View.GetX(); + double y = _view.View.GetY(); + double r = x + _view.View.Width; + double b = y + _view.View.Height; if (x <= _point.X && r >= _point.X && y <= _point.Y && b >= _point.Y) { diff --git a/src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj b/src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj index 0e94cecc2d..d09f162150 100644 --- a/src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj +++ b/src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj @@ -171,10 +171,6 @@ {3e10a5fa-e8da-48b1-ad44-6a5b6cb7750f} Avalonia.Themes.Default - - {4a1abb09-9047-4bd5-a4ad-a055e52c5ee0} - Avalonia.DotNetFrameworkRuntime - {5fb2b005-0a7f-4dad-add4-3ed01444e63d} Avalonia.HtmlRenderer diff --git a/src/Avalonia.Controls/AppBuilderBase.cs b/src/Avalonia.Controls/AppBuilderBase.cs index c53cca19d1..b098c270a5 100644 --- a/src/Avalonia.Controls/AppBuilderBase.cs +++ b/src/Avalonia.Controls/AppBuilderBase.cs @@ -60,10 +60,10 @@ namespace Avalonia.Controls /// public Action BeforeStartCallback { get; private set; } = builder => { }; - protected AppBuilderBase(IRuntimePlatform platform, Action platformSevices) + protected AppBuilderBase(IRuntimePlatform platform, Action platformSevices) { RuntimePlatform = platform; - RuntimePlatformServicesInitializer = platformSevices; + RuntimePlatformServicesInitializer = () => platformSevices((TAppBuilder)this); } /// diff --git a/src/Avalonia.DotNetCoreRuntime/AppBuilder.cs b/src/Avalonia.DotNetCoreRuntime/AppBuilder.cs index 5a6b82573b..2b9b3083b1 100644 --- a/src/Avalonia.DotNetCoreRuntime/AppBuilder.cs +++ b/src/Avalonia.DotNetCoreRuntime/AppBuilder.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Reflection; using System.Text; using System.Threading.Tasks; using Avalonia.Controls; @@ -15,7 +16,9 @@ namespace Avalonia /// Initializes a new instance of the class. /// public AppBuilder() - : base(new StandardRuntimePlatform(), () => StandardRuntimePlatformServices.Register()) + : base(new StandardRuntimePlatform(), + builder => StandardRuntimePlatformServices.Register(builder.Instance?.GetType() + ?.GetTypeInfo().Assembly)) { } diff --git a/src/Avalonia.DotNetFrameworkRuntime/AppBuilder.cs b/src/Avalonia.DotNetFrameworkRuntime/AppBuilder.cs index 3385e25d4f..f643bfe6e2 100644 --- a/src/Avalonia.DotNetFrameworkRuntime/AppBuilder.cs +++ b/src/Avalonia.DotNetFrameworkRuntime/AppBuilder.cs @@ -17,7 +17,8 @@ namespace Avalonia /// Initializes a new instance of the class. /// public AppBuilder() - : base(new StandardRuntimePlatform(), () => StandardRuntimePlatformServices.Register()) + : base(new StandardRuntimePlatform(), + builder => StandardRuntimePlatformServices.Register(builder.Instance?.GetType()?.Assembly)) { } diff --git a/src/Skia/Avalonia.Skia/BitmapImpl.cs b/src/Skia/Avalonia.Skia/BitmapImpl.cs index 232f2721e1..7d99156a1d 100644 --- a/src/Skia/Avalonia.Skia/BitmapImpl.cs +++ b/src/Skia/Avalonia.Skia/BitmapImpl.cs @@ -63,7 +63,10 @@ namespace Avalonia.Skia private static SKSurface CreateSurface(SKBitmap bitmap) { IntPtr length; - return SKSurface.Create(bitmap.Info, bitmap.GetPixels(out length), bitmap.RowBytes); + var rv = SKSurface.Create(bitmap.Info, bitmap.GetPixels(out length), bitmap.RowBytes); + if (rv == null) + throw new Exception("Unable to create Skia surface"); + return rv; } public BitmapDrawingContext(SKSurface surface) : base(surface.Canvas)