EDIT 4: It seems this only happens when running the app through the debugger. So this is not a major problem.
I have a lot of custom keyboard controls, and a lot of it needs to fire regardless of what control has focus. So I'm using the following code in my MainPage constructor:
public MainPage()
{
Window.Current.CoreWindow.KeyDown += CoreWindow_KeyDown;
Window.Current.CoreWindow.KeyUp += CoreWindow_KeyUp;
}
public void public async void CoreWindow_KeyDown(CoreWindow sender, KeyEventArgs args)
{
// Handle here
}
But I'm having the worst kind of problem. Whenever things are happening on the UI thread it seems to be badly interfering with keyboard input. It's as if it stores some kind of backlog.
For example if I go to an AutoSuggestBox which does a lot of logic each keypress and populates the results with graphics loaded from a server and such, and I type 'abcd' it's quite often the 'd' won't register. Then when I type 'e' a few seconds later, the 'd' will go through but not the 'e'. It's not hardware related, it only does this in my UWP app I'm working on.
In the debugger I have confirmed that this unwanted behavior is all happening before the event is fired. args.VirtualKey is firing a 'd' when I type 'e'.
Also the keyup events only fire like 95% of the time. CoreWindow.PointerWheelChanged
does not exhibit this problem. Gamepad input using the same handler as the keyboard does not have this problem either.
The more activity on the UI thread seems to increase the severity of the problem.
Does anyone know how to remedy this situation? Any kind of workaround or alternative solution, or at least an explanation of what might be happening?
EDIT: I tried setting all 4 options for Window.Current.CoreWindow.Dispatcher.ProcessEvents(), no improvement.
EDIT 2: It seems the fact that I'm capturing CoreWindow.Keydown for global events is a non-sequitur. The problem also happens with any regular KeyDown event on any focused control.
EDIT 3: I believe I realize what's happening and I think it's a bug. My cursory understanding is that UWP keyboard input is sandboxed to prevent keylogger malware or something, so there's some lower-level translation between the raw key input and the VirtualKey that CoreWindow processes. That's fine, but it seems it doesn't work right under certain conditions.
When there is load on the UI thread during rapid keyboard input (like typing) it sometimes does not detect key releases. This is why KeyUp doesn't fire occasionally as I mentioned. This also messes up KeyDown because keys are in a lock state it thinks the key is being held down when in reality it is not. Then when the next key release does register, the CoreWindow dispatcher flushes its queue and the result is that it fires both an event for the previous key input as well as for the new one. So type 'abcd' and 'd doesn't fire. Wait 10 seconds and then press 'e'. Suddenly both 'd' and 'e' will appear. Or more likly press 'd' again because it didn't register the first time, and double 'dd' will display. Absolutely unacceptable behavior by any standard.
The best way you can try to reproduce it yourself is use an AutoSuggestBox that does something blocking like queries and loads image thumbnails in the results as you type. And keep in mind even a tiny bit of UI load seems to cause it. Even if I asynchronously preload the image as a stream or byte array, it still blocks the UI thread for 1-2ms when the BitmapImage source is set. 1-2ms less than a frame of video and thus visually imperceptible, but it seems it's enough to occasionally not detect when a keyboard key is released.
This could be something hardware specific. I've tested different keyboards but not a different computer.