Bug 1632425 - Part 1: Add EditorUtils::IsPointInSelection() r=masayuki
authorKagami Sascha Rosylight <saschanaz@outlook.com>
Wed, 03 Jun 2020 03:08:05 +0000
changeset 533692 da4122fa9fd12a905a9a77809723df8a38db09df
parent 533691 a34182878b968d951dd7cc77440eda4070dab636
child 533693 67d197b2b8d270b6c852c812d57d670bd96ce9e7
push id37475
push userbtara@mozilla.com
push dateWed, 03 Jun 2020 16:12:12 +0000
treeherdermozilla-central@ea34fd156c89 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmasayuki
bugs1632425
milestone79.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1632425 - Part 1: Add EditorUtils::IsPointInSelection() r=masayuki Differential Revision: https://phabricator.services.mozilla.com/D77812
editor/libeditor/EditorEventListener.cpp
editor/libeditor/EditorUtils.cpp
editor/libeditor/EditorUtils.h
editor/libeditor/HTMLEditorEventListener.cpp
editor/libeditor/TextEditorDataTransfer.cpp
--- a/editor/libeditor/EditorEventListener.cpp
+++ b/editor/libeditor/EditorEventListener.cpp
@@ -1023,36 +1023,18 @@ bool EditorEventListener::CanInsertAtDro
 
   int32_t dropOffset = -1;
   nsCOMPtr<nsIContent> dropParentContent =
       aDragEvent->GetRangeParentContentAndOffset(&dropOffset);
   if (!dropParentContent || NS_WARN_IF(DetachedFromEditor())) {
     return false;
   }
 
-  uint32_t rangeCount = selection->RangeCount();
-  IgnoredErrorResult ignoredError;
-  for (uint32_t i = 0; i < rangeCount; i++) {
-    RefPtr<const nsRange> range = selection->GetRangeAt(i);
-    if (!range) {
-      // Don't bail yet, iterate through them all
-      continue;
-    }
-
-    bool inRange =
-        range->IsPointInRange(*dropParentContent, dropOffset, ignoredError);
-    NS_WARNING_ASSERTION(!ignoredError.Failed(),
-                         "nsRange::IsPointInRange() failed");
-    if (!ignoredError.Failed() && inRange) {
-      // Okay, now you can bail, we are over the orginal selection
-      return false;
-    }
-    ignoredError.SuppressException();
-  }
-  return true;
+  return !EditorUtils::IsPointInSelection(*selection, *dropParentContent,
+                                          dropOffset);
 }
 
 nsresult EditorEventListener::HandleStartComposition(
     WidgetCompositionEvent* aCompositionStartEvent) {
   if (NS_WARN_IF(!aCompositionStartEvent)) {
     return NS_ERROR_FAILURE;
   }
   if (DetachedFromEditor()) {
--- a/editor/libeditor/EditorUtils.cpp
+++ b/editor/libeditor/EditorUtils.cpp
@@ -249,9 +249,39 @@ bool EditorUtils::IsContentPreformatted(
     // For instance, this is true of JS tags inside the body (which show
     // up as #text nodes but have no ComputedStyle).
     return false;
   }
 
   return elementStyle->StyleText()->WhiteSpaceIsSignificant();
 }
 
+bool EditorUtils::IsPointInSelection(const Selection& aSelection,
+                                     nsINode& aParentNode, int32_t aOffset) {
+  if (aSelection.IsCollapsed()) {
+    return false;
+  }
+
+  uint32_t rangeCount = aSelection.RangeCount();
+  for (uint32_t i = 0; i < rangeCount; i++) {
+    RefPtr<const nsRange> range = aSelection.GetRangeAt(i);
+    if (!range) {
+      // Don't bail yet, iterate through them all
+      continue;
+    }
+
+    IgnoredErrorResult ignoredError;
+    bool nodeIsInSelection =
+        range->IsPointInRange(aParentNode, aOffset, ignoredError) &&
+        !ignoredError.Failed();
+    NS_WARNING_ASSERTION(!ignoredError.Failed(),
+                         "nsRange::IsPointInRange() failed");
+
+    // Done when we find a range that we are in
+    if (nodeIsInSelection) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
 }  // namespace mozilla
--- a/editor/libeditor/EditorUtils.h
+++ b/editor/libeditor/EditorUtils.h
@@ -903,13 +903,19 @@ class EditorUtils final {
         return true;
       case nsIEditor::ePrevious:
       case nsIEditor::eNext:
         return aSelection.IsCollapsed();
       default:
         return false;
     }
   }
+
+  /**
+   * Returns true if aSelection includes the point in aParentContent.
+   */
+  static bool IsPointInSelection(const Selection& aSelection,
+                                 nsINode& aParentNode, int32_t aOffset);
 };
 
 }  // namespace mozilla
 
 #endif  // #ifndef mozilla_EditorUtils_h
