committed by
GitHub
14 changed files with 178 additions and 76 deletions
@ -1,5 +1,5 @@ |
|||||
<?xml version="1.0" encoding="utf-8"?> |
<?xml version="1.0" encoding="utf-8"?> |
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="ControlCatalog.Android" android:versionCode="1" android:versionName="1.0" android:installLocation="auto"> |
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="ControlCatalog.Android" android:versionCode="1" android:versionName="1.0" android:installLocation="auto"> |
||||
<uses-sdk android:targetSdkVersion="29" /> |
<uses-sdk android:targetSdkVersion="30" /> |
||||
<application android:label="ControlCatalog.Android"></application> |
<application android:label="ControlCatalog.Android"></application> |
||||
</manifest> |
</manifest> |
||||
@ -1,47 +0,0 @@ |
|||||
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; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,101 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Reactive.Disposables; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
using Android.OS; |
||||
|
using Android.Views; |
||||
|
|
||||
|
using Avalonia.Rendering; |
||||
|
|
||||
|
using Java.Lang; |
||||
|
|
||||
|
namespace Avalonia.Android |
||||
|
{ |
||||
|
internal sealed class ChoreographerTimer : Java.Lang.Object, IRenderTimer, Choreographer.IFrameCallback |
||||
|
{ |
||||
|
private readonly object _lock = new object(); |
||||
|
|
||||
|
private readonly Thread _thread; |
||||
|
private readonly TaskCompletionSource<Choreographer> _choreographer = new TaskCompletionSource<Choreographer>(); |
||||
|
|
||||
|
private readonly ISet<AvaloniaView> _views = new HashSet<AvaloniaView>(); |
||||
|
|
||||
|
private Action<TimeSpan> _tick; |
||||
|
private int _count; |
||||
|
|
||||
|
public ChoreographerTimer() |
||||
|
{ |
||||
|
_thread = new Thread(Loop); |
||||
|
_thread.Start(); |
||||
|
} |
||||
|
|
||||
|
public event Action<TimeSpan> Tick |
||||
|
{ |
||||
|
add |
||||
|
{ |
||||
|
lock (_lock) |
||||
|
{ |
||||
|
_tick += value; |
||||
|
_count++; |
||||
|
|
||||
|
if (_count == 1) |
||||
|
{ |
||||
|
_choreographer.Task.Result.PostFrameCallback(this); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
remove |
||||
|
{ |
||||
|
lock (_lock) |
||||
|
{ |
||||
|
_tick -= value; |
||||
|
_count--; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
internal IDisposable SubscribeView(AvaloniaView view) |
||||
|
{ |
||||
|
lock (_lock) |
||||
|
{ |
||||
|
_views.Add(view); |
||||
|
|
||||
|
if (_views.Count == 1) |
||||
|
{ |
||||
|
_choreographer.Task.Result.PostFrameCallback(this); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return Disposable.Create( |
||||
|
() => |
||||
|
{ |
||||
|
lock (_lock) |
||||
|
{ |
||||
|
_views.Remove(view); |
||||
|
} |
||||
|
} |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
private void Loop() |
||||
|
{ |
||||
|
Looper.Prepare(); |
||||
|
_choreographer.SetResult(Choreographer.Instance); |
||||
|
Looper.Loop(); |
||||
|
} |
||||
|
|
||||
|
public void DoFrame(long frameTimeNanos) |
||||
|
{ |
||||
|
_tick?.Invoke(TimeSpan.FromTicks(frameTimeNanos / 100)); |
||||
|
|
||||
|
lock (_lock) |
||||
|
{ |
||||
|
if (_count > 0 && _views.Count > 0) |
||||
|
{ |
||||
|
Choreographer.Instance.PostFrameCallback(this); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,12 +1,21 @@ |
|||||
using System; |
|
||||
using Avalonia.Input; |
using Avalonia.Input; |
||||
using Avalonia.Platform; |
using Avalonia.Platform; |
||||
|
|
||||
namespace Avalonia.Android |
namespace Avalonia.Android |
||||
{ |
{ |
||||
internal class CursorFactory : IStandardCursorFactory |
internal class CursorFactory : ICursorFactory |
||||
{ |
{ |
||||
public IPlatformHandle GetCursor(StandardCursorType cursorType) |
public ICursorImpl CreateCursor(IBitmapImpl cursor, PixelPoint hotSpot) => CursorImpl.ZeroCursor; |
||||
=> new PlatformHandle(IntPtr.Zero, "ZeroCursor"); |
|
||||
|
public ICursorImpl GetCursor(StandardCursorType cursorType) => CursorImpl.ZeroCursor; |
||||
|
|
||||
|
private sealed class CursorImpl : ICursorImpl |
||||
|
{ |
||||
|
public static CursorImpl ZeroCursor { get; } = new CursorImpl(); |
||||
|
|
||||
|
private CursorImpl() { } |
||||
|
|
||||
|
public void Dispose() { } |
||||
|
} |
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -1,23 +1,30 @@ |
|||||
using Avalonia.OpenGL.Egl; |
using System; |
||||
|
|
||||
|
using Avalonia.OpenGL.Egl; |
||||
using Avalonia.OpenGL.Surfaces; |
using Avalonia.OpenGL.Surfaces; |
||||
|
|
||||
namespace Avalonia.Android.OpenGL |
namespace Avalonia.Android.OpenGL |
||||
{ |
{ |
||||
internal sealed class GlRenderTarget : EglPlatformSurfaceRenderTargetBase |
internal sealed class GlRenderTarget : EglPlatformSurfaceRenderTargetBase, IGlPlatformSurfaceRenderTargetWithCorruptionInfo |
||||
{ |
{ |
||||
private readonly EglGlPlatformSurfaceBase.IEglWindowGlPlatformSurfaceInfo _info; |
private readonly EglGlPlatformSurfaceBase.IEglWindowGlPlatformSurfaceInfo _info; |
||||
private readonly EglSurface _surface; |
private readonly EglSurface _surface; |
||||
|
private readonly IntPtr _handle; |
||||
|
|
||||
public GlRenderTarget( |
public GlRenderTarget( |
||||
EglPlatformOpenGlInterface egl, |
EglPlatformOpenGlInterface egl, |
||||
EglGlPlatformSurfaceBase.IEglWindowGlPlatformSurfaceInfo info, |
EglGlPlatformSurfaceBase.IEglWindowGlPlatformSurfaceInfo info, |
||||
EglSurface surface) |
EglSurface surface, |
||||
|
IntPtr handle) |
||||
: base(egl) |
: base(egl) |
||||
{ |
{ |
||||
_info = info; |
_info = info; |
||||
_surface = surface; |
_surface = surface; |
||||
|
_handle = handle; |
||||
} |
} |
||||
|
|
||||
|
public bool IsCorrupted => _handle != _info.Handle; |
||||
|
|
||||
public override IGlPlatformSurfaceRenderingSession BeginDraw() => BeginDraw(_surface, _info); |
public override IGlPlatformSurfaceRenderingSession BeginDraw() => BeginDraw(_surface, _info); |
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -1,6 +1,6 @@ |
|||||
<?xml version="1.0" encoding="utf-8"?> |
<?xml version="1.0" encoding="utf-8"?> |
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="Avalonia.AndroidTestApplication" android:versionCode="1" android:versionName="1.0" android:installLocation="auto"> |
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="Avalonia.AndroidTestApplication" android:versionCode="1" android:versionName="1.0" android:installLocation="auto"> |
||||
<uses-sdk android:targetSdkVersion="29" /> |
<uses-sdk android:targetSdkVersion="30" /> |
||||
<application android:label="Avalonia.AndroidTestApplication" android:icon="@drawable/Icon" android:hardwareAccelerated="true"></application> |
<application android:label="Avalonia.AndroidTestApplication" android:icon="@drawable/Icon" android:hardwareAccelerated="true"></application> |
||||
<uses-permission android:name="android.permission.INTERNET" /> |
<uses-permission android:name="android.permission.INTERNET" /> |
||||
</manifest> |
</manifest> |
||||
Loading…
Reference in new issue