Commit deb67ab9 authored by mukai's avatar mukai Committed by Commit bot

Update gesture logic.

- record the original state when the gesture starts
- changes the height condition for the closest state based on the
  original state
- limit the fling handling only when the closest state ends up with
  the original state. This will save the most of the case, however
  it may cause unexpected results if the user makes complicated
  gestures (like moves up from minimized, up to the full-screen,
  then fling-down). I think this is a rare case and we don't
  have to care about.

BUG=415211
R=pkotwicz@chromium.org
TEST=athena_unittests && manually

Review URL: https://codereview.chromium.org/581933004

Cr-Commit-Position: refs/heads/master@{#295616}
parent 3530cf95
...@@ -9,9 +9,31 @@ ...@@ -9,9 +9,31 @@
namespace athena { namespace athena {
namespace {
// The maximum height, in pixels, of a home card with final state
// VISIBLE_MINIMIZED.
const int kMinimizedFinalStateMaxHeight = 50 + kHomeCardMinimizedHeight;
// The maximum height, in pixels, of an initially centered home card with final
// state VISIBLE_MINIMIZED.
const int kMinimizedFinalStateMaxHeightInitiallyCentered =
90 + kHomeCardMinimizedHeight;
// The minimum height, as a percentage of the screen height, of a home card with
// final state VISIBLE_CENTERED.
const float kCenteredFinalStateMinScreenRatio = 0.5f;
// The minimum height, as a percentage of the screen height, of an initially
// minimized home card with final state VISIBLE_CENTERED.
const float kCenteredFinalStateMinScreenRatioInitiallyMinimized = 0.3f;
}
HomeCardGestureManager::HomeCardGestureManager(Delegate* delegate, HomeCardGestureManager::HomeCardGestureManager(Delegate* delegate,
const gfx::Rect& screen_bounds) const gfx::Rect& screen_bounds)
: delegate_(delegate), : delegate_(delegate),
original_state_(HomeCard::HIDDEN),
y_offset_(0), y_offset_(0),
last_estimated_height_(0), last_estimated_height_(0),
screen_bounds_(screen_bounds) {} screen_bounds_(screen_bounds) {}
...@@ -22,11 +44,13 @@ void HomeCardGestureManager::ProcessGestureEvent(ui::GestureEvent* event) { ...@@ -22,11 +44,13 @@ void HomeCardGestureManager::ProcessGestureEvent(ui::GestureEvent* event) {
switch (event->type()) { switch (event->type()) {
case ui::ET_GESTURE_SCROLL_BEGIN: case ui::ET_GESTURE_SCROLL_BEGIN:
y_offset_ = event->location().y(); y_offset_ = event->location().y();
original_state_ = HomeCard::Get()->GetState();
DCHECK_NE(HomeCard::HIDDEN, original_state_);
event->SetHandled(); event->SetHandled();
break; break;
case ui::ET_GESTURE_SCROLL_END: case ui::ET_GESTURE_SCROLL_END:
event->SetHandled(); event->SetHandled();
delegate_->OnGestureEnded(GetClosestState()); delegate_->OnGestureEnded(GetFinalState());
break; break;
case ui::ET_GESTURE_SCROLL_UPDATE: case ui::ET_GESTURE_SCROLL_UPDATE:
UpdateScrollState(*event); UpdateScrollState(*event);
...@@ -34,8 +58,18 @@ void HomeCardGestureManager::ProcessGestureEvent(ui::GestureEvent* event) { ...@@ -34,8 +58,18 @@ void HomeCardGestureManager::ProcessGestureEvent(ui::GestureEvent* event) {
case ui::ET_SCROLL_FLING_START: { case ui::ET_SCROLL_FLING_START: {
const ui::GestureEventDetails& details = event->details(); const ui::GestureEventDetails& details = event->details();
const float kFlingCompletionVelocity = 100.0f; const float kFlingCompletionVelocity = 100.0f;
HomeCard::State final_state = GetClosestState(); HomeCard::State final_state = GetFinalState();
if (::fabs(details.velocity_y()) > kFlingCompletionVelocity) {
// When the user does not drag far enough to switch the final state, but
// a fling happens at the end of the gesture, the state should change
// based on the direction of the fling.
// Checking |final_state| == |original_state| may cause unexpected results
// for gestures where the user flings in the opposite direction that they
// moved the home card (e.g. drag home card up from minimized state and
// then fling down)
// TODO(mukai): Consider this case once reported.
if (final_state == original_state_ &&
::fabs(details.velocity_y()) > kFlingCompletionVelocity) {
if (details.velocity_y() > 0) { if (details.velocity_y() > 0) {
final_state = std::min(HomeCard::VISIBLE_MINIMIZED, final_state = std::min(HomeCard::VISIBLE_MINIMIZED,
static_cast<HomeCard::State>(final_state + 1)); static_cast<HomeCard::State>(final_state + 1));
...@@ -53,18 +87,19 @@ void HomeCardGestureManager::ProcessGestureEvent(ui::GestureEvent* event) { ...@@ -53,18 +87,19 @@ void HomeCardGestureManager::ProcessGestureEvent(ui::GestureEvent* event) {
} }
} }
HomeCard::State HomeCardGestureManager::GetClosestState() const { HomeCard::State HomeCardGestureManager::GetFinalState() const {
const int kMinimizedHomeBufferSize = 50; int max_height = (original_state_ == HomeCard::VISIBLE_CENTERED)
if (last_estimated_height_ <= ? kMinimizedFinalStateMaxHeightInitiallyCentered
kHomeCardMinimizedHeight + kMinimizedHomeBufferSize) { : kMinimizedFinalStateMaxHeight;
if (last_estimated_height_ < max_height)
return HomeCard::VISIBLE_MINIMIZED; return HomeCard::VISIBLE_MINIMIZED;
}
int centered_height = screen_bounds_.height(); float ratio = (original_state_ == HomeCard::VISIBLE_MINIMIZED)
if (last_estimated_height_ - kHomeCardHeight <= ? kCenteredFinalStateMinScreenRatioInitiallyMinimized
(centered_height - kHomeCardHeight) / 3) { : kCenteredFinalStateMinScreenRatio;
if (last_estimated_height_ < screen_bounds_.height() * ratio)
return HomeCard::VISIBLE_BOTTOM; return HomeCard::VISIBLE_BOTTOM;
}
return HomeCard::VISIBLE_CENTERED; return HomeCard::VISIBLE_CENTERED;
} }
......
...@@ -44,14 +44,17 @@ class ATHENA_EXPORT HomeCardGestureManager { ...@@ -44,14 +44,17 @@ class ATHENA_EXPORT HomeCardGestureManager {
void ProcessGestureEvent(ui::GestureEvent* event); void ProcessGestureEvent(ui::GestureEvent* event);
private: private:
// Get the closest state from the last position. // Get the final state from the last position.
HomeCard::State GetClosestState() const; HomeCard::State GetFinalState() const;
// Update the current position and emits OnGestureProgressed(). // Update the current position and emits OnGestureProgressed().
void UpdateScrollState(const ui::GestureEvent& event); void UpdateScrollState(const ui::GestureEvent& event);
Delegate* delegate_; // Not owned. Delegate* delegate_; // Not owned.
// The state when the gesture starts.
HomeCard::State original_state_;
// The offset from the top edge of the home card and the initial position of // The offset from the top edge of the home card and the initial position of
// gesture. // gesture.
int y_offset_; int y_offset_;
......
...@@ -66,6 +66,7 @@ class HomeCardGestureManagerTest : public test::AthenaTestBase, ...@@ -66,6 +66,7 @@ class HomeCardGestureManagerTest : public test::AthenaTestBase,
last_y_ = y; last_y_ = y;
return event.handled(); return event.handled();
} }
void ProcessFlingGesture(float velocity) { void ProcessFlingGesture(float velocity) {
ui::GestureEvent event(0, last_y_, ui::EF_NONE, base::TimeDelta(), ui::GestureEvent event(0, last_y_, ui::EF_NONE, base::TimeDelta(),
ui::GestureEventDetails( ui::GestureEventDetails(
...@@ -73,6 +74,10 @@ class HomeCardGestureManagerTest : public test::AthenaTestBase, ...@@ -73,6 +74,10 @@ class HomeCardGestureManagerTest : public test::AthenaTestBase,
gesture_manager_->ProcessGestureEvent(&event); gesture_manager_->ProcessGestureEvent(&event);
} }
int screen_height() const {
return screen_bounds().height();
}
HomeCard::State final_state_; HomeCard::State final_state_;
HomeCard::State last_from_state_; HomeCard::State last_from_state_;
HomeCard::State last_to_state_; HomeCard::State last_to_state_;
...@@ -180,9 +185,41 @@ TEST_F(HomeCardGestureManagerTest, StartCentered) { ...@@ -180,9 +185,41 @@ TEST_F(HomeCardGestureManagerTest, StartCentered) {
EXPECT_GT(1.0f, last_progress_); EXPECT_GT(1.0f, last_progress_);
EXPECT_LT(0.0f, last_progress_); EXPECT_LT(0.0f, last_progress_);
EXPECT_TRUE(ProcessGestureEvent(ui::ET_GESTURE_SCROLL_END, 1000)); ProcessGestureEvent(ui::ET_GESTURE_SCROLL_UPDATE, 960);
EXPECT_TRUE(ProcessGestureEvent(ui::ET_GESTURE_SCROLL_END, 960));
EXPECT_EQ(1, GetEndCountAndReset());
EXPECT_EQ(HomeCard::VISIBLE_MINIMIZED, final_state_);
}
// Test gesture progress when the gesture is initiated when the home card is in
// the centered state.
TEST_F(HomeCardGestureManagerTest, StartBottom) {
HomeCard::Get()->SetState(HomeCard::VISIBLE_BOTTOM);
// No changes for slight moves.
EXPECT_TRUE(ProcessGestureEvent(ui::ET_GESTURE_SCROLL_BEGIN, 950));
ProcessGestureEvent(ui::ET_GESTURE_SCROLL_UPDATE, 960);
EXPECT_TRUE(ProcessGestureEvent(ui::ET_GESTURE_SCROLL_END, 960));
EXPECT_EQ(1, GetEndCountAndReset()); EXPECT_EQ(1, GetEndCountAndReset());
EXPECT_EQ(HomeCard::VISIBLE_BOTTOM, final_state_); EXPECT_EQ(HomeCard::VISIBLE_BOTTOM, final_state_);
EXPECT_TRUE(ProcessGestureEvent(ui::ET_GESTURE_SCROLL_BEGIN, 950));
EXPECT_TRUE(ProcessGestureEvent(ui::ET_GESTURE_SCROLL_END, 800));
EXPECT_EQ(1, GetEndCountAndReset());
EXPECT_EQ(HomeCard::VISIBLE_BOTTOM, final_state_);
// State change for the bigger moves.
EXPECT_TRUE(ProcessGestureEvent(ui::ET_GESTURE_SCROLL_BEGIN, 950));
ProcessGestureEvent(ui::ET_GESTURE_SCROLL_UPDATE, 1000);
EXPECT_TRUE(ProcessGestureEvent(ui::ET_GESTURE_SCROLL_END, 1000));
EXPECT_EQ(1, GetEndCountAndReset());
EXPECT_EQ(HomeCard::VISIBLE_MINIMIZED, final_state_);
EXPECT_TRUE(ProcessGestureEvent(ui::ET_GESTURE_SCROLL_BEGIN, 950));
ProcessGestureEvent(ui::ET_GESTURE_SCROLL_UPDATE, 300);
EXPECT_TRUE(ProcessGestureEvent(ui::ET_GESTURE_SCROLL_END, 300));
EXPECT_EQ(1, GetEndCountAndReset());
EXPECT_EQ(HomeCard::VISIBLE_CENTERED, final_state_);
} }
TEST_F(HomeCardGestureManagerTest, FlingUpAtEnd) { TEST_F(HomeCardGestureManagerTest, FlingUpAtEnd) {
...@@ -193,22 +230,20 @@ TEST_F(HomeCardGestureManagerTest, FlingUpAtEnd) { ...@@ -193,22 +230,20 @@ TEST_F(HomeCardGestureManagerTest, FlingUpAtEnd) {
EXPECT_EQ(0, GetProgressCountAndReset()); EXPECT_EQ(0, GetProgressCountAndReset());
ProcessGestureEvent(ui::ET_GESTURE_SCROLL_UPDATE, 1010); ProcessGestureEvent(ui::ET_GESTURE_SCROLL_UPDATE, 1010);
ProcessGestureEvent(ui::ET_GESTURE_SCROLL_UPDATE, 800);
ProcessFlingGesture(-150.0f); ProcessFlingGesture(-150.0f);
EXPECT_EQ(1, GetEndCountAndReset()); EXPECT_EQ(1, GetEndCountAndReset());
EXPECT_EQ(HomeCard::VISIBLE_CENTERED, final_state_); EXPECT_EQ(HomeCard::VISIBLE_BOTTOM, final_state_);
} }
TEST_F(HomeCardGestureManagerTest, FlingDownAtEnd) { TEST_F(HomeCardGestureManagerTest, FlingDownAtEnd) {
ASSERT_EQ(HomeCard::VISIBLE_MINIMIZED, HomeCard::Get()->GetState()); HomeCard::Get()->SetState(HomeCard::VISIBLE_CENTERED);
EXPECT_TRUE(ProcessGestureEvent(ui::ET_GESTURE_SCROLL_BEGIN, 1020)); EXPECT_TRUE(ProcessGestureEvent(ui::ET_GESTURE_SCROLL_BEGIN, 20));
EXPECT_EQ(0, GetEndCountAndReset()); EXPECT_EQ(0, GetEndCountAndReset());
EXPECT_EQ(0, GetProgressCountAndReset()); EXPECT_EQ(0, GetProgressCountAndReset());
ProcessGestureEvent(ui::ET_GESTURE_SCROLL_UPDATE, 1010); ProcessGestureEvent(ui::ET_GESTURE_SCROLL_UPDATE, 30);
ProcessGestureEvent(ui::ET_GESTURE_SCROLL_UPDATE, 800); ProcessGestureEvent(ui::ET_GESTURE_SCROLL_UPDATE, 100);
ProcessGestureEvent(ui::ET_GESTURE_SCROLL_UPDATE, 200);
ProcessFlingGesture(150.0f); ProcessFlingGesture(150.0f);
EXPECT_EQ(1, GetEndCountAndReset()); EXPECT_EQ(1, GetEndCountAndReset());
EXPECT_EQ(HomeCard::VISIBLE_BOTTOM, final_state_); EXPECT_EQ(HomeCard::VISIBLE_BOTTOM, final_state_);
...@@ -222,9 +257,29 @@ TEST_F(HomeCardGestureManagerTest, WeakFling) { ...@@ -222,9 +257,29 @@ TEST_F(HomeCardGestureManagerTest, WeakFling) {
EXPECT_EQ(0, GetProgressCountAndReset()); EXPECT_EQ(0, GetProgressCountAndReset());
ProcessGestureEvent(ui::ET_GESTURE_SCROLL_UPDATE, 1010); ProcessGestureEvent(ui::ET_GESTURE_SCROLL_UPDATE, 1010);
ProcessGestureEvent(ui::ET_GESTURE_SCROLL_UPDATE, 800);
ProcessFlingGesture(-30.0f); ProcessFlingGesture(-30.0f);
EXPECT_EQ(1, GetEndCountAndReset()); EXPECT_EQ(1, GetEndCountAndReset());
EXPECT_EQ(HomeCard::VISIBLE_MINIMIZED, final_state_);
}
// Test the situation where the user intends a single fling but the finger
// touches the screen long enough, so that the home card becomes bigger than the
// height of VISIBLE_BOTTOM state due to the scroll events.
// In this case the fling event should not change the final state from
// VISIBLE_BOTTOM to VISIBLE_CENTERED because the user's intention was a single
// fling. See http://crbug.com/415211
TEST_F(HomeCardGestureManagerTest, FastFling) {
ASSERT_EQ(HomeCard::VISIBLE_MINIMIZED, HomeCard::Get()->GetState());
EXPECT_TRUE(ProcessGestureEvent(ui::ET_GESTURE_SCROLL_BEGIN, 1020));
EXPECT_EQ(0, GetEndCountAndReset());
EXPECT_EQ(0, GetProgressCountAndReset());
ProcessGestureEvent(ui::ET_GESTURE_SCROLL_UPDATE, 1010);
ProcessGestureEvent(ui::ET_GESTURE_SCROLL_UPDATE,
screen_height() - kHomeCardHeight);
ProcessFlingGesture(-150.0f);
EXPECT_EQ(1, GetEndCountAndReset());
EXPECT_EQ(HomeCard::VISIBLE_BOTTOM, final_state_); EXPECT_EQ(HomeCard::VISIBLE_BOTTOM, final_state_);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment