platform: Windows 32
OS: Windows 10
previous version of CEF:
02/16/2017 - 3.2924.1570.g558741c / Chromium 56.0.2924.76
upgrade version of CEF:
01/15/2022 - 97.1.5+g2b00258+chromium-97.0.4692.71 / Chromium 97.0.4692.71
We call m_cefBrowser->GetHost()->SetFocus as shown below (from the window that owns the browser)
- Code: Select all
ON_WM_SETFOCUS()
ON_WM_KILLFOCUS()
END_MESSAGE_MAP()
CER_VOID
CER_PANEL_CEFB::OnSetFocus(PCWnd ppcLastFocus)
{
if (m_cefBrowser)
{
if (CefCurrentlyOn(TID_UI))
m_cefBrowser->GetHost()->SetFocus(true);
}
}
CER_VOID
CER_PANEL_CEFB::OnKillFocus(PCWnd ppcLastFocus)
{
if (m_cefBrowser)
{
if (CefCurrentlyOn(TID_UI))
m_cefBrowser->GetHost()->SetFocus(false);
}
}
Occassionally, we hit a nullptr exception in the call to ::SetFocus(HWNDForWidget(window_widget_) in the code below.
Exception:
Unhandled exception thrown: read access violation.
this->native_widget_ was nullptr.
Is this a bug in CEF (to check web_contents_->native_widget_ pointer before calling ::SetFocus(HWNDForWidget(window_widget_)), or is there something different we can do in our code to avoid this exception?
- Code: Select all
void CefBrowserPlatformDelegateNativeWin::SetFocus(bool setFocus) {
if (!setFocus)
return;
if (web_contents_) {
// Give logical focus to the RenderWidgetHostViewAura in the views
// hierarchy. This does not change the native keyboard focus.
web_contents_->Focus();
}
if (window_widget_) {
// Give native focus to the DesktopWindowTreeHostWin associated with the
// root window.
//
// The DesktopWindowTreeHostWin HandleNativeFocus/HandleNativeBlur methods
// are called in response to WM_SETFOCUS/WM_KILLFOCUS respectively. The
// implementation has been patched to call HandleActivationChanged which
// results in the following behaviors:
// 1. Update focus/activation state of the aura::Window indirectly via
// wm::FocusController. This allows focus-related behaviors (e.g. focus
// rings, flashing caret, onFocus/onBlur JS events, etc.) to work as
// expected (see issue #1677).
// 2. Update focus state of the ui::InputMethod. If this does not occur
// then InputMethodBase::GetTextInputClient will return NULL and
// InputMethodWin::OnChar will fail to sent character events to the
// renderer (see issue #1700).
//
// This differs from activation in Chrome which is handled via
// HWNDMessageHandler::PostProcessActivateMessage (Widget::Show indirectly
// calls HWNDMessageHandler::Activate which calls ::SetForegroundWindow
// resulting in a WM_ACTIVATE message being sent to the window). The Chrome
// code path doesn't work for CEF because IsTopLevelWindow in
// hwnd_message_handler.cc will return false and consequently
// HWNDMessageHandler::PostProcessActivateMessage will not be called.
//
// Activation events are usually reserved for the top-level window so
// triggering activation based on focus events may be incorrect in some
// circumstances. Revisit this implementation if additional problems are
// discovered.
::SetFocus(HWNDForWidget(window_widget_));
Call Stack:
- Code: Select all
libcef.dll!views::Widget::GetNativeWindow() Line 483 C++
> libcef.dll!views::HWNDForWidget(const views::Widget * widget) Line 22 C++
libcef.dll!CefBrowserPlatformDelegateNativeWin::SetFocus(bool setFocus) Line 312 C++
libcef.dll!AlloyBrowserHostImpl::OnSetFocus(<unnamed-tag> source) Line 819 C++
libcef.dll!AlloyBrowserHostImpl::SetFocusInternal(bool focus) Line 368 C++
[Inline Frame] libcef.dll!base::internal::FunctorTraits<void (CefMenuModelImpl::*)(bool) __attribute__((thiscall)),void>::Invoke(void(CefMenuModelImpl::*)(bool) method, scoped_refptr<CefMenuModelImpl> && receiver_ptr, bool && args) Line 533 C++
[Inline Frame] libcef.dll!base::internal::InvokeHelper<0,void>::MakeItSo(void(CefMenuModelImpl::*)(bool) && functor, scoped_refptr<CefMenuModelImpl> && args, bool && args) Line 708 C++
[Inline Frame] libcef.dll!base::internal::Invoker<base::internal::BindState<void (CefMenuModelImpl::*)(bool) __attribute__((thiscall)),scoped_refptr<CefMenuModelImpl>,bool>,void ()>::RunImpl(void(CefMenuModelImpl::*)(bool) && functor, std::__1::tuple<scoped_refptr<CefMenuModelImpl>,bool> && bound, std::__1::integer_sequence<unsigned int,0,1>) Line 781 C++
libcef.dll!base::internal::Invoker<base::internal::BindState<void (CefMenuModelImpl::*)(bool) __attribute__((thiscall)),scoped_refptr<CefMenuModelImpl>,bool>,void ()>::RunOnce(base::internal::BindStateBase * base) Line 754 C++
[Inline Frame] libcef.dll!base::OnceCallback<void ()>::Run() Line 142 C++
libcef.dll!base::TaskAnnotator::RunTaskImpl(base::PendingTask & pending_task) Line 157 C++
[Inline Frame] libcef.dll!base::TaskAnnotator::RunTask(perfetto::StaticString event_name, base::PendingTask & pending_task, base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWorkImpl::<lambda_0> && args) Line 73 C++
libcef.dll!base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWorkImpl(base::sequence_manager::LazyNow * continuation_lazy_now) Line 356 C++
libcef.dll!base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWork() Line 267 C++
libcef.dll!base::MessagePumpForUI::DoRunLoop() Line 221 C++
libcef.dll!base::MessagePumpWin::Run(base::MessagePump::Delegate * delegate) Line 79 C++
libcef.dll!base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::Run(bool application_tasks_allowed, base::TimeDelta timeout) Line 471 C++
libcef.dll!base::RunLoop::Run(const base::Location & location) Line 142 C++
libcef.dll!base::RunLoop::RunUntilIdle() Line 151 C++
libcef.dll!CefDoMessageLoopWork() Line 255 C++
ceraexe0.exe!CefDoMessageLoopWork() Line 129 C++
ceraexe0.exe!CCerApp::OnIdle(long lCount) Line 425 C++
Thank you.