cefclient: views: Add overlay BrowserView demo (see #3790)
Adds new `--show-overlay-browser` command-line flag that creates an overlay containing an Alloy-style BrowserView. The main BrowserView may be Chrome- (default) or Alloy-style (add `--use-alloy-style`). This overlay will only be added to standalone (non-popup) windows. Popups triggered via the overlay will receive standard Alloy-style handling in cefclient (e.g. Views-hosted window). Add `--use-default-popup` for default popup handling.
This commit is contained in:
parent
e23bf31bf4
commit
1bc1ca15d5
|
@ -288,6 +288,8 @@
|
|||
'tests/cefclient/browser/urlrequest_test.h',
|
||||
'tests/cefclient/browser/views_menu_bar.cc',
|
||||
'tests/cefclient/browser/views_menu_bar.h',
|
||||
'tests/cefclient/browser/views_overlay_browser.cc',
|
||||
'tests/cefclient/browser/views_overlay_browser.h',
|
||||
'tests/cefclient/browser/views_overlay_controls.cc',
|
||||
'tests/cefclient/browser/views_overlay_controls.h',
|
||||
'tests/cefclient/browser/views_style.cc',
|
||||
|
|
|
@ -280,8 +280,8 @@ void CefBrowserViewImpl::AddedToWidget() {
|
|||
CefWidget* cef_widget = CefWidget::GetForWidget(widget);
|
||||
DCHECK(cef_widget);
|
||||
|
||||
if (!browser_) {
|
||||
if (cef_widget->IsAlloyStyle() && !is_alloy_style_) {
|
||||
if (!browser_ && !is_alloy_style_) {
|
||||
if (cef_widget->IsAlloyStyle()) {
|
||||
LOG(ERROR) << "Cannot add Chrome style BrowserView to Alloy style Window";
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -4,8 +4,16 @@
|
|||
|
||||
#include "tests/cefclient/browser/default_client_handler.h"
|
||||
|
||||
#include "tests/cefclient/browser/main_context.h"
|
||||
#include "tests/cefclient/browser/root_window_manager.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
DefaultClientHandler::DefaultClientHandler(std::optional<bool> use_alloy_style)
|
||||
: use_alloy_style_(
|
||||
use_alloy_style.value_or(MainContext::Get()->UseAlloyStyleGlobal())) {
|
||||
}
|
||||
|
||||
// static
|
||||
CefRefPtr<DefaultClientHandler> DefaultClientHandler::GetForClient(
|
||||
CefRefPtr<CefClient> client) {
|
||||
|
@ -16,4 +24,39 @@ CefRefPtr<DefaultClientHandler> DefaultClientHandler::GetForClient(
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
bool DefaultClientHandler::OnBeforePopup(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
const CefString& target_url,
|
||||
const CefString& target_frame_name,
|
||||
CefLifeSpanHandler::WindowOpenDisposition target_disposition,
|
||||
bool user_gesture,
|
||||
const CefPopupFeatures& popupFeatures,
|
||||
CefWindowInfo& windowInfo,
|
||||
CefRefPtr<CefClient>& client,
|
||||
CefBrowserSettings& settings,
|
||||
CefRefPtr<CefDictionaryValue>& extra_info,
|
||||
bool* no_javascript_access) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
if (target_disposition == CEF_WOD_NEW_PICTURE_IN_PICTURE) {
|
||||
// Use default handling for document picture-in-picture popups.
|
||||
client = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Used to configure default values.
|
||||
RootWindowConfig config(/*command_line=*/nullptr);
|
||||
|
||||
// Potentially create a new RootWindow for the popup browser that will be
|
||||
// created asynchronously.
|
||||
MainContext::Get()->GetRootWindowManager()->CreateRootWindowAsPopup(
|
||||
config.use_views, use_alloy_style_, config.with_controls,
|
||||
/*is_osr=*/false, /*is_devtools=*/false, popupFeatures, windowInfo,
|
||||
client, settings);
|
||||
|
||||
// Allow popup creation.
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
#define CEF_TESTS_CEFCLIENT_BROWSER_DEFAULT_CLIENT_HANDLER_H_
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include "tests/cefclient/browser/base_client_handler.h"
|
||||
|
||||
namespace client {
|
||||
|
@ -14,18 +16,37 @@ namespace client {
|
|||
// style only.
|
||||
class DefaultClientHandler : public BaseClientHandler {
|
||||
public:
|
||||
DefaultClientHandler() = default;
|
||||
// If |use_alloy_style| is nullopt the global default will be used.
|
||||
explicit DefaultClientHandler(
|
||||
std::optional<bool> use_alloy_style = std::nullopt);
|
||||
|
||||
// Returns the DefaultClientHandler for |client|, or nullptr if |client| is
|
||||
// not a DefaultClientHandler.
|
||||
static CefRefPtr<DefaultClientHandler> GetForClient(
|
||||
CefRefPtr<CefClient> client);
|
||||
|
||||
protected:
|
||||
bool OnBeforePopup(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
const CefString& target_url,
|
||||
const CefString& target_frame_name,
|
||||
CefLifeSpanHandler::WindowOpenDisposition target_disposition,
|
||||
bool user_gesture,
|
||||
const CefPopupFeatures& popupFeatures,
|
||||
CefWindowInfo& windowInfo,
|
||||
CefRefPtr<CefClient>& client,
|
||||
CefBrowserSettings& settings,
|
||||
CefRefPtr<CefDictionaryValue>& extra_info,
|
||||
bool* no_javascript_access) override;
|
||||
|
||||
private:
|
||||
// Used to determine the object type.
|
||||
virtual const void* GetTypeKey() const override { return &kTypeKey; }
|
||||
static constexpr int kTypeKey = 0;
|
||||
|
||||
const bool use_alloy_style_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(DefaultClientHandler);
|
||||
DISALLOW_COPY_AND_ASSIGN(DefaultClientHandler);
|
||||
};
|
||||
|
|
|
@ -134,8 +134,11 @@ scoped_refptr<RootWindow> RootWindowManager::CreateRootWindowAsPopup(
|
|||
|
||||
if (MainContext::Get()->UseDefaultPopup() || (is_devtools && !use_views)) {
|
||||
// Use default window creation for the popup. A new |client| instance is
|
||||
// still required by cefclient architecture.
|
||||
client = new DefaultClientHandler();
|
||||
// required by cefclient architecture if the type is not already
|
||||
// DefaultClientHandler.
|
||||
if (!DefaultClientHandler::GetForClient(client)) {
|
||||
client = new DefaultClientHandler(use_alloy_style);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
// Copyright (c) 2024 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 "tests/cefclient/browser/views_overlay_browser.h"
|
||||
|
||||
#include "include/views/cef_window.h"
|
||||
#include "tests/cefclient/browser/views_window.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
ViewsOverlayBrowser::ViewsOverlayBrowser(ViewsWindow* owner_window)
|
||||
: owner_window_(owner_window) {}
|
||||
|
||||
void ViewsOverlayBrowser::Initialize(
|
||||
CefRefPtr<CefWindow> window,
|
||||
CefRefPtr<CefClient> client,
|
||||
const std::string& url,
|
||||
const CefBrowserSettings& settings,
|
||||
CefRefPtr<CefRequestContext> request_context) {
|
||||
CHECK(!window_);
|
||||
window_ = window;
|
||||
CHECK(window_);
|
||||
|
||||
browser_view_ = CefBrowserView::CreateBrowserView(
|
||||
client, url, settings, nullptr, request_context, this);
|
||||
CHECK(browser_view_);
|
||||
|
||||
controller_ = window_->AddOverlayView(browser_view_, CEF_DOCKING_MODE_CUSTOM,
|
||||
/*can_activate=*/true);
|
||||
CHECK(controller_);
|
||||
}
|
||||
|
||||
void ViewsOverlayBrowser::Destroy() {
|
||||
window_ = nullptr;
|
||||
browser_view_ = nullptr;
|
||||
controller_->Destroy();
|
||||
controller_ = nullptr;
|
||||
}
|
||||
|
||||
void ViewsOverlayBrowser::UpdateBounds(CefInsets insets) {
|
||||
if (!controller_) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Update location bar size, position and visibility.
|
||||
const auto window_bounds = window_->GetBounds();
|
||||
|
||||
// Client coordinates with insets.
|
||||
CefRect bounds;
|
||||
bounds.x = insets.left;
|
||||
bounds.width = window_bounds.width - insets.left - insets.right;
|
||||
bounds.y = insets.top;
|
||||
bounds.height = window_bounds.height - insets.top - insets.bottom;
|
||||
|
||||
const auto min_size = browser_view_->GetMinimumSize();
|
||||
if (bounds.width < min_size.width || bounds.height < min_size.height) {
|
||||
// Not enough space.
|
||||
controller_->SetVisible(false);
|
||||
} else {
|
||||
controller_->SetSize(CefSize(bounds.width, bounds.height));
|
||||
controller_->SetBounds(bounds);
|
||||
controller_->SetVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
void ViewsOverlayBrowser::UpdateDraggableRegions(
|
||||
std::vector<CefDraggableRegion>& window_regions) {
|
||||
if (controller_ && controller_->IsVisible()) {
|
||||
window_regions.emplace_back(controller_->GetBounds(),
|
||||
/*draggable=*/false);
|
||||
}
|
||||
}
|
||||
|
||||
CefSize ViewsOverlayBrowser::GetMinimumSize(CefRefPtr<CefView> view) {
|
||||
return CefSize(200, 200);
|
||||
}
|
||||
|
||||
CefRefPtr<CefBrowserViewDelegate>
|
||||
ViewsOverlayBrowser::GetDelegateForPopupBrowserView(
|
||||
CefRefPtr<CefBrowserView> browser_view,
|
||||
const CefBrowserSettings& settings,
|
||||
CefRefPtr<CefClient> client,
|
||||
bool is_devtools) {
|
||||
return owner_window_->GetDelegateForPopupBrowserView(browser_view, settings,
|
||||
client, is_devtools);
|
||||
}
|
||||
|
||||
bool ViewsOverlayBrowser::OnPopupBrowserViewCreated(
|
||||
CefRefPtr<CefBrowserView> browser_view,
|
||||
CefRefPtr<CefBrowserView> popup_browser_view,
|
||||
bool is_devtools) {
|
||||
return owner_window_->OnPopupBrowserViewCreated(
|
||||
browser_view, popup_browser_view, is_devtools);
|
||||
}
|
||||
|
||||
cef_runtime_style_t ViewsOverlayBrowser::GetBrowserRuntimeStyle() {
|
||||
// Overlay browser view must always be Alloy style.
|
||||
return CEF_RUNTIME_STYLE_ALLOY;
|
||||
}
|
||||
|
||||
} // namespace client
|
|
@ -0,0 +1,63 @@
|
|||
// Copyright (c) 2024 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_TESTS_CEFCLIENT_BROWSER_VIEWS_OVERLAY_BROWSER_H_
|
||||
#define CEF_TESTS_CEFCLIENT_BROWSER_VIEWS_OVERLAY_BROWSER_H_
|
||||
#pragma once
|
||||
|
||||
#include "include/views/cef_browser_view.h"
|
||||
#include "include/views/cef_browser_view_delegate.h"
|
||||
#include "include/views/cef_overlay_controller.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
class ViewsWindow;
|
||||
|
||||
// Implements a browser view that receives absolute positioning on top of the
|
||||
// main browser view. All methods must be called on the browser process UI
|
||||
// thread.
|
||||
class ViewsOverlayBrowser : public CefBrowserViewDelegate {
|
||||
public:
|
||||
explicit ViewsOverlayBrowser(ViewsWindow* owner_window);
|
||||
|
||||
void Initialize(CefRefPtr<CefWindow> window,
|
||||
CefRefPtr<CefClient> client,
|
||||
const std::string& url,
|
||||
const CefBrowserSettings& settings,
|
||||
CefRefPtr<CefRequestContext> request_context);
|
||||
void Destroy();
|
||||
|
||||
// Update browser bounds.
|
||||
void UpdateBounds(CefInsets insets);
|
||||
|
||||
// Exclude all regions obscured by overlays.
|
||||
void UpdateDraggableRegions(std::vector<CefDraggableRegion>& window_regions);
|
||||
|
||||
private:
|
||||
// CefViewDelegate methods:
|
||||
CefSize GetMinimumSize(CefRefPtr<CefView> view) override;
|
||||
|
||||
// CefBrowserViewDelegate methods:
|
||||
CefRefPtr<CefBrowserViewDelegate> GetDelegateForPopupBrowserView(
|
||||
CefRefPtr<CefBrowserView> browser_view,
|
||||
const CefBrowserSettings& settings,
|
||||
CefRefPtr<CefClient> client,
|
||||
bool is_devtools) override;
|
||||
bool OnPopupBrowserViewCreated(CefRefPtr<CefBrowserView> browser_view,
|
||||
CefRefPtr<CefBrowserView> popup_browser_view,
|
||||
bool is_devtools) override;
|
||||
cef_runtime_style_t GetBrowserRuntimeStyle() override;
|
||||
|
||||
ViewsWindow* const owner_window_;
|
||||
CefRefPtr<CefWindow> window_;
|
||||
CefRefPtr<CefBrowserView> browser_view_;
|
||||
CefRefPtr<CefOverlayController> controller_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(ViewsOverlayBrowser);
|
||||
DISALLOW_COPY_AND_ASSIGN(ViewsOverlayBrowser);
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_BROWSER_VIEWS_OVERLAY_BROWSER_H_
|
|
@ -12,6 +12,7 @@
|
|||
#include "include/cef_i18n_util.h"
|
||||
#include "include/views/cef_box_layout.h"
|
||||
#include "include/wrapper/cef_helpers.h"
|
||||
#include "tests/cefclient/browser/default_client_handler.h"
|
||||
#include "tests/cefclient/browser/main_context.h"
|
||||
#include "tests/cefclient/browser/resource.h"
|
||||
#include "tests/cefclient/browser/views_style.h"
|
||||
|
@ -146,6 +147,14 @@ CefRefPtr<ViewsWindow> ViewsWindow::Create(
|
|||
CefRefPtr<ViewsWindow> views_window =
|
||||
new ViewsWindow(type, delegate, nullptr, command_line);
|
||||
|
||||
// Only create an overlay browser for a primary window.
|
||||
if (command_line->HasSwitch(switches::kShowOverlayBrowser)) {
|
||||
views_window->with_overlay_browser_ = true;
|
||||
views_window->initial_url_ = url;
|
||||
views_window->settings_ = settings;
|
||||
views_window->request_context_ = request_context;
|
||||
}
|
||||
|
||||
const auto expected_browser_runtime_style = views_window->use_alloy_style_
|
||||
? CEF_RUNTIME_STYLE_ALLOY
|
||||
: CEF_RUNTIME_STYLE_CHROME;
|
||||
|
@ -359,6 +368,11 @@ void ViewsWindow::SetDraggableRegions(
|
|||
overlay_controls_->UpdateDraggableRegions(window_regions);
|
||||
}
|
||||
|
||||
if (overlay_browser_) {
|
||||
// Exclude all regions obscured by overlays.
|
||||
overlay_browser_->UpdateDraggableRegions(window_regions);
|
||||
}
|
||||
|
||||
window_->SetDraggableRegions(window_regions);
|
||||
}
|
||||
|
||||
|
@ -1001,6 +1015,19 @@ void ViewsWindow::OnWindowChanged(CefRefPtr<CefView> view, bool added) {
|
|||
CreateLocationBar(),
|
||||
chrome_toolbar_type_ != CEF_CTT_NONE);
|
||||
}
|
||||
|
||||
if (with_overlay_browser_) {
|
||||
overlay_browser_ = new ViewsOverlayBrowser(this);
|
||||
|
||||
// Use default behavior for the overlay browser. A new |client| instance
|
||||
// is still required by cefclient architecture.
|
||||
CefRefPtr<CefClient> client =
|
||||
new DefaultClientHandler(/*use_alloy_style=*/true);
|
||||
|
||||
overlay_browser_->Initialize(window_, client, initial_url_, settings_,
|
||||
request_context_);
|
||||
request_context_ = nullptr;
|
||||
}
|
||||
} else {
|
||||
// Remove any controls that may include the Chrome toolbar before removing
|
||||
// the BrowserView.
|
||||
|
@ -1015,6 +1042,10 @@ void ViewsWindow::OnWindowChanged(CefRefPtr<CefView> view, bool added) {
|
|||
location_bar_ = nullptr;
|
||||
}
|
||||
}
|
||||
if (overlay_browser_) {
|
||||
overlay_browser_->Destroy();
|
||||
overlay_browser_ = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1028,6 +1059,12 @@ void ViewsWindow::OnLayoutChanged(CefRefPtr<CefView> view,
|
|||
if (overlay_controls_) {
|
||||
overlay_controls_->UpdateControls();
|
||||
}
|
||||
|
||||
if (overlay_browser_) {
|
||||
// TODO: Consider modifying insets based on toolbar visibility.
|
||||
CefInsets window_insets(200, 200, 200, 200);
|
||||
overlay_browser_->UpdateBounds(window_insets);
|
||||
}
|
||||
}
|
||||
|
||||
void ViewsWindow::OnThemeChanged(CefRefPtr<CefView> view) {
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "tests/cefclient/browser/image_cache.h"
|
||||
#include "tests/cefclient/browser/root_window.h"
|
||||
#include "tests/cefclient/browser/views_menu_bar.h"
|
||||
#include "tests/cefclient/browser/views_overlay_browser.h"
|
||||
#include "tests/cefclient/browser/views_overlay_controls.h"
|
||||
|
||||
namespace client {
|
||||
|
@ -280,6 +281,13 @@ class ViewsWindow : public CefBrowserViewDelegate,
|
|||
|
||||
CefRefPtr<ViewsOverlayControls> overlay_controls_;
|
||||
|
||||
// Overlay browser view state.
|
||||
bool with_overlay_browser_ = false;
|
||||
std::string initial_url_;
|
||||
CefBrowserSettings settings_;
|
||||
CefRefPtr<CefRequestContext> request_context_;
|
||||
CefRefPtr<ViewsOverlayBrowser> overlay_browser_;
|
||||
|
||||
std::optional<float> default_titlebar_height_;
|
||||
std::optional<float> override_titlebar_height_;
|
||||
|
||||
|
|
|
@ -58,5 +58,6 @@ const char kHideWindowOnClose[] = "hide-window-on-close";
|
|||
const char kAcceptsFirstMouse[] = "accepts-first-mouse";
|
||||
const char kUseAlloyStyle[] = "use-alloy-style";
|
||||
const char kUseChromeStyleWindow[] = "use-chrome-style-window";
|
||||
const char kShowOverlayBrowser[] = "show-overlay-browser";
|
||||
|
||||
} // namespace client::switches
|
||||
|
|
|
@ -52,6 +52,7 @@ extern const char kHideWindowOnClose[];
|
|||
extern const char kAcceptsFirstMouse[];
|
||||
extern const char kUseAlloyStyle[];
|
||||
extern const char kUseChromeStyleWindow[];
|
||||
extern const char kShowOverlayBrowser[];
|
||||
|
||||
} // namespace client::switches
|
||||
|
||||
|
|
Loading…
Reference in New Issue