[M108 Migration][Text Selection] Selection handles & Caret Selection 57/287957/8
authorv-saha <v.saha@samsung.com>
Mon, 13 Feb 2023 17:44:37 +0000 (23:14 +0530)
committerBot Blink <blinkbot@samsung.com>
Mon, 20 Feb 2023 06:24:22 +0000 (06:24 +0000)
On longpress handles are to be displayed, migrate the handler
and caret related patches.

Expose WebNode::is_text_node in ContextMenuParameters,
add is_caret_mode_forced_ to selection controller.

References:
https://review.tizen.org/gerrit/281232

Change-Id: I8450c9c91745f7000a9b1395ff6999aca878ba05
Signed-off-by: v-saha <v.saha@samsung.com>
25 files changed:
third_party/blink/common/context_menu_data/context_menu_mojom_traits.cc
third_party/blink/common/context_menu_data/context_menu_params_builder.cc
third_party/blink/common/context_menu_data/untrustworthy_context_menu_params.cc
third_party/blink/public/common/context_menu_data/context_menu_data.h
third_party/blink/public/common/context_menu_data/context_menu_mojom_traits.h
third_party/blink/public/common/context_menu_data/untrustworthy_context_menu_params.h
third_party/blink/public/mojom/context_menu/context_menu.mojom
third_party/blink/renderer/core/page/context_menu_controller.cc
tizen_src/chromium_impl/content/BUILD.gn
tizen_src/chromium_impl/content/browser/renderer_host/rwhv_aura_offscreen_helper_efl.cc
tizen_src/chromium_impl/content/browser/renderer_host/rwhv_aura_offscreen_helper_efl.h
tizen_src/chromium_impl/content/browser/selection/selection_box_efl.cc
tizen_src/chromium_impl/content/browser/selection/selection_box_efl.h
tizen_src/chromium_impl/content/browser/selection/selection_controller_efl.cc
tizen_src/chromium_impl/content/browser/selection/selection_controller_efl.h
tizen_src/chromium_impl/content/browser/selection/selection_handle_efl.cc
tizen_src/chromium_impl/content/browser/selection/selection_handle_efl.h
tizen_src/chromium_impl/content/browser/selection/selection_magnifier_efl.cc
tizen_src/chromium_impl/content/browser/selection/selection_magnifier_efl.h
tizen_src/chromium_impl/edje_resources/MainLayout.edc
tizen_src/ewk/efl_integration/browser/autofill_popup_view_efl.cc
tizen_src/ewk/efl_integration/browser/autofill_popup_view_efl.h
tizen_src/ewk/efl_integration/context_menu_controller_efl.cc
tizen_src/ewk/efl_integration/eweb_view.cc
tizen_src/ewk/efl_integration/eweb_view.h

index 67e46bd..a26b986 100644 (file)
@@ -59,6 +59,9 @@ bool StructTraits<blink::mojom::UntrustworthyContextMenuParamsDataView,
   out->media_flags = data.media_flags();
   out->spellcheck_enabled = data.spellcheck_enabled();
   out->is_editable = data.is_editable();
+#if BUILDFLAG(IS_EFL)
+  out->is_text_node = data.is_text_node();
+#endif
   out->writing_direction_default = data.writing_direction_default();
   out->writing_direction_left_to_right = data.writing_direction_left_to_right();
   out->writing_direction_right_to_left = data.writing_direction_right_to_left();
