Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(340)

Unified Diff: ui/touch_selection/touch_handle_drawable_aura.cc

Issue 698253004: Reland: Implement Aura side of unified touch text selection for contents (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebased after addition of touch_handle_orientation file Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: ui/touch_selection/touch_handle_drawable_aura.cc
diff --git a/ui/touch_selection/touch_handle_drawable_aura.cc b/ui/touch_selection/touch_handle_drawable_aura.cc
new file mode 100644
index 0000000000000000000000000000000000000000..8f56d5c1ac8b52cbaba957bc272fef3b4400fa2c
--- /dev/null
+++ b/ui/touch_selection/touch_handle_drawable_aura.cc
@@ -0,0 +1,187 @@
+// 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 "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/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;
+ 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;
+ default:
sadrul 2015/03/05 12:37:03 Remove default, explicitly list UNDEFINED
mohsen 2015/03/06 23:10:08 Done.
+ NOTREACHED() << "Invalid touch handle bound type.";
+ return nullptr;
+ };
+ return &ResourceBundle::GetSharedInstance().GetImageNamed(resource_id);
+}
+
+bool IsNearlyZero(float value) {
+ return std::abs(value) < kEpsilon;
+}
+
+// A window targeter for touch handles that will let every touch event pass
+// through handles to the underlying window.
sadrul 2015/03/05 12:37:03 Can you set Window::set_ignore_events() instead?
mfomitchev 2015/03/05 16:07:54 So this is a bit awkward because at this point we
sadrul 2015/03/05 16:56:22 We shouldn't do this in a roundabout way to fit in
mfomitchev 2015/03/05 18:03:24 Yes, that's what I meant. Thus we'd have to switch
mohsen 2015/03/06 23:10:08 This is how ui::TouchSelectionController is implem
+class TouchHandleDrawableAuraTargeter : public aura::WindowTargeter {
+ protected:
+ bool EventLocationInsideBounds(EventTarget* target,
+ const LocatedEvent& event) const override;
+};
+
+bool TouchHandleDrawableAuraTargeter::EventLocationInsideBounds(
+ EventTarget* target,
+ const LocatedEvent& event) const {
+ return false;
+}
+
+}
+
+TouchHandleDrawableAura::TouchHandleDrawableAura(aura::Window* parent)
+ : window_(new aura::Window(this)),
+ enabled_(false),
+ alpha_(0),
+ orientation_(TouchHandleOrientation::UNDEFINED) {
+ set_image_offset(gfx::Vector2d(kSelectionHandlePadding,
+ kSelectionHandlePadding));
+ set_background_color(SK_ColorTRANSPARENT);
+ window_->SetTransparent(true);
+ window_->Init(aura::WINDOW_LAYER_TEXTURED);
+ window_->set_owned_by_parent(false);
+ window_->SetEventTargeter(
+ scoped_ptr<EventTargeter>(new TouchHandleDrawableAuraTargeter));
+ parent->AddChild(window_.get());
+}
+
+TouchHandleDrawableAura::~TouchHandleDrawableAura() {
+}
+
+// static
+gfx::Size TouchHandleDrawableAura::GetMaxHandleImageSize() {
+ gfx::Size max_size(GetHandleImage(TouchHandleOrientation::CENTER)->Size());
+ max_size.SetToMax(GetHandleImage(TouchHandleOrientation::LEFT)->Size());
+ max_size.SetToMax(GetHandleImage(TouchHandleOrientation::RIGHT)->Size());
+ return max_size;
+}
+
+void TouchHandleDrawableAura::OnWindowDestroyed(aura::Window* window) {
+ // Overriding ImageWindowDelegate's implementation, which calls |delete this|
+ // when the window is destroyed - in our case the delegate owns the window,
+ // and not vice versa.
+}
+
+void TouchHandleDrawableAura::UpdateBounds() {
+ gfx::RectF new_bounds = relative_bounds_;
+ new_bounds.Offset(focal_position_.x(), focal_position_.y());
+ window_->SetBounds(gfx::ToNearestRect(new_bounds));
+}
+
+void TouchHandleDrawableAura::SetEnabled(bool enabled) {
+ if (enabled == enabled_)
+ return;
+
+ enabled_ = enabled;
+ bool visible = !IsNearlyZero(alpha_);
+ if (enabled_ && visible)
+ window_->Show();
+ else
+ window_->Hide();
+}
+
+void TouchHandleDrawableAura::SetOrientation(
+ TouchHandleOrientation orientation) {
+ if (orientation_ == orientation)
+ return;
+ orientation_ = orientation;
+ gfx::Image* image = GetHandleImage(orientation);
+ 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;
+ // Due to the shape of the handle images, the window is aligned differently to
+ // the selection bound depending on the orientation.
+ int window_left = 0;
+ switch (orientation) {
+ case TouchHandleOrientation::LEFT:
+ window_left = -image_size.width() - kSelectionHandlePadding;
+ break;
+ case TouchHandleOrientation::RIGHT:
+ window_left = -kSelectionHandlePadding;
+ break;
+ case TouchHandleOrientation::CENTER:
+ window_left = -window_width / 2;
+ break;
+ default:
sadrul 2015/03/05 12:37:03 case UNDEFINED: instead of default:
mohsen 2015/03/06 23:10:08 Done.
+ NOTREACHED() << "Undefined handle orientation.";
+ break;
+ };
+ relative_bounds_ = gfx::RectF(
+ window_left,
+ kSelectionHandleVerticalVisualOffset - kSelectionHandlePadding,
+ window_width,
+ window_height);
+ UpdateBounds();
+}
+
+void TouchHandleDrawableAura::SetAlpha(float alpha) {
+ if (alpha == alpha_)
+ return;
+
+ alpha_ = alpha;
+ window_->layer()->SetOpacity(alpha_);
+ bool visible = !IsNearlyZero(alpha_);
+ if (enabled_ && visible)
+ window_->Show();
+ else
+ window_->Hide();
+}
+
+void TouchHandleDrawableAura::SetFocus(const gfx::PointF& position) {
+ focal_position_ = position;
+ UpdateBounds();
+}
+
+gfx::RectF TouchHandleDrawableAura::GetVisibleBounds() const {
+ gfx::RectF bounds(window_->bounds());
+ bounds.Inset(kSelectionHandlePadding,
+ kSelectionHandlePadding + kSelectionHandleVerticalVisualOffset,
+ kSelectionHandlePadding,
+ kSelectionHandlePadding);
+ return bounds;
+}
+
+} // namespace ui

Powered by Google App Engine
This is Rietveld 408576698