blob: c4a53b50b281283a576485a1e7478fb7e9e26941 [file] [log] [blame]
// Copyright 2018 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 "chrome/browser/ui/android/overlay/overlay_window_android.h"
#include "base/android/jni_android.h"
#include "base/memory/ptr_util.h"
#include "cc/layers/surface_layer.h"
#include "chrome/android/chrome_jni_headers/PictureInPictureActivity_jni.h"
#include "chrome/browser/android/tab_android.h"
#include "components/thin_webview/compositor_view.h"
#include "content/public/browser/overlay_window.h"
#include "content/public/browser/picture_in_picture_window_controller.h"
#include "ui/android/window_android_compositor.h"
// static
std::unique_ptr<content::OverlayWindow> content::OverlayWindow::Create(
PictureInPictureWindowController* controller) {
return std::make_unique<OverlayWindowAndroid>(controller);
}
OverlayWindowAndroid::OverlayWindowAndroid(
content::PictureInPictureWindowController* controller)
: window_android_(nullptr),
compositor_view_(nullptr),
surface_layer_(cc::SurfaceLayer::Create()),
bounds_(gfx::Rect(0, 0)),
controller_(controller) {
surface_layer_->SetIsDrawable(true);
surface_layer_->SetStretchContentToFillBounds(true);
surface_layer_->SetMayContainVideo(true);
surface_layer_->SetBackgroundColor(SK_ColorBLACK);
JNIEnv* env = base::android::AttachCurrentThread();
Java_PictureInPictureActivity_createActivity(
env, reinterpret_cast<intptr_t>(this),
TabAndroid::FromWebContents(controller_->GetWebContents())
->GetJavaObject());
}
OverlayWindowAndroid::~OverlayWindowAndroid() {
JNIEnv* env = base::android::AttachCurrentThread();
Java_PictureInPictureActivity_onWindowDestroyed(
env, reinterpret_cast<intptr_t>(this));
}
void OverlayWindowAndroid::OnActivityStart(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
const base::android::JavaParamRef<jobject>& jwindow_android) {
java_ref_ = JavaObjectWeakGlobalRef(env, obj);
window_android_ = ui::WindowAndroid::FromJavaWindowAndroid(jwindow_android);
window_android_->AddObserver(this);
if (video_size_.IsEmpty())
return;
Java_PictureInPictureActivity_updateVideoSize(
env, java_ref_.get(env), video_size_.width(), video_size_.height());
}
void OverlayWindowAndroid::OnAttachCompositor() {
window_android_->GetCompositor()->AddChildFrameSink(
surface_layer_->surface_id().frame_sink_id());
}
void OverlayWindowAndroid::OnDetachCompositor() {
window_android_->GetCompositor()->RemoveChildFrameSink(
surface_layer_->surface_id().frame_sink_id());
}
void OverlayWindowAndroid::OnActivityStopped() {
Destroy(nullptr);
}
void OverlayWindowAndroid::Destroy(JNIEnv* env) {
java_ref_.reset();
if (window_android_) {
window_android_->RemoveObserver(this);
window_android_ = nullptr;
}
controller_->CloseAndFocusInitiator();
controller_->OnWindowDestroyed();
}
void OverlayWindowAndroid::Play(JNIEnv* env) {
DCHECK(!controller_->IsPlayerActive());
controller_->TogglePlayPause();
}
void OverlayWindowAndroid::CompositorViewCreated(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& compositor_view) {
compositor_view_ =
thin_webview::android::CompositorView::FromJavaObject(compositor_view);
DCHECK(compositor_view_);
compositor_view_->SetRootLayer(surface_layer_);
}
void OverlayWindowAndroid::OnViewSizeChanged(JNIEnv* env,
jint width,
jint height) {
gfx::Size content_size(width, height);
if (bounds_.size() == content_size)
return;
bounds_.set_size(content_size);
surface_layer_->SetBounds(content_size);
controller_->UpdateLayerBounds();
}
void OverlayWindowAndroid::Close() {
if (java_ref_.is_uninitialized())
return;
DCHECK(window_android_);
window_android_->RemoveObserver(this);
window_android_ = nullptr;
JNIEnv* env = base::android::AttachCurrentThread();
Java_PictureInPictureActivity_close(env, java_ref_.get(env));
controller_->OnWindowDestroyed();
}
void OverlayWindowAndroid::Hide() {
Close();
}
bool OverlayWindowAndroid::IsActive() {
return true;
}
bool OverlayWindowAndroid::IsVisible() {
return true;
}
bool OverlayWindowAndroid::IsAlwaysOnTop() {
return true;
}
gfx::Rect OverlayWindowAndroid::GetBounds() {
return bounds_;
}
void OverlayWindowAndroid::UpdateVideoSize(const gfx::Size& natural_size) {
if (java_ref_.is_uninitialized()) {
video_size_ = natural_size;
return;
}
JNIEnv* env = base::android::AttachCurrentThread();
Java_PictureInPictureActivity_updateVideoSize(
env, java_ref_.get(env), natural_size.width(), natural_size.height());
}
void OverlayWindowAndroid::SetSurfaceId(const viz::SurfaceId& surface_id) {
const viz::SurfaceId& old_surface_id = surface_layer_->surface_id().is_valid()
? surface_layer_->surface_id()
: surface_id;
surface_layer_->SetSurfaceId(surface_id,
cc::DeadlinePolicy::UseDefaultDeadline());
if (!window_android_ || !window_android_->GetCompositor() ||
old_surface_id == surface_id) {
return;
}
window_android_->GetCompositor()->RemoveChildFrameSink(
old_surface_id.frame_sink_id());
window_android_->GetCompositor()->AddChildFrameSink(
surface_id.frame_sink_id());
}
cc::Layer* OverlayWindowAndroid::GetLayerForTesting() {
return nullptr;
}