Bug 1261299 - Update the selection cache on repaint to handle when a pre-existing selection becomes active aka the current selection.
MozReview-Commit-ID: HrTQnHd12rg
--- a/layout/generic/nsFrameSelection.h
+++ b/layout/generic/nsFrameSelection.h
@@ -368,17 +368,17 @@ public:
nsresult ScrollSelectionIntoView(mozilla::SelectionType aSelectionType,
SelectionRegion aRegion,
int16_t aFlags) const;
/** RepaintSelection repaints the selected frames that are inside the selection
* specified by aSelectionType.
* @param aSelectionType The selection type what you want to repaint.
*/
- nsresult RepaintSelection(mozilla::SelectionType aSelectionType) const;
+ nsresult RepaintSelection(mozilla::SelectionType aSelectionType);
/** GetFrameForNodeOffset given a node and its child offset, return the nsIFrame and
* the offset into that frame.
* @param aNode input parameter for the node to look at
* @param aOffset offset into above node.
* @param aReturnOffset will contain offset into frame.
*/
virtual nsIFrame* GetFrameForNodeOffset(nsIContent* aNode,
@@ -676,16 +676,20 @@ private:
uint32_t GetBatching() const {return mBatching; }
bool GetNotifyFrames() const { return mNotifyFrames; }
void SetDirty(bool aDirty=true){if (mBatching) mChangesDuringBatching = aDirty;}
// nsFrameSelection may get deleted when calling this,
// so remember to use nsCOMPtr when needed.
nsresult NotifySelectionListeners(mozilla::SelectionType aSelectionType);
+ // Update the selection cache on repaint when the
+ // selection being repainted is not empty.
+ nsresult UpdateSelectionCacheOnRepaintSelection(mozilla::dom::
+ Selection* aSel);
RefPtr<mozilla::dom::Selection>
mDomSelections[mozilla::kPresentSelectionTypeCount];
// Table selection support.
nsITableCellLayout* GetCellLayout(nsIContent *aCellContent) const;
nsresult SelectBlockOfCells(nsIContent *aStartNode, nsIContent *aEndNode);
--- a/layout/generic/nsSelection.cpp
+++ b/layout/generic/nsSelection.cpp
@@ -1959,24 +1959,32 @@ nsFrameSelection::ScrollSelectionIntoVie
// flushed and PresShell/PresContext/Frames may be dead. See bug 418470.
return mDomSelections[index]->ScrollIntoView(aRegion,
verticalScroll,
nsIPresShell::ScrollAxis(),
flags);
}
nsresult
-nsFrameSelection::RepaintSelection(SelectionType aSelectionType) const
+nsFrameSelection::RepaintSelection(SelectionType aSelectionType)
{
int8_t index = GetIndexFromSelectionType(aSelectionType);
if (index < 0)
return NS_ERROR_INVALID_ARG;
if (!mDomSelections[index])
return NS_ERROR_NULL_POINTER;
NS_ENSURE_STATE(mShell);
+
+// On macOS, update the selection cache to the new active selection
+// aka the current selection.
+#ifdef XP_MACOSX
+ if (aSelectionType == SelectionType::eNormal) {
+ UpdateSelectionCacheOnRepaintSelection(mDomSelections[index]);
+ }
+#endif
return mDomSelections[index]->Repaint(mShell->GetPresContext());
}
nsIFrame*
nsFrameSelection::GetFrameForNodeOffset(nsIContent* aNode,
int32_t aOffset,
CaretAssociateHint aHint,
int32_t* aReturnOffset) const
@@ -6507,16 +6515,54 @@ nsAutoCopyListener::NotifySelectionChang
nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDoc);
NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
// call the copy code
return nsCopySupport::HTMLCopy(aSel, doc,
mCachedClipboard, false);
}
+/**
+ * See Bug 1288453.
+ *
+ * Update the selection cache on repaint to handle when a pre-existing
+ * selection becomes active aka the current selection.
+ *
+ * 1. Change the current selection by click n dragging another selection.
+ * - Make a selection on content page. Make a selection in a text editor.
+ * - You can click n drag the content selection to make it active again.
+ * 2. Change the current selection when switching to a tab with a selection.
+ * - Make selection in tab.
+ * - Switching tabs will make its respective selection active.
+ *
+ * Therefore, we only update the selection cache on a repaint
+ * if the current selection being repainted is not an empty selection.
+ *
+ * If the current selection is empty. The current selection cache
+ * would be cleared by nsAutoCopyListener::NotifySelectionChanged.
+ */
+nsresult
+nsFrameSelection::UpdateSelectionCacheOnRepaintSelection(Selection* aSel)
+{
+ nsIPresShell* ps = aSel->GetPresShell();
+ if (!ps) {
+ return NS_OK;
+ }
+ nsCOMPtr<nsIDocument> aDoc = ps->GetDocument();
+
+ bool collapsed;
+ if (aDoc && aSel &&
+ NS_SUCCEEDED(aSel->GetIsCollapsed(&collapsed)) && !collapsed) {
+ return nsCopySupport::HTMLCopy(aSel, aDoc,
+ nsIClipboard::kSelectionCache, false);
+ }
+
+ return NS_OK;
+}
+
// SelectionChangeListener
SelectionChangeListener::RawRangeData::RawRangeData(const nsRange* aRange)
{
mozilla::ErrorResult rv;
mStartParent = aRange->GetStartContainer(rv);
rv.SuppressException();
mEndParent = aRange->GetEndContainer(rv);