Search code examples
c#webviewuwpkeyboard-eventswebview2

How to properly handle or block Alt and AltGr key behavior in WebView2 or WebView inside a UWP application?


I'm building a UWP application that uses WebView2 to display a web-based interface. However, I'm running into persistent issues with the handling of Alt and AltGr keys. Here's a summary of the problem:

Current Problem:

Key Events in WebView2:

  • When pressing Left Alt, I receive the keydown event, but the keyup event is often missed.
  • When pressing AltGr, the keydown event is recognized inconsistently, often as Ctrl or Alt, and sometimes gets "stuck".
  • Once "stuck," the Alt state seems cached by WebView2, and subsequent key presses (e.g., Ctrl) cause WebView2 to "release" the cached state.

Expected Behavior:

  • I want to reliably handle Alt and AltGr keys within the application without any inconsistencies.
  • I need to block the default navigation behavior of Alt in WebView2 (e.g., unfocusing WebView2 or activating hidden menus).
  • I'm not tied to WebView2 specifically. If someone has a solution for the legacy WebView, I’m open to switching.
  • I want to use Alt and ALT GR in my WebView properly (For clarification: google.com f.e. works fine with inputs like {[]}, but in the guacamole keyboard test, the inputs do not work properly -> images below. As far as I know google and other handles these inputs differently)

What I’ve Tried:

WebView2 Settings:

  • Set AreBrowserAcceleratorKeysEnabled = false to disable browser-level shortcuts.

Global Key Handling:

  • Used CoreWindow.KeyDown and KeyUp to catch and handle keys globally. However, these events are not always triggered when WebView2 is focused.

JavaScript Listeners:

  • Injected keydown and keyup listeners via AddScriptToExecuteOnDocumentCreatedAsync. While this works to some extent, it does not reliably reflect the physical state of the Alt and AltGr keys.

Focus Management:

  • Programmatically refocused WebView2 on specific key presses (e.g., Alt), but this introduced further inconsistencies.

What I’ve Observed:

Sometimes the KeyUp and KeyDown events subscribed from:

if (Window.Current != null && Window.Current.CoreWindow != null)
{
   Window.Current.CoreWindow.KeyDown += CoreWindow_KeyDown;
   Window.Current.CoreWindow.KeyUp += CoreWindow_KeyUp;
   Debug.WriteLine("KeyDown and KeyUp event handlers registered.");
}

are not being called while typing in webview2.

Left Alt:

-keydown works but keyup is frequently missed. Once the key is "stuck," subsequent unrelated key presses (e.g., Ctrl) cause the cached keyup to be processed.

AltGr:

-Similar to Left Alt, keydown is often misinterpreted as Ctrl or Alt. The behavior is inconsistent and varies depending on other keys pressed afterward.

Question:

How can I reliably handle Alt and AltGr key events in WebView2 or WebView within a UWP application? Specifically:

  • How can I block or disable the default behavior of Alt (e.g., navigation)?
  • How can I ensure consistent handling of AltGr without incorrect keydown/keyup caching?

Additional Context:

I’m aware that WebView2 is not officially supported in UWP, and I have also tested this with the legacy WebView control. If someone has a reliable solution for WebView, I’m happy to switch back to it. I’ve explored solutions involving global key hooks, focus management, and JavaScript injection, but none of them completely solved the problem.

Code

Global Key Handlers:

private void CoreWindow_KeyDown(CoreWindow sender, KeyEventArgs args)
{
    Debug.WriteLine($"Global KeyDown: {args.VirtualKey}");

    if (args.VirtualKey == VirtualKey.Menu) // Left Alt
    {
        Debug.WriteLine("Alt detected, resetting focus to WebView2.");
        args.Handled = true; // Prevent default behavior
        ExamBrowser.Focus(FocusState.Programmatic); // Refocus WebView2
    }
}

private void CoreWindow_KeyUp(CoreWindow sender, KeyEventArgs args)
{
    Debug.WriteLine($"Global KeyUp: {args.VirtualKey}");

    if (args.VirtualKey == VirtualKey.Menu) // Left Alt
    {
        Debug.WriteLine("Alt key released.");
        args.Handled = true; // Prevent default behavior
    }
}

document.addEventListener('keydown', function(event) {
    let message = {
        type: 'keydown',
        key: event.key,
        code: event.code,
        ctrlKey: event.ctrlKey,
        altKey: event.altKey,
        shiftKey: event.shiftKey,
        metaKey: event.metaKey
    };
    window.chrome.webview.postMessage(JSON.stringify(message));
});

document.addEventListener('keyup', function(event) {
    let message = {
        type: 'keyup',
        key: event.key,
        code: event.code,
        ctrlKey: event.ctrlKey,
        altKey: event.altKey,
        shiftKey: event.shiftKey,
        metaKey: event.metaKey
    };
    window.chrome.webview.postMessage(JSON.stringify(message));
});

Environment

  • OS: Windows 10
  • Platform: UWP with WebView2 (Chromium-based) and WebView (legacy tested)
  • WebView2 Version: 1.0.113 -prerelease

Pressing ALTGR in the Guacamole Keyboard Tester

Pressing ALTGR in the Guacamole Keyboard Tester

Pressing Left Alt and ALT GR (The Key Up for Left alt only shows up when pressing ALT GR again / Same behaviour when pressing Left control instead of ALT GR)

Pressing Left Alt and ALT GR

Any help is much appreciated!

Update:

When implementing the answer and switching back to Webview I managed to get these results: enter image description here Which look fine to me. But my problem is that Alt GR does not appear, which leads to my initial problem that inputs like {[]} are not working inside a guacamole rdp session. Used code:

        private void Dispatcher_AcceleratorKeyActivated(CoreDispatcher sender, AcceleratorKeyEventArgs args)
        {
            bool isAltPressed = args.KeyStatus.IsMenuKeyDown;
            bool isCtrlPressed = (args.VirtualKey == VirtualKey.Control);

            Debug.WriteLine($"Accelerator Key: {args.VirtualKey}, IsAltPressed: {isAltPressed}, IsCtrlPressed: {isCtrlPressed}");

            if (args.VirtualKey == VirtualKey.Menu && !isCtrlPressed)
            {
                Debug.WriteLine("Blocking Left Alt and refocusing WebView2.");
                args.Handled = true;
                ExamBrowser.Focus(FocusState.Programmatic);
            }
            else if (isAltPressed && isCtrlPressed)
            {
                Debug.WriteLine("AltGr detected, allowing input.");
            }
        }

Solution

  • Pulling heavily from this other SO question, I would suggest trying to use Dispatcher.AcceleratorKeyActivated instead of or in conjunction with KeyDown and KeyUp. I didn't have a chance to test this with your specific configuration, but for example, attaching your event:

    if (Window.Current != null && Window.Current.CoreWindow != null)
    {
       Window.Current.CoreWindow.GetForCurrentThread().Dispatcher.AcceleratorKeyActivated += Dispatcher_AcceleratorKeyActivated;
    }
    

    And your code for your event handler may be something like:

    private void Dispatcher_AcceleratorKeyActivated(CoreDispatcher sender, AcceleratorKeyEventArgs args)
    {
        if ((args.EventType == CoreAcceleratorKeyEventType.KeyDown || args.EventType == CoreAcceleratorKeyEventType.SystemKeyDown)
            && !args.KeyStatus.WasKeyDown)
        {
            if(args.KeyStatus.IsMenuKeyDown) Debug.WriteLine("Alt key pressed.");
        }
    }
    

    Hupefully, that at least helps get you going in the right direction.