Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

First Navigation in Winform WebView2 Instance Steals Focus #862

Closed
AidanVizzion opened this issue Jan 27, 2021 · 49 comments
Closed

First Navigation in Winform WebView2 Instance Steals Focus #862

AidanVizzion opened this issue Jan 27, 2021 · 49 comments
Assignees
Labels
bug Something isn't working tracked We are tracking this work internally.

Comments

@AidanVizzion
Copy link

AidanVizzion commented Jan 27, 2021

Hi,

I'm testing out WebView2 in Winform C# applications, and it seems that whenever a WebView2 instance is created, and the first navigation is completed, the application automatically steals focus from any other application that was focused at the time.

To illustrate, let's say I have an application called SampleApp with the following form:

image

And SampleApp has the following code:

using System;
using System.Windows.Forms;

namespace WebView2_Winform_Focus
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void msNav_Click(object sender, EventArgs e)
        {
            webview.Source = new Uri("https://microsoft.com");
        }
    }
}

When I click the Navigate to Microsoft.com button, and quickly click outside of SampleApp shifting the focus the away, the focus is immediately brought back to SampleApp after the navigation to microsoft.com is complete. Is this expected behavior, or a bug? And is there anyway I can prevent the focus from moving back to SampleApp after the navigation is complete?

Thank you!

AB#31515353

@jarno9981
Copy link

i can give you my code maybe helping use winforms 4.6.2 framework

@jarno9981
Copy link

public frmBrowser()
{
InitializeComponent();
webView21.NavigationStarting += EnsureHttps;
InitializeAsync();
}

    void EnsureHttps(object sender, CoreWebView2NavigationStartingEventArgs args)
    {
        String uri = args.Uri;
        if (!uri.StartsWith("https://"))
        {
            webView21.CoreWebView2.ExecuteScriptAsync($"alert('{uri} may not be safe, try an https link')");
            args.Cancel = true;
            txtUrl.IconLeft = Properties.Resources.delete_shield_40px;
        }
        else
        {
            txtUrl.IconLeft = Properties.Resources.shield_48px;
        }
    }

    private async void frmBrowser_Load(object sender, EventArgs e)
    {
        panel2.Visible = false;
        panel2.Enabled = false;
    }

    protected TitleBarTabs ParentTabs
    {
        get
        {
            return (ParentForm as TitleBarTabs);
        }
    }

    private void btnRefresh_Click(object sender, EventArgs e)
    {
        webView21.Reload();
    }

    private void btnGo_Click(object sender, EventArgs e)
    {
        if (webView21 != null && webView21.CoreWebView2 != null)
        {
            webView21.CoreWebView2.Navigate(txtUrl.Text);
        }
    }

    private void txtUrl_KeyPress(object sender, KeyPressEventArgs e)
    {

    }

    async void InitializeAsync()
    {
        await webView21.EnsureCoreWebView2Async(null);
        webView21.CoreWebView2.WebMessageReceived += UpdateAddressBar;
        await webView21.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync("window.chrome.webview.postMessage(window.document.URL);");
    }

    void UpdateAddressBar(object sender, CoreWebView2WebMessageReceivedEventArgs args)
    {
        String uri = args.TryGetWebMessageAsString();
        txtUrl.Text = uri;
        webView21.CoreWebView2.PostWebMessageAsString(uri);
    }


    private void txtUrl_KeyUp(object sender, KeyEventArgs e)
    {
        if (e.KeyCode == Keys.Enter && txtUrl.Text.Trim().Length > 0)
        {
            //detect url
            if (txtUrl.Text.Contains("."))
            {
                //ites a url
                webView21.CoreWebView2.Navigate(txtUrl.Text.Trim());

            }
            else
            {
                //its a search
                webView21.CoreWebView2.Navigate("https://www.google.com/search?client=opera&q=" + txtUrl.Text.Trim().Replace(" ", "+") + "&sourceid=opera&ie=UTF-8&oe=UTF-8");
            }
        }
    }

    private void btnBack_Click(object sender, EventArgs e)
    {
        webView21.GoBack();
    }

    private void btnForward_Click(object sender, EventArgs e)
    {
        webView21.GoForward();
    }

    private void btnMenu_Click(object sender, EventArgs e)
    {
        panel2.Visible = true;
        panel2.Enabled = true;
    }

    private void btnClose_Click_1(object sender, EventArgs e)
    {
        panel2.Visible = false;
        panel2.Enabled = false;
    }


    private void btnSettings_Click(object sender, EventArgs e)
    {
        Settings st = new Settings();
        st.ShowDialog();
    }

}