index 9c364c0..e257944 100644 (file)
@@ -55,6 +55,9 @@ UntrustworthyContextMenuParams ContextMenuParamsBuilder::Build(
   params.misspelled_word = data.misspelled_word;
   params.spellcheck_enabled = data.is_spell_checking_enabled;
   params.is_editable = data.is_editable;
+#if BUILDFLAG(IS_EFL)
+  params.is_text_node = data.is_text_node;
+#endif
   params.writing_direction_default = data.writing_direction_default;
   params.writing_direction_left_to_right = data.writing_direction_left_to_right;
   params.writing_direction_right_to_left = data.writing_direction_right_to_left;
index e670762..5ede70a 100644 (file)
@@ -62,6 +62,9 @@ void UntrustworthyContextMenuParams::Assign(
   dictionary_suggestions = other.dictionary_suggestions;
   spellcheck_enabled = other.spellcheck_enabled;
   is_editable = other.is_editable;
+#if BUILDFLAG(IS_EFL)
+  is_text_node = other.is_text_node;
+#endif
   writing_direction_default = other.writing_direction_default;
   writing_direction_left_to_right = other.writing_direction_left_to_right;
   writing_direction_right_to_left = other.writing_direction_right_to_left;
index dd207b4..611b3a8 100644 (file)
@@ -117,6 +117,10 @@ struct ContextMenuData {
   // Whether context is editable.
   bool is_editable;
 
+#if BUILDFLAG(IS_EFL)
+  bool is_text_node;
+#endif
+
   // If this node is an input field, the type of that field.
   blink::mojom::ContextMenuDataInputFieldType input_field_type;
 
@@ -171,6 +175,9 @@ struct ContextMenuData {
         media_flags(kMediaNone),
         is_spell_checking_enabled(false),
         is_editable(false),
+#if BUILDFLAG(IS_EFL)
+        is_text_node(false),
+#endif
         writing_direction_default(kCheckableMenuItemDisabled),
         writing_direction_left_to_right(kCheckableMenuItemEnabled),
         writing_direction_right_to_left(kCheckableMenuItemEnabled),
index 9e555d1..40c94c4 100644 (file)
@@ -115,6 +115,12 @@ struct BLINK_COMMON_EXPORT
     return r.is_editable;
   }
 
+#if BUILDFLAG(IS_EFL)
+  static bool is_text_node(const blink::UntrustworthyContextMenuParams& r) {
+    return r.is_text_node;
+  }
+#endif
+
   static int writing_direction_default(
       const blink::UntrustworthyContextMenuParams& r) {
     return r.writing_direction_default;
index 6f706a3..99a5b3a 100644 (file)
@@ -103,6 +103,11 @@ struct BLINK_COMMON_EXPORT UntrustworthyContextMenuParams {
   // Whether context is editable.
   bool is_editable;
 
+#if BUILDFLAG(IS_EFL)
+  // Whether node context menu was invoked on is a text node.
+  bool is_text_node;
+#endif
+
   // Writing direction menu items.
   int writing_direction_default;
   int writing_direction_left_to_right;
index 1c4d187..0aaa56f 100644 (file)
@@ -167,6 +167,10 @@ struct UntrustworthyContextMenuParams {
   // Whether context is editable.
   bool is_editable;
 
+  // Whether element is text
+  [EnableIf=is_efl]
+  bool is_text_node;
+
   // Writing direction menu items.
   int32 writing_direction_default;
   int32 writing_direction_left_to_right;
index 5501389..2d90e7e 100644 (file)
@@ -686,6 +686,10 @@ bool ContextMenuController::ShowContextMenu(LocalFrame* frame,
     }
   }
 
+#if BUILDFLAG(IS_EFL)
+  data.is_text_node = result.InnerNode()->IsTextNode();
+#endif
+
   if (result.IsContentEditable()) {
     data.is_editable = true;
     SpellChecker& spell_checker = selected_frame->GetSpellChecker();
index 62198de..70ce612 100644 (file)
@@ -5,6 +5,8 @@
 static_library("android_content_detection") {
   set_sources_assignment_filter([])
   sources = [
+    "//content/renderer/android/disambiguation_popup_helper.cc",
+    "//content/renderer/android/disambiguation_popup_helper.h",
     "//content/renderer/android/renderer_date_time_picker.cc",
     "//content/renderer/android/renderer_date_time_picker.h",
   ]
index aea5901..1e436c2 100644 (file)
@@ -549,6 +549,10 @@ void RWHVAuraOffscreenHelperEfl::OnFocusIn(void* data,
       static_cast<RWHVAuraOffscreenHelperEfl*>(data);
   thiz->FocusRWHVA();
 
+  if (IsMobileProfile() && thiz->GetSelectionController()) {
+    thiz->GetSelectionController()->ShowHandleAndContextMenuIfRequired();
+  }
+
   if (!thiz->on_focus_in_callback_.is_null())
     thiz->on_focus_in_callback_.Run();
 }
@@ -568,6 +572,10 @@ void RWHVAuraOffscreenHelperEfl::OnFocusOut(void* data,
   if (focused_window)
     focused_window->LostFocus();
 
+  if (IsMobileProfile() && thiz->GetSelectionController()) {
+    thiz->GetSelectionController()->HideHandleAndContextMenu();
+  }
+
   if (!thiz->on_focus_out_callback_.is_null())
     thiz->on_focus_out_callback_.Run();
 }
@@ -1053,6 +1061,42 @@ void RWHVAuraOffscreenHelperEfl::TextInputStateChanged(
   }
 }
 
+void RWHVAuraOffscreenHelperEfl::MoveCaret(const gfx::Point& point) {
+  if (auto* delegate = rwhv_aura_->host()->delegate()) {
+    delegate->MoveCaret(gfx::Point(point.x() / device_scale_factor_,
+                                   point.y() / device_scale_factor_));
+  }
+}
+
+void RWHVAuraOffscreenHelperEfl::SelectClosestWord(
+    const gfx::Point& touch_point) {
+  int view_x, view_y;
+  EvasToBlinkCords(touch_point.x(), touch_point.y(), &view_x, &view_y);
+
+#if !defined(EWK_BRINGUP)  // FIXME: m67 bringup
+  // FIXME: The SelectClosestWord function was removed by
+  // commit 9720a4494c8bcd24d1f496feec5cfac7582103d2 in s-chromium
+  // It will be fixed by webview team.
+  // FIXME: http://suprem.sec.samsung.net/jira/browse/TWF-2122
+  Send(new ViewMsg_SelectClosestWord(host_->GetRoutingID(), view_x, view_y));
+#endif  // EWK_BRINGUP
+}
+
+bool RWHVAuraOffscreenHelperEfl::HasSelectableText() {
+  // If the last character of textarea is '\n', We can assume an extra '\n'.
+  // Actually when you insert line break by ENTER key, '\n\n' is stored in
+  // textarea. And If you press delete key, only a '\n' character will be stored
+  // although there is no visible and selectable character in textarea. That's
+  // why we should check whether selection_text contains only one line break.
+  // Bug: http://suprem.sec.samsung.net/jira/browse/TSAM-2230
+  //
+  // Please see below commit for more information.
+  // https://codereview.chromium.org/1785603002
+  std::u16string selection_text = rwhv_aura_->GetSelectedText();
+  return !selection_text.empty() &&
+         base::UTF16ToUTF8(selection_text).compare("\n") != 0;
+}
+
 void RWHVAuraOffscreenHelperEfl::FocusedNodeChanged(
     bool editable
 #if BUILDFLAG(IS_TIZEN_TV)
index e93b196..3d47eb6 100644 (file)
@@ -145,6 +145,10 @@ class CONTENT_EXPORT RWHVAuraOffscreenHelperEfl {
 
   bool IsFocusedNodeContentEditable() const { return is_content_editable_; }
 
+  void MoveCaret(const gfx::Point& point);
+  void SelectClosestWord(const gfx::Point& touch_point);
+  bool HasSelectableText();
+
  private:
   static void OnParentViewResize(void* data, Evas*, Evas_Object*, void*);
   static void EvasObjectImagePixelsGetCallback(void*, Evas_Object*);
index f3af92d..c5a5eed 100644 (file)
@@ -5,17 +5,20 @@
 #include "selection_box_efl.h"
 
 #include "base/trace_event/trace_event.h"
+#include "content/browser/renderer_host/render_widget_host_view_aura.h"
 
 namespace content {
 
-SelectionBoxEfl::SelectionBoxEfl(Evas_Object* parent_view)
-  : status_(false),
-    is_anchor_first_(false),
-    context_params_(new ContextMenuParams()),
-    parent_view_(parent_view) {
-      context_params_->has_image_contents = false;
+SelectionBoxEfl::SelectionBoxEfl(RenderWidgetHostViewAura* rwhva)
+    : status_(false),
+      is_anchor_first_(false),
+      context_params_(new ContextMenuParams()),
+      rwhva_(rwhva) {
+  context_params_->has_image_contents = false;
 }
 
+SelectionBoxEfl::~SelectionBoxEfl() = default;
+
 void SelectionBoxEfl::UpdateSelectStringData(const std::u16string& text) {
   context_params_->selection_text = text;
 }
@@ -37,14 +40,12 @@ bool SelectionBoxEfl::UpdateRectData(const gfx::Rect& left_rect, const gfx::Rect
   left_rect_ = left_rect;
   right_rect_ = right_rect;
 
-  // Display point of context Menu
-  Evas_Coord x, y;
-  evas_object_geometry_get(parent_view_, &x, &y, 0, 0);
   //context params suppose to be global - related to evas not the web view
-  ret |= (context_params_->x != (left_rect_.x() + x));
-  ret |= (context_params_->y != (left_rect_.y() + y));
-  context_params_->x = left_rect_.x() + x;
-  context_params_->y = left_rect_.y() + y;
+  gfx::Rect view_bounds = rwhva_->offscreen_helper()->GetViewBoundsInPix();
+  ret |= (context_params_->x != (left_rect_.x() + (view_bounds.x())));
+  ret |= (context_params_->y != (left_rect_.y() + view_bounds.y()));
+  context_params_->x = left_rect_.x() + view_bounds.x();
+  context_params_->y = left_rect_.y() + view_bounds.y();
 
   return ret;
 }
@@ -54,12 +55,13 @@ bool SelectionBoxEfl::IsInEditField() const {
 }
 
 void SelectionBoxEfl::SetStatus(bool enable) {
-  bool invokeCbAtEnd = status_ != enable;
+  bool invoke_cb_at_end = status_ != enable;
   status_ = enable;
 
   // invoke CB only if mode actually changed
-  if (invokeCbAtEnd && parent_view_)
-      evas_object_smart_callback_call(parent_view_, "textselection,mode", &status_);
+  if (invoke_cb_at_end && rwhva_->offscreen_helper()->ewk_view())
+    evas_object_smart_callback_call(rwhva_->offscreen_helper()->ewk_view(),
+                                    "textselection,mode", &status_);
 }
 
 }
index f238587..aa4c8de 100644 (file)
@@ -15,12 +15,17 @@ class EWebView;
 
 namespace content {
 
+class RenderWidgetHostViewAura;
 // Hold the data related to drwaing the selection handlers
 // and context menu. Also stores all the data required for selection
 // controlling
 class SelectionBoxEfl {
  public:
-  SelectionBoxEfl(Evas_Object* parent_view);
+  explicit SelectionBoxEfl(RenderWidgetHostViewAura* rwhva);
+  ~SelectionBoxEfl();
+
+  SelectionBoxEfl(const SelectionBoxEfl&) = delete;
+  SelectionBoxEfl& operator=(const SelectionBoxEfl&) = delete;
 
   void SetStatus(bool enable);
   bool GetStatus() const { return status_; }
@@ -52,7 +57,7 @@ class SelectionBoxEfl {
   // Contains the menu item data for which context needs to be populated
   std::unique_ptr<ContextMenuParams> context_params_;
 
-  Evas_Object* parent_view_;
+  RenderWidgetHostViewAura* rwhva_;
 };
 
 }
index b8368ef..fd9168e 100644 (file)
@@ -4,11 +4,12 @@
 
 #include "selection_controller_efl.h"
 
-#include <Edje.h>
+#include <Elementary.h>
 
 #include "base/trace_event/trace_event.h"
 #include "content/browser/renderer_host/render_view_host_impl.h"
 #include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "content/browser/renderer_host/render_widget_host_view_aura.h"
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/browser/web_contents/web_contents_impl_efl.h"
 #include "content/public/browser/context_menu_params.h"
@@ -40,33 +41,39 @@ gfx::Vector2dF ComputeLineOffsetFromBottom(const gfx::SelectionBound& bound) {
   return line_offset;
 }
 
-SelectionControllerEfl::SelectionControllerEfl(Evas_Object* parent_view, WebContents& web_contents)
-    :  parent_view_(parent_view),
-       controls_temporarily_hidden_(false),
-       selection_change_reason_(Reason::Irrelevant),
-       long_mouse_press_(false),
-       selection_data_(new SelectionBoxEfl(parent_view)),
-       start_handle_(new SelectionHandleEfl(*this, SelectionHandleEfl::HANDLE_TYPE_LEFT, parent_view)),
-       end_handle_(new SelectionHandleEfl(*this, SelectionHandleEfl::HANDLE_TYPE_RIGHT, parent_view)),
-       input_handle_(new SelectionHandleEfl(*this, SelectionHandleEfl::HANDLE_TYPE_INPUT, parent_view)),
-       magnifier_(new SelectionMagnifierEfl(this, web_contents)),
-       is_selection_visible_(false),
-       handle_being_dragged_(false),
-       selection_on_empty_form_control_(false),
-       web_contents_(web_contents),
-       selection_mode_(None) {
-  evas_object_event_callback_add(parent_view_, EVAS_CALLBACK_MOVE, &EvasParentViewMoveCallback, this);
+content::WebContents* SelectionControllerEfl::web_contents() const {
+  return rwhva_->offscreen_helper()->GetWebContents();
+}
+
+SelectionControllerEfl::SelectionControllerEfl(RenderWidgetHostViewAura* rwhva)
+    : rwhva_(rwhva),
+      selection_data_(new SelectionBoxEfl(rwhva)),
+      start_handle_(
+          new SelectionHandleEfl(*this, SelectionHandleEfl::HANDLE_TYPE_LEFT)),
+      end_handle_(
+          new SelectionHandleEfl(*this, SelectionHandleEfl::HANDLE_TYPE_RIGHT)),
+      input_handle_(
+          new SelectionHandleEfl(*this, SelectionHandleEfl::HANDLE_TYPE_INPUT)),
+      magnifier_(new SelectionMagnifierEfl(this)),
+      selection_mode_(None) {
+  evas_object_event_callback_add(rwhva_->offscreen_helper()->content_image(),
+                                 EVAS_CALLBACK_MOVE,
+                                 &EvasParentViewMoveCallback, this);
 #if BUILDFLAG(IS_TIZEN)
   vconf_notify_key_changed(VCONFKEY_LANGSET, PlatformLanguageChanged, this);
 #endif
 }
 
 SelectionControllerEfl::~SelectionControllerEfl() {
+  if (ecore_events_filter_)
+    ecore_event_filter_del(ecore_events_filter_);
   if (GetSelectionStatus())
     ClearSelectionViaEWebView();
   HideHandleAndContextMenu();
 
-  evas_object_event_callback_del(parent_view_, EVAS_CALLBACK_MOVE, &EvasParentViewMoveCallback);
+  evas_object_event_callback_del(rwhva_->offscreen_helper()->content_image(),
+                                 EVAS_CALLBACK_MOVE,
+                                 &EvasParentViewMoveCallback);
 }
 
 void SelectionControllerEfl::SetSelectionStatus(bool enable) {
@@ -114,15 +121,10 @@ void SelectionControllerEfl::SetControlsTemporarilyHidden(bool value) {
                "controls are hidden:", value);
   if (controls_temporarily_hidden_ == value)
     return;
-#if !defined(USE_AURA)
-  RenderWidgetHostViewEfl* rwhv = static_cast<RenderWidgetHostViewEfl*>(
-      web_contents_.GetRenderWidgetHostView());
-  CHECK(rwhv);
   // Make sure to show selection controls only when no finger
   // is left touching the screen.
-  if (!value && rwhv->PointerStatePointerCount())
+  if (!value && rwhva_->event_handler()->pointer_state().GetPointerCount())
     return;
-#endif
   controls_temporarily_hidden_ = value;
   if (value) {
     Clear();
@@ -157,18 +159,30 @@ void SelectionControllerEfl::OnSelectionChanged(
   truncated_end = gfx::ToEnclosingRect(
       gfx::ConvertRectToPixels(truncated_end, device_scale_factor));
 
+  if (handle_being_dragged_ &&
+      dragging_handle_->Type() != SelectionHandleEfl::HANDLE_TYPE_INPUT) {
+    dragging_handle_->MoveObject(selection_data_->GetIsAnchorFirst()
+                                     ? truncated_end.bottom_right()
+                                     : truncated_start.bottom_left());
+  }
+
   bool finger_down = handle_being_dragged_ || long_mouse_press_;
   bool show = (selection_change_reason_ != Reason::Irrelevant) && !finger_down;
   UpdateSelectionDataAndShow(
       truncated_start, truncated_end, show);
   selection_change_reason_ = Reason::Irrelevant;
+
+  // In case of the selected text contains only line break and no other
+  // characters, we should use caret selection mode.
+  if (GetSelectionEditable() && !handle_being_dragged_ &&
+      rwhva_->GetSelectedText() == (u"\n")) {
+    rwhva_->offscreen_helper()->MoveCaret(
+        selection_data_->GetLeftRect().origin());
+    is_caret_mode_forced_ = true;
+  }
 }
 
 void SelectionControllerEfl::OnTextInputStateChanged() {
-#if !defined(USE_AURA)
-  RenderWidgetHostViewEfl* rwhv = static_cast<RenderWidgetHostViewEfl*>(
-      web_contents_.GetRenderWidgetHostView());
-  CHECK(rwhv);
   // In order to confirm if a long press gesture is ongoing,
   // we just needed to check "long_mouse_press_".
   // However, when long press happens on a link or image,
@@ -176,7 +190,8 @@ void SelectionControllerEfl::OnTextInputStateChanged() {
   // although finger is still down.
   // To compensate this, add an extra check asking from the engine
   // if a finger is still touching down.
-  bool is_touch_down = rwhv->PointerStatePointerCount() > 0;
+  bool is_touch_down =
+      rwhva_->event_handler()->pointer_state().GetPointerCount() > 0;
 
   // If on an editable field and in caret selection mode, only
   // show the large handle if:
@@ -185,12 +200,12 @@ void SelectionControllerEfl::OnTextInputStateChanged() {
   //    handling "tap" gesture.
   bool finger_down = handle_being_dragged_ || long_mouse_press_ || is_touch_down;
 
-  if (GetSelectionEditable() && !finger_down && !controls_temporarily_hidden_ &&
+  if (GetSelectionEditable() && GetCaretSelectionStatus() && !finger_down &&
+      !controls_temporarily_hidden_ &&
       selection_change_reason_ == Reason::Irrelevant) {
     HideHandleAndContextMenu();
     ClearSelection();
   }
-#endif
 }
 
 void SelectionControllerEfl::UpdateSelectionData(const std::u16string& text) {
@@ -198,17 +213,14 @@ void SelectionControllerEfl::UpdateSelectionData(const std::u16string& text) {
 }
 
 bool SelectionControllerEfl::ClearSelectionViaEWebView() {
-  if (!GetSelectionStatus() || !web_contents_.GetRenderViewHost() ||
-      web_contents_.IsBeingDestroyed()) {
+  if (!GetSelectionStatus() || !web_contents()->GetRenderViewHost() ||
+      web_contents()->IsBeingDestroyed()) {
     return false;
   }
 
-  // RenderWidgetHostImpl* rwhi = static_cast<RenderWidgetHostImpl*>(
-  //    web_contents_.GetRenderViewHost()->GetWidget());
-  // rwhi->ExecuteEditCommand("Unselect", "");
-
   RenderWidgetHostDelegate* host_delegate =
-      RenderWidgetHostImpl::From(web_contents_.GetRenderViewHost()->GetWidget())
+      RenderWidgetHostImpl::From(
+          web_contents()->GetRenderViewHost()->GetWidget())
           ->delegate();
   if (host_delegate) {
     host_delegate->ExecuteEditCommand("Unselect", absl::nullopt);
@@ -221,6 +233,14 @@ void SelectionControllerEfl::SetSelectionMode(enum SelectionMode mode) {
   selection_mode_ = mode;
 }
 
+void SelectionControllerEfl::ToggleCaretAfterSelection() {
+  if (!GetCaretSelectionStatus() && GetSelectionEditable()) {
+    rwhva_->offscreen_helper()->MoveCaret(
+        selection_data_->GetRightRect().origin());
+    ClearSelection();
+  }
+}
+
 void SelectionControllerEfl::DetermineSelectionMode(
     const gfx::Rect& left_rect,
     const gfx::Rect& right_rect) {
@@ -286,8 +306,8 @@ void SelectionControllerEfl::ShowHandleAndContextMenuIfRequired(
     return;
   }
 
-  bool is_any_handle_visible = start_selection_.visible() ||
-      end_selection_.visible();
+  bool is_selection_range_visible =
+      start_selection_.visible() || end_selection_.visible();
 
   // Is in edit field and no text is selected. show only single handle
   if (selection_data_->IsInEditField() && left == right) {
@@ -296,7 +316,7 @@ void SelectionControllerEfl::ShowHandleAndContextMenuIfRequired(
 
     CHECK(start_selection_ == end_selection_);
 
-    if (GetCaretSelectionStatus() && is_any_handle_visible) {
+    if (GetCaretSelectionStatus() && is_selection_range_visible) {
       gfx::Rect left = selection_data_->GetLeftRect();
       input_handle_->SetBasePosition(gfx::Point(left.x(), left.y()));
       input_handle_->Move(left.bottom_right());
@@ -305,10 +325,11 @@ void SelectionControllerEfl::ShowHandleAndContextMenuIfRequired(
     start_handle_->Hide();
     end_handle_->Hide();
 
-    bool show_context_menu = is_any_handle_visible &&
-                             effective_reason != Reason::ScrollOrZoomGestureEnded &&
-                             effective_reason != Reason::Tap &&
-                             effective_reason != Reason::Irrelevant;
+    bool show_context_menu =
+        IsAnyHandleVisible() &&
+        effective_reason != Reason::ScrollOrZoomGestureEnded &&
+        effective_reason != Reason::Tap &&
+        effective_reason != Reason::Irrelevant;
     if (!handle_being_dragged_ && show_context_menu)
       ShowContextMenu();
 
@@ -346,8 +367,9 @@ void SelectionControllerEfl::ShowHandleAndContextMenuIfRequired(
   // Do not show the context menu during selection extend and
   // offscreen selection.
   if (!handle_being_dragged_ && effective_reason != Reason::Irrelevant &&
-      is_any_handle_visible)
+      IsAnyHandleVisible()) {
     ShowContextMenu();
+  }
 }
 
 void SelectionControllerEfl::ShowContextMenu() {
@@ -401,14 +423,43 @@ void SelectionControllerEfl::Clear() {
   input_handle_->Hide();
 }
 
-void SelectionControllerEfl::HandleDragBeginNotification(SelectionHandleEfl* handle) {
+Eina_Bool SelectionControllerEfl::EcoreEventFilterCallback(void* user_data,
+                                                           void* /*loop_data*/,
+                                                           int type,
+                                                           void* event_info) {
+  if (type == ECORE_EVENT_MOUSE_MOVE) {
+    auto controller = static_cast<SelectionControllerEfl*>(user_data);
+    if (!controller || !controller->dragged_handle_)
+      return ECORE_CALLBACK_PASS_ON;
+
+    auto event = static_cast<Ecore_Event_Mouse_Move*>(event_info);
+    controller->dragged_handle_->UpdatePosition(gfx::Point(event->x, event->y));
+    return ECORE_CALLBACK_CANCEL;
+  }
+
+  return ECORE_CALLBACK_PASS_ON;
+}
+
+void SelectionControllerEfl::HandleDragBeginNotification(
+    SelectionHandleEfl* handle) {
+  selection_change_reason_ = Reason::HandleDragged;
+  dragged_handle_ = handle;
+  ecore_events_filter_ =
+      ecore_event_filter_add(nullptr, EcoreEventFilterCallback, nullptr, this);
+
+  if (!ecore_events_filter_) {
+    LOG(ERROR) << __PRETTY_FUNCTION__
+               << " : Unable to create ecore events filter";
+  }
+
   // Hide context menu on mouse down
   CancelContextMenu(0);
 
   handle_being_dragged_ = true;
 
   Evas_Coord x, y;
-  evas_object_geometry_get(parent_view_, &x, &y, 0, 0);
+  evas_object_geometry_get(rwhva_->offscreen_helper()->content_image(), &x, &y,
+                           0, 0);
   gfx::Point magnifier_point(
       handle->GetBasePosition().x() + x,
       handle->GetBasePosition().y() + y);
@@ -448,33 +499,29 @@ void SelectionControllerEfl::HandleDragBeginNotification(SelectionHandleEfl* han
   base += base_offset;
   extent += extent_offset;
 
-  WebContentsImpl* wci = static_cast<WebContentsImpl*>(&web_contents_);
+  WebContentsImpl* wci = static_cast<WebContentsImpl*>(web_contents());
   wci->SelectRange(gfx::ToFlooredPoint(base), gfx::ToFlooredPoint(extent));
 }
 
 void SelectionControllerEfl::HandleDragUpdateNotification(SelectionHandleEfl* handle) {
+  if (!rwhva_)
+    return;
 
   // FIXME : Check the text Direction later
-  Evas_Coord x, y;
-  evas_object_geometry_get(parent_view_, &x, &y, 0, 0);
+  gfx::Rect view_bounds = rwhva_->offscreen_helper()->GetViewBoundsInPix();
   selection_change_reason_ = Reason::HandleDragged;
 
   gfx::Point magnifier_point;
-  magnifier_point.set_x(handle->GetBasePosition().x() + x);
-  magnifier_point.set_y(handle->GetBasePosition().y() + y);
+  magnifier_point.set_x(handle->GetBasePosition().x() + view_bounds.x());
+  magnifier_point.set_y(handle->GetBasePosition().y() + view_bounds.y());
   magnifier_->UpdateLocation(magnifier_point);
   magnifier_->Move(magnifier_point);
 
   switch (handle->Type()) {
-#if !defined(USE_AURA)
     case SelectionHandleEfl::HANDLE_TYPE_INPUT: {
-      RenderWidgetHostViewEfl* rwhv =
-          static_cast<RenderWidgetHostViewEfl*>(web_contents_.GetRenderWidgetHostView());
-      if (rwhv)
-        rwhv->MoveCaret(handle->GetBasePosition());
+      rwhva_->offscreen_helper()->MoveCaret(handle->GetBasePosition());
       return;
     }
-#endif
     case SelectionHandleEfl::HANDLE_TYPE_LEFT:
     case SelectionHandleEfl::HANDLE_TYPE_RIGHT: {
       float device_scale_factor =
@@ -488,7 +535,7 @@ void SelectionControllerEfl::HandleDragUpdateNotification(SelectionHandleEfl* ha
                                    : ComputeLineOffsetFromBottom(end_selection_);
       extent += line_offset;
 
-      WebContentsImpl* wci = static_cast<WebContentsImpl*>(&web_contents_);
+      WebContentsImpl* wci = static_cast<WebContentsImpl*>(web_contents());
       wci->MoveRangeSelectionExtent(gfx::ToFlooredPoint(extent));
       return;
     }
@@ -496,6 +543,12 @@ void SelectionControllerEfl::HandleDragUpdateNotification(SelectionHandleEfl* ha
 }
 
 void SelectionControllerEfl::HandleDragEndNotification() {
+  dragged_handle_ = nullptr;
+
+  if (ecore_events_filter_)
+    ecore_event_filter_del(ecore_events_filter_);
+  ecore_events_filter_ = nullptr;
+
   selection_change_reason_ = Reason::Irrelevant;
   magnifier_->Hide();
   start_handle_->SetBasePosition(selection_data_->GetLeftRect().bottom_left());
@@ -535,7 +588,9 @@ void SelectionControllerEfl::HandleGesture(blink::WebGestureEvent& event) {
   }
 }
 
-void SelectionControllerEfl::HandlePostponedGesture(int x, int y, ui::EventType type) {
+void SelectionControllerEfl::HandlePostponedGesture(int x,
+                                                    int y,
+                                                    ui::EventType type) {
   DVLOG(0) << "HandlePostponedGesture :: " << type;
 #if !defined(USE_AURA)
   RenderWidgetHostViewEfl* rwhv =
@@ -583,14 +638,13 @@ bool SelectionControllerEfl::HandleLongPressEvent(
 #endif
     SetSelectionStatus(true);
     SetSelectionEditable(true);
+    if (selection_mode_ == None)
+      SetSelectionMode(Caret);
     HandleLongPressEventPrivate(touch_point);
     return true;
-  } else if (params.link_url.is_empty() && params.src_url.is_empty()
-#if !defined(EWK_BRINGUP)  // FIXME: m67 bringup
-             && params.is_text_node) {
-#else
-                 ) {
-#endif
+  } else if (params.link_url.is_empty() && params.src_url.is_empty() &&
+                 params.is_text_node ||
+             !params.selection_text.empty()) {
     // If user is long pressing on a content with
     // -webkit-user-select: none, we should bail and not enter
     // selection neither show magnigier class or context menu.
@@ -618,31 +672,18 @@ bool SelectionControllerEfl::HandleLongPressEvent(
   return true;
 }
 
-void SelectionControllerEfl::HandleLongPressEventPrivate(const gfx::Point& touch_point) {
+void SelectionControllerEfl::HandleLongPressEventPrivate(
+    const gfx::Point& touch_point) {
   Clear();
 
-  Evas_Coord x, y;
-  evas_object_geometry_get(parent_view_, &x, &y, 0, 0);
-  magnifier_->HandleLongPress(gfx::Point(touch_point.x() + x,
-                                         touch_point.y() + y));
+  gfx::Rect view_bounds = rwhva_->offscreen_helper()->GetViewBoundsInPix();
+  magnifier_->HandleLongPress(gfx::Point(touch_point.x() + view_bounds.x(),
+                                         touch_point.y() + view_bounds.y()));
 }
 
 void SelectionControllerEfl::HandleLongPressMoveEvent(const gfx::Point& touch_point) {
-#if !defined(USE_AURA)
-  RenderWidgetHostViewEfl* rwhv =
-      static_cast<RenderWidgetHostViewEfl*>(web_contents_.GetRenderWidgetHostView());
-  Clear();
-  selection_change_reason_ = Reason::LongPressMoved;
-  if (selection_data_->IsInEditField()) {
-    Evas_Coord x, y;
-    evas_object_geometry_get(parent_view_, &x, &y, 0, 0);
-    if (rwhv)
-      rwhv->MoveCaret(gfx::Point(touch_point.x() - x, touch_point.y() - y));
-  } else{
-    if (rwhv)
-      rwhv->SelectClosestWord(touch_point);
-  }
-#endif
+  if (rwhva_)
+    rwhva_->offscreen_helper()->SelectClosestWord(touch_point);
 }
 
 void SelectionControllerEfl::HandleLongPressEndEvent() {
@@ -652,14 +693,12 @@ void SelectionControllerEfl::HandleLongPressEndEvent() {
 }
 
 void SelectionControllerEfl::PostHandleTapGesture(bool is_content_editable) {
-  HideHandleAndContextMenu();
   if (is_content_editable) {
     DVLOG(1) << "PostHandleTapGesture :: Editable";
     SetSelectionStatus(true);
     SetSelectionEditable(true);
     selection_change_reason_ = Reason::Tap;
   } else {
-    ClearSelectionViaEWebView();
     SetSelectionEditable(false);
   }
 }
@@ -695,6 +734,7 @@ bool SelectionControllerEfl::IsSelectionValid(const gfx::Rect& left_rect,
 void SelectionControllerEfl::ClearSelection() {
   TRACE_EVENT0("selection,efl", __PRETTY_FUNCTION__);
   Clear();
+  CancelContextMenu(0);
   SetSelectionStatus(false);
   SetSelectionEditable(false);
   SetSelectionMode(None);
@@ -719,7 +759,8 @@ void SelectionControllerEfl::ChangeContextMenuPosition(gfx::Point& position, int
   int handleHeight, webViewX, webViewY, webViewWidth, webViewHeight;
   gfx::Rect imeRect;
   edje_object_part_geometry_get(input_handle_->evas_object(), "handle", 0, 0, 0, &handleHeight);
-  evas_object_geometry_get(GetParentView(), &webViewX, &webViewY, &webViewWidth, &webViewHeight);
+  evas_object_geometry_get(rwhva_->offscreen_helper()->content_image(),
+                           &webViewX, &webViewY, &webViewWidth, &webViewHeight);
   gfx::Rect viewportRect = gfx::Rect(webViewX, webViewY, webViewWidth, webViewHeight);
 #if !defined(USE_AURA)
   RenderWidgetHostViewEfl* rwhv =
@@ -846,6 +887,14 @@ void SelectionControllerEfl::ChangeContextMenuPosition(gfx::Point& position, int
   return;
 }
 
+gfx::Rect SelectionControllerEfl::GetVisibleViewportRect() const {
+  if (custom_visible_view_rect_.IsEmpty())
+    return rwhva_->offscreen_helper()->GetViewBoundsInPix();
+
+  return gfx::IntersectRects(rwhva_->offscreen_helper()->GetViewBoundsInPix(),
+                             custom_visible_view_rect_);
+}
+
 bool SelectionControllerEfl::TextSelectionDown(int x, int y) {
   /*
    * According to webkit-efl textSelectionDown is used on long press gesture, we already
index bfebbbd..7f34758 100644 (file)
@@ -25,6 +25,7 @@
 #include <libintl.h>
 
 namespace content {
+class RenderWidgetHostViewAura;
 class WebContents;
 class WebContentsImpl;
 
@@ -46,9 +47,12 @@ class CONTENT_EXPORT SelectionControllerEfl {
   };
 
  public:
-  explicit SelectionControllerEfl(Evas_Object* parent_view, WebContents& web_contents);
+  explicit SelectionControllerEfl(RenderWidgetHostViewAura* rwhva);
   ~SelectionControllerEfl();
 
+  SelectionControllerEfl(const SelectionControllerEfl&) = delete;
+  SelectionControllerEfl& operator=(const SelectionControllerEfl&) = delete;
+
   // Functions that handle long press, long press move and release
   bool HandleLongPressEvent(const gfx::Point& touch_point,
       const content::ContextMenuParams& params);
@@ -86,7 +90,6 @@ class CONTENT_EXPORT SelectionControllerEfl {
   // Clears the selection and hides context menu and handles
   void ClearSelection();
   bool ClearSelectionViaEWebView();
-  Evas_Object* GetParentView() const { return parent_view_; }
   void HideHandles();
   void HideHandleAndContextMenu();
   bool IsAnyHandleVisible() const;
@@ -120,6 +123,7 @@ class CONTENT_EXPORT SelectionControllerEfl {
     LongPressEnded,
     Tap,
     RequestedByContextMenu,
+    CaretModeForced,
     Irrelevant,
   };
   void SetWaitsForRendererSelectionChanges(
@@ -129,6 +133,20 @@ class CONTENT_EXPORT SelectionControllerEfl {
   void HandlePostponedGesture(int x, int y, ui::EventType type);
   void HandleGesture(blink::WebGestureEvent& event);
 
+  gfx::Rect GetVisibleViewportRect() const;
+
+  bool IsCaretModeForced() const { return is_caret_mode_forced_; }
+  void SetCustomVisibleViewRect(const gfx::Rect& custom_visible_view_rect) {
+    custom_visible_view_rect_ = custom_visible_view_rect;
+  }
+
+  void ToggleCaretAfterSelection();
+  void ShowHandleAndContextMenuIfRequired(
+      Reason explicit_reason = Reason::Irrelevant);
+
+  RenderWidgetHostViewAura* rwhva() const { return rwhva_; }
+  content::WebContents* web_contents() const;
+
  private:
   enum SelectionMode {
     None = 0,
@@ -145,16 +163,18 @@ class CONTENT_EXPORT SelectionControllerEfl {
 
   void HandleLongPressEventPrivate(const gfx::Point& touch_point);
 
-  void ShowHandleAndContextMenuIfRequired(Reason explicit_reason = Reason::Irrelevant);
-
   void Clear();
   bool IsSelectionValid(const gfx::Rect& left_rect, const gfx::Rect& right_rect);
 
   void ShowContextMenu();
   void CancelContextMenu(int request_id);
 
-  static void EvasParentViewMoveCallback(void *data, Evas *e, Evas_Object *obj, void *event_info)
-  { reinterpret_cast<SelectionControllerEfl*>(data)->OnParentParentViewMove(); }
+  static void EvasParentViewMoveCallback(void* data,
+                                         Evas* e,
+                                         Evas_Object* obj,
+                                         void* event_info) {
+    reinterpret_cast<SelectionControllerEfl*>(data)->OnParentParentViewMove();
+  }
 
 #if BUILDFLAG(IS_TIZEN)
   static void PlatformLanguageChanged(keynode_t* keynode, void* data);
@@ -162,20 +182,26 @@ class CONTENT_EXPORT SelectionControllerEfl {
 
   void OnParentParentViewMove();
 
-  Evas_Object* parent_view_;
+  static Eina_Bool EcoreEventFilterCallback(void* user_data,
+                                            void* loop_data,
+                                            int type,
+                                            void* event_info);
+
   // Is required to send back selction points and range extenstion co-ordinates
+  RenderWidgetHostViewAura* rwhva_;
 
   // Saves state so that selection controls are temporarily hidden due
   // to scrolling or zooming.
-  bool controls_temporarily_hidden_;
+  bool controls_temporarily_hidden_ = false;
 
   // Cache the reason of why browser has requested a text selection
   // change to the renderer. At the next composited selection update
   // the cache is handled and reset.
-  Reason selection_change_reason_;
+  Reason selection_change_reason_ = Reason::Irrelevant;
 
-  // Saves state so that handlers and context menu is not shown when seletion change event occurs.
-  bool long_mouse_press_;
+  // Saves state so that handlers and context menu is not shown when seletion
+  // change event occurs.
+  bool long_mouse_press_ = false;
 
   // Saves the data that are required to draw handle and context menu
   std::unique_ptr<SelectionBoxEfl> selection_data_;
@@ -198,13 +224,18 @@ class CONTENT_EXPORT SelectionControllerEfl {
   // Helper pointer to the stationary handle (during dragging).
   SelectionHandleEfl* stationary_handle_;
 
-  bool is_selection_visible_;
+  gfx::Rect custom_visible_view_rect_;
+
+  bool is_selection_visible_ = false;
+
+  bool handle_being_dragged_ = false;
 
-  bool handle_being_dragged_;
+  bool is_caret_mode_forced_ = false;
+  bool selection_on_empty_form_control_ = false;
 
-  bool selection_on_empty_form_control_;
+  Ecore_Event_Filter* ecore_events_filter_ = nullptr;
 
-  WebContents& web_contents_;
+  SelectionHandleEfl* dragged_handle_ = nullptr;
 
   enum SelectionMode selection_mode_;
   gfx::SelectionBound start_selection_;
index efb40d3..d095ff3 100644 (file)
@@ -11,7 +11,9 @@
 #include "base/files/file_path.h"
 #include "base/path_service.h"
 #include "base/trace_event/trace_event.h"
+#include "content/browser/renderer_host/render_widget_host_view_aura.h"
 #include "content/browser/selection/selection_controller_efl.h"
+#include "content/browser/web_contents/web_contents_impl.h"
 #include "content/common/paths_efl.h"
 
 namespace content {
@@ -35,13 +37,14 @@ static const char* GetEdjeObjectGroupPath(SelectionHandleEfl::HandleType type) {
   }
 }
 
-SelectionHandleEfl::SelectionHandleEfl(SelectionControllerEfl& controller, HandleType type, Evas_Object* parent)
-  : controller_(controller),
-    pressed_(false),
-    is_top_(false),
-    handle_type_(type) {
-
-  Evas* evas = evas_object_evas_get(parent);
+SelectionHandleEfl::SelectionHandleEfl(SelectionControllerEfl& controller,
+                                       HandleType type)
+    : controller_(controller),
+      pressed_(false),
+      is_top_(false),
+      handle_type_(type) {
+  Evas* evas = evas_object_evas_get(
+      controller_.rwhva()->offscreen_helper()->content_image());
   handle_ = edje_object_add(evas);
 
   base::FilePath edj_dir;
@@ -57,7 +60,12 @@ SelectionHandleEfl::SelectionHandleEfl(SelectionControllerEfl& controller, Handl
 
   edje_object_signal_emit(handle_, "edje,focus,in", "edje");
   edje_object_signal_emit(handle_, "elm,state,bottom", "elm");
-  evas_object_smart_member_add(handle_, parent);
+  Evas_Object* main_layout_ =
+      static_cast<WebContentsImpl*>(
+          controller_.rwhva()->offscreen_helper()->GetWebContents())
+          ->GetEflNativeView();
+  Evas_Object* smart_parent = evas_object_smart_parent_get(main_layout_);
+  evas_object_smart_member_add(handle_, smart_parent);
   evas_object_propagate_events_set(handle_, false);
 
   evas_object_event_callback_add(handle_, EVAS_CALLBACK_MOUSE_DOWN, OnMouseDown, this);
@@ -67,11 +75,13 @@ SelectionHandleEfl::SelectionHandleEfl(SelectionControllerEfl& controller, Handl
 SelectionHandleEfl::~SelectionHandleEfl() {
   evas_object_event_callback_del(handle_, EVAS_CALLBACK_MOUSE_DOWN, OnMouseDown);
   evas_object_event_callback_del(handle_, EVAS_CALLBACK_MOUSE_UP, OnMouseUp);
+  evas_object_smart_member_del(handle_);
   evas_object_del(handle_);
 }
 
 void SelectionHandleEfl::Show() {
   evas_object_show(handle_);
+  evas_object_raise(handle_);
 }
 
 void SelectionHandleEfl::Hide() {
@@ -79,13 +89,18 @@ void SelectionHandleEfl::Hide() {
 }
 
 bool SelectionHandleEfl::IsVisible() const {
-  return evas_object_visible_get(handle_);
+  int handle_x, handle_y;
+  evas_object_geometry_get(handle_, &handle_x, &handle_y, nullptr, nullptr);
+
+  auto view_rect = controller_.GetVisibleViewportRect();
+
+  return evas_object_visible_get(handle_) &&
+         view_rect.Contains(handle_x, handle_y);
 }
 
 void SelectionHandleEfl::Move(const gfx::Point& point) {
-  if (!pressed_) {
+  if (!pressed_)
     ChangeObjectDirection(CalculateDirection(point));
-  }
 
   if (handle_type_ == HANDLE_TYPE_INPUT)
     MoveInputHandle(point);
@@ -108,32 +123,21 @@ void SelectionHandleEfl::OnMouseDown(void* data, Evas*, Evas_Object*, void* even
   Evas_Event_Mouse_Down* event = static_cast<Evas_Event_Mouse_Down*>(event_info);
   SelectionHandleEfl* handle = static_cast<SelectionHandleEfl*>(data);
   handle->pressed_ = true;
-  evas_object_event_callback_add(handle->handle_, EVAS_CALLBACK_MOUSE_MOVE,
-      OnMouseMove, handle);
   //Save the diff_point between touch point and base point of the handle
   handle->diff_point_.SetPoint(event->canvas.x - handle->base_point_.x(),
       event->canvas.y - handle->base_point_.y());
 
-  Evas_Coord x, y;
-  evas_object_geometry_get(handle->evas_object(), &x, &y, 0, 0);
-  handle->handle_position_at_touch_down_ = gfx::Point(x, y);
-  handle->touch_down_position_ = gfx::Point(event->canvas.x, event->canvas.y);
-
   handle->controller_.HandleDragBeginNotification(handle);
 }
 
-void SelectionHandleEfl::OnMouseMove(void* data, Evas*, Evas_Object*, void* event_info) {
-  Evas_Event_Mouse_Move* event = static_cast<Evas_Event_Mouse_Move*>(event_info);
-  SelectionHandleEfl* handle = static_cast<SelectionHandleEfl*>(data);
-  handle->current_touch_point_.SetPoint(event->cur.canvas.x, event->cur.canvas.y);
-  ecore_job_add(UpdateMouseMove, handle);
+void SelectionHandleEfl::UpdatePosition(const gfx::Point& position) {
+  current_touch_point_ = position;
+  ecore_job_add(UpdateMouseMove, this);
 }
 
 void SelectionHandleEfl::OnMouseUp(void* data, Evas*, Evas_Object*, void* /* event_info */) {
   SelectionHandleEfl* handle = static_cast<SelectionHandleEfl*>(data);
   handle->pressed_ = false;
-  evas_object_event_callback_del(handle->handle_, EVAS_CALLBACK_MOUSE_MOVE, OnMouseMove);
-
   handle->controller_.HandleDragEndNotification();
 }
 
@@ -150,31 +154,23 @@ void SelectionHandleEfl::UpdateMouseMove(void* data) {
   int delta_y = handle->current_touch_point_.y() - handle->diff_point_.y();
   handle->base_point_.SetPoint(delta_x, delta_y);
 
-  gfx::Vector2d diff = handle->current_touch_point_ - handle->touch_down_position_;
-  if (handle->handle_type_ != HANDLE_TYPE_INPUT) {
-    // We call MoveObject with evas coordinates relative to
-    // the webview canvas. So we need to ignore the parent
-    // view offset calculation.
-    handle->MoveObject(handle->handle_position_at_touch_down_ + diff,
-                       true /*ignore_parent_view_offset*/);
-  }
-
   handle->controller_.HandleDragUpdateNotification(handle);
 }
 
 SelectionHandleEfl::HandleDirection SelectionHandleEfl::CalculateDirection(
     const gfx::Point& point) const {
-  bool reverse_horizontally = false,  reverse_vertically = false;
-  Evas_Coord x, y, deviceWidth, deviceHeight;
+  bool reverse_horizontally = false, reverse_vertically = false;
   int handleHeight;
-
   edje_object_part_geometry_get(handle_, "handle", 0, 0, 0, &handleHeight);
-  evas_object_geometry_get(controller_.GetParentView(),
-      &x, &y, &deviceWidth, &deviceHeight);
-  gfx::Point conv_point(point.x() + x, point.y() + y);
 
-  gfx::Rect reverse_direction_rect = gfx::Rect(x + kReverseMargin,
-      y, deviceWidth - 2 * kReverseMargin, deviceHeight - handleHeight);
+  auto visible_viewport_rect = controller_.GetVisibleViewportRect();
+  gfx::Point conv_point(point.x() + visible_viewport_rect.x(),
+                        point.y() + visible_viewport_rect.y());
+
+  gfx::Rect reverse_direction_rect = gfx::Rect(
+      visible_viewport_rect.x() + kReverseMargin, visible_viewport_rect.y(),
+      visible_viewport_rect.width() - 2 * kReverseMargin,
+      visible_viewport_rect.height() - handleHeight);
 
   if (!reverse_direction_rect.Contains(conv_point)) {
     if (conv_point.x() <= reverse_direction_rect.x() ||
@@ -188,29 +184,27 @@ SelectionHandleEfl::HandleDirection SelectionHandleEfl::CalculateDirection(
   }
 
   if (handle_type_ != HANDLE_TYPE_INPUT) {
-     if (reverse_vertically) {
-       if (reverse_horizontally) {
-         return DirectionTopReverse;
-       } else {
-         return DirectionBottomReverse;
-       }
-     } else {
-       if (reverse_horizontally) {
-         return DirectionTopNormal;
-       } else {
-         return DirectionBottomNormal;
-       }
-     }
+    if (reverse_vertically) {
+      if (reverse_horizontally)
+        return DirectionTopReverse;
+      else
+        return DirectionBottomReverse;
+    } else {
+      if (reverse_horizontally)
+        return DirectionTopNormal;
+      else
+        return DirectionBottomNormal;
+    }
   } else {
     // Input handle can only be rotated horizontally
-    if (reverse_horizontally) {
+    if (reverse_horizontally)
       return DirectionTopNormal;
-    } else {
+    else
       return DirectionBottomNormal;
-    }
   }
 
   NOTREACHED();
+  return DirectionBottomNormal;
 }
 
 void SelectionHandleEfl::ChangeObjectDirection(HandleDirection direction) {
@@ -244,20 +238,23 @@ void SelectionHandleEfl::ChangeObjectDirection(HandleDirection direction) {
       else
         edje_object_signal_emit(handle_, "elm,state,top,reversed", "elm");
       break;
-    }
+  }
 
   switch (handle_type_) {
     case HANDLE_TYPE_LEFT:
-      evas_object_smart_callback_call(controller_.GetParentView(),
-        "selection,handle,left,direction", &direction);
+      evas_object_smart_callback_call(
+          controller_.rwhva()->offscreen_helper()->ewk_view(),
+          "selection,handle,left,direction", &direction);
       break;
     case HANDLE_TYPE_RIGHT:
-      evas_object_smart_callback_call(controller_.GetParentView(),
-        "selection,handle,right,direction", &direction);
+      evas_object_smart_callback_call(
+          controller_.rwhva()->offscreen_helper()->ewk_view(),
+          "selection,handle,right,direction", &direction);
       break;
     case HANDLE_TYPE_INPUT:
-      evas_object_smart_callback_call(controller_.GetParentView(),
-        "selection,handle,large,direction", &direction);
+      evas_object_smart_callback_call(
+          controller_.rwhva()->offscreen_helper()->ewk_view(),
+          "selection,handle,large,direction", &direction);
       break;
   }
 }
@@ -279,17 +276,38 @@ gfx::Rect SelectionHandleEfl::GetSelectionRect() const {
 }
 
 void SelectionHandleEfl::MoveObject(const gfx::Point& point, bool ignore_parent_view_offset) {
-  Evas_Coord x = 0, y = 0;
-  if (!ignore_parent_view_offset)
-    evas_object_geometry_get(controller_.GetParentView(), &x, &y,
-      0, 0);
-
-  if (handle_type_ == HANDLE_TYPE_INPUT && IsTop()) {
-    evas_object_move(handle_, point.x() + x,
-        point.y() + y - controller_.GetLeftRect().height());
-  } else {
-    evas_object_move(handle_, point.x() + x, point.y() + y);
+  gfx::Rect view_bounds =
+      controller_.rwhva()->offscreen_helper()->GetViewBoundsInPix();
+  int handle_x = point.x() + view_bounds.x();
+  int handle_y = point.y() + view_bounds.y();
+
+  if (IsTop()) {
+    if (handle_type_ == HANDLE_TYPE_RIGHT)
+      handle_y -= controller_.GetRightRect().height();
+    else
+      handle_y -= controller_.GetLeftRect().height();
+  }
+
+  // Prevent selection handles from moving out of visible webview.
+  if (handle_type_ != HANDLE_TYPE_INPUT) {
+    const gfx::Rect& viewport_rect = controller_.GetVisibleViewportRect();
+    int viewport_rect_x = viewport_rect.x();
+    int viewport_rect_y = viewport_rect.y();
+    int viewport_rect_w = viewport_rect.width();
+    int viewport_rect_h = viewport_rect.height();
+
+    if (handle_y < viewport_rect_y)
+      handle_y = viewport_rect_y;
+    else if (handle_y > viewport_rect_h + viewport_rect_y)
+      handle_y = viewport_rect_h + viewport_rect_y;
+
+    if (handle_x < viewport_rect_x)
+      handle_x = viewport_rect_x;
+    else if (handle_x > viewport_rect_w + viewport_rect_x)
+      handle_x = viewport_rect_w + viewport_rect_x;
   }
+
+  evas_object_move(handle_, handle_x, handle_y);
 }
 
 } // namespace content
index e7efbb2..a886fbf 100644 (file)
@@ -41,7 +41,7 @@ class SelectionHandleEfl {
     DirectionNone,
   };
 
-  SelectionHandleEfl(SelectionControllerEfl& controller, HandleType type, Evas_Object* parent);
+  SelectionHandleEfl(SelectionControllerEfl& controller, HandleType type);
   ~SelectionHandleEfl();
   void Show();
   void Hide();
@@ -54,9 +54,12 @@ class SelectionHandleEfl {
 
   HandleType Type() const { return handle_type_; }
 
+  void UpdatePosition(const gfx::Point& position);
+  void MoveObject(const gfx::Point& point,
+                  bool ignore_parent_view_offset = false);
+
  private:
   static void OnMouseDown(void* data, Evas*, Evas_Object*, void* event_info);
-  static void OnMouseMove(void* data, Evas*, Evas_Object*, void* event_info);
   static void OnMouseUp(void* data, Evas*, Evas_Object*, void* event_info);
   static void UpdateMouseMove(void* data);
 
@@ -66,7 +69,6 @@ class SelectionHandleEfl {
   HandleDirection CalculateDirection(const gfx::Point&) const;
   void ChangeObjectDirection(HandleDirection direction);
   gfx::Rect GetSelectionRect() const;
-  void MoveObject(const gfx::Point& point, bool ignore_parent_view_offset = false);
 
   // This point is one which will be used during extending selection
   // it is in web view coordinates
@@ -79,14 +81,6 @@ class SelectionHandleEfl {
   // This save the gap between the touch point and base point when OnMouseDown is called
   gfx::Point diff_point_;
 
-  // Saves the original handle position at the time it started
-  // being dragged.
-  gfx::Point handle_position_at_touch_down_;
-
-  // Saves the original touch down position when a handle is grabbed.
-  // It is later used to calculate the movement offset.
-  gfx::Point touch_down_position_;
-
   // Parent to send back mouse events
   SelectionControllerEfl& controller_;
 
index a3db66b..7574dda 100644 (file)
@@ -8,10 +8,10 @@
 
 #include "base/files/file_path.h"
 #include "base/path_service.h"
+#include "content/browser/renderer_host/render_widget_host_view_aura.h"
 #include "content/browser/selection/selection_controller_efl.h"
 #include "content/common/paths_efl.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/browser/web_contents.h"
 
 namespace content {
 
@@ -20,21 +20,15 @@ const int kHeightOffset = 60;
 const float kZoomScale = 0.66;
 
 SelectionMagnifierEfl::SelectionMagnifierEfl(
-    content::SelectionControllerEfl* controller,
-    content::WebContents& web_contents)
-  : controller_(controller),
-    web_contents_(web_contents),
-    content_image_(0),
-    shown_(false) {
-  Evas_Object* top_widget = static_cast<Evas_Object*>(controller->
-      GetParentView());
-
+    content::SelectionControllerEfl* controller)
+    : controller_(controller), content_image_(0), shown_(false) {
   base::FilePath edj_dir;
   base::FilePath magnifier_edj;
   base::PathService::Get(PathsEfl::EDJE_RESOURCE_DIR, &edj_dir);
   magnifier_edj = edj_dir.Append(FILE_PATH_LITERAL("Magnifier.edj"));
 
-  container_ = elm_layout_add(top_widget);
+  container_ =
+      elm_layout_add(controller_->rwhva()->offscreen_helper()->content_image());
   elm_layout_file_set(container_, magnifier_edj.AsUTF8Unsafe().c_str(), "magnifier");
   edje_object_part_geometry_get(elm_layout_edje_get(container_), "bg", 0, 0, &width_, &height_);
 }
@@ -50,14 +44,12 @@ SelectionMagnifierEfl::~SelectionMagnifierEfl() {
 }
 
 void SelectionMagnifierEfl::HandleLongPress(const gfx::Point& touch_point) {
-  evas_object_event_callback_add(controller_->GetParentView(),
-                                 EVAS_CALLBACK_MOUSE_MOVE,
-                                 OnAnimatorMove,
-                                 this);
-  evas_object_event_callback_add(controller_->GetParentView(),
-                                 EVAS_CALLBACK_MOUSE_UP,
-                                 OnAnimatorUp,
-                                 this);
+  evas_object_event_callback_add(
+      controller_->rwhva()->offscreen_helper()->content_image(),
+      EVAS_CALLBACK_MOUSE_MOVE, OnAnimatorMove, this);
+  evas_object_event_callback_add(
+      controller_->rwhva()->offscreen_helper()->content_image(),
+      EVAS_CALLBACK_MOUSE_UP, OnAnimatorUp, this);
   // Call OnAnimatorMove here, so that the magnifier widget
   // gets properly placed. Other calls to it are expected to
   // happen as a react to finger/mouse movements.
@@ -66,12 +58,12 @@ void SelectionMagnifierEfl::HandleLongPress(const gfx::Point& touch_point) {
 }
 
 void SelectionMagnifierEfl::DisconnectCallbacks() {
-  evas_object_event_callback_del(controller_->GetParentView(),
-                                 EVAS_CALLBACK_MOUSE_MOVE,
-                                 OnAnimatorMove);
-  evas_object_event_callback_del(controller_->GetParentView(),
-                                 EVAS_CALLBACK_MOUSE_UP,
-                                 OnAnimatorUp);
+  evas_object_event_callback_del(
+      controller_->rwhva()->offscreen_helper()->content_image(),
+      EVAS_CALLBACK_MOUSE_MOVE, OnAnimatorMove);
+  evas_object_event_callback_del(
+      controller_->rwhva()->offscreen_helper()->content_image(),
+      EVAS_CALLBACK_MOUSE_UP, OnAnimatorUp);
 }
 
 void SelectionMagnifierEfl::OnAnimatorMove(void* data, Evas*, Evas_Object*, void*) {
@@ -84,9 +76,10 @@ void SelectionMagnifierEfl::OnAnimatorMove(void* data, Evas*, Evas_Object*, void
 
 void SelectionMagnifierEfl::OnAnimatorMove() {
   Evas_Coord_Point point;
-  evas_pointer_canvas_xy_get(evas_object_evas_get(controller_->GetParentView()),
-                             &point.x,
-                             &point.y);
+  evas_pointer_canvas_xy_get(
+      evas_object_evas_get(
+          controller_->rwhva()->offscreen_helper()->content_image()),
+      &point.x, &point.y);
   gfx::Point display_point(point.x, point.y);
   controller_->HandleLongPressMoveEvent(display_point);
   UpdateLocation(display_point);
@@ -133,11 +126,9 @@ void SelectionMagnifierEfl::MagnifierGetSnapshotCb(Evas_Object* image,
 
 void SelectionMagnifierEfl::UpdateLocation(const gfx::Point& location) {
   int device_x, device_y, device_width, device_height;
-  evas_object_geometry_get(controller_->GetParentView(),
-                           &device_x,
-                           &device_y,
-                           &device_width,
-                           &device_height);
+  evas_object_geometry_get(
+      controller_->rwhva()->offscreen_helper()->content_image(), &device_x,
+      &device_y, &device_width, &device_height);
 
   int zoomedWidth = width_ * kZoomScale;
   int zoomedHeight = height_ * kZoomScale;
@@ -177,11 +168,9 @@ void SelectionMagnifierEfl::UpdateLocation(const gfx::Point& location) {
 
 void SelectionMagnifierEfl::Move(const gfx::Point& location) {
   int device_x, device_y, device_width, device_height;
-  evas_object_geometry_get(controller_->GetParentView(),
-                           &device_x,
-                           &device_y,
-                           &device_width,
-                           &device_height);
+  evas_object_geometry_get(
+      controller_->rwhva()->offscreen_helper()->content_image(), &device_x,
+      &device_y, &device_width, &device_height);
 
   int magnifier_x = location.x();
   int magnifier_y = location.y() - height_ - kHeightOffset;
@@ -208,8 +197,11 @@ void SelectionMagnifierEfl::Show() {
   if (rwhv)
     rwhv->set_magnifier(true);
 #endif
-  if (controller_->GetParentView())
-    evas_object_smart_callback_call(controller_->GetParentView(), "magnifier,show", NULL);
+  if (controller_->rwhva()->offscreen_helper()->ewk_view()) {
+    evas_object_smart_callback_call(
+        controller_->rwhva()->offscreen_helper()->ewk_view(), "magnifier,show",
+        nullptr);
+  }
 }
 
 void SelectionMagnifierEfl::Hide() {
@@ -222,8 +214,11 @@ void SelectionMagnifierEfl::Hide() {
   if (rwhv)
     rwhv->set_magnifier(false);
 #endif
-  if (controller_->GetParentView())
-    evas_object_smart_callback_call(controller_->GetParentView(), "magnifier,hide", NULL);
+  if (controller_->rwhva()->offscreen_helper()->ewk_view()) {
+    evas_object_smart_callback_call(
+        controller_->rwhva()->offscreen_helper()->ewk_view(), "magnifier,hide",
+        nullptr);
+  }
 }
 
 }
index f84bff4..b80129d 100644 (file)
 namespace content {
 
 class SelectionControllerEfl;
-class WebContents;
 
 class SelectionMagnifierEfl {
  public:
-  SelectionMagnifierEfl(content::SelectionControllerEfl* controller,
-      WebContents& web_contents);
+  SelectionMagnifierEfl(content::SelectionControllerEfl* controller);
   ~SelectionMagnifierEfl();
 
   void HandleLongPress(const gfx::Point& touch_point);
@@ -42,8 +40,6 @@ class SelectionMagnifierEfl {
   // Parent to send back mouse events
   SelectionControllerEfl* controller_;
 
-  WebContents& web_contents_;
-
   // Magnifier
   Evas_Object* container_;
 
index 3c4c1ac..d560283 100644 (file)
@@ -15,6 +15,32 @@ collections { base_scale: 2.0;
                     rel2 { relative: 1.0 1.0; }
                 }
             }
+            part {
+                name: "autofill_popup";
+                type: SWALLOW;
+                scale: 1;
+                description {
+                    state: "default" 0.0;
+                    visible: 1;
+                    fixed: 1 1;
+                    align: 0.0 0.0;
+                    rel1 { relative: 0.0 0.0; to:"content";}
+                    rel2 { relative: 1.0 1.0; to:"content";}
+                }
+            }
+            part {
+                name: "context_menu_popup";
+                type: SWALLOW;
+                scale: 1;
+                description {
+                    state: "default" 0.0;
+                    visible: 1;
+                    fixed: 1 1;
+                    align: 0.0 0.0;
+                    rel1 { relative: 0.0 0.0; to:"content";}
+                    rel2 { relative: 1.0 1.0; to:"content";}
+                }
+            }
         }
     }
 }
index 2d36be4..3a221bf 100644 (file)
@@ -10,6 +10,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "components/autofill/core/browser/ui/popup_item_ids.h"
 #include "content/browser/renderer_host/render_widget_host_view_aura.h"
+#include "content/browser/web_contents/web_contents_impl.h"
 #include "content/common/paths_efl.h"
 #include "eweb_view.h"
 #include "tizen/system_info.h"
@@ -41,13 +42,21 @@ AutofillPopupViewEfl::AutofillPopupViewEfl(EWebView* view)
       autofill_list_(nullptr),
       password_popup_(nullptr),
       selected_line_(-1) {
-  Evas_Object* widgetWin_ = elm_object_top_widget_get(
-      elm_object_parent_widget_get(view->evas_object()));
-  if (!widgetWin_)
-    widgetWin_ = view->evas_object();
-  autofill_popup_ = elm_layout_add(widgetWin_);
+  auto native_view =
+      static_cast<content::WebContentsImpl*>(&(webview_->web_contents()))
+          ->GetEflNativeView();
+
   if (!autofill_popup_)
     return;
+  auto smart_parent = evas_object_smart_parent_get(native_view);
+  if (!smart_parent) {
+    LOG(ERROR) << "Unable to get smart parent from native view";
+    evas_object_del(autofill_popup_);
+    autofill_popup_ = nullptr;
+    return;
+  }
+  evas_object_smart_member_add(autofill_popup_, smart_parent);
+  elm_object_part_content_set(smart_parent, "autofill_popup", autofill_popup_);
   base::FilePath edj_dir;
   base::FilePath autofill_edj;
   base::PathService::Get(PathsEfl::EDJE_RESOURCE_DIR, &edj_dir);
@@ -60,8 +69,10 @@ AutofillPopupViewEfl::AutofillPopupViewEfl(EWebView* view)
 
 AutofillPopupViewEfl::~AutofillPopupViewEfl()
 {
-  if (autofill_popup_)
+  if (autofill_popup_) {
+    evas_object_smart_member_del(autofill_popup_);
     evas_object_del(autofill_popup_);
+  }
   if (password_popup_)
     evas_object_del(password_popup_);
 }
index c7b4fd1..52255e9 100644 (file)
@@ -26,6 +26,10 @@ namespace gfx {
 class RectF;
 }
 
+namespace content {
+class WebContentsImpl;
+}
+
 namespace autofill {
 
 class AutofillPopupViewEfl {
index ce3b6c8..4570b01 100644 (file)
@@ -12,6 +12,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "browser_context_efl.h"
 #include "common/web_contents_utils.h"
+#include "content/browser/renderer_host/render_widget_host_view_aura.h"
 #include "content/browser/selection/selection_controller_efl.h"
 #include "content/common/paths_efl.h"
 #include "content/public/browser/browser_thread.h"
@@ -207,16 +208,18 @@ void ContextMenuControllerEfl::GetProposedContextMenu() {
         params_.link_url.spec(),
         params_.link_url.spec());
   }
-#if !defined(EWK_BRINGUP)
-  RenderWidgetHostViewEfl* rwhv = static_cast<RenderWidgetHostViewEfl*>(web_contents_.GetRenderWidgetHostView());
+  RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>(
+      web_contents_.GetRenderWidgetHostView());
   if ((params_.media_type != ContextMenuDataMediaType::kImage &&
        !params_.selection_text.empty()) ||
-      (params_.is_editable && (rwhv && !rwhv->IsLastAvailableTextEmpty()))) {
+      (params_.is_editable &&
+       (rwhva && rwhva->offscreen_helper()->HasSelectableText()))) {
     AddItemToProposedList(EWK_CONTEXT_MENU_ITEM_TYPE_ACTION, EWK_CONTEXT_MENU_ITEM_TAG_SELECT_WORD,
         std::string(dgettext("WebKit", "IDS_WEBVIEW_OPT_SELECT_ABB")));
     AddItemToProposedList(EWK_CONTEXT_MENU_ITEM_TYPE_ACTION, EWK_CONTEXT_MENU_ITEM_TAG_SELECT_ALL,
         std::string(dgettext("WebKit", "IDS_WEBVIEW_OPT_SELECT_ALL_ABB")));
   }
+#if !defined(EWK_BRINGUP)
   if (params_.is_draggable) {
     AddItemToProposedList(EWK_CONTEXT_MENU_ITEM_TYPE_ACTION, EWK_CONTEXT_MENU_ITEM_TAG_DRAG,
         std::string(dgettext("WebKit", "IDS_WEBVIEW_OPT_DRAG_AND_DROP")));
@@ -260,6 +263,15 @@ bool ContextMenuControllerEfl::CreateContextMenu() {
 
   if (!popup_)
     return false;
+  auto smart_parent = evas_object_smart_parent_get(native_view_);
+  if (!smart_parent) {
+    LOG(ERROR) << "Unable to get smart parent from native view";
+    evas_object_del(popup_);
+    popup_ = nullptr;
+    return false;
+  }
+  evas_object_smart_member_add(popup_, smart_parent);
+  elm_object_part_content_set(smart_parent, "context_menu_popup", popup_);
 
   evas_object_data_set(popup_, "ContextMenuContollerEfl", this);
 
@@ -382,8 +394,14 @@ bool ContextMenuControllerEfl::CreateContextMenu() {
 
 void ContextMenuControllerEfl::ContextMenuHWBackKey(void* data, Evas_Object* obj,
                                                     void* event_info) {
-  ContextMenuControllerEfl* menu_controller = static_cast<ContextMenuControllerEfl*>(data);
+  auto menu_controller = static_cast<ContextMenuControllerEfl*>(data);
   if (menu_controller) {
+    auto selection_controller =
+        menu_controller->webview_->GetSelectionController();
+
+    if (selection_controller)
+      selection_controller->ToggleCaretAfterSelection();
+
     menu_controller->HideContextMenu();
     evas_object_data_del(obj, "ContextEfl");
   }
@@ -494,16 +512,19 @@ bool ContextMenuControllerEfl::ShowContextMenu() {
     }
     web_contents_.Focus();
   } else {
+    evas_object_smart_callback_add(popup_, "block,clicked",
+                                   BlockClickedCallback, this);
+  }
+
 #if BUILDFLAG(IS_TIZEN)
     eext_object_event_callback_add(popup_, EEXT_CALLBACK_BACK, ContextMenuHWBackKey, this);
     // Workaround. After context menu shows up, there is "unfocused" event fired.
     // evas_object_smart_callback_add(popup_, "unfocused", ContextMenuHWBackKey, this);
     evas_object_focus_set(popup_, EINA_TRUE);
 #endif
-    evas_object_smart_callback_add(popup_, "block,clicked", BlockClickedCallback, this);
-  }
-  evas_object_show(popup_);
-  return true;
+    evas_object_show(popup_);
+    evas_object_raise(popup_);
+    return true;
 }
 
 void ContextMenuControllerEfl::HideSelectionHandle() {
@@ -969,23 +990,28 @@ void ContextMenuControllerEfl::MenuItemSelected(ContextMenuItemEfl* menu_item)
 
 void ContextMenuControllerEfl::HideContextMenu() {
   if (popup_) {
+    evas_object_event_callback_del(popup_, EVAS_CALLBACK_RESIZE,
+                                   ContextMenuPopupResize);
     evas_object_del(popup_);
-    popup_ = NULL;
+    popup_ = nullptr;
   }
 
   _context_menu_resized = false;
 
-  if (menu_items_) {
+  if (IsMobileProfile()) {
+#if !defined(EWK_BRINGUP)
+    context_menu_status_ = HIDDEN;
+#endif
+  } else if (menu_items_) {
     void* data;
     EINA_LIST_FREE(menu_items_, data) {
       _Ewk_Context_Menu_Item *item = static_cast<_Ewk_Context_Menu_Item*> (data);
       delete item;
     }
-    menu_items_ = NULL;
+    menu_items_ = nullptr;
   }
 }
 
-
 void ContextMenuControllerEfl::SetPopupSize(int width, int height) {
   if (save_fail_dialog_)
     save_fail_dialog_->SetPopupSize(width, height);
@@ -1005,6 +1031,7 @@ void ContextMenuControllerEfl::DeletePopup() {
 
   if (popup_) {
     evas_object_data_set(popup_, "ContextMenuContollerEfl", 0);
+    evas_object_smart_member_del(popup_);
     evas_object_del(popup_);
     popup_ = 0;
   }
index cfa4506..b6bc1a0 100644 (file)
@@ -111,6 +111,10 @@ const char kReplaceWith[] = "_";
 static const char* kRendererCrashedHTMLMessage =
     "<html><body><h1>Renderer process has crashed!</h1></body></html>";
 
+// "visible,content,changed" is an email-app specific signal which informs
+// that the web view is only partially visible.
+static const char* kVisibleContentChangedSignalName = "visible,content,changed";
+
 inline void SetDefaultStringIfNull(const char*& variable,
                                    const char* default_string) {
   if (!variable) {
@@ -268,6 +272,15 @@ void EWebView::OnViewFocusOut(void* data, Evas*, Evas_Object*, void*) {
   view->SetFocus(EINA_FALSE);
 }
 
+void EWebView::VisibleContentChangedCallback(void* user_data,
+                                             Evas_Object* /*object*/,
+                                             void* event_info) {
+  auto view = static_cast<EWebView*>(user_data);
+  auto rect = static_cast<Eina_Rectangle*>(event_info);
+  view->GetSelectionController()->SetCustomVisibleViewRect(
+      gfx::Rect(rect->x, rect->y, rect->w, rect->h));
+}
+
 EWebView::EWebView(Ewk_Context* context, Evas_Object* object)
     : context_(context),
       evas_object_(object),
@@ -283,10 +296,14 @@ EWebView::EWebView(Ewk_Context* context, Evas_Object* object)
       y_delta_(0.0),
       is_initialized_(false) {
  if (evas_object_) {
-    evas_object_event_callback_add(evas_object_, EVAS_CALLBACK_FOCUS_IN,
-                                   OnViewFocusIn, this);
-    evas_object_event_callback_add(evas_object_, EVAS_CALLBACK_FOCUS_OUT,
-                                   OnViewFocusOut, this);
+   evas_object_smart_callback_add(evas_object_,
+                                  kVisibleContentChangedSignalName,
+                                  VisibleContentChangedCallback, this);
+
+   evas_object_event_callback_add(evas_object_, EVAS_CALLBACK_FOCUS_IN,
+                                  OnViewFocusIn, this);
+   evas_object_event_callback_add(evas_object_, EVAS_CALLBACK_FOCUS_OUT,
+                                  OnViewFocusOut, this);
   }
 }
 
@@ -407,6 +424,9 @@ EWebView::~EWebView() {
                                    OnViewFocusIn);
     evas_object_event_callback_del(evas_object_, EVAS_CALLBACK_FOCUS_OUT,
                                    OnViewFocusOut);
+    evas_object_smart_callback_del(evas_object_,
+                                   kVisibleContentChangedSignalName,
+                                   VisibleContentChangedCallback);
   }
 }
 
@@ -1348,10 +1368,8 @@ void EWebView::GetScrollSize(int* width, int* height) {
 }
 
 void EWebView::MoveCaret(const gfx::Point& point) {
-#if !defined(USE_AURA)
-  if (rwhv())
-    rwhv()->MoveCaret(point);
-#endif
+  if (rwhva())
+    rwhva()->offscreen_helper()->MoveCaret(point);
 }
 
 SelectionControllerEfl* EWebView::GetSelectionController() const {
@@ -1507,17 +1525,19 @@ _Ewk_Hit_Test* EWebView::RequestHitTestDataAtBlinkCoords(
 
 void EWebView::EvasToBlinkCords(int x, int y, int* view_x, int* view_y) {
   DCHECK(display::Screen::GetScreen());
-  Evas_Coord tmpX, tmpY;
-  evas_object_geometry_get(evas_object_, &tmpX, &tmpY, NULL, NULL);
+  if (!rwhva())
+    return;
+
+  gfx::Rect view_bounds = rwhva()->offscreen_helper()->GetViewBoundsInPix();
 
   if (view_x) {
-    *view_x = x - tmpX;
+    *view_x = x - view_bounds.x();
     *view_x /=
         display::Screen::GetScreen()->GetPrimaryDisplay().device_scale_factor();
   }
 
   if (view_y) {
-    *view_y = y - tmpY;
+    *view_y = y - view_bounds.y();
     *view_y /=
         display::Screen::GetScreen()->GetPrimaryDisplay().device_scale_factor();
   }
index 27fb2af..e85a825 100644 (file)
@@ -715,6 +715,9 @@ class EWebView {
 
   static void OnViewFocusIn(void* data, Evas*, Evas_Object*, void*);
   static void OnViewFocusOut(void* data, Evas*, Evas_Object*, void*);
+  static void VisibleContentChangedCallback(void* user_data,
+                                            Evas_Object* object,
+                                            void* event_info);
 
   scoped_refptr<WebViewEvasEventHandler> evas_event_handler_;
   scoped_refptr<Ewk_Context> context_;