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

Gamepad API does not work (WKWebView needs to be firstResponder?) #1397

Open
3 tasks done
AshleyScirra opened this issue Feb 15, 2024 · 11 comments
Open
3 tasks done

Gamepad API does not work (WKWebView needs to be firstResponder?) #1397

AshleyScirra opened this issue Feb 15, 2024 · 11 comments
Labels
webkit bug Bugs that originate upstream in Apple's WebKit implementation

Comments

@AshleyScirra
Copy link

Bug Report

The Gamepad API does not work in WKWebView. This affects any content published to iOS with Cordova that uses gamepad input (such as games, as used by Construct).

According to Apple the problem may be that WKWebView needs to be the firstResponder. I'm filing this issue as cordova-ios may need to configure the WKWebView accordingly.

Problem

Repro Xcode project made using Construct: Gamepad control example.ios.project.zip

Steps to reproduce:

  1. Connect a gamepad to an iOS device (in my case I used bluetooth to pair the controller to the device)
  2. Launch the Xcode project on the iOS device
  3. Press some gamepad buttons

What is expected to happen?

The app should detect the gamepad upon first pressing a button and allow controlling the sprite with gamepad input. This is how it works in the Safari browser.

What does actually happen?

No gamepad input is ever detected.

Information

Originally I assumed this was a bug in WKWebView and filed it with Apple here: https://bugs.webkit.org/show_bug.cgi?id=269292

They responded:

To expose Gamepad support, your WKWebView needs to be the firstResponder.

Safari - correctly for Apple platforms - keeps focused WKWebViews as the firstResponder.

Many apps neglect to do this, and once we let a developer know and they make the change gamepads start working.

So it may be the case that cordova-ios needs to configure WKWebView as they recommend.

Command or Code

See repro above. It ought to reproduce with any example that uses the Gamepad API if you want a more minimal repro.

Environment, Platform, Device

Tested on iPhone 12 Pro Max with iOS 17.2.1 and a PlayStation 4 wireless controller.

Version information

Using [email protected]

Checklist

  • I searched for existing GitHub issues
  • I updated all Cordova tooling to most recent version
  • I included all the necessary information above
@dpogue
Copy link
Member

dpogue commented Feb 15, 2024

hmmm, in theory we tried to fix this in #1337 which should be included in cordova-ios 7.0.1

@dpogue
Copy link
Member

dpogue commented Feb 16, 2024

@AshleyScirra I tried to test this (on cordova-ios master branch) with a hardware keyboard attached to an iPad, and it seemed like the Cordova WKWebView was receiving events properly with no need to tap the screen. I don't have a gamepad to test the specific API, but as far as I can tell it is correctly setting the webview as the first responder after the splash screen vanishes.

Are you doing anything custom in terms of splashscreen or using CDVViewController directly?

@AshleyScirra
Copy link
Author

I don't believe we're doing anything custom with the splashscreen or CDVViewController .

@AshleyScirra
Copy link
Author

A corresponding Chrome for iOS (which uses WKWebView) issue has apparently been fixed now: https://issues.chromium.org/issues/325307469

A Chromium engineer commented:

The gamepad API doesn't work if the WKWebView is not first responder at "the correct" point during a page load. I didn't dig into WebKit to see exactly where this is happening, but you can test with this attached sample app.

Perhaps that's relevant to Cordova too?

@michaeldo1
Copy link

Based on my testing in Chrome, I believe the change in #1337 happens too late to fix the Gamepad API. showLaunchScreen happens in onWebViewPageDidLoad after a delay of fadeSplashScreenDuration. In my testing, any delay more than "0 seconds" after requesting the webview to load would break the Gamepad API.

I attached a sample project to the WebKit bug in comment7 which can be used to test.

Note that keyboard commands appear to work even if the first responder is set later, but Gamepad API doesn't. (This seems like it could be a WebKit bug.)

@AshleyScirra If a change is made in this project, it needs to be debugged further with real hardware in order to find the right place to becomeFirstResponder without breaking any other Cordova functionality. Alternatively, digging into WebKit and suggesting a patch there to accept GamePad API hardware connections even if the firstResponder is set later on (similar to keyboard command handling) could also fix this.

@dpogue
Copy link
Member

dpogue commented Feb 23, 2024

Ahh, that's probably the issue, since we aren't marking the webview as first responder until after the page has finished loading.

I wonder if there are any accessibility concerns with setting the first responder immediately on the webview, even while the splashscreen is displayed...

@dpogue
Copy link
Member

dpogue commented Mar 21, 2024

I've confirmed that making the WKWebView the firstResponder immediately does make the gamepad API work as expected. I still don't love that solution so I might see if it can be fixed in WebKit, but we'll probably need this as a fallback for existing iOS versions.

@AshleyScirra
Copy link
Author

Thanks - appreciate the work on this.

@dpogue
Copy link
Member

dpogue commented Mar 26, 2024

I've opened a pull request to hopefully fix this in WebKit itself: WebKit/WebKit#26444

@dpogue dpogue added the webkit bug Bugs that originate upstream in Apple's WebKit implementation label May 28, 2024
@dpogue
Copy link
Member

dpogue commented Sep 26, 2024

@AshleyScirra I believe this is fixed on the WebKit side as of iOS 18, if you're able to test and confirm that.

Which does still leave a bit of a question around how/whether to address this issue in Cordova for earlier iOS versions... 🤔

@AshleyScirra
Copy link
Author

I tried out the repro steps with the latest Xcode and iOS 18, and it looks like it's working now. Thanks!

If it's not possible to fix older iOS versions, at least it works for the latest one, which is the most important thing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
webkit bug Bugs that originate upstream in Apple's WebKit implementation
Projects
None yet
Development

No branches or pull requests

3 participants