#include "ui/touch_selection/touch_handle_drawable_aura.h"
#include "ui/aura/window.h"
#include "ui/aura/window_targeter.h"
#include "ui/base/cursor/cursor.h"
#include "ui/base/hit_test.h"
#include "ui/base/models/image_model.h"
#include "ui/color/color_id.h"
#include "ui/color/color_provider.h"
#include "ui/color/color_provider_manager.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/paint_recorder.h"
#include "ui/events/event.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/geometry/outsets_f.h"
#include "ui/gfx/geometry/point_conversions.h"
#include "ui/gfx/image/image.h"
#include "ui/native_theme/native_theme.h"
#include "ui/native_theme/native_theme_observer.h"
#include "ui/touch_selection//vector_icons/vector_icons.h"
namespace ui {
namespace {
constexpr int kSelectionHandlePadding = 6;
constexpr float kSelectionHandleMaxOpacity = 0.8f;
constexpr float kEpsilon = 1e-8f;
ImageModel GetHandleVectorIcon(TouchHandleOrientation orientation) {
const gfx::VectorIcon* icon = nullptr;
switch (orientation) {
case TouchHandleOrientation::LEFT:
icon = &kTextSelectionHandleLeftIcon;
break;
case TouchHandleOrientation::CENTER:
icon = &kTextSelectionHandleCenterIcon;
break;
case TouchHandleOrientation::RIGHT:
icon = &kTextSelectionHandleRightIcon;
break;
case TouchHandleOrientation::UNDEFINED:
NOTREACHED() << "Invalid touch handle bound type.";
}
return ImageModel::FromVectorIcon(*icon,
kColorSysPrimary);
}
bool IsNearlyZero(float value) {
return std::abs(value) < kEpsilon;
}
}
TouchHandleDrawableAura::TouchHandleDrawableAura(aura::Window* parent)
: window_(std::make_unique<aura::Window>(nullptr)),
enabled_(false),
alpha_(0),
orientation_(TouchHandleOrientation::UNDEFINED) {
window_->Init(LAYER_TEXTURED);
window_->SetTransparent(true);
window_->set_owned_by_parent(false);
window_->SetEventTargetingPolicy(aura::EventTargetingPolicy::kNone);
window_->layer()->set_delegate(this);
parent->AddChild(window_.get());
theme_observation_.Observe(NativeTheme::GetInstanceForNativeUi());
}
TouchHandleDrawableAura::~TouchHandleDrawableAura() = default;
void TouchHandleDrawableAura::UpdateWindowBounds() {
gfx::Rect window_bounds(gfx::ToRoundedPoint(targetable_origin_),
handle_image_.Size());
window_bounds.Offset(kSelectionHandlePadding, 0);
window_->SetBounds(window_bounds);
}
bool TouchHandleDrawableAura::IsVisible() const {
return enabled_ && !IsNearlyZero(alpha_);
}
void TouchHandleDrawableAura::SetEnabled(bool enabled) {
if (enabled == enabled_)
return;
enabled_ = enabled;
if (IsVisible())
window_->Show();
else
window_->Hide();
}
void TouchHandleDrawableAura::SetOrientation(TouchHandleOrientation orientation,
bool mirror_vertical,
bool mirror_horizontal) {
DCHECK(!mirror_vertical);
DCHECK(!mirror_horizontal);
if (orientation_ == orientation)
return;
orientation_ = orientation;
handle_image_ = GetHandleVectorIcon(orientation);
UpdateWindowBounds();
window_->SchedulePaintInRect(gfx::Rect(window_->bounds().size()));
}
void TouchHandleDrawableAura::SetOrigin(const gfx::PointF& position) {
targetable_origin_ = position;
UpdateWindowBounds();
}
void TouchHandleDrawableAura::SetAlpha(float alpha) {
if (alpha == alpha_)
return;
alpha_ = alpha;
window_->layer()->SetOpacity(alpha_ * kSelectionHandleMaxOpacity);
if (IsVisible())
window_->Show();
else
window_->Hide();
}
gfx::RectF TouchHandleDrawableAura::GetVisibleBounds() const {
gfx::RectF targetable_bounds(window_->bounds());
targetable_bounds.Outset(gfx::OutsetsF::TLBR(0, kSelectionHandlePadding,
kSelectionHandlePadding,
kSelectionHandlePadding));
return targetable_bounds;
}
float TouchHandleDrawableAura::GetDrawableHorizontalPaddingRatio() const {
return kSelectionHandlePadding /
(window_->bounds().width() + 2.0f * kSelectionHandlePadding);
}
void TouchHandleDrawableAura::OnPaintLayer(const PaintContext& context) {
PaintRecorder recorder(context, window_->bounds().size());
if (!handle_image_.IsEmpty()) {
recorder.canvas()->DrawImageInt(
handle_image_.Rasterize(ColorProviderManager::Get().GetColorProviderFor(
NativeTheme::GetInstanceForNativeUi()->GetColorProviderKey(
nullptr))),
0, 0);
}
}
void TouchHandleDrawableAura::OnNativeThemeUpdated(
NativeTheme* observed_theme) {
window_->SchedulePaintInRect(gfx::Rect(window_->bounds().size()));
}
#if BUILDFLAG(ARKWEB_CLIPBOARD)
void TouchHandleDrawableAura::SetEdge(const gfx::PointF& top,
const gfx::PointF& bottom) {}
#endif
}