blob: a4335283fd818fbaf53ea03bc63fcea284978651 [file] [log] [blame]
// Copyright 2019 The Chromium 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 "weblayer/browser/browser_controls_container_view.h"
#include "base/android/jni_string.h"
#include "base/bind.h"
#include "base/feature_list.h"
#include "cc/layers/ui_resource_layer.h"
#include "content/public/browser/android/compositor.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/browser_controls_state.h"
#include "ui/android/resources/resource.h"
#include "ui/android/resources/resource_manager.h"
#include "ui/android/view_android.h"
#include "weblayer/browser/content_view_render_view.h"
#include "weblayer/browser/java/jni/BrowserControlsContainerView_jni.h"
#include "weblayer/browser/weblayer_features.h"
using base::android::AttachCurrentThread;
using base::android::JavaParamRef;
namespace weblayer {
BrowserControlsContainerView::BrowserControlsContainerView(
const JavaParamRef<jobject>& java_browser_controls_container_view,
ContentViewRenderView* content_view_render_view,
bool is_top)
: java_browser_controls_container_view_(
java_browser_controls_container_view),
content_view_render_view_(content_view_render_view),
is_top_(is_top) {
DCHECK(content_view_render_view_);
if (!is_top_) {
content_view_render_view_->SetHeightChangedListener(
base::BindRepeating(&BrowserControlsContainerView::ContentHeightChanged,
base::Unretained(this)));
}
}
BrowserControlsContainerView::~BrowserControlsContainerView() {
if (!is_top_) {
content_view_render_view_->SetHeightChangedListener(
base::RepeatingClosure());
}
}
int BrowserControlsContainerView::GetControlsHeight() {
return controls_layer_ ? controls_layer_->bounds().height() : 0;
}
int BrowserControlsContainerView::GetMinHeight() {
return Java_BrowserControlsContainerView_getMinHeight(
AttachCurrentThread(), java_browser_controls_container_view_);
}
bool BrowserControlsContainerView::OnlyExpandControlsAtPageTop() {
return Java_BrowserControlsContainerView_onlyExpandControlsAtPageTop(
AttachCurrentThread(), java_browser_controls_container_view_);
}
bool BrowserControlsContainerView::ShouldAnimateBrowserControlsHeightChanges() {
return Java_BrowserControlsContainerView_shouldAnimateBrowserControlsHeightChanges(
AttachCurrentThread(), java_browser_controls_container_view_);
}
int BrowserControlsContainerView::GetContentHeightDelta() {
if (!controls_layer_ || !web_contents())
return 0;
if (is_top_)
return web_contents()->GetNativeView()->GetLayer()->position().y();
return content_view_render_view_->height() - controls_layer_->position().y();
}
bool BrowserControlsContainerView::IsFullyVisible() const {
// At this time this is only needed for top-controls.
DCHECK(is_top_);
return controls_layer_ && controls_layer_->position().y() == 0;
}
void BrowserControlsContainerView::CreateControlsLayer(
JNIEnv* env,
int id) {
controls_resource_id_ = id;
controls_layer_ = cc::UIResourceLayer::Create();
// Real size is sent in SetControlsSize().
controls_layer_->SetBounds(gfx::Size(1, 1));
controls_layer_->SetPosition(gfx::PointF(0, 0));
controls_layer_->SetElementId(cc::ElementId(controls_layer_->id()));
controls_layer_->SetHitTestable(false);
controls_layer_->SetIsDrawable(true);
content_view_render_view_->root_container_layer()->AddChild(controls_layer_);
UpdateControlsResource(env);
}
void BrowserControlsContainerView::DeleteBrowserControlsContainerView(
JNIEnv* env) {
delete this;
}
void BrowserControlsContainerView::DeleteControlsLayer(JNIEnv* env) {
controls_layer_.reset();
}
void BrowserControlsContainerView::SetTopControlsOffset(JNIEnv* env,
int content_offset_y) {
DCHECK(is_top_);
// |controls_layer_| may not be created if the controls view has 0 height.
if (controls_layer_)
controls_layer_->SetPosition(gfx::PointF(0, GetControlsOffset()));
if (web_contents()) {
web_contents()->GetNativeView()->GetLayer()->SetPosition(
gfx::PointF(0, content_offset_y));
}
}
void BrowserControlsContainerView::SetBottomControlsOffset(JNIEnv* env) {
DCHECK(!is_top_);
DoSetBottomControlsOffset();
}
void BrowserControlsContainerView::SetControlsSize(
JNIEnv* env,
int width,
int height) {
DCHECK(controls_layer_);
controls_layer_->SetBounds(gfx::Size(width, height));
// It's assumed the caller handles triggering SynchronizeVisualProperties()
// being called (this is done in java code).
}
void BrowserControlsContainerView::UpdateControlsResource(JNIEnv* env) {
DCHECK(controls_layer_);
ui::ResourceManager& resource_manager =
content_view_render_view_->compositor()->GetResourceManager();
ui::Resource* controls_resource = resource_manager.GetResource(
ui::ANDROID_RESOURCE_TYPE_DYNAMIC, controls_resource_id_);
DCHECK(controls_resource);
controls_layer_->SetUIResourceId(controls_resource->ui_resource()->id());
}
void BrowserControlsContainerView::SetWebContents(
JNIEnv* env,
const JavaParamRef<jobject>& web_contents) {
Observe(content::WebContents::FromJavaWebContents(web_contents));
}
void BrowserControlsContainerView::DidToggleFullscreenModeForTab(
bool entered_fullscreen,
bool will_cause_resize) {
TRACE_EVENT0(
"weblayer",
"Java_BrowserControlsContainerView_didToggleFullscreenModeForTab");
Java_BrowserControlsContainerView_didToggleFullscreenModeForTab(
AttachCurrentThread(), java_browser_controls_container_view_,
entered_fullscreen);
}
void BrowserControlsContainerView::ContentHeightChanged() {
DCHECK(!is_top_);
DoSetBottomControlsOffset();
}
int BrowserControlsContainerView::GetControlsOffset() {
return Java_BrowserControlsContainerView_getControlsOffset(
AttachCurrentThread(), java_browser_controls_container_view_);
}
void BrowserControlsContainerView::DoSetBottomControlsOffset() {
DCHECK(!is_top_);
// |controls_layer_| may not be created if the controls view has 0 height.
if (!controls_layer_)
return;
controls_layer_->SetPosition(
gfx::PointF(0, content_view_render_view_->height() - GetControlsHeight() +
GetControlsOffset()));
}
static jlong
JNI_BrowserControlsContainerView_CreateBrowserControlsContainerView(
JNIEnv* env,
const JavaParamRef<jobject>& java_browser_controls_container_view,
jlong native_content_view_render_view,
jboolean is_top) {
return reinterpret_cast<jlong>(new BrowserControlsContainerView(
java_browser_controls_container_view,
reinterpret_cast<ContentViewRenderView*>(native_content_view_render_view),
is_top));
}
static jboolean JNI_BrowserControlsContainerView_ShouldDelayVisibilityChange(
JNIEnv* env) {
return !base::FeatureList::IsEnabled(kImmediatelyHideBrowserControlsForTest);
}
} // namespace weblayer