Added implementation of Drag&Drop for EFL port
authorDaniel Waślicki <d.waslicki@samsung.com>
Thu, 5 Feb 2015 13:03:36 +0000 (14:03 +0100)
committerYoungsoo Choi <kenshin.choi@samsung.com>
Tue, 10 Jul 2018 06:57:09 +0000 (06:57 +0000)
This patch adds implementation of Drag&Drop for EFL port.
D&D will be enabled after long press and allows to drag
any elements.

Bug: http://107.108.218.239/bugzilla/show_bug.cgi?id=10755
Reviewed by: Antonio Gomes, Piotr Tworek

Change-Id: I3fec12f5bcbd3544b08ba4bd24b23419f828d1fe
Signed-off-by: Daniel Waślicki <d.waslicki@samsung.com>
tizen_src/impl/browser/renderer_host/render_widget_host_view_efl.cc
tizen_src/impl/browser/web_contents/web_contents_view_efl.cc
tizen_src/impl/browser/web_contents/web_contents_view_efl.h
tizen_src/impl/browser/web_contents/web_drag_dest_efl.cc
tizen_src/impl/browser/web_contents/web_drag_dest_efl.h
tizen_src/impl/browser/web_contents/web_drag_source_efl.cc [new file with mode: 0644]
tizen_src/impl/browser/web_contents/web_drag_source_efl.h [new file with mode: 0644]
tizen_src/impl/chromium-efl.gyp
tizen_src/impl/command_line_efl.cc
tizen_src/impl/eweb_view.cc
tizen_src/impl/eweb_view.h

index d1054461381711d39852a7eed7a0e34f3af11c60..996e7dd6c735178ff319e55fa10ac41dda1d5378 100644 (file)
@@ -1459,6 +1459,15 @@ void RenderWidgetHostViewEfl::HandleGesture(
     event.data.tap.height = size;
   }
 
