We have had a number of reports of the Enter key not working in Chrome while Keyman Desktop is active.  I took on the task of investigating this issue and here's how it panned out.  Note: this post will be quite technical so if that doesn't interest you, do feel free to skip it!

I started by reproducing the issue with the lastest release of Chrome.  Basically, when a Keyman Desktop keyboard is active, the Enter key will not submit any forms in Chrome, nor will it work in a text area.  Quite an annoying issue!  I was able to reproduce the issue without any trouble.

The next step was to download the full Chrome source and build it.  This was quite an involved task, as none of our development machines were configured in the specific requirements that Chromium requires for building, and none of them had the hardware resources required (recommended 8GB RAM + 8 CPU cores!)  I had to configure a new computer just to build Chromium. In all, I downloaded over 1.2GB of Chrome source, plus over 2GB of development tools.  However, once all was in place, the Chromium build went smoothly, and I was able to start debugging.

With many thousands of source files, it could be difficult to locate the place within Chromium where the Enter key was being processed.  I started by using Spy++ to find the window class for the browser window with focus, and then searched the sources (using the online search, much faster!) for the window class name thus identified, Chrome_RenderWidgetHostHWND.  Once I had found this, I was actually in the correct source file, and only a minute or later I had located the message handler for WM_KEYDOWN, RenderWidgetHostViewWin::OnKeyEvent.  I added a breakpoint in this function, and it was now time to run Chromium and press Enter.

I loaded a page with a form, clicked on an element in the form, then pressed Enter, which then caused the debugger breakpoint to fire, and I stepped through the message handler function.  To my surprise and pleasure, the cause of the problem jumped out immediately.  The lines below from the RenderWidgetHostViewWin::OnKeyEvent function in Chromium are the relevant lines, and the red line below is specifically where we ended up:

  // Special processing for enter key: When user hits enter in omnibox
  // we change focus to render host after the navigation, so repeat WM_KEYDOWNs
  // and WM_KEYUP are going to render host, despite being initiated in other
  // window. This code filters out these messages.
  bool ignore_keyboard_event = false;
  if (wparam == VK_RETURN) {
    if (message == WM_KEYDOWN || message == WM_SYSKEYDOWN) {
      if (KF_REPEAT & HIWORD(lparam)) {
        // this is a repeated key
        if (!capture_enter_key_)
          ignore_keyboard_event = true;
      } else {
        capture_enter_key_ = true;
      }
    } else if (message == WM_KEYUP || message == WM_SYSKEYUP) {
      if (!capture_enter_key_)
        ignore_keyboard_event = true;
      capture_enter_key_ = false;
    } else {
      // Ignore all other keyboard events for the enter key if not captured.
      if (!capture_enter_key_)
        ignore_keyboard_event = true;
    }
  }

The Enter key was always being ignored when it was sent from Keyman Desktop! But why was this happening?  It seems the KF_REPEAT flag was being set on some keystrokes from Keyman Desktop, but we were never setting that flag. In fact, we didn't even have the ability to set that flag using the SendInput API!

It turns out that SendInput uses the existing keyboard state when synthesizing its keystrokes, and so when the Enter key is pressed by the user, and Keyman Desktop swallows that keystroke and then later reproduces it, the SendInput function uses the existing (real) KEYDOWN state of VK_RETURN within the keyboard state buffer and thinks that Keyman Desktop's synthesized VK_RETURN is now a repeat, and hence sets the KF_REPEAT flag.

Previously, we had avoided setting the keyboard state for each key as it is pressed.  We now have a beta fix that resets the keyboard state for a specific key before sending a keystroke, so that the correct flags will be set on the WM_KEYDOWN message.  In our testing, this is working well, but we need to test a bit more yet with other applications to ensure no side effects arise.  This fix is in build 8.0.347.0, downloadable from our beta home page.

Digression: This issue arose with Chrome due to a fix made more than two years ago, in Chrome issue 26755.  The Enter issue with Keyman Desktop is noted in Chrome issue 46451.  I have noted the link between the two issues for the Chromium developers to work through if they so desire.  I'm sorry it took so long to trace the cause of this issue…

Categories: Developing Keyman

0 thoughts on “Debugging the non-functional Enter key in Chrome”

Leave a Reply

Your email address will not be published. Required fields are marked *

Related Posts

Developing Keyboards

Using Keyman Engine for Android to create a custom keyboard app

Note: You must have a license for Keyman Engine for Android in order to access the resources documented in this blog. (Purchase a license) Keyman Engine for Android allows you to use any Keyman touch Read more…

Developing Keyman

An improved experience with deadkeys on European hardware keyboards

For many years, Keyman Desktop has adapted layouts to work more accurately with European hardware keyboards. For example, a US English keyboard has a top alphabetic row of QWERTYUIOP, but a French keyboard has instead AZERTYUIOP. Read more…

Amharic

Products we will be discontinuing in March 2015

Earlier this month, we conducted an internal review of our product offerings and development status. As a result of this review, we determined that we would stop developing and distributing several products. This is important Read more…