CefSharp icon indicating copy to clipboard operation
CefSharp copied to clipboard

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

Open kiewic opened this issue 4 years ago • 7 comments

  • What version of the product are you using?

Multiple versions:

CefSharp.MinimalExample with Nuget package 75.1.142.

But it also reproduces with 69 and 73

  • What architecture x86 or x64?

x64

  • On what operating system?

Windows 10

  • Are you using WinForms, WPF or OffScreen?

WinForms

  • What steps will reproduce the problem?

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
  • What is the expected output? What do you see instead?

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.

  • Please provide any additional information below.

No exceptions.

Nothing relevant in debug.log.

  • Does this problem also occur in the CEF Sample Application from http://opensource.spotify.com/cefbuilds/index.html?

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

kiewic avatar Sep 09 '19 21:09 kiewic

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

amaitland avatar Sep 09 '19 23:09 amaitland

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 avatar Sep 10 '19 04:09 amaitland

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 avatar Sep 10 '19 10:09 amaitland

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 avatar Sep 10 '19 10:09 amaitland

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

amaitland avatar Nov 22 '20 23:11 amaitland

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

  • [x] Add ChromiumHostControl to the CefSharp.WinForms project
    • [x] Override IsInputKey e.g. https://github.com/cefsharp/CefSharp/commit/1d2fb9531f087f99e22170f1a335d7b1cee7cec5#diff-86315df11fee16a159c95ae8d67cf3b3a05ef6594aa84ac23f892caa2dcc2721R11
    • [x] Handle resize/move notifications for hosting popups using a Winforms Control as the parent.

amaitland avatar Nov 22 '20 23:11 amaitland

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()

amaitland avatar Aug 13 '21 08:08 amaitland