Browse Source

Merge branch 'master' into skia-post-transform

Jeremy Koritzinsky 8 years ago
parent
commit
42f0c7b792

+ 1 - 5
samples/ControlCatalog.Android/ControlCatalog.Android.csproj

@@ -29,7 +29,7 @@
     <WarningLevel>4</WarningLevel>
     <AndroidUseSharedRuntime>True</AndroidUseSharedRuntime>
     <AndroidLinkMode>None</AndroidLinkMode>
-    <EmbedAssembliesIntoApk>False</EmbedAssembliesIntoApk>
+    <EmbedAssembliesIntoApk>True</EmbedAssembliesIntoApk>
     <BundleAssemblies>False</BundleAssemblies>
     <AndroidCreatePackagePerAbi>False</AndroidCreatePackagePerAbi>
     <AndroidSupportedAbis>armeabi;armeabi-v7a;x86</AndroidSupportedAbis>
@@ -112,10 +112,6 @@
       <Project>{7062ae20-5dcc-4442-9645-8195bdece63e}</Project>
       <Name>Avalonia.Diagnostics</Name>
     </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.DotNetFrameworkRuntime\Avalonia.DotNetFrameworkRuntime.csproj">
-      <Project>{4a1abb09-9047-4bd5-a4ad-a055e52c5ee0}</Project>
-      <Name>Avalonia.DotNetFrameworkRuntime</Name>
-    </ProjectReference>
     <ProjectReference Include="..\..\src\Avalonia.HtmlRenderer\Avalonia.HtmlRenderer.csproj">
       <Project>{5fb2b005-0a7f-4dad-add4-3ed01444e63d}</Project>
       <Name>Avalonia.HtmlRenderer</Name>

+ 47 - 0
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;
+        }
+    }
+}

+ 3 - 1
src/Android/Avalonia.Android/AndroidPlatform.cs

@@ -62,6 +62,8 @@ namespace Avalonia.Android
                 .Bind<IAssetLoader>().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();
         }
     }
 }

+ 26 - 0
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<AppBuilder>
+    {
+        public AppBuilder() : base(new StandardRuntimePlatform(),
+            builder => StandardRuntimePlatformServices.Register(builder.Instance?.GetType()?.Assembly))
+        {
+
+        }
+    }
+}

+ 3 - 0
src/Android/Avalonia.Android/Avalonia.Android.csproj

@@ -61,8 +61,10 @@
     <Reference Include="System.Xml" />
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="ActivityTracker.cs" />
     <Compile Include="AndroidPlatform.cs" />
     <Compile Include="AndroidThreadingInterface.cs" />
+    <Compile Include="AppBuilder.cs" />
     <Compile Include="AvaloniaActivity.cs" />
     <Compile Include="AvaloniaView.cs" />
     <Compile Include="PlatformIconLoader.cs" />
@@ -72,6 +74,7 @@
     <Compile Include="Platform\Input\AndroidMouseDevice.cs" />
     <Compile Include="Platform\SkiaPlatform\AndroidFramebuffer.cs" />
     <Compile Include="Platform\SkiaPlatform\InvalidationAwareSurfaceView.cs" />
+    <Compile Include="Platform\SkiaPlatform\PopupImpl.cs" />
     <Compile Include="Platform\SkiaPlatform\TopLevelImpl.cs" />
     <Compile Include="Platform\Specific\IAndroidView.cs" />
     <Compile Include="Platform\Specific\Helpers\AndroidTouchEventsHelper.cs" />

+ 8 - 7
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);
         }
     }
 }

+ 14 - 4
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;
         }
     }
 }

+ 4 - 0
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()
             {

+ 15 - 9
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";
     }

+ 91 - 0
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<IWindowManager>();
+                wm.RemoveView(View);
+                _isAdded = false;
+            }
+        }
+
+        public override void Dispose()
+        {
+            Hide();
+            base.Dispose();
+        }
+    }
+}

+ 93 - 59
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<TopLevelImpl> _keyboardHelper;
+        private readonly AndroidKeyboardEventsHelper<TopLevelImpl> _keyboardHelper;
+        private readonly AndroidTouchEventsHelper<TopLevelImpl> _touchHelper;
+        private ViewImpl _view;
 
