diff options
Diffstat (limited to 'ash/drag_drop/drag_drop_controller.cc')
-rw-r--r-- | ash/drag_drop/drag_drop_controller.cc | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/ash/drag_drop/drag_drop_controller.cc b/ash/drag_drop/drag_drop_controller.cc new file mode 100644 index 0000000..b316d14 --- /dev/null +++ b/ash/drag_drop/drag_drop_controller.cc @@ -0,0 +1,176 @@ +// 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 "ash/drag_drop/drag_drop_controller.h" + +#include "ash/drag_drop/drag_image_view.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/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 |