Bug 962005 Make mozilla::TextComposition ref-countable class r=smaug

This commit is contained in:
Masayuki Nakano 2014-01-28 17:19:29 +09:00
parent d46a808c6c
commit 95852769e5
5 changed files with 43 additions and 57 deletions

View File

@ -31,17 +31,6 @@ TextComposition::TextComposition(nsPresContext* aPresContext,
{
}
TextComposition::TextComposition(const TextComposition& aOther)
{
mNativeContext = aOther.mNativeContext;
mPresContext = aOther.mPresContext;
mNode = aOther.mNode;
mLastData = aOther.mLastData;
mCompositionStartOffset = aOther.mCompositionStartOffset;
mCompositionTargetOffset = aOther.mCompositionTargetOffset;
mIsSynthesizedForTests = aOther.mIsSynthesizedForTests;
}
bool
TextComposition::MatchesNativeContext(nsIWidget* aWidget) const
{
@ -118,15 +107,13 @@ TextComposition::DispatchCompsotionEventRunnable(uint32_t aEventMessage,
void
TextComposition::SynthesizeCommit(bool aDiscard)
{
// backup this instance and use it since this instance might be destroyed
// by nsIMEStateManager if this is managed by it.
TextComposition composition = *this;
nsAutoString data(aDiscard ? EmptyString() : composition.mLastData);
if (composition.mLastData != data) {
composition.DispatchCompsotionEventRunnable(NS_COMPOSITION_UPDATE, data);
composition.DispatchCompsotionEventRunnable(NS_TEXT_TEXT, data);
nsRefPtr<TextComposition> kungFuDeathGrip(this);
nsAutoString data(aDiscard ? EmptyString() : mLastData);
if (mLastData != data) {
DispatchCompsotionEventRunnable(NS_COMPOSITION_UPDATE, data);
DispatchCompsotionEventRunnable(NS_TEXT_TEXT, data);
}
composition.DispatchCompsotionEventRunnable(NS_COMPOSITION_END, data);
DispatchCompsotionEventRunnable(NS_COMPOSITION_END, data);
}
nsresult
@ -202,7 +189,7 @@ TextCompositionArray::index_type
TextCompositionArray::IndexOf(nsIWidget* aWidget)
{
for (index_type i = Length(); i > 0; --i) {
if (ElementAt(i - 1).MatchesNativeContext(aWidget)) {
if (ElementAt(i - 1)->MatchesNativeContext(aWidget)) {
return i - 1;
}
}
@ -213,7 +200,7 @@ TextCompositionArray::index_type
TextCompositionArray::IndexOf(nsPresContext* aPresContext)
{
for (index_type i = Length(); i > 0; --i) {
if (ElementAt(i - 1).GetPresContext() == aPresContext) {
if (ElementAt(i - 1)->GetPresContext() == aPresContext) {
return i - 1;
}
}
@ -228,7 +215,7 @@ TextCompositionArray::IndexOf(nsPresContext* aPresContext,
if (index == NoIndex) {
return NoIndex;
}
nsINode* node = ElementAt(index).GetEventTargetNode();
nsINode* node = ElementAt(index)->GetEventTargetNode();
return node == aNode ? index : NoIndex;
}
@ -236,7 +223,7 @@ TextComposition*
TextCompositionArray::GetCompositionFor(nsIWidget* aWidget)
{
index_type i = IndexOf(aWidget);
return i != NoIndex ? &ElementAt(i) : nullptr;
return i != NoIndex ? ElementAt(i) : nullptr;
}
TextComposition*
@ -244,7 +231,7 @@ TextCompositionArray::GetCompositionFor(nsPresContext* aPresContext,
nsINode* aNode)
{
index_type i = IndexOf(aPresContext, aNode);
return i != NoIndex ? &ElementAt(i) : nullptr;
return i != NoIndex ? ElementAt(i) : nullptr;
}
TextComposition*
@ -253,9 +240,9 @@ TextCompositionArray::GetCompositionInContent(nsPresContext* aPresContext,
{
// There should be only one composition per content object.
for (index_type i = Length(); i > 0; --i) {
nsINode* node = ElementAt(i - 1).GetEventTargetNode();
nsINode* node = ElementAt(i - 1)->GetEventTargetNode();
if (node && nsContentUtils::ContentIsDescendantOf(node, aContent)) {
return &ElementAt(i - 1);
return ElementAt(i - 1);
}
}
return nullptr;

View File

@ -31,13 +31,14 @@ namespace mozilla {
class TextComposition MOZ_FINAL
{
friend class ::nsIMEStateManager;
NS_INLINE_DECL_REFCOUNTING(TextComposition)
public:
TextComposition(nsPresContext* aPresContext,
nsINode* aNode,
WidgetGUIEvent* aEvent);
TextComposition(const TextComposition& aOther);
~TextComposition()
{
// WARNING: mPresContext may be destroying, so, be careful if you touch it.
@ -97,8 +98,10 @@ private:
// See the comment for IsSynthesizedForTests().
bool mIsSynthesizedForTests;
// Hide the default constructor
// Hide the default constructor and copy constructor.
TextComposition() {}
TextComposition(const TextComposition& aOther);
/**
* DispatchEvent() dispatches the aEvent to the mContent synchronously.
@ -163,7 +166,8 @@ private:
* in the array can be destroyed by calling some methods of itself.
*/
class TextCompositionArray MOZ_FINAL : public nsAutoTArray<TextComposition, 2>
class TextCompositionArray MOZ_FINAL :
public nsAutoTArray<nsRefPtr<TextComposition>, 2>
{
public:
index_type IndexOf(nsIWidget* aWidget);

View File

@ -148,12 +148,10 @@ nsIMEStateManager::OnRemoveContent(nsPresContext* aPresContext,
// First, if there is a composition in the aContent, clean up it.
if (sTextCompositions) {
TextComposition* compositionInContent =
nsRefPtr<TextComposition> compositionInContent =
sTextCompositions->GetCompositionInContent(aPresContext, aContent);
if (compositionInContent) {
// Store the composition before accessing the native IME.
TextComposition storedComposition = *compositionInContent;
// Try resetting the native IME state. Be aware, typically, this method
// is called during the content being removed. Then, the native
// composition events which are caused by following APIs are ignored due
@ -161,15 +159,15 @@ nsIMEStateManager::OnRemoveContent(nsPresContext* aPresContext,
nsCOMPtr<nsIWidget> widget = aPresContext->GetRootWidget();
if (widget) {
nsresult rv =
storedComposition.NotifyIME(REQUEST_TO_CANCEL_COMPOSITION);
compositionInContent->NotifyIME(REQUEST_TO_CANCEL_COMPOSITION);
if (NS_FAILED(rv)) {
storedComposition.NotifyIME(REQUEST_TO_COMMIT_COMPOSITION);
compositionInContent->NotifyIME(REQUEST_TO_COMMIT_COMPOSITION);
}
// By calling the APIs, the composition may have been finished normally.
compositionInContent =
sTextCompositions->GetCompositionFor(
storedComposition.GetPresContext(),
storedComposition.GetEventTargetNode());
compositionInContent->GetPresContext(),
compositionInContent->GetEventTargetNode());
}
}
@ -558,12 +556,12 @@ nsIMEStateManager::DispatchCompositionEvent(nsINode* aEventTargetNode,
WidgetGUIEvent* GUIEvent = aEvent->AsGUIEvent();
TextComposition* composition =
nsRefPtr<TextComposition> composition =
sTextCompositions->GetCompositionFor(GUIEvent->widget);
if (!composition) {
MOZ_ASSERT(GUIEvent->message == NS_COMPOSITION_START);
TextComposition newComposition(aPresContext, aEventTargetNode, GUIEvent);
composition = sTextCompositions->AppendElement(newComposition);
composition = new TextComposition(aPresContext, aEventTargetNode, GUIEvent);
sTextCompositions->AppendElement(composition);
}
#ifdef DEBUG
else {
@ -593,7 +591,7 @@ nsIMEStateManager::NotifyIME(NotificationToIME aNotification,
{
NS_ENSURE_TRUE(aWidget, NS_ERROR_INVALID_ARG);
TextComposition* composition = nullptr;
nsRefPtr<TextComposition> composition;
if (sTextCompositions) {
composition = sTextCompositions->GetCompositionFor(aWidget);
}
@ -618,12 +616,10 @@ nsIMEStateManager::NotifyIME(NotificationToIME aNotification,
switch (aNotification) {
case REQUEST_TO_COMMIT_COMPOSITION: {
nsCOMPtr<nsIWidget> widget(aWidget);
TextComposition backup = *composition;
nsEventStatus status = nsEventStatus_eIgnore;
if (!backup.GetLastData().IsEmpty()) {
if (!composition->GetLastData().IsEmpty()) {
WidgetTextEvent textEvent(true, NS_TEXT_TEXT, widget);
textEvent.theText = backup.GetLastData();
textEvent.theText = composition->GetLastData();
textEvent.mFlags.mIsSynthesizedForTests = true;
widget->DispatchEvent(&textEvent, status);
if (widget->Destroyed()) {
@ -633,7 +629,7 @@ nsIMEStateManager::NotifyIME(NotificationToIME aNotification,
status = nsEventStatus_eIgnore;
WidgetCompositionEvent endEvent(true, NS_COMPOSITION_END, widget);
endEvent.data = backup.GetLastData();
endEvent.data = composition->GetLastData();
endEvent.mFlags.mIsSynthesizedForTests = true;
widget->DispatchEvent(&endEvent, status);
@ -641,12 +637,10 @@ nsIMEStateManager::NotifyIME(NotificationToIME aNotification,
}
case REQUEST_TO_CANCEL_COMPOSITION: {
nsCOMPtr<nsIWidget> widget(aWidget);
TextComposition backup = *composition;
nsEventStatus status = nsEventStatus_eIgnore;
if (!backup.GetLastData().IsEmpty()) {
if (!composition->GetLastData().IsEmpty()) {
WidgetCompositionEvent updateEvent(true, NS_COMPOSITION_UPDATE, widget);
updateEvent.data = backup.GetLastData();
updateEvent.data = composition->GetLastData();
updateEvent.mFlags.mIsSynthesizedForTests = true;
widget->DispatchEvent(&updateEvent, status);
if (widget->Destroyed()) {
@ -655,7 +649,7 @@ nsIMEStateManager::NotifyIME(NotificationToIME aNotification,
status = nsEventStatus_eIgnore;
WidgetTextEvent textEvent(true, NS_TEXT_TEXT, widget);
textEvent.theText = backup.GetLastData();
textEvent.theText = composition->GetLastData();
textEvent.mFlags.mIsSynthesizedForTests = true;
widget->DispatchEvent(&textEvent, status);
if (widget->Destroyed()) {
@ -665,7 +659,7 @@ nsIMEStateManager::NotifyIME(NotificationToIME aNotification,
status = nsEventStatus_eIgnore;
WidgetCompositionEvent endEvent(true, NS_COMPOSITION_END, widget);
endEvent.data = backup.GetLastData();
endEvent.data = composition->GetLastData();
endEvent.mFlags.mIsSynthesizedForTests = true;
widget->DispatchEvent(&endEvent, status);
@ -1133,7 +1127,8 @@ nsIMEStateManager::GetFocusSelectionAndRoot(nsISelection** aSel,
}
TextComposition*
nsIMEStateManager::GetTextComposition(nsIWidget* aWidget)
nsIMEStateManager::GetTextCompositionFor(nsIWidget* aWidget)
{
return sTextCompositions->GetCompositionFor(aWidget);
return sTextCompositions ?
sTextCompositions->GetCompositionFor(aWidget) : nullptr;
}

View File

@ -98,7 +98,7 @@ public:
/**
* Get TextComposition from widget.
*/
static mozilla::TextComposition* GetTextComposition(nsIWidget* aWidget);
static mozilla::TextComposition* GetTextCompositionFor(nsIWidget* aWidget);
/**
* Send a notification to IME. It depends on the IME or platform spec what

View File

@ -490,8 +490,8 @@ PuppetWidget::NotifyIMEOfUpdateComposition()
NS_ENSURE_TRUE(mTabChild, NS_ERROR_FAILURE);
mozilla::TextComposition* textComposition =
nsIMEStateManager::GetTextComposition(this);
nsRefPtr<TextComposition> textComposition =
nsIMEStateManager::GetTextCompositionFor(this);
NS_ENSURE_TRUE(textComposition, NS_ERROR_FAILURE);
nsEventStatus status;