Make the reasons for showing handles and context menu explicit.
authorAntonio Gomes <a1.gomes@samsung.com>
Mon, 9 Nov 2015 23:41:10 +0000 (19:41 -0400)
committerYoungsoo Choi <kenshin.choi@samsung.com>
Tue, 10 Jul 2018 07:55:23 +0000 (07:55 +0000)
As of now there is a mix of reasons that request context menu
and selection handles show.
To keep control of what gets shown and when, currently there are
lots of state variables, conditions. To list some, we can name:

* show_after_scroll_
* should_restore_selection_menu_
* selection_acked_on_tap_
* single_tap_performed_
* show_only_large_handle_

Additionally, control is spreadied around different methods,
and is hard to follow.

In order to make it all simpler, patch introduces a single
control that allow us to handle case by case. It is an enum class
named "Reason" whose enum items list include:

* ScrollOrZoomGestureEnded
* HandleDragged
* HandleReleased
* LongPressMoved
* LongPressEnded
* Tap
* RequestedByContextMenu
* Irrelevant

"Irrelevant" enum item represents a case where a selection change
happaned without being asked by chromium-efl, e.g. a text selected by JS.

This way we can control show/not show of context menu and handles
in a simpler way, and eliminate all other mentioned controls (to be done
in a future patch for simplicity).

Bug: http://107.108.218.239/bugzilla/show_bug.cgi?id=14304

Reviewed by: a.renevier, a1.gomes, djmix.kim, sns.park

Change-Id: I6ea5a1146ab38d0478b8cbef036db6724c33cf87
Signed-off-by: Antonio Gomes <a1.gomes@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

index 59e6d39..0db0418 100644 (file)
@@ -39,7 +39,7 @@ SelectionControllerEfl::SelectionControllerEfl(Evas_Object* parent_view, WebCont
        single_tap_performed_(false),
        was_scrolled_(false),
        postponed_(false),
-       expecting_update_(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)),
@@ -113,7 +113,7 @@ void SelectionControllerEfl::SetScrollStatus(const bool enable) {
     Clear(IsAnyHandleVisible() || postponed_);
     CancelContextMenu(0);
   } else if (show_after_scroll_ || postponed_) {
-    ShowHandleAndContextMenuIfRequired();
+    ShowHandleAndContextMenuIfRequired(Reason::ScrollOrZoomGestureEnded);
   }
 }
 
