1 // Copyright (c) 2012 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 "content/browser/web_contents/web_drag_source_win.h"
8 #include "content/browser/renderer_host/render_view_host_impl.h"
9 #include "content/browser/web_contents/web_contents_impl.h"
10 #include "content/browser/web_contents/web_drag_utils_win.h"
11 #include "content/public/browser/browser_thread.h"
12 #include "content/public/browser/notification_source.h"
13 #include "content/public/browser/notification_types.h"
14 #include "ui/base/dragdrop/os_exchange_data.h"
16 using WebKit::WebDragOperationNone;
21 static void GetCursorPositions(gfx::NativeWindow wnd, gfx::Point* client,
24 GetCursorPos(&cursor_pos);
25 screen->SetPoint(cursor_pos.x, cursor_pos.y);
26 ScreenToClient(wnd, &cursor_pos);
27 client->SetPoint(cursor_pos.x, cursor_pos.y);
32 ///////////////////////////////////////////////////////////////////////////////
33 // WebDragSource, public:
35 WebDragSource::WebDragSource(gfx::NativeWindow source_wnd,
36 WebContents* web_contents)
37 : ui::DragSourceWin(),
38 source_wnd_(source_wnd),
39 web_contents_(static_cast<WebContentsImpl*>(web_contents)),
40 effect_(DROPEFFECT_NONE),
42 registrar_.Add(this, NOTIFICATION_RENDER_VIEW_HOST_CHANGED,
43 Source<WebContents>(web_contents));
44 registrar_.Add(this, NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
45 Source<WebContents>(web_contents));
48 WebDragSource::~WebDragSource() {
51 void WebDragSource::OnDragSourceCancel() {
52 // Delegate to the UI thread if we do drag-and-drop in the background thread.
53 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
54 BrowserThread::PostTask(
55 BrowserThread::UI, FROM_HERE,
56 base::Bind(&WebDragSource::OnDragSourceCancel, this));
65 GetCursorPositions(source_wnd_, &client, &screen);
66 web_contents_->DragSourceEndedAt(client.x(), client.y(),
67 screen.x(), screen.y(),
68 WebDragOperationNone);
71 void WebDragSource::OnDragSourceDrop() {
73 data_->SetInDragLoop(false);
74 // On Windows, we check for drag end in IDropSource::QueryContinueDrag which
75 // happens before IDropTarget::Drop is called. HTML5 requires the "dragend"
76 // event to happen after the "drop" event. Since Windows calls these two
77 // directly after each other we can just post a task to handle the
78 // OnDragSourceDrop after the current task.
79 BrowserThread::PostTask(
80 BrowserThread::UI, FROM_HERE,
81 base::Bind(&WebDragSource::DelayedOnDragSourceDrop, this));
84 void WebDragSource::DelayedOnDragSourceDrop() {
90 GetCursorPositions(source_wnd_, &client, &screen);
91 web_contents_->DragSourceEndedAt(client.x(), client.y(), screen.x(),
92 screen.y(), WinDragOpToWebDragOp(effect_));
95 void WebDragSource::OnDragSourceMove() {
96 // Delegate to the UI thread if we do drag-and-drop in the background thread.
97 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
98 BrowserThread::PostTask(
99 BrowserThread::UI, FROM_HERE,
100 base::Bind(&WebDragSource::OnDragSourceMove, this));
109 GetCursorPositions(source_wnd_, &client, &screen);
110 web_contents_->DragSourceMovedTo(client.x(), client.y(),
111 screen.x(), screen.y());
114 void WebDragSource::Observe(int type,
115 const NotificationSource& source,
116 const NotificationDetails& details) {
117 if (type == NOTIFICATION_RENDER_VIEW_HOST_CHANGED) {
118 // When the WebContents get swapped, our render view host goes away.
119 // That's OK, we can continue the drag, we just can't send messages back to
121 web_contents_ = NULL;
122 } else if (type == NOTIFICATION_WEB_CONTENTS_DISCONNECTED) {
123 // This could be possible when we close the tab and the source is still
124 // being used in DoDragDrop at the time that the virtual file is being
126 web_contents_ = NULL;
130 } // namespace content