1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "ui/views/widget/desktop_aura/desktop_drop_target_win.h" 6 7 #include "ui/aura/client/drag_drop_client.h" 8 #include "ui/aura/client/drag_drop_delegate.h" 9 #include "ui/aura/window.h" 10 #include "ui/aura/root_window.h" 11 #include "ui/base/dragdrop/drag_drop_types.h" 12 #include "ui/base/dragdrop/os_exchange_data_provider_win.h" 13 #include "ui/base/events/event.h" 14 15 using aura::client::DragDropDelegate; 16 using ui::OSExchangeData; 17 using ui::OSExchangeDataProviderWin; 18 19 namespace views { 20 21 DesktopDropTargetWin::DesktopDropTargetWin(aura::RootWindow* root_window, 22 HWND window) 23 : ui::DropTargetWin(window), 24 root_window_(root_window), 25 target_window_(NULL) { 26 } 27 28 DesktopDropTargetWin::~DesktopDropTargetWin() { 29 if (target_window_) 30 target_window_->RemoveObserver(this); 31 } 32 33 DWORD DesktopDropTargetWin::OnDragEnter(IDataObject* data_object, 34 DWORD key_state, 35 POINT position, 36 DWORD effect) { 37 scoped_ptr<OSExchangeData> data; 38 scoped_ptr<ui::DropTargetEvent> event; 39 DragDropDelegate* delegate; 40 // Translate will call OnDragEntered. 41 Translate(data_object, key_state, position, effect, &data, &event, &delegate); 42 return ui::DragDropTypes::DragOperationToDropEffect( 43 ui::DragDropTypes::DRAG_NONE); 44 } 45 46 DWORD DesktopDropTargetWin::OnDragOver(IDataObject* data_object, 47 DWORD key_state, 48 POINT position, 49 DWORD effect) { 50 int drag_operation = ui::DragDropTypes::DRAG_NONE; 51 scoped_ptr<OSExchangeData> data; 52 scoped_ptr<ui::DropTargetEvent> event; 53 DragDropDelegate* delegate; 54 Translate(data_object, key_state, position, effect, &data, &event, &delegate); 55 if (delegate) 56 drag_operation = delegate->OnDragUpdated(*event); 57 return ui::DragDropTypes::DragOperationToDropEffect(drag_operation); 58 } 59 60 void DesktopDropTargetWin::OnDragLeave(IDataObject* data_object) { 61 NotifyDragLeave(); 62 } 63 64 DWORD DesktopDropTargetWin::OnDrop(IDataObject* data_object, 65 DWORD key_state, 66 POINT position, 67 DWORD effect) { 68 int drag_operation = ui::DragDropTypes::DRAG_NONE; 69 scoped_ptr<OSExchangeData> data; 70 scoped_ptr<ui::DropTargetEvent> event; 71 DragDropDelegate* delegate; 72 Translate(data_object, key_state, position, effect, &data, &event, &delegate); 73 if (delegate) 74 drag_operation = delegate->OnPerformDrop(*event); 75 if (target_window_) { 76 target_window_->RemoveObserver(this); 77 target_window_ = NULL; 78 } 79 return ui::DragDropTypes::DragOperationToDropEffect(drag_operation); 80 } 81 82 void DesktopDropTargetWin::OnWindowDestroyed(aura::Window* window) { 83 DCHECK(window == target_window_); 84 target_window_ = NULL; 85 } 86 87 void DesktopDropTargetWin::Translate( 88 IDataObject* data_object, 89 DWORD key_state, 90 POINT position, 91 DWORD effect, 92 scoped_ptr<OSExchangeData>* data, 93 scoped_ptr<ui::DropTargetEvent>* event, 94 DragDropDelegate** delegate) { 95 gfx::Point location(position.x, position.y); 96 gfx::Point root_location = location; 97 root_window_->ConvertPointFromNativeScreen(&root_location); 98 aura::Window* target_window = 99 root_window_->GetEventHandlerForPoint(root_location); 100 bool target_window_changed = false; 101 if (target_window != target_window_) { 102 if (target_window_) 103 NotifyDragLeave(); 104 target_window_ = target_window; 105 if (target_window_) 106 target_window_->AddObserver(this); 107 target_window_changed = true; 108 } 109 *delegate = NULL; 110 if (!target_window_) 111 return; 112 *delegate = aura::client::GetDragDropDelegate(target_window_); 113 if (!*delegate) 114 return; 115 116 data->reset(new OSExchangeData(new OSExchangeDataProviderWin(data_object))); 117 location = root_location; 118 aura::Window::ConvertPointToTarget(root_window_, target_window_, &location); 119 event->reset(new ui::DropTargetEvent( 120 *(data->get()), 121 location, 122 root_location, 123 ui::DragDropTypes::DropEffectToDragOperation(effect))); 124 if (target_window_changed) 125 (*delegate)->OnDragEntered(*event->get()); 126 } 127 128 void DesktopDropTargetWin::NotifyDragLeave() { 129 if (!target_window_) 130 return; 131 DragDropDelegate* delegate = 132 aura::client::GetDragDropDelegate(target_window_); 133 if (delegate) 134 delegate->OnDragExited(); 135 target_window_->RemoveObserver(this); 136 target_window_ = NULL; 137 } 138 139 } // namespace views 140