Full NRT pass on Android

Includes everything except `AndroidInputHandler`s as those will be covered separately.
This commit is contained in:
Susko3
2022-07-02 20:15:27 +02:00
parent e918d33889
commit f5363df7e5
12 changed files with 56 additions and 80 deletions

View File

@@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using Android.App;
using osu.Framework;
using osu.Framework.Android;

View File

@@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using Android.App;
using Android.Content;
using Android.Content.PM;
@@ -11,7 +9,7 @@ using Android.Runtime;
using Android.Views;
using ManagedBass;
using osu.Framework.Bindables;
using Debug = System.Diagnostics.Debug;
using osu.Framework.Extensions.ObjectExtensions;
namespace osu.Framework.Android
{
@@ -43,22 +41,17 @@ namespace osu.Framework.Android
/// </summary>
public SystemUiFlags UIVisibilityFlags
{
get
{
Debug.Assert(Window != null);
return (SystemUiFlags)Window.DecorView.SystemUiVisibility;
}
get => (SystemUiFlags)Window.AsNonNull().DecorView.SystemUiVisibility;
set
{
Debug.Assert(Window != null);
systemUiFlags = value;
Window.DecorView.SystemUiVisibility = (StatusBarVisibility)value;
Window.AsNonNull().DecorView.SystemUiVisibility = (StatusBarVisibility)value;
}
}
private SystemUiFlags systemUiFlags;
private AndroidGameView gameView;
private AndroidGameView gameView = null!;
public override void OnTrimMemory([GeneratedEnum] TrimMemory level)
{
@@ -66,7 +59,7 @@ namespace osu.Framework.Android
gameView.Host?.Collect();
}
protected override void OnCreate(Bundle savedInstanceState)
protected override void OnCreate(Bundle? savedInstanceState)
{
// The default current directory on android is '/'.
// On some devices '/' maps to the app data directory. On others it maps to the root of the internal storage.
@@ -79,11 +72,9 @@ namespace osu.Framework.Android
UIVisibilityFlags = SystemUiFlags.LayoutFlags | SystemUiFlags.ImmersiveSticky | SystemUiFlags.HideNavigation | SystemUiFlags.Fullscreen;
Debug.Assert(Window != null);
// Firing up the on-screen keyboard (eg: interacting with textboxes) may cause the UI visibility flags to be altered thus showing the navigation bar and potentially the status bar
// This sets back the UI flags to hidden once the interaction with the on-screen keyboard has finished.
Window.DecorView.SystemUiVisibilityChange += (_, e) =>
Window.AsNonNull().DecorView.SystemUiVisibilityChange += (_, e) =>
{
if ((SystemUiFlags)e.Visibility != systemUiFlags)
{
@@ -93,8 +84,7 @@ namespace osu.Framework.Android
if (Build.VERSION.SdkInt >= BuildVersionCodes.P)
{
Debug.Assert(Window.Attributes != null);
Window.Attributes.LayoutInDisplayCutoutMode = LayoutInDisplayCutoutMode.ShortEdges;
Window.AsNonNull().Attributes.AsNonNull().LayoutInDisplayCutoutMode = LayoutInDisplayCutoutMode.ShortEdges;
}
gameView.HostStarted += host =>
@@ -104,9 +94,9 @@ namespace osu.Framework.Android
RunOnUiThread(() =>
{
if (!allow.NewValue)
Window.AddFlags(WindowManagerFlags.KeepScreenOn);
Window?.AddFlags(WindowManagerFlags.KeepScreenOn);
else
Window.ClearFlags(WindowManagerFlags.KeepScreenOn);
Window?.ClearFlags(WindowManagerFlags.KeepScreenOn);
});
}, true);
};
@@ -141,17 +131,17 @@ namespace osu.Framework.Android
// On some devices and keyboard combinations the OnKeyDown event does not propagate the key event to the view.
// Here it is done manually to ensure that the keys actually land in the view.
public override bool OnKeyDown([GeneratedEnum] Keycode keyCode, KeyEvent e)
public override bool OnKeyDown([GeneratedEnum] Keycode keyCode, KeyEvent? e)
{
return gameView.OnKeyDown(keyCode, e);
}
public override bool OnKeyUp([GeneratedEnum] Keycode keyCode, KeyEvent e)
public override bool OnKeyUp([GeneratedEnum] Keycode keyCode, KeyEvent? e)
{
return gameView.OnKeyUp(keyCode, e);
}
public override bool OnKeyLongPress([GeneratedEnum] Keycode keyCode, KeyEvent e)
public override bool OnKeyLongPress([GeneratedEnum] Keycode keyCode, KeyEvent? e)
{
return gameView.OnKeyLongPress(keyCode, e);
}

View File

@@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using System.Collections.Generic;
using System.IO;
using Android.App;
@@ -11,6 +9,7 @@ using osu.Framework.Android.Graphics.Textures;
using osu.Framework.Android.Graphics.Video;
using osu.Framework.Android.Input;
using osu.Framework.Configuration;
using osu.Framework.Extensions.ObjectExtensions;
using osu.Framework.Graphics.Textures;
using osu.Framework.Graphics.Video;
using osu.Framework.Input;
@@ -65,7 +64,7 @@ namespace osu.Framework.Android
public override IEnumerable<string> UserStoragePaths => new[]
{
// not null as internal "external storage" is always available.
Application.Context.GetExternalFilesDir(string.Empty)!.ToString(),
Application.Context.GetExternalFilesDir(string.Empty).AsNonNull().ToString(),
};
public override bool OpenFileExternally(string filename) => false;

View File

@@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using System;
using Android.Content;
using Android.Graphics;
@@ -15,19 +13,19 @@ using Android.Views.InputMethods;
using osu.Framework.Android.Input;
using osu.Framework.Logging;
using osu.Framework.Bindables;
using osu.Framework.Extensions.ObjectExtensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Primitives;
using osu.Framework.Platform;
using osuTK.Graphics;
using Debug = System.Diagnostics.Debug;
namespace osu.Framework.Android
{
public class AndroidGameView : osuTK.Android.AndroidGameView
{
public AndroidGameHost Host { get; private set; }
public AndroidGameHost? Host { get; private set; }
public AndroidGameActivity Activity { get; }
public AndroidGameActivity Activity { get; } = null!;
public BindableSafeArea SafeAreaPadding { get; } = new BindableSafeArea();
@@ -62,9 +60,9 @@ namespace osu.Framework.Android
}
}
private readonly Game game;
private readonly Game game = null!;
private InputMethodManager inputMethodManager;
private InputMethodManager? inputMethodManager;
/// <summary>
/// Whether <see cref="AndroidTextInput"/> is active.
@@ -128,8 +126,10 @@ namespace osu.Framework.Android
return false;
}
public override bool OnKeyDown([GeneratedEnum] Keycode keyCode, KeyEvent e)
public override bool OnKeyDown([GeneratedEnum] Keycode keyCode, KeyEvent? e)
{
if (e == null) return base.OnKeyDown(keyCode, e);
switch (keyCode)
{
// Do not consume Volume keys, so the system can handle them
@@ -151,14 +151,18 @@ namespace osu.Framework.Android
}
}
public override bool OnKeyLongPress([GeneratedEnum] Keycode keyCode, KeyEvent e)
public override bool OnKeyLongPress([GeneratedEnum] Keycode keyCode, KeyEvent? e)
{
if (e == null) return base.OnKeyLongPress(keyCode, e);
KeyLongPress?.Invoke(keyCode, e);
return true;
}
public override bool OnKeyUp([GeneratedEnum] Keycode keyCode, KeyEvent e)
public override bool OnKeyUp([GeneratedEnum] Keycode keyCode, KeyEvent? e)
{
if (e == null) return base.OnKeyUp(keyCode, e);
KeyUp?.Invoke(keyCode, e);
return true;
}
@@ -206,12 +210,10 @@ namespace osu.Framework.Android
/// </summary>
private void updateSafeArea()
{
Debug.Assert(Display != null);
// compute the usable screen area.
var screenSize = new Point();
Display.GetRealSize(screenSize);
Display.AsNonNull().GetRealSize(screenSize);
var screenArea = new RectangleI(0, 0, screenSize.X, screenSize.Y);
var usableScreenArea = screenArea;
@@ -257,8 +259,10 @@ namespace osu.Framework.Android
public override bool OnCheckIsTextEditor() => textInputActive;
/// <returns><c>null</c> to disable input methods</returns>
public override IInputConnection OnCreateInputConnection(EditorInfo outAttrs)
public override IInputConnection? OnCreateInputConnection(EditorInfo? outAttrs)
{
if (outAttrs == null) throw new ArgumentNullException(nameof(outAttrs));
// Properly disable native input methods so that the software keyboard doesn't unexpectedly open.
// Eg. when pressing keys on a hardware keyboard.
if (!textInputActive)
@@ -274,7 +278,7 @@ namespace osu.Framework.Android
textInputActive = true;
Activity.RunOnUiThread(() =>
{
inputMethodManager.RestartInput(this); // this syncs the Android input method state with `OnCreateInputConnection()`.
inputMethodManager?.RestartInput(this); // this syncs the Android input method state with `OnCreateInputConnection()`.
RequestFocus();
inputMethodManager?.ShowSoftInput(this, 0);
});
@@ -285,7 +289,7 @@ namespace osu.Framework.Android
textInputActive = false;
Activity.RunOnUiThread(() =>
{
inputMethodManager.RestartInput(this);
inputMethodManager?.RestartInput(this);
inputMethodManager?.HideSoftInputFromWindow(WindowToken, HideSoftInputFlags.None);
ClearFocus();
});
@@ -316,27 +320,27 @@ namespace osu.Framework.Android
/// <summary>
/// Invoked on a key down event.
/// </summary>
public new event Action<Keycode, KeyEvent> KeyDown;
public new event Action<Keycode, KeyEvent>? KeyDown;
/// <summary>
/// Invoked on a key up event.
/// </summary>
public new event Action<Keycode, KeyEvent> KeyUp;
public new event Action<Keycode, KeyEvent>? KeyUp;
/// <summary>
/// Invoked on a key long press event.
/// </summary>
public event Action<Keycode, KeyEvent> KeyLongPress;
public event Action<Keycode, KeyEvent>? KeyLongPress;
/// <summary>
/// Invoked when text is committed by an <see cref="AndroidInputConnection"/>.
/// </summary>
public event Action<string> CommitText;
public event Action<string>? CommitText;
/// <summary>
/// Invoked when the <see cref="game"/> has been started on the <see cref="Host"/>.
/// </summary>
public event Action<AndroidGameHost> HostStarted;
public event Action<AndroidGameHost>? HostStarted;
#endregion
}

View File

@@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using System;
using System.Collections.Generic;
using osu.Framework.Bindables;
@@ -29,7 +27,7 @@ namespace osu.Framework.Android
set { }
}
public event Action CursorStateChanged;
public event Action? CursorStateChanged;
public override CursorState CursorState
{

View File

@@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using osu.Framework.Platform;
namespace osu.Framework.Android

View File

@@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using System;
using System.IO;
using Android.Graphics;

View File

@@ -1,17 +1,15 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using Android.Runtime;
using FFmpeg.AutoGen;
using osu.Framework.Extensions.EnumExtensions;
using osu.Framework.Extensions.ObjectExtensions;
using osu.Framework.Graphics.Video;
using osu.Framework.Logging;
@@ -151,11 +149,9 @@ namespace osu.Framework.Android.Graphics.Video
const string java_vm_field_name = "java_vm";
var jvmPtrInfo = typeof(JNIEnv).GetField(java_vm_field_name, BindingFlags.NonPublic | BindingFlags.Static);
object jvmPtrObj = jvmPtrInfo?.GetValue(null);
object? jvmPtrObj = jvmPtrInfo?.GetValue(null);
Debug.Assert(jvmPtrObj != null);
int result = av_jni_set_java_vm((void*)(IntPtr)jvmPtrObj, null);
int result = av_jni_set_java_vm((void*)(IntPtr)jvmPtrObj.AsNonNull(), null);
if (result < 0)
throw new InvalidOperationException($"Couldn't pass Java VM handle to FFmpeg: ${result}");
}

