• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "chrome/browser/tab_contents/web_drag_source_win.h"
6 
7 #include "base/task.h"
8 #include "chrome/browser/tab_contents/web_drag_utils_win.h"
9 #include "content/browser/browser_thread.h"
10 #include "content/browser/renderer_host/render_view_host.h"
11 #include "content/browser/tab_contents/tab_contents.h"
12 #include "content/common/notification_source.h"
13 #include "content/common/notification_type.h"
14 
15 using WebKit::WebDragOperationNone;
16 
17 namespace {
18 
GetCursorPositions(gfx::NativeWindow wnd,gfx::Point * client,gfx::Point * screen)19 static void GetCursorPositions(gfx::NativeWindow wnd, gfx::Point* client,
20                                gfx::Point* screen) {
21   POINT cursor_pos;
22   GetCursorPos(&cursor_pos);
23   screen->SetPoint(cursor_pos.x, cursor_pos.y);
24   ScreenToClient(wnd, &cursor_pos);
25   client->SetPoint(cursor_pos.x, cursor_pos.y);
26 }
27 
28 }  // namespace
29 
30 ///////////////////////////////////////////////////////////////////////////////
31 // WebDragSource, public:
32 
WebDragSource(gfx::NativeWindow source_wnd,TabContents * tab_contents)33 WebDragSource::WebDragSource(gfx::NativeWindow source_wnd,
34                              TabContents* tab_contents)
35     : ui::DragSource(),
36       source_wnd_(source_wnd),
37       render_view_host_(tab_contents->render_view_host()),
38       effect_(DROPEFFECT_NONE) {
39   registrar_.Add(this, NotificationType::TAB_CONTENTS_SWAPPED,
40                  Source<TabContents>(tab_contents));
41   registrar_.Add(this, NotificationType::TAB_CONTENTS_DISCONNECTED,
42                  Source<TabContents>(tab_contents));
43 }
44 
~WebDragSource()45 WebDragSource::~WebDragSource() {
46 }
47 
OnDragSourceCancel()48 void WebDragSource::OnDragSourceCancel() {
49   // Delegate to the UI thread if we do drag-and-drop in the background thread.
50   if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
51     BrowserThread::PostTask(
52         BrowserThread::UI, FROM_HERE,
53         NewRunnableMethod(this, &WebDragSource::OnDragSourceCancel));
54     return;
55   }
56 
57   if (!render_view_host_)
58     return;
59 
60   gfx::Point client;
61   gfx::Point screen;
62   GetCursorPositions(source_wnd_, &client, &screen);
63   render_view_host_->DragSourceEndedAt(client.x(), client.y(),
64                                        screen.x(), screen.y(),
65                                        WebDragOperationNone);
66 }
67 
OnDragSourceDrop()68 void WebDragSource::OnDragSourceDrop() {
69   // On Windows, we check for drag end in IDropSource::QueryContinueDrag which
70   // happens before IDropTarget::Drop is called. HTML5 requires the "dragend"
71   // event to happen after the "drop" event. Since  Windows calls these two
72   // directly after each other we can just post a task to handle the
73   // OnDragSourceDrop after the current task.
74   BrowserThread::PostTask(
75       BrowserThread::UI, FROM_HERE,
76       NewRunnableMethod(this, &WebDragSource::DelayedOnDragSourceDrop));
77 }
78 
DelayedOnDragSourceDrop()79 void WebDragSource::DelayedOnDragSourceDrop() {
80   if (!render_view_host_)
81     return;
82 
83   gfx::Point client;
84   gfx::Point screen;
85   GetCursorPositions(source_wnd_, &client, &screen);
86   render_view_host_->DragSourceEndedAt(
87       client.x(), client.y(), screen.x(), screen.y(),
88       web_drag_utils_win::WinDragOpToWebDragOp(effect_));
89 }
90 
OnDragSourceMove()91 void WebDragSource::OnDragSourceMove() {
92   // Delegate to the UI thread if we do drag-and-drop in the background thread.
93   if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
94     BrowserThread::PostTask(
95         BrowserThread::UI, FROM_HERE,
96         NewRunnableMethod(this, &WebDragSource::OnDragSourceMove));
97     return;
98   }
99 
100   if (!render_view_host_)
101     return;
102 
103   gfx::Point client;
104   gfx::Point screen;
105   GetCursorPositions(source_wnd_, &client, &screen);
106   render_view_host_->DragSourceMovedTo(client.x(), client.y(),
107                                        screen.x(), screen.y());
108 }
109 
Observe(NotificationType type,const NotificationSource & source,const NotificationDetails & details)110 void WebDragSource::Observe(NotificationType type,
111     const NotificationSource& source, const NotificationDetails& details) {
112   if (NotificationType::TAB_CONTENTS_SWAPPED == type) {
113     // When the tab contents get swapped, our render view host goes away.
114     // That's OK, we can continue the drag, we just can't send messages back to
115     // our drag source.
116     render_view_host_ = NULL;
117   } else if (NotificationType::TAB_CONTENTS_DISCONNECTED == type) {
118     // This could be possible when we close the tab and the source is still
119     // being used in DoDragDrop at the time that the virtual file is being
120     // downloaded.
121     render_view_host_ = NULL;
122   }
123 }
124