Skip to content

[Problem/Bug]: KeyboardEvent repeat is false initially when holding down a key (and handling the first one in the desktop app) #4810

@pushkin-

Description

@pushkin-

What happened?

My app handles KeyDown/KeyUp events. If it detects a key like F10, say, it sets e.Handled = true. If it detects that the key is being held down, it keeps Handled false.

When Handled is false, the webapp gets the keydown events, but the first handle that's called has e.repeat set to false for some reason. All subsequent logs due to the held down key have repeat correctly set to true.

This doesn't happen in my Electron app.

Importance

Moderate. My app's user experience is affected, but still usable.

Runtime Channel

Stable release (WebView2 Runtime)

Runtime Version

128.0.2739.67

SDK Version

1.0.2535.41

Framework

Winforms

Operating System

Windows 11

OS Version

22631.4037

Repro steps

If you open this Electron gist:

  1. hold down F10
  2. in the devtools, you'll see the capture and bubble handlers firing with logs indicating that e.repeat is true.
  3. In the WebView2 app, the first bubble/capture handlers have e.repeat of false and then it gets set to true.
    I can kind of repro in Edge when holding down the Space key on google.com:
    execute this code in devtools:
  window.document.body.addEventListener("keydown", (e) =>
  {
      handler(e, true);
  }, true)

  window.document.body.addEventListener("keydown", (e) =>
  {
      handler(e, false);
  }, false)

  function handler(e, isCapture)
  {
      console.log(`${Date.now()}: ${(isCapture ? "capture" : "bubble")} handler: ${e.key} ${e.type} repeat: ${e.repeat}`);
  }

and see logs:

1726256395642: capture handler:   keydown repeat: false
1726256395642: bubble handler:   keydown repeat: false
1726256396144: capture handler:   keydown repeat: true
1726256396144: bubble handler:   keydown repeat: true

but the difference is that the desktop app is presumably not handling that first key press which is why repeat is false. In my app, I handle the first key press and only subsequent, repeated pressed I don't handle, so I'd expect the devtools in my app to say repeat is always true.

To repro:

  1. open WinForms sample app
  2. add this to AppStartPage.js:
  window.document.body.addEventListener("keydown", (e) =>
  {
      handler(e, true);
  }, true)

  window.document.body.addEventListener("keydown", (e) =>
  {
      handler(e, false);
  }, false)

  function handler(e, isCapture)
  {
      console.log(`${Date.now()}: ${(isCapture ? "capture" : "bubble")} handler: ${e.key} ${e.type} repeat: ${e.repeat}`);
  }

In BrowserForm.cs, since we don't have a built in way to tell if a key is held down, I had to add the following logic. Copy this code in:

	private readonly Dictionary<Keys, bool> _keysDown = new Dictionary<Keys, bool>();

	[LibraryImport("user32.dll")]
	private static partial short GetKeyState(int key);

	private void UpdateKeyStates()
	{
		foreach (KeyValuePair<Keys, bool> entry in _keysDown)
		{
			Keys key = entry.Key;
			if (!IsKeyPressed(key))
			{
				_keysDown.Remove(key);
			}
		}
	}

	private bool IsKeyPressed(Keys key)
	{
		short state = GetKeyState((int)key);
		return state < 0; // the high-order bit being one means the key is pressed
	}

(also updated the project to use .net 8.0)

In the KeyUp handler, call UpdateKeyStates();

In the KeyDown handler, also call UpdateKeyStates(); and then do:

	bool isKeyHeldDown = !_keysDown.TryAdd(e.KeyCode, true);
	if (e.KeyCode == Keys.F10 && !isKeyHeldDown)
	{
		e.Handled = true;
	}
  1. start the app
  2. open devtools
  3. hold down F10
  4. first capture/bubble handler logs in devtools show that repeat is false.
  5. I added tracepoints in the keydown handler to log DateTimeOffset.Now.ToUnixTimeMilliseconds() and isKeyHeldDown. This shows that the repeat=false log happens after the repeated key that we don't handle.

Repros in Edge Browser

No, issue does not reproduce in the corresponding Edge version

Regression

No, this never worked

Last working version (if regression)

No response

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions