Andy Krouwel
Andy Krouwel

Reputation: 1399

How can I get keyboard input when WebView visible in C++/XAML/UWP App?

I have a game app that is rendered on a Canvas, with an interface rendered in a WebView.

All the pre-game menus happen in the WebView. When the game starts I switch the WebView to a page with a transparent background so you can see the game Canvas through it, but I can still overlay some interface elements.

This all works fine graphically, and I can see my game clearly with the WebView interface overlayed. I can communicate between the game and the interface quite happily.

The problem I have is getting the WebView to give up the keyboard, so I can use the keys to control the game.

My keyboard listener is triggered on the (theoretically) global event Window.Current.CoreWindow.KeyDown, so it should get keyboard events whatever has the focus.

If I hide the WebView everything works fine, the keyboard events are picked up and the game is controllable. Obviously though I can't see the overlayed elements.

Is there some way to let me receive the keyboard events when the WebView is visible?

This is a Win 10/UWP app written in XAML/C++. Target platform is Win 10 10.0.14393.0/ minimum 10.0.10586.0 Tested on Surface Book running Windows 10 v1703 15063.674

Upvotes: 1

Views: 1538

Answers (3)

Avatar
Avatar

Reputation: 81

We have a Webview that must be interactive in our game at all times. The least ugly workaround that I have found so far is injecting a global event listener into the javascript to hook keyboard input, and relaying this back to the app via notify()

function onKeyDown(ev: KeyboardEvent) {

    let wrapper = { keyDown: ev }
    window['external']['notify'](JSON.stringify(wrapper));
}

function onKeyUp(ev: KeyboardEvent) {

    let wrapper = { keyUp: ev }
    window['external']['notify'](JSON.stringify(wrapper));
}


...

        let options: AddEventListenerOptions = { capture: true, passive:true,once:false } 
        document.addEventListener("keydown", onKeyDown, options);
        document.addEventListener("keyup", onKeyUp, options);

Upvotes: 0

duo
duo

Reputation: 330

Had a similar problem but managed to fix it with this trick based on Andy's answer:

DispatcherTimer timer = new DispatcherTimer
{
    Interval = TimeSpan.FromMilliseconds(100)
};

timer.Tick += (s, e) =>
{
    if (FocusManager.GetFocusedElement() is WebView webView)
    {
        webView.Visibility = Visibility.Collapsed;
        webView.Visibility = Visibility.Visible;
    }
};

timer.Start();

Upvotes: 0

Andy Krouwel
Andy Krouwel

Reputation: 1399

It is possible to release the focus from the WebView by hiding and then showing it again immediately.

webView->Visibility = Visibility::Collapsed;
webView->Visibility = Visibility::Visible;

Even if there's nowhere else for the focus to go - after this operation, FocusManager::GetFocusedElement() will return null.

The webview will remain visible, but keyboard events can now be received via Window.Current.CoreWindow.KeyDown.

Note however that any interaction with the webview (eg. touch, navigation) will cause it to regain focus and you will stop receiving keyboard events.

This isn't a very satisfactory solution, but it sort-of fulfills the requirement to see the webview but also receive keyboard events.

Upvotes: 2

Related Questions