Commit c6e9dffe authored by Sammie Quon's avatar Sammie Quon Committed by Commit Bot

overview: Fix how multi touch works for overview drag.

Using two fingers was not restricted which brought a bunch of other bugs.
Only allow one item to be dragged at a time. Still allows switching of
fingers midway, so we just check the item which requests drag events is
the same as the current drag item, instead of checking the gesture
finger id.

Test: ash_unittests WindowSelectorTest.DraggingWithTwoFingers
Bug: 827435
Change-Id: I2c897b1b3c483b5df7a98a658f575a6ebd706acd
Reviewed-on: https://chromium-review.googlesource.com/988294
Commit-Queue: Sammie Quon <sammiequon@chromium.org>
Reviewed-by: default avatarMitsuru Oshima <oshima@chromium.org>
Cr-Commit-Position: refs/heads/master@{#547932}
parent 51a90925
...@@ -90,6 +90,7 @@ void OverviewWindowDragController::CompleteDrag( ...@@ -90,6 +90,7 @@ void OverviewWindowDragController::CompleteDrag(
SnapWindow(snap_position_); SnapWindow(snap_position_);
} }
} }
item_ = nullptr;
} }
void OverviewWindowDragController::ActivateDraggedWindow() { void OverviewWindowDragController::ActivateDraggedWindow() {
...@@ -117,6 +118,9 @@ void OverviewWindowDragController::ResetGesture() { ...@@ -117,6 +118,9 @@ void OverviewWindowDragController::ResetGesture() {
window_selector_->PositionWindows(/*animate=*/true); window_selector_->PositionWindows(/*animate=*/true);
window_selector_->SetSplitViewDragIndicatorsIndicatorState( window_selector_->SetSplitViewDragIndicatorsIndicatorState(
IndicatorState::kNone, gfx::Point()); IndicatorState::kNone, gfx::Point());
// This function gets called on long press, which bypasses CompleteDrag but
// stops dragging as well, so reset |item_|.
item_ = nullptr;
} }
void OverviewWindowDragController::ResetWindowSelector() { void OverviewWindowDragController::ResetWindowSelector() {
......
...@@ -963,31 +963,52 @@ float WindowSelectorItem::GetItemScale(const gfx::Size& size) { ...@@ -963,31 +963,52 @@ float WindowSelectorItem::GetItemScale(const gfx::Size& size) {
void WindowSelectorItem::HandlePressEvent( void WindowSelectorItem::HandlePressEvent(
const gfx::Point& location_in_screen) { const gfx::Point& location_in_screen) {
// We allow switching finger while dragging, but do not allow dragging two or more items.
if (window_selector_->window_drag_controller() &&
window_selector_->window_drag_controller()->item()) {
return;
}
StartDrag(); StartDrag();
window_selector_->InitiateDrag(this, location_in_screen); window_selector_->InitiateDrag(this, location_in_screen);
} }
void WindowSelectorItem::HandleReleaseEvent( void WindowSelectorItem::HandleReleaseEvent(
const gfx::Point& location_in_screen) { const gfx::Point& location_in_screen) {
if (!IsDragItem())
return;
EndDrag(); EndDrag();
window_selector_->CompleteDrag(this, location_in_screen); window_selector_->CompleteDrag(this, location_in_screen);
} }
void WindowSelectorItem::HandleDragEvent(const gfx::Point& location_in_screen) { void WindowSelectorItem::HandleDragEvent(const gfx::Point& location_in_screen) {
if (!IsDragItem())
return;
window_selector_->Drag(this, location_in_screen); window_selector_->Drag(this, location_in_screen);
} }
void WindowSelectorItem::ActivateDraggedWindow() { void WindowSelectorItem::ActivateDraggedWindow() {
DCHECK_EQ(this, window_selector_->window_drag_controller()->item()); if (!IsDragItem())
return;
window_selector_->ActivateDraggedWindow(); window_selector_->ActivateDraggedWindow();
} }
void WindowSelectorItem::ResetDraggedWindowGesture() { void WindowSelectorItem::ResetDraggedWindowGesture() {
OnSelectorItemDragEnded(); OnSelectorItemDragEnded();
DCHECK_EQ(this, window_selector_->window_drag_controller()->item()); if (!IsDragItem())
return;
window_selector_->ResetDraggedWindowGesture(); window_selector_->ResetDraggedWindowGesture();
} }
bool WindowSelectorItem::IsDragItem() {
return window_selector_->window_drag_controller() &&
window_selector_->window_drag_controller()->item() == this;
}
void WindowSelectorItem::SetShadowBounds( void WindowSelectorItem::SetShadowBounds(
base::Optional<gfx::Rect> bounds_in_screen) { base::Optional<gfx::Rect> bounds_in_screen) {
if (!IsNewOverviewUi()) if (!IsNewOverviewUi())
......
...@@ -185,6 +185,9 @@ class ASH_EXPORT WindowSelectorItem : public views::ButtonListener, ...@@ -185,6 +185,9 @@ class ASH_EXPORT WindowSelectorItem : public views::ButtonListener,
void ActivateDraggedWindow(); void ActivateDraggedWindow();
void ResetDraggedWindowGesture(); void ResetDraggedWindowGesture();
// Checks if this item is current being dragged.
bool IsDragItem();
// Sets the bounds of the window shadow. If |bounds_in_screen| is nullopt, // Sets the bounds of the window shadow. If |bounds_in_screen| is nullopt,
// the shadow is hidden. // the shadow is hidden.
void SetShadowBounds(base::Optional<gfx::Rect> bounds_in_screen); void SetShadowBounds(base::Optional<gfx::Rect> bounds_in_screen);
......
...@@ -2907,6 +2907,61 @@ TEST_F(WindowSelectorTest, ShadowBounds) { ...@@ -2907,6 +2907,61 @@ TEST_F(WindowSelectorTest, ShadowBounds) {
ToggleOverview(); ToggleOverview();
} }
// Verify that attempting to drag with a secondary finger works as expected.
TEST_F(WindowSelectorTest, DraggingWithTwoFingers) {
std::unique_ptr<aura::Window> window1 = CreateTestWindow();
std::unique_ptr<aura::Window> window2 = CreateTestWindow();
// Dragging is only allowed in tablet mode.
RunAllPendingInMessageLoop();
Shell::Get()->tablet_mode_controller()->EnableTabletModeWindowManager(true);
RunAllPendingInMessageLoop();
ToggleOverview();
RunAllPendingInMessageLoop();
WindowSelectorItem* item1 = GetWindowItemForWindow(0, window1.get());
WindowSelectorItem* item2 = GetWindowItemForWindow(0, window2.get());
const gfx::Rect original_bounds1 = item1->target_bounds();
const gfx::Rect original_bounds2 = item2->target_bounds();
constexpr int kTouchId1 = 1;
constexpr int kTouchId2 = 2;
// Verify that the bounds of the tapped window expand when touched.
ui::test::EventGenerator& generator = GetEventGenerator();
generator.set_current_location(original_bounds1.CenterPoint());
generator.PressTouchId(kTouchId1);
EXPECT_GT(item1->target_bounds().width(), original_bounds1.width());
EXPECT_GT(item1->target_bounds().height(), original_bounds1.height());
// Verify that attempting to touch the second window with a second finger does
// nothing to the second window. The first window remains the window to be
// dragged.
generator.set_current_location(original_bounds2.CenterPoint());
generator.PressTouchId(kTouchId2);
EXPECT_GT(item1->target_bounds().width(), original_bounds1.width());
EXPECT_GT(item1->target_bounds().height(), original_bounds1.height());
EXPECT_EQ(item2->target_bounds(), original_bounds2);
// Verify the first window moves on drag.
gfx::Point last_center_point = item1->target_bounds().CenterPoint();
generator.MoveTouchIdBy(kTouchId1, 40, 40);
EXPECT_NE(last_center_point, item1->target_bounds().CenterPoint());
EXPECT_EQ(original_bounds2.CenterPoint(),
item2->target_bounds().CenterPoint());
// Verify the first window moves on drag, even if we switch to a second
// finger.
last_center_point = item1->target_bounds().CenterPoint();
generator.ReleaseTouchId(kTouchId2);
generator.PressTouchId(kTouchId2);
generator.MoveTouchIdBy(kTouchId2, 40, 40);
EXPECT_NE(last_center_point, item1->target_bounds().CenterPoint());
EXPECT_EQ(original_bounds2.CenterPoint(),
item2->target_bounds().CenterPoint());
}
class SplitViewWindowSelectorTest : public WindowSelectorTest { class SplitViewWindowSelectorTest : public WindowSelectorTest {
public: public:
SplitViewWindowSelectorTest() = default; SplitViewWindowSelectorTest() = default;
......
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