Skip to content

Win32 API won't dispatch the key up event of ShiftRight under certain conditions #81674

@dkwingsmt

Description

@dkwingsmt

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:

  1. Disable the logic: patch IsEventThatMustNotRedispatch in 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
 }
  1. 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)'),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}
  1. 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".
1

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    a: desktopRunning on desktopa: text inputEntering text in a text field or keyboard related problemsengineflutter/engine related. See also e: labels.platform-windowsBuilding on or for Windows specifically

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions