Index: chrome/browser/ui/views/tab_contents/native_tab_contents_view_aura.cc |
diff --git a/chrome/browser/ui/views/tab_contents/native_tab_contents_view_aura.cc b/chrome/browser/ui/views/tab_contents/native_tab_contents_view_aura.cc |
index 5084ddbd5014464c6c8dfb82e1500e9c406ae98f..7fd5c80761d08aef223a16dfbd557709befa5b6d 100644 |
--- a/chrome/browser/ui/views/tab_contents/native_tab_contents_view_aura.cc |
+++ b/chrome/browser/ui/views/tab_contents/native_tab_contents_view_aura.cc |
@@ -4,14 +4,123 @@ |
#include "chrome/browser/ui/views/tab_contents/native_tab_contents_view_aura.h" |
+#include "base/event_types.h" |
+#include "base/message_loop.h" |
#include "chrome/browser/ui/views/tab_contents/native_tab_contents_view_delegate.h" |
+#include "content/browser/renderer_host/render_view_host.h" |
#include "content/browser/renderer_host/render_widget_host_view_aura.h" |
#include "content/browser/tab_contents/tab_contents.h" |
#include "content/browser/tab_contents/tab_contents_view.h" |
+#include "ui/aura/client/aura_constants.h" |
+#include "ui/aura/client/drag_drop_client.h" |
+#include "ui/aura/desktop.h" |
#include "ui/aura/event.h" |
#include "ui/aura/window.h" |
+#include "ui/base/dragdrop/drag_drop_types.h" |
+#include "ui/base/dragdrop/os_exchange_data.h" |
+#include "ui/base/dragdrop/os_exchange_data_provider_aura.h" |
#include "ui/views/widget/widget.h" |
#include "views/views_delegate.h" |
+#include "webkit/glue/webdropdata.h" |
+ |
+namespace { |
+ |
+// Listens to all mouse drag events during a drag and drop and sends them to |
+// the renderer. |
+class WebDragSourceAura : public MessageLoopForUI::Observer { |
+ public: |
+ explicit WebDragSourceAura(NativeTabContentsViewAura* view) |
+ : view_(view) { |
+ MessageLoopForUI::current()->AddObserver(this); |
+ } |
+ |
+ virtual ~WebDragSourceAura() { |
+ MessageLoopForUI::current()->RemoveObserver(this); |
+ } |
+ |
+ // MessageLoop::Observer implementation: |
+ virtual base::EventStatus WillProcessEvent( |
+ const base::NativeEvent& event) OVERRIDE { |
+ return base::EVENT_CONTINUE; |
+ } |
+ virtual void DidProcessEvent(const base::NativeEvent& event) OVERRIDE { |
+ ui::EventType type = ui::EventTypeFromNative(event); |
+ RenderViewHost* rvh = NULL; |
+ switch (type) { |
+ case ui::ET_MOUSE_DRAGGED: |
+ rvh = view_->GetTabContents()->render_view_host(); |
+ if (rvh) { |
+ gfx::Point screen_loc = ui::EventLocationFromNative(event); |
+ gfx::Point client_loc = screen_loc; |
+ aura::Window* window = rvh->view()->GetNativeView(); |
+ aura::Window::ConvertPointToWindow(aura::Desktop::GetInstance(), |
+ window, &client_loc); |
+ rvh->DragSourceMovedTo(client_loc.x(), client_loc.y(), |
+ screen_loc.x(), screen_loc.y()); |
+ } |
+ break; |
+ default: |
+ break; |
+ } |
+ } |
+ |
+ private: |
+ NativeTabContentsViewAura* view_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(WebDragSourceAura); |
+}; |
+ |
+// Utility to fill a ui::OSExchangeDataProviderAura object from WebDropData. |
+void PrepareDragData(const WebDropData& drop_data, |
+ ui::OSExchangeDataProviderAura* provider) { |
+ if (!drop_data.plain_text.empty()) |
+ provider->SetString(drop_data.plain_text); |
+ if (drop_data.url.is_valid()) |
+ provider->SetURL(drop_data.url, drop_data.url_title); |
+ // TODO(varunjain): support other formats. |
+} |
+ |
+// Utility to fill a WebDropData object from ui::OSExchangeData. |
+void PrepareWebDropData(WebDropData* drop_data, |
+ const ui::OSExchangeData& data) { |
+ string16 plain_text, url_title; |
+ GURL url; |
+ data.GetString(&plain_text); |
+ if (!plain_text.empty()) |
+ drop_data->plain_text = plain_text; |
+ data.GetURLAndTitle(&url, &url_title); |
+ if (url.is_valid()) { |
+ drop_data->url = url; |
+ drop_data->url_title = url_title; |
+ } |
+ // TODO(varunjain): support other formats. |
+} |
+ |
+// Utilities to convert between WebKit::WebDragOperationsMask and |
+// ui::DragDropTypes. |
+int ConvertFromWeb(WebKit::WebDragOperationsMask ops) { |
+ int drag_op = ui::DragDropTypes::DRAG_NONE; |
+ if (ops & WebKit::WebDragOperationCopy) |
+ drag_op |= ui::DragDropTypes::DRAG_COPY; |
+ if (ops & WebKit::WebDragOperationMove) |
+ drag_op |= ui::DragDropTypes::DRAG_MOVE; |
+ if (ops & WebKit::WebDragOperationLink) |
+ drag_op |= ui::DragDropTypes::DRAG_LINK; |
+ return drag_op; |
+} |
+ |
+WebKit::WebDragOperationsMask ConvertToWeb(int drag_op) { |
+ int web_drag_op = WebKit::WebDragOperationNone; |
+ if (drag_op & ui::DragDropTypes::DRAG_COPY) |
+ web_drag_op |= WebKit::WebDragOperationCopy; |
+ if (drag_op & ui::DragDropTypes::DRAG_MOVE) |
+ web_drag_op |= WebKit::WebDragOperationMove; |
+ if (drag_op & ui::DragDropTypes::DRAG_LINK) |
+ web_drag_op |= WebKit::WebDragOperationLink; |
+ return (WebKit::WebDragOperationsMask) web_drag_op; |
+} |
+ |
+} // namespace |
//////////////////////////////////////////////////////////////////////////////// |
// NativeTabContentsViewAura, public: |
@@ -19,7 +128,8 @@ |
NativeTabContentsViewAura::NativeTabContentsViewAura( |
internal::NativeTabContentsViewDelegate* delegate) |
: views::NativeWidgetAura(delegate->AsNativeWidgetDelegate()), |
- delegate_(delegate) { |
+ delegate_(delegate), |
+ current_drag_op_(WebKit::WebDragOperationNone) { |
} |
NativeTabContentsViewAura::~NativeTabContentsViewAura() { |
@@ -29,12 +139,6 @@ TabContents* NativeTabContentsViewAura::GetTabContents() const { |
return delegate_->GetTabContents(); |
} |
-void NativeTabContentsViewAura::EndDragging() { |
- delegate_->OnNativeTabContentsViewDraggingEnded(); |
- // TODO(beng): |
- NOTIMPLEMENTED(); |
-} |
- |
//////////////////////////////////////////////////////////////////////////////// |
// NativeTabContentsViewAura, NativeTabContentsView implementation: |
@@ -67,6 +171,12 @@ RenderWidgetHostView* NativeTabContentsViewAura::CreateRenderWidgetHostView( |
view->InitAsChild(); |
GetNativeView()->AddChild(view->GetNativeView()); |
view->Show(); |
+ |
+ // We listen to drag drop events in the newly created view's window. |
+ aura::Window* window = static_cast<aura::Window*>(view->GetNativeView()); |
+ DCHECK(window); |
+ window->SetProperty(aura::kDragDropDelegateKey, |
+ static_cast<aura::WindowDragDropDelegate*>(this)); |
return view; |
} |
@@ -84,25 +194,51 @@ void NativeTabContentsViewAura::StartDragging(const WebDropData& drop_data, |
WebKit::WebDragOperationsMask ops, |
const SkBitmap& image, |
const gfx::Point& image_offset) { |
- // TODO(beng): |
- NOTIMPLEMENTED(); |
+ aura::DragDropClient* client = static_cast<aura::DragDropClient*>( |
+ aura::Desktop::GetInstance()->GetProperty( |
+ aura::kDesktopDragDropClientKey)); |
+ if (!client) |
+ return; |
+ |
+ ui::OSExchangeDataProviderAura* provider = new ui::OSExchangeDataProviderAura; |
+ PrepareDragData(drop_data, provider); |
+ if (!image.isNull()) |
+ provider->set_drag_image(image); |
+ ui::OSExchangeData data(provider); // takes ownership of |provider|. |
+ |
+ scoped_ptr<WebDragSourceAura> drag_source(new WebDragSourceAura(this)); |
+ |
+ // We need to enable recursive tasks on the message loop so we can get |
+ // updates while in the system DoDragDrop loop. |
+ bool old_state = MessageLoop::current()->NestableTasksAllowed(); |
+ MessageLoop::current()->SetNestableTasksAllowed(true); |
+ int result_op = client->StartDragAndDrop(data, ConvertFromWeb(ops)); |
+ MessageLoop::current()->SetNestableTasksAllowed(old_state); |
+ |
+ EndDrag(ConvertToWeb(result_op)); |
+ GetTabContents()->render_view_host()->DragSourceSystemDragEnded(); |
} |
void NativeTabContentsViewAura::CancelDrag() { |
- // TODO(beng): |
- NOTIMPLEMENTED(); |
+ aura::DragDropClient* client = static_cast<aura::DragDropClient*>( |
+ aura::Desktop::GetInstance()->GetProperty( |
+ aura::kDesktopDragDropClientKey)); |
+ if (client) |
+ client->DragCancel(); |
} |
bool NativeTabContentsViewAura::IsDoingDrag() const { |
- // TODO(beng): |
- NOTIMPLEMENTED(); |
+ aura::DragDropClient* client = static_cast<aura::DragDropClient*>( |
+ aura::Desktop::GetInstance()->GetProperty( |
+ aura::kDesktopDragDropClientKey)); |
+ if (client) |
+ return client->IsDragDropInProgress(); |
return false; |
} |
void NativeTabContentsViewAura::SetDragCursor( |
WebKit::WebDragOperation operation) { |
- // TODO(beng): |
- NOTIMPLEMENTED(); |
+ current_drag_op_ = operation; |
} |
views::NativeWidget* NativeTabContentsViewAura::AsNativeWidget() { |
@@ -136,6 +272,51 @@ bool NativeTabContentsViewAura::OnMouseEvent(aura::MouseEvent* event) { |
return views::NativeWidgetAura::OnMouseEvent(event); |
} |
+void NativeTabContentsViewAura::OnDragEntered( |
+ const aura::DropTargetEvent& event) { |
+ WebDropData drop_data; |
+ PrepareWebDropData(&drop_data, event.data()); |
+ WebKit::WebDragOperationsMask op = ConvertToWeb(event.source_operations()); |
+ |
+ gfx::Point screen_pt = aura::Desktop::GetInstance()->last_mouse_location(); |
+ GetTabContents()->render_view_host()->DragTargetDragEnter( |
+ drop_data, event.location(), screen_pt, op); |
+} |
+ |
+int NativeTabContentsViewAura::OnDragUpdated( |
+ const aura::DropTargetEvent& event) { |
+ WebKit::WebDragOperationsMask op = ConvertToWeb(event.source_operations()); |
+ gfx::Point screen_pt = aura::Desktop::GetInstance()->last_mouse_location(); |
+ GetTabContents()->render_view_host()->DragTargetDragOver( |
+ event.location(), screen_pt, op); |
+ return ConvertFromWeb(current_drag_op_); |
+} |
+ |
+void NativeTabContentsViewAura::OnDragExited() { |
+ GetTabContents()->render_view_host()->DragTargetDragLeave(); |
+} |
+ |
+int NativeTabContentsViewAura::OnPerformDrop( |
+ const aura::DropTargetEvent& event) { |
+ GetTabContents()->render_view_host()->DragTargetDrop( |
+ event.location(), aura::Desktop::GetInstance()->last_mouse_location()); |
+ return current_drag_op_; |
+} |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
+// NativeTabContentsViewAura, private: |
+ |
+void NativeTabContentsViewAura::EndDrag(WebKit::WebDragOperationsMask ops) { |
+ gfx::Point screen_loc = aura::Desktop::GetInstance()->last_mouse_location(); |
+ gfx::Point client_loc = screen_loc; |
+ RenderViewHost* rvh = GetTabContents()->render_view_host(); |
+ aura::Window* window = rvh->view()->GetNativeView(); |
+ aura::Window::ConvertPointToWindow(aura::Desktop::GetInstance(), |
+ window, &client_loc); |
+ rvh->DragSourceEndedAt(client_loc.x(), client_loc.y(), screen_loc.x(), |
+ screen_loc.y(), ops); |
+} |
+ |
//////////////////////////////////////////////////////////////////////////////// |
// NativeTabContentsView, public: |