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 "base/win/win_util.h" 8 #include "ui/aura/window.h" 9 #include "ui/aura/window_tree_host.h" 10 #include "ui/base/dragdrop/drag_drop_types.h" 11 #include "ui/base/dragdrop/drop_target_event.h" 12 #include "ui/base/dragdrop/os_exchange_data_provider_win.h" 13 #include "ui/events/event_constants.h" 14 #include "ui/wm/public/drag_drop_client.h" 15 #include "ui/wm/public/drag_drop_delegate.h" 16 17 using aura::client::DragDropDelegate; 18 using ui::OSExchangeData; 19 using ui::OSExchangeDataProviderWin; 20 21 namespace views { 22 23 DesktopDropTargetWin::DesktopDropTargetWin(aura::Window* root_window, 24 HWND window) 25 : ui::DropTargetWin(window), 26 root_window_(root_window), 27 target_window_(NULL) { 28 } 29 30 DesktopDropTargetWin::~DesktopDropTargetWin() { 31 if (target_window_) 32 target_window_->RemoveObserver(this); 33 } 34 35 DWORD DesktopDropTargetWin::OnDragEnter(IDataObject* data_object, 36 DWORD key_state, 37 POINT position, 38 DWORD effect) { 39 scoped_ptr<OSExchangeData> data; 40 scoped_ptr<ui::DropTargetEvent> event; 41 DragDropDelegate* delegate; 42 // Translate will call OnDragEntered. 43 Translate(data_object, key_state, position, effect, &data, &event, &delegate); 44 return ui::DragDropTypes::DragOperationToDropEffect( 45 ui::DragDropTypes::DRAG_NONE); 46 } 47 48 DWORD DesktopDropTargetWin::OnDragOver(IDataObject* data_object, 49 DWORD key_state, 50 POINT position, 51 DWORD effect) { 52 int drag_operation = ui::DragDropTypes::DRAG_NONE; 53 scoped_ptr<OSExchangeData> data; 54 scoped_ptr<ui::DropTargetEvent> event; 55 DragDropDelegate* delegate; 56 Translate(data_object, key_state, position, effect, &data, &event, &delegate); 57 if (delegate) 58 drag_operation = delegate->OnDragUpdated(*event); 59 return ui::DragDropTypes::DragOperationToDropEffect(drag_operation); 60 } 61 62 void DesktopDropTargetWin::OnDragLeave(IDataObject* data_object) { 63 NotifyDragLeave(); 64 } 65 66 DWORD DesktopDropTargetWin::OnDrop(IDataObject* data_object, 67 DWORD key_state, 68 POINT position, 69 DWORD effect) { 70 int drag_operation = ui::DragDropTypes::DRAG_NONE; 71 scoped_ptr<OSExchangeData> data; 72 scoped_ptr<ui::DropTargetEvent> event; 73 DragDropDelegate* delegate; 74 Translate(data_object, key_state, position, effect, &data, &event, &delegate); 75 if (delegate) 76 drag_operation = delegate->OnPerformDrop(*event); 77 if (target_window_) { 78 target_window_->RemoveObserver(this); 79 target_window_ = NULL; 80 } 81 return ui::DragDropTypes::DragOperationToDropEffect(drag_operation); 82 } 83 84 void DesktopDropTargetWin::OnWindowDestroyed(aura::Window* window) { 85 DCHECK(window == target_window_); 86 target_window_ = NULL; 87 } 88 89 void DesktopDropTargetWin::Translate( 90 IDataObject* data_object, 91 DWORD key_state, 92 POINT position, 93 DWORD effect, 94 scoped_ptr<OSExchangeData>* data, 95 scoped_ptr<ui::DropTargetEvent>* event, 96 DragDropDelegate** delegate) { 97 gfx::Point location(position.x, position.y); 98 gfx::Point root_location = location; 99 root_window_->GetHost()->ConvertPointFromNativeScreen( 100 &root_location); 101 aura::Window* target_window = 102 root_window_->GetEventHandlerForPoint(root_location); 103 bool target_window_changed = false; 104 if (target_window != target_window_) { 105 if (target_window_) 106 NotifyDragLeave(); 107 target_window_ = target_window; 108 if (target_window_) 109 target_window_->AddObserver(this); 110 target_window_changed = true; 111 } 112 *delegate = NULL; 113 if (!target_window_) 114 return; 115 *delegate = aura::client::GetDragDropDelegate(target_window_); 116 if (!*delegate) 117 return; 118 119 data->reset(new OSExchangeData(new OSExchangeDataProviderWin(data_object))); 120 location = root_location; 121 aura::Window::ConvertPointToTarget(root_window_, target_window_, &location); 122 event->reset(new ui::DropTargetEvent( 123 *(data->get()), 124 location, 125 root_location, 126 ui::DragDropTypes::DropEffectToDragOperation(effect))); 127 int flags = 0; 128 flags |= base::win::IsAltPressed() ? ui::EF_ALT_DOWN : ui::EF_NONE; 129 flags |= base::win::IsShiftPressed() ? ui::EF_SHIFT_DOWN : ui::EF_NONE; 130 flags |= base::win::IsCtrlPressed() ? ui::EF_CONTROL_DOWN : ui::EF_NONE; 131 (*event)->set_flags(flags); 132 if (target_window_changed) 133 (*delegate)->OnDragEntered(*event->get()); 134 } 135 136 void DesktopDropTargetWin::NotifyDragLeave() { 137 if (!target_window_) 138 return; 139 DragDropDelegate* delegate = 140 aura::client::GetDragDropDelegate(target_window_); 141 if (delegate) 142 delegate->OnDragExited(); 143 target_window_->RemoveObserver(this); 144 target_window_ = NULL; 145 } 146 147 } // namespace views 148