Skip to content

Commit

Permalink
Merge pull request ppy#5442 from Susko3/fix-android-keyboard
Browse files Browse the repository at this point in the history
Fix some physical keyboards not working on Android
  • Loading branch information
peppy authored Oct 21, 2022
2 parents ef5c6a8 + 2846f8b commit c464502
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 26 deletions.
8 changes: 7 additions & 1 deletion osu.Framework.Android/Input/AndroidInputExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,12 @@ public static bool TryGetMouseButton(this Keycode keycode, out MouseButton butto
return false;
}

public static bool IsKeyboard(this InputSourceType source)
{
// ReSharper disable once BitwiseOperatorOnEnumWithoutFlags
return source is InputSourceType.Keyboard or (InputSourceType.Keyboard | InputSourceType.Dpad);
}

public static bool TryGetJoystickButton(this KeyEvent e, out JoystickButton button)
{
var keycode = e.KeyCode;
Expand All @@ -192,7 +198,7 @@ public static bool TryGetJoystickButton(this KeyEvent e, out JoystickButton butt
case Keycode.DpadDown:
case Keycode.DpadLeft:
case Keycode.DpadRight:
case Keycode.Back when e.Source == InputSourceType.Keyboard:
case Keycode.Back when e.Source.IsKeyboard():
default:
button = JoystickButton.FirstButton;
return false;
Expand Down
32 changes: 28 additions & 4 deletions osu.Framework.Android/Input/AndroidInputHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ protected virtual bool OnHover(MotionEvent hoverEvent)
/// Subscribe <see cref="HandleKeyDown"/> to <see cref="View"/>.<see cref="AndroidGameView.KeyDown"/> to receive events here.
/// <returns>Whether the event was handled. Unhandled events are logged.</returns>
/// </remarks>
protected virtual bool OnKeyDown(Keycode keycode, KeyEvent e)
protected virtual ReturnCode OnKeyDown(Keycode keycode, KeyEvent e)
{
throw new NotSupportedException($"{nameof(HandleKeyDown)} subscribed to {nameof(View.KeyDown)} but the relevant method was not overriden.");
}
Expand All @@ -112,7 +112,7 @@ protected virtual bool OnKeyDown(Keycode keycode, KeyEvent e)
/// Subscribe <see cref="HandleKeyUp"/> to <see cref="View"/>.<see cref="AndroidGameView.KeyUp"/> to receive events here.
/// <returns>Whether the event was handled. Unhandled events are logged.</returns>
/// </remarks>
protected virtual bool OnKeyUp(Keycode keycode, KeyEvent e)
protected virtual ReturnCode OnKeyUp(Keycode keycode, KeyEvent e)
{
throw new NotSupportedException($"{nameof(HandleKeyUp)} subscribed to {nameof(View.KeyUp)} but the relevant method was not overriden.");
}
Expand Down Expand Up @@ -191,7 +191,7 @@ protected void HandleKeyDown(Keycode keycode, KeyEvent e)
{
if (ShouldHandleEvent(e))
{
if (!OnKeyDown(keycode, e))
if (OnKeyDown(keycode, e) == ReturnCode.Unhandled)
logUnhandledEvent(nameof(OnKeyDown), e);
}
}
Expand All @@ -203,7 +203,7 @@ protected void HandleKeyUp(Keycode keycode, KeyEvent e)
{
if (ShouldHandleEvent(e))
{
if (!OnKeyUp(keycode, e))
if (OnKeyUp(keycode, e) == ReturnCode.Unhandled)
logUnhandledEvent(nameof(OnKeyUp), e);
}
}
Expand All @@ -228,5 +228,29 @@ private void logUnhandledEvent(string methodName, InputEvent inputEvent)
{
Log($"Unknown {GetType().ReadableName()}.{methodName} event: {inputEvent}");
}

protected enum ReturnCode
{
/// <summary>
/// Denotes an event that was handled by this handler.
/// </summary>
Handled,

/// <summary>
/// Denotes an event that this handler did not handle.
/// </summary>
/// <remarks>
/// Since all events are first put through the <see cref="AndroidInputHandler.HandledEventSources"/> filter, an unhandled event is considered a bug and is logged.
/// </remarks>
Unhandled,

/// <summary>
/// Same as <see cref="Unhandled"/>, but will not be logged.
/// </summary>
/// <remarks>
/// Used when an event might also be handled by another handler, but that cannot be determined purely on <see cref="AndroidInputHandler.HandledEventSources"/>.
/// </remarks>
UnhandledSuppressLogging,
}
}
}
22 changes: 14 additions & 8 deletions osu.Framework.Android/Input/AndroidJoystickHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,28 +64,34 @@ public override bool Initialize(GameHost host)
return true;
}

