mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-03-06 16:51:46 +00:00
Fix for bug 335856 (Can't easily put caret in this designmode iframe testcase (caret doesn't show up)), also fixes bug 393568 (blocking1.9+) and bug 386872. r/sr=jst.
This commit is contained in:
parent
4a67feba15
commit
f6c6606714
@ -217,7 +217,8 @@ nsEditor::~nsEditor()
|
||||
NS_IF_RELEASE(mViewManager);
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS4(nsEditor, nsIEditor, nsIEditorIMESupport, nsISupportsWeakReference, nsIPhonetic)
|
||||
NS_IMPL_ISUPPORTS5(nsEditor, nsIEditor, nsIEditorIMESupport,
|
||||
nsISupportsWeakReference, nsIPhonetic, nsIMutationObserver)
|
||||
|
||||
#ifdef XP_MAC
|
||||
#pragma mark -
|
||||
@ -244,6 +245,9 @@ nsEditor::Init(nsIDOMDocument *aDoc, nsIPresShell* aPresShell, nsIContent *aRoot
|
||||
if (aRoot)
|
||||
mRootElement = do_QueryInterface(aRoot);
|
||||
|
||||
nsCOMPtr<nsINode> document = do_QueryInterface(aDoc);
|
||||
document->AddMutationObserver(this);
|
||||
|
||||
// Set up the DTD
|
||||
// XXX - in the long run we want to get this from the document, but there
|
||||
// is no way to do that right now. So we leave it null here and set
|
||||
@ -519,6 +523,10 @@ nsEditor::PreDestroy()
|
||||
// tell our listeners that the doc is going away
|
||||
NotifyDocumentListeners(eDocumentToBeDestroyed);
|
||||
|
||||
nsCOMPtr<nsINode> document = do_QueryReferent(mDocWeak);
|
||||
if (document)
|
||||
document->RemoveMutationObserver(this);
|
||||
|
||||
// Unregister event listeners
|
||||
RemoveEventListeners();
|
||||
mActionListeners.Clear();
|
||||
@ -2280,6 +2288,45 @@ nsEditor::GetQueryCaretRect(nsQueryCaretRectEventReply* aReply)
|
||||
/* Non-interface, public methods */
|
||||
|
||||
|
||||
void
|
||||
nsEditor::ContentAppended(nsIDocument *aDocument, nsIContent* aContainer,
|
||||
PRInt32 aNewIndexInContainer)
|
||||
{
|
||||
ContentInserted(aDocument, aContainer, nsnull, aNewIndexInContainer);
|
||||
}
|
||||
|
||||
void
|
||||
nsEditor::ContentInserted(nsIDocument *aDocument, nsIContent* aContainer,
|
||||
nsIContent* aChild, PRInt32 aIndexInContainer)
|
||||
{
|
||||
// XXX If we need aChild then nsEditor::ContentAppended should start passing
|
||||
// in the child.
|
||||
if (!mRootElement)
|
||||
{
|
||||
// Need to remove the event listeners first because BeginningOfDocument
|
||||
// could set a new root (and event target) and we won't be able to remove
|
||||
// them from the old event target then.
|
||||
RemoveEventListeners();
|
||||
BeginningOfDocument();
|
||||
InstallEventListeners();
|
||||
SyncRealTimeSpell();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsEditor::ContentRemoved(nsIDocument *aDocument, nsIContent* aContainer,
|
||||
nsIContent* aChild, PRInt32 aIndexInContainer)
|
||||
{
|
||||
nsCOMPtr<nsIDOMHTMLElement> elem = do_QueryInterface(aChild);
|
||||
if (elem == mRootElement)
|
||||
{
|
||||
RemoveEventListeners();
|
||||
mRootElement = nsnull;
|
||||
mEventTarget = nsnull;
|
||||
InstallEventListeners();
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsEditor::GetRootElement(nsIDOMElement **aRootElement)
|
||||
{
|
||||
|
@ -64,6 +64,7 @@
|
||||
#include "nsIEditorSpellCheck.h"
|
||||
#include "nsIInlineSpellChecker.h"
|
||||
#include "nsPIDOMEventTarget.h"
|
||||
#include "nsStubMutationObserver.h"
|
||||
|
||||
class nsIDOMCharacterData;
|
||||
class nsIDOMRange;
|
||||
@ -97,7 +98,8 @@ class nsIDOMEventTarget;
|
||||
class nsEditor : public nsIEditor,
|
||||
public nsIEditorIMESupport,
|
||||
public nsSupportsWeakReference,
|
||||
public nsIPhonetic
|
||||
public nsIPhonetic,
|
||||
public nsStubMutationObserver
|
||||
{
|
||||
public:
|
||||
|
||||
@ -151,6 +153,9 @@ public:
|
||||
// nsIPhonetic
|
||||
NS_DECL_NSIPHONETIC
|
||||
|
||||
NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
|
||||
NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
|
||||
NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
|
||||
|
||||
public:
|
||||
|
||||
|
@ -1123,7 +1123,7 @@ nsTextEditorFocusListener::Focus(nsIDOMEvent* aEvent)
|
||||
|
||||
nsCOMPtr<nsISelectionController> selCon;
|
||||
mEditor->GetSelectionController(getter_AddRefs(selCon));
|
||||
if (selCon && editableRoot)
|
||||
if (selCon)
|
||||
{
|
||||
nsCOMPtr<nsISelection> selection;
|
||||
selCon->GetSelection(nsISelectionController::SELECTION_NORMAL,
|
||||
@ -1150,6 +1150,14 @@ nsTextEditorFocusListener::Focus(nsIDOMEvent* aEvent)
|
||||
{
|
||||
selectionPrivate->SetAncestorLimiter(editableRoot);
|
||||
}
|
||||
|
||||
if (!editableRoot) {
|
||||
PRInt32 rangeCount;
|
||||
selection->GetRangeCount(&rangeCount);
|
||||
if (rangeCount == 0) {
|
||||
mEditor->BeginningOfDocument();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -134,7 +134,7 @@ nsTextEditRules::Init(nsPlaintextEditor *aEditor, PRUint32 aFlags)
|
||||
NS_ASSERTION(selection, "editor cannot get selection");
|
||||
|
||||
// Cache our body node, if available.
|
||||
GetBody();
|
||||
nsIDOMNode *body = mEditor->GetRoot();
|
||||
|
||||
// Put in a magic br if needed. This method handles null selection,
|
||||
// which should never happen anyway
|
||||
@ -148,15 +148,15 @@ nsTextEditRules::Init(nsPlaintextEditor *aEditor, PRUint32 aFlags)
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
|
||||
if (mBody)
|
||||
if (body)
|
||||
{
|
||||
// create a range that is the entire body contents
|
||||
nsCOMPtr<nsIDOMRange> wholeDoc =
|
||||
do_CreateInstance("@mozilla.org/content/range;1");
|
||||
if (!wholeDoc) return NS_ERROR_NULL_POINTER;
|
||||
wholeDoc->SetStart(mBody,0);
|
||||
wholeDoc->SetStart(body,0);
|
||||
nsCOMPtr<nsIDOMNodeList> list;
|
||||
res = mBody->GetChildNodes(getter_AddRefs(list));
|
||||
res = body->GetChildNodes(getter_AddRefs(list));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!list) return NS_ERROR_FAILURE;
|
||||
|
||||
@ -164,7 +164,7 @@ nsTextEditRules::Init(nsPlaintextEditor *aEditor, PRUint32 aFlags)
|
||||
res = list->GetLength(&listCount);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
res = wholeDoc->SetEnd(mBody, listCount);
|
||||
res = wholeDoc->SetEnd(body, listCount);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// replace newlines in that range with breaks
|
||||
@ -992,9 +992,11 @@ nsTextEditRules::WillDeleteSelection(nsISelection *aSelection,
|
||||
// make sure it is not last node in editfield. If it is, cancel deletion.
|
||||
if (nextNode && (aCollapsedAction == nsIEditor::eNext) && nsTextEditUtils::IsBreak(nextNode))
|
||||
{
|
||||
if (!GetBody()) return NS_ERROR_NULL_POINTER;
|
||||
nsIDOMNode *body = mEditor->GetRoot();
|
||||
if (!body)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
nsCOMPtr<nsIDOMNode> lastChild;
|
||||
res = mBody->GetLastChild(getter_AddRefs(lastChild));
|
||||
res = body->GetLastChild(getter_AddRefs(lastChild));
|
||||
if (lastChild == nextNode)
|
||||
{
|
||||
*aCancel = PR_TRUE;
|
||||
@ -1251,9 +1253,11 @@ nsTextEditRules::CreateTrailingBRIfNeeded()
|
||||
// but only if we aren't a single line edit field
|
||||
if (mFlags & nsIPlaintextEditor::eEditorSingleLineMask)
|
||||
return NS_OK;
|
||||
if (!GetBody()) return NS_ERROR_NULL_POINTER;
|
||||
nsIDOMNode *body = mEditor->GetRoot();
|
||||
if (!body)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
nsCOMPtr<nsIDOMNode> lastChild;
|
||||
nsresult res = mBody->GetLastChild(getter_AddRefs(lastChild));
|
||||
nsresult res = body->GetLastChild(getter_AddRefs(lastChild));
|
||||
// assuming CreateBogusNodeIfNeeded() has been called first
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!lastChild) return NS_ERROR_NULL_POINTER;
|
||||
@ -1262,10 +1266,10 @@ nsTextEditRules::CreateTrailingBRIfNeeded()
|
||||
{
|
||||
nsAutoTxnsConserveSelection dontSpazMySelection(mEditor);
|
||||
PRUint32 rootLen;
|
||||
res = mEditor->GetLengthOfDOMNode(mBody, rootLen);
|
||||
res = mEditor->GetLengthOfDOMNode(body, rootLen);
|
||||
if (NS_FAILED(res)) return res;
|
||||
nsCOMPtr<nsIDOMNode> unused;
|
||||
res = CreateMozBR(mBody, rootLen, address_of(unused));
|
||||
res = CreateMozBR(body, rootLen, address_of(unused));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@ -1279,8 +1283,9 @@ nsTextEditRules::CreateBogusNodeIfNeeded(nsISelection *aSelection)
|
||||
|
||||
// tell rules system to not do any post-processing
|
||||
nsAutoRules beginRulesSniffing(mEditor, nsEditor::kOpIgnore, nsIEditor::eNone);
|
||||
|
||||
if (!GetBody())
|
||||
|
||||
nsIDOMNode* body = mEditor->GetRoot();
|
||||
if (!body)
|
||||
{
|
||||
// we don't even have a body yet, don't insert any bogus nodes at
|
||||
// this point.
|
||||
@ -1293,11 +1298,11 @@ nsTextEditRules::CreateBogusNodeIfNeeded(nsISelection *aSelection)
|
||||
// if no editable content is found, insert the bogus node
|
||||
PRBool needsBogusContent=PR_TRUE;
|
||||
nsCOMPtr<nsIDOMNode> bodyChild;
|
||||
nsresult res = mBody->GetFirstChild(getter_AddRefs(bodyChild));
|
||||
nsresult res = body->GetFirstChild(getter_AddRefs(bodyChild));
|
||||
while ((NS_SUCCEEDED(res)) && bodyChild)
|
||||
{
|
||||
if (mEditor->IsMozEditorBogusNode(bodyChild) ||
|
||||
!mEditor->IsEditable(mBody) ||
|
||||
!mEditor->IsEditable(body) ||
|
||||
mEditor->IsEditable(bodyChild))
|
||||
{
|
||||
needsBogusContent = PR_FALSE;
|
||||
@ -1324,11 +1329,11 @@ nsTextEditRules::CreateBogusNodeIfNeeded(nsISelection *aSelection)
|
||||
kMOZEditorBogusNodeValue );
|
||||
|
||||
// put the node in the document
|
||||
res = mEditor->InsertNode(mBogusNode, mBody, 0);
|
||||
res = mEditor->InsertNode(mBogusNode, body, 0);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// set selection
|
||||
aSelection->Collapse(mBody, 0);
|
||||
aSelection->Collapse(body, 0);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@ -1466,15 +1471,3 @@ nsTextEditRules::CreateMozBR(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr<ns
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
nsIDOMNode *
|
||||
nsTextEditRules::GetBody()
|
||||
{
|
||||
if (!mBody)
|
||||
{
|
||||
// remember our body node
|
||||
mBody = mEditor->GetRoot();
|
||||
}
|
||||
|
||||
return mBody;
|
||||
}
|
||||
|
@ -197,15 +197,12 @@ protected:
|
||||
nsIEditor::EDirection aAction,
|
||||
PRBool *aCancel);
|
||||
|
||||
nsIDOMNode *GetBody();
|
||||
|
||||
// data members
|
||||
nsPlaintextEditor *mEditor; // note that we do not refcount the editor
|
||||
nsString mPasswordText; // a buffer we use to store the real value of password editors
|
||||
nsString mPasswordIMEText; // a buffer we use to track the IME composition string
|
||||
PRUint32 mPasswordIMEIndex;
|
||||
nsCOMPtr<nsIDOMNode> mBogusNode; // magic node acts as placeholder in empty doc
|
||||
nsCOMPtr<nsIDOMNode> mBody; // cached root node
|
||||
nsCOMPtr<nsIDOMNode> mCachedSelectionNode; // cached selected node
|
||||
PRInt32 mCachedSelectionOffset; // cached selected offset
|
||||
PRUint32 mFlags;
|
||||
|
Loading…
x
Reference in New Issue
Block a user