mainform

@AidanVizzion
Copy link
Author

i can give you my code maybe helping use winforms 4.6.2 framework

Did you also have issues with WebView2 stealing focus? And did your code solve your issues?

@champnic champnic self-assigned this Jan 28, 2021
@jarno9981
Copy link

Yes above framwork 4.6.2 had it but after going to 4.6.2 and changing the navigatie code i didn't have it any more

@champnic
Copy link
Member

I believe this behavior is by design, but I'll open a bug on our backlog to verify.

Are you seeing this behavior in other instances, or only on first navigate when quickly making the app lose focus? Does @jarno9981's workaround work for you?

@champnic champnic added bug Something isn't working tracked We are tracking this work internally. labels Jan 28, 2021
@AidanVizzion
Copy link
Author

AidanVizzion commented Jan 28, 2021

This behavior is seen on first navigation of any WebView2 instance when quickly making the app lose focus, and the workaround of downgrading to .NET 4.6.2 did not work.

@jarno9981
Copy link

Yes work around works for me

@champnic
Copy link
Member

champnic commented Feb 2, 2021

@AidanVizzion Can you try running the app without the debugger attached? Do you still see the same behavior? We think it may be related to running under the VS debugger. In general, background apps shouldn't be able to force themselves to be foreground.

@AidanVizzion
Copy link
Author

@AidanVizzion Can you try running the app without the debugger attached? Do you still see the same behavior? We think it may be related to running under the VS debugger. In general, background apps shouldn't be able to force themselves to be foreground.

@champnic Yes, we still see the same behavior when we build for Release and run the .exe.

@champnic
Copy link
Member

champnic commented Feb 4, 2021

How are you launching the app? I wasn't referring to Debug vs Release builds, but instead referring to "Start without debugging":
image

Though when you say "run the .exe" maybe you are referring to starting the .exe directly from Explorer. If so, we'll take a closer look.

@AidanVizzion
Copy link
Author

Yes, we were starting the .exe directly from Explorer and seeing the same behavior. We also see the same behavior when starting without debugging like you mentioned,

@champnic
Copy link
Member

champnic commented Feb 5, 2021

Thanks for trying it out and confirming the issue is still there. We'll take a look on our end.

@johna-ms
Copy link
Contributor

johna-ms commented Feb 20, 2021

Hi, I'm the dev looking into this issue. @AidanVizzion I'm unable to repro for .NET Framework 4.7.2 WinForms. I tried out your sample code but when I click on the button to navigate, then switch to another window, the navigation completes in the background and does not bring the WinForms window to the forefront. Could you provide the OS, SDK and runtime version you are seeing this on?

@AidanVizzion
Copy link
Author

I'm running on Windows 7. SDK version is 1.0.705.50. Runtime version version is 89.0.774.54.

@RickStrahl
Copy link

RickStrahl commented Jun 3, 2021

I'm seeing the same thing in a WPF application where when the WebView is navigated focus does not work properly in other control on the same form.

It's really odd, but if I don't navigate the WebView I get normal behavior, but with the WV navigated I see this funky behavior:

  • It looks like another control is focused
  • But when I press a key it doesn't work initially. Takes multiple keypresses
  • Windows command keys like Enter/Ctrl-Enter will trigger the form's control box on first click, then work

It seems that the WV is not returning focus properly back to the Window after rendering. As said, visually it appears that focus is in the right place, but it's not behaving correctly when using keys. Pressing keys multiple times, or clicking on the Window provides proper control focus to the actually focused control.

I've not found a good way to work around this - even if I delay focusing or focus multiple times in code using the Dispatcher, this same behavior persists. Only some active UI operation seems to get the focus to work correctly (like a delayed key sequence like ctrl, then Enter for example).

Here's what this looks like:

WpfWebViewFocusIssue

