#ifndef CEF_LIBCEF_BROWSER_VIEWS_VIEW_VIEW_H_
#define CEF_LIBCEF_BROWSER_VIEWS_VIEW_VIEW_H_
#pragma once
#include "include/views/cef_view.h"
#include "include/views/cef_view_delegate.h"
#include "libcef/browser/thread_util.h"
#include "libcef/browser/views/view_util.h"
#include "base/logging.h"
#include "ui/views/accessibility/accessibility_paint_checks.h"
#include "ui/views/background.h"
#include "ui/views/view.h"
#define CEF_VIEW_VIEW_T \
template <class ViewsViewClass, class CefViewDelegateClass>
#define CEF_VIEW_VIEW_A ViewsViewClass, CefViewDelegateClass
#define CEF_VIEW_VIEW_D CefViewView<CEF_VIEW_VIEW_A>
CEF_VIEW_VIEW_T class CefViewView : public ViewsViewClass {
public:
using ParentClass = ViewsViewClass;
template <typename... Args>
explicit CefViewView(CefViewDelegateClass* cef_delegate, Args... args)
: ParentClass(args...), cef_delegate_(cef_delegate) {}
virtual void Initialize() {
ParentClass::SetBackground(
views::CreateSolidBackground(view_util::kDefaultBackgroundColor));
ParentClass::SetProperty(views::kSkipAccessibilityPaintChecks, true);
}
CefViewDelegateClass* cef_delegate() const { return cef_delegate_; }
CefRefPtr<CefView> GetCefView() const {
CefRefPtr<CefView> view = view_util::GetFor(this, false);
DCHECK(view);
return view;
}
gfx::Size CalculatePreferredSize() const override;
gfx::Size GetMinimumSize() const override;
gfx::Size GetMaximumSize() const override;
int GetHeightForWidth(int w) const override;
void Layout() override;
void ViewHierarchyChanged(
const views::ViewHierarchyChangedDetails& details) override;
void AddedToWidget() override;
void RemovedFromWidget() override;
void OnFocus() override;
void OnBlur() override;
virtual bool HasMinimumSize() const { return false; }
private:
void NotifyChildViewChanged(
const views::ViewHierarchyChangedDetails& details);
void NotifyParentViewChanged(
const views::ViewHierarchyChangedDetails& details);
CefViewDelegateClass* const cef_delegate_;
};
CEF_VIEW_VIEW_T gfx::Size CEF_VIEW_VIEW_D::CalculatePreferredSize() const {
gfx::Size result;
if (cef_delegate()) {
CefSize cef_size = cef_delegate()->GetPreferredSize(GetCefView());
if (!cef_size.IsEmpty())
result = gfx::Size(cef_size.width, cef_size.height);
}
if (result.IsEmpty())
result = ParentClass::CalculatePreferredSize();
if (result.IsEmpty()) {
result = ParentClass::size();
}
return result;
}
CEF_VIEW_VIEW_T gfx::Size CEF_VIEW_VIEW_D::GetMinimumSize() const {
gfx::Size result;
if (cef_delegate()) {
CefSize cef_size = cef_delegate()->GetMinimumSize(GetCefView());
if (!cef_size.IsEmpty())
result = gfx::Size(cef_size.width, cef_size.height);
}
if (result.IsEmpty() && HasMinimumSize())
result = ParentClass::GetMinimumSize();
return result;
}
CEF_VIEW_VIEW_T gfx::Size CEF_VIEW_VIEW_D::GetMaximumSize() const {
gfx::Size result;
if (cef_delegate()) {
CefSize cef_size = cef_delegate()->GetMaximumSize(GetCefView());
if (!cef_size.IsEmpty())
result = gfx::Size(cef_size.width, cef_size.height);
}
if (result.IsEmpty())
result = ParentClass::GetMaximumSize();
return result;
}
CEF_VIEW_VIEW_T int CEF_VIEW_VIEW_D::GetHeightForWidth(int w) const {
int result = 0;
if (cef_delegate())
result = cef_delegate()->GetHeightForWidth(GetCefView(), w);
if (result == 0)
result = ParentClass::GetHeightForWidth(w);
if (result == 0) {
result = ParentClass::GetPreferredSize().height();
}
return result;
}
CEF_VIEW_VIEW_T void CEF_VIEW_VIEW_D::Layout() {
ParentClass::Layout();
if (ParentClass::size().IsEmpty())
ParentClass::SizeToPreferredSize();
if (cef_delegate()) {
const auto new_bounds = ParentClass::bounds();
CefRect new_rect(new_bounds.x(), new_bounds.y(), new_bounds.width(),
new_bounds.height());
cef_delegate()->OnLayoutChanged(GetCefView(), new_rect);
}
}
CEF_VIEW_VIEW_T void CEF_VIEW_VIEW_D::ViewHierarchyChanged(
const views::ViewHierarchyChangedDetails& details) {
NotifyChildViewChanged(details);
NotifyParentViewChanged(details);
ParentClass::ViewHierarchyChanged(details);
}
CEF_VIEW_VIEW_T void CEF_VIEW_VIEW_D::AddedToWidget() {
ParentClass::AddedToWidget();
if (cef_delegate())
cef_delegate()->OnWindowChanged(GetCefView(), true);
}
CEF_VIEW_VIEW_T void CEF_VIEW_VIEW_D::RemovedFromWidget() {
if (cef_delegate())
cef_delegate()->OnWindowChanged(GetCefView(), false);
ParentClass::RemovedFromWidget();
}
CEF_VIEW_VIEW_T void CEF_VIEW_VIEW_D::OnFocus() {
if (cef_delegate())
cef_delegate()->OnFocus(GetCefView());
ParentClass::OnFocus();
}
CEF_VIEW_VIEW_T void CEF_VIEW_VIEW_D::OnBlur() {
if (cef_delegate())
cef_delegate()->OnBlur(GetCefView());
ParentClass::OnBlur();
}
CEF_VIEW_VIEW_T void CEF_VIEW_VIEW_D::NotifyChildViewChanged(
const views::ViewHierarchyChangedDetails& details) {
if (!cef_delegate())
return;
if (details.parent != this || details.child->parent() != this)
return;
CefRefPtr<CefView> child = view_util::GetFor(details.child, false);
if (child) {
cef_delegate()->OnChildViewChanged(GetCefView(), details.is_add, child);
}
}
CEF_VIEW_VIEW_T void CEF_VIEW_VIEW_D::NotifyParentViewChanged(
const views::ViewHierarchyChangedDetails& details) {
if (!cef_delegate())
return;
if (details.child != this || details.parent != ParentClass::parent())
return;
CefRefPtr<CefView> parent = view_util::GetFor(details.parent, true);
if (parent) {
cef_delegate()->OnParentViewChanged(GetCefView(), details.is_add, parent);
}
}
#endif