Skip to content

[Windows] HardwareKeyboard misses next key press after alt is pressed #177822

Description

@josh-audio

Steps to reproduce

These steps use Windows 11 with Flutter 3.35.7 (see doctor output below).

  1. Create a new Flutter project with flutter create
  2. In main.dart, add the following in main() after runApp():
    HardwareKeyboard.instance.addHandler((event) {
      if (event is KeyDownEvent) {
        print('Key pressed: ${event.logicalKey.debugName}');
      }
      return false;
    });
  3. Run the project
  4. Try the following two things:
    1. Press the left alt key 4 times
    2. Press alt, then release alt, then press another key

Expected results

I expect an output like the following:

(for the first)
Key pressed: Alt Left
Key pressed: Alt Left
Key pressed: Alt Left
Key pressed: Alt Left

(for the second)
Key pressed: Alt Left
Key pressed: Key A

Actual results

Instead, I get the following output:

(for the first)
Key pressed: Alt Left
Key pressed: Alt Left

(for the second)
Key pressed: Alt Left

Note that this does not happen for other keys, including other modifiers like shift and control.

Code sample

Code sample
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() {
  runApp(const MyApp());

  HardwareKeyboard.instance.addHandler((event) {
    if (event is KeyDownEvent) {
      print('Key pressed: ${event.logicalKey.debugName}');
    }
    return false;
  });
}

// Rest of file unchanged from flutter create output

Flutter Doctor output

Doctor output
[✓] Flutter (Channel stable, 3.35.7, on Microsoft Windows [Version 10.0.26200.6899], locale en-US) [411ms]
    • Flutter version 3.35.7 on channel stable at C:\Users\qbgee\Documents\flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision adc9010625 (9 days ago), 2025-10-21 14:16:03 -0400
    • Engine revision 035316565a
    • Dart version 3.9.2
    • DevTools version 2.48.0
    • Feature flags: enable-web, enable-linux-desktop, enable-macos-desktop, enable-windows-desktop,
      enable-android, enable-ios, cli-animations, enable-lldb-debugging

[✓] Windows Version (11 Home 64-bit, 25H2, 2009) [1,943ms]

