Bug 1626291 - Repaint selection when safe. r=masayuki

Note that we intentionally don't move the SetDisplaySelection stuff to the
runnables. It would probably be safe enough, but it's not required and it makes
reasoning about this code harder.

Differential Revision: https://phabricator.services.mozilla.com/D70183

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Emilio Cobos Álvarez 2020-04-09 09:50:58 +00:00
Родитель 9b034b0eaf
Коммит 79f62fbd71
2 изменённых файлов: 32 добавлений и 4 удалений

Просмотреть файл

@ -1597,6 +1597,24 @@ void PresShell::SelectionWillLoseFocus() {
// Do nothing, the main selection is the default focused selection.
}
// Selection repainting code relies on selection offsets being properly
// adjusted (see bug 1626291), so we need to wait until the DOM is finished
// notifying.
static void RepaintNormalSelectionWhenSafe(nsFrameSelection& aFrameSelection) {
if (nsContentUtils::IsSafeToRunScript()) {
aFrameSelection.RepaintSelection(SelectionType::eNormal);
return;
}
// Note that importantly we don't defer changing the DisplaySelection. That'd
// be potentially racy with other code that may change it.
nsContentUtils::AddScriptRunner(NS_NewRunnableFunction(
"RepaintNormalSelectionWhenSafe",
[sel = RefPtr<nsFrameSelection>(&aFrameSelection)] {
sel->RepaintSelection(SelectionType::eNormal);
}));
}
void PresShell::FrameSelectionWillLoseFocus(nsFrameSelection& aFrameSelection) {
if (mFocusedFrameSelection != &aFrameSelection) {
return;
@ -1612,7 +1630,7 @@ void PresShell::FrameSelectionWillLoseFocus(nsFrameSelection& aFrameSelection) {
if (old->GetDisplaySelection() != nsISelectionController::SELECTION_HIDDEN) {
old->SetDisplaySelection(nsISelectionController::SELECTION_HIDDEN);
old->RepaintSelection(SelectionType::eNormal);
RepaintNormalSelectionWhenSafe(*old);
}
if (mSelection) {
@ -1627,7 +1645,7 @@ void PresShell::FrameSelectionWillTakeFocus(nsFrameSelection& aFrameSelection) {
// document's focused selection doesn't change, and this is currently done
// from RepaintSelection. Maybe we should move part of the global selection
// handling here, or something of that sort, unclear.
aFrameSelection.RepaintSelection(SelectionType::eNormal);
RepaintNormalSelectionWhenSafe(aFrameSelection);
#endif
return;
}
@ -1638,13 +1656,13 @@ void PresShell::FrameSelectionWillTakeFocus(nsFrameSelection& aFrameSelection) {
if (old &&
old->GetDisplaySelection() != nsISelectionController::SELECTION_HIDDEN) {
old->SetDisplaySelection(nsISelectionController::SELECTION_HIDDEN);
old->RepaintSelection(SelectionType::eNormal);
RepaintNormalSelectionWhenSafe(*old);
}
if (aFrameSelection.GetDisplaySelection() !=
nsISelectionController::SELECTION_ON) {
aFrameSelection.SetDisplaySelection(nsISelectionController::SELECTION_ON);
aFrameSelection.RepaintSelection(SelectionType::eNormal);
RepaintNormalSelectionWhenSafe(aFrameSelection);
}
}

Просмотреть файл

@ -0,0 +1,10 @@
<script>
function start() {
document.execCommand('selectAll', false)
document.documentElement.appendChild(document.getElementById('input'))
}
</script>
<body onload="start()">
<input id="input" autofocus>
<canvas contenteditable="true" hidden></canvas>
</body>