protected override bool OnKeyDown(Keycode keycode, KeyEvent e)
private ReturnCode returnCodeForSource(InputSourceType source)
{
// keyboard only events are handled in AndroidKeyboardHandler
return source.IsKeyboard()
? ReturnCode.UnhandledSuppressLogging
: ReturnCode.Unhandled;
}

protected override ReturnCode OnKeyDown(Keycode keycode, KeyEvent e)
{
if (e.TryGetJoystickButton(out var button))
{
enqueueButtonDown(button);
return true;
return ReturnCode.Handled;
}

// keyboard only events are handled in AndroidKeyboardHandler
return e.Source == InputSourceType.Keyboard;
return returnCodeForSource(e.Source);
}

protected override bool OnKeyUp(Keycode keycode, KeyEvent e)
protected override ReturnCode OnKeyUp(Keycode keycode, KeyEvent e)
{
if (e.TryGetJoystickButton(out var button))
{
enqueueButtonUp(button);
return true;
return ReturnCode.Handled;
}

// keyboard only events are handled in AndroidKeyboardHandler
return e.Source == InputSourceType.Keyboard;
return returnCodeForSource(e.Source);
}

/// <summary>
Expand Down
27 changes: 20 additions & 7 deletions osu.Framework.Android/Input/AndroidKeyboardHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,12 @@ namespace osu.Framework.Android.Input
{
public class AndroidKeyboardHandler : AndroidInputHandler
{
protected override IEnumerable<InputSourceType> HandledEventSources => new[] { InputSourceType.Keyboard };
protected override IEnumerable<InputSourceType> HandledEventSources => new[]
{
InputSourceType.Keyboard,
// Some physical keyboards report as (Keyboard | Dpad)
InputSourceType.Dpad,
};

public AndroidKeyboardHandler(AndroidGameView view)
: base(view)
Expand Down Expand Up @@ -44,30 +49,38 @@ public override bool Initialize(GameHost host)

public override bool IsActive => true;

protected override bool OnKeyDown(Keycode keycode, KeyEvent e)
private ReturnCode returnCodeForKeycode(Keycode keycode)
{
// gamepad buttons are handled in AndroidJoystickHandler
return KeyEvent.IsGamepadButton(keycode)
? ReturnCode.UnhandledSuppressLogging
: ReturnCode.Unhandled;
}

protected override ReturnCode OnKeyDown(Keycode keycode, KeyEvent e)
{
var key = GetKeyCodeAsKey(keycode);

if (key != Key.Unknown)
{
enqueueInput(new KeyboardKeyInput(key, true));
return true;
return ReturnCode.Handled;
}

return false;
return returnCodeForKeycode(keycode);
}

protected override bool OnKeyUp(Keycode keycode, KeyEvent e)
protected override ReturnCode OnKeyUp(Keycode keycode, KeyEvent e)
{
var key = GetKeyCodeAsKey(keycode);

if (key != Key.Unknown)
{
enqueueInput(new KeyboardKeyInput(key, false));
return true;
return ReturnCode.Handled;
}

return false;
return returnCodeForKeycode(keycode);
}

/// <summary>
Expand Down
12 changes: 6 additions & 6 deletions osu.Framework.Android/Input/AndroidMouseHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -136,27 +136,27 @@ private void updatePointerCapture()
View.PointerCapture = shouldCapture;
}

protected override bool OnKeyDown(Keycode keycode, KeyEvent e)
protected override ReturnCode OnKeyDown(Keycode keycode, KeyEvent e)
{
// some implementations might send Mouse1 and Mouse2 as keyboard keycodes, so we handle those here.
if (keycode.TryGetMouseButton(out var button))
{
handleMouseButton(button, true);
return true;
return ReturnCode.Handled;
}

return false;
return ReturnCode.Unhandled;
}

protected override bool OnKeyUp(Keycode keycode, KeyEvent e)
protected override ReturnCode OnKeyUp(Keycode keycode, KeyEvent e)
{
if (keycode.TryGetMouseButton(out var button))
{
handleMouseButton(button, false);
return true;
return ReturnCode.Handled;
}

return false;
return ReturnCode.Unhandled;
}

protected override bool OnHover(MotionEvent hoverEvent)
Expand Down

0 comments on commit c464502

Please sign in to comment.