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

Unified Diff: ui/touch_selection/touch_handle.cc

Issue 481683003: Support for Adaptive Handle Orientation (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebased Created 5 years, 2 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
« no previous file with comments | « ui/touch_selection/touch_handle.h ('k') | ui/touch_selection/touch_handle_drawable_aura.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/touch_selection/touch_handle.cc
diff --git a/ui/touch_selection/touch_handle.cc b/ui/touch_selection/touch_handle.cc
index 1925a1a474f09d793b6a983a061a13c3246851f3..0fe3612eab31714ea616529d42ad28eb635c944d 100644
--- a/ui/touch_selection/touch_handle.cc
+++ b/ui/touch_selection/touch_handle.cc
@@ -63,9 +63,11 @@ static std::ostream& operator<<(std::ostream& os,
// Responsible for rendering a selection or insertion handle for text editing.
TouchHandle::TouchHandle(TouchHandleClient* client,
- TouchHandleOrientation orientation)
+ TouchHandleOrientation orientation,
+ const gfx::RectF& viewport_rect)
: drawable_(client->CreateDrawable()),
client_(client),
+ viewport_rect_(viewport_rect),
orientation_(orientation),
deferred_orientation_(TouchHandleOrientation::UNDEFINED),
alpha_(0.f),
@@ -73,12 +75,16 @@ TouchHandle::TouchHandle(TouchHandleClient* client,
enabled_(true),
is_visible_(false),
is_dragging_(false),
- is_drag_within_tap_region_(false) {
+ is_drag_within_tap_region_(false),
+ is_handle_layout_update_required_(false),
+ mirror_vertical_(false),
+ mirror_horizontal_(false) {
DCHECK_NE(orientation, TouchHandleOrientation::UNDEFINED);
drawable_->SetEnabled(enabled_);
- drawable_->SetOrientation(orientation_);
+ drawable_->SetOrientation(orientation_, false, false);
+ drawable_->SetOrigin(focus_bottom_);
drawable_->SetAlpha(alpha_);
- drawable_->SetFocus(position_);
+ handle_horizontal_padding_ = drawable_->GetDrawableHorizontalPaddingRatio();
}
TouchHandle::~TouchHandle() {
@@ -104,7 +110,7 @@ void TouchHandle::SetVisible(bool visible, AnimationStyle animation_style) {
// Handle repositioning may have been deferred while previously invisible.
if (visible)
- drawable_->SetFocus(position_);
+ SetUpdateLayoutRequired();
bool animate = animation_style != ANIMATION_NONE;
if (is_dragging_) {
@@ -118,16 +124,23 @@ void TouchHandle::SetVisible(bool visible, AnimationStyle animation_style) {
EndFade();
}
-void TouchHandle::SetPosition(const gfx::PointF& position) {
+void TouchHandle::SetFocus(const gfx::PointF& top, const gfx::PointF& bottom) {
DCHECK(enabled_);
- if (position_ == position)
+ if (focus_top_ == top && focus_bottom_ == bottom)
return;
- position_ = position;
- // Suppress repositioning a handle while invisible or fading out to prevent it
- // from "ghosting" outside the visible bounds. The position will be pushed to
- // the drawable when the handle regains visibility (see |SetVisible()|).
- if (is_visible_)
- drawable_->SetFocus(position_);
+
+ focus_top_ = top;
+ focus_bottom_ = bottom;
+ SetUpdateLayoutRequired();
+}
+
+void TouchHandle::SetViewportRect(const gfx::RectF& viewport_rect) {
+ DCHECK(enabled_);
+ if (viewport_rect_ == viewport_rect)
+ return;
+
+ viewport_rect_ = viewport_rect;
+ SetUpdateLayoutRequired();
}
void TouchHandle::SetOrientation(TouchHandleOrientation orientation) {
@@ -142,7 +155,7 @@ void TouchHandle::SetOrientation(TouchHandleOrientation orientation) {
return;
orientation_ = orientation;
- drawable_->SetOrientation(orientation);
+ SetUpdateLayoutRequired();
}
bool TouchHandle::WillHandleTouchEvent(const MotionEvent& event) {
@@ -170,7 +183,7 @@ bool TouchHandle::WillHandleTouchEvent(const MotionEvent& event) {
return false;
}
touch_down_position_ = touch_point;
- touch_drag_offset_ = position_ - touch_down_position_;
+ touch_drag_offset_ = focus_bottom_ - touch_down_position_;
touch_down_time_ = event.GetEventTime();
BeginDrag();
} break;
@@ -217,8 +230,8 @@ bool TouchHandle::Animate(base::TimeTicks frame_time) {
float time_u =
1.f - (fade_end_time_ - frame_time).InMillisecondsF() / kFadeDurationMs;
- float position_u =
- (position_ - fade_start_position_).LengthSquared() / kFadeDistanceSquared;
+ float position_u = (focus_bottom_ - fade_start_position_).LengthSquared() /
+ kFadeDistanceSquared;
float u = std::max(time_u, position_u);
SetAlpha(is_visible_ ? u : 1.f - u);
@@ -237,6 +250,86 @@ gfx::RectF TouchHandle::GetVisibleBounds() const {
return drawable_->GetVisibleBounds();
}
+void TouchHandle::UpdateHandleLayout() {
+ // Suppress repositioning a handle while invisible or fading out to prevent it
+ // from "ghosting" outside the visible bounds. The position will be pushed to
+ // the drawable when the handle regains visibility (see |SetVisible()|).
+ if (!is_visible_ || !is_handle_layout_update_required_)
+ return;
+
+ is_handle_layout_update_required_ = false;
+
+ // Update mirror values only when dragging has stopped to prevent unwanted
+ // inversion while dragging of handles.
+ if (client_->IsAdaptiveHandleOrientationEnabled() && !is_dragging_) {
+ gfx::RectF handle_bounds = drawable_->GetVisibleBounds();
+ bool mirror_horizontal = false;
+ bool mirror_vertical = false;
+
+ const float handle_width =
+ handle_bounds.width() * (1.0 - handle_horizontal_padding_);
+ const float handle_height = handle_bounds.height();
+
+ const float bottom_y_unmirrored =
+ focus_bottom_.y() + handle_height + viewport_rect_.y();
+ const float top_y_mirrored =
+ focus_top_.y() - handle_height + viewport_rect_.y();
+
+ // In case the viewport height is small, like webview, avoid inversion.
+ if (bottom_y_unmirrored > viewport_rect_.bottom() &&
+ top_y_mirrored > viewport_rect_.y()) {
+ mirror_vertical = true;
+ }
+
+ if (orientation_ == TouchHandleOrientation::LEFT &&
+ focus_bottom_.x() - handle_width < viewport_rect_.x()) {
+ mirror_horizontal = true;
+ } else if (orientation_ == TouchHandleOrientation::RIGHT &&
+ focus_bottom_.x() + handle_width > viewport_rect_.right()) {
+ mirror_horizontal = true;
+ }
+
+ mirror_horizontal_ = mirror_horizontal;
+ mirror_vertical_ = mirror_vertical;
+ }
+
+ drawable_->SetOrientation(orientation_, mirror_vertical_, mirror_horizontal_);
+ drawable_->SetOrigin(ComputeHandleOrigin());
+}
+
+gfx::PointF TouchHandle::ComputeHandleOrigin() const {
+ gfx::PointF focus = mirror_vertical_ ? focus_top_ : focus_bottom_;
+ gfx::RectF drawable_bounds = drawable_->GetVisibleBounds();
+ float drawable_width = drawable_->GetVisibleBounds().width();
+
+ // Calculate the focal offsets from origin for the handle drawable
+ // based on the orientation.
+ int focal_offset_x = 0;
+ int focal_offset_y = mirror_vertical_ ? drawable_bounds.height() : 0;
+ switch (orientation_) {
+ case ui::TouchHandleOrientation::LEFT:
+ focal_offset_x =
+ mirror_horizontal_
+ ? drawable_width * handle_horizontal_padding_
+ : drawable_width * (1.0f - handle_horizontal_padding_);
+ break;
+ case ui::TouchHandleOrientation::RIGHT:
+ focal_offset_x =
+ mirror_horizontal_
+ ? drawable_width * (1.0f - handle_horizontal_padding_)
+ : drawable_width * handle_horizontal_padding_;
+ break;
+ case ui::TouchHandleOrientation::CENTER:
+ focal_offset_x = drawable_width * 0.5f;
+ break;
+ case ui::TouchHandleOrientation::UNDEFINED:
+ NOTREACHED() << "Invalid touch handle orientation.";
+ break;
+ };
+
+ return focus - gfx::Vector2dF(focal_offset_x, focal_offset_y);
+}
+
void TouchHandle::BeginDrag() {
DCHECK(enabled_);
if (is_dragging_)
@@ -244,7 +337,7 @@ void TouchHandle::BeginDrag() {
EndFade();
is_dragging_ = true;
is_drag_within_tap_region_ = true;
- client_->OnDragBegin(*this, position());
+ client_->OnDragBegin(*this, focus_bottom());
}
void TouchHandle::EndDrag() {
@@ -260,6 +353,9 @@ void TouchHandle::EndDrag() {
TouchHandleOrientation deferred_orientation = deferred_orientation_;
deferred_orientation_ = TouchHandleOrientation::UNDEFINED;
SetOrientation(deferred_orientation);
+ // Handle layout may be deferred while the handle is dragged.
+ SetUpdateLayoutRequired();
+ UpdateHandleLayout();
}
if (animate_deferred_fade_) {
@@ -284,7 +380,7 @@ void TouchHandle::BeginFade() {
fade_end_time_ = base::TimeTicks::Now() +
base::TimeDelta::FromMillisecondsD(
kFadeDurationMs * std::abs(target_alpha - alpha_));
- fade_start_position_ = position_;
+ fade_start_position_ = focus_bottom_;
client_->SetNeedsAnimate();
}
@@ -303,4 +399,10 @@ void TouchHandle::SetAlpha(float alpha) {
drawable_->SetAlpha(alpha);
}
+void TouchHandle::SetUpdateLayoutRequired() {
+ // TODO(AviD): Make the layout call explicit to the caller by adding this in
+ // TouchHandleClient.
+ is_handle_layout_update_required_ = true;
+}
+
} // namespace ui
« no previous file with comments | « ui/touch_selection/touch_handle.h ('k') | ui/touch_selection/touch_handle_drawable_aura.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698