-        private AndroidTouchEventsHelper<TopLevelImpl> _touchHelper;
-
-        public TopLevelImpl(Context context) : base(context)
+        public TopLevelImpl(Context context, bool placeOnTop = false)
         {
+            _view = new ViewImpl(context, this, placeOnTop);
             _keyboardHelper = new AndroidKeyboardEventsHelper<TopLevelImpl>(this);
-            _touchHelper = new AndroidTouchEventsHelper<TopLevelImpl>(this, () => InputRoot, p => GetAvaloniaPointFromEvent(p));
+            _touchHelper = new AndroidTouchEventsHelper<TopLevelImpl>(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<RawInputEventArgs> Input { get; set; }
 
-        public Size MaxClientSize { get; private set; }
+        public Size MaxClientSize { get; protected set; }
 
         public Action<Rect> Paint { get; set; }
 
@@ -84,21 +81,21 @@ namespace Avalonia.Android.Platform.SkiaPlatform
 
         public Action<Point> 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<object> Surfaces => new object[] { this };
+        public IEnumerable<object> 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);
     }
 }

+ 3 - 3
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<TView> : IDisposable where TView : View, ITopLevelImpl, IAndroidView
+    public class AndroidKeyboardEventsHelper<TView> : 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<InputMethodManager>();
+            var input = _view.View.Context.GetSystemService(Context.InputMethodService).JavaCast<InputMethodManager>();
 
             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);
             }
         }
 

+ 5 - 5
src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidTouchEventsHelper.cs

@@ -8,7 +8,7 @@ using System;
 
 namespace Avalonia.Android.Platform.Specific.Helpers
 {
-    public class AndroidTouchEventsHelper<TView> : IDisposable where TView : View, ITopLevelImpl, IAndroidView
+    public class AndroidTouchEventsHelper<TView> : 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)
                 {

+ 0 - 4
src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj

@@ -171,10 +171,6 @@
       <Project>{3e10a5fa-e8da-48b1-ad44-6a5b6cb7750f}</Project>
       <Name>Avalonia.Themes.Default</Name>
     </ProjectReference>
-    <ProjectReference Include="..\..\Avalonia.DotNetFrameworkRuntime\Avalonia.DotNetFrameworkRuntime.csproj">
-      <Project>{4a1abb09-9047-4bd5-a4ad-a055e52c5ee0}</Project>
-      <Name>Avalonia.DotNetFrameworkRuntime</Name>
-    </ProjectReference>
     <ProjectReference Include="..\..\Avalonia.HtmlRenderer\Avalonia.HtmlRenderer.csproj">
       <Project>{5fb2b005-0a7f-4dad-add4-3ed01444e63d}</Project>
       <Name>Avalonia.HtmlRenderer</Name>

+ 2 - 2
src/Avalonia.Controls/AppBuilderBase.cs

@@ -60,10 +60,10 @@ namespace Avalonia.Controls
         /// </summary>
         public Action<TAppBuilder> BeforeStartCallback { get; private set; } = builder => { };
 
-        protected AppBuilderBase(IRuntimePlatform platform, Action platformSevices)
+        protected AppBuilderBase(IRuntimePlatform platform, Action<TAppBuilder> platformSevices)
         {
             RuntimePlatform = platform;
-            RuntimePlatformServicesInitializer = platformSevices;
+            RuntimePlatformServicesInitializer = () => platformSevices((TAppBuilder)this);
         }
 
         /// <summary>

+ 4 - 1
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 <see cref="AppBuilder"/> class.
         /// </summary>
         public AppBuilder()
-            : base(new StandardRuntimePlatform(), () => StandardRuntimePlatformServices.Register())
+            : base(new StandardRuntimePlatform(),
+                  builder => StandardRuntimePlatformServices.Register(builder.Instance?.GetType()
+                      ?.GetTypeInfo().Assembly))
         {
         }
 

+ 2 - 1
src/Avalonia.DotNetFrameworkRuntime/AppBuilder.cs

@@ -17,7 +17,8 @@ namespace Avalonia
         /// Initializes a new instance of the <see cref="AppBuilder"/> class.
         /// </summary>
         public AppBuilder()
-            : base(new StandardRuntimePlatform(), () => StandardRuntimePlatformServices.Register())
+            : base(new StandardRuntimePlatform(),
+                builder => StandardRuntimePlatformServices.Register(builder.Instance?.GetType()?.Assembly))
         {
         }
 

+ 4 - 1
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)