Notice that I press alt-c to open the form. Form opens and focus goes to the combo box (you can see it by way of the highlight.

If I press Enter, focus goes to the control box, if I press Control Enter it goes to the control box. If I esc out of the control box, then the Combo gets focus and I can scroll through the options. IOW, the combo had focus all along but somehow due to the WV it's not actually acting like its focused.

I've tried all sorts of stuff including delaying and dispatcher activation. Forcing focus to the form first, activating. None of it seems to help other than pressing keys that basically get eaten. If I type a letter like c into the combo (which should navigate to c++ for example, the key is just lost. Yet I have a focus rectangle around the combo control.

If I don't navigate the WebView, then focus works as expected when the form is activated.

@pontusn
Copy link

pontusn commented Apr 5, 2022

Starting yesterday this bug also affects window.location.reload() and ICoreWebView2::Reload.

For our multi-window application this effectively mean that focus is transfered between windows without any user interaction as soon as something updates content in WebView2.

Only workaround sofar is to avoid calling reload when root window is not active...
::GetAncestor(hWnd, GA_ROOT) == ::GetActiveWindow()

Currently this is a major issue for our customers that recieve automatic updates:

  • Are there any viable workaround we can implement?
  • How soon can the underlying problem be resolved?

@champnic

@champnic
Copy link
Member

champnic commented Apr 7, 2022

@pontusn Thanks for the update. What OS versions are you seeing this on? And presumable "starting yesterday" means with the new v100 runtime? If you use the older v99 runtime does the issue go away? (You can use Fixed Version runtime download for v99 to check)

@pontusn
Copy link

pontusn commented Apr 7, 2022

@champnic
Not sure about OS-distribution, but mostly Windows 10. I reproduced on Windows 11.

The problem appeared widely from "nowhere", hence it's some automatic upgrade.

@champnic
Copy link
Member

champnic commented Apr 7, 2022

What version of the runtime are you currently seeing this on?

@pontusn
Copy link

pontusn commented Apr 8, 2022

WebView2 Runtime 100.0.1185.36
WevView2 SDK 1.0.1108.44

@champnic
Copy link
Member

champnic commented Apr 8, 2022

Are you able to see the issue if you use the Fixed Version 99?
https://developer.microsoft.com/en-us/microsoft-edge/webview2/

@pontusn
Copy link

pontusn commented Apr 11, 2022

@champnic
Using fixed version I've now confirmed that behavior has changes between versions 99.* and 100.*

Repro steps:

  • Display WebView2 in two different top-level windows
  • Partially cover one window with the other
  • Issue window.location.reload() for the background window

99.*:
Content is reloaded in background.

100.*:
Window is activated and moved to foreground during reload.

Currently we have mitigated this problem by disabling the Refresh-method in our API for inactive windows.

@dhohlin
Copy link

dhohlin commented Apr 13, 2022

facing the same problem.
After Runtime update to 100.* WebView is stealing focus from other control in my application. Works fine with 99.*.
@pontusn can you please elaborate a little bit on the workaround you use ?
@champnic do you have any more details on why it's happening and how to properly correct it?

@pontusn
Copy link

pontusn commented Apr 13, 2022

In our application the problem mostly occure due to legacy customizations that refresh background windows. Now we detect this and use an internal flag to delay refresh until activated.

Snipplet in previous post is used to detect if top level parent is active.

Unfortunately this does not handle refresh triggered by JS window.location.reload etc, but in our case that is not a problem.

@champnic
Copy link
Member

No details on why this is happening yet. We'll take a look soon though to try and get a fix.

@dhohlin
Copy link

dhohlin commented Apr 18, 2022

I have easier way of reproducing the issue.
In @AidanVizzion's repro steps just make sure that webview is hidden before source is assigned and then shown again afterwards:

private void msNav_Click(object sender, EventArgs e)
{
	webview.Hide();
	webview.Source = new Uri("https://microsoft.com");
	webview.Show();
}

@champnic can you share any timeline when this bug can be expected to be looked at ?

@johna-ms
Copy link
Contributor

johna-ms commented Apr 18, 2022

Hi I'll take a look at this and try in the next couple days. Thanks for the repro information!

@johna-ms
Copy link
Contributor

So I was able to repro some things but not others. @dhohlin does your bug repro w just setting source? I found that this focus 'stealing' behavior can repro in WPF w non-webview controls. If you have 2 windows one on top of the other, setting the visibility of one of them from Hidden to Visible causes them to take the foreground.

@pontusn are you working in a Win32 application? When I have 2 windows open w WebViews in them, I do not see one taking focus from the other when reloading. WebView will successfully reload in the background. It would be helpful if you could help come up with a min repro app.

@pontusn
Copy link

pontusn commented Apr 19, 2022

We are hosting WebView2 via Win32 as an drop-in replacement for IE/WebBrowser via a ATL-based ActiveX. Our main application is MFC-based.

The problem is most evident when there are multiple top-level windows, each hosting several instances of WebView2.

Any reload (from JS or via external API) will result in focus theft.

Problem can also be seen for input controls hosted in same top-level as WebView2, however this is more subtle.

Maybe I can PM details on how to use our desktop client to reproduce? Not sure if I can find time to build standalone app to repro...

@johna-ms
Copy link
Contributor

Sure that sounds reasonable, please PM me

@dhohlin
Copy link

dhohlin commented Apr 21, 2022

My tests were done in WinForms application. I click on button (handler as listed above) and after content is rendered by WebView button is not focused anymore. I.e. pressing arrow keys is handled by WebView itself.
Do you need the complete sample @johna-ms ?

@johna-ms
Copy link
Contributor

@dhohlin I think the focus behavior you are describing is an artifact of the WPF framework, not from WebView. Could you confirm if your bug behavior repros if you use a control other than WebView?

@dhohlin
Copy link

dhohlin commented Apr 25, 2022

@johna-ms it's definitely not any artifact of WPF. I am using windows forms and I can clearly see that wrong focus behaviour occurs with latest available evergreen WebView runtime (100.0.1185.50) and is not occurring if I use fixed runtime version 99.0.1150.55.
I am attaching a test application which has WebView instance and a text box. TestFirstLoad.zip
Repro steps are as simple as:

  1. build and start test app
  2. type something in text box, then press enter or space - WebView will load web page. You will see that focus is still in text box (and you can continue typing there)
  3. type something else ans again press enter or space - WebView will load web page but not focus will jump to WebView and stay there.
  4. you use mouse and move focus back to WebView but it will again steal focus after next load.

Once again issue is clearly happening in 100.0.1185.50 and not in 99.0.1150.55.
Hope this makes sense. Please let me know if any additional info is needed.

@johna-ms
Copy link
Contributor

Thanks for the update dhohlin I'll take a look at your repro app

@dhohlin
Copy link

dhohlin commented Apr 29, 2022

any luck there? do you need any more info may be ? @johna-ms

@a-legotin
Copy link

@johna-ms Any updates on this? Looks like I'm facing the same problem.

@johna-ms
Copy link
Contributor

johna-ms commented May 4, 2022

Hi guys, sorry for the late update. I've been on some high priority work the past couple days. I'll give an update this week

@johna-ms
Copy link
Contributor

johna-ms commented May 7, 2022

@dhohlin I'm able to repro w your app and have a stack. It's looking like this is on us and I have a fix in mind. There are still some inconsistencies in my investigation I need to iron out. I will update more next week

@pontusn
Copy link

pontusn commented May 11, 2022

Update:
Today I discovered that setting vibility via ICoreWebView2Controller::put_IsVisible from NavigationComplete-handler triggers the problem in our application.

Workaround:
Remove calls...

    m_spWebViewController->put_IsVisible(FALSE);
    m_spWebViewController->put_IsVisible(TRUE);

These calls were added to workaround some previous bug for request filters in open.window. Now I've refined this other workaround to avoid focus theft.

@johna-ms

@dhohlin
Copy link

dhohlin commented May 12, 2022

any updates @johna-ms ?

@johna-ms
Copy link
Contributor

Sorry I wasn't able to take a look at this this week. As @pontusn has discovered, this looks to be an issue with put_IsVisible from our side. I'll try and update early next week.

@dhohlin
Copy link

dhohlin commented May 18, 2022

@johna-ms any luck with the fix may be ?

@johna-ms
Copy link
Contributor

Confirming this is a bug related to put_IsVisible. I've prototyped a fix locally and can likely have it in for 103 stable. I'll update the thread when the fix is available to try in canary

@dhohlin
Copy link

dhohlin commented May 19, 2022

Great news, thanks @johna-ms !

@dvdrw1024
Copy link

I was frantically trying to understand what went wrong for weeks now :-( .
I've finally stumbled on this thread today. Hope to see 103 with the fix soon.
Thanks @johna-ms

@johna-ms
Copy link
Contributor

johna-ms commented Jun 8, 2022

Hello all, this actually ended up being applied to 102 as well. Please try out 102 or 103 and see if the issue is fixed for you

@dvdrw1024
Copy link

Hello all, this actually ended up being applied to 102 as well. Please try out 102 or 103 and see if the issue is fixed for you

Can confirm. 102.0.1245.33 fixes the issue for me. Many thanks.

@johna-ms
Copy link
Contributor

johna-ms commented Jun 8, 2022

Thanks! Resolving this. Please reawaken if there is still an issue.

@johna-ms johna-ms closed this as completed Jun 8, 2022
@dhohlin
Copy link

dhohlin commented Jun 9, 2022

Confirmed fixed in 102.0.1245.33. Thanks @johna-ms !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working tracked We are tracking this work internally.
Projects
None yet
Development

No branches or pull requests

9 participants