Bug 960866 part.6 mozilla::TextComposition should holds a weak reference to composition handling editor during composition r=ehsan+smaug

This commit is contained in:
Masayuki Nakano 2014-02-12 22:02:56 +09:00
parent 49f0d8e935
commit 3407551379
3 changed files with 73 additions and 2 deletions

View File

@ -9,6 +9,7 @@
#include "nsContentUtils.h"
#include "nsEventDispatcher.h"
#include "nsIContent.h"
#include "nsIEditor.h"
#include "nsIMEStateManager.h"
#include "nsIPresShell.h"
#include "nsPresContext.h"
@ -50,7 +51,19 @@ TextComposition::DispatchEvent(WidgetGUIEvent* aEvent,
nsEventDispatcher::Dispatch(mNode, mPresContext,
aEvent, nullptr, aStatus, aCallBack);
MOZ_ASSERT_IF(aEvent->message == NS_COMPOSITION_END, !mIsComposing);
// Emulate editor behavior of text event handler if no editor handles
// composition/text events.
if (aEvent->message == NS_TEXT_TEXT && !HasEditor()) {
EditorWillHandleTextEvent(aEvent->AsTextEvent());
EditorDidHandleTextEvent();
}
#ifdef DEBUG
else if (aEvent->message == NS_COMPOSITION_END) {
MOZ_ASSERT(!mIsComposing, "Why is the editor still composing?");
MOZ_ASSERT(!HasEditor(), "Why does the editor still keep to hold this?");
}
#endif // #ifdef DEBUG
// Notify composition update to widget if possible
NotityUpdateComposition(aEvent);
@ -142,6 +155,37 @@ TextComposition::EditorDidHandleTextEvent()
mString = mLastData;
}
void
TextComposition::StartHandlingComposition(nsIEditor* aEditor)
{
MOZ_ASSERT(!HasEditor(), "There is a handling editor already");
mEditorWeak = do_GetWeakReference(aEditor);
}
void
TextComposition::EndHandlingComposition(nsIEditor* aEditor)
{
#ifdef DEBUG
nsCOMPtr<nsIEditor> editor = GetEditor();
MOZ_ASSERT(editor == aEditor, "Another editor handled the composition?");
#endif // #ifdef DEBUG
mEditorWeak = nullptr;
}
already_AddRefed<nsIEditor>
TextComposition::GetEditor() const
{
nsCOMPtr<nsIEditor> editor = do_QueryReferent(mEditorWeak);
return editor.forget();
}
bool
TextComposition::HasEditor() const
{
nsCOMPtr<nsIEditor> editor = GetEditor();
return !!editor;
}
/******************************************************************************
* TextComposition::CompositionEventDispatcher
******************************************************************************/

View File

@ -9,6 +9,7 @@
#include "nsCOMPtr.h"
#include "nsINode.h"
#include "nsIWeakReference.h"
#include "nsIWidget.h"
#include "nsTArray.h"
#include "nsThreadUtils.h"
@ -17,8 +18,8 @@
#include "mozilla/EventForwards.h"
class nsDispatchingCallback;
class nsIEditor;
class nsIMEStateManager;
class nsIWidget;
namespace mozilla {
@ -98,6 +99,13 @@ public:
*/
void EditorDidHandleTextEvent();
/**
* StartHandlingComposition() and EndHandlingComposition() are called by
* editor when it holds a TextComposition instance and release it.
*/
void StartHandlingComposition(nsIEditor* aEditor);
void EndHandlingComposition(nsIEditor* aEditor);
private:
// This class holds nsPresContext weak. This instance shouldn't block
// destroying it. When the presContext is being destroyed, it's notified to
@ -110,6 +118,9 @@ private:
// composition. Don't access the instance, it may not be available.
void* mNativeContext;
// mEditorWeak is a weak reference to the focused editor handling composition.
nsWeakPtr mEditorWeak;
// mLastData stores the data attribute of the latest composition event (except
// the compositionstart event).
nsString mLastData;
@ -134,6 +145,16 @@ private:
TextComposition() {}
TextComposition(const TextComposition& aOther);
/**
* GetEditor() returns nsIEditor pointer of mEditorWeak.
*/
already_AddRefed<nsIEditor> GetEditor() const;
/**
* HasEditor() returns true if mEditorWeak holds nsIEditor instance which is
* alive. Otherwise, false.
*/
bool HasEditor() const;
/**
* DispatchEvent() dispatches the aEvent to the mContent synchronously.

View File

@ -357,6 +357,10 @@ nsEditor::RemoveEventListeners()
return;
}
reinterpret_cast<nsEditorEventListener*>(mEventListener.get())->Disconnect();
if (mComposition) {
mComposition->EndHandlingComposition(this);
mComposition = nullptr;
}
mEventTarget = nullptr;
}
@ -2020,6 +2024,7 @@ nsEditor::EnsureComposition(mozilla::WidgetGUIEvent* aEvent)
if (!mComposition) {
MOZ_CRASH("nsIMEStateManager doesn't return proper composition");
}
mComposition->StartHandlingComposition(this);
}
nsresult
@ -2053,6 +2058,7 @@ nsEditor::EndIMEComposition()
/* reset the data we need to construct a transaction */
mIMETextNode = nullptr;
mIMETextOffset = 0;
mComposition->EndHandlingComposition(this);
mComposition = nullptr;
// notify editor observers of action