// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "ui/aura_shell/drag_drop_controller.h" #include "base/message_loop.h" #include "ui/aura/client/drag_drop_delegate.h" #include "ui/aura/root_window.h" #include "ui/aura/window.h" #include "ui/aura_shell/drag_image_view.h" #include "ui/aura_shell/shell.h" #include "ui/base/dragdrop/drag_drop_types.h" #include "ui/base/dragdrop/os_exchange_data_provider_aura.h" #include "ui/gfx/point.h" #include "ui/gfx/rect.h" #include "ui/views/widget/native_widget_aura.h" namespace aura_shell { namespace internal { using aura::RootWindow; namespace { const gfx::Point kDragDropWidgetOffset(0, 0); } //////////////////////////////////////////////////////////////////////////////// // DragDropController, public: DragDropController::DragDropController() : aura::EventFilter(RootWindow::GetInstance()), drag_image_(NULL), drag_data_(NULL), drag_operation_(0), dragged_window_(NULL), drag_drop_in_progress_(false), should_block_during_drag_drop_(true) { Shell::GetInstance()->AddRootWindowEventFilter(this); aura::client::SetDragDropClient(this); } DragDropController::~DragDropController() { Shell::GetInstance()->RemoveRootWindowEventFilter(this); Cleanup(); } int DragDropController::StartDragAndDrop(const ui::OSExchangeData& data, int operation) { DCHECK(!drag_drop_in_progress_); aura::Window* capture_window = RootWindow::GetInstance()->capture_window(); if (capture_window) RootWindow::GetInstance()->ReleaseCapture(capture_window); drag_drop_in_progress_ = true; drag_data_ = &data; drag_operation_ = operation; gfx::Point location = RootWindow::GetInstance()->last_mouse_location(); const ui::OSExchangeDataProviderAura& provider = static_cast<const ui::OSExchangeDataProviderAura&>(data.provider()); drag_image_.reset(new DragImageView); drag_image_->SetImage(provider.drag_image()); drag_image_->SetScreenBounds(gfx::Rect(location.Add(kDragDropWidgetOffset), drag_image_->GetPreferredSize())); drag_image_->SetWidgetVisible(true); dragged_window_ = NULL; if (should_block_during_drag_drop_) { MessageLoopForUI::current()->RunWithDispatcher( RootWindow::GetInstance()->GetDispatcher()); } return drag_operation_; } void DragDropController::DragUpdate(aura::Window* target, const aura::MouseEvent& event) { aura::client::DragDropDelegate* delegate = NULL; if (target != dragged_window_) { if (dragged_window_ && (delegate = aura::client::GetDragDropDelegate(dragged_window_))) { delegate->OnDragExited(); } dragged_window_ = target; if ((delegate = aura::client::GetDragDropDelegate(dragged_window_))) { aura::DropTargetEvent e(*drag_data_, event.location(), drag_operation_); delegate->OnDragEntered(e); } } else { if ((delegate = aura::client::GetDragDropDelegate(dragged_window_))) { aura::DropTargetEvent e(*drag_data_, event.location(), drag_operation_); int op = delegate->OnDragUpdated(e); gfx::NativeCursor cursor = (op == ui::DragDropTypes::DRAG_NONE)? aura::kCursorMove : aura::kCursorHand; RootWindow::GetInstance()->SetCursor(cursor); } } DCHECK(drag_image_.get()); if (drag_image_->visible()) { drag_image_->SetScreenPosition(RootWindow::GetInstance()-> last_mouse_location().Add(kDragDropWidgetOffset)); } } void DragDropController::Drop(aura::Window* target, const aura::MouseEvent& event) { aura::client::DragDropDelegate* delegate = NULL; DCHECK(target == dragged_window_); if ((delegate = aura::client::GetDragDropDelegate(dragged_window_))) { aura::DropTargetEvent e(*drag_data_, event.location(), drag_operation_); drag_operation_ = delegate->OnPerformDrop(e); // TODO(varunjain): if drag_op is 0, do drag widget flying back animation } Cleanup(); if (should_block_during_drag_drop_) MessageLoop::current()->Quit(); } void DragDropController::DragCancel() { // TODO(varunjain): Do drag widget flying back animation Cleanup(); drag_operation_ = 0; if (should_block_during_drag_drop_) MessageLoop::current()->Quit(); } bool DragDropController::IsDragDropInProgress() { return drag_drop_in_progress_; } bool DragDropController::PreHandleKeyEvent(aura::Window* target, aura::KeyEvent* event) { return false; } bool DragDropController::PreHandleMouseEvent(aura::Window* target, aura::MouseEvent* event) { if (!drag_drop_in_progress_) return false; switch (event->type()) { case ui::ET_MOUSE_DRAGGED: DragUpdate(target, *event); break; case ui::ET_MOUSE_RELEASED: Drop(target, *event); break; case ui::ET_MOUSE_EXITED: DragCancel(); break; default: NOTREACHED(); break; } return true; } ui::TouchStatus DragDropController::PreHandleTouchEvent( aura::Window* target, aura::TouchEvent* event) { return ui::TOUCH_STATUS_UNKNOWN; } //////////////////////////////////////////////////////////////////////////////// // DragDropController, private: void DragDropController::Cleanup() { drag_image_.reset(); drag_data_ = NULL; drag_drop_in_progress_ = false; } } // namespace internal } // namespace aura_shell