15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/drag_drop/drag_drop_controller.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/drag_drop/drag_drop_tracker.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/drag_drop/drag_image_view.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/shell.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/wm/coordinate_conversion.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h"
127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/message_loop/message_loop.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/run_loop.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/client/capture_client.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/client/drag_drop_delegate.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/env.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/root_window.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/window.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/aura/window_delegate.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/dragdrop/drag_drop_types.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/base/dragdrop/os_exchange_data.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/base/hit_test.h"
23d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/events/event.h"
24d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/events/event_utils.h"
25d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/gfx/animation/linear_animation.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/path.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/point.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/rect.h"
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/rect_conversions.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/views_delegate.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/native_widget_aura.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ash {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace internal {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The duration of the drag cancel animation in millisecond.
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kCancelAnimationDuration = 250;
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kTouchCancelAnimationDuration = 20;
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The frame rate of the drag cancel animation in hertz.
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kCancelAnimationFrameRate = 60;
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// For touch initiated dragging, we scale and shift drag image by the following:
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const float kTouchDragImageScale = 1.2f;
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const int kTouchDragImageVerticalOffset = -25;
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Adjusts the drag image bounds such that the new bounds are scaled by |scale|
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// and translated by the |drag_image_offset| and and additional
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |vertical_offset|.
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)gfx::Rect AdjustDragImageBoundsForScaleAndOffset(
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const gfx::Rect& drag_image_bounds,
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int vertical_offset,
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    float scale,
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    gfx::Vector2d* drag_image_offset) {
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::PointF final_origin = drag_image_bounds.origin();
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::SizeF final_size = drag_image_bounds.size();
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  final_size.Scale(scale);
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  drag_image_offset->set_x(drag_image_offset->x() * scale);
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  drag_image_offset->set_y(drag_image_offset->y() * scale);
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  float total_x_offset = drag_image_offset->x();
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  float total_y_offset = drag_image_offset->y() - vertical_offset;
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  final_origin.Offset(-total_x_offset, -total_y_offset);
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return gfx::ToEnclosingRect(gfx::RectF(final_origin, final_size));
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DispatchGestureEndToWindow(aura::Window* window) {
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (window && window->delegate()) {
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ui::GestureEvent gesture_end(
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        ui::ET_GESTURE_END,
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        0,
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        0,
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        0,
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        ui::EventTimeForNow(),
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        ui::GestureEventDetails(ui::ET_GESTURE_END, 0, 0),
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        0);
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    window->delegate()->OnGestureEvent(&gesture_end);
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class DragDropTrackerDelegate : public aura::WindowDelegate {
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  explicit DragDropTrackerDelegate(DragDropController* controller)
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : drag_drop_controller_(controller) {}
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~DragDropTrackerDelegate() {}
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Overridden from WindowDelegate:
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual gfx::Size GetMinimumSize() const OVERRIDE {
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return gfx::Size();
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual gfx::Size GetMaximumSize() const OVERRIDE {
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return gfx::Size();
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnBoundsChanged(const gfx::Rect& old_bounds,
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               const gfx::Rect& new_bounds) OVERRIDE {}
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual gfx::NativeCursor GetCursor(const gfx::Point& point) OVERRIDE {
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return gfx::kNullCursor;
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual int GetNonClientComponent(const gfx::Point& point) const OVERRIDE {
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return HTCAPTION;
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool ShouldDescendIntoChildForEventHandling(
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      aura::Window* child,
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const gfx::Point& location) OVERRIDE {
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool CanFocus() OVERRIDE { return true; }
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnCaptureLost() OVERRIDE {
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (drag_drop_controller_->IsDragDropInProgress())
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      drag_drop_controller_->DragCancel();
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE {}
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnWindowDestroying() OVERRIDE {}
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnWindowDestroyed() OVERRIDE {}
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE {}
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool HasHitTestMask() const OVERRIDE {
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void GetHitTestMask(gfx::Path* mask) const OVERRIDE {
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(mask->isEmpty());
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
12658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  virtual void DidRecreateLayer(ui::Layer* old_layer,
12758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                ui::Layer* new_layer) OVERRIDE {}
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DragDropController* drag_drop_controller_;
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(DragDropTrackerDelegate);
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DragDropController, public:
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DragDropController::DragDropController()
1397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    : drag_data_(NULL),
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      drag_operation_(0),
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      drag_window_(NULL),
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      drag_source_window_(NULL),
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      should_block_during_drag_drop_(true),
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      drag_drop_window_delegate_(new DragDropTrackerDelegate(this)),
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      current_drag_event_source_(ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE),
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      weak_factory_(this) {
147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Shell::GetInstance()->PrependPreTargetHandler(this);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DragDropController::~DragDropController() {
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Shell::GetInstance()->RemovePreTargetHandler(this);
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Cleanup();
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (cancel_animation_)
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    cancel_animation_->End();
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (drag_image_)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    drag_image_.reset();
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int DragDropController::StartDragAndDrop(
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ui::OSExchangeData& data,
1611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    aura::Window* root_window,
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    aura::Window* source_window,
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Point& root_location,
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int operation,
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ui::DragDropTypes::DragEventSource source) {
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (IsDragDropInProgress())
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return 0;
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const ui::OSExchangeData::Provider* provider = &data.provider();
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We do not support touch drag/drop without a drag image.
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (source == ui::DragDropTypes::DRAG_EVENT_SOURCE_TOUCH &&
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      provider->GetDragImage().size().IsEmpty())
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return 0;
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  current_drag_event_source_ = source;
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DragDropTracker* tracker =
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new DragDropTracker(root_window, drag_drop_window_delegate_.get());
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (source == ui::DragDropTypes::DRAG_EVENT_SOURCE_TOUCH) {
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // We need to transfer the current gesture sequence and the GR's touch event
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // queue to the |drag_drop_tracker_|'s capture window so that when it takes
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // capture, it still gets a valid gesture state.
1828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    ui::GestureRecognizer::Get()->TransferEventsTo(source_window,
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        tracker->capture_window());
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // We also send a gesture end to the source window so it can clear state.
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // TODO(varunjain): Remove this whole block when gesture sequence
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // transferring is properly done in the GR (http://crbug.com/160558)
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DispatchGestureEndToWindow(source_window);
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  tracker->TakeCapture();
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  drag_drop_tracker_.reset(tracker);
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  drag_source_window_ = source_window;
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (drag_source_window_)
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    drag_source_window_->AddObserver(this);
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pending_long_tap_.reset();
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  drag_data_ = &data;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  drag_operation_ = operation;
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  float drag_image_scale = 1;
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int drag_image_vertical_offset = 0;
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (source == ui::DragDropTypes::DRAG_EVENT_SOURCE_TOUCH) {
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    drag_image_scale = kTouchDragImageScale;
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    drag_image_vertical_offset = kTouchDragImageVerticalOffset;
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Point start_location = root_location;
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ash::wm::ConvertPointToScreen(root_window, &start_location);
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  drag_image_final_bounds_for_cancel_animation_ = gfx::Rect(
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      start_location - provider->GetDragImageOffset(),
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      provider->GetDragImage().size());
2104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  drag_image_.reset(new DragImageView(source_window->GetRootWindow(), source));
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  drag_image_->SetImage(provider->GetDragImage());
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  drag_image_offset_ = provider->GetDragImageOffset();
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect drag_image_bounds(start_location, drag_image_->GetPreferredSize());
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  drag_image_bounds = AdjustDragImageBoundsForScaleAndOffset(drag_image_bounds,
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      drag_image_vertical_offset, drag_image_scale, &drag_image_offset_);
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  drag_image_->SetBoundsInScreen(drag_image_bounds);
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  drag_image_->SetWidgetVisible(true);
2184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (source == ui::DragDropTypes::DRAG_EVENT_SOURCE_TOUCH) {
2194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    drag_image_->SetTouchDragOperationHintPosition(gfx::Point(
2204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        drag_image_offset_.x(),
2214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        drag_image_offset_.y() + drag_image_vertical_offset));
2224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  drag_window_ = NULL;
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Ends cancel animation if it's in progress.
227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (cancel_animation_)
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    cancel_animation_->End();
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (should_block_during_drag_drop_) {
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::RunLoop run_loop(aura::Env::GetInstance()->GetDispatcher());
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    quit_closure_ = run_loop.QuitClosure();
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::MessageLoopForUI* loop = base::MessageLoopForUI::current();
234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::MessageLoop::ScopedNestableTaskAllower allow_nested(loop);
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    run_loop.Run();
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!cancel_animation_.get() || !cancel_animation_->is_animating() ||
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      !pending_long_tap_.get()) {
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // If drag cancel animation is running, this cleanup is done when the
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // animation completes.
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (drag_source_window_)
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      drag_source_window_->RemoveObserver(this);
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    drag_source_window_ = NULL;
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return drag_operation_;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DragDropController::DragUpdate(aura::Window* target,
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    const ui::LocatedEvent& event) {
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aura::client::DragDropDelegate* delegate = NULL;
2534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  int op = ui::DragDropTypes::DRAG_NONE;
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (target != drag_window_) {
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (drag_window_) {
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if ((delegate = aura::client::GetDragDropDelegate(drag_window_)))
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        delegate->OnDragExited();
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (drag_window_ != drag_source_window_)
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        drag_window_->RemoveObserver(this);
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    drag_window_ = target;
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // We are already an observer of |drag_source_window_| so no need to add.
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (drag_window_ != drag_source_window_)
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      drag_window_->AddObserver(this);
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((delegate = aura::client::GetDragDropDelegate(drag_window_))) {
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ui::DropTargetEvent e(*drag_data_,
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            event.location(),
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            event.root_location(),
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            drag_operation_);
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      e.set_flags(event.flags());
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delegate->OnDragEntered(e);
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((delegate = aura::client::GetDragDropDelegate(drag_window_))) {
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ui::DropTargetEvent e(*drag_data_,
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            event.location(),
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            event.root_location(),
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            drag_operation_);
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      e.set_flags(event.flags());
2804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      op = delegate->OnDragUpdated(e);
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      gfx::NativeCursor cursor = ui::kCursorNoDrop;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (op & ui::DragDropTypes::DRAG_COPY)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        cursor = ui::kCursorCopy;
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else if (op & ui::DragDropTypes::DRAG_LINK)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        cursor = ui::kCursorAlias;
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else if (op & ui::DragDropTypes::DRAG_MOVE)
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        cursor = ui::kCursorGrabbing;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ash::Shell::GetInstance()->cursor_manager()->SetCursor(cursor);
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(drag_image_.get());
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (drag_image_->visible()) {
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Point root_location_in_screen = event.root_location();
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ash::wm::ConvertPointToScreen(target->GetRootWindow(),
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  &root_location_in_screen);
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    drag_image_->SetScreenPosition(
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        root_location_in_screen - drag_image_offset_);
2994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    drag_image_->SetTouchDragOperation(op);
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DragDropController::Drop(aura::Window* target,
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              const ui::LocatedEvent& event) {
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ash::Shell::GetInstance()->cursor_manager()->SetCursor(ui::kCursorPointer);
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aura::client::DragDropDelegate* delegate = NULL;
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We must guarantee that a target gets a OnDragEntered before Drop. WebKit
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // depends on not getting a Drop without DragEnter. This behavior is
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // consistent with drag/drop on other platforms.
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (target != drag_window_)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DragUpdate(target, event);
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(target == drag_window_);
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((delegate = aura::client::GetDragDropDelegate(target))) {
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ui::DropTargetEvent e(
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *drag_data_, event.location(), event.root_location(), drag_operation_);
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    e.set_flags(event.flags());
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    drag_operation_ = delegate->OnPerformDrop(e);
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (drag_operation_ == 0)
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      StartCanceledAnimation(kCancelAnimationDuration);
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      drag_image_.reset();
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    drag_image_.reset();
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Cleanup();
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (should_block_during_drag_drop_)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    quit_closure_.Run();
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DragDropController::DragCancel() {
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DoDragCancel(kCancelAnimationDuration);
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DragDropController::IsDragDropInProgress() {
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !!drag_drop_tracker_.get();
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DragDropController::OnKeyEvent(ui::KeyEvent* event) {
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsDragDropInProgress() && event->key_code() == ui::VKEY_ESCAPE) {
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DragCancel();
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    event->StopPropagation();
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DragDropController::OnMouseEvent(ui::MouseEvent* event) {
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsDragDropInProgress())
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If current drag session was not started by mouse, dont process this mouse
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // event, but consume it so it does not interfere with current drag session.
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (current_drag_event_source_ !=
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE) {
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    event->StopPropagation();
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aura::Window* translated_target = drag_drop_tracker_->GetTarget(*event);
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!translated_target) {
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DragCancel();
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    event->StopPropagation();
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<ui::LocatedEvent> translated_event(
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      drag_drop_tracker_->ConvertEvent(translated_target, *event));
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (translated_event->type()) {
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::ET_MOUSE_DRAGGED:
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DragUpdate(translated_target, *translated_event.get());
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::ET_MOUSE_RELEASED:
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Drop(translated_target, *translated_event.get());
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We could also reach here because RootWindow may sometimes generate a
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // bunch of fake mouse events
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // (aura::RootWindow::PostMouseMoveEventAfterWindowChange).
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  event->StopPropagation();
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DragDropController::OnTouchEvent(ui::TouchEvent* event) {
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsDragDropInProgress())
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If current drag session was not started by touch, dont process this touch
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // event, but consume it so it does not interfere with current drag session.
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (current_drag_event_source_ != ui::DragDropTypes::DRAG_EVENT_SOURCE_TOUCH)
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    event->StopPropagation();
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (event->handled())
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (event->type() == ui::ET_TOUCH_CANCELLED)
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DragCancel();
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DragDropController::OnGestureEvent(ui::GestureEvent* event) {
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!IsDragDropInProgress())
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
40490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // No one else should handle gesture events when in drag drop. Note that it is
40590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // not enough to just set ER_HANDLED because the dispatcher only stops
40690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // dispatching when the event has ER_CONSUMED. If we just set ER_HANDLED, the
40790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // event will still be dispatched to other handlers and we depend on
40890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // individual handlers' kindness to not touch events marked ER_HANDLED (not
40990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // all handlers are so kind and may cause bugs like crbug.com/236493).
41090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  event->StopPropagation();
41190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
41290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // If current drag session was not started by touch, dont process this event.
41390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (current_drag_event_source_ != ui::DragDropTypes::DRAG_EVENT_SOURCE_TOUCH)
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Apply kTouchDragImageVerticalOffset to the location.
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ui::GestureEvent touch_offset_event(*event,
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      static_cast<aura::Window*>(NULL),
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      static_cast<aura::Window*>(NULL));
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Point touch_offset_location = touch_offset_event.location();
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Point touch_offset_root_location = touch_offset_event.root_location();
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  touch_offset_location.Offset(0, kTouchDragImageVerticalOffset);
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  touch_offset_root_location.Offset(0, kTouchDragImageVerticalOffset);
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  touch_offset_event.set_location(touch_offset_location);
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  touch_offset_event.set_root_location(touch_offset_root_location);
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  aura::Window* translated_target =
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      drag_drop_tracker_->GetTarget(touch_offset_event);
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!translated_target) {
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DragCancel();
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    event->SetHandled();
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<ui::LocatedEvent> translated_event(
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      drag_drop_tracker_->ConvertEvent(translated_target, touch_offset_event));
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (event->type()) {
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case ui::ET_GESTURE_SCROLL_UPDATE:
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DragUpdate(translated_target, *translated_event.get());
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case ui::ET_GESTURE_SCROLL_END:
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Drop(translated_target, *translated_event.get());
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case ui::ET_SCROLL_FLING_START:
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case ui::ET_GESTURE_LONG_TAP:
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Ideally we would want to just forward this long tap event to the
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // |drag_source_window_|. However, webkit does not accept events while a
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // drag drop is still in progress. The drag drop ends only when the nested
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // message loop ends. Due to this stupidity, we have to defer forwarding
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // the long tap.
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      pending_long_tap_.reset(
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          new ui::GestureEvent(*event,
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              static_cast<aura::Window*>(drag_drop_tracker_->capture_window()),
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              static_cast<aura::Window*>(drag_source_window_)));
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DoDragCancel(kTouchCancelAnimationDuration);
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  event->SetHandled();
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DragDropController::OnWindowDestroyed(aura::Window* window) {
464a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (drag_window_ == window)
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    drag_window_ = NULL;
466a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (drag_source_window_ == window)
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    drag_source_window_ = NULL;
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// DragDropController, protected:
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
473d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)gfx::LinearAnimation* DragDropController::CreateCancelAnimation(
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int duration,
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int frame_rate,
476d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    gfx::AnimationDelegate* delegate) {
477d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return new gfx::LinearAnimation(duration, frame_rate, delegate);
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DragDropController, private:
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
483d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void DragDropController::AnimationEnded(const gfx::Animation* animation) {
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  cancel_animation_.reset();
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // By the time we finish animation, another drag/drop session may have
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // started. We do not want to destroy the drag image in that case.
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsDragDropInProgress())
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    drag_image_.reset();
490c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (pending_long_tap_) {
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // If not in a nested message loop, we can forward the long tap right now.
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!should_block_during_drag_drop_)
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ForwardPendingLongTap();
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    else {
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // See comment about this in OnGestureEvent().
496c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::MessageLoopForUI::current()->PostTask(
497c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          FROM_HERE,
498c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          base::Bind(&DragDropController::ForwardPendingLongTap,
499c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     weak_factory_.GetWeakPtr()));
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DragDropController::DoDragCancel(int drag_cancel_animation_duration_ms) {
5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ash::Shell::GetInstance()->cursor_manager()->SetCursor(ui::kCursorPointer);
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // |drag_window_| can be NULL if we have just started the drag and have not
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // received any DragUpdates, or, if the |drag_window_| gets destroyed during
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // a drag/drop.
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  aura::client::DragDropDelegate* delegate = drag_window_?
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      aura::client::GetDragDropDelegate(drag_window_) : NULL;
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (delegate)
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    delegate->OnDragExited();
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Cleanup();
5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  drag_operation_ = 0;
5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StartCanceledAnimation(drag_cancel_animation_duration_ms);
5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (should_block_during_drag_drop_)
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    quit_closure_.Run();
5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
522d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void DragDropController::AnimationProgressed(const gfx::Animation* animation) {
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect current_bounds = animation->CurrentValueBetween(
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      drag_image_initial_bounds_for_cancel_animation_,
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      drag_image_final_bounds_for_cancel_animation_);
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  drag_image_->SetBoundsInScreen(current_bounds);
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
529d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void DragDropController::AnimationCanceled(const gfx::Animation* animation) {
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AnimationEnded(animation);
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DragDropController::StartCanceledAnimation(int animation_duration_ms) {
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(drag_image_.get());
5354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  drag_image_->SetTouchDragOperationHintOff();
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  drag_image_initial_bounds_for_cancel_animation_ =
5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      drag_image_->GetBoundsInScreen();
5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  cancel_animation_.reset(CreateCancelAnimation(animation_duration_ms,
5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                kCancelAnimationFrameRate,
5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                this));
5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  cancel_animation_->Start();
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DragDropController::ForwardPendingLongTap() {
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (drag_source_window_ && drag_source_window_->delegate()) {
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    drag_source_window_->delegate()->OnGestureEvent(pending_long_tap_.get());
5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DispatchGestureEndToWindow(drag_source_window_);
5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pending_long_tap_.reset();
5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (drag_source_window_)
5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    drag_source_window_->RemoveObserver(this);
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  drag_source_window_ = NULL;
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DragDropController::Cleanup() {
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (drag_window_)
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    drag_window_->RemoveObserver(this);
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  drag_window_ = NULL;
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  drag_data_ = NULL;
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cleanup can be called again while deleting DragDropTracker, so use Pass
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // instead of reset to avoid double free.
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  drag_drop_tracker_.Pass();
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace internal
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace ash
567