-
Notifications
You must be signed in to change notification settings - Fork 425
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
Conversation
`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.
There was a problem hiding this 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
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.
AndroidMouseHandler
and improve Android mouse inputpublic override bool Initialize(GameHost host) => true; | ||
|
||
private void handleTouch(object sender, View.TouchEventArgs e) | ||
protected override void OnTouch(MotionEvent touchEvent) | ||
{ |
There was a problem hiding this comment.
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.
…ant method was not overriden
/// 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; } |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this 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.
As requested in code review. `Handle*` methods are now subscribed to in each handler separately. Too much boilerplate with everything in AndroidInputHandler.
Code looks good now. I'll try and give it a test today against touch and stylus. |
Stylus and touch work as expected here 👍 |
/// 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."); |
There was a problem hiding this comment.
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()
.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this 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)
This brings us one step closer to resolving #4373.
In addition to separating mouse from touch events,
AndroidMouseHandler
enables the following:Tested on Realme 6, Android 11 (API 30) with a bluetooth mouse.
On-screen keyboard input works as expected.
Test works with:
Test existing behaviour isn't broken for: