Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve Android mouse input and restructure Android input handlers #4971

Merged
merged 10 commits into from
Jan 5, 2022

Conversation

Susko3
Copy link
Member

@Susko3 Susko3 commented Dec 27, 2021

This brings us one step closer to resolving #4373.

In addition to separating mouse from touch events, AndroidMouseHandler enables the following:

  • support for all mouse buttons (including forward and back)
  • support for scrolling
  • starting point for implementing pointer capture.

Tested on Realme 6, Android 11 (API 30) with a bluetooth mouse.
On-screen keyboard input works as expected.

Test works with:

  • touchpad (not required, but would be nice to test)

Test existing behaviour isn't broken for:

  • physical keyboard
  • stylus

`ConfigChanges.Navigation` is needed so the game doesn't crash when connecting
additional devices (eg. a bluetooth mouse). `ConfigChanges.Touchscreen` added
just in case.
…od overrides

This makes it easier to get the desired behaviour for the upcoming AndroidMouseHandler.
Also add some comments to the events and moves them to a separate region.
In addition to separating mouse from touch events, AndroidMouseHandler enables the following:
- Support for all mouse buttons (including forward and back).
- Support for scrolling.

Additional changes include:
- Changes AndroidGameView to invoke events based on the input source.
- Adds new events specifically for the mouse and touchpad.
- Exposes framework internals to Android project so that FrameStatistics
  for MouseEvents can be incremented.
Copy link
Collaborator

@bdach bdach left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seemingly correct but i have no actual means to test

osu.Framework.Android/AndroidGameView.cs Outdated Show resolved Hide resolved
osu.Framework.Android/Input/AndroidMouseHandler.cs Outdated Show resolved Hide resolved
The events were getting out of hand, and future additions (eg. controller input)
would increase the complexity even more. So checking the event source was
moved to InputHandler-side and standardized with AndroidInputHandler.
AndroidInputHandler will now strictly enforce the event types and sources specified.
Input handlers now override the desired methods to handle those events.
@Susko3 Susko3 changed the title Add AndroidMouseHandler and improve Android mouse input Improve Android mouse input and restructure Android input handlers Dec 28, 2021
public override bool Initialize(GameHost host) => true;

private void handleTouch(object sender, View.TouchEventArgs e)
protected override void OnTouch(MotionEvent touchEvent)
{
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using MotionEvent because e.Event is nullable and I didn't want to have a null check.

/// The <see cref="InputEventType"/>s that this <see cref="AndroidInputHandler"/> will handle.
/// </summary>
/// <remarks>For each <see cref="InputEventType"/> specified here, this <see cref="AndroidInputHandler"/> should override the appropriate method.</remarks>
protected abstract IEnumerable<InputEventType> HandledEventTypes { get; }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not super sure on this setup. Rather than having to declare event types the handler is interested in and then having to override the correct methods (lest you get NotSupportedException at runtime), you could just subscribe to all events but leave the handlers empty. That'd get rid of some of the boilerplate.

I don't hate this setup though, will wait for more opinions.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can agree with this. Seems like too much boilerplate for an edge case usage as it's currently written.

Copy link
Member

@peppy peppy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR in general seems pretty fine, but would like to see it with manual event binding at each usage as proposed.

Susko3 added 2 commits January 3, 2022 22:33
As requested in code review.
`Handle*` methods are now subscribed to in each handler separately.
Too much boilerplate with everything in AndroidInputHandler.
@peppy
Copy link
Member

peppy commented Jan 4, 2022

Code looks good now. I'll try and give it a test today against touch and stylus.

@peppy
Copy link
Member

peppy commented Jan 4, 2022

Stylus and touch work as expected here 👍

Comment on lines +62 to +66
/// Subscribe <see cref="HandleCapturedPointer"/> to <see cref="View"/>.<see cref="AndroidGameView.CapturedPointer"/> to receive events here.
/// </remarks>
protected virtual void OnCapturedPointer(MotionEvent capturedPointerEvent)
{
throw new NotSupportedException($"{nameof(HandleCapturedPointer)} subscribed to {nameof(View.CapturedPointer)} but the relevant method was not overriden.");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't quite what I had in mind with my last review but I suppose it works...?

To clarify, I was proposing subscribing to all input events which are available on the view at the AndroidInputHandler level, and calling the OnEvent methods on them there - as long as they match eventSourceBitmask - but leaving the input handlers blank to be overridden by inheritors. That way the only thing that needs to be done to handle an event in an implementation of this is overriding the correct handler, while this solution also requires manually hooking the events up in OnInitialize().

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried doing it how peppy suggested, and figured it was less wasteful than your proposal. So I went with that.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure any overhead from these events is ever going to matter but I don't feel like splitting hairs over this.

Copy link
Collaborator

@bdach bdach left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

code seems fine, haven't tested, relying on @peppy's testing as i could only test the same part of this PR at most anyway (don't have required hardware to test mouse)

@peppy peppy merged commit e4f3389 into ppy:master Jan 5, 2022
@Susko3 Susko3 deleted the android-mouse branch January 5, 2022 06:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants