Bug 1275914 part.4 Add a method to retrieve focused content's selection controller to nsIPresShell r?smaug draft
authorMasayuki Nakano <masayuki@d-toybox.com>
Fri, 10 Jun 2016 21:01:32 +0900
changeset 380217 75ebfce7be10045e212b8ad4c6363bd590c5f5e8
parent 380216 41a5a069d53de2172e4060472b8d5f6749405319
child 380218 d91d6527a822d62a6abb24904b3f23a606ef39e2
push id21167
push usermasayuki@d-toybox.com
push dateTue, 21 Jun 2016 06:55:55 +0000
reviewerssmaug
bugs1275914
milestone50.0a1
Bug 1275914 part.4 Add a method to retrieve focused content's selection controller to nsIPresShell r?smaug ContentEventHandler will need to support query any types of selection. Therefore, it cannot use nsCopySupport::GetSelectionForCopy(). Instead, a part of it should be implemented by nsIPresShell::GetSelectionControllerForFocusedContent() and it should be shared by nsCopySupport::GetSelectionForCopy() and ContentEventHandler. MozReview-Commit-ID: 1ItkkIUPFMG
dom/base/nsCopySupport.cpp
layout/base/nsIPresShell.h
layout/base/nsPresShell.cpp
layout/base/nsPresShell.h
--- a/dom/base/nsCopySupport.cpp
+++ b/dom/base/nsCopySupport.cpp
@@ -549,37 +549,27 @@ nsIContent*
 nsCopySupport::GetSelectionForCopy(nsIDocument* aDocument, nsISelection** aSelection)
 {
   *aSelection = nullptr;
 
   nsIPresShell* presShell = aDocument->GetShell();
   if (!presShell)
     return nullptr;
 
-  // check if the focused node in the window has a selection
-  nsCOMPtr<nsPIDOMWindowOuter> focusedWindow;
-  nsIContent* content =
-    nsFocusManager::GetFocusedDescendant(aDocument->GetWindow(), false,
-                                         getter_AddRefs(focusedWindow));
-  if (content) {
-    nsIFrame* frame = content->GetPrimaryFrame();
-    if (frame) {
-      nsCOMPtr<nsISelectionController> selCon;
-      frame->GetSelectionController(presShell->GetPresContext(), getter_AddRefs(selCon));
-      if (selCon) {
-        selCon->GetSelection(nsISelectionController::SELECTION_NORMAL, aSelection);
-        return content;
-      }
-    }
+  nsCOMPtr<nsIContent> focusedContent;
+  nsCOMPtr<nsISelectionController> selectionController =
+    presShell->GetSelectionControllerForFocusedContent(
+      getter_AddRefs(focusedContent));
+  if (!selectionController) {
+    return nullptr;
   }
 
-  // if no selection was found, use the main selection for the window
-  NS_IF_ADDREF(*aSelection =
-                 presShell->GetCurrentSelection(SelectionType::eNormal));
-  return nullptr;
+  selectionController->GetSelection(nsISelectionController::SELECTION_NORMAL,
+                                    aSelection);
+  return focusedContent;
 }
 
 bool
 nsCopySupport::CanCopy(nsIDocument* aDocument)
 {
   if (!aDocument)
     return false;
 
--- a/layout/base/nsIPresShell.h
+++ b/layout/base/nsIPresShell.h
@@ -831,16 +831,34 @@ public:
     *           as set by SetDisplayNonTextSelection
     */
   int16_t GetSelectionFlags() const { return mSelectionFlags; }
 
   virtual mozilla::dom::Selection*
     GetCurrentSelection(mozilla::SelectionType aSelectionType) = 0;
 
   /**
+   * Gets a selection controller for the focused content in the DOM window
+   * for mDocument.
+   *
+   * @param aFocusedContent     If there is focused content in the DOM window,
+   *                            the focused content will be returned.  This may
+   *                            be nullptr if it's not necessary.
+   * @return                    A selection controller for focused content.
+   *                            E.g., if an <input> element has focus, returns
+   *                            the independent selection controller of it.
+   *                            If the DOM window does not have focused content
+   *                            (similar to Document.activeElement), returns
+   *                            nullptr.
+   */
+  virtual already_AddRefed<nsISelectionController>
+            GetSelectionControllerForFocusedContent(
+              nsIContent** aFocusedContent = nullptr) = 0;
+
+  /**
     * Interface to dispatch events via the presshell
     * @note The caller must have a strong reference to the PresShell.
     */
   virtual nsresult HandleEventWithTarget(
                                  mozilla::WidgetEvent* aEvent,
                                  nsIFrame* aFrame,
                                  nsIContent* aContent,
                                  nsEventStatus* aStatus) = 0;
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -1551,16 +1551,47 @@ Selection*
 PresShell::GetCurrentSelection(SelectionType aSelectionType)
 {
   if (!mSelection)
     return nullptr;
 
   return mSelection->GetSelection(aSelectionType);
 }
 
+already_AddRefed<nsISelectionController>
+PresShell::GetSelectionControllerForFocusedContent(nsIContent** aFocusedContent)
+{
+  if (aFocusedContent) {
+    *aFocusedContent = nullptr;
+  }
+
+  if (mDocument) {
+    nsCOMPtr<nsPIDOMWindowOuter> focusedWindow;
+    nsCOMPtr<nsIContent> focusedContent =
+      nsFocusManager::GetFocusedDescendant(mDocument->GetWindow(), false,
+                                           getter_AddRefs(focusedWindow));
+    if (focusedContent) {
+      nsIFrame* frame = focusedContent->GetPrimaryFrame();
+      if (frame) {
+        nsCOMPtr<nsISelectionController> selectionController;
+        frame->GetSelectionController(mPresContext,
+                                      getter_AddRefs(selectionController));
+        if (selectionController) {
+          if (aFocusedContent) {
+            focusedContent.forget(aFocusedContent);
+          }
+          return selectionController.forget();
+        }
+      }
+    }
+  }
+  nsCOMPtr<nsISelectionController> self(this);
+  return self.forget();
+}
+
 NS_IMETHODIMP
 PresShell::ScrollSelectionIntoView(RawSelectionType aRawSelectionType,
                                    SelectionRegion aRegion,
                                    int16_t aFlags)
 {
   if (!mSelection)
     return NS_ERROR_NULL_POINTER;
 
--- a/layout/base/nsPresShell.h
+++ b/layout/base/nsPresShell.h
@@ -107,16 +107,19 @@ public:
   virtual void MakeZombie() override;
 
   virtual void UpdatePreferenceStyles() override;
 
   NS_IMETHOD GetSelection(RawSelectionType aRawSelectionType,
                           nsISelection** aSelection) override;
   virtual mozilla::dom::Selection*
     GetCurrentSelection(SelectionType aSelectionType) override;
+  virtual already_AddRefed<nsISelectionController>
+            GetSelectionControllerForFocusedContent(
+              nsIContent** aFocusedContent = nullptr) override;
 
   NS_IMETHOD SetDisplaySelection(int16_t aToggle) override;
   NS_IMETHOD GetDisplaySelection(int16_t *aToggle) override;
   NS_IMETHOD ScrollSelectionIntoView(RawSelectionType aRawSelectionType,
                                      SelectionRegion aRegion,
                                      int16_t aFlags) override;
   NS_IMETHOD RepaintSelection(RawSelectionType aRawSelectionType) override;