diff options
Diffstat (limited to 'libcef/browser/views/view_impl.h')
-rw-r--r-- | libcef/browser/views/view_impl.h | 760 |
1 files changed, 760 insertions, 0 deletions
diff --git a/libcef/browser/views/view_impl.h b/libcef/browser/views/view_impl.h new file mode 100644 index 00000000..d9e105d8 --- /dev/null +++ b/libcef/browser/views/view_impl.h @@ -0,0 +1,760 @@ +// 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 + +// 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 "include/views/cef_browser_view.h" +#include "include/views/cef_button.h" +#include "include/views/cef_panel.h" +#include "include/views/cef_scroll_view.h" +#include "include/views/cef_textfield.h" +#include "include/views/cef_view.h" + +#include "libcef/browser/thread_util.h" +#include "libcef/browser/views/view_adapter.h" +#include "libcef/browser/views/view_util.h" + +#include "base/json/json_writer.h" +#include "base/logging.h" +#include "base/values.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; + 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. + 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()->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(); + content_view()->SetBackground(views::CreateSolidBackground(color)); +} + +CEF_VIEW_IMPL_T cef_color_t CEF_VIEW_IMPL_D::GetBackgroundColor() { + CEF_REQUIRE_VALID_RETURN(0U); + return content_view()->background()->get_color(); +} + +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_ |