WinForms - Enter/Arrow keys not working with DevTool/Popups with MultiThreadedMessageLoop = false
- 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,WPForOffScreen?
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:
- Open DevTools
- Write a command, for example,
console.log("Hello World") - Press
ENTERkey, but nothing happens, the key is ignored - Press
left arroworright arrowto 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
CEFSample 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
For an accurate comparison you need to test with the CEF Sample application version 75.1.14
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
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).
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.
Confirming this issue is present with any popup (DevTools is just opened as a popup).
I have yet to find another means of changing how WinForms processes the key inputs.
- [x] Add
ChromiumHostControlto theCefSharp.WinFormsproject- [x] Override IsInputKey e.g. https://github.com/cefsharp/CefSharp/commit/1d2fb9531f087f99e22170f1a335d7b1cee7cec5#diff-86315df11fee16a159c95ae8d67cf3b3a05ef6594aa84ac23f892caa2dcc2721R11
- [x] Handle resize/move notifications for hosting popups using a
WinformsControl as the parent.
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()