Bug 978023 part.2 Clean up IMEContentObserver r=smaug

This commit is contained in:
Masayuki Nakano 2014-03-08 10:20:07 +09:00
parent ce875b5089
commit 9236d6ef28
3 changed files with 110 additions and 85 deletions

View File

@ -74,11 +74,11 @@ IMEContentObserver::Init(nsIWidget* aWidget,
NS_ENSURE_TRUE_VOID(selCon);
selCon->GetSelection(nsISelectionController::SELECTION_NORMAL,
getter_AddRefs(mSel));
NS_ENSURE_TRUE_VOID(mSel);
getter_AddRefs(mSelection));
NS_ENSURE_TRUE_VOID(mSelection);
nsCOMPtr<nsIDOMRange> selDomRange;
if (NS_SUCCEEDED(mSel->GetRangeAt(0, getter_AddRefs(selDomRange)))) {
if (NS_SUCCEEDED(mSelection->GetRangeAt(0, getter_AddRefs(selDomRange)))) {
nsRange* selRange = static_cast<nsRange*>(selDomRange.get());
NS_ENSURE_TRUE_VOID(selRange && selRange->GetStartParent());
@ -117,13 +117,13 @@ IMEContentObserver::Init(nsIWidget* aWidget,
void
IMEContentObserver::ObserveEditableNode()
{
MOZ_ASSERT(mSel);
MOZ_ASSERT(mSelection);
MOZ_ASSERT(mRootContent);
mUpdatePreference = mWidget->GetIMEUpdatePreference();
if (mUpdatePreference.WantSelectionChange()) {
// add selection change listener
nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryInterface(mSel));
nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryInterface(mSelection));
NS_ENSURE_TRUE_VOID(selPrivate);
nsresult rv = selPrivate->AddSelectionListener(this);
NS_ENSURE_SUCCESS_VOID(rv);
@ -143,7 +143,7 @@ IMEContentObserver::ObserveEditableNode()
}
void
IMEContentObserver::Destroy(void)
IMEContentObserver::Destroy()
{
// If CreateTextStateManager failed, mRootContent will be null,
// and we should not call NotifyIME(IMENotification(NOTIFY_IME_OF_BLUR))
@ -157,12 +157,13 @@ IMEContentObserver::Destroy(void)
}
// Even if there are some pending notification, it'll never notify the widget.
mWidget = nullptr;
if (mUpdatePreference.WantSelectionChange() && mSel) {
nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryInterface(mSel));
if (selPrivate)
if (mUpdatePreference.WantSelectionChange() && mSelection) {
nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryInterface(mSelection));
if (selPrivate) {
selPrivate->RemoveSelectionListener(this);
}
mSel = nullptr;
}
mSelection = nullptr;
if (mUpdatePreference.WantTextChange() && mRootContent) {
mRootContent->RemoveMutationObserver(this);
}
@ -180,7 +181,7 @@ bool
IMEContentObserver::IsManaging(nsPresContext* aPresContext,
nsIContent* aContent)
{
if (!mSel || !mRootContent || !mEditableNode) {
if (!mSelection || !mRootContent || !mEditableNode) {
return false; // failed to initialize.
}
if (!mRootContent->IsInDoc()) {
@ -204,6 +205,20 @@ IMEContentObserver::IsEditorHandlingEventForComposition() const
return composition->IsEditorHandlingEvent();
}
nsresult
IMEContentObserver::GetSelectionAndRoot(nsISelection** aSelection,
nsIContent** aRootContent) const
{
if (!mEditableNode || !mSelection) {
return NS_ERROR_NOT_AVAILABLE;
}
NS_ASSERTION(mSelection && mRootContent, "uninitialized content observer");
NS_ADDREF(*aSelection = mSelection);
NS_ADDREF(*aRootContent = mRootContent);
return NS_OK;
}
// Helper class, used for selection change notification
class SelectionChangeEvent : public nsRunnable
{
@ -218,11 +233,11 @@ public:
NS_IMETHOD Run()
{
if (mDispatcher->mWidget) {
if (mDispatcher->GetWidget()) {
IMENotification notification(NOTIFY_IME_OF_SELECTION_CHANGE);
notification.mSelectionChangeData.mCausedByComposition =
mCausedByComposition;
mDispatcher->mWidget->NotifyIME(notification);
mDispatcher->GetWidget()->NotifyIME(notification);
}
return NS_OK;
}
@ -233,8 +248,8 @@ private:
};
nsresult
IMEContentObserver::NotifySelectionChanged(nsIDOMDocument* aDoc,
nsISelection* aSel,
IMEContentObserver::NotifySelectionChanged(nsIDOMDocument* aDOMDocument,
nsISelection* aSelection,
int16_t aReason)
{
bool causedByComposition = IsEditorHandlingEventForComposition();
@ -244,7 +259,7 @@ IMEContentObserver::NotifySelectionChanged(nsIDOMDocument* aDoc,
}
int32_t count = 0;
nsresult rv = aSel->GetRangeCount(&count);
nsresult rv = aSelection->GetRangeCount(&count);
NS_ENSURE_SUCCESS(rv, rv);
if (count > 0 && mWidget) {
nsContentUtils::AddScriptRunner(
@ -265,8 +280,8 @@ public:
NS_IMETHOD Run()
{
if (mDispatcher->mWidget) {
mDispatcher->mWidget->NotifyIME(
if (mDispatcher->GetWidget()) {
mDispatcher->GetWidget()->NotifyIME(
IMENotification(NOTIFY_IME_OF_POSITION_CHANGE));
}
return NS_OK;
@ -322,13 +337,13 @@ public:
NS_IMETHOD Run()
{
if (mDispatcher->mWidget) {
if (mDispatcher->GetWidget()) {
IMENotification notification(NOTIFY_IME_OF_TEXT_CHANGE);
notification.mTextChangeData.mStartOffset = mStart;
notification.mTextChangeData.mOldEndOffset = mOldEnd;
notification.mTextChangeData.mNewEndOffset = mNewEnd;
notification.mTextChangeData.mCausedByComposition = mCausedByComposition;
mDispatcher->mWidget->NotifyIME(notification);
mDispatcher->GetWidget()->NotifyIME(notification);
}
return NS_OK;
}
@ -355,9 +370,11 @@ IMEContentObserver::CharacterDataChanged(nsIDocument* aDocument,
uint32_t offset = 0;
// get offsets of change and fire notification
if (NS_FAILED(nsContentEventHandler::GetFlatTextOffsetOfRange(
mRootContent, aContent, aInfo->mChangeStart, &offset)))
return;
nsresult rv =
nsContentEventHandler::GetFlatTextOffsetOfRange(mRootContent, aContent,
aInfo->mChangeStart,
&offset);
NS_ENSURE_SUCCESS_VOID(rv);
uint32_t oldEnd = offset + aInfo->mChangeEnd - aInfo->mChangeStart;
uint32_t newEnd = offset + aInfo->mReplaceLength;
@ -377,23 +394,27 @@ IMEContentObserver::NotifyContentAdded(nsINode* aContainer,
return;
}
uint32_t offset = 0, newOffset = 0;
if (NS_FAILED(nsContentEventHandler::GetFlatTextOffsetOfRange(
mRootContent, aContainer, aStartIndex, &offset)))
return;
uint32_t offset = 0;
nsresult rv =
nsContentEventHandler::GetFlatTextOffsetOfRange(mRootContent, aContainer,
aStartIndex, &offset);
NS_ENSURE_SUCCESS_VOID(rv);
// get offset at the end of the last added node
if (NS_FAILED(nsContentEventHandler::GetFlatTextOffsetOfRange(
aContainer->GetChildAt(aStartIndex),
aContainer, aEndIndex, &newOffset)))
return;
nsIContent* childAtStart = aContainer->GetChildAt(aStartIndex);
uint32_t addingLength = 0;
rv =
nsContentEventHandler::GetFlatTextOffsetOfRange(childAtStart, aContainer,
aEndIndex, &addingLength);
NS_ENSURE_SUCCESS_VOID(rv);
// fire notification
if (newOffset) {
nsContentUtils::AddScriptRunner(
new TextChangeEvent(this, offset, offset, offset + newOffset,
causedByComposition));
if (!addingLength) {
return;
}
nsContentUtils::AddScriptRunner(
new TextChangeEvent(this, offset, offset, offset + addingLength,
causedByComposition));
}
void
@ -429,28 +450,33 @@ IMEContentObserver::ContentRemoved(nsIDocument* aDocument,
return;
}
uint32_t offset = 0, childOffset = 1;
if (NS_FAILED(nsContentEventHandler::GetFlatTextOffsetOfRange(
mRootContent, NODE_FROM(aContainer, aDocument),
aIndexInContainer, &offset)))
return;
uint32_t offset = 0;
nsresult rv =
nsContentEventHandler::GetFlatTextOffsetOfRange(mRootContent,
NODE_FROM(aContainer,
aDocument),
aIndexInContainer, &offset);
NS_ENSURE_SUCCESS_VOID(rv);
// get offset at the end of the deleted node
if (aChild->IsNodeOfType(nsINode::eTEXT))
childOffset = aChild->TextLength();
else if (0 < aChild->GetChildCount())
childOffset = aChild->GetChildCount();
int32_t nodeLength =
aChild->IsNodeOfType(nsINode::eTEXT) ?
static_cast<int32_t>(aChild->TextLength()) :
std::max(static_cast<int32_t>(aChild->GetChildCount()), 1);
MOZ_ASSERT(nodeLength >= 0, "The node length is out of range");
uint32_t textLength = 0;
rv =
nsContentEventHandler::GetFlatTextOffsetOfRange(aChild, aChild,
nodeLength, &textLength);
NS_ENSURE_SUCCESS_VOID(rv);
if (NS_FAILED(nsContentEventHandler::GetFlatTextOffsetOfRange(
aChild, aChild, childOffset, &childOffset)))
if (!textLength) {
return;
// fire notification
if (childOffset) {
nsContentUtils::AddScriptRunner(
new TextChangeEvent(this, offset, offset + childOffset, offset,
causedByComposition));
}
nsContentUtils::AddScriptRunner(
new TextChangeEvent(this, offset, offset + textLength, offset,
causedByComposition));
}
static nsIContent*
@ -492,17 +518,21 @@ IMEContentObserver::AttributeChanged(nsIDocument* aDocument,
if (!content) {
return;
}
uint32_t postAttrChangeLength =
nsContentEventHandler::GetNativeTextLength(content);
if (postAttrChangeLength != mPreAttrChangeLength) {
if (postAttrChangeLength == mPreAttrChangeLength) {
return;
}
uint32_t start;
if (NS_SUCCEEDED(nsContentEventHandler::GetFlatTextOffsetOfRange(
mRootContent, content, 0, &start))) {
nsContentUtils::AddScriptRunner(new TextChangeEvent(this, start,
start + mPreAttrChangeLength, start + postAttrChangeLength,
causedByComposition));
}
}
nsresult rv =
nsContentEventHandler::GetFlatTextOffsetOfRange(mRootContent, content,
0, &start);
NS_ENSURE_SUCCESS_VOID(rv);
nsContentUtils::AddScriptRunner(
new TextChangeEvent(this, start, start + mPreAttrChangeLength,
start + postAttrChangeLength, causedByComposition));
}
} // namespace mozilla

View File

@ -48,26 +48,27 @@ public:
// nsIScrollObserver
virtual void ScrollPositionChanged() MOZ_OVERRIDE;
void Init(nsIWidget* aWidget,
nsPresContext* aPresContext,
void Init(nsIWidget* aWidget, nsPresContext* aPresContext,
nsIContent* aContent);
void Destroy(void);
void Destroy();
bool IsManaging(nsPresContext* aPresContext, nsIContent* aContent);
bool IsEditorHandlingEventForComposition() const;
bool KeepAliveDuringDeactive() const
{
return mUpdatePreference.WantDuringDeactive();
}
nsCOMPtr<nsIWidget> mWidget;
nsCOMPtr<nsISelection> mSel;
nsCOMPtr<nsIContent> mRootContent;
nsCOMPtr<nsINode> mEditableNode;
nsIWidget* GetWidget() const { return mWidget; }
nsresult GetSelectionAndRoot(nsISelection** aSelection,
nsIContent** aRoot) const;
private:
void NotifyContentAdded(nsINode* aContainer, int32_t aStart, int32_t aEnd);
void ObserveEditableNode();
nsCOMPtr<nsIWidget> mWidget;
nsCOMPtr<nsISelection> mSelection;
nsCOMPtr<nsIContent> mRootContent;
nsCOMPtr<nsINode> mEditableNode;
nsCOMPtr<nsIDocShell> mDocShell;
nsIMEUpdatePreference mUpdatePreference;
uint32_t mPreAttrChangeLength;

View File

@ -731,17 +731,11 @@ nsresult
nsIMEStateManager::GetFocusSelectionAndRoot(nsISelection** aSelection,
nsIContent** aRootContent)
{
if (!sActiveIMEContentObserver || !sActiveIMEContentObserver->mEditableNode ||
!sActiveIMEContentObserver->mSel) {
if (!sActiveIMEContentObserver) {
return NS_ERROR_NOT_AVAILABLE;
}
NS_ASSERTION(sActiveIMEContentObserver->mSel &&
sActiveIMEContentObserver->mRootContent,
"uninitialized content observer");
NS_ADDREF(*aSelection = sActiveIMEContentObserver->mSel);
NS_ADDREF(*aRootContent = sActiveIMEContentObserver->mRootContent);
return NS_OK;
return sActiveIMEContentObserver->GetSelectionAndRoot(aSelection,
aRootContent);
}
// static