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
--- 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;