Bug 699703 - Need reframe before calling SetSelectionAfterTableEdit. r?masayuki
HTMLEditor::TabInTable inserts row element, then it selects a cell. But when enabling lazy frame construction for editable node, it selects invalid cell and table.
Because HTMLEditor::SetSelectionAfterTableEdit doesn't select cell correctly on InsertTableRow().
HTMLEditor::SetSelectionAfterTableEdit uses HTMLEditor::GetCellAt, so it depends on frame. So we need flush frame before calling it.
Also, a comment of HTMLEditor::InsertTableRow is invalid now because we don't use nsresult version of CreateElementWithDefualts.
MozReview-Commit-ID: 698TvmMZgwB
--- a/editor/libeditor/EditorBase.h
+++ b/editor/libeditor/EditorBase.h
@@ -1001,16 +1001,21 @@ public:
* IsSuppressingDispatchingInputEvent() returns true if the editor stops
* dispatching input event. Otherwise, false.
*/
bool IsSuppressingDispatchingInputEvent() const
{
return !mDispatchInputEvent;
}
+ bool Destroyed() const
+ {
+ return mDidPreDestroy;
+ }
+
/**
* GetTransactionManager() returns transaction manager associated with the
* editor. This may return nullptr if undo/redo hasn't been enabled.
*/
already_AddRefed<nsITransactionManager> GetTransactionManager() const;
/**
* Get the input event target. This might return null.
--- a/editor/libeditor/HTMLEditor.cpp
+++ b/editor/libeditor/HTMLEditor.cpp
@@ -652,16 +652,20 @@ HTMLEditor::HandleKeyPressEvent(WidgetKe
if (!blockParent) {
break;
}
bool handled = false;
nsresult rv = NS_OK;
if (HTMLEditUtils::IsTableElement(blockParent)) {
rv = TabInTable(aKeyboardEvent->IsShift(), &handled);
+ // TabInTable might cause reframe
+ if (Destroyed()) {
+ return NS_OK;
+ }
if (handled) {
ScrollSelectionIntoView(false);
}
} else if (HTMLEditUtils::IsListItem(blockParent)) {
rv = Indent(aKeyboardEvent->IsShift()
? NS_LITERAL_STRING("outdent")
: NS_LITERAL_STRING("indent"));
handled = true;
@@ -1015,17 +1019,17 @@ HTMLEditor::TypedText(const nsAString& a
// only inserts a br node
nsCOMPtr<nsIDOMNode> brNode;
return InsertBR(address_of(brNode));
}
return TextEditor::TypedText(aString, aAction);
}
-NS_IMETHODIMP
+nsresult
HTMLEditor::TabInTable(bool inIsShift,
bool* outHandled)
{
NS_ENSURE_TRUE(outHandled, NS_ERROR_NULL_POINTER);
*outHandled = false;
// Find enclosing table cell from selection (cell may be selected element)
nsCOMPtr<Element> cellElement =
--- a/editor/libeditor/HTMLEditor.h
+++ b/editor/libeditor/HTMLEditor.h
@@ -428,17 +428,17 @@ protected:
*/
already_AddRefed<nsINode> GetFocusedNode();
/**
* Return TRUE if aElement is a table-related elemet and caret was set.
*/
bool SetCaretInTableCell(nsIDOMElement* aElement);
- NS_IMETHOD TabInTable(bool inIsShift, bool* outHandled);
+ nsresult TabInTable(bool inIsShift, bool* outHandled);
already_AddRefed<Element> CreateBR(nsINode* aNode, int32_t aOffset,
EDirection aSelect = eNone);
NS_IMETHOD CreateBR(
nsIDOMNode* aNode, int32_t aOffset,
nsCOMPtr<nsIDOMNode>* outBRNode,
nsIEditor::EDirection aSelect = nsIEditor::eNone) override;
nsresult InsertBR(nsCOMPtr<nsIDOMNode>* outBRNode);
--- a/editor/libeditor/HTMLEditorEventListener.cpp
+++ b/editor/libeditor/HTMLEditorEventListener.cpp
@@ -212,16 +212,21 @@ HTMLEditorEventListener::MouseClick(nsID
}
nsCOMPtr<nsIDOMEventTarget> target;
nsresult rv = aMouseEvent->AsEvent()->GetTarget(getter_AddRefs(target));
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(target, NS_ERROR_NULL_POINTER);
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(target);
- HTMLEditor* htmlEditor = mEditorBase->AsHTMLEditor();
+ RefPtr<HTMLEditor> htmlEditor = mEditorBase->AsHTMLEditor();
MOZ_ASSERT(htmlEditor);
htmlEditor->DoInlineTableEditingAction(element);
+ // DoInlineTableEditingAction might cause reframe
+ // Editor is destroyed.
+ if (htmlEditor->Destroyed()) {
+ return NS_OK;
+ }
return EditorEventListener::MouseClick(aMouseEvent);
}
} // namespace mozilla
--- a/editor/libeditor/HTMLInlineTableEditor.cpp
+++ b/editor/libeditor/HTMLInlineTableEditor.cpp
@@ -169,16 +169,21 @@ HTMLEditor::DoInlineTableEditingAction(n
DeleteTableRow(1);
#ifndef DISABLE_TABLE_DELETION
hideUI = (rowCount == 1);
#endif
}
else
return NS_OK;
+ // InsertTableRow might causes reframe
+ if (Destroyed()) {
+ return NS_OK;
+ }
+
if (hideUI) {
HideInlineTableEditingUI();
if (hideResizersWithInlineTableUI)
HideResizers();
}
}
return NS_OK;
--- a/editor/libeditor/HTMLTableEditor.cpp
+++ b/editor/libeditor/HTMLTableEditor.cpp
@@ -5,16 +5,17 @@
#include <stdio.h>
#include "mozilla/HTMLEditor.h"
#include "HTMLEditUtils.h"
#include "mozilla/Assertions.h"
#include "mozilla/EditorUtils.h"
+#include "mozilla/FlushType.h"
#include "mozilla/dom/Selection.h"
#include "mozilla/dom/Element.h"
#include "nsAString.h"
#include "nsAlgorithm.h"
#include "nsCOMPtr.h"
#include "nsDebug.h"
#include "nsError.h"
#include "nsGkAtoms.h"
@@ -685,19 +686,26 @@ HTMLEditor::InsertTableRow(int32_t aNumb
}
// Use transaction system to insert the entire row+cells
// (Note that rows are inserted at same childoffset each time)
rv = InsertNode(*newRow, *parentOfRow, newRowOffset);
NS_ENSURE_SUCCESS(rv, rv);
}
}
- // XXX This might be the result of the last call of
- // CreateElementWithDefaults(), otherwise, NS_OK.
- return rv;
+
+ // SetSelectionAfterTableEdit from AutoSelectionSetterAfterTableEdit will
+ // access frame selection, so we need reframe.
+ // Because GetCellAt depends on frame.
+ nsCOMPtr<nsIPresShell> ps = GetPresShell();
+ if (ps) {
+ ps->FlushPendingNotifications(FlushType::Frames);
+ }
+
+ return NS_OK;
}
// Editor helper only
// XXX Code changed for bug 217717 and now we don't need aSelection param
// TODO: Remove aSelection param
nsresult
HTMLEditor::DeleteTable2(nsIDOMElement* aTable,
Selection* aSelection)