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
;
25 int ConvertKeyStateToAuraEventFlags(DWORD key_state
)
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
;
49 DesktopDropTargetWin::DesktopDropTargetWin(aura::Window
* root_window
,
51 : ui::DropTargetWin(window
),
52 root_window_(root_window
),
53 target_window_(NULL
) {
56 DesktopDropTargetWin::~DesktopDropTargetWin() {
58 target_window_
->RemoveObserver(this);
61 DWORD
DesktopDropTargetWin::OnDragEnter(IDataObject
* data_object
,
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
,
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
);
84 drag_operation
= delegate
->OnDragUpdated(*event
);
85 return ui::DragDropTypes::DragOperationToDropEffect(drag_operation
);
88 void DesktopDropTargetWin::OnDragLeave(IDataObject
* data_object
) {
92 DWORD
DesktopDropTargetWin::OnDrop(IDataObject
* data_object
,
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
);
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
,
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(
133 aura::Window
* target_window
=
134 root_window_
->GetEventHandlerForPoint(root_location
);
135 bool target_window_changed
= false;
136 if (target_window
!= target_window_
) {
139 target_window_
= target_window
;
141 target_window_
->AddObserver(this);
142 target_window_changed
= true;
147 *delegate
= aura::client::GetDragDropDelegate(target_window_
);
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(
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() {
167 DragDropDelegate
* delegate
=
168 aura::client::GetDragDropDelegate(target_window_
);
170 delegate
->OnDragExited();
171 target_window_
->RemoveObserver(this);
172 target_window_
= NULL
;