diff options
9 files changed, 80 insertions, 43 deletions
diff --git a/content/browser/android/composited_touch_handle_drawable.cc b/content/browser/android/composited_touch_handle_drawable.cc index ff734a1..27fd671 100644 --- a/content/browser/android/composited_touch_handle_drawable.cc +++ b/content/browser/android/composited_touch_handle_drawable.cc @@ -139,22 +139,18 @@ void CompositedTouchHandleDrawable::SetFocus(const gfx::PointF& position) { layer_->SetPosition(focal_position_ - focal_offset_from_origin_); } -bool CompositedTouchHandleDrawable::IntersectsWith( - const gfx::RectF& rect) const { - return BoundingRect().Intersects(gfx::ScaleRect(rect, dpi_scale_)); +gfx::RectF CompositedTouchHandleDrawable::GetVisibleBounds() const { + return gfx::ScaleRect(gfx::RectF(layer_->position().x(), + layer_->position().y(), + layer_->bounds().width(), + layer_->bounds().height()), + 1.f / dpi_scale_); } void CompositedTouchHandleDrawable::Detach() { layer_->RemoveFromParent(); } -gfx::RectF CompositedTouchHandleDrawable::BoundingRect() const { - return gfx::RectF(layer_->position().x(), - layer_->position().y(), - layer_->bounds().width(), - layer_->bounds().height()); -} - // static bool CompositedTouchHandleDrawable::RegisterHandleViewResources(JNIEnv* env) { return RegisterNativesImpl(env); diff --git a/content/browser/android/composited_touch_handle_drawable.h b/content/browser/android/composited_touch_handle_drawable.h index 3f31d77..63370f7 100644 --- a/content/browser/android/composited_touch_handle_drawable.h +++ b/content/browser/android/composited_touch_handle_drawable.h @@ -25,13 +25,12 @@ class CompositedTouchHandleDrawable : public ui::TouchHandleDrawable { virtual void SetOrientation(ui::TouchHandleOrientation orientation) override; virtual void SetAlpha(float alpha) override; virtual void SetFocus(const gfx::PointF& position) override; - virtual bool IntersectsWith(const gfx::RectF& rect) const override; + virtual gfx::RectF GetVisibleBounds() const override; static bool RegisterHandleViewResources(JNIEnv* env); private: void Detach(); - gfx::RectF BoundingRect() const; const float dpi_scale_; ui::TouchHandleOrientation orientation_; diff --git a/content/browser/android/popup_touch_handle_drawable.cc b/content/browser/android/popup_touch_handle_drawable.cc index 42b7d7a..0ab3935 100644 --- a/content/browser/android/popup_touch_handle_drawable.cc +++ b/content/browser/android/popup_touch_handle_drawable.cc @@ -64,15 +64,14 @@ void PopupTouchHandleDrawable::SetFocus(const gfx::PointF& position) { env, drawable_.obj(), position_pix.x(), position_pix.y()); } -bool PopupTouchHandleDrawable::IntersectsWith(const gfx::RectF& rect) const { - const gfx::RectF rect_pix = gfx::ScaleRect(rect, dpi_scale_); +gfx::RectF PopupTouchHandleDrawable::GetVisibleBounds() const { JNIEnv* env = base::android::AttachCurrentThread(); - return Java_PopupTouchHandleDrawable_intersectsWith(env, - drawable_.obj(), - rect_pix.x(), - rect_pix.y(), - rect_pix.width(), - rect_pix.height()); + gfx::RectF unscaled_rect( + Java_PopupTouchHandleDrawable_getPositionX(env, drawable_.obj()), + Java_PopupTouchHandleDrawable_getPositionY(env, drawable_.obj()), + Java_PopupTouchHandleDrawable_getVisibleWidth(env, drawable_.obj()), + Java_PopupTouchHandleDrawable_getVisibleHeight(env, drawable_.obj())); + return gfx::ScaleRect(unscaled_rect, 1.f / dpi_scale_); } // static diff --git a/content/browser/android/popup_touch_handle_drawable.h b/content/browser/android/popup_touch_handle_drawable.h index a991cac..e7f46ca 100644 --- a/content/browser/android/popup_touch_handle_drawable.h +++ b/content/browser/android/popup_touch_handle_drawable.h @@ -23,7 +23,7 @@ class PopupTouchHandleDrawable : public ui::TouchHandleDrawable { virtual void SetOrientation(ui::TouchHandleOrientation orientation) override; virtual void SetAlpha(float alpha) override; virtual void SetFocus(const gfx::PointF& position) override; - virtual bool IntersectsWith(const gfx::RectF& rect) const override; + virtual gfx::RectF GetVisibleBounds() const override; static bool RegisterPopupTouchHandleDrawable(JNIEnv* env); diff --git a/content/public/android/java/src/org/chromium/content/browser/input/PopupTouchHandleDrawable.java b/content/public/android/java/src/org/chromium/content/browser/input/PopupTouchHandleDrawable.java index 34565de..02fa6a1 100644 --- a/content/public/android/java/src/org/chromium/content/browser/input/PopupTouchHandleDrawable.java +++ b/content/public/android/java/src/org/chromium/content/browser/input/PopupTouchHandleDrawable.java @@ -384,13 +384,24 @@ public class PopupTouchHandleDrawable extends View { } @CalledByNative - private boolean intersectsWith(float x, float y, float width, float height) { - if (mDrawable == null) return false; - final int drawableWidth = mDrawable.getIntrinsicWidth(); - final int drawableHeight = mDrawable.getIntrinsicHeight(); - return !(x >= mPositionX + drawableWidth - || y >= mPositionY + drawableHeight - || x + width <= mPositionX - || y + height <= mPositionY); + private int getPositionX() { + return mPositionX; + } + + @CalledByNative + private int getPositionY() { + return mPositionX; + } + + @CalledByNative + private int getVisibleWidth() { + if (mDrawable == null) return 0; + return mDrawable.getIntrinsicWidth(); + } + + @CalledByNative + private int getVisibleHeight() { + if (mDrawable == null) return 0; + return mDrawable.getIntrinsicHeight(); } } diff --git a/ui/touch_selection/touch_handle.cc b/ui/touch_selection/touch_handle.cc index 91c2874..0680e6d 100644 --- a/ui/touch_selection/touch_handle.cc +++ b/ui/touch_selection/touch_handle.cc @@ -27,6 +27,21 @@ const float kMinTouchMajorForHitTesting = 1.f; // breaking handle dragging behavior. const float kMaxTouchMajorForHitTesting = 36.f; +// Note that the intersection region is boundary *exclusive*. +bool RectIntersectsCircle(const gfx::RectF& rect, + const gfx::PointF& circle_center, + float circle_radius) { + DCHECK_GT(circle_radius, 0.f); + // An intersection occurs if the closest point between the rect and the + // circle's center is less than the circle's radius. + gfx::PointF closest_point_in_rect(circle_center); + closest_point_in_rect.SetToMax(rect.origin()); + closest_point_in_rect.SetToMin(rect.bottom_right()); + + gfx::Vector2dF distance = circle_center - closest_point_in_rect; + return distance.LengthSquared() < (circle_radius * circle_radius); +} + } // namespace // Responsible for rendering a selection or insertion handle for text editing. @@ -124,16 +139,17 @@ bool TouchHandle::WillHandleTouchEvent(const MotionEvent& event) { case MotionEvent::ACTION_DOWN: { if (!is_visible_) return false; - const float touch_size = std::max( + const gfx::PointF touch_point(event.GetX(), event.GetY()); + const float touch_radius = std::max( kMinTouchMajorForHitTesting, - std::min(kMaxTouchMajorForHitTesting, event.GetTouchMajor())); - const gfx::RectF touch_rect(event.GetX() - touch_size * .5f, - event.GetY() - touch_size * .5f, - touch_size, - touch_size); - if (!drawable_->IntersectsWith(touch_rect)) + std::min(kMaxTouchMajorForHitTesting, event.GetTouchMajor())) * 0.5f; + if (!RectIntersectsCircle(drawable_->GetVisibleBounds(), + touch_point, + touch_radius)) { + EndDrag(); return false; - touch_down_position_ = gfx::PointF(event.GetX(), event.GetY()); + } + touch_down_position_ = touch_point; touch_to_focus_offset_ = position_ - touch_down_position_; touch_down_time_ = event.GetEventTime(); BeginDrag(); diff --git a/ui/touch_selection/touch_handle.h b/ui/touch_selection/touch_handle.h index 1998f8e..f6863a2 100644 --- a/ui/touch_selection/touch_handle.h +++ b/ui/touch_selection/touch_handle.h @@ -33,7 +33,7 @@ class UI_TOUCH_SELECTION_EXPORT TouchHandleDrawable { virtual void SetOrientation(TouchHandleOrientation orientation) = 0; virtual void SetAlpha(float alpha) = 0; virtual void SetFocus(const gfx::PointF& position) = 0; - virtual bool IntersectsWith(const gfx::RectF& rect) const = 0; + virtual gfx::RectF GetVisibleBounds() const = 0; }; // Interface through which |TouchHandle| communicates handle manipulation and diff --git a/ui/touch_selection/touch_handle_unittest.cc b/ui/touch_selection/touch_handle_unittest.cc index fded0c5..b266fdb 100644 --- a/ui/touch_selection/touch_handle_unittest.cc +++ b/ui/touch_selection/touch_handle_unittest.cc @@ -52,8 +52,8 @@ class MockTouchHandleDrawable : public TouchHandleDrawable { data_->rect.set_origin(position); } - bool IntersectsWith(const gfx::RectF& rect) const override { - return data_->rect.Intersects(rect); + gfx::RectF GetVisibleBounds() const override { + return data_->rect; } private: @@ -415,7 +415,7 @@ TEST_F(TouchHandleTest, DragTargettingUsesTouchSize) { const float kOffset = kDefaultDrawableSize + kTouchSize / 2.001f; MockMotionEvent event( - MockMotionEvent::ACTION_DOWN, event_time, kOffset, kOffset); + MockMotionEvent::ACTION_DOWN, event_time, kOffset, 0); event.SetTouchMajor(0.f); EXPECT_FALSE(handle.WillHandleTouchEvent(event)); EXPECT_FALSE(IsDragging()); @@ -432,6 +432,21 @@ TEST_F(TouchHandleTest, DragTargettingUsesTouchSize) { EXPECT_TRUE(handle.WillHandleTouchEvent(event)); EXPECT_TRUE(IsDragging()); + // The touch hit test region should be circular. + event = MockMotionEvent( + MockMotionEvent::ACTION_DOWN, event_time, kOffset, kOffset); + event.SetTouchMajor(kTouchSize); + EXPECT_FALSE(handle.WillHandleTouchEvent(event)); + EXPECT_FALSE(IsDragging()); + + event.SetTouchMajor(kTouchSize * std::sqrt(2.f) - 0.1f); + EXPECT_FALSE(handle.WillHandleTouchEvent(event)); + EXPECT_FALSE(IsDragging()); + + event.SetTouchMajor(kTouchSize * std::sqrt(2.f) + 0.1f); + EXPECT_TRUE(handle.WillHandleTouchEvent(event)); + EXPECT_TRUE(IsDragging()); + // Ensure a touch size of 0 can still register a hit. event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time, diff --git a/ui/touch_selection/touch_selection_controller_unittest.cc b/ui/touch_selection/touch_selection_controller_unittest.cc index 5b1839a..7bfc6c2 100644 --- a/ui/touch_selection/touch_selection_controller_unittest.cc +++ b/ui/touch_selection/touch_selection_controller_unittest.cc @@ -24,8 +24,9 @@ class MockTouchHandleDrawable : public TouchHandleDrawable { void SetOrientation(TouchHandleOrientation orientation) override {} void SetAlpha(float alpha) override {} void SetFocus(const gfx::PointF& position) override {} - bool IntersectsWith(const gfx::RectF& rect) const override { - return *intersects_rect_; + gfx::RectF GetVisibleBounds() const override { + return *intersects_rect_ ? gfx::RectF(-1000, -1000, 2000, 2000) + : gfx::RectF(-1000, -1000, 0, 0); } private: |