blob: b8575319321ec5678fc8b8297c493efe00f7a7fe [file] [log] [blame]
// Copyright 2015 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 "ui/touch_selection/touch_handle_drawable_aura.h"
#include "services/ws/public/mojom/window_tree_constants.mojom.h"
#include "ui/aura/window.h"
#include "ui/aura/window_targeter.h"
#include "ui/aura_extra/image_window_delegate.h"
#include "ui/base/cursor/cursor.h"
#include "ui/base/hit_test.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/events/event.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/resources/grit/ui_resources.h"
namespace ui {
namespace {
// The distance by which a handle image is offset from the focal point (i.e.
// text baseline) downwards.
const int kSelectionHandleVerticalVisualOffset = 2;
// The padding around the selection handle image can be used to extend the
// handle window so that touch events near the selection handle image are
// targeted to the selection handle window.
const int kSelectionHandlePadding = 0;
// Epsilon value used to compare float values to zero.
const float kEpsilon = 1e-8f;
// Returns the appropriate handle image based on the handle orientation.
gfx::Image* GetHandleImage(TouchHandleOrientation orientation) {
int resource_id = 0;
switch (orientation) {
case TouchHandleOrientation::LEFT:
resource_id = IDR_TEXT_SELECTION_HANDLE_LEFT;
break;
case TouchHandleOrientation::CENTER:
resource_id = IDR_TEXT_SELECTION_HANDLE_CENTER;
break;
case TouchHandleOrientation::RIGHT:
resource_id = IDR_TEXT_SELECTION_HANDLE_RIGHT;
break;
case TouchHandleOrientation::UNDEFINED:
NOTREACHED() << "Invalid touch handle bound type.";
return nullptr;
};
return &ResourceBundle::GetSharedInstance().GetImageNamed(resource_id);
}
bool IsNearlyZero(float value) {
return std::abs(value) < kEpsilon;
}
} // namespace
TouchHandleDrawableAura::TouchHandleDrawableAura(aura::Window* parent)
: window_delegate_(new aura_extra::ImageWindowDelegate),
window_(new aura::Window(window_delegate_)),
enabled_(false),
alpha_(0),
orientation_(TouchHandleOrientation::UNDEFINED) {
window_delegate_->set_image_offset(gfx::Vector2d(kSelectionHandlePadding,
kSelectionHandlePadding));
window_delegate_->set_background_color(SK_ColorTRANSPARENT);
window_->SetTransparent(true);
window_->Init(LAYER_TEXTURED);
window_->set_owned_by_parent(false);
window_->SetEventTargetingPolicy(ws::mojom::EventTargetingPolicy::NONE);
parent->AddChild(window_.get());
}
TouchHandleDrawableAura::~TouchHandleDrawableAura() {
}
void TouchHandleDrawableAura::UpdateBounds() {
gfx::RectF new_bounds = relative_bounds_;
new_bounds.Offset(origin_position_.x(), origin_position_.y());
window_->SetBounds(gfx::ToEnclosingRect(new_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) {
// TODO(AviD): Implement adaptive handle orientation logic for Aura
DCHECK(!mirror_vertical);
DCHECK(!mirror_horizontal);
if (orientation_ == orientation)
return;
orientation_ = orientation;
gfx::Image* image = GetHandleImage(orientation);
window_delegate_->SetImage(*image);
// Calculate the relative bounds.
gfx::Size image_size = image->Size();
int window_width = image_size.width() + 2 * kSelectionHandlePadding;
int window_height = image_size.height() + 2 * kSelectionHandlePadding;
relative_bounds_ =
gfx::RectF(-kSelectionHandlePadding,
kSelectionHandleVerticalVisualOffset - kSelectionHandlePadding,
window_width, window_height);
gfx::Rect paint_bounds(relative_bounds_.x(), relative_bounds_.y(),
relative_bounds_.width(), relative_bounds_.height());
window_->SchedulePaintInRect(paint_bounds);
UpdateBounds();
}
void TouchHandleDrawableAura::SetOrigin(const gfx::PointF& position) {
origin_position_ = position;
UpdateBounds();
}
void TouchHandleDrawableAura::SetAlpha(float alpha) {
if (alpha == alpha_)
return;
alpha_ = alpha;
window_->layer()->SetOpacity(alpha_);
if (IsVisible())
window_->Show();
else
window_->Hide();
}
gfx::RectF TouchHandleDrawableAura::GetVisibleBounds() const {
gfx::RectF bounds(window_->bounds());
bounds.Inset(kSelectionHandlePadding,
kSelectionHandlePadding + kSelectionHandleVerticalVisualOffset,
kSelectionHandlePadding,
kSelectionHandlePadding);
return bounds;
}
float TouchHandleDrawableAura::GetDrawableHorizontalPaddingRatio() const {
// Aura does not have any transparent padding for its handle drawable.
return 0.0f;
}
} // namespace ui