cef
cef copied to clipboard
osr: Focus is lost during redirection (causing missing cursor and no FocusEvent)
Describe the bug Hello @magreenblatt
We recently encountered a problem with the focus in CEF. We had difficulty reproducing it because it rarely happened. But we're contacting you today because we've managed to find a simple scenario that you can easily reproduce.
To Reproduce Steps to reproduce the behavior:
- Run cefclient using the following command to to https://duckduckgo.com
cefclient.exe --use-alloy-style --enable-chrome-runtime --off-screen-rendering-enabled --enable-logging=stderr --v=1 --url=https://duckduckgo.com
- Try to search something on the first page to be redirected on another.
- Write something in the new input field and clear it.
- Then click again in the input field, the carret, which originally appeared as a flashing vertical bar, is no longer displayed. But you can still type.
In our case, we observed this expected behaviour in a form created with VueJS. We had a drop-down list that wasn't displayed because the focus event hadn't been received, even though the activeElement property had changed.
We tested with Chrome and Edge and didn't have the problem. The problem only occurs when you activate the Chrome runtime with the Alloy style.
Expected behavior We expect the behaviour to be in line with that of Chrome and Edge.
Video https://github.com/user-attachments/assets/fbc9e37e-ce6e-4002-91ca-14be454da1fd
Impacted Version:
- OS: Windows 10, MacOS 13.2, Ubuntu 22.10
- CEF Version: 125, 126, 127, 128, 129, 130, 131, 132, 133 (using Chrome Runtime + Alloy Style)
Additional context Yes, the problem is reproducible with cefclient as you can see.
Maybe related to issue #3510 and #3436 If someone has any hint to help us starting to debug, we're very interested as we have blocking scenarios on such issue.
I've tried to start the debug by the callstack of the renderer process when CefRenderProcessHandler::OnFocusedNodeChanged is called but this method is actually callbacked correctly, even when the onfocus event is not fired. Which code manages the focus in OSR mode ? where I can start the debug ?
Hello @magreenblatt
We found a workaround to this scenario that we can apply in OnLoadingStateChange as follows :
void ClientHandler::OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
bool isLoading,
bool canGoBack,
bool canGoForward) {
// Proposal 1
CefRefPtr<CefFrame> frame = browser->GetFocusedFrame();
if (frame->IsFocused() && !isLoading) {
browser->GetHost()->SetFocus(true);
}
// Proposal 2
CefRefPtr<CefFrame> frame = browser->GetFocusedFrame();
if (frame->IsMain() && !isLoading) {
browser->GetHost()->SetFocus(true);
}
}
There is also an alternative to this using OnLoadEnd as described here: https://www.magpcss.org/ceforum/viewtopic.php?f=6&t=20161
What do you think? Is this without risk?
However, we believe that redirection significantly disrupts focus as implemented in the internal layers of CEF/Chromium.
We are ready to help if you provide us with feedback on the subject, in order to achieve a more lasting solution than this bypass.
Still no fix?
With OSR, focus is generally handled by the client application. Can you set a breakpoint in CefBrowserPlatformDelegateOsr::SetFocus and see if/why it's being called with setFocus=false in the redirection case that you mention?
Hi @magreenblatt, from my side I see CEF just released focus from Browser when we navigate new page.
- create CEF browser with target www.google.com,
- the methods in CefFocusHandler get called correctly
- CefFocusHandler::OnSetFocus
- CefFocusHandler::OnGotFocus
- type in any keyword and then navigate to the search result (by enter key or mouse button)
- the browser navigates to the new page successfully without any CefFocusHandler methods invocation but actually the browser has released focus. (the caret is missing, if we don't call SetFocus on the browser host, we cannot interact with this page by IME and the caret is missing forever. if we click outside of the CEF application and then click the browser again, everything gets back well)
In a short word, after navigation CEF released(reset) it's focus silently regardless it's previous status.
With OSR, focus is generally handled by the client application. Can you set a breakpoint in CefBrowserPlatformDelegateOsr::SetFocus and see if/why it's being called with setFocus=false in the redirection case that you mention?
with your suggestion, I just keep a CEF browser status focus flag in my application implementation, and every time when CefLoadHandler::OnLoadEnd gets called, I just sync the focus status back to CEF browser host, it works and so far so good.
But I think, when navigation to the new page CEF should not touch the internal browser focus status, then the consumers don't need to care about the silent focus lost problem.