From c1a664398594bcc5744253997ea4b13618f49c13 Mon Sep 17 00:00:00 2001 From: pkotwicz Date: Mon, 25 May 2015 12:20:54 -0700 Subject: End gesture drag when mouse capture is lost We grab mouse capture when either a mouse drag or a touch drag starts. Capture loss should end the drag irrespective of which drag is in progress. BUG=490497 TEST=ToplevelWindowEventHandlerTest.GestureDragCaptureLoss Review URL: https://codereview.chromium.org/1156013002 Cr-Commit-Position: refs/heads/master@{#331299} --- ash/wm/toplevel_window_event_handler.cc | 20 ++++++++++++------ ash/wm/toplevel_window_event_handler.h | 3 +++ ash/wm/toplevel_window_event_handler_unittest.cc | 27 ++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 6 deletions(-) (limited to 'ash') diff --git a/ash/wm/toplevel_window_event_handler.cc b/ash/wm/toplevel_window_event_handler.cc index cc0362e..667fc52 100644 --- a/ash/wm/toplevel_window_event_handler.cc +++ b/ash/wm/toplevel_window_event_handler.cc @@ -190,6 +190,13 @@ void ToplevelWindowEventHandler::OnMouseEvent( (ui::EF_MIDDLE_MOUSE_BUTTON | ui::EF_RIGHT_MOUSE_BUTTON)) != 0) return; + if (event->type() == ui::ET_MOUSE_CAPTURE_CHANGED) { + // Capture is grabbed when both gesture and mouse drags start. Handle + // capture loss regardless of which type of drag is in progress. + HandleCaptureLost(event); + return; + } + if (in_gesture_drag_) return; @@ -201,7 +208,6 @@ void ToplevelWindowEventHandler::OnMouseEvent( case ui::ET_MOUSE_DRAGGED: HandleDrag(target, event); break; - case ui::ET_MOUSE_CAPTURE_CHANGED: case ui::ET_MOUSE_RELEASED: HandleMouseReleased(target, event); break; @@ -512,11 +518,8 @@ void ToplevelWindowEventHandler::HandleMousePressed( void ToplevelWindowEventHandler::HandleMouseReleased( aura::Window* target, ui::MouseEvent* event) { - if (event->phase() != ui::EP_PRETARGET) - return; - - CompleteDrag(event->type() == ui::ET_MOUSE_RELEASED ? - DRAG_COMPLETE : DRAG_REVERT); + if (event->phase() == ui::EP_PRETARGET) + CompleteDrag(DRAG_COMPLETE); } void ToplevelWindowEventHandler::HandleDrag( @@ -579,6 +582,11 @@ void ToplevelWindowEventHandler::HandleMouseExited( controller->HideShadow(target); } +void ToplevelWindowEventHandler::HandleCaptureLost(ui::LocatedEvent* event) { + if (event->phase() == ui::EP_PRETARGET) + CompleteDrag(DRAG_REVERT); +} + void ToplevelWindowEventHandler::SetWindowStateTypeFromGesture( aura::Window* window, wm::WindowStateType new_state_type) { diff --git a/ash/wm/toplevel_window_event_handler.h b/ash/wm/toplevel_window_event_handler.h index a51eb5c..bcaaa91 100644 --- a/ash/wm/toplevel_window_event_handler.h +++ b/ash/wm/toplevel_window_event_handler.h @@ -89,6 +89,9 @@ class ASH_EXPORT ToplevelWindowEventHandler // Called for mouse exits to hide window resize shadows. void HandleMouseExited(aura::Window* target, ui::LocatedEvent* event); + // Called when mouse capture is lost. + void HandleCaptureLost(ui::LocatedEvent* event); + // Sets |window|'s state type to |new_state_type|. Called after the drag has // been completed for fling gestures. void SetWindowStateTypeFromGesture(aura::Window* window, diff --git a/ash/wm/toplevel_window_event_handler_unittest.cc b/ash/wm/toplevel_window_event_handler_unittest.cc index 1f2acb7..bec3eae 100644 --- a/ash/wm/toplevel_window_event_handler_unittest.cc +++ b/ash/wm/toplevel_window_event_handler_unittest.cc @@ -16,6 +16,7 @@ #include "base/basictypes.h" #include "base/compiler_specific.h" #include "base/message_loop/message_loop.h" +#include "base/thread_task_runner_handle.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/aura/client/aura_constants.h" #include "ui/aura/test/aura_test_base.h" @@ -725,6 +726,32 @@ TEST_F(ToplevelWindowEventHandlerTest, CaptureLossAfterMouseRelease) { aura::client::WINDOW_MOVE_SOURCE_MOUSE)); } +namespace { + +// Checks that |window| has capture and releases capture. +void CheckHasCaptureAndReleaseCapture(aura::Window* window) { + ASSERT_TRUE(window->HasCapture()); + window->ReleaseCapture(); +} + +} // namespace + +// Test that releasing capture cancels an in-progress gesture drag. +TEST_F(ToplevelWindowEventHandlerTest, GestureDragCaptureLoss) { + scoped_ptr window(CreateWindow(HTNOWHERE)); + ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), + window.get()); + + aura::client::WindowMoveClient* move_client = + aura::client::GetWindowMoveClient(window->GetRootWindow()); + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(&CheckHasCaptureAndReleaseCapture, + base::Unretained(window.get()))); + EXPECT_EQ(aura::client::MOVE_CANCELED, + move_client->RunMoveLoop(window.get(), gfx::Vector2d(), + aura::client::WINDOW_MOVE_SOURCE_TOUCH)); +} + // Showing the resize shadows when the mouse is over the window edges is tested // in resize_shadow_and_cursor_test.cc -- cgit v1.1