Chromium Code Reviews| Index: ui/aura_shell/drag_drop_controller.cc |
| diff --git a/ui/aura_shell/drag_drop_controller.cc b/ui/aura_shell/drag_drop_controller.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..4b0344b69bf8d344c31d0db5b7bb8ebd52f42c34 |
| --- /dev/null |
| +++ b/ui/aura_shell/drag_drop_controller.cc |
| @@ -0,0 +1,185 @@ |
| +// 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/aura_constants.h" |
| +#include "ui/aura/client/window_drag_drop_delegate.h" |
| +#include "ui/aura/desktop.h" |
| +#include "ui/aura/window.h" |
| +#include "ui/aura_shell/desktop_event_filter.h" |
| +#include "ui/aura_shell/drag_image_view.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 "views/widget/native_widget_aura.h" |
| + |
| +namespace aura_shell { |
| +namespace internal { |
| + |
| +using aura::Desktop; |
| + |
| +namespace { |
| +aura::WindowDragDropDelegate* GetDragDropDelegate(aura::Window* window) { |
| + if (!window) |
| + return NULL; |
| + void* prop = window->GetProperty(aura::kDragDropDelegateKey); |
| + if (!prop) |
| + return NULL; |
| + return static_cast<aura::WindowDragDropDelegate*>(prop); |
| +} |
| + |
| +const gfx::Point kDragDropWidgetOffset(0, 0); |
| + |
| +} |
| + |
| +//////////////////////////////////////////////////////////////////////////////// |
| +// DragDropController, public: |
| + |
| +DragDropController::DragDropController() |
| + : aura::EventFilter(Desktop::GetInstance()), |
| + drag_image_(NULL), |
| + drag_data_(NULL), |
| + drag_operation_(0), |
| + dragged_window_(NULL), |
| + drag_drop_in_progress_(false), |
| + should_block_during_drag_drop_(true) { |
| + static_cast<DesktopEventFilter*>(Desktop::GetInstance()->event_filter())-> |
|
Ben Goodger (Google)
2011/11/16 20:39:49
Sync, and you can now just do:
Shell::GetInstance
varunjain
2011/11/16 22:55:20
Done.
|
| + AddFilter(this); |
| +} |
| + |
| +DragDropController::~DragDropController() { |
| + static_cast<DesktopEventFilter*>(Desktop::GetInstance()->event_filter())-> |
| + RemoveFilter(this); |
|
Ben Goodger (Google)
2011/11/16 20:39:49
ditto:
Shell::GetInstance()->RemoveDesktopEventFi
varunjain
2011/11/16 22:55:20
Done.
|
| + Cleanup(); |
| +} |
| + |
| +void DragDropController::StartDragAndDrop(const ui::OSExchangeData& data, |
| + int operation) { |
| + DCHECK(!drag_drop_in_progress_); |
| + aura::Window* capture_window = Desktop::GetInstance()->capture_window(); |
| + if (capture_window) |
| + Desktop::GetInstance()->ReleaseCapture(capture_window); |
| + drag_drop_in_progress_ = true; |
| + |
| + drag_data_ = &data; |
| + drag_operation_ = operation; |
| + gfx::Point location = Desktop::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_ = Desktop::GetInstance()->GetEventHandlerForPoint(location); |
| + |
| + if (should_block_during_drag_drop_) { |
| + MessageLoopForUI::current()->RunWithDispatcher( |
| + Desktop::GetInstance()->GetDispatcher()); |
| + } |
| +} |
| + |
| +void DragDropController::DragUpdate(aura::Window* target, |
| + const aura::MouseEvent& event) { |
| + aura::WindowDragDropDelegate* delegate = NULL; |
| + if (target != dragged_window_) { |
| + if ((delegate = GetDragDropDelegate(dragged_window_))) |
| + delegate->OnDragExited(); |
| + dragged_window_ = target; |
| + if ((delegate = GetDragDropDelegate(dragged_window_))) { |
| + aura::DropTargetEvent e(*drag_data_, event.location(), drag_operation_); |
| + if (delegate->CanDrop(e)) |
| + delegate->OnDragEntered(e); |
| + } |
| + } else { |
| + if ((delegate = GetDragDropDelegate(dragged_window_))) { |
| + aura::DropTargetEvent e(*drag_data_, event.location(), drag_operation_); |
| + delegate->OnDragUpdated(e); |
| + // TODO(varunjain): uncomment the following lines when cursor issue with |
| + // X for tests is fixed. |
| + // gfx::NativeCursor cursor = (op == ui::DragDropTypes::DRAG_NONE)? |
| + // aura::kCursorMove : aura::kCursorHand; |
| + // Desktop::GetInstance()->SetCursor(cursor); |
| + } |
| + } |
| + |
| + DCHECK(drag_image_.get()); |
| + if (drag_image_->IsVisible()) { |
| + drag_image_->SetScreenPosition(Desktop::GetInstance()-> |
| + last_mouse_location().Add(kDragDropWidgetOffset)); |
| + } |
| +} |
| + |
| +void DragDropController::Drop(aura::Window* target, |
| + const aura::MouseEvent& event) { |
| + aura::WindowDragDropDelegate* delegate = NULL; |
| + DCHECK(target == dragged_window_); |
| + if ((delegate = GetDragDropDelegate(dragged_window_))) { |
| + aura::DropTargetEvent e(*drag_data_, event.location(), drag_operation_); |
| + if (delegate->CanDrop(e)) |
| + delegate->OnPerformDrop(e); |
| + // TODO(varunjain): else 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(); |
| + if (should_block_during_drag_drop_) |
| + MessageLoop::current()->Quit(); |
| +} |
| + |
| +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_operation_ = 0; |
| + drag_drop_in_progress_ = false; |
| +} |
| + |
| +} // namespace internal |
| +} // namespace aura_shell |