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