зеркало из https://github.com/mozilla/gecko-dev.git
Bug 961704 part.2 Add an option to nsIMEUpdatePreference which prevents to be notified selection/text changes caused by composition r=smaug
This commit is contained in:
Родитель
a23b1b2838
Коммит
4fac2c03ae
|
@ -26,12 +26,15 @@ namespace mozilla {
|
|||
|
||||
TextComposition::TextComposition(nsPresContext* aPresContext,
|
||||
nsINode* aNode,
|
||||
WidgetGUIEvent* aEvent) :
|
||||
mPresContext(aPresContext), mNode(aNode),
|
||||
mNativeContext(aEvent->widget->GetInputContext().mNativeIMEContext),
|
||||
mCompositionStartOffset(0), mCompositionTargetOffset(0),
|
||||
mIsSynthesizedForTests(aEvent->mFlags.mIsSynthesizedForTests),
|
||||
mIsComposing(false)
|
||||
WidgetGUIEvent* aEvent)
|
||||
: mPresContext(aPresContext)
|
||||
, mNode(aNode)
|
||||
, mNativeContext(aEvent->widget->GetInputContext().mNativeIMEContext)
|
||||
, mCompositionStartOffset(0)
|
||||
, mCompositionTargetOffset(0)
|
||||
, mIsSynthesizedForTests(aEvent->mFlags.mIsSynthesizedForTests)
|
||||
, mIsComposing(false)
|
||||
, mIsEditorHandlingEvent(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -158,6 +161,7 @@ void
|
|||
TextComposition::EditorWillHandleTextEvent(const WidgetTextEvent* aTextEvent)
|
||||
{
|
||||
mIsComposing = aTextEvent->IsComposing();
|
||||
mIsEditorHandlingEvent = true;
|
||||
|
||||
MOZ_ASSERT(mLastData == aTextEvent->theText,
|
||||
"The text of a text event must be same as previous data attribute value "
|
||||
|
@ -168,6 +172,7 @@ void
|
|||
TextComposition::EditorDidHandleTextEvent()
|
||||
{
|
||||
mString = mLastData;
|
||||
mIsEditorHandlingEvent = false;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -93,6 +93,15 @@ public:
|
|||
*/
|
||||
bool IsComposing() const { return mIsComposing; }
|
||||
|
||||
/**
|
||||
* Returns true while editor is handling an event which is modifying the
|
||||
* composition string.
|
||||
*/
|
||||
bool IsEditorHandlingEvent() const
|
||||
{
|
||||
return mIsEditorHandlingEvent;
|
||||
}
|
||||
|
||||
/**
|
||||
* StartHandlingComposition() and EndHandlingComposition() are called by
|
||||
* editor when it holds a TextComposition instance and release it.
|
||||
|
@ -161,6 +170,10 @@ private:
|
|||
// See the comment for IsComposing().
|
||||
bool mIsComposing;
|
||||
|
||||
// mIsEditorHandlingEvent is true while editor is modifying the composition
|
||||
// string.
|
||||
bool mIsEditorHandlingEvent;
|
||||
|
||||
// Hide the default constructor and copy constructor.
|
||||
TextComposition() {}
|
||||
TextComposition(const TextComposition& aOther);
|
||||
|
|
|
@ -67,6 +67,7 @@ public:
|
|||
nsIContent* aContent);
|
||||
void Destroy(void);
|
||||
bool IsManaging(nsPresContext* aPresContext, nsIContent* aContent);
|
||||
bool IsEditorHandlingEventForComposition() const;
|
||||
bool KeepAliveDuringDeactive() const
|
||||
{
|
||||
return mUpdatePreference.WantDuringDeactive();
|
||||
|
@ -818,6 +819,20 @@ nsTextStateManager::IsManaging(nsPresContext* aPresContext,
|
|||
aContent);
|
||||
}
|
||||
|
||||
bool
|
||||
nsTextStateManager::IsEditorHandlingEventForComposition() const
|
||||
{
|
||||
if (!mWidget) {
|
||||
return false;
|
||||
}
|
||||
nsRefPtr<TextComposition> composition =
|
||||
nsIMEStateManager::GetTextCompositionFor(mWidget);
|
||||
if (!composition) {
|
||||
return false;
|
||||
}
|
||||
return composition->IsEditorHandlingEvent();
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS2(nsTextStateManager,
|
||||
nsIMutationObserver,
|
||||
nsISelectionListener)
|
||||
|
@ -825,22 +840,27 @@ NS_IMPL_ISUPPORTS2(nsTextStateManager,
|
|||
// Helper class, used for selection change notification
|
||||
class SelectionChangeEvent : public nsRunnable {
|
||||
public:
|
||||
SelectionChangeEvent(nsTextStateManager *aDispatcher)
|
||||
SelectionChangeEvent(nsTextStateManager *aDispatcher,
|
||||
bool aCausedByComposition)
|
||||
: mDispatcher(aDispatcher)
|
||||
, mCausedByComposition(aCausedByComposition)
|
||||
{
|
||||
MOZ_ASSERT(mDispatcher);
|
||||
}
|
||||
|
||||
NS_IMETHOD Run() {
|
||||
if (mDispatcher->mWidget) {
|
||||
mDispatcher->mWidget->NotifyIME(
|
||||
IMENotification(NOTIFY_IME_OF_SELECTION_CHANGE));
|
||||
IMENotification notification(NOTIFY_IME_OF_SELECTION_CHANGE);
|
||||
notification.mSelectionChangeData.mCausedByComposition =
|
||||
mCausedByComposition;
|
||||
mDispatcher->mWidget->NotifyIME(notification);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<nsTextStateManager> mDispatcher;
|
||||
bool mCausedByComposition;
|
||||
};
|
||||
|
||||
nsresult
|
||||
|
@ -848,11 +868,18 @@ nsTextStateManager::NotifySelectionChanged(nsIDOMDocument* aDoc,
|
|||
nsISelection* aSel,
|
||||
int16_t aReason)
|
||||
{
|
||||
bool causedByComposition = IsEditorHandlingEventForComposition();
|
||||
if (causedByComposition &&
|
||||
!mUpdatePreference.WantChangesCausedByComposition()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
int32_t count = 0;
|
||||
nsresult rv = aSel->GetRangeCount(&count);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (count > 0 && mWidget) {
|
||||
nsContentUtils::AddScriptRunner(new SelectionChangeEvent(this));
|
||||
nsContentUtils::AddScriptRunner(
|
||||
new SelectionChangeEvent(this, causedByComposition));
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -861,11 +888,13 @@ nsTextStateManager::NotifySelectionChanged(nsIDOMDocument* aDoc,
|
|||
class TextChangeEvent : public nsRunnable {
|
||||
public:
|
||||
TextChangeEvent(nsTextStateManager* aDispatcher,
|
||||
uint32_t start, uint32_t oldEnd, uint32_t newEnd)
|
||||
uint32_t aStart, uint32_t aOldEnd, uint32_t aNewEnd,
|
||||
bool aCausedByComposition)
|
||||
: mDispatcher(aDispatcher)
|
||||
, mStart(start)
|
||||
, mOldEnd(oldEnd)
|
||||
, mNewEnd(newEnd)
|
||||
, mStart(aStart)
|
||||
, mOldEnd(aOldEnd)
|
||||
, mNewEnd(aNewEnd)
|
||||
, mCausedByComposition(aCausedByComposition)
|
||||
{
|
||||
MOZ_ASSERT(mDispatcher);
|
||||
}
|
||||
|
@ -876,6 +905,7 @@ public:
|
|||
notification.mTextChangeData.mStartOffset = mStart;
|
||||
notification.mTextChangeData.mOldEndOffset = mOldEnd;
|
||||
notification.mTextChangeData.mNewEndOffset = mNewEnd;
|
||||
notification.mTextChangeData.mCausedByComposition = mCausedByComposition;
|
||||
mDispatcher->mWidget->NotifyIME(notification);
|
||||
}
|
||||
return NS_OK;
|
||||
|
@ -884,6 +914,7 @@ public:
|
|||
private:
|
||||
nsRefPtr<nsTextStateManager> mDispatcher;
|
||||
uint32_t mStart, mOldEnd, mNewEnd;
|
||||
bool mCausedByComposition;
|
||||
};
|
||||
|
||||
void
|
||||
|
@ -894,6 +925,12 @@ nsTextStateManager::CharacterDataChanged(nsIDocument* aDocument,
|
|||
NS_ASSERTION(aContent->IsNodeOfType(nsINode::eTEXT),
|
||||
"character data changed for non-text node");
|
||||
|
||||
bool causedByComposition = IsEditorHandlingEventForComposition();
|
||||
if (causedByComposition &&
|
||||
!mUpdatePreference.WantChangesCausedByComposition()) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t offset = 0;
|
||||
// get offsets of change and fire notification
|
||||
if (NS_FAILED(nsContentEventHandler::GetFlatTextOffsetOfRange(
|
||||
|
@ -904,7 +941,7 @@ nsTextStateManager::CharacterDataChanged(nsIDocument* aDocument,
|
|||
uint32_t newEnd = offset + aInfo->mReplaceLength;
|
||||
|
||||
nsContentUtils::AddScriptRunner(
|
||||
new TextChangeEvent(this, offset, oldEnd, newEnd));
|
||||
new TextChangeEvent(this, offset, oldEnd, newEnd, causedByComposition));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -912,6 +949,12 @@ nsTextStateManager::NotifyContentAdded(nsINode* aContainer,
|
|||
int32_t aStartIndex,
|
||||
int32_t aEndIndex)
|
||||
{
|
||||
bool causedByComposition = IsEditorHandlingEventForComposition();
|
||||
if (causedByComposition &&
|
||||
!mUpdatePreference.WantChangesCausedByComposition()) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t offset = 0, newOffset = 0;
|
||||
if (NS_FAILED(nsContentEventHandler::GetFlatTextOffsetOfRange(
|
||||
mRootContent, aContainer, aStartIndex, &offset)))
|
||||
|
@ -924,9 +967,11 @@ nsTextStateManager::NotifyContentAdded(nsINode* aContainer,
|
|||
return;
|
||||
|
||||
// fire notification
|
||||
if (newOffset)
|
||||
if (newOffset) {
|
||||
nsContentUtils::AddScriptRunner(
|
||||
new TextChangeEvent(this, offset, offset, offset + newOffset));
|
||||
new TextChangeEvent(this, offset, offset, offset + newOffset,
|
||||
causedByComposition));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -956,6 +1001,12 @@ nsTextStateManager::ContentRemoved(nsIDocument* aDocument,
|
|||
int32_t aIndexInContainer,
|
||||
nsIContent* aPreviousSibling)
|
||||
{
|
||||
bool causedByComposition = IsEditorHandlingEventForComposition();
|
||||
if (causedByComposition &&
|
||||
!mUpdatePreference.WantChangesCausedByComposition()) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t offset = 0, childOffset = 1;
|
||||
if (NS_FAILED(nsContentEventHandler::GetFlatTextOffsetOfRange(
|
||||
mRootContent, NODE_FROM(aContainer, aDocument),
|
||||
|
@ -973,9 +1024,11 @@ nsTextStateManager::ContentRemoved(nsIDocument* aDocument,
|
|||
return;
|
||||
|
||||
// fire notification
|
||||
if (childOffset)
|
||||
if (childOffset) {
|
||||
nsContentUtils::AddScriptRunner(
|
||||
new TextChangeEvent(this, offset, offset + childOffset, offset));
|
||||
new TextChangeEvent(this, offset, offset + childOffset, offset,
|
||||
causedByComposition));
|
||||
}
|
||||
}
|
||||
|
||||
static nsIContent*
|
||||
|
@ -1006,6 +1059,12 @@ nsTextStateManager::AttributeChanged(nsIDocument* aDocument,
|
|||
nsIAtom* aAttribute,
|
||||
int32_t aModType)
|
||||
{
|
||||
bool causedByComposition = IsEditorHandlingEventForComposition();
|
||||
if (causedByComposition &&
|
||||
!mUpdatePreference.WantChangesCausedByComposition()) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsIContent *content = GetContentBR(aElement);
|
||||
if (!content) {
|
||||
return;
|
||||
|
@ -1017,7 +1076,8 @@ nsTextStateManager::AttributeChanged(nsIDocument* aDocument,
|
|||
if (NS_SUCCEEDED(nsContentEventHandler::GetFlatTextOffsetOfRange(
|
||||
mRootContent, content, 0, &start))) {
|
||||
nsContentUtils::AddScriptRunner(new TextChangeEvent(this, start,
|
||||
start + mPreAttrChangeLength, start + postAttrChangeLength));
|
||||
start + mPreAttrChangeLength, start + postAttrChangeLength,
|
||||
causedByComposition));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -130,11 +130,13 @@ parent:
|
|||
* offset Starting offset of the change
|
||||
* end Ending offset of the range deleted
|
||||
* newEnd New ending offset after insertion
|
||||
* causedByComposition true if the change is caused by composition
|
||||
*
|
||||
* for insertion, offset == end
|
||||
* for deletion, offset == newEnd
|
||||
*/
|
||||
NotifyIMETextChange(uint32_t offset, uint32_t end, uint32_t newEnd);
|
||||
NotifyIMETextChange(uint32_t offset, uint32_t end, uint32_t newEnd,
|
||||
bool causedByComposition);
|
||||
|
||||
/**
|
||||
* Notifies chrome that there is a IME compostion rect updated
|
||||
|
@ -152,8 +154,10 @@ parent:
|
|||
* seqno Current seqno value on the content side
|
||||
* anchor Offset where the selection started
|
||||
* focus Offset where the caret is
|
||||
* causedByComposition true if the change is caused by composition
|
||||
*/
|
||||
NotifyIMESelection(uint32_t seqno, uint32_t anchor, uint32_t focus);
|
||||
NotifyIMESelection(uint32_t seqno, uint32_t anchor, uint32_t focus,
|
||||
bool causedByComposition);
|
||||
|
||||
/**
|
||||
* Notifies chrome to refresh its text cache
|
||||
|
|
|
@ -1051,7 +1051,7 @@ TabParent::RecvNotifyIMEFocus(const bool& aFocus,
|
|||
{
|
||||
nsCOMPtr<nsIWidget> widget = GetWidget();
|
||||
if (!widget) {
|
||||
aPreference->mWantUpdates = nsIMEUpdatePreference::NOTIFY_NOTHING;
|
||||
*aPreference = nsIMEUpdatePreference();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1073,19 +1073,27 @@ TabParent::RecvNotifyIMEFocus(const bool& aFocus,
|
|||
bool
|
||||
TabParent::RecvNotifyIMETextChange(const uint32_t& aStart,
|
||||
const uint32_t& aEnd,
|
||||
const uint32_t& aNewEnd)
|
||||
const uint32_t& aNewEnd,
|
||||
const bool& aCausedByComposition)
|
||||
{
|
||||
nsCOMPtr<nsIWidget> widget = GetWidget();
|
||||
if (!widget)
|
||||
return true;
|
||||
|
||||
NS_ASSERTION(widget->GetIMEUpdatePreference().WantTextChange(),
|
||||
#ifdef DEBUG
|
||||
nsIMEUpdatePreference updatePreference = widget->GetIMEUpdatePreference();
|
||||
NS_ASSERTION(updatePreference.WantTextChange(),
|
||||
"Don't call Send/RecvNotifyIMETextChange without NOTIFY_TEXT_CHANGE");
|
||||
MOZ_ASSERT(!aCausedByComposition ||
|
||||
updatePreference.WantChangesCausedByComposition(),
|
||||
"The widget doesn't want text change notification caused by composition");
|
||||
#endif
|
||||
|
||||
IMENotification notification(NOTIFY_IME_OF_TEXT_CHANGE);
|
||||
notification.mTextChangeData.mStartOffset = aStart;
|
||||
notification.mTextChangeData.mOldEndOffset = aEnd;
|
||||
notification.mTextChangeData.mNewEndOffset = aNewEnd;
|
||||
notification.mTextChangeData.mCausedByComposition = aCausedByComposition;
|
||||
widget->NotifyIME(notification);
|
||||
return true;
|
||||
}
|
||||
|
@ -1111,7 +1119,8 @@ TabParent::RecvNotifyIMESelectedCompositionRect(const uint32_t& aOffset,
|
|||
bool
|
||||
TabParent::RecvNotifyIMESelection(const uint32_t& aSeqno,
|
||||
const uint32_t& aAnchor,
|
||||
const uint32_t& aFocus)
|
||||
const uint32_t& aFocus,
|
||||
const bool& aCausedByComposition)
|
||||
{
|
||||
nsCOMPtr<nsIWidget> widget = GetWidget();
|
||||
if (!widget)
|
||||
|
@ -1120,8 +1129,15 @@ TabParent::RecvNotifyIMESelection(const uint32_t& aSeqno,
|
|||
if (aSeqno == mIMESeqno) {
|
||||
mIMESelectionAnchor = aAnchor;
|
||||
mIMESelectionFocus = aFocus;
|
||||
if (widget->GetIMEUpdatePreference().WantSelectionChange()) {
|
||||
widget->NotifyIME(IMENotification(NOTIFY_IME_OF_SELECTION_CHANGE));
|
||||
const nsIMEUpdatePreference updatePreference =
|
||||
widget->GetIMEUpdatePreference();
|
||||
if (updatePreference.WantSelectionChange() &&
|
||||
(updatePreference.WantChangesCausedByComposition() ||
|
||||
!aCausedByComposition)) {
|
||||
IMENotification notification(NOTIFY_IME_OF_SELECTION_CHANGE);
|
||||
notification.mSelectionChangeData.mCausedByComposition =
|
||||
aCausedByComposition;
|
||||
widget->NotifyIME(notification);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -149,13 +149,15 @@ public:
|
|||
uint32_t* aSeqno) MOZ_OVERRIDE;
|
||||
virtual bool RecvNotifyIMETextChange(const uint32_t& aStart,
|
||||
const uint32_t& aEnd,
|
||||
const uint32_t& aNewEnd) MOZ_OVERRIDE;
|
||||
const uint32_t& aNewEnd,
|
||||
const bool& aCausedByComposition) MOZ_OVERRIDE;
|
||||
virtual bool RecvNotifyIMESelectedCompositionRect(const uint32_t& aOffset,
|
||||
const nsIntRect& aRect,
|
||||
const nsIntRect& aCaretRect) MOZ_OVERRIDE;
|
||||
virtual bool RecvNotifyIMESelection(const uint32_t& aSeqno,
|
||||
const uint32_t& aAnchor,
|
||||
const uint32_t& aFocus) MOZ_OVERRIDE;
|
||||
const uint32_t& aFocus,
|
||||
const bool& aCausedByComposition) MOZ_OVERRIDE;
|
||||
virtual bool RecvNotifyIMETextHint(const nsString& aText) MOZ_OVERRIDE;
|
||||
virtual bool RecvEndIMEComposition(const bool& aCancel,
|
||||
nsString* aComposition) MOZ_OVERRIDE;
|
||||
|
|
|
@ -2379,9 +2379,9 @@ nsWindow::NotifyIMEOfTextChange(const IMENotification& aIMENotification)
|
|||
nsIMEUpdatePreference
|
||||
nsWindow::GetIMEUpdatePreference()
|
||||
{
|
||||
int8_t notifications = (nsIMEUpdatePreference::NOTIFY_SELECTION_CHANGE |
|
||||
nsIMEUpdatePreference::NOTIFY_TEXT_CHANGE);
|
||||
return nsIMEUpdatePreference(notifications);
|
||||
return nsIMEUpdatePreference(
|
||||
nsIMEUpdatePreference::NOTIFY_SELECTION_CHANGE |
|
||||
nsIMEUpdatePreference::NOTIFY_TEXT_CHANGE);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -221,23 +221,39 @@ struct nsIMEUpdatePreference {
|
|||
|
||||
typedef uint8_t Notifications;
|
||||
|
||||
enum
|
||||
enum MOZ_ENUM_TYPE(Notifications)
|
||||
{
|
||||
NOTIFY_NOTHING = 0x00,
|
||||
NOTIFY_SELECTION_CHANGE = 0x01,
|
||||
NOTIFY_TEXT_CHANGE = 0x02,
|
||||
NOTIFY_DURING_DEACTIVE = 0x80
|
||||
NOTIFY_NOTHING = 0,
|
||||
NOTIFY_SELECTION_CHANGE = 1 << 0,
|
||||
NOTIFY_TEXT_CHANGE = 1 << 1,
|
||||
// Following values indicate when widget needs or doesn't need notification.
|
||||
NOTIFY_CHANGES_CAUSED_BY_COMPOSITION = 1 << 6,
|
||||
// NOTE: NOTIFY_DURING_DEACTIVE isn't supported in environments where two
|
||||
// or more compositions are possible. E.g., Mac and Linux (GTK).
|
||||
NOTIFY_DURING_DEACTIVE = 1 << 7,
|
||||
// Changes are notified in following conditions if the instance is
|
||||
// just constructed. If some platforms don't need change notifications
|
||||
// in some of following conditions, the platform should remove following
|
||||
// flags before returing the instance from nsIWidget::GetUpdatePreference().
|
||||
DEFAULT_CONDITIONS_OF_NOTIFYING_CHANGES =
|
||||
NOTIFY_CHANGES_CAUSED_BY_COMPOSITION
|
||||
};
|
||||
|
||||
nsIMEUpdatePreference()
|
||||
: mWantUpdates(NOTIFY_NOTHING)
|
||||
: mWantUpdates(DEFAULT_CONDITIONS_OF_NOTIFYING_CHANGES)
|
||||
{
|
||||
}
|
||||
|
||||
nsIMEUpdatePreference(Notifications aWantUpdates)
|
||||
: mWantUpdates(aWantUpdates)
|
||||
: mWantUpdates(aWantUpdates | DEFAULT_CONDITIONS_OF_NOTIFYING_CHANGES)
|
||||
{
|
||||
}
|
||||
|
||||
void DontNotifyChangesCausedByComposition()
|
||||
{
|
||||
mWantUpdates &= ~DEFAULT_CONDITIONS_OF_NOTIFYING_CHANGES;
|
||||
}
|
||||
|
||||
bool WantSelectionChange() const
|
||||
{
|
||||
return !!(mWantUpdates & NOTIFY_SELECTION_CHANGE);
|
||||
|
@ -248,6 +264,17 @@ struct nsIMEUpdatePreference {
|
|||
return !!(mWantUpdates & NOTIFY_TEXT_CHANGE);
|
||||
}
|
||||
|
||||
bool WantChanges() const
|
||||
{
|
||||
return WantSelectionChange() || WantTextChange();
|
||||
}
|
||||
|
||||
bool WantChangesCausedByComposition() const
|
||||
{
|
||||
return WantChanges() &&
|
||||
!!(mWantUpdates & NOTIFY_CHANGES_CAUSED_BY_COMPOSITION);
|
||||
}
|
||||
|
||||
bool WantDuringDeactive() const
|
||||
{
|
||||
return !!(mWantUpdates & NOTIFY_DURING_DEACTIVE);
|
||||
|
@ -479,10 +506,14 @@ struct IMENotification
|
|||
: mMessage(aMessage)
|
||||
{
|
||||
switch (aMessage) {
|
||||
case NOTIFY_IME_OF_SELECTION_CHANGE:
|
||||
mSelectionChangeData.mCausedByComposition = false;
|
||||
break;
|
||||
case NOTIFY_IME_OF_TEXT_CHANGE:
|
||||
mTextChangeData.mStartOffset = 0;
|
||||
mTextChangeData.mOldEndOffset = 0;
|
||||
mTextChangeData.mNewEndOffset = 0;
|
||||
mTextChangeData.mCausedByComposition = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -493,6 +524,12 @@ struct IMENotification
|
|||
|
||||
union
|
||||
{
|
||||
// NOTIFY_IME_OF_SELECTION_CHANGE specific data
|
||||
struct
|
||||
{
|
||||
bool mCausedByComposition;
|
||||
} mSelectionChangeData;
|
||||
|
||||
// NOTIFY_IME_OF_TEXT_CHANGE specific data
|
||||
struct
|
||||
{
|
||||
|
@ -500,6 +537,8 @@ struct IMENotification
|
|||
uint32_t mOldEndOffset;
|
||||
uint32_t mNewEndOffset;
|
||||
|
||||
bool mCausedByComposition;
|
||||
|
||||
uint32_t OldLength() const { return mOldEndOffset - mStartOffset; }
|
||||
uint32_t NewLength() const { return mNewEndOffset - mStartOffset; }
|
||||
int32_t AdditionalLength() const
|
||||
|
@ -515,6 +554,18 @@ struct IMENotification
|
|||
} mTextChangeData;
|
||||
};
|
||||
|
||||
bool IsCausedByComposition() const
|
||||
{
|
||||
switch (mMessage) {
|
||||
case NOTIFY_IME_OF_SELECTION_CHANGE:
|
||||
return mSelectionChangeData.mCausedByComposition;
|
||||
case NOTIFY_IME_OF_TEXT_CHANGE:
|
||||
return mTextChangeData.mCausedByComposition;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
IMENotification();
|
||||
};
|
||||
|
|
|
@ -3171,18 +3171,21 @@ nsTextStore::OnFocusChange(bool aGotFocus,
|
|||
nsIMEUpdatePreference
|
||||
nsTextStore::GetIMEUpdatePreference()
|
||||
{
|
||||
nsIMEUpdatePreference::Notifications notifications =
|
||||
nsIMEUpdatePreference::NOTIFY_NOTHING;
|
||||
if (sTsfThreadMgr && sTsfTextStore && sTsfTextStore->mDocumentMgr) {
|
||||
nsRefPtr<ITfDocumentMgr> docMgr;
|
||||
sTsfThreadMgr->GetFocus(getter_AddRefs(docMgr));
|
||||
if (docMgr == sTsfTextStore->mDocumentMgr) {
|
||||
notifications = (nsIMEUpdatePreference::NOTIFY_SELECTION_CHANGE |
|
||||
nsIMEUpdatePreference::NOTIFY_TEXT_CHANGE |
|
||||
nsIMEUpdatePreference::NOTIFY_DURING_DEACTIVE);
|
||||
nsIMEUpdatePreference updatePreference(
|
||||
nsIMEUpdatePreference::NOTIFY_SELECTION_CHANGE |
|
||||
nsIMEUpdatePreference::NOTIFY_TEXT_CHANGE |
|
||||
nsIMEUpdatePreference::NOTIFY_DURING_DEACTIVE);
|
||||
// nsTextStore shouldn't notify TSF of selection change and text change
|
||||
// which are caused by composition.
|
||||
updatePreference.DontNotifyChangesCausedByComposition();
|
||||
return updatePreference;
|
||||
}
|
||||
}
|
||||
return nsIMEUpdatePreference(notifications);
|
||||
return nsIMEUpdatePreference();
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
|
|
@ -390,7 +390,7 @@ PuppetWidget::NotifyIME(const IMENotification& aIMENotification)
|
|||
case NOTIFY_IME_OF_BLUR:
|
||||
return NotifyIMEOfFocusChange(false);
|
||||
case NOTIFY_IME_OF_SELECTION_CHANGE:
|
||||
return NotifyIMEOfSelectionChange();
|
||||
return NotifyIMEOfSelectionChange(aIMENotification);
|
||||
case NOTIFY_IME_OF_TEXT_CHANGE:
|
||||
return NotifyIMEOfTextChange(aIMENotification);
|
||||
case NOTIFY_IME_OF_COMPOSITION_UPDATE:
|
||||
|
@ -467,14 +467,16 @@ PuppetWidget::NotifyIMEOfFocusChange(bool aFocus)
|
|||
}
|
||||
|
||||
uint32_t chromeSeqno;
|
||||
mIMEPreferenceOfParent.mWantUpdates = nsIMEUpdatePreference::NOTIFY_NOTHING;
|
||||
mIMEPreferenceOfParent = nsIMEUpdatePreference();
|
||||
if (!mTabChild->SendNotifyIMEFocus(aFocus, &mIMEPreferenceOfParent,
|
||||
&chromeSeqno)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (aFocus) {
|
||||
NotifyIMEOfSelectionChange(); // Update selection
|
||||
IMENotification notification(NOTIFY_IME_OF_SELECTION_CHANGE);
|
||||
notification.mSelectionChangeData.mCausedByComposition = false;
|
||||
NotifyIMEOfSelectionChange(notification); // Update selection
|
||||
} else {
|
||||
mIMELastBlurSeqno = chromeSeqno;
|
||||
}
|
||||
|
@ -531,6 +533,9 @@ PuppetWidget::GetIMEUpdatePreference()
|
|||
nsresult
|
||||
PuppetWidget::NotifyIMEOfTextChange(const IMENotification& aIMENotification)
|
||||
{
|
||||
MOZ_ASSERT(aIMENotification.mMessage == NOTIFY_IME_OF_TEXT_CHANGE,
|
||||
"Passed wrong notification");
|
||||
|
||||
#ifndef MOZ_CROSS_PROCESS_IME
|
||||
return NS_OK;
|
||||
#endif
|
||||
|
@ -550,18 +555,25 @@ PuppetWidget::NotifyIMEOfTextChange(const IMENotification& aIMENotification)
|
|||
|
||||
// TabParent doesn't this this to cache. we don't send the notification
|
||||
// if parent process doesn't request NOTIFY_TEXT_CHANGE.
|
||||
if (mIMEPreferenceOfParent.WantTextChange()) {
|
||||
if (mIMEPreferenceOfParent.WantTextChange() &&
|
||||
(mIMEPreferenceOfParent.WantChangesCausedByComposition() ||
|
||||
!aIMENotification.mTextChangeData.mCausedByComposition)) {
|
||||
mTabChild->SendNotifyIMETextChange(
|
||||
aIMENotification.mTextChangeData.mStartOffset,
|
||||
aIMENotification.mTextChangeData.mOldEndOffset,
|
||||
aIMENotification.mTextChangeData.mNewEndOffset);
|
||||
aIMENotification.mTextChangeData.mNewEndOffset,
|
||||
aIMENotification.mTextChangeData.mCausedByComposition);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
PuppetWidget::NotifyIMEOfSelectionChange()
|
||||
PuppetWidget::NotifyIMEOfSelectionChange(
|
||||
const IMENotification& aIMENotification)
|
||||
{
|
||||
MOZ_ASSERT(aIMENotification.mMessage == NOTIFY_IME_OF_SELECTION_CHANGE,
|
||||
"Passed wrong notification");
|
||||
|
||||
#ifndef MOZ_CROSS_PROCESS_IME
|
||||
return NS_OK;
|
||||
#endif
|
||||
|
@ -575,9 +587,11 @@ PuppetWidget::NotifyIMEOfSelectionChange()
|
|||
DispatchEvent(&queryEvent, status);
|
||||
|
||||
if (queryEvent.mSucceeded) {
|
||||
mTabChild->SendNotifyIMESelection(mIMELastReceivedSeqno,
|
||||
queryEvent.GetSelectionStart(),
|
||||
queryEvent.GetSelectionEnd());
|
||||
mTabChild->SendNotifyIMESelection(
|
||||
mIMELastReceivedSeqno,
|
||||
queryEvent.GetSelectionStart(),
|
||||
queryEvent.GetSelectionEnd(),
|
||||
aIMENotification.mSelectionChangeData.mCausedByComposition);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -180,7 +180,7 @@ private:
|
|||
|
||||
nsresult IMEEndComposition(bool aCancel);
|
||||
nsresult NotifyIMEOfFocusChange(bool aFocus);
|
||||
nsresult NotifyIMEOfSelectionChange();
|
||||
nsresult NotifyIMEOfSelectionChange(const IMENotification& aIMENotification);
|
||||
nsresult NotifyIMEOfUpdateComposition();
|
||||
nsresult NotifyIMEOfTextChange(const IMENotification& aIMENotification);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче