flutter / flutter

Flutter makes it easy and fast to build beautiful apps for mobile and beyond
https://flutter.dev
BSD 3-Clause "New" or "Revised" License
165.71k stars 27.36k forks source link

[ios] Incorrect caps lock status while pressing other keys #157241

Open fufesou opened 5 days ago

fufesou commented 5 days ago

Steps to reproduce

I can only test the simulator because I don't have an Apple developer account.

  1. Start an iOS simulator on macOS
  2. Run the sample code
  3. Click CapsLock and some other letter keys

Expected results

CapsLock state matches the physical keyboard connected to macOS.

Actual results

The state is incorrect.

CapsLock events are triggered twice sometimes and do not trigger sometimes when clicking CapsLock.

Code sample

Code sample ```dart import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Keyboard Event Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: const KeyboardEventPage(), ); } } class KeyboardEventPage extends StatefulWidget { const KeyboardEventPage({super.key}); @override _KeyboardEventPageState createState() => _KeyboardEventPageState(); } class _KeyboardEventPageState extends State { int _idx = 0; final List _lastKeyEvents = []; final FocusNode _focusNode = FocusNode(); @override Widget build(BuildContext context) { final child = Scaffold( appBar: AppBar( title: const Text('Keyboard Event Demo'), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Text( 'Press any key:', style: TextStyle(fontSize: 20), ), const SizedBox(height: 20), for (final keyEvent in _lastKeyEvents) Text( keyEvent, style: const TextStyle(fontSize: 16), ), ], ), ), ); return FocusScope( autofocus: true, child: Focus( autofocus: true, canRequestFocus: true, focusNode: _focusNode, onKeyEvent: (node, event) { if (event is KeyDownEvent) { setState(() { var capsLock = false; if (HardwareKeyboard.instance.lockModesEnabled .contains(KeyboardLockMode.capsLock)) { capsLock = true; } _lastKeyEvents.add('$_idx: CapsLock: $capsLock, event: ${event.logicalKey.keyLabel}, ${event.logicalKey.debugName}'); _lastKeyEvents.add(''); _idx++; if (_lastKeyEvents.length > 8) { _lastKeyEvents.removeAt(0); } }); } return KeyEventResult.handled; }, child: child, ), ); } } ```

Screenshots or Video

I click CapsLock one time, but there're two events 24 and 25.

Screenshots / Video demonstration ![image](https://github.com/user-attachments/assets/6651d419-09ef-4102-ac84-0fa3fee27df1)

Logs

No response

Flutter Doctor output

Doctor output ```console [✓] Flutter (Channel stable, 3.24.3, on macOS 14.6.1 23G93 darwin-arm64, locale en-CN) • Flutter version 3.24.3 on channel stable at /Users/rustdesk/workspace/devenv/flutter • Upstream repository https://github.com/flutter/flutter.git • Framework revision 2663184aa7 (6 weeks ago), 2024-09-11 16:27:48 -0500 • Engine revision 36335019a8 • Dart version 3.5.3 • DevTools version 2.37.3 [!] Android toolchain - develop for Android devices (Android SDK version 35.0.0) • Android SDK at /Users/rustdesk/Library/Android/sdk ✗ cmdline-tools component is missing Run `path/to/sdkmanager --install "cmdline-tools;latest"` See https://developer.android.com/studio/command-line for more details. ✗ Android license status unknown. Run `flutter doctor --android-licenses` to accept the SDK licenses. See https://flutter.dev/to/macos-android-setup for more details. [✓] Xcode - develop for iOS and macOS (Xcode 15.2) • Xcode at /Applications/Xcode.app/Contents/Developer • Build 15C500b • CocoaPods version 1.15.2 [✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome [✓] Android Studio (version 2022.2) • Android Studio at /Applications/Android Studio.app/Contents • Flutter plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/9212-flutter • Dart plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/6351-dart • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b802.4-9586694) [✓] VS Code (version 1.94.2) • VS Code at /Applications/Visual Studio Code.app/Contents • Flutter extension version 3.98.0 [!] Proxy Configuration • HTTP_PROXY is set ! NO_PROXY is not set [✓] Connected device (4 available) • iPhone SE (3rd generation) (mobile) • 38639D5D-28FC-44BB-A81F-A4336E3E4DC4 • ios • com.apple.CoreSimulator.SimRuntime.iOS-17-2 (simulator) • macOS (desktop) • macos • darwin-arm64 • macOS 14.6.1 23G93 darwin-arm64 • Mac Designed for iPad (desktop) • mac-designed-for-ipad • darwin • macOS 14.6.1 23G93 darwin-arm64 • Chrome (web) • chrome • web-javascript • Google Chrome 123.0.6312.123 [✓] Network resources • All expected network resources are available. ! Doctor found issues in 2 categories. ```
darshankawar commented 4 days ago

Thanks for the report. I verified on iOS simulator and observed the same behavior. When the caps lock is ON, it correctly shows true event. If we press any other key with caps lock ON, it reports the caps lock event status as false and then if we tap on caps lock to turn it OFF, the event passed is true as shown below:

Simulator Screen Shot - iPhone 13 Pro Max - 2024-10-21 at 15 44 43

Screenshot 2024-10-21 at 3 36 23 PM

Maybe similar / related to https://github.com/flutter/flutter/issues/98377

Stable : 3.24.3
Master : 3.27.0-1.0.pre.120
jmagman commented 3 days ago

Maybe something funky going on around here https://github.com/flutter/engine/blob/62a8bae6ad7d5d4d7d66c718ad9314de177e21fd/shell/platform/darwin/ios/framework/Source/FlutterEmbedderKeyResponder.mm#L552-L558

I don't see anything calling this out particularly in the big hardware keyboard PR https://github.com/flutter/engine/pull/25961