+  if ((event.type == blink::WebInputEvent::GestureScrollBegin ||
+      event.type == blink::WebInputEvent::GestureScrollUpdate ||
+      event.type == blink::WebInputEvent::GestureScrollEnd) &&
+      eweb_view()->IsDragging()) {
+    // Disable screen scrolling while D&D is active.
+    event.data.scrollUpdate.deltaX = 0;
+    event.data.scrollUpdate.deltaY = 0;
+  }
+
   if (event.type == blink::WebInputEvent::GestureTapDown) {
     // Webkit does not stop a fling-scroll on tap-down. So explicitly send an
     // event to stop any in-progress flings.
index 9d38c98bac46b082dd5e0f45e807fbf8605d37dc..2b6d9b9ebbf946e05a788ab44a901ca66c4ec11e 100644 (file)
@@ -87,25 +87,11 @@ void WebContentsViewEfl::UpdateDragDest(RenderViewHost* host) {
     return;
   }
 
-  // If supporting RenderWidgetHostViewEfl::GetNativeView(), following lines
-  // will be enabled similar to GTK+ port
-  RenderWidgetHostViewEfl* view = static_cast<RenderWidgetHostViewEfl*>(
-    web_contents_->GetRenderWidgetHostView());
-
-  // If the host is already used by the drag_dest_, there's no point in deleting
-  // the old one to create an identical copy.
-
-  /*if (drag_dest_.get() && drag_dest_->widget() == content_view)
-    return;*/
-
-  // Clear the currently connected drag drop signals by deleting the old
-  // drag_dest_ before creating the new one.
-  drag_dest_.reset();
   // Create the new drag_dest_.
-  drag_dest_.reset(new WebDragDestEfl(web_contents_, view));
+  drag_dest_.reset(new WebDragDestEfl(web_contents_, GetEWebView()));
 
   if (delegate_)
-    drag_dest_->set_delegate(delegate_->GetDragDestDelegate());
+    drag_dest_->SetDelegate(delegate_->GetDragDestDelegate());
 }
 
 void WebContentsViewEfl::RenderViewCreated(RenderViewHost* host) {
@@ -179,8 +165,9 @@ void WebContentsViewEfl::RestoreFocus() {
 }
 
 DropData* WebContentsViewEfl::GetDropData() const {
-  NOTIMPLEMENTED();
-  return 0;
+  if (drag_dest_.get())
+    return drag_dest_->GetDropData();
+  return nullptr;
 }
 
 gfx::Rect WebContentsViewEfl::GetViewBounds() const {
@@ -229,6 +216,31 @@ void WebContentsViewEfl::ShowPopupMenu(RenderFrameHost* render_frame_host,
 }
 #endif
 
+void WebContentsViewEfl::StartDragging(const DropData& drop_data,
+                             blink::WebDragOperationsMask allowed_ops,
+                             const gfx::ImageSkia& image,
+                             const gfx::Vector2d& image_offset,
+                             const DragEventSourceInfo& event_info) {
+  if (drag_dest_.get()) {
+    drag_dest_->SetDropData(drop_data);
+    drag_dest_->SetAction(allowed_ops);
+  }
+
+  if (!drag_source_)
+    drag_source_.reset(new WebDragSourceEfl(web_contents_, GetEWebView()));
+
+  if (!drag_source_->StartDragging(drop_data, allowed_ops,
+          event_info.event_location, *image.bitmap(), image_offset)) {
+    web_contents_->SystemDragEnded();
+  }
+}
+
+bool WebContentsViewEfl::IsDragging() const {
+  if (!drag_source_)
+    return false;
+  return drag_source_->IsDragging();
+}
+
 void WebContentsViewEfl::SetOrientation(int orientation) {
   RenderWidgetHostViewEfl* rwhv = static_cast<RenderWidgetHostViewEfl*>(
                                     web_contents_->GetRenderWidgetHostView());
index 200607d2bac8912fa205e84c2cd19c682d7e74de..578ee2361f6dda0a529a782902d4cfa9bbc6371a 100644 (file)
@@ -7,6 +7,7 @@
 #define WEB_CONTENTS_VIEW_EFL
 
 #include "browser/web_contents/web_drag_dest_efl.h"
+#include "browser/web_contents/web_drag_source_efl.h"
 #include "content/browser/renderer_host/render_view_host_delegate_view.h"
 #include "content/browser/web_contents/web_contents_view.h"
 #include "tizen_webview/public/tw_view_mode.h"
@@ -64,6 +65,14 @@ class WebContentsViewEfl
 #endif
   void UpdateDragDest(RenderViewHost* host);
 
+  void StartDragging(const DropData& drop_data,
+                     blink::WebDragOperationsMask allowed_ops,
+                     const gfx::ImageSkia& image,
+                     const gfx::Vector2d& image_offset,
+                     const DragEventSourceInfo& event_info) override;
+
+  bool IsDragging() const;
+
   void SetViewMode(tizen_webview::View_Mode mode);
 
   virtual void UpdateFormNavigation(int formElementCount, int currentNodeIndex,
@@ -85,11 +94,10 @@ private:
   // The size we want the view to be.
   gfx::Size requested_size_;
 
-  // The helper object that handles drag destination related interactions with
-  // EFL.
+  // Helpers handling drag source/destination related interactions with EFL.
+  scoped_ptr<WebDragSourceEfl> drag_source_;
   scoped_ptr<WebDragDestEfl> drag_dest_;
 
-
   tizen_webview::View_Mode view_mode_;
 
   int orientation_;
index 46c0b3ac1039569d5ca6ea1139aed13ef91b6aed..890ddfb9d83901d1e98cd112d1046acd611c671c 100644 (file)
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "web_drag_dest_efl.h"
+#include "browser/web_contents/web_drag_dest_efl.h"
 
-#include <string>
-#include "base/bind.h"
-#include "base/files/file_path.h"
-#include "base/message_loop/message_loop.h"
-#include "base/strings/utf_string_conversions.h"
 #include "content/browser/web_contents/web_contents_impl.h"
-#include "content/public/browser/web_contents_delegate.h"
 #include "content/public/browser/web_drag_dest_delegate.h"
-#include "content/public/common/url_constants.h"
-#include "net/base/net_util.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
-#include "ui/base/clipboard/custom_data_helper.h"
-
-#include "browser/renderer_host/render_widget_host_view_efl.h"
+#include "ui/gfx/screen.h"
 
 using blink::WebDragOperation;
-using blink::WebDragOperationNone;
-using blink::WebDragOperationCopy;
 
 namespace content {
 
-#if defined(OS_TIZEN)
-static void drag_state_enter_cb(void *data, Evas_Object *obj) {
-  WebDragDestEfl *webdragdestefl = (WebDragDestEfl *)data;
+namespace {
+static void DragStateEnterCb(void* data, Evas_Object*) {
+  WebDragDestEfl* web_drag_dest_efl = static_cast<WebDragDestEfl*>(data);
+  web_drag_dest_efl->DragStateEnter();
+}
 
-  webdragdestefl->drop_data_.reset(new DropData);
+static void DragStateLeaveCb(void* data, Evas_Object*) {
+  WebDragDestEfl* web_drag_dest_efl = static_cast<WebDragDestEfl*>(data);
+  web_drag_dest_efl->DragStateLeave();
+}
 
-  if (webdragdestefl->delegate())
-    webdragdestefl->delegate()->DragInitialize(webdragdestefl->web_contents());
+static void DragPosCb(void* data, Evas_Object*, Evas_Coord x,
+    Evas_Coord y, Elm_Xdnd_Action action) {
+  WebDragDestEfl* web_drag_dest_efl = static_cast<WebDragDestEfl*>(data);
+  web_drag_dest_efl->DragPos(x, y, action);
 }
 
-static void drag_state_leave_cb(void *data, Evas_Object *obj) {
-  WebDragDestEfl *webdragdestefl = (WebDragDestEfl *)data;
+static Eina_Bool DragDropCb(void* data, Evas_Object*,
+    Elm_Selection_Data* drop) {
+  WebDragDestEfl *web_drag_dest_efl = static_cast<WebDragDestEfl*>(data);
+  return web_drag_dest_efl->DragDrop(drop);
+}
+} // namespace
+
+WebDragDestEfl::WebDragDestEfl(WebContents* web_contents, EWebView* eweb_view)
+    : eweb_view_(eweb_view),
+      web_contents_(web_contents),
+      delegate_(nullptr),
+      drag_initialized_(false),
+      modifier_flags_(0) {
+  device_scale_factor_ = gfx::Screen::GetNativeScreen()->
+      GetPrimaryDisplay().device_scale_factor();
+
+  SetDragCallbacks();
+}
 
-  base::MessageLoop::current()->PostTask(
-    FROM_HERE,
-    base::Bind(&WebDragDestEfl::DragLeave, webdragdestefl->method_factory_.GetWeakPtr()));
+WebDragDestEfl::~WebDragDestEfl() {
+  UnsetDragCallbacks();
 }
 
-static void drag_Pos(void *data, Evas_Object *obj, Evas_Coord x, Evas_Coord y, Elm_Xdnd_Action action) {
-  WebDragDestEfl *webdragdestefl = (WebDragDestEfl *)data;
+void WebDragDestEfl::SetDragCallbacks() {
+  elm_drop_target_add(eweb_view_->evas_object(), ELM_SEL_FORMAT_TEXT,
+      DragStateEnterCb, this,
+      DragStateLeaveCb, this,
+      DragPosCb, this,
+      DragDropCb, this);
+}
 
-  gfx::Rect rect = webdragdestefl->render_widget_host_view()->GetBoundsInRootWindow();
-  gfx::Point point = gfx::Point(rect.x(), rect.y());
+void WebDragDestEfl::UnsetDragCallbacks() {
+#if defined(TIZEN_LEGACY_V_2_2_1)
+  elm_drop_target_del(eweb_view_->evas_object());
+#else
+  elm_drop_target_del(eweb_view_->evas_object(), ELM_SEL_FORMAT_TEXT,
+      DragStateEnterCb, this,
+      DragStateLeaveCb, this,
+      DragPosCb, this,
+      DragDropCb, this);
+#endif
+}
 
-  webdragdestefl->GetRenderViewHost()->DragTargetDragOver(
-      point,
-      point,
-      WebDragOperationCopy,
-      blink::WebInputEvent::ControlKey);
+void WebDragDestEfl::ResetDragCallbacks() {
+  UnsetDragCallbacks();
+  SetDragCallbacks();
+}
 
-  if (webdragdestefl->delegate())
-    webdragdestefl->delegate()->OnDragOver();
+void WebDragDestEfl::DragStateEnter() {
+  if (!delegate_)
+    return;
+  delegate_->DragInitialize(web_contents_);
 }
 
-static Eina_Bool drag_drop_cb(void *data, Evas_Object *obj, Elm_Selection_Data *drop) {
-  WebDragDestEfl *webdragdestefl = (WebDragDestEfl *)data;
-  webdragdestefl->drop_data_->text = base::NullableString16(base::UTF8ToUTF16(std::string(reinterpret_cast<const char*>(drop->data))),
-                                     false);
+void WebDragDestEfl::DragStateLeave() {
+  GetRenderViewHost()->DragTargetDragLeave();
+  if (delegate_)
+    delegate_->OnDragLeave();
+}
 
-  gfx::Rect rect = webdragdestefl->render_widget_host_view()->GetBoundsInRootWindow();
-  gfx::Point point = gfx::Point(rect.x(), rect.y());
+void WebDragDestEfl::DragPos(Evas_Coord x, Evas_Coord y, Elm_Xdnd_Action action) {
+  gfx::Point screen_pt = gfx::Point(x / device_scale_factor_, y / device_scale_factor_);
+  float page_scale = eweb_view_->GetScale();
+  last_pointer_pos_ = screen_pt;
+  gfx::Point client_pt = gfx::Point(screen_pt.x() / page_scale, screen_pt.y() / page_scale);
+
+  if (!drag_initialized_) {
+    GetRenderViewHost()->DragTargetDragEnter(
+        *drop_data_,
+        client_pt,
+        screen_pt,
+        drag_action_,
+        modifier_flags_);
+
+    if (delegate_)
+      delegate_->OnDragEnter();
+
+    drag_initialized_ = true;
+  }
+
+  GetRenderViewHost()->DragTargetDragOver(
+      client_pt,
+      screen_pt,
+      drag_action_,
+      modifier_flags_);
+
+  if (!delegate_)
+    return;
+  delegate_->OnDragOver();
+}
 
-  webdragdestefl->GetRenderViewHost()->DragTargetDragEnter(
-      *webdragdestefl->drop_data_.get(),
-      point,
-      point,
-      WebDragOperationCopy,
-      blink::WebInputEvent::ControlKey);
+Eina_Bool WebDragDestEfl::DragDrop(Elm_Selection_Data* data) {
+  float page_scale = eweb_view_->GetScale();
 
-  if (webdragdestefl->delegate())
-    webdragdestefl->delegate()->OnDragEnter();
+  gfx::Point client_pt =
+      gfx::Point(last_pointer_pos_.x() / page_scale, last_pointer_pos_.y() / page_scale);
 
-  // Efl port need to check this, GTK+ port has drag data received & drag drop two callbacks
-  webdragdestefl->method_factory_.InvalidateWeakPtrs();
+  GetRenderViewHost()->DragTargetDrop(
+      client_pt,
+      last_pointer_pos_,
+      modifier_flags_);
 
-  webdragdestefl->GetRenderViewHost()->
-      DragTargetDrop(point, point, blink::WebInputEvent::ControlKey);
+  if (delegate_)
+    delegate_->OnDrop();
 
-  if (webdragdestefl->delegate())
-    webdragdestefl->delegate()->OnDrop();
+  drag_initialized_ = false;
+  // Invoking via message loop to not mess around with target
+  // from within one of its callbacks.
+  base::MessageLoop::current()->PostTask(
+      FROM_HERE,
+      base::Bind(&WebDragDestEfl::ResetDragCallbacks, base::Unretained(this)));
 
   return EINA_TRUE;
 }
-#endif // OS_TIZEN
-
-WebDragDestEfl::WebDragDestEfl(WebContents* web_contents, RenderWidgetHostViewEfl *rwhvefl)
-    : method_factory_(this),
-      rwhvefl_(rwhvefl),
-      web_contents_(web_contents) {
-#if defined(OS_TIZEN)
-  elm_drop_target_add(rwhvefl_->eweb_view()->evas_object(), ELM_SEL_FORMAT_TEXT,
-                                   drag_state_enter_cb, this,
-                                   drag_state_leave_cb, this,
-                                   drag_Pos, this,
-                                   drag_drop_cb, this);
-#endif // OS_TIZEN
-}
-
-WebDragDestEfl::~WebDragDestEfl() {
-#if defined(OS_TIZEN)
-#if defined(TIZEN_LEGACY_V_2_2_1)
-  elm_drop_target_del(rwhvefl_->eweb_view()->evas_object());
-#else
-  elm_drop_target_del(
-      rwhvefl_->eweb_view()->evas_object(), ELM_SEL_FORMAT_TEXT,
-      drag_state_enter_cb, this,
-      drag_state_leave_cb, this,
-      drag_Pos, this,
-      drag_drop_cb, this);
-#endif
-#endif // OS_TIZEN
-}
 
 void WebDragDestEfl::DragLeave() {
   GetRenderViewHost()->DragTargetDragLeave();
-  if (delegate())
-    delegate()->OnDragLeave();
+  if (delegate_)
+    delegate_->OnDragLeave();
 
   drop_data_.reset();
 }
 
-RenderViewHostImpl* WebDragDestEfl::GetRenderViewHost() const {
-  return static_cast<RenderViewHostImpl*>(web_contents_->GetRenderViewHost());
+void WebDragDestEfl::SetDropData(const DropData& drop_data) {
+  drop_data_.reset(new DropData(drop_data));
+}
+
+RenderViewHost* WebDragDestEfl::GetRenderViewHost() const {
+  return web_contents_->GetRenderViewHost();
 }
 
 }  // namespace content
index db6f78d5398d29a3b4d01f3507e1f77dfc7c99c9..6bb507f90e610c8a155cef83c8e5ceca9deac505 100644 (file)
@@ -6,64 +6,74 @@
 #ifndef CONTENT_BROWSER_WEB_CONTENTS_WEB_DRAG_DEST_EFL_H_
 #define CONTENT_BROWSER_WEB_CONTENTS_WEB_DRAG_DEST_EFL_H_
 
-#include "base/gtest_prod_util.h"
+#include <Elementary.h>
+
 #include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
-#include "content/browser/renderer_host/render_view_host_impl.h"
-#include "content/common/content_export.h"
 #include "content/public/common/drop_data.h"
+#include "eweb_view.h"
 #include "third_party/WebKit/public/web/WebDragOperation.h"
-
-#include <Ecore.h>
-#include <Ecore_Evas.h>
-#include <Ecore_Input.h>
-#include "ecore_x_wrapper.h"
-#include <Elementary.h>
+#include "ui/gfx/point.h"
 
 namespace content {
 
-class RenderViewHostImpl;
 class WebContents;
 class WebDragDestDelegate;
-class RenderWidgetHostViewEfl;
-
-#define EFL_CONTENT_EXPORT __attribute__((visibility("default")))
+class RenderViewHost;
 
-class EFL_CONTENT_EXPORT WebDragDestEfl {
+class WebDragDestEfl {
  public:
-  WebDragDestEfl(WebContents* web_contents, RenderWidgetHostViewEfl* rwhvefl);
+  WebDragDestEfl(WebContents* web_contents, EWebView* eweb_view);
   ~WebDragDestEfl();
 
+  blink::WebDragOperationsMask GetAction() { return drag_action_; }
+  WebDragDestDelegate* GetDelegate() const { return delegate_; }
+  DropData* GetDropData() { return drop_data_.get(); }
+  RenderViewHost* GetRenderViewHost() const;
+  WebContents* GetWebContents() { return web_contents_; }
+
+  void ResetDropData() { drop_data_.reset(); }
+  void SetAction(blink::WebDragOperationsMask allowed_ops) { drag_action_ = allowed_ops; }
+  void SetDelegate(WebDragDestDelegate* delegate) { delegate_ = delegate; }
+  void SetDropData(const DropData& drop_data);
+
   // Informs the renderer when a system drag has left the render view.
   // See OnDragLeave().
   void DragLeave();
 
-  WebDragDestDelegate* delegate() const { return delegate_; }
-  void set_delegate(WebDragDestDelegate* delegate) { delegate_ = delegate; }
-
-  RenderViewHostImpl* GetRenderViewHost() const;
-
-  RenderWidgetHostViewEfl* render_widget_host_view() { return rwhvefl_; }
-
-  WebContents* web_contents() { return web_contents_; }
-
-  // EFL port - public variables for now, need to add get methods to make private,
-  // faced build errors with scoped_ptr, base::WeakPtrFactory methods.
+  // EFL callbacks
+  void DragStateEnter();
+  void DragStateLeave();
+  void DragPos(Evas_Coord x, Evas_Coord y, Elm_Xdnd_Action action);
+  Eina_Bool DragDrop(Elm_Selection_Data *);
 
-  // The data for the current drag, or NULL if |context_| is NULL.
-  scoped_ptr<DropData> drop_data_;
+ private:
+  void SetDragCallbacks();
+  void UnsetDragCallbacks();
+  void ResetDragCallbacks();
 
-  base::WeakPtrFactory<WebDragDestEfl> method_factory_;
+  // Flag that indicates which modifier buttons (alt, shift, ctrl) are pressed
+  const int modifier_flags_;
 
- private:
   // A delegate that can receive drag information about drag events.
   WebDragDestDelegate* delegate_;
 
   // The render view.
-  RenderWidgetHostViewEfl *rwhvefl_;
+  EWebView* eweb_view_;
 
   WebContents* web_contents_;
 
+  // Drag operation - copy, move or link
+  blink::WebDragOperationsMask drag_action_;
+
+  float device_scale_factor_;
+
+  gfx::Point last_pointer_pos_;
+
+  bool drag_initialized_;
+
+  // The data for the current drag, or NULL if |context_| is NULL.
+  scoped_ptr<DropData> drop_data_;
+
   DISALLOW_COPY_AND_ASSIGN(WebDragDestEfl);
 };
 }  // namespace content
diff --git a/tizen_src/impl/browser/web_contents/web_drag_source_efl.cc b/tizen_src/impl/browser/web_contents/web_drag_source_efl.cc
new file mode 100644 (file)
index 0000000..be8986a
--- /dev/null
@@ -0,0 +1,188 @@
+// Copyright (c) 2015 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a license that can be
+// found in the LICENSE file.
+
+#include "browser/web_contents/web_drag_source_efl.h"
+
+#include "web_contents_delegate_efl.h"
+#include "content/browser/download/drag_download_util.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/common/drop_data.h"
+#include "third_party/skia/include/core/SkPixelRef.h"
+#include "ui/gfx/screen.h"
+
+namespace content {
+
+namespace {
+blink::WebDragOperation GetWebOperationFromMask(
+    blink::WebDragOperationsMask allowed_ops)
+{
+  if (allowed_ops & blink::WebDragOperationCopy)
+    return blink::WebDragOperationCopy;
+  if (allowed_ops & blink::WebDragOperationLink)
+    return blink::WebDragOperationLink;
+  if (allowed_ops & blink::WebDragOperationMove)
+    return blink::WebDragOperationMove;
+  if (allowed_ops & blink::WebDragOperationGeneric)
+    return blink::WebDragOperationGeneric;
+  if (allowed_ops & blink::WebDragOperationPrivate)
+    return blink::WebDragOperationPrivate;
+  if (allowed_ops & blink::WebDragOperationDelete)
+    return blink::WebDragOperationDelete;
+  return blink::WebDragOperationNone;
+}
+
+Evas_Object* DragIconCreateCb(void* data, Evas_Object* win,
+    Evas_Coord* xoff, Evas_Coord* yoff) {
+  WebDragSourceEfl* web_drag_source_efl = static_cast<WebDragSourceEfl*>(data);
+  return web_drag_source_efl->DragIconCreate(win, xoff, yoff);
+}
+
+void DragPosCb(void* data, Evas_Object* obj, Evas_Coord x, Evas_Coord y,
+    Elm_Xdnd_Action action) {
+  WebDragSourceEfl *web_drag_source_efl = static_cast<WebDragSourceEfl*>(data);
+  web_drag_source_efl->DragPos(x, y, action);
+}
+
+void DragAcceptCb(void* data, Evas_Object* obj, Eina_Bool doaccept) {
+}
+
+void DragStateCb(void* data, Evas_Object* obj) {
+  WebDragSourceEfl* web_drag_source_efl = static_cast<WebDragSourceEfl*>(data);
+  web_drag_source_efl->DragState();
+}
+
+} // namespace
+
+WebDragSourceEfl::WebDragSourceEfl(WebContents* web_contents, EWebView* eweb_view)
+    : web_contents_(static_cast<WebContentsImpl*>(web_contents)),
+      eweb_view_(eweb_view),
+      drag_failed_(false),
+      drag_started_(false) {
+}
+
+WebDragSourceEfl::~WebDragSourceEfl() {
+}
+
+bool WebDragSourceEfl::StartDragging(const DropData& drop_data,
+                                     blink::WebDragOperationsMask allowed_ops,
+                                     const gfx::Point& root_location,
+                                     const SkBitmap& image,
+                                     const gfx::Vector2d& image_offset) {
+  // Guard against re-starting before previous drag completed.
+  if (drag_started_) {
+    NOTREACHED();
+    return false;
+  }
+
+  int targets_mask = 0;
+  drop_data_.reset(new DropData(drop_data));
+
+  if (!drop_data.text.string().empty())
+    targets_mask |= ELM_SEL_FORMAT_TEXT;
+  if (drop_data.url.is_valid())
+    targets_mask |= ELM_SEL_FORMAT_TEXT;
+  if (!drop_data.html.string().empty())
+    targets_mask |= ELM_SEL_FORMAT_HTML;
+  if (!drop_data.file_contents.empty())
+    targets_mask |= ELM_SEL_FORMAT_IMAGE;
+  if (!drop_data.download_metadata.empty() &&
+      ParseDownloadMetadata(drop_data.download_metadata,
+                            &wide_download_mime_type_,
+                            &download_file_name_,
+                            &download_url_))
+    targets_mask |= ELM_SEL_FORMAT_IMAGE;
+  if (!drop_data.custom_data.empty())
+    targets_mask |= ELM_SEL_FORMAT_NONE;
+
+  int action = 0;
+
+  if (allowed_ops & blink::WebDragOperationCopy)
+    action |= ELM_XDND_ACTION_COPY;
+  if (allowed_ops & blink::WebDragOperationLink)
+    action |= ELM_XDND_ACTION_LINK ;
+  if (allowed_ops & blink::WebDragOperationMove)
+    action |= ELM_XDND_ACTION_MOVE;
+  if(!action)
+    action = ELM_XDND_ACTION_UNKNOWN;
+
+  image_ = image;
+  image_offset_ = image_offset;
+  drag_action_ = allowed_ops;
+  drag_failed_ = false;
+  device_scale_factor_ = gfx::Screen::GetNativeScreen()->
+      GetPrimaryDisplay().device_scale_factor();
+
+  drag_started_ = elm_drag_start(eweb_view_->evas_object(),
+                                  static_cast<Elm_Sel_Format>(targets_mask),
+                                  reinterpret_cast<char*>(drop_data_.get()),
+                                  static_cast<Elm_Xdnd_Action>(action),
+                                  DragIconCreateCb, this,
+                                  DragPosCb, this,
+                                  DragAcceptCb, this,
+                                  DragStateCb, this);
+
+  // Sometimes the drag fails to start; |drag_started_| will be false and we won't
+  // get a drag-end signal.
+  if (!drag_started_) {
+    LOG(WARNING) << "Failed to start drag and drop";
+    drag_failed_ = true;
+    drop_data_.reset();
+    return false;
+  }
+
+  return true;
+}
+
+Evas_Object* WebDragSourceEfl::DragIconCreate(
+    Evas_Object* win, Evas_Coord* xoff, Evas_Coord* yoff) const {
+  int w = image_.width(), h = image_.height(), x, y;
+
+  gfx::Point position = eweb_view_->GetContextMenuPosition();
+
+  // set icon position above the touch point
+  x = position.x() - w / 2;
+  y = position.y() - h;
+
+  if (xoff) *xoff = x;
+  if (yoff) *yoff = y;
+  Evas* evas = evas_object_evas_get(win);
+  Evas_Object* icon = evas_object_image_add(evas);
+  evas_object_image_size_set(icon, w, h);
+  evas_object_image_alpha_set(icon, EINA_TRUE);
+  evas_object_image_data_copy_set(icon, image_.pixelRef()->pixels());
+  evas_object_size_hint_align_set(icon,
+      EVAS_HINT_FILL, EVAS_HINT_FILL);
+  evas_object_size_hint_weight_set(icon,
+      EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+  evas_object_move(icon, x, y);
+  evas_object_image_fill_set(icon, 0, 0, w, h);
+  evas_object_resize(icon, w, h);
+  evas_object_show(icon);
+
+  return icon;
+}
+
+void WebDragSourceEfl::DragPos(Evas_Coord x, Evas_Coord y,
+    Elm_Xdnd_Action action) {
+  gfx::Point screen_pt = gfx::Point(x / device_scale_factor_,
+                                    y / device_scale_factor_);
+  last_pointer_pos_ = screen_pt;
+}
+
+void WebDragSourceEfl::DragState() {
+  double page_scale = eweb_view_->GetScale();
+
+  gfx::Point client_pt = gfx::Point(last_pointer_pos_.x() / page_scale,
+                                    last_pointer_pos_.y() / page_scale);
+
+  web_contents_->DragSourceEndedAt(
+      client_pt.x(), client_pt.y(),
+      last_pointer_pos_.x(), last_pointer_pos_.y(),
+      GetWebOperationFromMask(drag_action_));
+
+  web_contents_->SystemDragEnded();
+  drag_started_ = false;
+}
+
+}  // namespace content
diff --git a/tizen_src/impl/browser/web_contents/web_drag_source_efl.h b/tizen_src/impl/browser/web_contents/web_drag_source_efl.h
new file mode 100644 (file)
index 0000000..9377841
--- /dev/null
@@ -0,0 +1,98 @@
+// Copyright (c) 2014 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_WEB_CONTENTS_WEB_DRAG_SOURCE_EFL_H_
+#define CONTENT_BROWSER_WEB_CONTENTS_WEB_DRAG_SOURCE_EFL_H_
+
+#include <Elementary.h>
+
+#include "base/basictypes.h"
+#include "base/files/file_path.h"
+#include "base/strings/string16.h"
+#include "eweb_view.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/WebKit/public/web/WebDragOperation.h"
+#include "ui/gfx/point.h"
+#include "ui/gfx/vector2d.h"
+#include "url/gurl.h"
+
+namespace content {
+
+class WebContents;
+class WebContentsImpl;
+
+struct DropData;
+
+// WebDragSourceEfl takes care of managing the drag from a WebContents
+// with Efl.
+class WebDragSourceEfl {
+ public:
+  explicit WebDragSourceEfl(WebContents* web_contents, EWebView* eweb_view);
+  virtual ~WebDragSourceEfl();
+
+  // Starts a drag for the WebContents this object was created for.
+  // Returns false if the drag could not be started.
+  bool StartDragging(const DropData& drop_data,
+                     blink::WebDragOperationsMask allowed_ops,
+                     const gfx::Point& root_location,
+                     const SkBitmap& image,
+                     const gfx::Vector2d& image_offset);
+
+  void Reset() { drag_started_ = false; }
+  void SetLastPoint(gfx::Point point) { last_point_ = point; }
+  bool IsDragging() { return drag_started_; }
+
+  // EFL callbacks
+  Evas_Object* DragIconCreate(Evas_Object* win, Evas_Coord* xoff, Evas_Coord* yoff) const;
+  void DragPos(Evas_Coord x, Evas_Coord y, Elm_Xdnd_Action action);
+  void DragState();
+
+ private:
+  EWebView* eweb_view_;
+
+  // The tab we're manging the drag for.
+  WebContentsImpl* web_contents_;
+
+  // The drop data for the current drag (for drags that originate in the render
+  // view). Non-NULL iff there is a current drag.
+  scoped_ptr<DropData> drop_data_;
+
+  // The image used for depicting the drag, and the offset between the cursor
+  // and the top left pixel.
+  SkBitmap image_;
+  gfx::Vector2d image_offset_;
+
+  // Whether the current drag has failed. Meaningless if we are not the source
+  // for a current drag.
+  bool drag_failed_;
+
+  // True set once drag starts.  A false value indicates that there is
+  // no drag currently in progress.
+  bool drag_started_;
+
+  // Last registered point from drag_pos_cb callback.
+  gfx::Point last_point_;
+
+  // Maks of all available drag actions linke copy, move or link
+  blink::WebDragOperationsMask drag_action_;
+
+  // The file mime type for a drag-out download.
+  base::string16 wide_download_mime_type_;
+
+  // The file name to be saved to for a drag-out download.
+  base::FilePath download_file_name_;
+
+  // The URL to download from for a drag-out download.
+  GURL download_url_;
+
+  float device_scale_factor_;
+
+  gfx::Point last_pointer_pos_;
+
+  DISALLOW_COPY_AND_ASSIGN(WebDragSourceEfl);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_WEB_CONTENTS_WEB_DRAG_SOURCE_EFL_H_
index 8f22a795850a24129ccac8f9791588af66b254e8..15a9a11984cc95524bb987c0b35fbc3cc37b0243 100644 (file)
       'browser/web_contents/web_contents_view_efl.h',
       'browser/web_contents/web_drag_dest_efl.cc',
       'browser/web_contents/web_drag_dest_efl.h',
+      'browser/web_contents/web_drag_source_efl.cc',
+      'browser/web_contents/web_drag_source_efl.h',
       'browser/web_view_browser_message_filter.h',
       'browser/web_view_browser_message_filter.cc',
       'browser/webdata/web_data_service.cc',
index 778d500205def6a97cf7bdaf1a231f49cd7ed074..38ded977567e7adc942d0f14d0b65be22089a357 100644 (file)
@@ -14,6 +14,7 @@
 #include "cc/base/switches.h"
 #include "ui/events/event_switches.h"
 #include "extensions/common/switches.h"
+#include "ui/base/ui_base_switches.h"
 #include "ui/gl/gl_switches.h"
 #include "url/gurl.h"
 
@@ -84,6 +85,8 @@ content::MainFunctionParams CommandLineEfl::GetDefaultPortParams() {
   p_command_line->AppendSwitch(cc::switches::kEnableParallelCanvasMode);
 #endif
 
+  p_command_line->AppendSwitch(switches::kEnableTouchDragDrop);
+
   if (p_command_line->HasSwitch(switches::kDisableIpcSandbox))
     p_command_line->AppendSwitch(switches::kDisableRendererZygote);
 
index e466fc5f8c6c8ca0c6f58649edc4e8214cf2c9b4..8dd9e2c7f02fb7a337676fb4128a634a089fd686 100644 (file)
@@ -664,9 +664,7 @@ void EWebView::SetOrientation(int orientation) {
       screen_orientation_ == 90  ||
       screen_orientation_ == 180 ||
       screen_orientation_ == 270) {
-    WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(web_contents_.get());
-    WebContentsViewEfl* web_contents_view = static_cast<WebContentsViewEfl*>(web_contents->GetView());
-    web_contents_view->SetOrientation(screen_orientation_);
+    GetWebContentsViewEfl()->SetOrientation(screen_orientation_);
 
     // workaround for platform issue not resizing popup after rotation
     // this should be removed when when proper fix will be applied for platorm.
@@ -905,6 +903,11 @@ void EWebView::HandleTapGesture(int x, int y,
   }
 }
 
+content::WebContentsViewEfl* EWebView::GetWebContentsViewEfl() const {
+  WebContentsImpl* wc = static_cast<WebContentsImpl*>(web_contents_.get());
+  return static_cast<WebContentsViewEfl*>(wc->GetView());
+}
+
 void EWebView::HandlePostponedGesture(int x, int y, ui::EventType type) {
   LOG(INFO) << "HandlePostponedGesture :: " << type;
   switch (type) {
@@ -1378,6 +1381,8 @@ void EWebView::ShowContextMenu(
   convertedParams.x += x;
   convertedParams.y += y;
 
+  context_menu_position_ = gfx::Point(convertedParams.x, convertedParams.y);
+
   if (!selection_controller_->IsShowingMagnifier() &&
       selection_controller_->IsCaretSelection()) {
     if(!context_menu_->PopulateAndShowContextMenu(convertedParams))
@@ -2121,6 +2126,10 @@ void EWebView::SetCertificatePem(const std::string& certificate) {
   SmartCallback<EWebViewCallbacks::SetCertificatePem>().call(pem_certificate_.c_str());
 }
 
+bool EWebView::IsDragging() const {
+  return GetWebContentsViewEfl()->IsDragging();
+}
+
 void EWebView::ShowFileChooser(const content::FileChooserParams& params) {
   RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
   if (!render_view_host)
@@ -2147,9 +2156,11 @@ void EWebView::ShowFileChooser(const content::FileChooserParams& params) {
 }
 
 void EWebView::SetViewMode(tizen_webview::View_Mode view_mode) {
-  WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(web_contents_.get());
-  WebContentsViewEfl *web_contents_view = static_cast<WebContentsViewEfl*>(web_contents->GetView());
-  web_contents_view->SetViewMode(view_mode);
+  GetWebContentsViewEfl()->SetViewMode(view_mode);
+}
+
+gfx::Point EWebView::GetContextMenuPosition() const {
+  return context_menu_position_;
 }
 
 #ifdef TIZEN_CONTENTS_DETECTION
index 70291ab2081581e556130a8a67305cb334023b24..d58e5d32b2fe5659e6759e6633cf3dc66c35cf21 100644 (file)
@@ -76,6 +76,7 @@ class RenderWidgetHostViewEfl;
 class WebContentsDelegateEfl;
 class ContextMenuControllerEfl;
 class DevToolsDelegateEfl;
+class WebContentsViewEfl;
 #ifdef TIZEN_CONTENTS_DETECTION
 class PopupControllerEfl;
 #endif
@@ -429,6 +430,7 @@ class EWebView {
   void DidChangeContentsArea(int width, int height);
   void SetBrowserFont();
   void SetCertificatePem(const std::string& certificate);
+  bool IsDragging() const;
 
   void RequestColorPicker(int r, int g, int b, int a);
   void DismissColorPicker();
@@ -460,6 +462,8 @@ class EWebView {
   void SetOverrideEncoding(const std::string& encoding);
   void SetViewMode(tizen_webview::View_Mode view_mode);
 
+  gfx::Point GetContextMenuPosition() const;
+
   /// ---- Event handling
   bool HandleShow();
   bool HandleHide();
@@ -488,6 +492,7 @@ class EWebView {
       tizen_webview::Hit_Test*);
   void HandleTapGesture(int x, int y, tizen_webview::Hit_Test_Mode mode,
       tizen_webview::Hit_Test*);
+  content::WebContentsViewEfl* GetWebContentsViewEfl() const;
 
 #if defined(OS_TIZEN_MOBILE) && !defined(EWK_BRINGUP)
   static void cameraResultCb(service_h request, service_h reply,
@@ -585,6 +590,8 @@ private:
 
   gfx::Vector2d previous_scroll_position_;
 
+  gfx::Point context_menu_position_;
+
   std::map<int64_t, WebViewAsyncRequestHitTestDataCallback*> hit_test_callback_;
   // only tizen_webview::WebView can create and delete this
   EWebView(tizen_webview::WebView* owner, tizen_webview::WebContext*, Evas_Object* smart_object);