[M108 Migration] Selection & Context menu controller. 15/288515/4
authorv-saha <v.saha@samsung.com>
Fri, 17 Feb 2023 12:34:31 +0000 (18:04 +0530)
committerv-saha <v.saha@samsung.com>
Tue, 28 Feb 2023 05:36:42 +0000 (11:06 +0530)
This change migrates below fixes related to context menu/text selection.
1. Uses GetSelectedText in RWHVA.
2. Avoid hiding context menu during potrait to landscape and vice versa.
3. Do not restore context popup when in caret mode.

Reference: https://review.tizen.org/gerrit/282457

Change-Id: Iadc9cb3c5bb9948b867c24ba825e658260908a8c
Signed-off-by: v-saha <v.saha@samsung.com>
tizen_src/chromium_impl/content/browser/selection/selection_controller_efl.cc
tizen_src/chromium_impl/content/browser/selection/selection_controller_efl.h
tizen_src/ewk/efl_integration/context_menu_controller_efl.cc
tizen_src/ewk/efl_integration/web_contents_view_delegate_ewk.cc

index efca84b..225550c 100644 (file)
@@ -137,9 +137,8 @@ bool SelectionControllerEfl::GetCaretSelectionStatus() const {
   return selection_mode_ == SelectionMode::CARET;
 }
 
