From 49801f467c4d00add49d17aaee7efd83751322e4 Mon Sep 17 00:00:00 2001 From: "mrbkap%gmail.com" Date: Tue, 7 Nov 2006 01:35:36 +0000 Subject: [PATCH] Add an API on the presshell for invalidating the caret if it isn't currently contained entirely in its frame. Use it in the editor where we remove the caret's frame out from under it without properly notifying it (due to selection batching). bug 335065, r+sr=roc --- editor/libeditor/text/nsPlaintextEditor.cpp | 7 +++++++ layout/base/nsIPresShell.h | 13 ++++++++++--- layout/base/nsPresShell.cpp | 8 ++++++++ 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/editor/libeditor/text/nsPlaintextEditor.cpp b/editor/libeditor/text/nsPlaintextEditor.cpp index 915fa706128a..97e72c08e17e 100644 --- a/editor/libeditor/text/nsPlaintextEditor.cpp +++ b/editor/libeditor/text/nsPlaintextEditor.cpp @@ -784,6 +784,13 @@ NS_IMETHODIMP nsPlaintextEditor::InsertLineBreak() if (NS_FAILED(res)) return res; if (!selection) return NS_ERROR_NULL_POINTER; + // Batching the selection and moving nodes out from under the caret causes + // caret turds. Ask the shell to invalidate the caret now to avoid the turds. + nsCOMPtr shell; + res = GetPresShell(getter_AddRefs(shell)); + if (NS_FAILED(res)) return res; + shell->MaybeInvalidateCaretPosition(); + nsTextRulesInfo ruleInfo(nsTextEditRules::kInsertBreak); PRBool cancel, handled; res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled); diff --git a/layout/base/nsIPresShell.h b/layout/base/nsIPresShell.h index 2f0ef61bd486..baec14a8b8a6 100644 --- a/layout/base/nsIPresShell.h +++ b/layout/base/nsIPresShell.h @@ -98,10 +98,10 @@ class nsWeakFrame; typedef short SelectionType; -// 0d8a87aa-3e6f-409f-a518-96fd8a29b423 +// 845BA869-F93B-4026-8F42-CB058F0E4D87 #define NS_IPRESSHELL_IID \ -{ 0x79433b66, 0xe8a4, 0x442f, \ - { 0x9c, 0x6e, 0x2f, 0xb2, 0x8d, 0x5e, 0x84, 0xd7 } } +{ 0x845BA869, 0xF93B, 0x4026, \ + { 0x8F, 0x42, 0xCB, 0x05, 0x8F, 0x0E, 0x4D, 0x87 } } // Constants uses for ScrollFrameIntoView() function #define NS_PRESSHELL_SCROLL_TOP 0 @@ -484,6 +484,13 @@ public: */ NS_IMETHOD GetCaret(nsICaret **aOutCaret) = 0; + /** + * Invalidate the caret's current position if it's outside of its frame's + * boundaries. This function is useful if you're batching selection + * notifications and might remove the caret's frame out from under it. + */ + NS_IMETHOD_(void) MaybeInvalidateCaretPosition() = 0; + /** * Set the current caret to a new caret. Returns the old caret. */ diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index c1bb219e3fbe..b005568151b6 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -1202,6 +1202,7 @@ public: // caret handling NS_IMETHOD GetCaret(nsICaret **aOutCaret); + NS_IMETHOD_(void) MaybeInvalidateCaretPosition(); NS_IMETHOD SetCaretEnabled(PRBool aInEnable); NS_IMETHOD SetCaretReadOnly(PRBool aReadOnly); NS_IMETHOD GetCaretEnabled(PRBool *aOutEnabled); @@ -3215,6 +3216,13 @@ NS_IMETHODIMP PresShell::GetCaret(nsICaret **outCaret) return NS_OK; } +NS_IMETHODIMP_(void) PresShell::MaybeInvalidateCaretPosition() +{ + if (mCaret) { + mCaret->InvalidateOutsideCaret(); + } +} + already_AddRefed PresShell::SetCaret(nsICaret *aNewCaret) { nsICaret *oldCaret = nsnull;