View File

@@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using Android.Views;
using Android.Views.InputMethods;
using Java.Lang;
@@ -11,40 +9,43 @@ namespace osu.Framework.Android.Input
{
internal class AndroidInputConnection : BaseInputConnection
{
public AndroidGameView TargetView { get; set; }
private readonly AndroidGameView targetView;
public AndroidInputConnection(AndroidGameView targetView, bool fullEditor)
: base(targetView, fullEditor)
{
TargetView = targetView;
this.targetView = targetView;
}
public override bool CommitText(ICharSequence text, int newCursorPosition)
public override bool CommitText(ICharSequence? text, int newCursorPosition)
{
if (text.Length() != 0)
if (text?.Length() > 0)
{
TargetView.OnCommitText(text.ToString());
targetView.OnCommitText(text.ToString());
return true;
}
return base.CommitText(text, newCursorPosition);
}
public override bool SendKeyEvent(KeyEvent e)
public override bool SendKeyEvent(KeyEvent? e)
{
if (e == null)
return base.SendKeyEvent(e);
switch (e.Action)
{
case KeyEventActions.Down:
TargetView?.OnKeyDown(e.KeyCode, e);
targetView.OnKeyDown(e.KeyCode, e);
return true;
case KeyEventActions.Up:
TargetView?.OnKeyUp(e.KeyCode, e);
targetView.OnKeyUp(e.KeyCode, e);
return true;
case KeyEventActions.Multiple:
TargetView?.OnKeyDown(e.KeyCode, e);
TargetView?.OnKeyUp(e.KeyCode, e);
targetView.OnKeyDown(e.KeyCode, e);
targetView.OnKeyUp(e.KeyCode, e);
return true;
}

View File

@@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using System;
using System.Collections.Generic;
using Android.Views;

View File

@@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using System.Runtime.CompilerServices;
using Android;
using Android.App;

View File

@@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using Android.App;
using osu.Framework.Android;