Opening the Tab Switcher from an Embedded Web View

Docking/MDI for WPF Forum

Posted 5 months ago by Alex Serio
Version: 22.1.4
Avatar

My application uses a TabbedMdiHost, which opens a tab switcher UI via Ctrl+Tab. One of my document types has a web browser control (a DotNetBrowser BrowserView). The web browser embeds a Chromium window using an HwndHost, so all input ends up getting routed to that window.

I noticed that SwitcherBase.ProcessKeyDown is called when handling a PreviewKeyDown event, so I have my browser key event handler raising that event like so:

if (e.Modifiers.ControlDown && e.VirtualKey == KeyCode.Tab)
{
    KeyEventArgs args = new(
        Keyboard.PrimaryDevice,
        PresentationSource.FromDependencyObject(this),
        0,
        key)
    {
        RoutedEvent = PreviewKeyDownEvent,
        Source = this
    };

    InputManager.Current.ProcessInput(args);
}

This does successfully open the tab switcher UI, but at that point, keyboard input no longer works and the tab switcher UI is stuck open until I click somewhere. Focus does leave the browser, but I'm not sure where it is going or how to figure that out.

Comments (5)

Posted 5 months ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hello,

Did you set our docking:InteropFocusTracking.IsEnabled="True" attached property on your HwndHost?  If so, it should be watching the HwndHost's KeyUp so it can detect switcher close scenarios.


Actipro Software Support

Posted 5 months ago by Alex Serio
Avatar

I am now setting this property to true right after the HwndHost is added to the visual tree, but it doesn't seem to change anything unfortunately.

browserView.InitializeFrom(m_browser); // this sets browserView.Content to an HwndHost

InteropFocusTracking.SetIsEnabled((HwndHost)browserView.Content, true);

I verified in Visual Studio's Live Visual Tree window that the property is indeed set to true.

Posted 5 months ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hello,

Could you make a new simple sample project showing this scenario and send it to our support address, referencing this thread in your email?  Be sure to exclude the bin/obj folders from the .zip you send so it doesn't get spam blocked.  Then we can debug with that and see why it's not working.  Thank you!


Actipro Software Support

Posted 5 months ago by Alex Serio
Avatar

I've just sent a sample project that reproduces the issue.

[Modified 5 months ago]

Answer - Posted 4 months ago by Alex Serio
Avatar

My problem has been solved! (Thanks Bill!). For posterity, here was the solution:

// - m_browser is a DotNetBrowser.Browser.IBrowser
// - this code is run from a custom control that wraps a DotNetBrowser.Wpf.BrowserView
m_browser.Keyboard.KeyPressed.Handler = new Handler<IKeyPressedEventArgs, InputEventResponse>(e =>
{
    if (e.Modifiers.ControlDown && e.VirtualKey == KeyCode.Tab)
    {
        Application.Current.Dispatcher.InvokeAsync(() =>
        {
            if (VisualTreeHelperExtended.GetAncestor<DockingWindow>(this) is { } dockingWindow)
            {
                // This is the secret sauce: Unfocus the web browser and then focus the docking window
                m_browser.Unfocus();
                dockingWindow.Focus();

                System.Windows.Input.KeyEventArgs args = new(
                    Keyboard.PrimaryDevice,
                    PresentationSource.FromDependencyObject(this),
                    0,
                    Key.Tab)
                {
                    RoutedEvent = PreviewKeyDownEvent,
                    Source = this
                };

                InputManager.Current.ProcessInput(args);

                args.RoutedEvent = KeyDownEvent;
                InputManager.Current.ProcessInput(args);
            }
        });

        return InputEventResponse.Suppress;
    }

    return InputEventResponse.Proceed;
});
The latest build of this product (v24.1.2) was released 2 months ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.