-void SelectionControllerEfl::SetControlsTemporarilyHidden(
-    bool value,
-    bool from_custom_scroll_callback) {
+void SelectionControllerEfl::SetControlsTemporarilyHidden(bool value,
+                                                          bool set_forcefully) {
   TRACE_EVENT1("selection,efl", __PRETTY_FUNCTION__,
                "controls are hidden:", value);
   if (controls_temporarily_hidden_ == value)
@@ -147,7 +146,7 @@ void SelectionControllerEfl::SetControlsTemporarilyHidden(
   // Make sure to show selection controls only when no finger
   // is left touching the screen.
   if (!value && rwhva_->event_handler()->pointer_state().GetPointerCount() &&
-      !from_custom_scroll_callback) {
+      !set_forcefully) {
     return;
   }
   controls_temporarily_hidden_ = value;
@@ -164,13 +163,14 @@ void SelectionControllerEfl::SetIsAnchorFirst(bool value) {
 }
 
 void SelectionControllerEfl::TriggerOnSelectionChange() {
+  triggered_selection_change_ = true;
   OnSelectionChanged(start_selection_, end_selection_);
 }
 
 void SelectionControllerEfl::OnSelectionChanged(
     const gfx::SelectionBound& start, const gfx::SelectionBound& end) {
   if (start_selection_ == start && end_selection_ == end &&
-      selection_change_reason_ != Reason::RequestedByContextMenu)
+      !triggered_selection_change_)
     return;
 
   if (selection_change_reason_ != Reason::HandleDragged)
@@ -202,11 +202,12 @@ void SelectionControllerEfl::OnSelectionChanged(
   bool show = (selection_change_reason_ != Reason::Irrelevant) && !finger_down;
   UpdateSelectionDataAndShow(
       truncated_start, truncated_end, show);
+  triggered_selection_change_ = false;
   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_ &&
+  if (GetSelectionEditable() && !handle_being_dragged_ && rwhva_ &&
       rwhva_->GetSelectedText() == (u"\n")) {
     rwhva_->offscreen_helper()->MoveCaret(
         selection_data_->GetLeftRect().origin());
@@ -238,6 +239,11 @@ void SelectionControllerEfl::OnTextInputStateChanged() {
     HideHandleAndContextMenu();
     ClearSelection();
   }
+
+  if (selection_change_reason_ == Reason::CaretModeForced) {
+    is_caret_mode_forced_ = false;
+    selection_change_reason_ = Reason::Irrelevant;
+  }
 }
 
 void SelectionControllerEfl::UpdateSelectionData(const std::u16string& text) {
@@ -308,10 +314,8 @@ bool SelectionControllerEfl::UpdateSelectionDataAndShow(
     return false;
   }
 
-  if (selection_changed ||
-      selection_change_reason_ == Reason::RequestedByContextMenu) {
+  if (selection_changed || triggered_selection_change_)
     ShowHandleAndContextMenuIfRequired();
-  }
 
   return true;
 }
@@ -389,6 +393,11 @@ void SelectionControllerEfl::ShowHandleAndContextMenuIfRequired(
       selection_change_reason_ = saved_reason;
       ShowContextMenu();
     }
+
+    // In order to keep selection controlls showing up,
+    // Reason::CaretModeForced should be used as a reason of selection change.
+    if (is_caret_mode_forced_)
+      selection_change_reason_ = Reason::CaretModeForced;
     return;
   }
   input_handle_->Hide();
@@ -709,7 +718,6 @@ void SelectionControllerEfl::HandlePostponedGesture(int x,
 bool SelectionControllerEfl::HandleLongPressEvent(
     const gfx::Point& touch_point,
     const content::ContextMenuParams& params) {
-
   if (params.is_editable) {
     // If one long press on an empty form, do not enter selection mode.
     // Instead, context menu will be shown if needed for clipboard actions.
index b41234c..c687da4 100644 (file)
@@ -86,8 +86,7 @@ class CONTENT_EXPORT SelectionControllerEfl {
   void HideHandleAndContextMenu();
   bool IsAnyHandleVisible() const;
 
-  void SetControlsTemporarilyHidden(bool hidden,
-                                    bool from_custom_scroll_callback = false);
+  void SetControlsTemporarilyHidden(bool hidden, bool set_forcefully = false);
 
   gfx::Rect GetLeftRect() const;
   gfx::Rect GetRightRect() const;
@@ -240,6 +239,7 @@ class CONTENT_EXPORT SelectionControllerEfl {
 
   enum ContextMenuStatus context_menu_status_ = ContextMenuStatus::NONE;
   enum SelectionMode selection_mode_ = SelectionMode::NONE;
+  bool triggered_selection_change_ = false;
   gfx::SelectionBound start_selection_;
   gfx::SelectionBound end_selection_;
 };
index 0590549..838a328 100644 (file)
@@ -225,24 +225,66 @@ void ContextMenuControllerEfl::GetProposedContextMenu() {
         params_.link_url.spec(),
         params_.link_url.spec());
   }
-  RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>(
-      web_contents_.GetRenderWidgetHostView());
-  if ((params_.media_type != ContextMenuDataMediaType::kImage &&
-       !params_.selection_text.empty()) ||
-      (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 BUILDFLAG(IS_TIZEN)
-    if (!params_.is_editable && !params_.selection_text.empty()) {
-      // TODO: IDS_WEBVIEW_OPT_SHARE should be added for all po files.
-      AddItemToProposedList(EWK_CONTEXT_MENU_ITEM_TYPE_ACTION,
-                            EWK_CONTEXT_MENU_ITEM_TAG_SHARE,
-                            dgettext("WebKit", "IDS_WEBVIEW_OPT_SHARE"));
+  if (params_.is_editable) {
+    RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>(
+        web_contents_.GetRenderWidgetHostView());
+    const SelectionControllerEfl* controller =
+        webview_->GetSelectionController();
+    bool should_add_select_and_select_all =
+        (!controller) ? true : !controller->IsCaretModeForced();
+
+    if (rwhva && rwhva->offscreen_helper()->HasSelectableText() &&
+        should_add_select_and_select_all) {
+      if (params_.selection_text.empty() &&
+          params_.input_field_type !=
+              blink::mojom::ContextMenuDataInputFieldType::kPassword) {
+        AddItemToProposedList(
+            EWK_CONTEXT_MENU_ITEM_TYPE_ACTION,
+            EWK_CONTEXT_MENU_ITEM_TAG_SELECT_WORD,
+            std::string(dgettext("WebKit", "IDS_WEBVIEW_OPT_SELECT_ABB")));
+      }
+
+      // This is a tricky way to check if everything in the editable field is
+      // selected, because there is no other known way.
+      //
+      // * params_.selection_text contains selected text
+      // * rwhva->GetSelectedText() contains selected
+      //   text and some text around selection
+      //
+      // If both strings are the same length, it means that the selection has
+      // no more text around it, so everything is already selected.
+      //
+      // There is also one more issue with this hack: if the last character of
+      // textarea is '\n', there will be additional '\n' reported in selection
+      // with surrounding characters, which isn't reported in selection text
+      // from params_. This means that lengths aren't equal, so normal length
+      // check won't work.
+      //
+      // To work around this, we assume that everything is already selected if
+      // selection with surroundings is one character longer than selection,
+      // and that last character is '\n'.
+      size_t surroundings_length = rwhva->GetSelectedText().length();
+      size_t selection_length = params_.selection_text.length();
+      char16_t surroundings_last_char =
+          rwhva->GetSelectedText()[surroundings_length - 1];
+
+      if (surroundings_length != selection_length &&
+          !(surroundings_length == selection_length + 1 &&
+            surroundings_last_char == '\n')) {
+        AddItemToProposedList(
+            EWK_CONTEXT_MENU_ITEM_TYPE_ACTION,
+            EWK_CONTEXT_MENU_ITEM_TAG_SELECT_ALL,
+            std::string(dgettext("WebKit", "IDS_WEBVIEW_OPT_SELECT_ALL_ABB")));
+      }
+    }
+  } else {
+    if (params_.media_type != ContextMenuDataMediaType::kImage &&
+        is_text_selection_) {
+      AddItemToProposedList(
+          EWK_CONTEXT_MENU_ITEM_TYPE_ACTION,
+          EWK_CONTEXT_MENU_ITEM_TAG_SELECT_ALL,
+          std::string(dgettext("WebKit", "IDS_WEBVIEW_OPT_SELECT_ALL_ABB")));
     }
-#endif
   }
 #if BUILDFLAG(IS_TIZEN)
   if (IsMobileProfile() && params_.is_draggable &&
@@ -437,8 +479,10 @@ Eina_Bool ContextMenuControllerEfl::RestoreTimerCallback(void* data) {
       menu_controller->webview_->GetSelectionController();
 
   if (menu_controller->popup_ && selection_controller &&
-      selection_controller->GetSelectionStatus())
+      selection_controller->GetSelectionStatus() &&
+      !selection_controller->IsCaretMode()) {
     evas_object_show(menu_controller->popup_);
+  }
 
   menu_controller->restore_timer_ = nullptr;
 
index f4433aa..e3b770e 100644 (file)
@@ -19,7 +19,7 @@ WebContentsViewDelegateEwk::WebContentsViewDelegateEwk(EWebView* wv)
 void WebContentsViewDelegateEwk::ShowContextMenu(
     content::RenderFrameHost& render_frame_host,
     const content::ContextMenuParams& params) {
-  if (params.source_type == ui::MENU_SOURCE_TOUCH) {
+  if (params.source_type == ui::MENU_SOURCE_LONG_PRESS) {
     CHECK(web_view_->TouchEventsEnabled());
     web_view_->HandleLongPressGesture(params);
   } else {