Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / ui / views / widget / desktop_aura / desktop_drop_target_win.cc
blob6931bd5186338255f1c7d5476861b79c7a822f4f
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.
5 #include "ui/views/widget/desktop_aura/desktop_drop_target_win.h"
7 #include "base/metrics/histogram.h"
8 #include "base/win/win_util.h"
9 #include "ui/aura/window.h"
10 #include "ui/aura/window_tree_host.h"
11 #include "ui/base/dragdrop/drag_drop_types.h"
12 #include "ui/base/dragdrop/drop_target_event.h"
13 #include "ui/base/dragdrop/os_exchange_data_provider_win.h"
14 #include "ui/events/event_constants.h"
15 #include "ui/wm/public/drag_drop_client.h"
16 #include "ui/wm/public/drag_drop_delegate.h"
18 using aura::client::DragDropClient;
19 using aura::client::DragDropDelegate;
20 using ui::OSExchangeData;
21 using ui::OSExchangeDataProviderWin;
23 namespace {
25 int ConvertKeyStateToAuraEventFlags(DWORD key_state)
27 int flags = 0;
29 if (key_state & MK_CONTROL)
30 flags |= ui::EF_CONTROL_DOWN;
31 if (key_state & MK_ALT)
32 flags |= ui::EF_ALT_DOWN;
33 if (key_state & MK_SHIFT)
34 flags |= ui::EF_SHIFT_DOWN;
35 if (key_state & MK_LBUTTON)
36 flags |= ui::EF_LEFT_MOUSE_BUTTON;
37 if (key_state & MK_MBUTTON)
38 flags |= ui::EF_MIDDLE_MOUSE_BUTTON;
39 if (key_state & MK_RBUTTON)
40 flags |= ui::EF_RIGHT_MOUSE_BUTTON;
42 return flags;
45 } // namespace
47 namespace views {
49 DesktopDropTargetWin::DesktopDropTargetWin(aura::Window* root_window,
50 HWND window)
51 : ui::DropTargetWin(window),
52 root_window_(root_window),
53 target_window_(NULL) {
56 DesktopDropTargetWin::~DesktopDropTargetWin() {
57 if (target_window_)
58 target_window_->RemoveObserver(this);
61 DWORD DesktopDropTargetWin::OnDragEnter(IDataObject* data_object,
62 DWORD key_state,
63 POINT position,
64 DWORD effect) {
65 scoped_ptr<OSExchangeData> data;
66 scoped_ptr<ui::DropTargetEvent> event;
67 DragDropDelegate* delegate;
68 // Translate will call OnDragEntered.
69 Translate(data_object, key_state, position, effect, &data, &event, &delegate);
70 return ui::DragDropTypes::DragOperationToDropEffect(
71 ui::DragDropTypes::DRAG_NONE);
74 DWORD DesktopDropTargetWin::OnDragOver(IDataObject* data_object,
75 DWORD key_state,
76 POINT position,
77 DWORD effect) {
78 int drag_operation = ui::DragDropTypes::DRAG_NONE;
79 scoped_ptr<OSExchangeData> data;
80 scoped_ptr<ui::DropTargetEvent> event;
81 DragDropDelegate* delegate;
82 Translate(data_object, key_state, position, effect, &data, &event, &delegate);
83 if (delegate)
84 drag_operation = delegate->OnDragUpdated(*event);
85 return ui::DragDropTypes::DragOperationToDropEffect(drag_operation);
88 void DesktopDropTargetWin::OnDragLeave(IDataObject* data_object) {
89 NotifyDragLeave();
92 DWORD DesktopDropTargetWin::OnDrop(IDataObject* data_object,
93 DWORD key_state,
94 POINT position,
95 DWORD effect) {
96 int drag_operation = ui::DragDropTypes::DRAG_NONE;
97 scoped_ptr<OSExchangeData> data;
98 scoped_ptr<ui::DropTargetEvent> event;
99 DragDropDelegate* delegate;
100 Translate(data_object, key_state, position, effect, &data, &event, &delegate);
101 if (delegate) {
102 drag_operation = delegate->OnPerformDrop(*event);
103 DragDropClient* client = aura::client::GetDragDropClient(root_window_);
104 if (client && !client->IsDragDropInProgress() &&
105 drag_operation != ui::DragDropTypes::DRAG_NONE) {
106 UMA_HISTOGRAM_COUNTS("Event.DragDrop.ExternalOriginDrop", 1);
109 if (target_window_) {
110 target_window_->RemoveObserver(this);
111 target_window_ = NULL;
113 return ui::DragDropTypes::DragOperationToDropEffect(drag_operation);
116 void DesktopDropTargetWin::OnWindowDestroyed(aura::Window* window) {
117 DCHECK(window == target_window_);
118 target_window_ = NULL;
121 void DesktopDropTargetWin::Translate(
122 IDataObject* data_object,
123 DWORD key_state,
124 POINT position,
125 DWORD effect,
126 scoped_ptr<OSExchangeData>* data,
127 scoped_ptr<ui::DropTargetEvent>* event,
128 DragDropDelegate** delegate) {
129 gfx::Point location(position.x, position.y);
130 gfx::Point root_location = location;
131 root_window_->GetHost()->ConvertPointFromNativeScreen(
132 &root_location);
133 aura::Window* target_window =
134 root_window_->GetEventHandlerForPoint(root_location);
135 bool target_window_changed = false;
136 if (target_window != target_window_) {
137 if (target_window_)
138 NotifyDragLeave();
139 target_window_ = target_window;
140 if (target_window_)
141 target_window_->AddObserver(this);
142 target_window_changed = true;
144 *delegate = NULL;
145 if (!target_window_)
146 return;
147 *delegate = aura::client::GetDragDropDelegate(target_window_);
148 if (!*delegate)
149 return;
151 data->reset(new OSExchangeData(new OSExchangeDataProviderWin(data_object)));
152 location = root_location;
153 aura::Window::ConvertPointToTarget(root_window_, target_window_, &location);
154 event->reset(new ui::DropTargetEvent(
155 *(data->get()),
156 location,
157 root_location,
158 ui::DragDropTypes::DropEffectToDragOperation(effect)));
159 (*event)->set_flags(ConvertKeyStateToAuraEventFlags(key_state));
160 if (target_window_changed)
161 (*delegate)->OnDragEntered(*event->get());
164 void DesktopDropTargetWin::NotifyDragLeave() {
165 if (!target_window_)
166 return;
167 DragDropDelegate* delegate =
168 aura::client::GetDragDropDelegate(target_window_);
169 if (delegate)
170 delegate->OnDragExited();
171 target_window_->RemoveObserver(this);
172 target_window_ = NULL;
175 } // namespace views