cefsharp / CefSharp

.NET (WPF and Windows Forms) bindings for the Chromium Embedded Framework
http://cefsharp.github.io/
Other
9.89k stars 2.92k forks source link

WinForms - Enter/Arrow keys not working with DevTool/Popups with MultiThreadedMessageLoop = false #2899

Open kiewic opened 5 years ago

kiewic commented 5 years ago

Multiple versions:

CefSharp.MinimalExample with Nuget package 75.1.142.

But it also reproduces with 69 and 73

x64

Windows 10

WinForms

I used CefSharp.MinimalExample.WinForms.csproj as the base. I added MultiThreadedMessageLoop = false and called Cef.DoMessageLoopWork() on a timer to enable the integrated message loop.

Here is a branch with the changes: https://github.com/kiewic/CefSharp.MinimalExample/tree/kiewic/devtools-enter-key-integrated-message-loop

Once the modified sample is running:

  1. Open DevTools
  2. Write a command, for example, console.log("Hello World")
  3. Press ENTER key, but nothing happens, the key is ignored
  4. Press left arrow or right arrow to move the cursor left or right, but the cursor does not move

It is expected that ENTER and arrow keys work the same as in the multi-threaded message loop. ENTER key should execute the command, and arrow keys should move the cursor.

No exceptions.

Nothing relevant in debug.log.

This does not reproduce with cefclient.exe. I executed it WITHOUT --multi-threaded-message-loop. I tried version: cef_binary_76.1.13+gf19c584+chromium-76.0.3809.132_windows64_client

amaitland commented 5 years ago

For an accurate comparison you need to test with the CEF Sample application version 75.1.14

amaitland commented 5 years ago

Now that I've has a few minutes to read this in detail the behaviour you are seeing is somewhat an expected one. The keys listed are actually preprocessed in WinForms see https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.control.isinputkey?view=netframework-4.8#remarks I will comment in more detail next time I'm in front of a PC

amaitland commented 5 years ago

This method is called during window message preprocessing to determine whether the specified input key should be preprocessed or sent directly to the control. If IsInputKey returns true, the specified key is sent directly to the control. If IsInputKey returns false, the specified key is preprocessed and only sent to the control if it is not consumed by the preprocessing phase. Keys that are preprocessed include the TAB, RETURN, ESC, and the UP ARROW, DOWN ARROW, LEFT ARROW, and RIGHT ARROW keys.

As per https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.control.isinputkey?view=netframework-4.8#remarks WinForms does some preprocessing of TAB, RETURN, ESC, UP, DOWN, LEFT and RIGHT by default. Integrating CEF into the WinForms Message Loop and this behaviour means those keys aren't forwarded as one might expect from a user point of view (expected from a WinForms point of view). In ChromiumWebBrowser.IsInputKey we have some fairly trivial code to override the default behaviour.

In the CefSharp.WinForms.Example project there is a recently added example of docking DevTools in a SplitContainer, in this scenario a custom parent control (which is really all ChromiumWebBrowser is in the first place) can be used to override the default behaviour, see commit https://github.com/cefsharp/CefSharp/commit/1d2fb9531f087f99e22170f1a335d7b1cee7cec5 for a very quick and not extensively tested example.

In theory you should be able to use a similar technique to host DevTools in your own form with a similar parent control using WindowInfo.SetAsChild to specify the parent(host) control Handle.

There is a chance this will be marked as wontfix as it may not be practical to override the default WinForms behaviour when CEF hosts DevTools. The best you might get is an example that works around the behaviour (Pull Requests welcome).

amaitland commented 5 years ago

It may well be wise to ask for help on http://stackoverflow.com/questions/tagged/winforms as there are people better versed in the deep inner workings of WinForms who might have a more elegant solution.

amaitland commented 4 years ago

Confirming this issue is present with any popup (DevTools is just opened as a popup).

amaitland commented 4 years ago

I have yet to find another means of changing how WinForms processes the key inputs.

amaitland commented 3 years ago

ChromiumHostControl was added in commit https://github.com/cefsharp/CefSharp/commit/3dc37b2dd2717be91e40af6a748b8057564535cb#diff-5ce832ad0887b4ba2a2fb5a8d34fe775f48b4ccd137d6031f3dcde9cb5e7339b

You can use the ShowDevToolsDocked extension method to give DevTools a specific parent, can be a form, child control, etc

https://github.com/cefsharp/CefSharp/blob/3dc37b2dd2717be91e40af6a748b8057564535cb/CefSharp.WinForms/WebBrowserExtensions.cs#L75

I haven't tested hosting with a Form as the parent, the Form on close probably needs to call CloseDevTools()