diff --git a/Avalonia.sln b/Avalonia.sln index a6fdcbd421..241ba1383c 100644 --- a/Avalonia.sln +++ b/Avalonia.sln @@ -99,8 +99,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Skia.Desktop", "sr EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Skia.Android", "src\Skia\Avalonia.Skia.Android\Avalonia.Skia.Android.csproj", "{BD43F7C0-396B-4AA1-BAD9-DFDE54D51298}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Skia.Android.TestApp", "src\Skia\Avalonia.Skia.Android.TestApp\Avalonia.Skia.Android.TestApp.csproj", "{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Skia.iOS.TestApp", "src\Skia\Avalonia.Skia.iOS.TestApp\Avalonia.Skia.iOS.TestApp.csproj", "{DA49C5F3-BE95-461C-B999-072128CCF59E}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Skia.iOS", "src\Skia\Avalonia.Skia.iOS\Avalonia.Skia.iOS.csproj", "{47BE08A7-5985-410B-9FFC-2264B8EA595F}" @@ -1469,38 +1467,6 @@ Global {BD43F7C0-396B-4AA1-BAD9-DFDE54D51298}.Release|Mono.ActiveCfg = Release|Any CPU {BD43F7C0-396B-4AA1-BAD9-DFDE54D51298}.Release|x86.ActiveCfg = Release|Any CPU {BD43F7C0-396B-4AA1-BAD9-DFDE54D51298}.Release|x86.Build.0 = Release|Any CPU - {F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU - {F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU - {F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU - {F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Ad-Hoc|Mono.ActiveCfg = Debug|Any CPU - {F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU - {F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Ad-Hoc|x86.Build.0 = Debug|Any CPU - {F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Ad-Hoc|x86.Deploy.0 = Debug|Any CPU - {F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.AppStore|Any CPU.ActiveCfg = Release|Any CPU - {F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.AppStore|iPhone.ActiveCfg = Release|Any CPU - {F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU - {F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.AppStore|Mono.ActiveCfg = Debug|Any CPU - {F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.AppStore|x86.ActiveCfg = Debug|Any CPU - {F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.AppStore|x86.Build.0 = Debug|Any CPU - {F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.AppStore|x86.Deploy.0 = Debug|Any CPU - {F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Debug|Any CPU.Deploy.0 = Debug|Any CPU - {F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Debug|Mono.ActiveCfg = Debug|Any CPU - {F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Debug|x86.ActiveCfg = Debug|Any CPU - {F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Debug|x86.Build.0 = Debug|Any CPU - {F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Debug|x86.Deploy.0 = Debug|Any CPU - {F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Release|Any CPU.Build.0 = Release|Any CPU - {F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Release|Any CPU.Deploy.0 = Release|Any CPU - {F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Release|iPhone.ActiveCfg = Release|Any CPU - {F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU - {F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Release|Mono.ActiveCfg = Release|Any CPU - {F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Release|x86.ActiveCfg = Release|Any CPU - {F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Release|x86.Build.0 = Release|Any CPU - {F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Release|x86.Deploy.0 = Release|Any CPU {DA49C5F3-BE95-461C-B999-072128CCF59E}.Ad-Hoc|Any CPU.ActiveCfg = Ad-Hoc|iPhone {DA49C5F3-BE95-461C-B999-072128CCF59E}.Ad-Hoc|iPhone.ActiveCfg = Ad-Hoc|iPhone {DA49C5F3-BE95-461C-B999-072128CCF59E}.Ad-Hoc|iPhone.Build.0 = Ad-Hoc|iPhone @@ -2359,7 +2325,6 @@ Global {2F59F3D0-748D-4652-B01E-E0D954756308} = {3743B0F2-CC41-4F14-A8C8-267F579BF91E} {925DD807-B651-475F-9F7C-CBEB974CE43D} = {3743B0F2-CC41-4F14-A8C8-267F579BF91E} {BD43F7C0-396B-4AA1-BAD9-DFDE54D51298} = {3743B0F2-CC41-4F14-A8C8-267F579BF91E} - {F92E55A5-ED73-4CCB-AB4B-0541B6757F31} = {3743B0F2-CC41-4F14-A8C8-267F579BF91E} {DA49C5F3-BE95-461C-B999-072128CCF59E} = {3743B0F2-CC41-4F14-A8C8-267F579BF91E} {47BE08A7-5985-410B-9FFC-2264B8EA595F} = {3743B0F2-CC41-4F14-A8C8-267F579BF91E} {7B92AF71-6287-4693-9DCB-BD5B6E927E23} = {7CF9789C-F1D3-4D0E-90E5-F1DF67A2753F} diff --git a/samples/ControlCatalog.Android/ControlCatalog.Android.csproj b/samples/ControlCatalog.Android/ControlCatalog.Android.csproj index 5b39aa3dfb..fa29610b18 100644 --- a/samples/ControlCatalog.Android/ControlCatalog.Android.csproj +++ b/samples/ControlCatalog.Android/ControlCatalog.Android.csproj @@ -32,9 +32,12 @@ False False False - armeabi,armeabi-v7a,x86 + armeabi;armeabi-v7a;x86 Xamarin False + False + False + False pdbonly diff --git a/samples/ControlCatalog.Android/MainActivity.cs b/samples/ControlCatalog.Android/MainActivity.cs index 3f357b0e70..157609088f 100644 --- a/samples/ControlCatalog.Android/MainActivity.cs +++ b/samples/ControlCatalog.Android/MainActivity.cs @@ -1,9 +1,8 @@ using System; using Android.App; - using Android.OS; using Android.Content.PM; -using Avalonia.Android.Platform.Specific; +using Avalonia.Android; using Avalonia.Controls; using Avalonia.Controls.Templates; using Avalonia.Markup.Xaml; @@ -17,29 +16,16 @@ namespace ControlCatalog.Android [Activity(Label = "ControlCatalog.Android", MainLauncher = true, Icon = "@drawable/icon", LaunchMode = LaunchMode.SingleInstance)] public class MainActivity : AvaloniaActivity { - public MainActivity() : base(typeof (App)) - { - - } - protected override void OnCreate(Bundle savedInstanceState) { - base.OnCreate(savedInstanceState); - - App app; - if (Avalonia.Application.Current != null) - app = (App)Avalonia.Application.Current; - else + if (Avalonia.Application.Current == null) { - app = new App(); - AppBuilder.Configure(app) + AppBuilder.Configure(new App()) .UseAndroid() - .UseSkia() .SetupWithoutStarting(); + Content = new MainView(); } - - var mainWindow = new MainWindow(); - app.Run(mainWindow); + base.OnCreate(savedInstanceState); } } } diff --git a/src/Android/Avalonia.Android/AndroidPlatform.cs b/src/Android/Avalonia.Android/AndroidPlatform.cs index afaa314e6c..5b3170a0c7 100644 --- a/src/Android/Avalonia.Android/AndroidPlatform.cs +++ b/src/Android/Avalonia.Android/AndroidPlatform.cs @@ -1,5 +1,8 @@ using System; using System.IO; +using System.Linq; +using Android.Content; +using Android.Views; using Avalonia.Android.Platform; using Avalonia.Android.Platform.Input; using Avalonia.Android.Platform.SkiaPlatform; @@ -8,6 +11,7 @@ using Avalonia.Controls.Platform; using Avalonia.Input; using Avalonia.Input.Platform; using Avalonia.Platform; +using Avalonia.Rendering; using Avalonia.Shared.PlatformSupport; using Avalonia.Skia; @@ -17,7 +21,8 @@ namespace Avalonia { public static T UseAndroid(this T builder) where T : AppBuilderBase, new() { - builder.UseWindowingSubsystem(Android.AndroidPlatform.Initialize, "Android"); + builder.UseWindowingSubsystem(() => Android.AndroidPlatform.Initialize(builder.Instance), "Android"); + builder.UseSkia(); return builder; } } @@ -25,7 +30,7 @@ namespace Avalonia namespace Avalonia.Android { - public class AndroidPlatform : IPlatformSettings, IWindowingPlatform + class AndroidPlatform : IPlatformSettings, IWindowingPlatform { public static readonly AndroidPlatform Instance = new AndroidPlatform(); public Size DoubleClickSize => new Size(4, 4); @@ -40,7 +45,7 @@ namespace Avalonia.Android _scalingFactor = global::Android.App.Application.Context.Resources.DisplayMetrics.ScaledDensity; } - public static void Initialize() + public static void Initialize(Avalonia.Application app) { AvaloniaLocator.CurrentMutable .Bind().ToTransient() @@ -51,24 +56,22 @@ namespace Avalonia.Android .Bind().ToConstant(new AndroidThreadingInterface()) .Bind().ToTransient() .Bind().ToConstant(Instance) - .Bind().ToSingleton(); + .Bind().ToSingleton() + .Bind().ToConstant(new DefaultRenderLoop(60)) - SkiaPlatform.Initialize(); - } + .Bind().ToConstant(new AssetLoader(app.GetType().Assembly)); - public void Init(Type applicationType) - { - StandardRuntimePlatformServices.Register(applicationType.Assembly); + SkiaPlatform.Initialize(); } public IWindowImpl CreateWindow() { - return new WindowImpl(); + throw new NotSupportedException(); } public IEmbeddableWindowImpl CreateEmbeddableWindow() { - throw new NotImplementedException(); + throw new NotSupportedException(); } public IPopupImpl CreatePopup() diff --git a/src/Android/Avalonia.Android/AndroidThreadingInterface.cs b/src/Android/Avalonia.Android/AndroidThreadingInterface.cs index b4059e3114..6327be12a5 100644 --- a/src/Android/Avalonia.Android/AndroidThreadingInterface.cs +++ b/src/Android/Avalonia.Android/AndroidThreadingInterface.cs @@ -51,10 +51,16 @@ namespace Avalonia.Android scheduled = true; EnsureInvokeOnMainThread(() => { - tick(); - lock (l) + try { - scheduled = false; + tick(); + } + finally + { + lock (l) + { + scheduled = false; + } } }); } diff --git a/src/Android/Avalonia.Android/Avalonia.Android.csproj b/src/Android/Avalonia.Android/Avalonia.Android.csproj index 654cb13678..0dfab3f518 100644 --- a/src/Android/Avalonia.Android/Avalonia.Android.csproj +++ b/src/Android/Avalonia.Android/Avalonia.Android.csproj @@ -63,16 +63,17 @@ + + - - + + + - - diff --git a/src/Android/Avalonia.Android/AvaloniaActivity.cs b/src/Android/Avalonia.Android/AvaloniaActivity.cs new file mode 100644 index 0000000000..a9b04c882b --- /dev/null +++ b/src/Android/Avalonia.Android/AvaloniaActivity.cs @@ -0,0 +1,50 @@ +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; + +namespace Avalonia.Android +{ + public abstract class AvaloniaActivity : Activity + { + AvaloniaView _view; + object _content; + + protected override void OnCreate(Bundle savedInstanceState) + { + RequestWindowFeature(WindowFeatures.NoTitle); + _view = new AvaloniaView(this); + if(_content != null) + _view.Content = _content; + SetContentView(_view); + TakeKeyEvents(true); + base.OnCreate(savedInstanceState); + } + + public object Content + { + get + { + return _content; + } + set + { + _content = value; + if (_view != null) + _view.Content = value; + } + } + + public override bool DispatchKeyEvent(KeyEvent 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 new file mode 100644 index 0000000000..71eea14a1d --- /dev/null +++ b/src/Android/Avalonia.Android/AvaloniaView.cs @@ -0,0 +1,59 @@ +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.Android.Platform.SkiaPlatform; +using Avalonia.Controls.Embedding; +using Avalonia.Platform; + +namespace Avalonia.Android +{ + public class AvaloniaView : FrameLayout + { + private readonly EmbeddableControlRoot _root; + private readonly ViewImpl _view; + + public AvaloniaView(Context context) : base(context) + { + _view = new ViewImpl(context); + AddView(_view); + _root = new EmbeddableControlRoot(_view); + _root.Prepare(); + } + + public object Content + { + get { return _root.Content; } + set { _root.Content = value; } + } + + public override bool DispatchKeyEvent(KeyEvent e) + { + return _view.DispatchKeyEvent(e); + } + + class ViewImpl : TopLevelImpl, IEmbeddableWindowImpl + { + public event Action LostFocus; + + public ViewImpl(Context context) : base(context) + { + Focusable = true; + FocusChange += ViewImpl_FocusChange; + } + + private void ViewImpl_FocusChange(object sender, FocusChangeEventArgs e) + { + if(!e.HasFocus) + LostFocus?.Invoke(); + } + } + } +} \ 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 new file mode 100644 index 0000000000..982c79560b --- /dev/null +++ b/src/Android/Avalonia.Android/Platform/SkiaPlatform/AndroidFramebuffer.cs @@ -0,0 +1,101 @@ +using System; +using System.Runtime.InteropServices; +using Android.Runtime; +using Android.Views; +using Avalonia.Controls.Platform.Surfaces; + +namespace Avalonia.Android.Platform.SkiaPlatform +{ + class AndroidFramebuffer : ILockedFramebuffer + { + private IntPtr _window; + + public AndroidFramebuffer(Surface surface) + { + _window = ANativeWindow_fromSurface(JNIEnv.Handle, surface.Handle); + ANativeWindow_Buffer buffer; + var rc = new ARect() + { + right = Width = ANativeWindow_getWidth(_window), + bottom = Height = ANativeWindow_getHeight(_window) + }; + ANativeWindow_lock(_window, out buffer, ref rc); + + Format = buffer.format == AndroidPixelFormat.WINDOW_FORMAT_RGB_565 + ? PixelFormat.Rgb565 : PixelFormat.Rgba8888; + + RowBytes = buffer.stride * (Format == PixelFormat.Rgb565 ? 2 : 4); + Address = buffer.bits; + } + + public void Dispose() + { + ANativeWindow_unlockAndPost(_window); + ANativeWindow_release(_window); + _window = IntPtr.Zero; + Address = IntPtr.Zero; + } + + public IntPtr Address { get; set; } + public int Width { get; } + public int Height { get; } + public int RowBytes { get; } + public Size Dpi { get; } = new Size(96, 96); + public PixelFormat Format { get; } + + [DllImport("android")] + internal static extern IntPtr ANativeWindow_fromSurface(IntPtr jniEnv, IntPtr handle); + [DllImport("android")] + internal static extern int ANativeWindow_getWidth(IntPtr window); + [DllImport("android")] + internal static extern int ANativeWindow_getHeight(IntPtr window); + [DllImport("android")] + internal static extern void ANativeWindow_release(IntPtr window); + [DllImport("android")] + internal static extern void ANativeWindow_unlockAndPost(IntPtr window); + + [DllImport("android")] + internal static extern int ANativeWindow_lock(IntPtr window, out ANativeWindow_Buffer outBuffer, ref ARect inOutDirtyBounds); + public enum AndroidPixelFormat + { + WINDOW_FORMAT_RGBA_8888 = 1, + WINDOW_FORMAT_RGBX_8888 = 2, + WINDOW_FORMAT_RGB_565 = 4, + } + + internal struct ARect + { + public int left; + public int top; + public int right; + public int bottom; + } + + internal struct ANativeWindow_Buffer + { + // The number of pixels that are show horizontally. + public int width; + + // The number of pixels that are shown vertically. + public int height; + + // The number of *pixels* that a line in the buffer takes in + // memory. This may be >= width. + public int stride; + + // The format of the buffer. One of WINDOW_FORMAT_* + public AndroidPixelFormat format; + + // The actual bits. + public IntPtr bits; + + // Do not touch. + uint reserved1; + uint reserved2; + uint reserved3; + uint reserved4; + uint reserved5; + uint reserved6; + } + } +} \ No newline at end of file diff --git a/src/Skia/Avalonia.Skia.Android/SkiaView.cs b/src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs similarity index 88% rename from src/Skia/Avalonia.Skia.Android/SkiaView.cs rename to src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs index a45a80cf18..2213ebddcc 100644 --- a/src/Skia/Avalonia.Skia.Android/SkiaView.cs +++ b/src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs @@ -14,16 +14,16 @@ using Android.Widget; using Avalonia.Media; using Avalonia.Platform; -namespace Avalonia.Skia.Android +namespace Avalonia.Android { - public abstract class SkiaView : SurfaceView, ISurfaceHolderCallback, IPlatformHandle + public abstract class InvalidationAwareSurfaceView : SurfaceView, ISurfaceHolderCallback, IPlatformHandle { - private readonly Activity _context; + private readonly Context _context; bool _invalidateQueued; readonly object _lock = new object(); private readonly Handler _handler; - public SkiaView(Activity context) : base(context) + public InvalidationAwareSurfaceView(Context context) : base(context) { _context = context; Holder.AddCallback(this); diff --git a/src/Android/Avalonia.Android/Platform/SkiaPlatform/MainWindowImpl.cs b/src/Android/Avalonia.Android/Platform/SkiaPlatform/MainWindowImpl.cs deleted file mode 100644 index 690c509b53..0000000000 --- a/src/Android/Avalonia.Android/Platform/SkiaPlatform/MainWindowImpl.cs +++ /dev/null @@ -1,44 +0,0 @@ -using Android.Views; -using Avalonia.Android.Platform.Specific; -using Avalonia.Controls; -using Avalonia.Input; -using Avalonia.Platform; - -namespace Avalonia.Android.Platform.SkiaPlatform -{ - public class MainWindowImpl : - WindowImpl - , IWindowImpl - { - public MainWindowImpl() - { - } - - public new WindowState WindowState - { - get { return WindowState.Normal; } - set { } - } - - protected override void Init() - { - base.Init(); - - HandleEvents = true; - _keyboardHelper.ActivateAutoShowKeybord(); - } - - void ITopLevelImpl.Show() - { - (Parent as ViewGroup)?.RemoveAllViews(); - AvaloniaLocator.Current.GetService().ContentView = this; - //this.Visibility = ViewStates.Visible; - } - - void ITopLevelImpl.SetInputRoot(IInputRoot inputRoot) - { - base.SetInputRoot(inputRoot); - _keyboardHelper.UpdateKeyboardState(inputRoot); - } - } -} \ No newline at end of file diff --git a/src/Android/Avalonia.Android/Platform/SkiaPlatform/WindowImpl.cs b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs similarity index 85% rename from src/Android/Avalonia.Android/Platform/SkiaPlatform/WindowImpl.cs rename to src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs index 17b1cfba0a..26d2b0aad9 100644 --- a/src/Android/Avalonia.Android/Platform/SkiaPlatform/WindowImpl.cs +++ b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs @@ -7,32 +7,30 @@ using Avalonia.Android.Platform.Specific.Helpers; using Avalonia.Input; using Avalonia.Input.Raw; using Avalonia.Platform; -using Avalonia.Skia.Android; using System; using System.Collections.Generic; using Avalonia.Controls; +using Avalonia.Controls.Platform.Surfaces; namespace Avalonia.Android.Platform.SkiaPlatform { - public class WindowImpl : SkiaView, IAndroidView, IWindowImpl, ISurfaceHolderCallback + class TopLevelImpl : InvalidationAwareSurfaceView, IAndroidView, ITopLevelImpl, + ISurfaceHolderCallback, IFramebufferPlatformSurface + { - protected AndroidKeyboardEventsHelper _keyboardHelper; + protected AndroidKeyboardEventsHelper _keyboardHelper; - private AndroidTouchEventsHelper _touchHelper; + private AndroidTouchEventsHelper _touchHelper; - public WindowImpl(Context context) : base((Activity)context) + public TopLevelImpl(Context context) : base(context) { - _keyboardHelper = new AndroidKeyboardEventsHelper(this); - _touchHelper = new AndroidTouchEventsHelper(this, () => InputRoot, p => GetAvaloniaPointFromEvent(p)); + _keyboardHelper = new AndroidKeyboardEventsHelper(this); + _touchHelper = new AndroidTouchEventsHelper(this, () => InputRoot, p => GetAvaloniaPointFromEvent(p)); MaxClientSize = new Size(Resources.DisplayMetrics.WidthPixels, Resources.DisplayMetrics.HeightPixels); ClientSize = MaxClientSize; - Init(); - } - - public WindowImpl() : this(AvaloniaLocator.Current.GetService().Activity) - { } + void ISurfaceHolderCallback.SurfaceChanged(ISurfaceHolder holder, Format format, int width, int height) { @@ -46,11 +44,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform base.SurfaceChanged(holder, format, width, height); } - - protected virtual void Init() - { - } - + private bool _handleEvents; public bool HandleEvents @@ -191,5 +185,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform { // No window icons for mobile platforms } - } + + ILockedFramebuffer IFramebufferPlatformSurface.Lock()=>new AndroidFramebuffer(Holder.Surface); + } } \ No newline at end of file diff --git a/src/Android/Avalonia.Android/Platform/Specific/AvaloniaActivity.cs b/src/Android/Avalonia.Android/Platform/Specific/AvaloniaActivity.cs deleted file mode 100644 index 4ccff10455..0000000000 --- a/src/Android/Avalonia.Android/Platform/Specific/AvaloniaActivity.cs +++ /dev/null @@ -1,60 +0,0 @@ -using System; -using Android.App; -using Android.OS; -using Android.Views; -using Android.Widget; - -namespace Avalonia.Android.Platform.Specific -{ - public class AvaloniaActivity : Activity, IAndroidActivity - { - private IAndroidView _contentView; - - public AvaloniaActivity(Type applicationType) - { - AndroidPlatform.Instance.Init(applicationType); - } - - public Activity Activity => this; - - public IAndroidView ContentView - { - get - { - return this._contentView; - } - - set - { - this._contentView = value; - var fl = new FrameLayout(this); - fl.AddView(this._contentView.View); - //this.SetContentView(value.View); - this.SetContentView(fl); - } - } - - protected override void OnCreate(Bundle savedInstanceState) - { - AvaloniaLocator.CurrentMutable.Bind().ToConstant(this); - RequestWindowFeature(WindowFeatures.NoTitle); - base.OnCreate(savedInstanceState); - } - - public override void SetContentView(View view) - { - base.SetContentView(view); - TakeKeyEvents(true); - } - - public override bool DispatchKeyEvent(KeyEvent e) - { - if (_contentView != null) - { - _contentView.View.DispatchKeyEvent(e); - } - - return base.DispatchKeyEvent(e); - } - } -} \ 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 17e1f62e8c..7bac0ff814 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, IWindowImpl, IAndroidView + public class AndroidKeyboardEventsHelper : IDisposable where TView : View, ITopLevelImpl, IAndroidView { private TView _view; private IInputElement _lastFocusedElement; diff --git a/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidTouchEventsHelper.cs b/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidTouchEventsHelper.cs index c6d1833d2d..a448044ee6 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, IWindowImpl, IAndroidView + public class AndroidTouchEventsHelper : IDisposable where TView : View, ITopLevelImpl, IAndroidView { private TView _view; public bool HandleEvents { get; set; } diff --git a/src/Android/Avalonia.Android/Platform/Specific/IAndroidActivity.cs b/src/Android/Avalonia.Android/Platform/Specific/IAndroidActivity.cs deleted file mode 100644 index b2a999d4be..0000000000 --- a/src/Android/Avalonia.Android/Platform/Specific/IAndroidActivity.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Android.App; -using Android.Views; - -namespace Avalonia.Android.Platform.Specific -{ - public interface IAndroidActivity - { - Activity Activity { get; } - - IAndroidView ContentView { get; set; } - } -} \ No newline at end of file diff --git a/src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj b/src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj index e004121323..ebe268adcf 100644 --- a/src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj +++ b/src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj @@ -20,7 +20,7 @@ Properties\AndroidManifest.xml - true + True full false bin\Debug\ @@ -29,16 +29,16 @@ 4 True None - - False + True False False - armeabi,armeabi-v7a,x86 - - + armeabi;armeabi-v7a;x86 Xamarin False True + False + False + False pdbonly diff --git a/src/Android/Avalonia.AndroidTestApplication/MainActivity.cs b/src/Android/Avalonia.AndroidTestApplication/MainActivity.cs index ff27e12f6e..7973ad72e5 100644 --- a/src/Android/Avalonia.AndroidTestApplication/MainActivity.cs +++ b/src/Android/Avalonia.AndroidTestApplication/MainActivity.cs @@ -2,7 +2,7 @@ using System; using Android.App; using Android.Content.PM; using Android.OS; -using Avalonia.Android.Platform.Specific; +using Avalonia.Android; using Avalonia.Controls; using Avalonia.Controls.Templates; using Avalonia.Markup.Xaml; @@ -17,36 +17,24 @@ namespace Avalonia.AndroidTestApplication Icon = "@drawable/icon", LaunchMode = LaunchMode.SingleInstance/*, ScreenOrientation = ScreenOrientation.Landscape*/)] - public class MainBaseActivity : AvaloniaActivity + public class MainBaseActivity : Activity { - public MainBaseActivity() : base(typeof (App)) - { - - } - protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); - - App app; - if (Avalonia.Application.Current != null) - app = (App)Avalonia.Application.Current; - else + if (Avalonia.Application.Current == null) { - app = new App(); - AppBuilder.Configure(app) + AppBuilder.Configure() .UseAndroid() - .UseSkia() .SetupWithoutStarting(); } - - app.Run(); + SetContentView(new AvaloniaView(this) { Content = App.CreateSimpleWindow() }); } } public class App : Application { - public void Run() + public override void Initialize() { Styles.Add(new DefaultTheme()); @@ -55,18 +43,14 @@ namespace Avalonia.AndroidTestApplication new Uri("resm:Avalonia.Themes.Default.Accents.BaseLight.xaml?assembly=Avalonia.Themes.Default")); Styles.Add(baseLight); - var wnd = App.CreateSimpleWindow(); - wnd.AttachDevTools(); - Run(wnd); } // This provides a simple UI tree for testing input handling, drawing, etc - public static Window CreateSimpleWindow() + public static ContentControl CreateSimpleWindow() { - Window window = new Window + ContentControl window = new ContentControl() { - Title = "Avalonia Test Application", Background = Brushes.Red, Content = new StackPanel { diff --git a/src/Skia/Avalonia.Skia.Android.TestApp/App.cs b/src/Skia/Avalonia.Skia.Android.TestApp/App.cs deleted file mode 100644 index ca4d36b820..0000000000 --- a/src/Skia/Avalonia.Skia.Android.TestApp/App.cs +++ /dev/null @@ -1,7 +0,0 @@ - -namespace Avalonia.Skia.Android.TestApp -{ - public class App : Application - { - } -} diff --git a/src/Skia/Avalonia.Skia.Android.TestApp/Avalonia.Skia.Android.TestApp.csproj b/src/Skia/Avalonia.Skia.Android.TestApp/Avalonia.Skia.Android.TestApp.csproj deleted file mode 100644 index 041c8d9ecb..0000000000 --- a/src/Skia/Avalonia.Skia.Android.TestApp/Avalonia.Skia.Android.TestApp.csproj +++ /dev/null @@ -1,138 +0,0 @@ - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {F92E55A5-ED73-4CCB-AB4B-0541B6757F31} - {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - Library - Properties - Avalonia.Skia.Android.TestApp - Avalonia.Skia.Android.TestApp - 512 - true - Resources\Resource.Designer.cs - Off - False - v4.4 - Properties\AndroidManifest.xml - - - True - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - True - None - False - False - False - armeabi;armeabi-v7a;x86 - Xamarin - False - True - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - False - Full - True - False - False - Xamarin - False - False - False - False - False - armeabi;armeabi-v7a;x86 - - - - - - - - - - - - - - - - - - - - - - - - {7b92af71-6287-4693-9dcb-bd5b6e927e23} - Avalonia.Android - - - {d211e587-d8bc-45b9-95a4-f297c8fa5200} - Avalonia.Animation - - - {b09b78d8-9b26-48b0-9149-d64a2f120f3f} - Avalonia.Base - - - {d2221c82-4a25-4583-9b43-d791e3f6820c} - Avalonia.Controls - - - {4a1abb09-9047-4bd5-a4ad-a055e52c5ee0} - Avalonia.DotNetFrameworkRuntime - - - {62024b2d-53eb-4638-b26b-85eeaa54866e} - Avalonia.Input - - - {6b0ed19d-a08b-461c-a9d9-a9ee40b0c06b} - Avalonia.Interactivity - - - {42472427-4774-4c81-8aff-9f27b8e31721} - Avalonia.Layout - - - {eb582467-6abb-43a1-b052-e981ba910e3a} - Avalonia.Visuals - - - {f1baa01a-f176-4c6a-b39d-5b40bb1b148f} - Avalonia.Styling - - - {bd43f7c0-396b-4aa1-bad9-dfde54d51298} - Avalonia.Skia.Android - - - - - - - - - \ No newline at end of file diff --git a/src/Skia/Avalonia.Skia.Android.TestApp/Avalonia.Skia.Android.TestApp.v2.ncrunchproject b/src/Skia/Avalonia.Skia.Android.TestApp/Avalonia.Skia.Android.TestApp.v2.ncrunchproject deleted file mode 100644 index e1b4d7cf28..0000000000 --- a/src/Skia/Avalonia.Skia.Android.TestApp/Avalonia.Skia.Android.TestApp.v2.ncrunchproject +++ /dev/null @@ -1,26 +0,0 @@ - - true - 1000 - false - false - false - true - false - false - true - false - false - false - true - false - true - true - true - 60000 - - - - AutoDetect - STA - x86 - \ No newline at end of file diff --git a/src/Skia/Avalonia.Skia.Android.TestApp/MainActivity.cs b/src/Skia/Avalonia.Skia.Android.TestApp/MainActivity.cs deleted file mode 100644 index 9ac833a559..0000000000 --- a/src/Skia/Avalonia.Skia.Android.TestApp/MainActivity.cs +++ /dev/null @@ -1,78 +0,0 @@ -using Android.App; -using Android.OS; -using Android.Views; -using Avalonia; -using Avalonia.Controls; -using Avalonia.Media; - -namespace Avalonia.Skia.Android.TestApp -{ - [Activity(Label = "Avalonia.Skia.Android.TestApp", MainLauncher = true, Icon = "@drawable/icon")] - public class MainActivity : Activity - { - - protected override void OnCreate(Bundle bundle) - { - base.OnCreate(bundle); - - App app; - if (Avalonia.Application.Current != null) - app = (App)Avalonia.Application.Current; - else - { - app = new App(); - AppBuilder.Configure(app) - .UseAndroid() - .UseSkia() - .SetupWithoutStarting(); - } - - SetContentView(new MainView(this)); - } - - class MainView : SkiaRenderView - { - float _radians = 0; - public MainView(Activity context) : base(context) - { - } - - protected override void OnRender(DrawingContext ctx) - { - ctx.FillRectangle(Brushes.Green, new Rect(0, 0, Width, Height)); - - var rc = new Rect(0, 0, Width/3, Height/3); - using (ctx.PushPostTransform( - Avalonia.Matrix.CreateTranslation(-Width/6, -Width/6)* - Avalonia.Matrix.CreateRotation(_radians)* - Avalonia.Matrix.CreateTranslation(Width/2, Height/2))) - { - ctx.FillRectangle(new LinearGradientBrush() - { - GradientStops = - { - new GradientStop() {Color = Colors.Blue}, - new GradientStop(Colors.Red, 1) - } - }, rc, 5); - } - - - } - - public override bool OnTouchEvent(MotionEvent e) - { - if (e.Action == MotionEventActions.Down) - return true; - if (e.Action == MotionEventActions.Move) - { - _radians = (e.RawY + e.RawY)/100; - Invalidate(); - return true; - } - return base.OnTouchEvent(e); - } - } - } -} - diff --git a/src/Skia/Avalonia.Skia.Android.TestApp/Properties/AndroidManifest.xml b/src/Skia/Avalonia.Skia.Android.TestApp/Properties/AndroidManifest.xml deleted file mode 100644 index 5af8811830..0000000000 --- a/src/Skia/Avalonia.Skia.Android.TestApp/Properties/AndroidManifest.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/src/Skia/Avalonia.Skia.Android.TestApp/Properties/AssemblyInfo.cs b/src/Skia/Avalonia.Skia.Android.TestApp/Properties/AssemblyInfo.cs deleted file mode 100644 index 68efca2668..0000000000 --- a/src/Skia/Avalonia.Skia.Android.TestApp/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using Android.App; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Avalonia.Skia.Android.TestApp")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("Avalonia.Skia.Android.TestApp")] -[assembly: AssemblyCopyright("Copyright © 2015")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] -[assembly: ComVisible(false)] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/Skia/Avalonia.Skia.Android.TestApp/Resources/Resource.Designer.cs b/src/Skia/Avalonia.Skia.Android.TestApp/Resources/Resource.Designer.cs deleted file mode 100644 index 7d9036603f..0000000000 --- a/src/Skia/Avalonia.Skia.Android.TestApp/Resources/Resource.Designer.cs +++ /dev/null @@ -1,114 +0,0 @@ -#pragma warning disable 1591 -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -[assembly: global::Android.Runtime.ResourceDesignerAttribute("Avalonia.Skia.Android.TestApp.Resource", IsApplication=true)] - -namespace Avalonia.Skia.Android.TestApp -{ - - - [System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "1.0.0.0")] - public partial class Resource - { - - static Resource() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - public static void UpdateIdValues() - { - global::Avalonia.Android.Resource.String.ApplicationName = global::Avalonia.Skia.Android.TestApp.Resource.String.ApplicationName; - global::Avalonia.Android.Resource.String.Hello = global::Avalonia.Skia.Android.TestApp.Resource.String.Hello; - } - - public partial class Attribute - { - - static Attribute() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Attribute() - { - } - } - - public partial class Drawable - { - - // aapt resource value: 0x7f020000 - public const int Icon = 2130837504; - - static Drawable() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Drawable() - { - } - } - - public partial class Id - { - - // aapt resource value: 0x7f050000 - public const int MyButton = 2131034112; - - static Id() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Id() - { - } - } - - public partial class Layout - { - - // aapt resource value: 0x7f030000 - public const int Main = 2130903040; - - static Layout() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Layout() - { - } - } - - public partial class String - { - - // aapt resource value: 0x7f040001 - public const int ApplicationName = 2130968577; - - // aapt resource value: 0x7f040000 - public const int Hello = 2130968576; - - static String() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private String() - { - } - } - } -} -#pragma warning restore 1591 diff --git a/src/Skia/Avalonia.Skia.Android.TestApp/Resources/drawable/Icon.png b/src/Skia/Avalonia.Skia.Android.TestApp/Resources/drawable/Icon.png deleted file mode 100644 index 8074c4c571..0000000000 Binary files a/src/Skia/Avalonia.Skia.Android.TestApp/Resources/drawable/Icon.png and /dev/null differ diff --git a/src/Skia/Avalonia.Skia.Android.TestApp/Resources/layout/Main.axml b/src/Skia/Avalonia.Skia.Android.TestApp/Resources/layout/Main.axml deleted file mode 100644 index 98be1643ef..0000000000 --- a/src/Skia/Avalonia.Skia.Android.TestApp/Resources/layout/Main.axml +++ /dev/null @@ -1,13 +0,0 @@ - - -