blob: 4b9a4a146ec03851614c45bfdb3efd075f121e2d [file] [log] [blame]
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/glic/widget/glic_inactive_side_panel_ui.h"
#include "base/notimplemented.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "chrome/browser/glic/widget/glic_side_panel_ui.h"
#include "chrome/browser/ui/tabs/public/tab_features.h"
#include "chrome/browser/ui/views/side_panel/glic/glic_side_panel_coordinator.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkImage.h"
#include "third_party/skia/include/core/SkPaint.h"
#include "third_party/skia/include/effects/SkImageFilters.h"
#include "ui/base/models/image_model.h"
#include "ui/gfx/image/image_skia_operations.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
#include "ui/views/view.h"
namespace glic {
namespace {
constexpr float kBlurRadius = 10.0f;
gfx::ImageSkia BlurImage(gfx::ImageSkia image) {
SkBitmap blurred_bitmap;
const SkBitmap* bitmap = image.bitmap();
if (bitmap) {
SkImageInfo info = bitmap->info();
blurred_bitmap.allocPixels(info);
SkCanvas canvas(blurred_bitmap);
SkPaint paint;
paint.setImageFilter(
SkImageFilters::Blur(kBlurRadius, kBlurRadius, nullptr));
canvas.drawImage(SkImages::RasterFromBitmap(*bitmap), 0, 0,
SkSamplingOptions(), &paint);
}
return gfx::ImageSkia::CreateFrom1xBitmap(blurred_bitmap);
}
} // namespace
// static
std::unique_ptr<GlicInactiveSidePanelUi> GlicInactiveSidePanelUi::From(
const GlicSidePanelUi& active_ui,
base::WeakPtr<tabs::TabInterface> tab) {
// Using `new` to access a private constructor.
auto inactive_side_panel = base::WrapUnique(new GlicInactiveSidePanelUi(tab));
inactive_side_panel->VisibilityChanged(/*visible=*/true);
// Capture screenshot asynchronously and update the inactive panel.
active_ui.TakeScreenshot(
base::BindOnce(&GlicInactiveSidePanelUi::OnScreenshotCaptured,
inactive_side_panel->weak_ptr_factory_.GetWeakPtr()));
return inactive_side_panel;
}
GlicInactiveSidePanelUi::GlicInactiveSidePanelUi(
base::WeakPtr<tabs::TabInterface> tab)
: tab_(tab) {
if (!tab_ || !tab_->GetTabFeatures()) {
return;
}
auto* glic_side_panel_coordinator =
tab_->GetTabFeatures()->glic_side_panel_coordinator();
coordinator_observation_.Observe(glic_side_panel_coordinator);
glic_side_panel_coordinator->SetContentsView(CreateView(tab_));
}
std::unique_ptr<views::View> GlicInactiveSidePanelUi::CreateView(
base::WeakPtr<tabs::TabInterface> tab) {
auto image_view = std::make_unique<views::ImageView>();
image_view->SetHorizontalAlignment(views::ImageView::Alignment::kCenter);
image_view->SetVerticalAlignment(views::ImageView::Alignment::kCenter);
image_view_tracker_.SetView(image_view.get()); // Track the image view
return image_view;
}
GlicInactiveSidePanelUi::~GlicInactiveSidePanelUi() = default;
Host::EmbedderDelegate* GlicInactiveSidePanelUi::GetHostEmbedderDelegate() {
// This should not be called for an inactive embedder. The delegate is managed
// by the GlicInstanceImpl.
NOTREACHED();
}
bool GlicInactiveSidePanelUi::IsShowing() const {
return is_showing_;
}
void GlicInactiveSidePanelUi::Show() {
NOTIMPLEMENTED();
}
void GlicInactiveSidePanelUi::Close() {
// TODO: implement close.
NOTIMPLEMENTED();
}
std::unique_ptr<GlicUiEmbedder>
GlicInactiveSidePanelUi::CreateInactiveEmbedder() const {
NOTREACHED() << "The embedder is already inactive.";
}
void GlicInactiveSidePanelUi::VisibilityChanged(bool visible) {
is_showing_ = visible;
}
void GlicInactiveSidePanelUi::OnScreenshotCaptured(gfx::Image screenshot) {
screenshot_ = screenshot.AsImageSkia();
UpdateImageView();
}
void GlicInactiveSidePanelUi::UpdateImageView() {
if (!image_view_tracker_.view() || screenshot_.isNull()) {
return;
}
// Post task to a background thread to blur the image.
base::ThreadPool::PostTaskAndReplyWithResult(
FROM_HERE, {base::TaskPriority::USER_VISIBLE, base::MayBlock()},
base::BindOnce(&BlurImage, screenshot_),
base::BindOnce(&GlicInactiveSidePanelUi::OnImageBlurred,
weak_ptr_factory_.GetWeakPtr()));
}
void GlicInactiveSidePanelUi::OnImageBlurred(gfx::ImageSkia blurred_image) {
if (!image_view_tracker_.view()) {
return;
}
auto* image_view = static_cast<views::ImageView*>(image_view_tracker_.view());
image_view->SetImage(ui::ImageModel::FromImageSkia(blurred_image));
image_view->SetImageSize(screenshot_.size());
}
} // namespace glic