[✗] Android toolchain - develop for Android devices [161ms]
    ✗ Unable to locate Android SDK.
      Install Android Studio from: https://developer.android.com/studio/index.html
      On first launch it will assist you in installing the Android SDK components.
      (or visit https://flutter.dev/to/windows-android-setup for detailed instructions).
      If the Android SDK has been installed to a custom location, please use
      `flutter config --android-sdk` to update to that location.


[✓] Chrome - develop for the web [118ms]
    • Chrome at C:\Program Files\Google\Chrome\Application\chrome.exe

[✓] Visual Studio - develop Windows apps (Visual Studio Community 2022 17.14.10) [116ms]
    • Visual Studio at C:\Program Files\Microsoft Visual Studio\2022\Community
    • Visual Studio Community 2022 version 17.14.36327.8
    • Windows 10 SDK version 10.0.26100.0

[!] Android Studio (not installed) [12ms]
    • Android Studio not found; download from https://developer.android.com/studio/index.html
      (or visit https://flutter.dev/to/windows-android-setup for detailed instructions).

[✓] VS Code (version 1.105.1) [11ms]
    • VS Code at C:\Users\qbgee\AppData\Local\Programs\Microsoft VS Code
    • Flutter extension version 3.120.0

[✓] Connected device (3 available) [194ms]
    • Windows (desktop) • windows • windows-x64    • Microsoft Windows [Version 10.0.26200.6899]
    • Chrome (web)      • chrome  • web-javascript • Google Chrome 141.0.7390.123
    • Edge (web)        • edge    • web-javascript • Microsoft Edge 141.0.3537.99

[✓] Network resources [222ms]
    • All expected network resources are available.

! Doctor found issues in 2 categories.

Activity

  1. changed the title [-][Windows] HardwareKeyboard skips every other key press from the alt key[/-] [+][Windows] HardwareKeyboard misses every other key press from the alt key[/+] on Oct 31, 2025
  2. tirth-patel-nc commented on Oct 31, 2025

    @tirth-patel-nc
    Member

    @josh-audio thanks for the report. I can't seem to replicate the reported issue. I tested on 3.35.7 and latest master on macOS.

    Screen.Recording.2025-10-31.at.4.56.35.PM.mov

    could you please check if you can still reproduce this on the latest master? (also share the verbose logs with flutter run -v) also, are there any console errors similar to #107972?

  3. added
    waiting for responseThe Flutter team cannot make further progress on this issue until the original reporter responds
    on Oct 31, 2025
  4. josh-audio commented on Oct 31, 2025

    @josh-audio
    Author

    Hi @tirth-patel-nc, thank you for looking into this!

    My apologies, I missed an important detail in the report. I also cannot reproduce this when running on web with e.g. -p chrome - it only reproduces on a Windows-native build for me. So, I am wondering if this is related to the Windows platform embedder.

    To answer your questions:

    • After running flutter channel master and then flutter run -d windows, I still observe this behavior. See the video below.
    • I do not see any console errors like the ones in that report.

    I have a Linux desktop as well, so I will test it there when I get a chance.

    Recording.2025-10-31.103912.mp4
  5. removed
    waiting for responseThe Flutter team cannot make further progress on this issue until the original reporter responds
    on Oct 31, 2025
  6. changed the title [-][Windows] HardwareKeyboard misses every other key press from the alt key[/-] [+][Windows] HardwareKeyboard misses next key press after alt is pressed[/+] on Oct 31, 2025
  7. josh-audio commented on Oct 31, 2025

    @josh-audio
    Author

    My motivating case for this is for a complex editor, where modifier keys including alt are used to change the current mouse action. Examples include:

    • Ctrl + click + drag to create a multi-selection
    • Alt + mouse wheel to constrain editor zoom behavior

    For this use-case, my alt-modified mouse actions were showing the behavior I originally reported here.

    After testing this morning, I've realized that the issue is a bit simpler: If "alt" is pressed and released, Flutter will miss the next keystroke. I have modified the report to reflect this.

    If I press and release "alt", "a", "b", and "c" in that order, I get the following output:

    Image

    I've tried checking if it does anything when I press and release "alt", then press another key. I've tried a lot of combinations, but so far I can't find any functionality tied to this behavior, though it does play a Windows error sound when I press the second key.

  8. josh-audio commented on Oct 31, 2025

    @josh-audio
    Author

    Looks like the error sound is already reported: #119251

    I see a workaround in that issue for this specific case (press alt, release alt, press key), but no mention of losing the key press. I can't try it now, but I will try it as soon as I can and report here.

  9. josh-audio commented on Oct 31, 2025

    @josh-audio
    Author

    Just tried it, and it addressed the problem for me.

    I added the following case to FlutterWindow::MessageHandler() in flutter_window.cpp:

    case WM_SYSCOMMAND:
      if (wparam == SC_KEYMENU) {
        // Disable ALT application menu.
        return 0;
      }
      break;
    Image

    The full file is below.

    flutter_window.cpp
    #include "flutter_window.h"
    
    #include <optional>
    
    #include "flutter/generated_plugin_registrant.h"
    
    FlutterWindow::FlutterWindow(const flutter::DartProject& project)
        : project_(project) {}
    
    FlutterWindow::~FlutterWindow() {}
    
    bool FlutterWindow::OnCreate() {
      if (!Win32Window::OnCreate()) {
        return false;
      }
    
      RECT frame = GetClientArea();
    
      // The size here must match the window dimensions to avoid unnecessary surface
      // creation / destruction in the startup path.
      flutter_controller_ = std::make_unique<flutter::FlutterViewController>(
          frame.right - frame.left, frame.bottom - frame.top, project_);
      // Ensure that basic setup of the controller was successful.
      if (!flutter_controller_->engine() || !flutter_controller_->view()) {
        return false;
      }
      RegisterPlugins(flutter_controller_->engine());
      SetChildContent(flutter_controller_->view()->GetNativeWindow());
    
      flutter_controller_->engine()->SetNextFrameCallback([&]() {
        this->Show();
      });
    
      // Flutter can complete the first frame before the "show window" callback is
      // registered. The following call ensures a frame is pending to ensure the
      // window is shown. It is a no-op if the first frame hasn't completed yet.
      flutter_controller_->ForceRedraw();
    
      return true;
    }
    
    void FlutterWindow::OnDestroy() {
      if (flutter_controller_) {
        flutter_controller_ = nullptr;
      }
    
      Win32Window::OnDestroy();
    }
    
    LRESULT
    FlutterWindow::MessageHandler(HWND hwnd, UINT const message,
                                  WPARAM const wparam,
                                  LPARAM const lparam) noexcept {
      // Give Flutter, including plugins, an opportunity to handle window messages.
      if (flutter_controller_) {
        std::optional<LRESULT> result =
            flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam,
                                                          lparam);
        if (result) {
          return *result;
        }
      }
    
      switch (message) {
        case WM_FONTCHANGE:
          flutter_controller_->engine()->ReloadSystemFonts();
          break;
        case WM_SYSCOMMAND:
          if (wparam == SC_KEYMENU) {
            // Disable ALT application menu.
            return 0;
          }
          break;
      }
    
      return Win32Window::MessageHandler(hwnd, message, wparam, lparam);
    }
    
  10. FusoraTech commented on Nov 1, 2025

    @FusoraTech

    Mac, Windows and Linux need to implement "menus". Menu items on Windows react as a combination of Alt+Key (Accelerator), or Alt alone, bringing focus to the menu, and another action key after. This seems linked to some kind of key press consumption from some menu engine. I think it needs analysis from @mattkae and how window menus are being implemented in the new windowing system.

  11. josh-audio commented on Nov 2, 2025

    @josh-audio
    Author

    The workaround above has at least one major drawback so far. If I press alt + tab to switch to another application, then use the mouse to put the application back in focus, HardwareKeyboard.instance.isAltPressed will be true until I press alt again.

    I can work around this using a plugin (specifically https://pub.dev/packages/window_manager), but it's quite involved; essentially:

    1. Implement the workaround described above
    2. Add a key handler to HardwareKeyboard that listens for alt, ctrl, and shift, and records the current pressed state in my own custom singleton store
    3. Use WindowListener.onWindowBlur() from window_manager to reset these values when the window loses focus
  12. tirth-patel-nc commented on Nov 3, 2025

    @tirth-patel-nc
    Member

    Looks like the error sound is already reported: #119251

    @josh-audio thanks for the detailed comments. I'll keep this open for team input and tracking.

  13. added
    platform-windowsBuilding on or for Windows specifically
    and removed
    in triagePresently being triaged by the triage team
    on Nov 3, 2025
  14. 1 remaining item

  15. added
    P2Important issues not at the top of the work list
    triaged-windowsTriaged by the Windows platform team
    on Nov 12, 2025
  16. mattkae commented on Nov 13, 2025

    @mattkae
    Contributor

    I've been looking into this today. It looks like consuming the WM_SYSKEYDOWN (VK_MENU) message is the way to go, but I am seeing that it affects alt tab. I should be able to work around this, but I'll have to think about it a bit more :)

    As for the multi-window work: we should provide a hook in the API for users to do handle this when asked to do so by the embedder. This shouldn't be too difficult to add in my opinion, and we can do the interception of the message in the meantime.

  17. github-actions commented on Dec 10, 2025

    @github-actions

    This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

  18. locked as resolved and limited conversation to collaborators on Dec 10, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work lista: desktopRunning on desktopengineflutter/engine related. See also e: labels.platform-windowsBuilding on or for Windows specificallyr: fixedIssue is closed as already fixed in a newer versionteam-windowsOwned by the Windows platform teamtriaged-windowsTriaged by the Windows platform team

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions