diff options
-rw-r--r-- | ash/drag_drop/drag_drop_controller.cc | 63 | ||||
-rw-r--r-- | ash/drag_drop/drag_drop_controller.h | 2 | ||||
-rw-r--r-- | ash/drag_drop/drag_drop_controller_unittest.cc | 59 | ||||
-rw-r--r-- | ash/drag_drop/drag_drop_tracker.cc | 17 | ||||
-rw-r--r-- | ash/drag_drop/drag_drop_tracker.h | 4 | ||||
-rw-r--r-- | ash/drag_drop/drag_drop_tracker_unittest.cc | 6 | ||||
-rw-r--r-- | chrome/browser/chromeos/login/webui_screen_locker.cc | 7 |
7 files changed, 146 insertions, 12 deletions
diff --git a/ash/drag_drop/drag_drop_controller.cc b/ash/drag_drop/drag_drop_controller.cc index c13e087..1500dae 100644 --- a/ash/drag_drop/drag_drop_controller.cc +++ b/ash/drag_drop/drag_drop_controller.cc @@ -16,11 +16,14 @@ #include "ui/aura/env.h" #include "ui/aura/root_window.h" #include "ui/aura/window.h" +#include "ui/aura/window_delegate.h" #include "ui/base/animation/linear_animation.h" #include "ui/base/dragdrop/drag_drop_types.h" #include "ui/base/dragdrop/os_exchange_data.h" #include "ui/base/events/event.h" #include "ui/base/events/event_utils.h" +#include "ui/base/hit_test.h" +#include "ui/gfx/path.h" #include "ui/gfx/point.h" #include "ui/gfx/rect.h" #include "ui/gfx/rect_conversions.h" @@ -77,6 +80,61 @@ void DispatchGestureEndToWindow(aura::Window* window) { } } // namespace +class DragDropTrackerDelegate : public aura::WindowDelegate { + public: + explicit DragDropTrackerDelegate(DragDropController* controller) + : drag_drop_controller_(controller) {} + virtual ~DragDropTrackerDelegate() {} + + // Overridden from WindowDelegate: + virtual gfx::Size GetMinimumSize() const OVERRIDE { + return gfx::Size(); + } + + virtual gfx::Size GetMaximumSize() const OVERRIDE { + return gfx::Size(); + } + + virtual void OnBoundsChanged(const gfx::Rect& old_bounds, + const gfx::Rect& new_bounds) OVERRIDE {} + virtual gfx::NativeCursor GetCursor(const gfx::Point& point) OVERRIDE { + return gfx::kNullCursor; + } + virtual int GetNonClientComponent(const gfx::Point& point) const OVERRIDE { + return HTCAPTION; + } + virtual bool ShouldDescendIntoChildForEventHandling( + aura::Window* child, + const gfx::Point& location) OVERRIDE { + return true; + } + virtual bool CanFocus() OVERRIDE { return true; } + virtual void OnCaptureLost() OVERRIDE { + if (drag_drop_controller_->IsDragDropInProgress()) + drag_drop_controller_->DragCancel(); + } + virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE { + } + virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE {} + virtual void OnWindowDestroying() OVERRIDE {} + virtual void OnWindowDestroyed() OVERRIDE {} + virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE {} + virtual bool HasHitTestMask() const OVERRIDE { + return true; + } + virtual void GetHitTestMask(gfx::Path* mask) const OVERRIDE { + DCHECK(mask->isEmpty()); + } + virtual scoped_refptr<ui::Texture> CopyTexture() OVERRIDE { + return scoped_refptr<ui::Texture>(); + } + + private: + DragDropController* drag_drop_controller_; + + DISALLOW_COPY_AND_ASSIGN(DragDropTrackerDelegate); +}; + //////////////////////////////////////////////////////////////////////////////// // DragDropController, public: @@ -87,6 +145,8 @@ DragDropController::DragDropController() drag_window_(NULL), drag_source_window_(NULL), should_block_during_drag_drop_(true), + ALLOW_THIS_IN_INITIALIZER_LIST( + drag_drop_window_delegate_(new DragDropTrackerDelegate(this))), current_drag_event_source_(ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE), weak_factory_(this) { Shell::GetInstance()->AddPreTargetHandler(this); @@ -118,7 +178,8 @@ int DragDropController::StartDragAndDrop( return 0; current_drag_event_source_ = source; - DragDropTracker* tracker = new DragDropTracker(root_window); + DragDropTracker* tracker = + new DragDropTracker(root_window, drag_drop_window_delegate_.get()); if (source == ui::DragDropTypes::DRAG_EVENT_SOURCE_TOUCH) { // We need to transfer the current gesture sequence and the GR's touch event // queue to the |drag_drop_tracker_|'s capture window so that when it takes diff --git a/ash/drag_drop/drag_drop_controller.h b/ash/drag_drop/drag_drop_controller.h index 8c4e6bb..a23ed91 100644 --- a/ash/drag_drop/drag_drop_controller.h +++ b/ash/drag_drop/drag_drop_controller.h @@ -34,6 +34,7 @@ class DragDropControllerTest; namespace internal { class DragDropTracker; +class DragDropTrackerDelegate; class DragImageView; class ASH_EXPORT DragDropController @@ -127,6 +128,7 @@ class ASH_EXPORT DragDropController base::Closure quit_closure_; scoped_ptr<ash::internal::DragDropTracker> drag_drop_tracker_; + scoped_ptr<DragDropTrackerDelegate> drag_drop_window_delegate_; ui::DragDropTypes::DragEventSource current_drag_event_source_; diff --git a/ash/drag_drop/drag_drop_controller_unittest.cc b/ash/drag_drop/drag_drop_controller_unittest.cc index 8599535..2b0091f 100644 --- a/ash/drag_drop/drag_drop_controller_unittest.cc +++ b/ash/drag_drop/drag_drop_controller_unittest.cc @@ -4,12 +4,14 @@ #include "ash/drag_drop/drag_drop_controller.h" +#include "ash/drag_drop/drag_drop_tracker.h" #include "ash/drag_drop/drag_image_view.h" #include "ash/shell.h" #include "ash/test/ash_test_base.h" #include "base/command_line.h" #include "base/location.h" #include "base/utf_string_conversions.h" +#include "ui/aura/client/capture_client.h" #include "ui/aura/root_window.h" #include "ui/aura/test/event_generator.h" #include "ui/base/animation/linear_animation.h" @@ -329,6 +331,10 @@ class DragDropControllerTest : public AshTestBase { NULL; } + internal::DragDropTracker* drag_drop_tracker() { + return drag_drop_controller_->drag_drop_tracker_.get(); + } + void CompleteCancelAnimation() { CompletableLinearAnimation* animation = static_cast<CompletableLinearAnimation*>( @@ -754,8 +760,10 @@ TEST_F(DragDropControllerTest, SyntheticEventsDuringDragDrop) { // TODO(win_aura) http://crbug.com/154081 #if defined(OS_WIN) #define MAYBE_PressingEscapeCancelsDragDrop DISABLED_PressingEscapeCancelsDragDrop +#define MAYBE_CaptureLostCancelsDragDrop DISABLED_CaptureLostCancelsDragDrop #else #define MAYBE_PressingEscapeCancelsDragDrop PressingEscapeCancelsDragDrop +#define MAYBE_CaptureLostCancelsDragDrop CaptureLostCancelsDragDrop #endif TEST_F(DragDropControllerTest, MAYBE_PressingEscapeCancelsDragDrop) { scoped_ptr<views::Widget> widget(CreateNewWidget()); @@ -799,6 +807,57 @@ TEST_F(DragDropControllerTest, MAYBE_PressingEscapeCancelsDragDrop) { EXPECT_TRUE(drag_view->drag_done_received_); } +TEST_F(DragDropControllerTest, MAYBE_CaptureLostCancelsDragDrop) { + scoped_ptr<views::Widget> widget(CreateNewWidget()); + DragTestView* drag_view = new DragTestView; + AddViewToWidgetAndResize(widget.get(), drag_view); + ui::OSExchangeData data; + data.SetString(UTF8ToUTF16("I am being dragged")); + aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), + widget->GetNativeView()); + generator.PressLeftButton(); + + int num_drags = 17; + for (int i = 0; i < num_drags; ++i) { + // Because we are not doing a blocking drag and drop, the original + // OSDragExchangeData object is lost as soon as we return from the drag + // initiation in DragDropController::StartDragAndDrop(). Hence we set the + // drag_data_ to a fake drag data object that we created. + if (i > 0) + UpdateDragData(&data); + generator.MoveMouseBy(0, 1); + + // Execute any scheduled draws to process deferred mouse events. + RunAllPendingInMessageLoop(); + } + // Make sure the capture window won't handle mouse events. + aura::Window* capture_window = drag_drop_tracker()->capture_window(); + ASSERT_TRUE(!!capture_window); + EXPECT_EQ("0x0", capture_window->bounds().size().ToString()); + EXPECT_EQ(NULL, + capture_window->GetEventHandlerForPoint(gfx::Point())); + EXPECT_EQ(NULL, + capture_window->GetTopWindowContainingPoint(gfx::Point())); + + aura::client::GetCaptureClient(widget->GetNativeView()->GetRootWindow())-> + SetCapture(NULL); + + EXPECT_TRUE(drag_drop_controller_->drag_start_received_); + EXPECT_EQ(num_drags - 1 - drag_view->VerticalDragThreshold(), + drag_drop_controller_->num_drag_updates_); + EXPECT_FALSE(drag_drop_controller_->drop_received_); + EXPECT_TRUE(drag_drop_controller_->drag_canceled_); + EXPECT_EQ(UTF8ToUTF16("I am being dragged"), + drag_drop_controller_->drag_string_); + + EXPECT_EQ(1, drag_view->num_drag_enters_); + EXPECT_EQ(num_drags - 1 - drag_view->VerticalDragThreshold(), + drag_view->num_drag_updates_); + EXPECT_EQ(0, drag_view->num_drops_); + EXPECT_EQ(1, drag_view->num_drag_exits_); + EXPECT_TRUE(drag_view->drag_done_received_); +} + TEST_F(DragDropControllerTest, TouchDragDropInMultipleWindows) { CommandLine::ForCurrentProcess()->AppendSwitch( switches::kEnableTouchDragDrop); diff --git a/ash/drag_drop/drag_drop_tracker.cc b/ash/drag_drop/drag_drop_tracker.cc index 269e2edb..9de4645 100644 --- a/ash/drag_drop/drag_drop_tracker.cc +++ b/ash/drag_drop/drag_drop_tracker.cc @@ -11,25 +11,28 @@ #include "ui/base/events/event.h" #include "ui/gfx/screen.h" +namespace ash { +namespace internal { + namespace { // Creates a window for capturing drag events. -aura::Window* CreateCaptureWindow(aura::RootWindow* context_root) { - aura::Window* window = new aura::Window(NULL); +aura::Window* CreateCaptureWindow(aura::RootWindow* context_root, + aura::WindowDelegate* delegate) { + aura::Window* window = new aura::Window(delegate); window->SetType(aura::client::WINDOW_TYPE_NORMAL); window->Init(ui::LAYER_NOT_DRAWN); window->SetDefaultParentByRootWindow(context_root, gfx::Rect()); window->Show(); + DCHECK(window->bounds().size().IsEmpty()); return window; } } // namespace -namespace ash { -namespace internal { - -DragDropTracker::DragDropTracker(aura::RootWindow* context_root) - : capture_window_(CreateCaptureWindow(context_root)) { +DragDropTracker::DragDropTracker(aura::RootWindow* context_root, + aura::WindowDelegate* delegate) + : capture_window_(CreateCaptureWindow(context_root, delegate)) { } DragDropTracker::~DragDropTracker() { diff --git a/ash/drag_drop/drag_drop_tracker.h b/ash/drag_drop/drag_drop_tracker.h index 22cf630..d7212ef 100644 --- a/ash/drag_drop/drag_drop_tracker.h +++ b/ash/drag_drop/drag_drop_tracker.h @@ -13,6 +13,7 @@ namespace aura { class RootWindow; class Window; +class WindowDelegate; } namespace ash { @@ -25,7 +26,8 @@ namespace internal { // is supported for now. class ASH_EXPORT DragDropTracker { public: - explicit DragDropTracker(aura::RootWindow* context_root); + DragDropTracker(aura::RootWindow* context_root, + aura::WindowDelegate* delegate); ~DragDropTracker(); aura::Window* capture_window() { return capture_window_.get(); } diff --git a/ash/drag_drop/drag_drop_tracker_unittest.cc b/ash/drag_drop/drag_drop_tracker_unittest.cc index 7113c22..acb87a4 100644 --- a/ash/drag_drop/drag_drop_tracker_unittest.cc +++ b/ash/drag_drop/drag_drop_tracker_unittest.cc @@ -32,7 +32,8 @@ class DragDropTrackerTest : public test::AshTestBase { static aura::Window* GetTarget(const gfx::Point& location) { scoped_ptr<internal::DragDropTracker> tracker( - new internal::DragDropTracker(Shell::GetPrimaryRootWindow())); + new internal::DragDropTracker(Shell::GetPrimaryRootWindow(), + NULL)); ui::MouseEvent e(ui::ET_MOUSE_DRAGGED, location, location, @@ -44,7 +45,8 @@ class DragDropTrackerTest : public test::AshTestBase { static ui::LocatedEvent* ConvertEvent(aura::Window* target, const ui::MouseEvent& event) { scoped_ptr<internal::DragDropTracker> tracker( - new internal::DragDropTracker(Shell::GetPrimaryRootWindow())); + new internal::DragDropTracker(Shell::GetPrimaryRootWindow(), + NULL)); ui::LocatedEvent* converted = tracker->ConvertEvent(target, event); return converted; } diff --git a/chrome/browser/chromeos/login/webui_screen_locker.cc b/chrome/browser/chromeos/login/webui_screen_locker.cc index c80ea5f..c99bc5a 100644 --- a/chrome/browser/chromeos/login/webui_screen_locker.cc +++ b/chrome/browser/chromeos/login/webui_screen_locker.cc @@ -25,6 +25,7 @@ #include "content/public/browser/notification_types.h" #include "content/public/browser/render_widget_host_view.h" #include "content/public/browser/web_ui.h" +#include "ui/aura/client/capture_client.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/x/x11_util.h" #include "ui/gfx/screen.h" @@ -273,8 +274,12 @@ void WebUIScreenLocker::OnLockWindowReady() { void WebUIScreenLocker::OnSessionStateEvent( ash::SessionStateObserver::EventType event) { - if (event == ash::SessionStateObserver::EVENT_LOCK_ANIMATION_FINISHED) + if (event == ash::SessionStateObserver::EVENT_LOCK_ANIMATION_FINISHED) { + // Release capture if any. + aura::client::GetCaptureClient(GetNativeWindow()->GetRootWindow())-> + SetCapture(NULL); GetWebUI()->CallJavascriptFunction("cr.ui.Oobe.animateOnceFullyDisplayed"); + } } //////////////////////////////////////////////////////////////////////////////// |