chrome: win/linux: Add support for browser with native parent (see issue #3294)

This change adds Chrome runtime support on Windows and Linux for creating a
browser parented to a native window supplied by the client application.
Expected API usage and window behavior is similar to what already exists with
the Alloy runtime. The parent window handle should be specified by using
CefWindowInfo::SetAsChild in combination with the CefBrowserHost::CreateBrowser
and CefLifeSpanHandler::OnBeforePopup callbacks.

The previously existing behavior of creating a fully-featured Chrome browser
window when empty CefWindowInfo is used with CreateBrowser remains unchanged
and Views is still the preferred API for creating top-level Chrome windows
with custom styling (e.g. title bar only, frameless, etc).

The cefclient Popup Window test with a native parent window continues to crash
on Linux with both the Alloy and Chrome runtimes (see issue #3165).

Also adds Chrome runtime support for CefDisplayHandler::OnCursorChange.

To test:
- Run `cefclient --enable-chrome-runtime [--use-views]` for the default (and
  previously existing) Views-based behavior.
- Run `cefclient --enable-chrome-runtime --use-native` for the new native
  parent window behavior.
- Run `cefclient --enable-chrome-runtime --use-native --no-activate` and the
  window will not be activated (take input focus) on launch (Windows only).
- Run `cefclient --enable-chrome-runtime [--use-views|--use-native]
  --mouse-cursor-change-disabled` and the mouse cursor will not change on
  mouseover of DOM elements.
This commit is contained in:
Marshall Greenblatt 2022-04-08 16:48:56 -04:00
parent 5f4bccd672
commit 3000bc8748
43 changed files with 702 additions and 245 deletions

View File

@ -1029,12 +1029,16 @@ static_library("libcef_static") {
if (toolkit_views) { if (toolkit_views) {
sources += [ sources += [
"libcef/browser/chrome/views/browser_platform_delegate_chrome_child_window.cc",
"libcef/browser/chrome/views/browser_platform_delegate_chrome_child_window.h",
"libcef/browser/chrome/views/browser_platform_delegate_chrome_views.cc", "libcef/browser/chrome/views/browser_platform_delegate_chrome_views.cc",
"libcef/browser/chrome/views/browser_platform_delegate_chrome_views.h", "libcef/browser/chrome/views/browser_platform_delegate_chrome_views.h",
"libcef/browser/chrome/views/chrome_browser_frame.cc", "libcef/browser/chrome/views/chrome_browser_frame.cc",
"libcef/browser/chrome/views/chrome_browser_frame.h", "libcef/browser/chrome/views/chrome_browser_frame.h",
"libcef/browser/chrome/views/chrome_browser_view.cc", "libcef/browser/chrome/views/chrome_browser_view.cc",
"libcef/browser/chrome/views/chrome_browser_view.h", "libcef/browser/chrome/views/chrome_browser_view.h",
"libcef/browser/chrome/views/chrome_child_window.cc",
"libcef/browser/chrome/views/chrome_child_window.h",
"libcef/browser/chrome/views/chrome_views_util.cc", "libcef/browser/chrome/views/chrome_views_util.cc",
"libcef/browser/chrome/views/chrome_views_util.h", "libcef/browser/chrome/views/chrome_views_util.h",
"libcef/browser/chrome/views/toolbar_view_impl.cc", "libcef/browser/chrome/views/toolbar_view_impl.cc",

View File

@ -99,6 +99,9 @@ class CefWindowInfo : public CefStructBase<CefWindowInfoTraits> {
explicit CefWindowInfo(const cef_window_info_t& r) : parent(r) {} explicit CefWindowInfo(const cef_window_info_t& r) : parent(r) {}
explicit CefWindowInfo(const CefWindowInfo& r) : parent(r) {} explicit CefWindowInfo(const CefWindowInfo& r) : parent(r) {}
CefWindowInfo& operator=(const CefWindowInfo&) = default;
CefWindowInfo& operator=(CefWindowInfo&&) = default;
/// ///
// Create the browser as a child window. // Create the browser as a child window.
/// ///

View File

@ -100,6 +100,9 @@ class CefWindowInfo : public CefStructBase<CefWindowInfoTraits> {
explicit CefWindowInfo(const cef_window_info_t& r) : parent(r) {} explicit CefWindowInfo(const cef_window_info_t& r) : parent(r) {}
explicit CefWindowInfo(const CefWindowInfo& r) : parent(r) {} explicit CefWindowInfo(const CefWindowInfo& r) : parent(r) {}
CefWindowInfo& operator=(const CefWindowInfo&) = default;
CefWindowInfo& operator=(CefWindowInfo&&) = default;
/// ///
// Create the browser as a child view. // Create the browser as a child view.
/// ///

View File

@ -102,6 +102,9 @@ class CefWindowInfo : public CefStructBase<CefWindowInfoTraits> {
explicit CefWindowInfo(const cef_window_info_t& r) : parent(r) {} explicit CefWindowInfo(const cef_window_info_t& r) : parent(r) {}
explicit CefWindowInfo(const CefWindowInfo& r) : parent(r) {} explicit CefWindowInfo(const CefWindowInfo& r) : parent(r) {}
CefWindowInfo& operator=(const CefWindowInfo&) = default;
CefWindowInfo& operator=(CefWindowInfo&&) = default;
/// ///
// Create the browser as a child window. // Create the browser as a child window.
/// ///

View File

@ -18,7 +18,6 @@
#include "libcef/browser/context.h" #include "libcef/browser/context.h"
#include "libcef/browser/devtools/devtools_manager.h" #include "libcef/browser/devtools/devtools_manager.h"
#include "libcef/browser/media_capture_devices_dispatcher.h" #include "libcef/browser/media_capture_devices_dispatcher.h"
#include "libcef/browser/native/cursor_util.h"
#include "libcef/browser/osr/osr_util.h" #include "libcef/browser/osr/osr_util.h"
#include "libcef/browser/request_context_impl.h" #include "libcef/browser/request_context_impl.h"
#include "libcef/browser/thread_util.h" #include "libcef/browser/thread_util.h"
@ -35,7 +34,6 @@
#include "base/command_line.h" #include "base/command_line.h"
#include "chrome/browser/picture_in_picture/picture_in_picture_window_manager.h" #include "chrome/browser/picture_in_picture/picture_in_picture_window_manager.h"
#include "content/browser/gpu/compositor_util.h" #include "content/browser/gpu/compositor_util.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/public/browser/desktop_media_id.h" #include "content/public/browser/desktop_media_id.h"
#include "content/public/browser/file_select_listener.h" #include "content/public/browser/file_select_listener.h"
#include "content/public/browser/host_zoom_map.h" #include "content/public/browser/host_zoom_map.h"
@ -47,12 +45,11 @@
#include "content/public/browser/render_process_host.h" #include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h" #include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host.h" #include "content/public/browser/render_widget_host.h"
#include "content/public/browser/render_widget_host_observer.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#include "content/public/common/url_constants.h"
#include "extensions/common/constants.h" #include "extensions/common/constants.h"
#include "extensions/common/extension.h" #include "extensions/common/extension.h"
#include "net/base/net_errors.h" #include "net/base/net_errors.h"
#include "third_party/blink/public/mojom/widget/platform_widget.mojom-test-utils.h"
#include "ui/events/base_event_utils.h" #include "ui/events/base_event_utils.h"
using content::KeyboardEventProcessingResult; using content::KeyboardEventProcessingResult;
@ -86,48 +83,6 @@ void ShowDevToolsWithHelper(ShowDevToolsHelper* helper) {
delete helper; delete helper;
} }
class CefWidgetHostInterceptor
: public blink::mojom::WidgetHostInterceptorForTesting,
public content::RenderWidgetHostObserver {
public:
CefWidgetHostInterceptor(AlloyBrowserHostImpl* browser,
content::RenderViewHost* render_view_host)
: browser_(browser),
render_widget_host_(
content::RenderWidgetHostImpl::From(render_view_host->GetWidget())),
impl_(render_widget_host_->widget_host_receiver_for_testing()
.SwapImplForTesting(this)) {
render_widget_host_->AddObserver(this);
}
CefWidgetHostInterceptor(const CefWidgetHostInterceptor&) = delete;
CefWidgetHostInterceptor& operator=(const CefWidgetHostInterceptor&) = delete;
blink::mojom::WidgetHost* GetForwardingInterface() override { return impl_; }
// WidgetHostInterceptorForTesting method:
void SetCursor(const ui::Cursor& cursor) override {
if (cursor_util::OnCursorChange(browser_, cursor)) {
// Don't change the cursor.
return;
}
GetForwardingInterface()->SetCursor(cursor);
}
// RenderWidgetHostObserver method:
void RenderWidgetHostDestroyed(
content::RenderWidgetHost* widget_host) override {
widget_host->RemoveObserver(this);
delete this;
}
private:
AlloyBrowserHostImpl* const browser_;
content::RenderWidgetHostImpl* const render_widget_host_;
blink::mojom::WidgetHost* const impl_;
};
static constexpr base::TimeDelta kRecentlyAudibleTimeout = base::Seconds(2); static constexpr base::TimeDelta kRecentlyAudibleTimeout = base::Seconds(2);
} // namespace } // namespace
@ -243,7 +198,15 @@ CefRefPtr<AlloyBrowserHostImpl> AlloyBrowserHostImpl::CreateInternal(
// Notify that the browser has been created. These must be delivered in the // Notify that the browser has been created. These must be delivered in the
// expected order. // expected order.
// 1. Notify the browser's LifeSpanHandler. This must always be the first if (opener && opener->platform_delegate_) {
// 1. Notify the opener browser's platform delegate. With Views this will
// result in a call to CefBrowserViewDelegate::OnPopupBrowserViewCreated().
// Do this first for consistency with the Chrome runtime.
opener->platform_delegate_->PopupBrowserCreated(browser.get(),
is_devtools_popup);
}
// 2. Notify the browser's LifeSpanHandler. This must always be the first
// notification for the browser. Block navigation to avoid issues with focus // notification for the browser. Block navigation to avoid issues with focus
// changes being sent to an unbound interface. // changes being sent to an unbound interface.
{ {
@ -251,17 +214,10 @@ CefRefPtr<AlloyBrowserHostImpl> AlloyBrowserHostImpl::CreateInternal(
browser->OnAfterCreated(); browser->OnAfterCreated();
} }
// 2. Notify the platform delegate. With Views this will result in a call to // 3. Notify the platform delegate. With Views this will result in a call to
// CefBrowserViewDelegate::OnBrowserCreated(). // CefBrowserViewDelegate::OnBrowserCreated().
browser->platform_delegate_->NotifyBrowserCreated(); browser->platform_delegate_->NotifyBrowserCreated();
if (opener && opener->platform_delegate_) {
// 3. Notify the opener browser's platform delegate. With Views this will
// result in a call to CefBrowserViewDelegate::OnPopupBrowserViewCreated().
opener->platform_delegate_->PopupBrowserCreated(browser.get(),
is_devtools_popup);
}
return browser; return browser;
} }
@ -355,20 +311,6 @@ bool AlloyBrowserHostImpl::TryCloseBrowser() {
return true; return true;
} }
void AlloyBrowserHostImpl::SetFocus(bool focus) {
// Always execute asynchronously to work around issue #3040.
CEF_POST_TASK(CEF_UIT, base::BindOnce(&AlloyBrowserHostImpl::SetFocusInternal,
this, focus));
}
void AlloyBrowserHostImpl::SetFocusInternal(bool focus) {
CEF_REQUIRE_UIT();
if (focus)
OnSetFocus(FOCUS_SOURCE_SYSTEM);
else if (platform_delegate_)
platform_delegate_->SetFocus(false);
}
CefWindowHandle AlloyBrowserHostImpl::GetWindowHandle() { CefWindowHandle AlloyBrowserHostImpl::GetWindowHandle() {
if (is_views_hosted_ && CEF_CURRENTLY_ON_UIT()) { if (is_views_hosted_ && CEF_CURRENTLY_ON_UIT()) {
// Always return the most up-to-date window handle for a views-hosted // Always return the most up-to-date window handle for a views-hosted
@ -664,20 +606,6 @@ void AlloyBrowserHostImpl::SendCaptureLostEvent() {
platform_delegate_->SendCaptureLostEvent(); platform_delegate_->SendCaptureLostEvent();
} }
void AlloyBrowserHostImpl::NotifyMoveOrResizeStarted() {
#if BUILDFLAG(IS_WIN) || (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC))
if (!CEF_CURRENTLY_ON_UIT()) {
CEF_POST_TASK(
CEF_UIT,
base::BindOnce(&AlloyBrowserHostImpl::NotifyMoveOrResizeStarted, this));
return;
}
if (platform_delegate_)
platform_delegate_->NotifyMoveOrResizeStarted();
#endif
}
int AlloyBrowserHostImpl::GetWindowlessFrameRate() { int AlloyBrowserHostImpl::GetWindowlessFrameRate() {
// Verify that this method is being called on the UI thread. // Verify that this method is being called on the UI thread.
if (!CEF_CURRENTLY_ON_UIT()) { if (!CEF_CURRENTLY_ON_UIT()) {
@ -1490,19 +1418,6 @@ bool AlloyBrowserHostImpl::IsPrerender2Supported(
// content::WebContentsObserver methods. // content::WebContentsObserver methods.
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void AlloyBrowserHostImpl::RenderFrameCreated(
content::RenderFrameHost* render_frame_host) {
if (render_frame_host->GetParent() == nullptr) {
auto render_view_host = render_frame_host->GetRenderViewHost();
new CefWidgetHostInterceptor(this, render_view_host);
platform_delegate_->RenderViewCreated(render_view_host);
}
}
void AlloyBrowserHostImpl::RenderViewReady() {
platform_delegate_->RenderViewReady();
}
void AlloyBrowserHostImpl::DidFinishNavigation( void AlloyBrowserHostImpl::DidFinishNavigation(
content::NavigationHandle* navigation_handle) { content::NavigationHandle* navigation_handle) {
if (web_contents()) { if (web_contents()) {

View File

@ -79,7 +79,6 @@ class AlloyBrowserHostImpl : public CefBrowserHostBase,
// CefBrowserHost methods. // CefBrowserHost methods.
void CloseBrowser(bool force_close) override; void CloseBrowser(bool force_close) override;
bool TryCloseBrowser() override; bool TryCloseBrowser() override;
void SetFocus(bool focus) override;
CefWindowHandle GetWindowHandle() override; CefWindowHandle GetWindowHandle() override;
CefWindowHandle GetOpenerWindowHandle() override; CefWindowHandle GetOpenerWindowHandle() override;
double GetZoomLevel() override; double GetZoomLevel() override;
@ -113,7 +112,6 @@ class AlloyBrowserHostImpl : public CefBrowserHostBase,
void SendExternalBeginFrame() override; void SendExternalBeginFrame() override;
void SendTouchEvent(const CefTouchEvent& event) override; void SendTouchEvent(const CefTouchEvent& event) override;
void SendCaptureLostEvent() override; void SendCaptureLostEvent() override;
void NotifyMoveOrResizeStarted() override;
int GetWindowlessFrameRate() override; int GetWindowlessFrameRate() override;
void SetWindowlessFrameRate(int frame_rate) override; void SetWindowlessFrameRate(int frame_rate) override;
void ImeSetComposition(const CefString& text, void ImeSetComposition(const CefString& text,
@ -293,8 +291,6 @@ class AlloyBrowserHostImpl : public CefBrowserHostBase,
// content::WebContentsObserver methods. // content::WebContentsObserver methods.
using content::WebContentsObserver::BeforeUnloadFired; using content::WebContentsObserver::BeforeUnloadFired;
void RenderFrameCreated(content::RenderFrameHost* render_frame_host) override;
void RenderViewReady() override;
void DidFinishNavigation( void DidFinishNavigation(
content::NavigationHandle* navigation_handle) override; content::NavigationHandle* navigation_handle) override;
void OnAudioStateChanged(bool audible) override; void OnAudioStateChanged(bool audible) override;
@ -339,8 +335,6 @@ class AlloyBrowserHostImpl : public CefBrowserHostBase,
void StartAudioCapturer(); void StartAudioCapturer();
void OnRecentlyAudibleTimerFired(); void OnRecentlyAudibleTimerFired();
void SetFocusInternal(bool focus);
CefWindowHandle opener_; CefWindowHandle opener_;
const bool is_windowless_; const bool is_windowless_;
CefWindowHandle host_window_handle_ = kNullWindowHandle; CefWindowHandle host_window_handle_ = kNullWindowHandle;

View File

@ -112,10 +112,15 @@ void CefBrowserPlatformDelegateAlloy::WebContentsCreated(
content::WebContents* web_contents, content::WebContents* web_contents,
bool owned) { bool owned) {
CefBrowserPlatformDelegate::WebContentsCreated(web_contents, owned); CefBrowserPlatformDelegate::WebContentsCreated(web_contents, owned);
find_in_page::FindTabHelper::CreateForWebContents(web_contents);
if (owned) { if (primary_) {
SetOwnedWebContents(web_contents); find_in_page::FindTabHelper::CreateForWebContents(web_contents);
if (owned) {
SetOwnedWebContents(web_contents);
}
} else {
DCHECK(!owned);
} }
} }
@ -159,8 +164,8 @@ bool CefBrowserPlatformDelegateAlloy::
void CefBrowserPlatformDelegateAlloy::RenderViewCreated( void CefBrowserPlatformDelegateAlloy::RenderViewCreated(
content::RenderViewHost* render_view_host) { content::RenderViewHost* render_view_host) {
// Indicate that the view has an external parent (namely us). This changes the // Indicate that the view has an external parent (namely us). This setting is
// default view behavior in some cases (e.g. focus handling on Linux). // required for proper focus handling on Windows and Linux.
if (!IsViewsHosted() && render_view_host->GetWidget()->GetView()) if (!IsViewsHosted() && render_view_host->GetWidget()->GetView())
render_view_host->GetWidget()->GetView()->SetHasExternalParent(true); render_view_host->GetWidget()->GetView()->SetHasExternalParent(true);
} }

View File

@ -7,8 +7,10 @@
#include "libcef/browser/browser_host_base.h" #include "libcef/browser/browser_host_base.h"
#include "libcef/browser/browser_platform_delegate.h" #include "libcef/browser/browser_platform_delegate.h"
#include "libcef/browser/browser_util.h" #include "libcef/browser/browser_util.h"
#include "libcef/browser/native/cursor_util.h"
#include "libcef/common/frame_util.h" #include "libcef/common/frame_util.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/public/browser/focused_node_details.h" #include "content/public/browser/focused_node_details.h"
#include "content/public/browser/keyboard_event_processing_result.h" #include "content/public/browser/keyboard_event_processing_result.h"
#include "content/public/browser/native_web_keyboard_event.h" #include "content/public/browser/native_web_keyboard_event.h"
@ -19,12 +21,60 @@
#include "content/public/browser/notification_types.h" #include "content/public/browser/notification_types.h"
#include "content/public/browser/render_view_host.h" #include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host.h" #include "content/public/browser/render_widget_host.h"
#include "content/public/browser/render_widget_host_observer.h"
#include "content/public/browser/render_widget_host_view.h" #include "content/public/browser/render_widget_host_view.h"
#include "third_party/blink/public/mojom/favicon/favicon_url.mojom.h" #include "third_party/blink/public/mojom/favicon/favicon_url.mojom.h"
#include "third_party/blink/public/mojom/input/focus_type.mojom-blink.h" #include "third_party/blink/public/mojom/input/focus_type.mojom-blink.h"
#include "third_party/blink/public/mojom/widget/platform_widget.mojom-test-utils.h"
using content::KeyboardEventProcessingResult; using content::KeyboardEventProcessingResult;
namespace {
class CefWidgetHostInterceptor
: public blink::mojom::WidgetHostInterceptorForTesting,
public content::RenderWidgetHostObserver {
public:
CefWidgetHostInterceptor(CefRefPtr<CefBrowser> browser,
content::RenderViewHost* render_view_host)
: browser_(browser),
render_widget_host_(
content::RenderWidgetHostImpl::From(render_view_host->GetWidget())),
impl_(render_widget_host_->widget_host_receiver_for_testing()
.SwapImplForTesting(this)) {
render_widget_host_->AddObserver(this);
}
CefWidgetHostInterceptor(const CefWidgetHostInterceptor&) = delete;
CefWidgetHostInterceptor& operator=(const CefWidgetHostInterceptor&) = delete;
blink::mojom::WidgetHost* GetForwardingInterface() override { return impl_; }
// WidgetHostInterceptorForTesting method:
void SetCursor(const ui::Cursor& cursor) override {
if (cursor_util::OnCursorChange(browser_, cursor)) {
// Don't change the cursor.
return;
}
GetForwardingInterface()->SetCursor(cursor);
}
// RenderWidgetHostObserver method:
void RenderWidgetHostDestroyed(
content::RenderWidgetHost* widget_host) override {
widget_host->RemoveObserver(this);
delete this;
}
private:
CefRefPtr<CefBrowser> const browser_;
content::RenderWidgetHostImpl* const render_widget_host_;
blink::mojom::WidgetHost* const impl_;
};
} // namespace
CefBrowserContentsDelegate::CefBrowserContentsDelegate( CefBrowserContentsDelegate::CefBrowserContentsDelegate(
scoped_refptr<CefBrowserInfo> browser_info) scoped_refptr<CefBrowserInfo> browser_info)
: browser_info_(browser_info) { : browser_info_(browser_info) {
@ -265,6 +315,9 @@ void CefBrowserContentsDelegate::RenderFrameCreated(
} }
render_view_host->GetWidget()->GetView()->SetBackgroundColor( render_view_host->GetWidget()->GetView()->SetBackgroundColor(
base_background_color); base_background_color);
new CefWidgetHostInterceptor(browser(), render_view_host);
platform_delegate()->RenderViewCreated(render_view_host);
} }
} }
@ -295,6 +348,8 @@ void CefBrowserContentsDelegate::RenderFrameDeleted(
} }
void CefBrowserContentsDelegate::RenderViewReady() { void CefBrowserContentsDelegate::RenderViewReady() {
platform_delegate()->RenderViewReady();
if (auto c = client()) { if (auto c = client()) {
if (auto handler = c->GetRequestHandler()) { if (auto handler = c->GetRequestHandler()) {
handler->OnRenderViewReady(browser()); handler->OnRenderViewReady(browser());

View File

@ -194,6 +194,20 @@ bool CefBrowserHostBase::HasView() {
return is_views_hosted_; return is_views_hosted_;
} }
void CefBrowserHostBase::SetFocus(bool focus) {
// Always execute asynchronously to work around issue #3040.
CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefBrowserHostBase::SetFocusInternal,
this, focus));
}
void CefBrowserHostBase::SetFocusInternal(bool focus) {
CEF_REQUIRE_UIT();
if (focus)
OnSetFocus(FOCUS_SOURCE_SYSTEM);
else if (platform_delegate_)
platform_delegate_->SetFocus(false);
}
void CefBrowserHostBase::StartDownload(const CefString& url) { void CefBrowserHostBase::StartDownload(const CefString& url) {
if (!CEF_CURRENTLY_ON_UIT()) { if (!CEF_CURRENTLY_ON_UIT()) {
CEF_POST_TASK( CEF_POST_TASK(
@ -377,6 +391,20 @@ CefRefPtr<CefNavigationEntry> CefBrowserHostBase::GetVisibleNavigationEntry() {
return new CefNavigationEntryImpl(entry); return new CefNavigationEntryImpl(entry);
} }
void CefBrowserHostBase::NotifyMoveOrResizeStarted() {
#if BUILDFLAG(IS_WIN) || (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC))
if (!CEF_CURRENTLY_ON_UIT()) {
CEF_POST_TASK(
CEF_UIT,
base::BindOnce(&CefBrowserHostBase::NotifyMoveOrResizeStarted, this));
return;
}
if (platform_delegate_)
platform_delegate_->NotifyMoveOrResizeStarted();
#endif
}
void CefBrowserHostBase::ReplaceMisspelling(const CefString& word) { void CefBrowserHostBase::ReplaceMisspelling(const CefString& word) {
if (!CEF_CURRENTLY_ON_UIT()) { if (!CEF_CURRENTLY_ON_UIT()) {
CEF_POST_TASK( CEF_POST_TASK(

View File

@ -39,14 +39,19 @@ struct CefBrowserCreateParams {
settings = that.settings; settings = that.settings;
request_context = that.request_context; request_context = that.request_context;
extra_info = that.extra_info; extra_info = that.extra_info;
if (that.window_info)
MaybeSetWindowInfo(*that.window_info);
#if defined(TOOLKIT_VIEWS) #if defined(TOOLKIT_VIEWS)
browser_view = that.browser_view; browser_view = that.browser_view;
#endif #endif
return *this; return *this;
} }
// Platform-specific window creation info. Will be nullptr when creating a // Set |window_info| if appropriate (see below).
// views-hosted browser. Currently used with the alloy runtime only. void MaybeSetWindowInfo(const CefWindowInfo& window_info);
// Platform-specific window creation info. Will be nullptr for Views-hosted
// browsers except when using the Chrome runtime with a native parent handle.
std::unique_ptr<CefWindowInfo> window_info; std::unique_ptr<CefWindowInfo> window_info;
#if defined(TOOLKIT_VIEWS) #if defined(TOOLKIT_VIEWS)
@ -154,6 +159,7 @@ class CefBrowserHostBase : public CefBrowserHost,
CefRefPtr<CefClient> GetClient() override; CefRefPtr<CefClient> GetClient() override;
CefRefPtr<CefRequestContext> GetRequestContext() override; CefRefPtr<CefRequestContext> GetRequestContext() override;
bool HasView() override; bool HasView() override;
void SetFocus(bool focus) override;
void StartDownload(const CefString& url) override; void StartDownload(const CefString& url) override;
void DownloadImage(const CefString& image_url, void DownloadImage(const CefString& image_url,
bool is_favicon, bool is_favicon,
@ -180,6 +186,7 @@ class CefBrowserHostBase : public CefBrowserHost,
void GetNavigationEntries(CefRefPtr<CefNavigationEntryVisitor> visitor, void GetNavigationEntries(CefRefPtr<CefNavigationEntryVisitor> visitor,
bool current_only) override; bool current_only) override;
CefRefPtr<CefNavigationEntry> GetVisibleNavigationEntry() override; CefRefPtr<CefNavigationEntry> GetVisibleNavigationEntry() override;
void NotifyMoveOrResizeStarted() override;
// CefBrowser methods: // CefBrowser methods:
bool IsValid() override; bool IsValid() override;
@ -283,6 +290,8 @@ class CefBrowserHostBase : public CefBrowserHost,
// Called from LoadMainFrameURL to perform the actual navigation. // Called from LoadMainFrameURL to perform the actual navigation.
virtual bool Navigate(const content::OpenURLParams& params); virtual bool Navigate(const content::OpenURLParams& params);
void SetFocusInternal(bool focus);
// Thread-safe members. // Thread-safe members.
CefBrowserSettings settings_; CefBrowserSettings settings_;
CefRefPtr<CefClient> client_; CefRefPtr<CefClient> client_;

View File

@ -10,6 +10,10 @@
#include "libcef/browser/thread_util.h" #include "libcef/browser/thread_util.h"
#include "libcef/features/runtime.h" #include "libcef/features/runtime.h"
#if defined(TOOLKIT_VIEWS)
#include "libcef/browser/chrome/views/chrome_child_window.h"
#endif
namespace { namespace {
class CreateBrowserHelper { class CreateBrowserHelper {
@ -138,7 +142,7 @@ CefRefPtr<CefBrowser> CefBrowserHost::CreateBrowserSync(
} }
CefBrowserCreateParams create_params; CefBrowserCreateParams create_params;
create_params.window_info.reset(new CefWindowInfo(windowInfo)); create_params.MaybeSetWindowInfo(windowInfo);
create_params.client = client; create_params.client = client;
create_params.url = url; create_params.url = url;
create_params.settings = settings; create_params.settings = settings;
@ -148,10 +152,24 @@ CefRefPtr<CefBrowser> CefBrowserHost::CreateBrowserSync(
return CefBrowserHostBase::Create(create_params); return CefBrowserHostBase::Create(create_params);
} }
void CefBrowserCreateParams::MaybeSetWindowInfo(
const CefWindowInfo& new_window_info) {
if (!cef::IsChromeRuntimeEnabled() ||
chrome_child_window::HasParentHandle(new_window_info)) {
window_info = std::make_unique<CefWindowInfo>(new_window_info);
}
}
// static // static
CefRefPtr<CefBrowserHostBase> CefBrowserHostBase::Create( CefRefPtr<CefBrowserHostBase> CefBrowserHostBase::Create(
CefBrowserCreateParams& create_params) { CefBrowserCreateParams& create_params) {
if (cef::IsChromeRuntimeEnabled()) { if (cef::IsChromeRuntimeEnabled()) {
#if defined(TOOLKIT_VIEWS)
if (auto browser =
chrome_child_window::MaybeCreateChildBrowser(create_params)) {
return browser.get();
}
#endif
auto browser = ChromeBrowserHostImpl::Create(create_params); auto browser = ChromeBrowserHostImpl::Create(create_params);
return browser.get(); return browser.get();
} }

View File

@ -129,10 +129,10 @@ bool CefBrowserInfoManager::CanCreateWindow(
CefRefPtr<CefClient> client = browser->GetClient(); CefRefPtr<CefClient> client = browser->GetClient();
bool allow = true; bool allow = true;
std::unique_ptr<CefWindowInfo> window_info(new CefWindowInfo); CefWindowInfo window_info;
#if BUILDFLAG(IS_WIN) #if BUILDFLAG(IS_WIN)
window_info->SetAsPopup(nullptr, CefString()); window_info.SetAsPopup(nullptr, CefString());
#endif #endif
auto pending_popup = std::make_unique<CefBrowserInfoManager::PendingPopup>(); auto pending_popup = std::make_unique<CefBrowserInfoManager::PendingPopup>();
@ -157,20 +157,20 @@ bool CefBrowserInfoManager::CanCreateWindow(
#if (BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)) #if (BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC))
// Default to the size from the popup features. // Default to the size from the popup features.
if (cef_features.xSet) if (cef_features.xSet)
window_info->bounds.x = cef_features.x; window_info.bounds.x = cef_features.x;
if (cef_features.ySet) if (cef_features.ySet)
window_info->bounds.y = cef_features.y; window_info.bounds.y = cef_features.y;
if (cef_features.widthSet) if (cef_features.widthSet)
window_info->bounds.width = cef_features.width; window_info.bounds.width = cef_features.width;
if (cef_features.heightSet) if (cef_features.heightSet)
window_info->bounds.height = cef_features.height; window_info.bounds.height = cef_features.height;
#endif #endif
allow = !handler->OnBeforePopup( allow = !handler->OnBeforePopup(
browser.get(), opener_frame, pending_popup->target_url.spec(), browser.get(), opener_frame, pending_popup->target_url.spec(),
pending_popup->target_frame_name, pending_popup->target_frame_name,
static_cast<cef_window_open_disposition_t>(disposition), user_gesture, static_cast<cef_window_open_disposition_t>(disposition), user_gesture,
cef_features, *window_info, pending_popup->client, cef_features, window_info, pending_popup->client,
pending_popup->settings, pending_popup->extra_info, pending_popup->settings, pending_popup->extra_info,
no_javascript_access); no_javascript_access);
} }
@ -178,13 +178,8 @@ bool CefBrowserInfoManager::CanCreateWindow(
if (allow) { if (allow) {
CefBrowserCreateParams create_params; CefBrowserCreateParams create_params;
create_params.MaybeSetWindowInfo(window_info);
if (browser->HasView()) { create_params.popup_with_views_hosted_opener = browser->HasView();
create_params.popup_with_views_hosted_opener = true;
} else {
create_params.window_info = std::move(window_info);
}
create_params.settings = pending_popup->settings; create_params.settings = pending_popup->settings;
create_params.client = pending_popup->client; create_params.client = pending_popup->client;
create_params.extra_info = pending_popup->extra_info; create_params.extra_info = pending_popup->extra_info;

View File

@ -172,9 +172,7 @@ void CefBrowserPlatformDelegate::SendTouchEvent(const CefTouchEvent& event) {
NOTIMPLEMENTED(); NOTIMPLEMENTED();
} }
void CefBrowserPlatformDelegate::SetFocus(bool setFocus) { void CefBrowserPlatformDelegate::SetFocus(bool setFocus) {}
NOTIMPLEMENTED();
}
void CefBrowserPlatformDelegate::SendCaptureLostEvent() { void CefBrowserPlatformDelegate::SendCaptureLostEvent() {
NOTIMPLEMENTED(); NOTIMPLEMENTED();

View File

@ -30,7 +30,9 @@
#endif #endif
#if defined(TOOLKIT_VIEWS) #if defined(TOOLKIT_VIEWS)
#include "libcef/browser/chrome/views/browser_platform_delegate_chrome_child_window.h"
#include "libcef/browser/chrome/views/browser_platform_delegate_chrome_views.h" #include "libcef/browser/chrome/views/browser_platform_delegate_chrome_views.h"
#include "libcef/browser/chrome/views/chrome_child_window.h"
#include "libcef/browser/views/browser_platform_delegate_views.h" #include "libcef/browser/views/browser_platform_delegate_views.h"
#endif #endif
@ -80,50 +82,37 @@ std::unique_ptr<CefBrowserPlatformDelegate> CefBrowserPlatformDelegate::Create(
&create_params.settings, is_windowless ? STATE_ENABLED : STATE_DISABLED); &create_params.settings, is_windowless ? STATE_ENABLED : STATE_DISABLED);
if (cef::IsChromeRuntimeEnabled()) { if (cef::IsChromeRuntimeEnabled()) {
// CefWindowInfo is not used in this case. CefWindowInfo window_info;
if (create_params.window_info) {
window_info = *create_params.window_info;
}
std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate = std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate =
CreateNativeDelegate(CefWindowInfo(), background_color); CreateNativeDelegate(window_info, background_color);
#if defined(TOOLKIT_VIEWS) #if defined(TOOLKIT_VIEWS)
if (create_params.browser_view || if (create_params.window_info) {
create_params.popup_with_views_hosted_opener) { // CefWindowInfo should only be set if a parent handle was specified.
DCHECK(chrome_child_window::HasParentHandle(window_info));
return std::make_unique<CefBrowserPlatformDelegateChromeChildWindow>(
std::move(native_delegate),
static_cast<CefBrowserViewImpl*>(create_params.browser_view.get()));
} else if (create_params.browser_view ||
create_params.popup_with_views_hosted_opener) {
// CefWindowInfo is not used in this case.
return std::make_unique<CefBrowserPlatformDelegateChromeViews>( return std::make_unique<CefBrowserPlatformDelegateChromeViews>(
std::move(native_delegate), std::move(native_delegate),
static_cast<CefBrowserViewImpl*>(create_params.browser_view.get())); static_cast<CefBrowserViewImpl*>(create_params.browser_view.get()));
} }
#endif #endif // defined(TOOLKIT_VIEWS)
return std::make_unique<CefBrowserPlatformDelegateChrome>( return std::make_unique<CefBrowserPlatformDelegateChrome>(
std::move(native_delegate)); std::move(native_delegate));
} }
if (create_params.window_info) {
std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate =
CreateNativeDelegate(*create_params.window_info.get(),
background_color);
if (is_windowless) {
REQUIRE_ALLOY_RUNTIME();
const bool use_shared_texture =
create_params.window_info &&
create_params.window_info->shared_texture_enabled;
const bool use_external_begin_frame =
create_params.window_info &&
create_params.window_info->external_begin_frame_enabled;
return CreateOSRDelegate(std::move(native_delegate), use_shared_texture,
use_external_begin_frame);
}
return std::move(native_delegate);
} else if (create_params.extension_host_type ==
extensions::mojom::ViewType::kExtensionBackgroundPage) {
// Creating a background extension host without a window.
std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate =
CreateNativeDelegate(CefWindowInfo(), background_color);
return std::make_unique<CefBrowserPlatformDelegateBackground>(
std::move(native_delegate));
}
#if defined(TOOLKIT_VIEWS) #if defined(TOOLKIT_VIEWS)
else { if (create_params.browser_view ||
create_params.popup_with_views_hosted_opener) {
// CefWindowInfo is not used in this case. // CefWindowInfo is not used in this case.
std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate = std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate =
CreateNativeDelegate(CefWindowInfo(), background_color); CreateNativeDelegate(CefWindowInfo(), background_color);
@ -133,6 +122,31 @@ std::unique_ptr<CefBrowserPlatformDelegate> CefBrowserPlatformDelegate::Create(
} }
#endif // defined(TOOLKIT_VIEWS) #endif // defined(TOOLKIT_VIEWS)
if (create_params.extension_host_type ==
extensions::mojom::ViewType::kExtensionBackgroundPage) {
// Creating a background extension host without a window.
std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate =
CreateNativeDelegate(CefWindowInfo(), background_color);
return std::make_unique<CefBrowserPlatformDelegateBackground>(
std::move(native_delegate));
} else if (create_params.window_info) {
std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate =
CreateNativeDelegate(*create_params.window_info, background_color);
if (is_windowless) {
REQUIRE_ALLOY_RUNTIME();
const bool use_shared_texture =
create_params.window_info->shared_texture_enabled;
const bool use_external_begin_frame =
create_params.window_info->external_begin_frame_enabled;
return CreateOSRDelegate(std::move(native_delegate), use_shared_texture,
use_external_begin_frame);
}
return std::move(native_delegate);
}
NOTREACHED(); NOTREACHED();
return nullptr; return nullptr;
} }

View File

@ -45,6 +45,10 @@ class CefBrowserPlatformDelegateChrome
void set_chrome_browser(Browser* browser); void set_chrome_browser(Browser* browser);
CefBrowserPlatformDelegateNative* native_delegate() const {
return native_delegate_.get();
}
protected: protected:
std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate_; std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate_;

View File

@ -341,6 +341,7 @@ std::unique_ptr<BrowserDelegate> BrowserDelegate::Create(
create_params = params->create_params_; create_params = params->create_params_;
// Clear these values so they're not persisted to additional Browsers. // Clear these values so they're not persisted to additional Browsers.
params->create_params_.window_info.reset();
#if defined(TOOLKIT_VIEWS) #if defined(TOOLKIT_VIEWS)
params->create_params_.browser_view = nullptr; params->create_params_.browser_view = nullptr;
#endif #endif

View File

@ -143,6 +143,9 @@ void ChromeBrowserHostImpl::OnSetFocus(cef_focus_source_t source) {
if (contents_delegate_->OnSetFocus(source)) if (contents_delegate_->OnSetFocus(source))
return; return;
if (platform_delegate_)
platform_delegate_->SetFocus(true);
if (browser_) { if (browser_) {
const int tab_index = GetCurrentTabIndex(); const int tab_index = GetCurrentTabIndex();
if (tab_index != TabStripModel::kNoTab) { if (tab_index != TabStripModel::kNoTab) {
@ -163,13 +166,13 @@ bool ChromeBrowserHostImpl::TryCloseBrowser() {
return true; return true;
} }
void ChromeBrowserHostImpl::SetFocus(bool focus) {
if (focus) {
OnSetFocus(FOCUS_SOURCE_SYSTEM);
}
}
CefWindowHandle ChromeBrowserHostImpl::GetWindowHandle() { CefWindowHandle ChromeBrowserHostImpl::GetWindowHandle() {
if (CEF_CURRENTLY_ON_UIT()) {
// Always return the most up-to-date window handle for a views-hosted
// browser since it may change if the view is re-parented.
if (platform_delegate_)
return platform_delegate_->GetHostWindowHandle();
}
NOTIMPLEMENTED(); NOTIMPLEMENTED();
return kNullWindowHandle; return kNullWindowHandle;
} }
@ -282,10 +285,6 @@ void ChromeBrowserHostImpl::SendCaptureLostEvent() {
NOTIMPLEMENTED(); NOTIMPLEMENTED();
} }
void ChromeBrowserHostImpl::NotifyMoveOrResizeStarted() {
NOTIMPLEMENTED();
}
int ChromeBrowserHostImpl::GetWindowlessFrameRate() { int ChromeBrowserHostImpl::GetWindowlessFrameRate() {
return 0; return 0;
} }
@ -513,7 +512,20 @@ void ChromeBrowserHostImpl::Attach(content::WebContents* web_contents,
// Notify that the browser has been created. These must be delivered in the // Notify that the browser has been created. These must be delivered in the
// expected order. // expected order.
// 1. Notify the browser's LifeSpanHandler. This must always be the first if (opener && opener->platform_delegate_) {
// 1. Notify the opener browser's platform delegate. With Views this will
// result in a call to CefBrowserViewDelegate::OnPopupBrowserViewCreated().
// We want to call this method first because the implementation will often
// create the Widget for the new popup browser. Without that Widget
// CefBrowserHost::GetWindowHandle() will return kNullWindowHandle in
// OnAfterCreated(), which breaks client expectations (e.g. clients expect
// everything about the browser to be valid at that time).
opener->platform_delegate_->PopupBrowserCreated(
this,
/*is_devtools_popup=*/false);
}
// 2. Notify the browser's LifeSpanHandler. This must always be the first
// notification for the browser. // notification for the browser.
{ {
// The WebContents won't be added to the Browser's TabStripModel until later // The WebContents won't be added to the Browser's TabStripModel until later
@ -522,17 +534,9 @@ void ChromeBrowserHostImpl::Attach(content::WebContents* web_contents,
OnAfterCreated(); OnAfterCreated();
} }
// 2. Notify the platform delegate. With Views this will result in a call to // 3. Notify the platform delegate. With Views this will result in a call to
// CefBrowserViewDelegate::OnBrowserCreated(). // CefBrowserViewDelegate::OnBrowserCreated().
platform_delegate_->NotifyBrowserCreated(); platform_delegate_->NotifyBrowserCreated();
if (opener && opener->platform_delegate_) {
// 3. Notify the opener browser's platform delegate. With Views this will
// result in a call to CefBrowserViewDelegate::OnPopupBrowserViewCreated().
opener->platform_delegate_->PopupBrowserCreated(
this,
/*is_devtools_popup=*/false);
}
} }
void ChromeBrowserHostImpl::SetBrowser(Browser* browser) { void ChromeBrowserHostImpl::SetBrowser(Browser* browser) {

View File

@ -62,7 +62,6 @@ class ChromeBrowserHostImpl : public CefBrowserHostBase {
// CefBrowserHost methods: // CefBrowserHost methods:
void CloseBrowser(bool force_close) override; void CloseBrowser(bool force_close) override;
bool TryCloseBrowser() override; bool TryCloseBrowser() override;
void SetFocus(bool focus) override;
CefWindowHandle GetWindowHandle() override; CefWindowHandle GetWindowHandle() override;
CefWindowHandle GetOpenerWindowHandle() override; CefWindowHandle GetOpenerWindowHandle() override;
double GetZoomLevel() override; double GetZoomLevel() override;
@ -96,7 +95,6 @@ class ChromeBrowserHostImpl : public CefBrowserHostBase {
void SendExternalBeginFrame() override; void SendExternalBeginFrame() override;
void SendTouchEvent(const CefTouchEvent& event) override; void SendTouchEvent(const CefTouchEvent& event) override;
void SendCaptureLostEvent() override; void SendCaptureLostEvent() override;
void NotifyMoveOrResizeStarted() override;
int GetWindowlessFrameRate() override; int GetWindowlessFrameRate() override;
void SetWindowlessFrameRate(int frame_rate) override; void SetWindowlessFrameRate(int frame_rate) override;
void ImeSetComposition(const CefString& text, void ImeSetComposition(const CefString& text,

View File

@ -0,0 +1,38 @@
// Copyright 2022 The Chromium Embedded Framework Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "libcef/browser/chrome/views/browser_platform_delegate_chrome_child_window.h"
#include "include/views/cef_browser_view.h"
#include "libcef/browser/chrome/views/chrome_child_window.h"
CefBrowserPlatformDelegateChromeChildWindow::
CefBrowserPlatformDelegateChromeChildWindow(
std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate,
CefRefPtr<CefBrowserViewImpl> browser_view)
: CefBrowserPlatformDelegateChromeViews(std::move(native_delegate),
browser_view) {}
void CefBrowserPlatformDelegateChromeChildWindow::RenderViewCreated(
content::RenderViewHost* render_view_host) {
CefBrowserPlatformDelegateChromeViews::RenderViewCreated(render_view_host);
// Calls SetHasExternalParent(true). This setting is required for proper
// focus handling on Windows and Linux.
native_delegate_->RenderViewCreated(render_view_host);
}
void CefBrowserPlatformDelegateChromeChildWindow::CloseHostWindow() {
native_delegate_->CloseHostWindow();
}
void CefBrowserPlatformDelegateChromeChildWindow::SetFocus(bool focus) {
native_delegate_->SetFocus(focus);
}
#if BUILDFLAG(IS_WIN) || (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC))
void CefBrowserPlatformDelegateChromeChildWindow::NotifyMoveOrResizeStarted() {
native_delegate_->NotifyMoveOrResizeStarted();
}
#endif

View File

@ -0,0 +1,28 @@
// Copyright 2022 The Chromium Embedded Framework Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CEF_LIBCEF_BROWSER_CHROME_VIEWS_BROWSER_PLATFORM_DELEGATE_CHROME_CHILD_WINDOW_H_
#define CEF_LIBCEF_BROWSER_CHROME_VIEWS_BROWSER_PLATFORM_DELEGATE_CHROME_CHILD_WINDOW_H_
#include "libcef/browser/chrome/views/browser_platform_delegate_chrome_views.h"
// Implementation of Chrome-based browser functionality.
class CefBrowserPlatformDelegateChromeChildWindow
: public CefBrowserPlatformDelegateChromeViews {
public:
CefBrowserPlatformDelegateChromeChildWindow(
std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate,
CefRefPtr<CefBrowserViewImpl> browser_view);
// CefBrowserPlatformDelegate overrides.
void RenderViewCreated(content::RenderViewHost* render_view_host) override;
void CloseHostWindow() override;
void SetFocus(bool focus) override;
#if BUILDFLAG(IS_WIN) || (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC))
void NotifyMoveOrResizeStarted() override;
#endif
};
#endif // CEF_LIBCEF_BROWSER_CHROME_VIEWS_BROWSER_PLATFORM_DELEGATE_CHROME_CHILD_WINDOW_H_

View File

@ -95,6 +95,11 @@ void CefBrowserPlatformDelegateChromeViews::CloseHostWindow() {
widget->Close(); widget->Close();
} }
CefWindowHandle CefBrowserPlatformDelegateChromeViews::GetHostWindowHandle()
const {
return view_util::GetWindowHandle(GetWindowWidget());
}
views::Widget* CefBrowserPlatformDelegateChromeViews::GetWindowWidget() const { views::Widget* CefBrowserPlatformDelegateChromeViews::GetWindowWidget() const {
if (browser_view_->root_view()) if (browser_view_->root_view())
return browser_view_->root_view()->GetWidget(); return browser_view_->root_view()->GetWidget();

View File

@ -24,6 +24,7 @@ class CefBrowserPlatformDelegateChromeViews
void NotifyBrowserDestroyed() override; void NotifyBrowserDestroyed() override;
void BrowserDestroyed(CefBrowserHostBase* browser) override; void BrowserDestroyed(CefBrowserHostBase* browser) override;
void CloseHostWindow() override; void CloseHostWindow() override;
CefWindowHandle GetHostWindowHandle() const override;
views::Widget* GetWindowWidget() const override; views::Widget* GetWindowWidget() const override;
CefRefPtr<CefBrowserView> GetBrowserView() const override; CefRefPtr<CefBrowserView> GetBrowserView() const override;
void PopupWebContentsCreated( void PopupWebContentsCreated(
@ -36,6 +37,8 @@ class CefBrowserPlatformDelegateChromeViews
bool is_devtools) override; bool is_devtools) override;
bool IsViewsHosted() const override; bool IsViewsHosted() const override;
CefRefPtr<CefBrowserViewImpl> browser_view() const { return browser_view_; }
private: private:
void SetBrowserView(CefRefPtr<CefBrowserViewImpl> browser_view); void SetBrowserView(CefRefPtr<CefBrowserViewImpl> browser_view);

View File

@ -0,0 +1,199 @@
// Copyright 2022 The Chromium Embedded Framework Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file.
#include "libcef/browser/chrome/views/chrome_child_window.h"
#include "libcef/browser/chrome/views/browser_platform_delegate_chrome_views.h"
#include "libcef/browser/views/browser_view_impl.h"
#include "libcef/browser/views/window_impl.h"
#if BUILDFLAG(IS_WIN)
#include "libcef/browser/native/browser_platform_delegate_native_win.h"
#include "ui/views/win/hwnd_util.h"
#endif
namespace {
class ChildWindowDelegate : public CefWindowDelegate {
public:
ChildWindowDelegate(const ChildWindowDelegate&) = delete;
ChildWindowDelegate& operator=(const ChildWindowDelegate&) = delete;
static void Create(CefRefPtr<CefBrowserView> browser_view,
const CefWindowInfo& window_info,
gfx::AcceleratedWidget parent_handle) {
DCHECK(parent_handle != gfx::kNullAcceleratedWidget);
// Create the Window. It will show itself after creation.
CefWindowImpl::Create(new ChildWindowDelegate(browser_view, window_info),
parent_handle);
}
void OnWindowCreated(CefRefPtr<CefWindow> window) override {
DCHECK(!window_);
window_ = window;
// Add the browser view. It will now have an associated Widget.
window_->AddChildView(browser_view_);
ShowWindow();
}
void OnWindowDestroyed(CefRefPtr<CefWindow> window) override {
browser_view_ = nullptr;
window_ = nullptr;
}
CefRect GetInitialBounds(CefRefPtr<CefWindow> window) override {
CefRect initial_bounds(window_info_.bounds);
if (initial_bounds.IsEmpty())
return CefRect(0, 0, 800, 600);
return initial_bounds;
}
void ShowWindow() {
#if BUILDFLAG(IS_WIN)
auto widget = static_cast<CefWindowImpl*>(window_.get())->widget();
DCHECK(widget);
const HWND widget_hwnd = HWNDForWidget(widget);
DCHECK(widget_hwnd);
// The native delegate needs state to perform some actions.
auto browser =
static_cast<CefBrowserHostBase*>(browser_view_->GetBrowser().get());
auto platform_delegate = browser->platform_delegate();
DCHECK(platform_delegate->IsViewsHosted());
auto chrome_delegate =
static_cast<CefBrowserPlatformDelegateChromeViews*>(platform_delegate);
auto native_delegate = static_cast<CefBrowserPlatformDelegateNativeWin*>(
chrome_delegate->native_delegate());
native_delegate->set_widget(widget, widget_hwnd);
if (window_info_.ex_style & WS_EX_NOACTIVATE) {
const DWORD widget_ex_styles = GetWindowLongPtr(widget_hwnd, GWL_EXSTYLE);
// Add the WS_EX_NOACTIVATE style on the DesktopWindowTreeHostWin HWND
// so that HWNDMessageHandler::Show() called via Widget::Show() does not
// activate the window.
SetWindowLongPtr(widget_hwnd, GWL_EXSTYLE,
widget_ex_styles | WS_EX_NOACTIVATE);
window_->Show();
// Remove the WS_EX_NOACTIVATE style so that future mouse clicks inside
// the browser correctly activate and focus the window.
SetWindowLongPtr(widget_hwnd, GWL_EXSTYLE, widget_ex_styles);
return;
}
#endif // BUILDFLAG(IS_WIN)
window_->Show();
// Give keyboard focus to the browser view.
browser_view_->RequestFocus();
}
private:
ChildWindowDelegate(CefRefPtr<CefBrowserView> browser_view,
const CefWindowInfo& window_info)
: browser_view_(browser_view), window_info_(window_info) {}
CefRefPtr<CefBrowserView> browser_view_;
const CefWindowInfo window_info_;
CefRefPtr<CefWindow> window_;
IMPLEMENT_REFCOUNTING(ChildWindowDelegate);
};
class ChildBrowserViewDelegate : public CefBrowserViewDelegate {
public:
ChildBrowserViewDelegate() = default;
ChildBrowserViewDelegate(const ChildBrowserViewDelegate&) = delete;
ChildBrowserViewDelegate& operator=(const ChildBrowserViewDelegate&) = delete;
CefRefPtr<CefBrowserViewDelegate> GetDelegateForPopupBrowserView(
CefRefPtr<CefBrowserView> browser_view,
const CefBrowserSettings& settings,
CefRefPtr<CefClient> client,
bool is_devtools) override {
return new ChildBrowserViewDelegate();
}
bool OnPopupBrowserViewCreated(CefRefPtr<CefBrowserView> browser_view,
CefRefPtr<CefBrowserView> popup_browser_view,
bool is_devtools) override {
DCHECK(!is_devtools);
auto new_browser = static_cast<CefBrowserHostBase*>(
popup_browser_view->GetBrowser().get());
auto new_platform_delegate = new_browser->platform_delegate();
DCHECK(new_platform_delegate->IsViewsHosted());
auto new_platform_delegate_impl =
static_cast<CefBrowserPlatformDelegateChromeViews*>(
new_platform_delegate);
const auto& window_info =
new_platform_delegate_impl->native_delegate()->window_info();
const auto parent_handle =
chrome_child_window::GetParentHandle(window_info);
if (parent_handle != gfx::kNullAcceleratedWidget) {
ChildWindowDelegate::Create(popup_browser_view, window_info,
parent_handle);
return true;
}
// Use the default implementation that creates a new Views-hosted top-level
// window.
return false;
}
private:
IMPLEMENT_REFCOUNTING(ChildBrowserViewDelegate);
};
} // namespace
namespace chrome_child_window {
bool HasParentHandle(const CefWindowInfo& window_info) {
return GetParentHandle(window_info) != gfx::kNullAcceleratedWidget;
}
gfx::AcceleratedWidget GetParentHandle(const CefWindowInfo& window_info) {
#if !BUILDFLAG(IS_MAC)
return window_info.parent_window;
#else
return gfx::kNullAcceleratedWidget;
#endif
}
CefRefPtr<CefBrowserHostBase> MaybeCreateChildBrowser(
const CefBrowserCreateParams& create_params) {
// If the BrowserView already exists it means that we're dealing with a popup
// and we'll instead create the Window in OnPopupBrowserViewCreated.
if (create_params.browser_view)
return nullptr;
if (!create_params.window_info)
return nullptr;
const auto parent_handle = GetParentHandle(*create_params.window_info);
if (parent_handle == gfx::kNullAcceleratedWidget)
return nullptr;
// Create the BrowserView.
auto browser_view = CefBrowserViewImpl::Create(
*create_params.window_info, create_params.client, create_params.url,
create_params.settings, create_params.extra_info,
create_params.request_context, new ChildBrowserViewDelegate());
ChildWindowDelegate::Create(browser_view, *create_params.window_info,
parent_handle);
return static_cast<CefBrowserHostBase*>(browser_view->GetBrowser().get());
}
} // namespace chrome_child_window

View File

@ -0,0 +1,24 @@
// Copyright 2022 The Chromium Embedded Framework Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file.
#ifndef CEF_LIBCEF_BROWSER_CHROME_VIEWS_CHROME_CHILD_WINDOW_H_
#define CEF_LIBCEF_BROWSER_CHROME_VIEWS_CHROME_CHILD_WINDOW_H_
#pragma once
#include "libcef/browser/browser_host_base.h"
#include "ui/gfx/native_widget_types.h"
namespace chrome_child_window {
bool HasParentHandle(const CefWindowInfo& window_info);
gfx::AcceleratedWidget GetParentHandle(const CefWindowInfo& window_info);
// Called from CefBrowserHostBase::Create.
CefRefPtr<CefBrowserHostBase> MaybeCreateChildBrowser(
const CefBrowserCreateParams& create_params);
} // namespace chrome_child_window
#endif // CEF_LIBCEF_BROWSER_CHROME_VIEWS_CHROME_CHILD_WINDOW_H_

View File

@ -251,8 +251,11 @@ CefDevToolsFrontend* CefDevToolsFrontend::Show(
} }
CefBrowserCreateParams create_params; CefBrowserCreateParams create_params;
if (!inspected_browser->is_views_hosted()) if (inspected_browser->is_views_hosted()) {
create_params.popup_with_views_hosted_opener = true;
} else {
create_params.window_info.reset(new CefWindowInfo(windowInfo)); create_params.window_info.reset(new CefWindowInfo(windowInfo));
}
create_params.client = client; create_params.client = client;
create_params.settings = new_settings; create_params.settings = new_settings;
create_params.devtools_opener = inspected_browser; create_params.devtools_opener = inspected_browser;

View File

@ -381,6 +381,7 @@ base::DictionaryValue* CefExtensionFunctionDetails::OpenTab(
if (active_browser->is_views_hosted()) { if (active_browser->is_views_hosted()) {
// The new browser will also be Views hosted. // The new browser will also be Views hosted.
create_params.popup_with_views_hosted_opener = true;
create_params.window_info.reset(); create_params.window_info.reset();
} }

View File

@ -37,7 +37,7 @@ CefBrowserPlatformDelegateNativeLinux::CefBrowserPlatformDelegateNativeLinux(
void CefBrowserPlatformDelegateNativeLinux::BrowserDestroyed( void CefBrowserPlatformDelegateNativeLinux::BrowserDestroyed(
CefBrowserHostBase* browser) { CefBrowserHostBase* browser) {
CefBrowserPlatformDelegateNative::BrowserDestroyed(browser); CefBrowserPlatformDelegateNativeAura::BrowserDestroyed(browser);
if (host_window_created_) { if (host_window_created_) {
// Release the reference added in CreateHostWindow(). // Release the reference added in CreateHostWindow().
@ -155,7 +155,7 @@ void CefBrowserPlatformDelegateNativeLinux::SetFocus(bool setFocus) {
void CefBrowserPlatformDelegateNativeLinux::NotifyMoveOrResizeStarted() { void CefBrowserPlatformDelegateNativeLinux::NotifyMoveOrResizeStarted() {
// Call the parent method to dismiss any existing popups. // Call the parent method to dismiss any existing popups.
CefBrowserPlatformDelegateNative::NotifyMoveOrResizeStarted(); CefBrowserPlatformDelegateNativeAura::NotifyMoveOrResizeStarted();
if (!web_contents_) if (!web_contents_)
return; return;

View File

@ -156,9 +156,18 @@ CefBrowserPlatformDelegateNativeWin::CefBrowserPlatformDelegateNativeWin(
SkColor background_color) SkColor background_color)
: CefBrowserPlatformDelegateNativeAura(window_info, background_color) {} : CefBrowserPlatformDelegateNativeAura(window_info, background_color) {}
void CefBrowserPlatformDelegateNativeWin::set_widget(
views::Widget* widget,
CefWindowHandle widget_handle) {
DCHECK(!window_widget_);
window_widget_ = widget;
DCHECK(!window_info_.window);
window_info_.window = widget_handle;
}
void CefBrowserPlatformDelegateNativeWin::BrowserDestroyed( void CefBrowserPlatformDelegateNativeWin::BrowserDestroyed(
CefBrowserHostBase* browser) { CefBrowserHostBase* browser) {
CefBrowserPlatformDelegateNative::BrowserDestroyed(browser); CefBrowserPlatformDelegateNativeAura::BrowserDestroyed(browser);
if (host_window_created_) { if (host_window_created_) {
// Release the reference added in CreateHostWindow(). // Release the reference added in CreateHostWindow().
@ -315,7 +324,7 @@ void CefBrowserPlatformDelegateNativeWin::SetFocus(bool setFocus) {
void CefBrowserPlatformDelegateNativeWin::NotifyMoveOrResizeStarted() { void CefBrowserPlatformDelegateNativeWin::NotifyMoveOrResizeStarted() {
// Call the parent method to dismiss any existing popups. // Call the parent method to dismiss any existing popups.
CefBrowserPlatformDelegateNative::NotifyMoveOrResizeStarted(); CefBrowserPlatformDelegateNativeAura::NotifyMoveOrResizeStarted();
if (!window_widget_) if (!window_widget_)
return; return;

View File

@ -16,6 +16,9 @@ class CefBrowserPlatformDelegateNativeWin
CefBrowserPlatformDelegateNativeWin(const CefWindowInfo& window_info, CefBrowserPlatformDelegateNativeWin(const CefWindowInfo& window_info,
SkColor background_color); SkColor background_color);
// Called from chrome_child_window.cc after |widget| is created.
void set_widget(views::Widget* widget, CefWindowHandle widget_handle);
// CefBrowserPlatformDelegate methods: // CefBrowserPlatformDelegate methods:
void BrowserDestroyed(CefBrowserHostBase* browser) override; void BrowserDestroyed(CefBrowserHostBase* browser) override;
bool CreateHostWindow() override; bool CreateHostWindow() override;

View File

@ -12,8 +12,8 @@
namespace cursor_util { namespace cursor_util {
bool OnCursorChange(CefBrowserHostBase* browser, const ui::Cursor& ui_cursor) { bool OnCursorChange(CefRefPtr<CefBrowser> browser, const ui::Cursor& ui_cursor) {
auto client = browser->GetClient(); auto client = browser->GetHost()->GetClient();
if (!client) if (!client)
return false; return false;
auto handler = client->GetDisplayHandler(); auto handler = client->GetDisplayHandler();

View File

@ -5,7 +5,7 @@
#ifndef CEF_LIBCEF_BROWSER_NATIVE_CURSOR_UTIL_H_ #ifndef CEF_LIBCEF_BROWSER_NATIVE_CURSOR_UTIL_H_
#define CEF_LIBCEF_BROWSER_NATIVE_CURSOR_UTIL_H_ #define CEF_LIBCEF_BROWSER_NATIVE_CURSOR_UTIL_H_
#include "include/internal/cef_types.h" #include "include/cef_browser.h"
#include "ui/base/cursor/cursor.h" #include "ui/base/cursor/cursor.h"
#include "ui/base/cursor/mojom/cursor_type.mojom-forward.h" #include "ui/base/cursor/mojom/cursor_type.mojom-forward.h"
@ -14,8 +14,6 @@
#include "ui/base/cursor/platform_cursor.h" #include "ui/base/cursor/platform_cursor.h"
#endif #endif
class CefBrowserHostBase;
namespace cursor_util { namespace cursor_util {
#if defined(USE_AURA) #if defined(USE_AURA)
@ -24,7 +22,7 @@ cef_cursor_handle_t ToCursorHandle(scoped_refptr<ui::PlatformCursor> cursor);
#endif // defined(USE_AURA) #endif // defined(USE_AURA)
// Returns true if the client handled the cursor change. // Returns true if the client handled the cursor change.
bool OnCursorChange(CefBrowserHostBase* browser, const ui::Cursor& ui_cursor); bool OnCursorChange(CefRefPtr<CefBrowser> browser, const ui::Cursor& ui_cursor);
} // namespace cursor_util } // namespace cursor_util

View File

@ -23,8 +23,8 @@ CefRefPtr<CefBrowserView> CefBrowserView::CreateBrowserView(
CefRefPtr<CefDictionaryValue> extra_info, CefRefPtr<CefDictionaryValue> extra_info,
CefRefPtr<CefRequestContext> request_context, CefRefPtr<CefRequestContext> request_context,
CefRefPtr<CefBrowserViewDelegate> delegate) { CefRefPtr<CefBrowserViewDelegate> delegate) {
return CefBrowserViewImpl::Create(client, url, settings, extra_info, return CefBrowserViewImpl::Create(CefWindowInfo(), client, url, settings,
request_context, delegate); extra_info, request_context, delegate);
} }
// static // static
@ -41,6 +41,7 @@ CefRefPtr<CefBrowserView> CefBrowserView::GetForBrowser(
// static // static
CefRefPtr<CefBrowserViewImpl> CefBrowserViewImpl::Create( CefRefPtr<CefBrowserViewImpl> CefBrowserViewImpl::Create(
const CefWindowInfo& window_info,
CefRefPtr<CefClient> client, CefRefPtr<CefClient> client,
const CefString& url, const CefString& url,
const CefBrowserSettings& settings, const CefBrowserSettings& settings,
@ -62,8 +63,8 @@ CefRefPtr<CefBrowserViewImpl> CefBrowserViewImpl::Create(
} }
CefRefPtr<CefBrowserViewImpl> browser_view = new CefBrowserViewImpl(delegate); CefRefPtr<CefBrowserViewImpl> browser_view = new CefBrowserViewImpl(delegate);
browser_view->SetPendingBrowserCreateParams(client, url, settings, extra_info, browser_view->SetPendingBrowserCreateParams(
request_context); window_info, client, url, settings, extra_info, request_context);
browser_view->Initialize(); browser_view->Initialize();
browser_view->SetDefaults(settings); browser_view->SetDefaults(settings);
return browser_view; return browser_view;
@ -212,6 +213,7 @@ CefBrowserViewImpl::CefBrowserViewImpl(
: ParentClass(delegate), weak_ptr_factory_(this) {} : ParentClass(delegate), weak_ptr_factory_(this) {}
void CefBrowserViewImpl::SetPendingBrowserCreateParams( void CefBrowserViewImpl::SetPendingBrowserCreateParams(
const CefWindowInfo& window_info,
CefRefPtr<CefClient> client, CefRefPtr<CefClient> client,
const CefString& url, const CefString& url,
const CefBrowserSettings& settings, const CefBrowserSettings& settings,
@ -219,6 +221,7 @@ void CefBrowserViewImpl::SetPendingBrowserCreateParams(
CefRefPtr<CefRequestContext> request_context) { CefRefPtr<CefRequestContext> request_context) {
DCHECK(!pending_browser_create_params_); DCHECK(!pending_browser_create_params_);
pending_browser_create_params_.reset(new CefBrowserCreateParams()); pending_browser_create_params_.reset(new CefBrowserCreateParams());
pending_browser_create_params_->MaybeSetWindowInfo(window_info);
pending_browser_create_params_->client = client; pending_browser_create_params_->client = client;
pending_browser_create_params_->url = url; pending_browser_create_params_->url = url;
pending_browser_create_params_->settings = settings; pending_browser_create_params_->settings = settings;
@ -248,6 +251,9 @@ void CefBrowserViewImpl::InitializeRootView() {
} }
views::WebView* CefBrowserViewImpl::web_view() const { views::WebView* CefBrowserViewImpl::web_view() const {
if (!root_view())
return nullptr;
if (cef::IsChromeRuntimeEnabled()) { if (cef::IsChromeRuntimeEnabled()) {
return static_cast<ChromeBrowserView*>(root_view())->contents_web_view(); return static_cast<ChromeBrowserView*>(root_view())->contents_web_view();
} }

View File

@ -30,7 +30,9 @@ class CefBrowserViewImpl
CefBrowserViewImpl& operator=(const CefBrowserViewImpl&) = delete; CefBrowserViewImpl& operator=(const CefBrowserViewImpl&) = delete;
// Create a new CefBrowserView instance. |delegate| may be nullptr. // Create a new CefBrowserView instance. |delegate| may be nullptr.
// |window_info| will only be used when creating a Chrome child window.
static CefRefPtr<CefBrowserViewImpl> Create( static CefRefPtr<CefBrowserViewImpl> Create(
const CefWindowInfo& window_info,
CefRefPtr<CefClient> client, CefRefPtr<CefClient> client,
const CefString& url, const CefString& url,
const CefBrowserSettings& settings, const CefBrowserSettings& settings,
@ -84,6 +86,7 @@ class CefBrowserViewImpl
explicit CefBrowserViewImpl(CefRefPtr<CefBrowserViewDelegate> delegate); explicit CefBrowserViewImpl(CefRefPtr<CefBrowserViewDelegate> delegate);
void SetPendingBrowserCreateParams( void SetPendingBrowserCreateParams(
const CefWindowInfo& window_info,
CefRefPtr<CefClient> client, CefRefPtr<CefClient> client,
const CefString& url, const CefString& url,
const CefBrowserSettings& settings, const CefBrowserSettings& settings,

View File

@ -125,16 +125,17 @@ class CefUnhandledKeyEventHandler : public ui::EventHandler {
// static // static
CefRefPtr<CefWindow> CefWindow::CreateTopLevelWindow( CefRefPtr<CefWindow> CefWindow::CreateTopLevelWindow(
CefRefPtr<CefWindowDelegate> delegate) { CefRefPtr<CefWindowDelegate> delegate) {
return CefWindowImpl::Create(delegate); return CefWindowImpl::Create(delegate, gfx::kNullAcceleratedWidget);
} }
// static // static
CefRefPtr<CefWindowImpl> CefWindowImpl::Create( CefRefPtr<CefWindowImpl> CefWindowImpl::Create(
CefRefPtr<CefWindowDelegate> delegate) { CefRefPtr<CefWindowDelegate> delegate,
gfx::AcceleratedWidget parent_widget) {
CEF_REQUIRE_UIT_RETURN(nullptr); CEF_REQUIRE_UIT_RETURN(nullptr);
CefRefPtr<CefWindowImpl> window = new CefWindowImpl(delegate); CefRefPtr<CefWindowImpl> window = new CefWindowImpl(delegate);
window->Initialize(); window->Initialize();
window->CreateWidget(); window->CreateWidget(parent_widget);
if (delegate) if (delegate)
delegate->OnWindowCreated(window.get()); delegate->OnWindowCreated(window.get());
return window; return window;
@ -656,10 +657,10 @@ void CefWindowImpl::InitializeRootView() {
static_cast<CefWindowView*>(root_view())->Initialize(); static_cast<CefWindowView*>(root_view())->Initialize();
} }
void CefWindowImpl::CreateWidget() { void CefWindowImpl::CreateWidget(gfx::AcceleratedWidget parent_widget) {
DCHECK(!widget_); DCHECK(!widget_);
root_view()->CreateWidget(); root_view()->CreateWidget(parent_widget);
widget_ = root_view()->GetWidget(); widget_ = root_view()->GetWidget();
DCHECK(widget_); DCHECK(widget_);

View File

@ -33,8 +33,10 @@ class CefWindowImpl
CefWindowImpl(const CefWindowImpl&) = delete; CefWindowImpl(const CefWindowImpl&) = delete;
CefWindowImpl& operator=(const CefWindowImpl&) = delete; CefWindowImpl& operator=(const CefWindowImpl&) = delete;
// Create a new CefWindow instance. |delegate| may be nullptr. // Create a new CefWindow instance. |delegate| may be nullptr. |parent_widget|
static CefRefPtr<CefWindowImpl> Create(CefRefPtr<CefWindowDelegate> delegate); // will be used when creating a Chrome child window.
static CefRefPtr<CefWindowImpl> Create(CefRefPtr<CefWindowDelegate> delegate,
gfx::AcceleratedWidget parent_widget);
// CefWindow methods: // CefWindow methods:
void Show() override; void Show() override;
@ -141,7 +143,7 @@ class CefWindowImpl
void InitializeRootView() override; void InitializeRootView() override;
// Initialize the Widget. // Initialize the Widget.
void CreateWidget(); void CreateWidget(gfx::AcceleratedWidget parent_widget);
views::Widget* widget_; views::Widget* widget_;

View File

@ -254,7 +254,7 @@ CefWindowView::CefWindowView(CefWindowDelegate* cef_delegate,
DCHECK(window_delegate_); DCHECK(window_delegate_);
} }
void CefWindowView::CreateWidget() { void CefWindowView::CreateWidget(gfx::AcceleratedWidget parent_widget) {
DCHECK(!GetWidget()); DCHECK(!GetWidget());
// |widget| is owned by the NativeWidget and will be destroyed in response to // |widget| is owned by the NativeWidget and will be destroyed in response to
@ -264,8 +264,29 @@ void CefWindowView::CreateWidget() {
views::Widget::InitParams params; views::Widget::InitParams params;
params.delegate = this; params.delegate = this;
params.type = views::Widget::InitParams::TYPE_WINDOW;
bool can_activate = true; bool can_activate = true;
bool can_resize = true;
const bool has_native_parent = parent_widget != gfx::kNullAcceleratedWidget;
if (has_native_parent) {
params.parent_widget = parent_widget;
// Remove the window frame.
is_frameless_ = true;
// See CalculateWindowStylesFromInitParams in
// ui/views/widget/widget_hwnd_utils.cc for the conversion of |params| to
// Windows style flags.
// - Set the WS_CHILD flag.
params.child = true;
// - Set the WS_VISIBLE flag.
params.type = views::Widget::InitParams::TYPE_CONTROL;
// - Don't set the WS_EX_COMPOSITED flag.
params.opacity = views::Widget::InitParams::WindowOpacity::kOpaque;
} else {
params.type = views::Widget::InitParams::TYPE_WINDOW;
}
// WidgetDelegate::DeleteDelegate() will delete |this| after executing the // WidgetDelegate::DeleteDelegate() will delete |this| after executing the
// registered callback. // registered callback.
@ -275,47 +296,49 @@ void CefWindowView::CreateWidget() {
if (cef_delegate()) { if (cef_delegate()) {
CefRefPtr<CefWindow> cef_window = GetCefWindow(); CefRefPtr<CefWindow> cef_window = GetCefWindow();
is_frameless_ = cef_delegate()->IsFrameless(cef_window);
auto bounds = cef_delegate()->GetInitialBounds(cef_window); auto bounds = cef_delegate()->GetInitialBounds(cef_window);
params.bounds = gfx::Rect(bounds.x, bounds.y, bounds.width, bounds.height); params.bounds = gfx::Rect(bounds.x, bounds.y, bounds.width, bounds.height);
SetCanResize(cef_delegate()->CanResize(cef_window)); if (has_native_parent) {
DCHECK(!params.bounds.IsEmpty());
} else {
is_frameless_ = cef_delegate()->IsFrameless(cef_window);
can_resize = cef_delegate()->CanResize(cef_window);
const auto show_state = cef_delegate()->GetInitialShowState(cef_window); const auto show_state = cef_delegate()->GetInitialShowState(cef_window);
switch (show_state) { switch (show_state) {
case CEF_SHOW_STATE_NORMAL: case CEF_SHOW_STATE_NORMAL:
params.show_state = ui::SHOW_STATE_NORMAL; params.show_state = ui::SHOW_STATE_NORMAL;
break; break;
case CEF_SHOW_STATE_MINIMIZED: case CEF_SHOW_STATE_MINIMIZED:
params.show_state = ui::SHOW_STATE_MINIMIZED; params.show_state = ui::SHOW_STATE_MINIMIZED;
break; break;
case CEF_SHOW_STATE_MAXIMIZED: case CEF_SHOW_STATE_MAXIMIZED:
params.show_state = ui::SHOW_STATE_MAXIMIZED; params.show_state = ui::SHOW_STATE_MAXIMIZED;
break; break;
case CEF_SHOW_STATE_FULLSCREEN: case CEF_SHOW_STATE_FULLSCREEN:
params.show_state = ui::SHOW_STATE_FULLSCREEN; params.show_state = ui::SHOW_STATE_FULLSCREEN;
break; break;
} }
bool is_menu = false; bool is_menu = false;
bool can_activate_menu = true; bool can_activate_menu = true;
CefRefPtr<CefWindow> parent_window = cef_delegate()->GetParentWindow( CefRefPtr<CefWindow> parent_window = cef_delegate()->GetParentWindow(
cef_window, &is_menu, &can_activate_menu); cef_window, &is_menu, &can_activate_menu);
if (parent_window && !parent_window->IsSame(cef_window)) { if (parent_window && !parent_window->IsSame(cef_window)) {
CefWindowImpl* parent_window_impl = CefWindowImpl* parent_window_impl =
static_cast<CefWindowImpl*>(parent_window.get()); static_cast<CefWindowImpl*>(parent_window.get());
params.parent = view_util::GetNativeView(parent_window_impl->widget()); params.parent = view_util::GetNativeView(parent_window_impl->widget());
if (is_menu) { if (is_menu) {
// Don't clip the window to parent bounds. // Don't clip the window to parent bounds.
params.type = views::Widget::InitParams::TYPE_MENU; params.type = views::Widget::InitParams::TYPE_MENU;
// Don't set "always on top" for the window. // Don't set "always on top" for the window.
params.z_order = ui::ZOrderLevel::kNormal; params.z_order = ui::ZOrderLevel::kNormal;
can_activate = can_activate_menu; can_activate = can_activate_menu;
if (can_activate_menu) }
params.activatable = views::Widget::InitParams::Activatable::kYes;
} }
} }
} }
@ -325,6 +348,13 @@ void CefWindowView::CreateWidget() {
params.bounds = gfx::Rect(CalculatePreferredSize()); params.bounds = gfx::Rect(CalculatePreferredSize());
} }
if (can_activate) {
// Cause WidgetDelegate::CanActivate to return true.
params.activatable = views::Widget::InitParams::Activatable::kYes;
}
SetCanResize(can_resize);
#if BUILDFLAG(IS_WIN) #if BUILDFLAG(IS_WIN)
if (is_frameless_) { if (is_frameless_) {
// Don't show the native window caption. Setting this value on Linux will // Don't show the native window caption. Setting this value on Linux will

View File

@ -51,7 +51,7 @@ class CefWindowView
CefWindowView& operator=(const CefWindowView&) = delete; CefWindowView& operator=(const CefWindowView&) = delete;
// Create the Widget. // Create the Widget.
void CreateWidget(); void CreateWidget(gfx::AcceleratedWidget parent_widget);
// Returns the CefWindow associated with this view. See comments on // Returns the CefWindow associated with this view. See comments on
// CefViewView::GetCefView. // CefViewView::GetCefView.

View File

@ -539,5 +539,10 @@ patches = [
# Remove DCHECK that triggers while loading DevTools resources. # Remove DCHECK that triggers while loading DevTools resources.
# https://bugs.chromium.org/p/chromium/issues/detail?id=1289230 # https://bugs.chromium.org/p/chromium/issues/detail?id=1289230
'name': 'blink_security_policy_1289230', 'name': 'blink_security_policy_1289230',
},
{
# Windows: Always use the root window as the owner for shell dialogs.
# https://bitbucket.org/chromiumembedded/cef/issues/3294
'name': 'win_shell_dialogs_3294',
} }
] ]

View File

@ -45,7 +45,7 @@ index f9d291e52bc70..288d8ea2b3d72 100644
bool BrowserCommandController::IsWebAppOrCustomTab() const { bool BrowserCommandController::IsWebAppOrCustomTab() const {
diff --git chrome/browser/ui/views/frame/browser_frame.cc chrome/browser/ui/views/frame/browser_frame.cc diff --git chrome/browser/ui/views/frame/browser_frame.cc chrome/browser/ui/views/frame/browser_frame.cc
index 42ce84a750319..a0e5ead15263b 100644 index 42ce84a750319..28b8702260434 100644
--- chrome/browser/ui/views/frame/browser_frame.cc --- chrome/browser/ui/views/frame/browser_frame.cc
+++ chrome/browser/ui/views/frame/browser_frame.cc +++ chrome/browser/ui/views/frame/browser_frame.cc
@@ -74,15 +74,23 @@ bool IsUsingGtkTheme(Profile* profile) { @@ -74,15 +74,23 @@ bool IsUsingGtkTheme(Profile* profile) {
@ -127,7 +127,16 @@ index 42ce84a750319..a0e5ead15263b 100644
Browser* browser = browser_view_->browser(); Browser* browser = browser_view_->browser();
// If this is an incognito profile, there should never be a custom theme. // If this is an incognito profile, there should never be a custom theme.
if (browser->profile()->IsIncognitoProfile()) if (browser->profile()->IsIncognitoProfile())
@@ -352,6 +378,8 @@ void BrowserFrame::SetTabDragKind(TabDragKind tab_drag_kind) { @@ -263,6 +289,8 @@ BrowserFrame::GetCustomTheme() const {
}
void BrowserFrame::OnNativeWidgetWorkspaceChanged() {
+ if (!browser_view_)
+ return;
chrome::SaveWindowWorkspace(browser_view_->browser(), GetWorkspace());
chrome::SaveWindowVisibleOnAllWorkspaces(browser_view_->browser(),
IsVisibleOnAllWorkspaces());
@@ -352,6 +380,8 @@ void BrowserFrame::SetTabDragKind(TabDragKind tab_drag_kind) {
ui::ColorProviderManager::Key BrowserFrame::GetColorProviderKey() const { ui::ColorProviderManager::Key BrowserFrame::GetColorProviderKey() const {
auto key = Widget::GetColorProviderKey(); auto key = Widget::GetColorProviderKey();
@ -136,7 +145,7 @@ index 42ce84a750319..a0e5ead15263b 100644
auto* app_controller = browser_view_->browser()->app_controller(); auto* app_controller = browser_view_->browser()->app_controller();
key.app_controller = key.app_controller =
app_controller ? app_controller->get_weak_ref() : nullptr; app_controller ? app_controller->get_weak_ref() : nullptr;
@@ -382,7 +410,8 @@ void BrowserFrame::SelectNativeTheme() { @@ -382,7 +412,8 @@ void BrowserFrame::SelectNativeTheme() {
// Select between regular, dark and GTK theme. // Select between regular, dark and GTK theme.
ui::NativeTheme* native_theme = ui::NativeTheme::GetInstanceForNativeUi(); ui::NativeTheme* native_theme = ui::NativeTheme::GetInstanceForNativeUi();
@ -146,7 +155,7 @@ index 42ce84a750319..a0e5ead15263b 100644
// No matter if we are using the default theme or not we always use the dark // No matter if we are using the default theme or not we always use the dark
// ui instance. // ui instance.
SetNativeTheme(ui::NativeTheme::GetInstanceForDarkUI()); SetNativeTheme(ui::NativeTheme::GetInstanceForDarkUI());
@@ -395,7 +424,8 @@ void BrowserFrame::SelectNativeTheme() { @@ -395,7 +426,8 @@ void BrowserFrame::SelectNativeTheme() {
// display_override so the web contents can blend with the overlay by using // display_override so the web contents can blend with the overlay by using
// the developer-provided theme color for a better experience. Context: // the developer-provided theme color for a better experience. Context:
// https://crbug.com/1219073. // https://crbug.com/1219073.

View File

@ -0,0 +1,29 @@
diff --git ui/shell_dialogs/base_shell_dialog_win.cc ui/shell_dialogs/base_shell_dialog_win.cc
index 46fd116c02dad..499bf49cff882 100644
--- ui/shell_dialogs/base_shell_dialog_win.cc
+++ ui/shell_dialogs/base_shell_dialog_win.cc
@@ -59,11 +59,15 @@ BaseShellDialogImpl::Owners& BaseShellDialogImpl::GetOwners() {
// static
void BaseShellDialogImpl::DisableOwner(HWND owner) {
+ if (owner)
+ owner = GetAncestor(owner, GA_ROOT);
SetOwnerEnabled(owner, false);
}
std::unique_ptr<BaseShellDialogImpl::RunState> BaseShellDialogImpl::BeginRun(
HWND owner) {
+ if (owner)
+ owner = GetAncestor(owner, GA_ROOT);
// Cannot run a modal shell dialog if one is already running for this owner.
DCHECK(!IsRunningDialogForOwner(owner));
// The owner must be a top level window, otherwise we could end up with two
@@ -89,6 +93,8 @@ void BaseShellDialogImpl::EndRun(std::unique_ptr<RunState> run_state) {
}
bool BaseShellDialogImpl::IsRunningDialogForOwner(HWND owner) const {
+ if (owner)
+ owner = GetAncestor(owner, GA_ROOT);
return (owner && GetOwners().find(owner) != GetOwners().end());
}

View File

@ -108,6 +108,13 @@ MainContextImpl::MainContextImpl(CefRefPtr<CefCommandLine> command_line,
use_views_ = false; use_views_ = false;
} }
#if defined(OS_WIN) || defined(OS_LINUX)
if (use_chrome_runtime_ && !use_views_ &&
!command_line->HasSwitch(switches::kUseNative)) {
LOG(WARNING) << "Chrome runtime defaults to the Views framework.";
use_views_ = true;
}
#else // !(defined(OS_WIN) || defined(OS_LINUX))
if (use_chrome_runtime_ && !use_views_) { if (use_chrome_runtime_ && !use_views_) {
// TODO(chrome): Add support for this runtime configuration (e.g. a fully // TODO(chrome): Add support for this runtime configuration (e.g. a fully
// styled Chrome window with cefclient menu customizations). In the mean // styled Chrome window with cefclient menu customizations). In the mean
@ -115,6 +122,7 @@ MainContextImpl::MainContextImpl(CefRefPtr<CefCommandLine> command_line,
LOG(WARNING) << "Chrome runtime requires the Views framework."; LOG(WARNING) << "Chrome runtime requires the Views framework.";
use_views_ = true; use_views_ = true;
} }
#endif // !(defined(OS_WIN) || defined(OS_LINUX))
if (use_views_ && command_line->HasSwitch(switches::kHideFrame) && if (use_views_ && command_line->HasSwitch(switches::kHideFrame) &&
!command_line_->HasSwitch(switches::kUrl)) { !command_line_->HasSwitch(switches::kUrl)) {

View File

@ -35,6 +35,7 @@ const char kBackgroundColor[] = "background-color";
const char kEnableGPU[] = "enable-gpu"; const char kEnableGPU[] = "enable-gpu";
const char kFilterURL[] = "filter-url"; const char kFilterURL[] = "filter-url";
const char kUseViews[] = "use-views"; const char kUseViews[] = "use-views";
const char kUseNative[] = "use-native";
const char kHideFrame[] = "hide-frame"; const char kHideFrame[] = "hide-frame";
const char kHideControls[] = "hide-controls"; const char kHideControls[] = "hide-controls";
const char kHideOverlays[] = "hide-overlays"; const char kHideOverlays[] = "hide-overlays";

View File

@ -29,6 +29,7 @@ extern const char kBackgroundColor[];
extern const char kEnableGPU[]; extern const char kEnableGPU[];
extern const char kFilterURL[]; extern const char kFilterURL[];
extern const char kUseViews[]; extern const char kUseViews[];
extern const char kUseNative[];
extern const char kHideFrame[]; extern const char kHideFrame[];
extern const char kHideControls[]; extern const char kHideControls[];
extern const char kHideOverlays[]; extern const char kHideOverlays[];