cef/libcef/browser/views/view_impl.h

774 lines
28 KiB
C++

// Copyright 2016 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_VIEWS_VIEW_IMPL_H_
#define CEF_LIBCEF_BROWSER_VIEWS_VIEW_IMPL_H_
#pragma once
#include "base/memory/raw_ptr.h"
// CEF exposes views framework functionality via a hierarchy of CefView and
// related objects. While the goal is to accurately represent views framework
// capabilities there is not always a direct 1:1 mapping between the CEF
// implementation and the underlying views implementation. Certain liberties
// have been taken with the CEF API design to clarify the user experience.
//
// CEF implementation overview:
//
// CefView-derived classes (CefPanel, CefLabelButton, etc.) are implemented
// using a specialization of the CefViewImpl template. On Initialize() the
// CefViewImpl object creates an underlying views::View object via the
// CreateRootView() method. The views::View objects are implemented using a
// specialization of the CefViewView template. CefViewView extends the
// views::View-derived class and executes CefViewDelegate-derived callbacks by
// overriding views::View methods.
//
// Example 1: The CefBasicPanelImpl object created via CefPanel::CreatePanel()
// has the following object hierarchy:
//
// CefView => CefPanel =>
// CefViewImpl<views::View, CefPanel, CefPanelDelegate> =>
// CefPanelImpl<views::View, CefPanel, CefPanelDelegate> =>
// CefBasicPanelImpl.
//
// And the CefBasicPanelView object created via
// CefBasicPanelImpl::CreateRootView() has the following object hierarchy:
//
// views::View =>
// CefViewView<views::View, CefPanelDelegate> =>
// CefPanelView<views::View, CefPanelDelegate> =>
// CefBasicPanelView.
//
// Example 2: In some cases an intermediary type is required to meet CEF
// template requirements (e.g. CefViewView requires a no-argument constructor).
// The CefBasicLabelButtonImpl object created via
// CefLabelButton::CreateLabelButton() has the following object hierarchy:
//
// CefView => CefButton => CefLabelButton =>
// CefViewImpl<views::LabelButton, CefLabelButton, CefButtonDelegate> =>
// CefButtonImpl<views::LabelButton, CefLabelButton, CefButtonDelegate> =>
// CefLabelButtonImpl<views::LabelButton, CefLabelButton,
// CefButtonDelegate> =>
// CefBasicLabelButtonImpl
//
// And the CefBasicLabelButtonView object created via
// CefBasicLabelButtonImpl::CreateRootView() has the following object hierarchy:
//
// views::View => views::Button => views::LabelButton =>
// LabelButtonEx (used to implement the required no-argument constructor) =>
// CefViewView<LabelButtonEx, CefButtonDelegate> =>
// CefButtonView<LabelButtonEx, CefButtonDelegate> =>
// CefLabelButtonView<LabelButtonEx, CefButtonDelegate> =>
// CefBasicLabelButtonView.
//
//
// General design considerations:
//
// CefView classes are ref-counted whereas views::View classes are not. There
// is generally a 1:1 relationship between CefView and views::View objects.
// However, there may be intermediary views::View objects that are not exposed
// by the CEF layer. For example:
// - views::Widget creates views::RootView and views::ContentView child objects;
// - views::ScrollView creates views::ScrollView::Viewport child objects.
//
// The views::View class exposes methods that are not applicable for a subset of
// views implementations. For example:
// - Calling AddChildView() on a views::LabelButton is unexpected;
// - Adding a child to a views::ScrollView requires calling the SetContents()
// method instead of AddChildView().
// To avoid user confusion CEF introduces a CefPanel type that extends CefView
// and exposes common child management functionality. Types that allow
// arbitrary children extend CefPanel instead of CefView.
//
//
// Object ownership considerations:
//
// On initial creation the CefViewImpl object owns an underlying views::View
// object (created by overriding the CreateRootView() method) and the
// views::View object holds a non-ref-counted reference to the CefViewImpl
// object. If a CefViewImpl is destroyed (all refs released) then the underlying
// views::View object is deleted.
//
// When a views::View object is parented to another views::View (via
// CefPanel::AddChildView or similar) the ownership semantics change. The
// CefViewImpl swaps its owned reference for an unowned reference and the
// views::View gains a ref-counted reference to the CefViewImpl
// (CefView::IsAttached() now returns true).
//
// When a parent views::View is deleted all child views::Views in the view
// hierarchy are also deleted (see [1] for exceptions). When this happens the
// ref-counted CefViewImpl reference held by the views::View is released. The
// CefViewImpl is deleted if the client kept no references, otherwise the
// CefViewImpl is marked as invalid (CefView::IsValid() now returns false).
//
// When a views::View is removed from the view hierarchy (via
// CefPanel::RemoveChildView or similar) the initial ownership state is
// restored. The CefViewImpl regains ownership of the views::View and the
// ref-counted CefViewImpl reference held by the views::View is released.
//
// The relationship between CefViewImpl and views::View objects is managed using
// the view_util:: functions. Type conversion is facilitated using the As*()
// methods exposed by CefView-derived classes and the CefViewAdapter interface
// implemented by CefViewImpl. See view_util.[cc|h] for implementation details.
//
// Some other object types are also tied to views::View lifetime. For example,
// CefLayout and the underling views::LayoutManager objects are owned by the
// views::View that they're assigned to. This relationship is managed using the
// layout_util:: functions in layout_util.[cc|h].
//
// [1] By default views::View objects are deleted when the parent views::View
// object is deleted. However, this behavior can be changed either
// explicitly by calling set_owned_by_client() or implicitly by using
// interfaces like WidgetDelegateView (where WidgetDelegate is-a View, and
// the View is deleted when the native Widget is destroyed). CEF
// implementations that utilize this behavior must take special care with
// object ownership management.
//
//
// To implement a new CefView-derived class:
//
// 1. Choose a views class to expose.
// * We'll create a new CefFooBar class which exposes a hypothetical
// views::FooBar class. The views::FooBar class might look like this:
//
// File ui/views/foo_bar.h:
//
// namespace views {
//
// // FooBar view does a task on child views.
// class FooBar : public View {
// public:
// FooBar();
//
// // Do a task.
// void DoTask();
// // Called when the task is done.
// virtual void OnTaskDone();
//
// // View methods:
// void Layout() override; // Implements custom layout of child views.
// };
//
// } // namespace views
//
// 2. Determine the existing CefView-derived class that the new view class
// should extend.
// * Since in this example CefFooBar can have arbitrary child views we'll
// have it extend CefPanel.
//
// 3. Determine whether the new view class can use an existing delegate class
// (like CefPanelDelegate) or whether it needs its own delegate class.
// * Since CefFooBar has an OnTaskDone() callback we'll add a new
// CefFooBarDelegate class to expose it.
//
// 4. Create new header files in the cef/include/views/ directory.
// * Using existing files as a model, the resulting header contents might
// look like this:
//
// File cef/include/views/cef_foo_bar.h:
//
// ///
// // A FooBar view does a task on child views.
// ///
// /*--cef(source=library)--*/
// class CefFooBar : public CefPanel {
// public:
// ///
// // Create a new FooBar.
// ///
// /*--cef(optional_param=delegate)--*/
// static CefRefPtr<CefFooBar> CreateFooBar(
// CefRefPtr<CefFooBarDelegate> delegate);
//
// ///
// // Do a task.
// ///
// /*--cef()--*/
// virtual void DoTask() =0;
// };
//
// File cef/include/views/cef_foo_bar_delegate.h:
//
// ///
// // Implement this interface to handle FooBar events.
// ///
// /*--cef(source=client)--*/
// class CefFooBarDelegate : public CefPanelDelegate {
// public:
// ///
// // Called when the task is done.
// ///
// /*--cef()--*/
// virtual void OnTaskDone(CefRefPtr<CefFooBar> foobar) {}
// };
//
// 5. Add an As*() method to the CefView-derived class.
// * Using existing file contents as a model, make the following changes in
// cef/include/views/cef_panel.h:
// * Forward declare the CefFooBar class.
// * Add a new CefPanel::AsFooBar() method:
//
// ///
// // Returns this Panel as a FooBar or NULL if this is not a FooBar.
// ///
// /*--cef()--*/
// virtual CefRefPtr<CefFooBar> AsFooBar() =0;
//
// 6. Add a default implementation for the As*() method to the CefViewImpl-
// derived class.
// * Using existing file contents as a model, make the following changes in
// cef/libcef/browser/views/panel_impl.h:
// * Include "include/views/cef_foo_bar.h".
// * Add a default CefPanelImpl::AsFooBar() implementation:
//
// CefRefPtr<CefFooBar> AsFooBar() override { return nullptr; }
//
// 7. Update the CefViewAdapter::GetFor() method implementation to call the
// As*() method.
// * Using existing file contents as a model, make the following changes in
// cef/libcef/browser/views/view_adapter.cc:
// * Include "include/views/cef_foo_bar.h".
// * Call the AsFooBar() method to identify the adapter object:
//
// ... if (view->AsPanel()) {
// CefRefPtr<CefPanel> panel = view->AsPanel();
// if (panel->AsFooBar()) {
// adapter = static_cast<CefFooBarImpl*>(panel->AsFooBar().get());
// } else ...
// } else ...
//
// 8. Implement the CefViewView-derived class.
// * Using existing files as a model (for example, CefBasicPanelView), create
// a CefFooBarView class at cef/libcef/browser/views/foo_bar_view.[cc|h].
// This class:
// * Extends CefPanelView<views::FooBar, CefFooBarDelegate>.
// * Overrides the views::FooBar::OnTaskDone method to execute the
// CefFooBarDelegate::OnTaskDone callback:
//
// void CefFooBarView::OnTaskDone() {
// if (cef_delegate())
// cef_delegate()->OnTaskDone(GetCefFooBar());
// }
//
// 9. Implement the CefViewImpl-derived class.
// * Use existing files as a model (for example, CefBasicPanelImpl), create a
// CefFooBarImpl class at cef/libcef/browser/views/foo_bar_impl.[cc|h].
// This class:
// * Extends CefPanelImpl<views::FooBar, CefFooBar, CefFooBarDelegate>.
// * Implements AsFooBar() to return |this|.
// * Implements CreateRootView() to return a new CefFooBarView instance.
// * Implements the CefFooBar::DoTask() method to call
// views::FooBar::DoTask():
//
// void CefFooBarImpl::DoTask() {
// CEF_REQUIRE_VALID_RETURN_VOID();
// root_view()->DoTask();
// }
//
// 10. Implement the static method that creates the CefViewImpl-derived object
// instance.
// * Use existing files as a model (for example, CefBasicPanelImpl),
// implement the CefFooBar::CreateFooBar static method in
// cef/libcef/browser/views/foo_bar_impl.cc. This method:
// * Creates a new CefFooBarImpl object.
// * Calls Initialize() on the CefFooBarImpl object.
// * Returns the CefFooBarImpl object.
//
// 11. Add the new source files from #7 and #8 to the 'libcef_static' target in
// cef.gyp.
//
// 12. Update the CEF project files and build.
// * Run cef/tools/translator.[bat|sh] to update the translation layer for
// the new/modified classes. This tool needs to be run whenever header
// files in the cef/include/ directory are changed.
// * Run cef/cef_create_projects.[bat|sh] to update the Ninja build files.
// * Build CEF using Ninja.
//
#include "base/json/json_writer.h"
#include "base/logging.h"
#include "base/values.h"
#include "cef/include/views/cef_browser_view.h"
#include "cef/include/views/cef_button.h"
#include "cef/include/views/cef_panel.h"
#include "cef/include/views/cef_scroll_view.h"
#include "cef/include/views/cef_textfield.h"
#include "cef/include/views/cef_view.h"
#include "cef/libcef/browser/thread_util.h"
#include "cef/libcef/browser/views/view_adapter.h"
#include "cef/libcef/browser/views/view_util.h"
#include "ui/gfx/color_palette.h"
#include "ui/views/accessibility/view_accessibility.h"
#include "ui/views/background.h"
#include "ui/views/border.h"
#include "ui/views/view.h"
// Helpers for template boiler-plate.
#define CEF_VIEW_IMPL_T \
template <class ViewsViewClass, class CefViewClass, \
class CefViewDelegateClass>
#define CEF_VIEW_IMPL_A ViewsViewClass, CefViewClass, CefViewDelegateClass
#define CEF_VIEW_IMPL_D CefViewImpl<CEF_VIEW_IMPL_A>
// Base template for implementing CefView-derived classes. See above comments
// for a usage overview.
CEF_VIEW_IMPL_T class CefViewImpl : public CefViewAdapter, public CefViewClass {
public:
// Necessary for the CEF_REQUIRE_VALID_*() macros to compile.
using ParentClass = CEF_VIEW_IMPL_D;
// Returns the content views::View object that should be the target of most
// customization actions. May be the root view or a child of the root view.
virtual views::View* content_view() const { return root_view(); }
// Returns the CEF delegate as the derived type which may be nullptr.
CefViewDelegateClass* delegate() const { return delegate_.get(); }
// Returns the root views::View object owned by this CefView.
ViewsViewClass* root_view() const { return root_view_ref_; }
// CefViewAdapter methods:
views::View* Get() const override { return root_view(); }
std::unique_ptr<views::View> PassOwnership() override {
DCHECK(root_view_);
return std::move(root_view_);
}
void ResumeOwnership() override {
DCHECK(root_view_ref_);
DCHECK(!root_view_);
root_view_.reset(root_view_ref_);
}
void Detach() override {
if (root_view_) {
root_view_.reset();
}
root_view_ref_ = nullptr;
}
void GetDebugInfo(base::Value::Dict* info, bool include_children) override {
info->Set("type", GetDebugType());
info->Set("id", root_view()->GetID());
// Use GetBounds() because some subclasses (like CefWindowImpl) override it.
const CefRect& bounds = GetBounds();
base::Value::Dict bounds_value;
bounds_value.Set("x", bounds.x);
bounds_value.Set("y", bounds.y);
bounds_value.Set("width", bounds.width);
bounds_value.Set("height", bounds.height);
info->Set("bounds", std::move(bounds_value));
}
// CefView methods. When adding new As*() methods make sure to update
// CefViewAdapter::GetFor() in view_adapter.cc.
CefRefPtr<CefBrowserView> AsBrowserView() override { return nullptr; }
CefRefPtr<CefButton> AsButton() override { return nullptr; }
CefRefPtr<CefPanel> AsPanel() override { return nullptr; }
CefRefPtr<CefScrollView> AsScrollView() override { return nullptr; }
CefRefPtr<CefTextfield> AsTextfield() override { return nullptr; }
CefString GetTypeString() override;
CefString ToString(bool include_children) override;
bool IsValid() override;
bool IsAttached() override;
bool IsSame(CefRefPtr<CefView> that) override;
CefRefPtr<CefViewDelegate> GetDelegate() override;
CefRefPtr<CefWindow> GetWindow() override;
int GetID() override;
void SetID(int id) override;
int GetGroupID() override;
void SetGroupID(int group_id) override;
CefRefPtr<CefView> GetParentView() override;
CefRefPtr<CefView> GetViewForID(int id) override;
void SetBounds(const CefRect& bounds) override;
CefRect GetBounds() override;
CefRect GetBoundsInScreen() override;
void SetSize(const CefSize& size) override;
CefSize GetSize() override;
void SetPosition(const CefPoint& position) override;
CefPoint GetPosition() override;
void SetInsets(const CefInsets& insets) override;
CefInsets GetInsets() override;
CefSize GetPreferredSize() override;
void SizeToPreferredSize() override;
CefSize GetMinimumSize() override;
CefSize GetMaximumSize() override;
int GetHeightForWidth(int width) override;
void InvalidateLayout() override;
void SetVisible(bool visible) override;
bool IsVisible() override;
bool IsDrawn() override;
void SetEnabled(bool enabled) override;
bool IsEnabled() override;
void SetFocusable(bool focusable) override;
bool IsFocusable() override;
bool IsAccessibilityFocusable() override;
void RequestFocus() override;
void SetBackgroundColor(cef_color_t color) override;
cef_color_t GetBackgroundColor() override;
cef_color_t GetThemeColor(int color_id) override;
bool ConvertPointToScreen(CefPoint& point) override;
bool ConvertPointFromScreen(CefPoint& point) override;
bool ConvertPointToWindow(CefPoint& point) override;
bool ConvertPointFromWindow(CefPoint& point) override;
bool ConvertPointToView(CefRefPtr<CefView> view, CefPoint& point) override;
bool ConvertPointFromView(CefRefPtr<CefView> view, CefPoint& point) override;
protected:
// Create a new implementation object.
// Always call Initialize() after creation.
// |delegate| may be nullptr.
explicit CefViewImpl(CefRefPtr<CefViewDelegateClass> delegate)
: delegate_(delegate), root_view_ref_(nullptr) {}
// Initialize this object.
virtual void Initialize() {
root_view_.reset(CreateRootView());
DCHECK(root_view_.get());
root_view_ref_ = root_view_.get();
view_util::Register(this);
InitializeRootView();
}
// Create the root views::View object.
virtual ViewsViewClass* CreateRootView() = 0;
// Perform required initialization of the root_view() object created by
// CreateRootView(). Called after this object has been registered.
virtual void InitializeRootView() = 0;
private:
CefRefPtr<CefViewDelegateClass> delegate_;
// Owned reference to the views::View wrapped by this object. Will be nullptr
// before the View is created and after the View's ownership is transferred.
std::unique_ptr<ViewsViewClass> root_view_;
// Unowned reference to the views::View wrapped by this object. Will be
// nullptr before the View is created and after the View is destroyed.
raw_ptr<ViewsViewClass> root_view_ref_;
};
CEF_VIEW_IMPL_T CefString CEF_VIEW_IMPL_D::GetTypeString() {
CEF_REQUIRE_UIT_RETURN(CefString());
return GetDebugType();
}
CEF_VIEW_IMPL_T CefString CEF_VIEW_IMPL_D::ToString(bool include_children) {
CEF_REQUIRE_UIT_RETURN(CefString());
base::Value::Dict info;
if (IsValid()) {
GetDebugInfo(&info, include_children);
} else {
info.Set("type", GetDebugType());
}
std::string json_string;
base::JSONWriter::WriteWithOptions(info, 0, &json_string);
return json_string;
}
CEF_VIEW_IMPL_T bool CEF_VIEW_IMPL_D::IsValid() {
CEF_REQUIRE_UIT_RETURN(false);
return !!root_view_ref_;
}
CEF_VIEW_IMPL_T bool CEF_VIEW_IMPL_D::IsAttached() {
CEF_REQUIRE_UIT_RETURN(false);
return !root_view_.get();
}
CEF_VIEW_IMPL_T bool CEF_VIEW_IMPL_D::IsSame(CefRefPtr<CefView> that) {
CEF_REQUIRE_UIT_RETURN(false);
CefViewImpl* that_impl = static_cast<CefViewImpl*>(that.get());
if (!that_impl) {
return false;
}
return this == that_impl;
}
CEF_VIEW_IMPL_T CefRefPtr<CefViewDelegate> CEF_VIEW_IMPL_D::GetDelegate() {
CEF_REQUIRE_UIT_RETURN(nullptr);
return delegate();
}
CEF_VIEW_IMPL_T CefRefPtr<CefWindow> CEF_VIEW_IMPL_D::GetWindow() {
CEF_REQUIRE_UIT_RETURN(nullptr);
if (root_view()) {
return view_util::GetWindowFor(root_view()->GetWidget());
}
return nullptr;
}
CEF_VIEW_IMPL_T int CEF_VIEW_IMPL_D::GetID() {
CEF_REQUIRE_VALID_RETURN(0);
return root_view()->GetID();
}
CEF_VIEW_IMPL_T void CEF_VIEW_IMPL_D::SetID(int id) {
CEF_REQUIRE_VALID_RETURN_VOID();
root_view()->SetID(id);
}
CEF_VIEW_IMPL_T int CEF_VIEW_IMPL_D::GetGroupID() {
CEF_REQUIRE_VALID_RETURN(0);
return root_view()->GetGroup();
}
CEF_VIEW_IMPL_T void CEF_VIEW_IMPL_D::SetGroupID(int group_id) {
CEF_REQUIRE_VALID_RETURN_VOID();
if (root_view()->GetGroup() != -1) {
return;
}
root_view()->SetGroup(group_id);
}
CEF_VIEW_IMPL_T CefRefPtr<CefView> CEF_VIEW_IMPL_D::GetParentView() {
CEF_REQUIRE_VALID_RETURN(nullptr);
views::View* view = root_view()->parent();
if (!view) {
return nullptr;
}
return view_util::GetFor(view, true);
}
CEF_VIEW_IMPL_T CefRefPtr<CefView> CEF_VIEW_IMPL_D::GetViewForID(int id) {
CEF_REQUIRE_VALID_RETURN(nullptr);
views::View* view = root_view()->GetViewByID(id);
if (!view) {
return nullptr;
}
return view_util::GetFor(view, true);
}
CEF_VIEW_IMPL_T void CEF_VIEW_IMPL_D::SetBounds(const CefRect& bounds) {
CEF_REQUIRE_VALID_RETURN_VOID();
root_view()->SetBoundsRect(
gfx::Rect(bounds.x, bounds.y, bounds.width, bounds.height));
}
CEF_VIEW_IMPL_T CefRect CEF_VIEW_IMPL_D::GetBounds() {
CEF_REQUIRE_VALID_RETURN(CefRect());
const gfx::Rect& bounds = root_view()->bounds();
return CefRect(bounds.x(), bounds.y(), bounds.width(), bounds.height());
}
CEF_VIEW_IMPL_T CefRect CEF_VIEW_IMPL_D::GetBoundsInScreen() {
CEF_REQUIRE_VALID_RETURN(CefRect());
const gfx::Rect& bounds = root_view()->GetBoundsInScreen();
return CefRect(bounds.x(), bounds.y(), bounds.width(), bounds.height());
}
CEF_VIEW_IMPL_T void CEF_VIEW_IMPL_D::SetSize(const CefSize& size) {
CEF_REQUIRE_VALID_RETURN_VOID();
root_view()->SetSize(gfx::Size(size.width, size.height));
}
CEF_VIEW_IMPL_T CefSize CEF_VIEW_IMPL_D::GetSize() {
CEF_REQUIRE_VALID_RETURN(CefSize());
// Call GetBounds() since child classes may override it.
const CefRect& bounds = GetBounds();
return CefSize(bounds.width, bounds.height);
}
CEF_VIEW_IMPL_T void CEF_VIEW_IMPL_D::SetPosition(const CefPoint& position) {
CEF_REQUIRE_VALID_RETURN_VOID();
root_view()->SetPosition(gfx::Point(position.x, position.y));
}
CEF_VIEW_IMPL_T CefPoint CEF_VIEW_IMPL_D::GetPosition() {
CEF_REQUIRE_VALID_RETURN(CefPoint());
// Call GetBounds() since child classes may override it.
const CefRect& bounds = GetBounds();
return CefPoint(bounds.x, bounds.y);
}
CEF_VIEW_IMPL_T void CEF_VIEW_IMPL_D::SetInsets(const CefInsets& insets) {
CEF_REQUIRE_VALID_RETURN_VOID();
const gfx::Insets& gfx_insets =
gfx::Insets::TLBR(insets.top, insets.left, insets.bottom, insets.right);
root_view()->SetBorder(
gfx_insets.IsEmpty() ? nullptr : views::CreateEmptyBorder(gfx_insets));
}
CEF_VIEW_IMPL_T CefInsets CEF_VIEW_IMPL_D::GetInsets() {
CEF_REQUIRE_VALID_RETURN(CefInsets());
const auto insets = root_view()->GetInsets();
return CefInsets(insets.top(), insets.left(), insets.bottom(),
insets.right());
}
CEF_VIEW_IMPL_T CefSize CEF_VIEW_IMPL_D::GetPreferredSize() {
CEF_REQUIRE_VALID_RETURN(CefSize());
const gfx::Size& size = root_view()->GetPreferredSize();
return CefSize(size.width(), size.height());
}
CEF_VIEW_IMPL_T void CEF_VIEW_IMPL_D::SizeToPreferredSize() {
CEF_REQUIRE_VALID_RETURN_VOID();
root_view()->SizeToPreferredSize();
}
CEF_VIEW_IMPL_T CefSize CEF_VIEW_IMPL_D::GetMinimumSize() {
CEF_REQUIRE_VALID_RETURN(CefSize());
const gfx::Size& size = root_view()->GetMinimumSize();
return CefSize(size.width(), size.height());
}
CEF_VIEW_IMPL_T CefSize CEF_VIEW_IMPL_D::GetMaximumSize() {
CEF_REQUIRE_VALID_RETURN(CefSize());
const gfx::Size& size = root_view()->GetMaximumSize();
return CefSize(size.width(), size.height());
}
CEF_VIEW_IMPL_T int CEF_VIEW_IMPL_D::GetHeightForWidth(int width) {
CEF_REQUIRE_VALID_RETURN(0);
return root_view()->GetHeightForWidth(width);
}
CEF_VIEW_IMPL_T void CEF_VIEW_IMPL_D::InvalidateLayout() {
CEF_REQUIRE_VALID_RETURN_VOID();
root_view()->InvalidateLayout();
}
CEF_VIEW_IMPL_T void CEF_VIEW_IMPL_D::SetVisible(bool visible) {
CEF_REQUIRE_VALID_RETURN_VOID();
root_view()->SetVisible(visible);
}
CEF_VIEW_IMPL_T bool CEF_VIEW_IMPL_D::IsVisible() {
CEF_REQUIRE_VALID_RETURN(false);
return root_view()->GetVisible();
}
CEF_VIEW_IMPL_T bool CEF_VIEW_IMPL_D::IsDrawn() {
CEF_REQUIRE_VALID_RETURN(false);
return root_view()->IsDrawn();
}
CEF_VIEW_IMPL_T void CEF_VIEW_IMPL_D::SetEnabled(bool enabled) {
CEF_REQUIRE_VALID_RETURN_VOID();
root_view()->SetEnabled(enabled);
}
CEF_VIEW_IMPL_T bool CEF_VIEW_IMPL_D::IsEnabled() {
CEF_REQUIRE_VALID_RETURN(false);
return root_view()->GetEnabled();
}
CEF_VIEW_IMPL_T void CEF_VIEW_IMPL_D::SetFocusable(bool focusable) {
CEF_REQUIRE_VALID_RETURN_VOID();
root_view()->SetFocusBehavior(focusable ? views::View::FocusBehavior::ALWAYS
: views::View::FocusBehavior::NEVER);
}
CEF_VIEW_IMPL_T bool CEF_VIEW_IMPL_D::IsFocusable() {
CEF_REQUIRE_VALID_RETURN(false);
return root_view()->IsFocusable();
}
CEF_VIEW_IMPL_T bool CEF_VIEW_IMPL_D::IsAccessibilityFocusable() {
CEF_REQUIRE_VALID_RETURN(false);
return root_view()->GetViewAccessibility().IsAccessibilityFocusable();
}
CEF_VIEW_IMPL_T void CEF_VIEW_IMPL_D::RequestFocus() {
CEF_REQUIRE_VALID_RETURN_VOID();
root_view()->RequestFocus();
}
CEF_VIEW_IMPL_T void CEF_VIEW_IMPL_D::SetBackgroundColor(cef_color_t color) {
CEF_REQUIRE_VALID_RETURN_VOID();
root_view()->SetBackground(views::CreateSolidBackground(color));
}
CEF_VIEW_IMPL_T cef_color_t CEF_VIEW_IMPL_D::GetBackgroundColor() {
CEF_REQUIRE_VALID_RETURN(gfx::kPlaceholderColor);
// May return an empty value.
const auto& color =
view_util::GetBackgroundColor(root_view(), /*allow_transparency=*/true);
if (color) {
return *color;
}
return SK_ColorTRANSPARENT;
}
CEF_VIEW_IMPL_T cef_color_t CEF_VIEW_IMPL_D::GetThemeColor(int color_id) {
CEF_REQUIRE_VALID_RETURN(gfx::kPlaceholderColor);
return view_util::GetColor(root_view(), color_id);
}
CEF_VIEW_IMPL_T bool CEF_VIEW_IMPL_D::ConvertPointToScreen(CefPoint& point) {
CEF_REQUIRE_VALID_RETURN(false);
gfx::Point gfx_point = gfx::Point(point.x, point.y);
if (!view_util::ConvertPointToScreen(root_view(), &gfx_point, false)) {
return false;
}
point = CefPoint(gfx_point.x(), gfx_point.y());
return true;
}
CEF_VIEW_IMPL_T bool CEF_VIEW_IMPL_D::ConvertPointFromScreen(CefPoint& point) {
CEF_REQUIRE_VALID_RETURN(false);
gfx::Point gfx_point = gfx::Point(point.x, point.y);
if (!view_util::ConvertPointFromScreen(root_view(), &gfx_point, false)) {
return false;
}
point = CefPoint(gfx_point.x(), gfx_point.y());
return true;
}
CEF_VIEW_IMPL_T bool CEF_VIEW_IMPL_D::ConvertPointToWindow(CefPoint& point) {
CEF_REQUIRE_VALID_RETURN(false);
gfx::Point gfx_point = gfx::Point(point.x, point.y);
if (!view_util::ConvertPointToWindow(root_view(), &gfx_point)) {
return false;
}
point = CefPoint(gfx_point.x(), gfx_point.y());
return true;
}
CEF_VIEW_IMPL_T bool CEF_VIEW_IMPL_D::ConvertPointFromWindow(CefPoint& point) {
CEF_REQUIRE_VALID_RETURN(false);
gfx::Point gfx_point = gfx::Point(point.x, point.y);
if (!view_util::ConvertPointFromWindow(root_view(), &gfx_point)) {
return false;
}
point = CefPoint(gfx_point.x(), gfx_point.y());
return true;
}
CEF_VIEW_IMPL_T bool CEF_VIEW_IMPL_D::ConvertPointToView(
CefRefPtr<CefView> view,
CefPoint& point) {
CEF_REQUIRE_VALID_RETURN(false);
if (!root_view()->GetWidget()) {
return false;
}
views::View* target_view = view_util::GetFor(view);
if (!target_view || target_view->GetWidget() != root_view()->GetWidget()) {
return false;
}
gfx::Point gfx_point = gfx::Point(point.x, point.y);
views::View::ConvertPointToTarget(root_view(), target_view, &gfx_point);
point = CefPoint(gfx_point.x(), gfx_point.y());
return true;
}
CEF_VIEW_IMPL_T bool CEF_VIEW_IMPL_D::ConvertPointFromView(
CefRefPtr<CefView> view,
CefPoint& point) {
CEF_REQUIRE_VALID_RETURN(false);
if (!root_view()->GetWidget()) {
return false;
}
views::View* target_view = view_util::GetFor(view);
if (!target_view || target_view->GetWidget() != root_view()->GetWidget()) {
return false;
}
gfx::Point gfx_point = gfx::Point(point.x, point.y);
views::View::ConvertPointToTarget(target_view, root_view(), &gfx_point);
point = CefPoint(gfx_point.x(), gfx_point.y());
return true;
}
#endif // CEF_LIBCEF_BROWSER_VIEWS_VIEW_IMPL_H_