@@ -142,8 +142,7 @@ void SelectionControllerEfl::OnSelectionChanged(
   //    handling "tap" gesture.
   bool finger_down = handle_being_dragged_ || long_mouse_press_;
   if (start == end && GetSelectionEditable() &&
-      (!expecting_update_ && !finger_down)) {
-    expecting_update_ = false;
+      (selection_change_reason_ == Reason::Irrelevant && !finger_down && !scrolling_)) {
     HideHandleAndContextMenu();
     ClearSelection();
     return;
@@ -157,10 +156,10 @@ void SelectionControllerEfl::OnSelectionChanged(
   truncated_start = ConvertRectToPixel(device_scale_factor, truncated_start);
   truncated_end = ConvertRectToPixel(device_scale_factor, truncated_end);
 
-  bool show = expecting_update_ && !finger_down;
+  bool show = (selection_change_reason_ != Reason::Irrelevant) && !finger_down;
   UpdateSelectionDataAndShow(
       truncated_start, truncated_end, show);
-  expecting_update_ = false;
+  selection_change_reason_ = Reason::Irrelevant;
 }
 
 void SelectionControllerEfl::UpdateSelectionData(const base::string16& text) {
@@ -196,37 +195,32 @@ void SelectionControllerEfl::DetermineSelectionMode(
 bool SelectionControllerEfl::UpdateSelectionDataAndShow(
     const gfx::Rect& left_rect,
     const gfx::Rect& right_rect,
-    bool show) {
+    bool /* show */) {
 
   DetermineSelectionMode(left_rect, right_rect);
 
   TRACE_EVENT0("selection,efl", __PRETTY_FUNCTION__);
-  if (!show && !IsSelectionValid(left_rect, right_rect)) {
+  if ((selection_change_reason_ == Reason::Irrelevant) && !IsSelectionValid(left_rect, right_rect)) {
     if (!GetCaretSelectionStatus())
       ClearSelection();
     selection_data_->UpdateRectData(left_rect, right_rect);
     return false;
   }
 
-  RenderWidgetHostViewEfl* rwhv =
-      static_cast<RenderWidgetHostViewEfl*>(web_contents_.GetRenderWidgetHostView());
-  if (show_only_large_handle_ && GetCaretSelectionStatus() &&
-      (rwhv && !rwhv->IsLastAvailableTextEmpty())) {
-    selection_data_->UpdateRectData(left_rect, right_rect);
-    ShowHandleAndContextMenuIfRequired();
-    return true;
-  }
-  if ((selection_data_->UpdateRectData(left_rect, right_rect) &&
-      IsAnyHandleVisible()) || show || postponed_) {
-    show_only_large_handle_ = false;
+  if (selection_data_->UpdateRectData(left_rect, right_rect))
     ShowHandleAndContextMenuIfRequired();
-  }
+
   return true;
 }
 
-void SelectionControllerEfl::ShowHandleAndContextMenuIfRequired() {
+void SelectionControllerEfl::ShowHandleAndContextMenuIfRequired(
+    Reason explicit_reason) {
   TRACE_EVENT0("selection,efl", __PRETTY_FUNCTION__);
 
+  Reason effective_reason = selection_change_reason_;
+  if (explicit_reason != Reason::Irrelevant)
+    effective_reason = explicit_reason;
+
   if (!selection_data_->GetStatus()) {
     postponed_ = true;
     return;
@@ -270,7 +264,10 @@ void SelectionControllerEfl::ShowHandleAndContextMenuIfRequired() {
 
     QuerySelectionStyle();
 
-    if (!handle_being_dragged_ && !show_only_large_handle_)
+    bool show_context_menu = effective_reason != Reason::ScrollOrZoomGestureEnded &&
+                             effective_reason != Reason::Tap &&
+                             effective_reason != Reason::Irrelevant;
+    if (!handle_being_dragged_ && show_context_menu)
       ShowContextMenu();
 
     return;
@@ -315,7 +312,7 @@ void SelectionControllerEfl::ShowHandleAndContextMenuIfRequired() {
   }
 
   // Do not show the context menu during selection extend
-  if (!handle_being_dragged_)
+  if (!handle_being_dragged_ && effective_reason != Reason::Irrelevant)
     ShowContextMenu();
 
   QuerySelectionStyle();
@@ -449,7 +446,7 @@ void SelectionControllerEfl::HandleDragUpdateNotification(SelectionHandleEfl* ha
   // FIXME : Check the text Direction later
   Evas_Coord x, y;
   evas_object_geometry_get(parent_view_, &x, &y, 0, 0);
-  expecting_update_ = true;
+  selection_change_reason_ = Reason::HandleDragged;
 
   gfx::Point magnifier_point;
   magnifier_point.set_x(handle->GetBasePosition().x() + x);
@@ -481,12 +478,12 @@ void SelectionControllerEfl::HandleDragUpdateNotification(SelectionHandleEfl* ha
 
 void SelectionControllerEfl::HandleDragEndNotification() {
   show_only_large_handle_ = false;
-  expecting_update_ = false;
+  selection_change_reason_ = Reason::Irrelevant;
   magnifier_->Hide();
   start_handle_->SetBasePosition(selection_data_->GetLeftRect().bottom_left());
   end_handle_->SetBasePosition(selection_data_->GetRightRect().bottom_right());
   handle_being_dragged_ = false;
-  ShowHandleAndContextMenuIfRequired();
+  ShowHandleAndContextMenuIfRequired(Reason::HandleReleased);
 }
 
 void SelectionControllerEfl::GetSelectionBounds(gfx::Rect* left,
@@ -640,7 +637,7 @@ void SelectionControllerEfl::HandleLongPressMoveEvent(const gfx::Point& touch_po
   RenderWidgetHostViewEfl* rwhv =
       static_cast<RenderWidgetHostViewEfl*>(web_contents_.GetRenderWidgetHostView());
   Clear();
-  expecting_update_ = true;
+  selection_change_reason_ = Reason::LongPressMoved;
   if (selection_data_->IsInEditField()) {
     Evas_Coord x, y;
     evas_object_geometry_get(parent_view_, &x, &y, 0, 0);
@@ -655,10 +652,10 @@ void SelectionControllerEfl::HandleLongPressMoveEvent(const gfx::Point& touch_po
 void SelectionControllerEfl::HandleLongPressEndEvent() {
   show_only_large_handle_ = false;
   long_mouse_press_ = false;
-  expecting_update_ = false;
+  selection_change_reason_ = Reason::Irrelevant;
   if (scrolling_)
     show_after_scroll_ = true;
-  ShowHandleAndContextMenuIfRequired();
+  ShowHandleAndContextMenuIfRequired(Reason::LongPressEnded);
 }
 
 void SelectionControllerEfl::PostHandleTapGesture(bool is_content_editable) {
@@ -668,7 +665,7 @@ void SelectionControllerEfl::PostHandleTapGesture(bool is_content_editable) {
     SetSelectionStatus(true);
     SetShowOnlyLargeHandle(true);
     SetSelectionEditable(true);
-    expecting_update_ = true;
+    selection_change_reason_ = Reason::Tap;
   } else {
     SetSelectionEditable(false);
   }
@@ -694,7 +691,7 @@ bool SelectionControllerEfl::IsSelectionValid(const gfx::Rect& left_rect,
   // for such cases. So, the equality for x and y rather than width should be tested.
   if (left_rect.x() == right_rect.x() && left_rect.y() == right_rect.y() &&
       !selection_data_->IsInEditField()  && !handle_being_dragged_ &&
-      !expecting_update_) {
+      selection_change_reason_ == Reason::Irrelevant) {
     SetSelectionStatus(false);
     return false;
   }
index bf542fd..01dbb64 100644 (file)
@@ -112,8 +112,21 @@ class CONTENT_EXPORT SelectionControllerEfl {
   { show_only_large_handle_ = show_only_large_handle; }
   bool GetShowOnlyLargeHandle() const { return show_only_large_handle_; }
 
+  // 'Reason' enum class enumerates all reasons that can cause
+  // text selection changes that require changes on the status
+  // of selection controls (handles and context menu).
+  enum class Reason {
+    ScrollOrZoomGestureEnded = 0,
+    HandleDragged,
+    HandleReleased,
+    LongPressMoved,
+    LongPressEnded,
+    Tap,
+    RequestedByContextMenu,
+    Irrelevant,
+  };
   void SetWaitsForRendererSelectionChanges(
-      bool value) { expecting_update_ = value; }
+      Reason reason) { selection_change_reason_ = reason; }
 
   // Gesture handlers.
   void HandlePostponedGesture(int x, int y, ui::EventType type);
@@ -137,7 +150,7 @@ class CONTENT_EXPORT SelectionControllerEfl {
 
   void HandleLongPressEventPrivate(const gfx::Point& touch_point);
 
-  void ShowHandleAndContextMenuIfRequired();
+  void ShowHandleAndContextMenuIfRequired(Reason explicit_reason = Reason::Irrelevant);
 
   void Clear(bool show_after_scroll = false);
   bool IsSelectionValid(const gfx::Rect& left_rect, const gfx::Rect& right_rect);
@@ -175,10 +188,10 @@ class CONTENT_EXPORT SelectionControllerEfl {
   // behind other layer.
   bool postponed_;
 
-  // Enters a state where browser has requested a text selection
+  // Cache the reason of why browser has requested a text selection
   // change to the renderer. At the next composited selection update
-  // state is handled and reset.
-  bool expecting_update_;
+  // the cache is handled and reset.
+  Reason selection_change_reason_;
 
   // Saves state so that handlers and context menu is not shown when seletion change event occurs.
   bool long_mouse_press_;
index 2473979..0af6610 100644 (file)
@@ -481,7 +481,8 @@ void ContextMenuControllerEfl::RequestShowSelectionHandleAndContextMenu() {
   SelectionControllerEfl* controller = webview_->GetSelectionController();
   if (controller) {
     controller->SetSelectionStatus(true);
-    controller->SetWaitsForRendererSelectionChanges(true);
+    controller->SetWaitsForRendererSelectionChanges(
+        SelectionControllerEfl::Reason::RequestedByContextMenu);
   }
 }