OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "content/browser/web_contents/web_drag_source_win.h" | |
6 | |
7 #include "base/bind.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" | |
15 | |
16 using blink::WebDragOperationNone; | |
17 | |
18 namespace content { | |
19 namespace { | |
20 | |
21 static void GetCursorPositions(gfx::NativeWindow wnd, gfx::Point* client, | |
22 gfx::Point* screen) { | |
23 POINT cursor_pos; | |
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); | |
28 } | |
29 | |
30 } // namespace | |
31 | |
32 /////////////////////////////////////////////////////////////////////////////// | |
33 // WebDragSource, public: | |
34 | |
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), | |
41 data_(NULL) { | |
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)); | |
46 } | |
47 | |
48 WebDragSource::~WebDragSource() { | |
49 } | |
50 | |
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)); | |
57 return; | |
58 } | |
59 | |
60 if (!web_contents_) | |
61 return; | |
62 | |
63 gfx::Point client; | |
64 gfx::Point screen; | |
65 GetCursorPositions(source_wnd_, &client, &screen); | |
66 web_contents_->DragSourceEndedAt(client.x(), client.y(), | |
67 screen.x(), screen.y(), | |
68 WebDragOperationNone); | |
69 } | |
70 | |
71 void WebDragSource::OnDragSourceDrop() { | |
72 DCHECK(data_); | |
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)); | |
82 } | |
83 | |
84 void WebDragSource::DelayedOnDragSourceDrop() { | |
85 if (!web_contents_) | |
86 return; | |
87 | |
88 gfx::Point client; | |
89 gfx::Point screen; | |
90 GetCursorPositions(source_wnd_, &client, &screen); | |
91 web_contents_->DragSourceEndedAt(client.x(), client.y(), screen.x(), | |
92 screen.y(), WinDragOpToWebDragOp(effect_)); | |
93 } | |
94 | |
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)); | |
101 return; | |
102 } | |
103 | |
104 if (!web_contents_) | |
105 return; | |
106 | |
107 gfx::Point client; | |
108 gfx::Point screen; | |
109 GetCursorPositions(source_wnd_, &client, &screen); | |
110 web_contents_->DragSourceMovedTo(client.x(), client.y(), | |
111 screen.x(), screen.y()); | |
112 } | |
113 | |
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 | |
120 // our drag source. | |
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 | |
125 // downloaded. | |
126 web_contents_ = NULL; | |
127 } | |
128 } | |
129 | |
130 } // namespace content | |
OLD | NEW |