--- a/editor/libeditor/HTMLEditorEventListener.cpp
+++ b/editor/libeditor/HTMLEditorEventListener.cpp
@@ -309,40 +309,18 @@ nsresult HTMLEditorEventListener::MouseD
     int32_t offset = -1;
     nsCOMPtr<nsIContent> parentContent =
         aMouseEvent->GetRangeParentContentAndOffset(&offset);
     if (NS_WARN_IF(!parentContent)) {
       return NS_ERROR_FAILURE;
     }
 
     // Detect if mouse point is within current selection for context click
-    bool nodeIsInSelection = false;
-    if (isContextClick && !selection->IsCollapsed()) {
-      uint32_t rangeCount = selection->RangeCount();
-
-      for (uint32_t i = 0; i < rangeCount; i++) {
-        RefPtr<const nsRange> range = selection->GetRangeAt(i);
-        if (!range) {
-          // Don't bail yet, iterate through them all
-          continue;
-        }
-
-        IgnoredErrorResult ignoredError;
-        nodeIsInSelection =
-            range->IsPointInRange(*parentContent, offset, ignoredError) &&
-            !ignoredError.Failed();
-        NS_WARNING_ASSERTION(!ignoredError.Failed(),
-                             "nsRange::IsPointInRange() failed");
-
-        // Done when we find a range that we are in
-        if (nodeIsInSelection) {
-          break;
-        }
-      }
-    }
+    bool nodeIsInSelection =
+        EditorUtils::IsPointInSelection(*selection, *parentContent, offset);
     nsCOMPtr<nsIContent> originalEventTargetContent =
         originalEventTargetElement;
     if (!originalEventTargetContent) {
       originalEventTargetContent = do_QueryInterface(originalEventTarget);
     }
     if (originalEventTargetContent && !nodeIsInSelection) {
       RefPtr<Element> element = originalEventTargetElement.get();
       if (!originalEventTargetContent->IsElement()) {
--- a/editor/libeditor/TextEditorDataTransfer.cpp
+++ b/editor/libeditor/TextEditorDataTransfer.cpp
@@ -248,37 +248,27 @@ nsresult TextEditor::OnDrop(DragEvent* a
   if (NS_WARN_IF(!droppedAt.IsSet()) ||
       NS_WARN_IF(!droppedAt.GetContainerAsContent())) {
     return NS_ERROR_FAILURE;
   }
 
   // Check if dropping into a selected range.  If so and the source comes from
   // same document, jump through some hoops to determine if mouse is over
   // selection (bail) and whether user wants to copy selection or delete it.
-  if (!SelectionRefPtr()->IsCollapsed() && sourceNode &&
-      sourceNode->IsEditable() && srcdoc == document) {
-    uint32_t rangeCount = SelectionRefPtr()->RangeCount();
-    for (uint32_t j = 0; j < rangeCount; j++) {
-      const nsRange* range = SelectionRefPtr()->GetRangeAt(j);
-      if (NS_WARN_IF(!range)) {
-        // don't bail yet, iterate through them all
-        continue;
-      }
-      IgnoredErrorResult ignoredError;
-      if (range->IsPointInRange(*droppedAt.GetContainer(), droppedAt.Offset(),
-                                ignoredError) &&
-          !ignoredError.Failed()) {
-        // If source document and destination document is same and dropping
-        // into one of selected ranges, we don't need to do nothing.
-        // XXX If the source comes from outside of this editor, this check
-        //     means that we don't allow to drop the item in the selected
-        //     range.  However, the selection is hidden until the <input> or
-        //     <textarea> gets focus, therefore, this looks odd.
-        return NS_OK;
-      }
+  if (sourceNode && sourceNode->IsEditable() && srcdoc == document) {
+    bool isPointInSelection = EditorUtils::IsPointInSelection(
+        *SelectionRefPtr(), *droppedAt.GetContainer(), droppedAt.Offset());
+    if (isPointInSelection) {
+      // If source document and destination document is same and dropping
+      // into one of selected ranges, we don't need to do nothing.
+      // XXX If the source comes from outside of this editor, this check
+      //     means that we don't allow to drop the item in the selected
+      //     range.  However, the selection is hidden until the <input> or
+      //     <textarea> gets focus, therefore, this looks odd.
+      return NS_OK;
     }
   }
 
   // Delete if user doesn't want to copy when user moves selected content
   // to different place in same editor.
   // XXX Do we need the check whether it's in same document or not?
   RefPtr<TextEditor> editorToDeleteSelection;
   if (sourceNode && sourceNode->IsEditable() && srcdoc == document) {