1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
|
// 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_window_resize_animation.h"
#include "base/task/sequenced_task_runner.h"
#include "build/buildflag.h"
#include "chrome/browser/glic/widget/glic_view.h"
#include "chrome/browser/glic/widget/glic_widget.h"
#include "chrome/browser/glic/widget/glic_window_animator.h"
#include "chrome/browser/glic/widget/glic_window_controller.h"
#include "ui/gfx/animation/tween.h"
#include "ui/views/background.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"
#if BUILDFLAG(IS_WIN)
#include "chrome/common/chrome_features.h"
#include "ui/base/win/hwnd_metrics.h"
#include "ui/views/win/hwnd_util.h"
#endif
#if BUILDFLAG(IS_MAC)
#include "ui/accelerated_widget_mac/ca_transaction_observer.h"
#endif
namespace glic {
namespace {
void RunCallbackList(std::unique_ptr<base::OnceClosureList> callbacks) {
callbacks->Notify();
}
} // namespace
GlicWindowResizeAnimation::GlicWindowResizeAnimation(
GlicWindowController* window_controller,
GlicWindowAnimator* window_animator,
const gfx::Rect& target_bounds,
base::TimeDelta duration,
base::OnceClosure destruction_callback)
: gfx::LinearAnimation(duration, kDefaultFrameRate, this),
window_controller_(window_controller),
glic_window_animator_(window_animator),
initial_bounds_(
window_controller_->GetGlicWidget()->GetWindowBoundsInScreen()),
new_bounds_(target_bounds),
destruction_callbacks_(std::make_unique<base::OnceClosureList>()) {
// Using AddUnsafe() because the callback list is run on a task posted on
// destruction of `this`, so we aren't able to hold CallbackSubscriptions
// here.
destruction_callbacks_->AddUnsafe(std::move(destruction_callback));
// TODO(crbug.com/389238233): CompositorAnimationRunner does not appear to
// be fully functional.
// Use a CompositorAnimationRunner for smoother vsync driven resize animation.
// auto container = base::MakeRefCounted<gfx::AnimationContainer>();
// container->SetAnimationRunner(
// std::make_unique<views::CompositorAnimationRunner>(widget));
// SetContainer(container.get());
Start();
}
GlicWindowResizeAnimation::~GlicWindowResizeAnimation() {
if (!destruction_callbacks_->empty()) {
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(&RunCallbackList, std::move(destruction_callbacks_)));
}
}
void GlicWindowResizeAnimation::AnimateToState(double state) {
if (window_controller_->IsDragging()) {
return;
}
gfx::Rect bounds_to_animate = gfx::Tween::RectValueBetween(
gfx::Tween::CalculateValue(gfx::Tween::FAST_OUT_SLOW_IN_3, state),
initial_bounds_, new_bounds_);
GlicWidget* glic_widget = window_controller_->GetGlicWidget();
if (window_controller_->IsAttached()) {
// If the widget is attached, resize normally.
glic_widget->SetBounds(bounds_to_animate);
} else {
// If the widget is detached, make sure the bounds don't go out-of-screen.
glic_widget->SetBoundsConstrained(bounds_to_animate);
}
duration_left_ = (1 - GetCurrentValue()) * duration();
}
void GlicWindowResizeAnimation::AnimationEnded(const Animation* animation) {
// Destroys `this`.
glic_window_animator_->ResizeFinished();
}
void GlicWindowResizeAnimation::UpdateTargetBounds(
const gfx::Rect& target_bounds,
base::OnceClosure callback) {
new_bounds_ = target_bounds;
destruction_callbacks_->AddUnsafe(std::move(callback));
}
} // namespace glic
|