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/base/dragdrop/drop_target_win.h"
6
7#include <shlobj.h>
8
9#include "base/logging.h"
10
11namespace ui {
12
13IDropTargetHelper* DropTargetWin::cached_drop_target_helper_ = NULL;
14
15DropTargetWin::DropTargetWin(HWND hwnd)
16    : hwnd_(hwnd),
17      ref_count_(0) {
18  DCHECK(hwnd);
19  HRESULT result = RegisterDragDrop(hwnd, this);
20  DCHECK(SUCCEEDED(result));
21}
22
23DropTargetWin::~DropTargetWin() {
24}
25
26// static
27IDropTargetHelper* DropTargetWin::DropHelper() {
28  if (!cached_drop_target_helper_) {
29    CoCreateInstance(CLSID_DragDropHelper, 0, CLSCTX_INPROC_SERVER,
30                     IID_IDropTargetHelper,
31                     reinterpret_cast<void**>(&cached_drop_target_helper_));
32  }
33  return cached_drop_target_helper_;
34}
35
36///////////////////////////////////////////////////////////////////////////////
37// DropTargetWin, IDropTarget implementation:
38
39HRESULT DropTargetWin::DragEnter(IDataObject* data_object,
40                                 DWORD key_state,
41                                 POINTL cursor_position,
42                                 DWORD* effect) {
43  // Tell the helper that we entered so it can update the drag image.
44  IDropTargetHelper* drop_helper = DropHelper();
45  if (drop_helper) {
46    drop_helper->DragEnter(GetHWND(), data_object,
47                           reinterpret_cast<POINT*>(&cursor_position), *effect);
48  }
49
50  current_data_object_ = data_object;
51  POINT screen_pt = { cursor_position.x, cursor_position.y };
52  *effect = OnDragEnter(current_data_object_, key_state, screen_pt, *effect);
53  return S_OK;
54}
55
56HRESULT DropTargetWin::DragOver(DWORD key_state,
57                                POINTL cursor_position,
58                                DWORD* effect) {
59  // Tell the helper that we moved over it so it can update the drag image.
60  IDropTargetHelper* drop_helper = DropHelper();
61  if (drop_helper)
62    drop_helper->DragOver(reinterpret_cast<POINT*>(&cursor_position), *effect);
63
64  POINT screen_pt = { cursor_position.x, cursor_position.y };
65  *effect = OnDragOver(current_data_object_, key_state, screen_pt, *effect);
66  return S_OK;
67}
68
69HRESULT DropTargetWin::DragLeave() {
70  // Tell the helper that we moved out of it so it can update the drag image.
71  IDropTargetHelper* drop_helper = DropHelper();
72  if (drop_helper)
73    drop_helper->DragLeave();
74
75  OnDragLeave(current_data_object_);
76
77  current_data_object_ = NULL;
78  return S_OK;
79}
80
81HRESULT DropTargetWin::Drop(IDataObject* data_object,
82                            DWORD key_state,
83                            POINTL cursor_position,
84                            DWORD* effect) {
85  // Tell the helper that we dropped onto it so it can update the drag image.
86  IDropTargetHelper* drop_helper = DropHelper();
87  if (drop_helper) {
88    drop_helper->Drop(current_data_object_,
89                      reinterpret_cast<POINT*>(&cursor_position), *effect);
90  }
91
92  POINT screen_pt = { cursor_position.x, cursor_position.y };
93  *effect = OnDrop(current_data_object_, key_state, screen_pt, *effect);
94  return S_OK;
95}
96
97///////////////////////////////////////////////////////////////////////////////
98// DropTargetWin, IUnknown implementation:
99
100HRESULT DropTargetWin::QueryInterface(const IID& iid, void** object) {
101  *object = NULL;
102  if (IsEqualIID(iid, IID_IUnknown) || IsEqualIID(iid, IID_IDropTarget)) {
103    *object = this;
104  } else {
105    return E_NOINTERFACE;
106  }
107  AddRef();
108  return S_OK;
109}
110
111ULONG DropTargetWin::AddRef() {
112  return ++ref_count_;
113}
114
115ULONG DropTargetWin::Release() {
116  if (--ref_count_ == 0) {
117    delete this;
118    return 0U;
119  }
120  return ref_count_;
121}
122
123DWORD DropTargetWin::OnDragEnter(IDataObject* data_object,
124                                 DWORD key_state,
125                                 POINT cursor_position,
126                                 DWORD effect) {
127  return DROPEFFECT_NONE;
128}
129
130DWORD DropTargetWin::OnDragOver(IDataObject* data_object,
131                                DWORD key_state,
132                                POINT cursor_position,
133                                DWORD effect) {
134  return DROPEFFECT_NONE;
135}
136
137void DropTargetWin::OnDragLeave(IDataObject* data_object) {
138}
139
140DWORD DropTargetWin::OnDrop(IDataObject* data_object,
141                            DWORD key_state,
142                            POINT cursor_position,
143                            DWORD effect) {
144  return DROPEFFECT_NONE;
145}
146
147}  // namespace ui
148