-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Description
Under certain conditions, when the right shift key is released, Win32 API won't dispatch the key up event. This issue has been reported as #75675.
This issue is unrelated to Flutter classes, such as KeyboardManager or TextInputPlugin, since this message is not even received by the system hook WindowWin32::WndProc. It is probably related to the implementation of Win32, although we do hope not.
It is found out that this happens when the ShiftRight KeyDown event is redispatched. The reason is unknown.
Reproduction step:
- Disable the logic: patch
IsEventThatMustNotRedispatchin keyboard_key_embedder_handler.cc as follows:
static bool IsEventThatMustNotRedispatch(int virtual_key, bool was_down) {
#ifdef WINUWP
return false;
#else
+ return false;
- return virtual_key == VK_RSHIFT && !was_down;
#endif
}- Run the following sample code with
flutter run -d windows --local-engine=host_debug_unopt:
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
class MyWidget extends StatefulWidget {
@override
State<StatefulWidget> createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
@override
void initState() {
WidgetsBinding.instance.window.onKeyData = _handleKey;
super.initState();
}
bool leftShiftDown = false;
bool rightShiftDown = false;
bool returnValue = false;
bool _handleKey(ui.KeyData event) {
setState(() {
if (event.logical == LogicalKeyboardKey.shiftLeft.keyId) {
leftShiftDown = event.type != ui.KeyEventType.up;
} else if (event.logical == LogicalKeyboardKey.shiftRight.keyId) {
rightShiftDown = event.type != ui.KeyEventType.up;
}
});
return returnValue;
}
TextStyle get textStyle => const TextStyle(
fontSize: 12,
);
@override
Widget build(BuildContext context) {
return Directionality(
textDirection: TextDirection.ltr,
child: Material(
child: Column(
children: <Widget>[
Text('Left down: $leftShiftDown'),
Text('Right down: $rightShiftDown'),
ColoredBox(
color: returnValue ? Colors.blue : Colors.grey,
child: GestureDetector(
onTap: () {
setState(() {
returnValue = !returnValue;
});
},
child: Container(
padding: EdgeInsets.all(10),
child: Text('Returning ${returnValue ? 'true' : 'false'} (toggle here)'),
),
),
),
],
),
),
);
}
}- Tap ShiftLeft and ShiftRight and toggle the return value by clicking the "Returning ..." box.
Actual behavior: When the return value is false, after shift right is tapped, its state stays "true".

Expected behavior: No matter what the return value is, tapping shift right should make ShiftRight released.
For now this issue has been bandage-fixed by flutter/engine#25882. It would be nice to keep investigating this problem and see if we can find the root cause, or at least narrow the case that needs special treatment.