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

WebView2 breaks window message processing in some way #2707

Closed
alan008 opened this issue Aug 22, 2022 · 8 comments
Closed

WebView2 breaks window message processing in some way #2707

alan008 opened this issue Aug 22, 2022 · 8 comments
Assignees
Labels
bug Something isn't working

Comments

@alan008
Copy link

alan008 commented Aug 22, 2022

I use WebView2 from Delphi.

Got some strange behavior, a bit hard to explain.

Assume I have main form with TEdgeBrowser (Delphi wrapper for WebView2) on it. It does nothing, just initializes at application startup:

EdgeBrowser1.BrowserExecutableFolder := ExtractFilePath(Application.ExeName) + 'WebView2Runtime64';
EdgeBrowser1.CreateWebView;
while not EdgeBrowser1.WebViewCreated do
Application.ProcessMessages;

Fixed Version of runtime is located in WebView2Runtime64 subfolder of Exe-folder.

This works nice.

I have a second form, let's assume it's a progress form or some kind a splash form. It's just a test example.

In main application window there is code, which Shows second form, does some Application.ProcessMessages in cycle, and then Hides second form. And let's repeat this cycle forever:

vForm2 := TForm2.Create(Self);
       while True do
       begin
         vForm2.Show;
         try
           for k := 1 to 1000 do
           begin
             sleep(1);
             Application.ProcessMessages;
           end;
         finally
           vForm2.Hide;
         end;
       end;

Here magic begins!
If you run two or more instances of this application at the same time (outside of the debugger, it's important), just double clicking on exe in Windows Explorer) and start "splashing", each showing of the second window will catch focus and make "active" the copy of the application, in which send form was shown last time. So it tranfers focus from one application to another.

But if you rename source exe-file to example1.exe and example2.exe, and run them, the behavior is not reproducible, windows don't catch focus from another app.

What do you suggest to investigate the problem?

@alan008 alan008 added the bug Something isn't working label Aug 22, 2022
@alan008
Copy link
Author

alan008 commented Aug 22, 2022

Added example project (precompiled exe included, fixed version of runtime also included):
https://www.dropbox.com/s/o2jx5fx7r3j03jd/WebView2_Focus.zip?dl=1

Run Project1.exe twice or more times from Windows Explorer (I use Windows 10 64-bit).
Press "Start Test" button in each of the running instances, see how splash screen from other app instance shows above current active app instance. If you copy Project1.exe to Project2.exe and run Project1.exe and Project2.exe, behavior will change - splashing window from inactive instance will not show above current active instance.

@alan008
Copy link
Author

alan008 commented Aug 22, 2022

More investigation - problem happens, when both instances of application share same user data folder, the default is Project1.exe.WebView2

If I set different user data folders for each instance (or rename exe, so it has other default user data folder), problem not happpens.

But I think it's still kind of a bug. Why and how User Data Folder (or WebView2 itself) affect how my application handles windows showing and hiding ?

@alan008
Copy link
Author

alan008 commented Aug 30, 2022

any ideas?

@LiangTheDev
Copy link
Member

Sorry for slow response. This is outside of my expertise. I've asked another team member to look into this.

@bradp0721
Copy link
Member

Hi @alan008. I took a look at the provided sample app. I think I figured out what's going on. I can see that the main Form1 window contains a WebView2. The 'SPLASH!' popup window that gets created does not appear to contain a WebView2.

When you run a single instance of Program1.exe and start the test, the Form1 window creates the SPLASH! window and activates the window. When the SPLASH! window is closed, focus is returned to the Form1 window. If I move focus to another application while the test is running, Program1.exe is not able to steal focus from the foreground application, so the SPLASH! window is not given focus when it gets shown.

When you have two instances of Program1.exe (Program1.exe-A and Program1.exe-B) that share a user data folder, they end up sharing the same WebView2 process (msedgewebview2.exe) and each Program1.exe has a child HWND from msedgewebview2.exe attached to its HWND tree. A parent/child HWND relationship results in attached input queues (essentially the same as explicitly calling AttachThreadInput). This results in Program1.exe-A, Program1.exe-B, and msedgewebview2.exe all being part of the same input queue. Because these three processes have attached input queues, they all have the ability to change the active window. This allows Program1.exe-A to steal focus from Program1.exe-B when it shows its SPLASH! window.

I would expect you to also see this behavior if Program1.exe created two main Form1 windows and you had each of those windows run the test to create a SPLASH! popup window. Maybe you could use the ShowWithoutActivation property to prevent the SPLASH! window from taking focus when it's owner form is not active.

@alan008
Copy link
Author

alan008 commented Aug 31, 2022

they end up sharing the same WebView2 process (msedgewebview2.exe) and each Program1.exe has a child HWND from msedgewebview2.exe attached to its HWND tree

Whoa! Great answer, Brad! I expected something like this, but was not sure of the mechanism details.

"When you have two instances of Program1.exe (Program1.exe-A and Program1.exe-B) that share a user data folder, they end up sharing the same WebView2 process (msedgewebview2.exe)"

I'm not quite sure, why same user data folder causes sharing WebView2 process. WebView2 process is run not from user data folder, but from Browser Executable Folder (fixed version folder or evergreen folder), user data folder is only a command-line parameter, which is passed on msedgewebview2 process creation. Or did you mean, that executing msedgewebview2 with same user data folder parameter will cause that no "additional" web view2 process will be created for the second app instance and existing process (from first app instance) will be used for the second app? Is this exprected behavior for WebView2? (that Program1.exe-A, Program1.exe-B, and msedgewebview2.exe all being part of the same input queue) Should it be documented somewhere?

As for now, I decided to create user data folder with name, based on the Main Thread ID of my application (Project1WebView2.12345, where 12345 is main thread id), so any instance will get separate user data folder (anyway I delete it on application close, so there is no "garbage").

@bradp0721
Copy link
Member

Creating a WebView2 with the same user data folder will cause no additional msedgewebview2.exe processes to be created. When you use separate user data folders, you will have different msedgewebview2.exe processes in Task Manager (with different PIDs even if the path to msedgewebview2.exe is the same). When you have the same user data folder, the WebView2s from the different apps will use the same msedgewebview2.exe (with the same PID).

We do document that sharing a user data folder will result in sharing an msedgewebview2.exe process. See Processes in the WebView2 Runtime. The part that's not documented is that WebView2 creates a cross-proc child HWND, which results in attached input queues. Although, we are investigating removing the cross-proc child HWND because it has other restrictions like forcing DPI awareness of the app processes to match the msedgewebview2.exe DPI awareness #985.

@alan008
Copy link
Author

alan008 commented Sep 1, 2022

Thanks @bradp0721 for the comprehensive answer! I think issue can be closed for now.

we are investigating removing the cross-proc child HWND because it has other restrictions like forcing DPI awareness of the app processes to match the msedgewebview2.exe DPI awareness

Nice plan, because such "indirect" behavior is not what somebody is expecting from using a library or a framework. Or at least make this behavior documented, more explicit or user-controllable.

WebView2 is great component! Thanks, anyway!

@alan008 alan008 closed this as completed Sep 1, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants