Bug 1275918 part.2 Update TextComposition::mCompositionStartOffset when it's modified in the remote process r?m_kato
MozReview-Commit-ID: H1SJTWWav6G
--- a/dom/events/IMEStateManager.cpp
+++ b/dom/events/IMEStateManager.cpp
@@ -217,16 +217,49 @@ IMEStateManager::StopIMEStateManagement(
sActiveInputContextWidget = nullptr;
sPresContext = nullptr;
sContent = nullptr;
sActiveTabParent = nullptr;
DestroyIMEContentObserver();
}
// static
+void
+IMEStateManager::MaybeStartOffsetUpdatedInChild(nsIWidget* aWidget,
+ uint32_t aStartOffset)
+{
+ if (NS_WARN_IF(!sTextCompositions)) {
+ MOZ_LOG(sISMLog, LogLevel::Warning,
+ ("ISM: IMEStateManager::MaybeStartOffsetUpdatedInChild("
+ "aWidget=0x%p, aStartOffset=%u), called when there is no "
+ "composition", aWidget, aStartOffset));
+ return;
+ }
+
+ RefPtr<TextComposition> composition = GetTextCompositionFor(aWidget);
+ if (NS_WARN_IF(!composition)) {
+ MOZ_LOG(sISMLog, LogLevel::Warning,
+ ("ISM: IMEStateManager::MaybeStartOffsetUpdatedInChild("
+ "aWidget=0x%p, aStartOffset=%u), called when there is no "
+ "composition", aWidget, aStartOffset));
+ return;
+ }
+
+ if (composition->NativeOffsetOfStartComposition() == aStartOffset) {
+ return;
+ }
+
+ MOZ_LOG(sISMLog, LogLevel::Info,
+ ("ISM: IMEStateManager::MaybeStartOffsetUpdatedInChild("
+ "aWidget=0x%p, aStartOffset=%u), old offset=%u",
+ aWidget, aStartOffset, composition->NativeOffsetOfStartComposition()));
+ composition->OnStartOffsetUpdatedInChild(aStartOffset);
+}
+
+// static
nsresult
IMEStateManager::OnDestroyPresContext(nsPresContext* aPresContext)
{
NS_ENSURE_ARG_POINTER(aPresContext);
// First, if there is a composition in the aPresContext, clean up it.
if (sTextCompositions) {
TextCompositionArray::index_type i =
--- a/dom/events/IMEStateManager.h
+++ b/dom/events/IMEStateManager.h
@@ -92,16 +92,28 @@ public:
const InputContextAction& aAction);
/**
* StopIMEStateManagement() is called when the process should stop managing
* IME state.
*/
static void StopIMEStateManagement();
+ /**
+ * MaybeStartOffsetUpdatedInChild() is called when composition start offset
+ * is maybe updated in the child process. I.e., even if it's not updated,
+ * this is called and never called if the composition is in this process.
+ * @param aWidget The widget whose native IME context has the
+ * composition.
+ * @param aStartOffset New composition start offset with native
+ * linebreaks.
+ */
+ static void MaybeStartOffsetUpdatedInChild(nsIWidget* aWidget,
+ uint32_t aStartOffset);
+
static nsresult OnDestroyPresContext(nsPresContext* aPresContext);
static nsresult OnRemoveContent(nsPresContext* aPresContext,
nsIContent* aContent);
/**
* OnChangeFocus() should be called when focused content is changed or
* IME enabled state is changed. If nobody has focus, set both aPresContext
* and aContent nullptr. E.g., all windows are deactivated.
*/
--- a/dom/events/TextComposition.cpp
+++ b/dom/events/TextComposition.cpp
@@ -505,16 +505,22 @@ TextComposition::OnCompositionEventDispa
}
if (aCompositionEvent->CausesDOMTextEvent()) {
mTargetClauseOffsetInComposition = aCompositionEvent->TargetClauseOffset();
}
}
void
+TextComposition::OnStartOffsetUpdatedInChild(uint32_t aStartOffset)
+{
+ mCompositionStartOffset = aStartOffset;
+}
+
+void
TextComposition::MaybeNotifyIMEOfCompositionEventHandled(
const WidgetCompositionEvent* aCompositionEvent)
{
if (aCompositionEvent->mMessage != eCompositionStart &&
!aCompositionEvent->CausesDOMTextEvent()) {
return;
}
--- a/dom/events/TextComposition.h
+++ b/dom/events/TextComposition.h
@@ -397,16 +397,25 @@ private:
/**
* GetSelectionStartOffset() returns normal selection start offset in the
* editor which has this composition.
* If it failed or lost focus, this would return 0.
*/
uint32_t GetSelectionStartOffset();
/**
+ * OnStartOffsetUpdatedInChild() is called when composition start offset
+ * is updated in the child process. I.e., this is called and never called
+ * if the composition is in this process.
+ * @param aStartOffset New composition start offset with native
+ * linebreaks.
+ */
+ void OnStartOffsetUpdatedInChild(uint32_t aStartOffset);
+
+ /**
* CompositionEventDispatcher dispatches the specified composition (or text)
* event.
*/
class CompositionEventDispatcher : public Runnable
{
public:
CompositionEventDispatcher(TextComposition* aTextComposition,
nsINode* aEventTarget,
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -1861,17 +1861,17 @@ TabParent::RecvNotifyIMEFocus(const Cont
nsIMEUpdatePreference* aPreference)
{
nsCOMPtr<nsIWidget> widget = GetWidget();
if (!widget) {
*aPreference = nsIMEUpdatePreference();
return true;
}
- mContentCache.AssignContent(aContentCache, &aIMENotification);
+ mContentCache.AssignContent(aContentCache, widget, &aIMENotification);
IMEStateManager::NotifyIME(aIMENotification, widget, true);
if (aIMENotification.mMessage == NOTIFY_IME_OF_FOCUS) {
*aPreference = widget->GetIMEUpdatePreference();
}
return true;
}
@@ -1887,58 +1887,58 @@ TabParent::RecvNotifyIMETextChange(const
nsIMEUpdatePreference updatePreference = widget->GetIMEUpdatePreference();
NS_ASSERTION(updatePreference.WantTextChange(),
"Don't call Send/RecvNotifyIMETextChange without NOTIFY_TEXT_CHANGE");
MOZ_ASSERT(!aIMENotification.mTextChangeData.mCausedOnlyByComposition ||
updatePreference.WantChangesCausedByComposition(),
"The widget doesn't want text change notification caused by composition");
#endif
- mContentCache.AssignContent(aContentCache, &aIMENotification);
+ mContentCache.AssignContent(aContentCache, widget, &aIMENotification);
mContentCache.MaybeNotifyIME(widget, aIMENotification);
return true;
}
bool
TabParent::RecvNotifyIMECompositionUpdate(
const ContentCache& aContentCache,
const IMENotification& aIMENotification)
{
nsCOMPtr<nsIWidget> widget = GetWidget();
if (!widget) {
return true;
}
- mContentCache.AssignContent(aContentCache, &aIMENotification);
+ mContentCache.AssignContent(aContentCache, widget, &aIMENotification);
mContentCache.MaybeNotifyIME(widget, aIMENotification);
return true;
}
bool
TabParent::RecvNotifyIMESelection(const ContentCache& aContentCache,
const IMENotification& aIMENotification)
{
nsCOMPtr<nsIWidget> widget = GetWidget();
if (!widget)
return true;
- mContentCache.AssignContent(aContentCache, &aIMENotification);
+ mContentCache.AssignContent(aContentCache, widget, &aIMENotification);
mContentCache.MaybeNotifyIME(widget, aIMENotification);
return true;
}
bool
TabParent::RecvUpdateContentCache(const ContentCache& aContentCache)
{
nsCOMPtr<nsIWidget> widget = GetWidget();
if (!widget) {
return true;
}
- mContentCache.AssignContent(aContentCache);
+ mContentCache.AssignContent(aContentCache, widget);
return true;
}
bool
TabParent::RecvNotifyIMEMouseButtonEvent(
const IMENotification& aIMENotification,
bool* aConsumedByIME)
{
@@ -1957,17 +1957,17 @@ bool
TabParent::RecvNotifyIMEPositionChange(const ContentCache& aContentCache,
const IMENotification& aIMENotification)
{
nsCOMPtr<nsIWidget> widget = GetWidget();
if (!widget) {
return true;
}
- mContentCache.AssignContent(aContentCache, &aIMENotification);
+ mContentCache.AssignContent(aContentCache, widget, &aIMENotification);
mContentCache.MaybeNotifyIME(widget, aIMENotification);
return true;
}
bool
TabParent::RecvOnEventNeedingAckHandled(const EventMessage& aMessage)
{
// This is called when the child process receives WidgetCompositionEvent or
--- a/widget/ContentCache.cpp
+++ b/widget/ContentCache.cpp
@@ -433,41 +433,50 @@ ContentCacheInParent::ContentCacheInPare
, mCommitStringByRequest(nullptr)
, mPendingEventsNeedingAck(0)
, mIsComposing(false)
{
}
void
ContentCacheInParent::AssignContent(const ContentCache& aOther,
+ nsIWidget* aWidget,
const IMENotification* aNotification)
{
mCompositionStart = aOther.mCompositionStart;
mText = aOther.mText;
mSelection = aOther.mSelection;
mFirstCharRect = aOther.mFirstCharRect;
mCaret = aOther.mCaret;
mTextRectArray = aOther.mTextRectArray;
mEditorRect = aOther.mEditorRect;
+ if (mIsComposing) {
+ NS_WARN_IF(mCompositionStart == UINT32_MAX);
+ IMEStateManager::MaybeStartOffsetUpdatedInChild(aWidget, mCompositionStart);
+ } else {
+ NS_WARN_IF(mCompositionStart != UINT32_MAX);
+ }
+
MOZ_LOG(sContentCacheLog, LogLevel::Info,
("ContentCacheInParent: 0x%p AssignContent(aNotification=%s), "
"Succeeded, mText.Length()=%u, mSelection={ mAnchor=%u, mFocus=%u, "
"mWritingMode=%s, mAnchorCharRect=%s, mFocusCharRect=%s, mRect=%s }, "
"mFirstCharRect=%s, mCaret={ mOffset=%u, mRect=%s }, mTextRectArray={ "
- "mStart=%u, mRects.Length()=%u }, mCompositionStart=%u, mEditorRect=%s",
+ "mStart=%u, mRects.Length()=%u }, mIsComposing=%s, mCompositionStart=%u, "
+ "mEditorRect=%s",
this, GetNotificationName(aNotification),
mText.Length(), mSelection.mAnchor, mSelection.mFocus,
GetWritingModeName(mSelection.mWritingMode).get(),
GetRectText(mSelection.mAnchorCharRect).get(),
GetRectText(mSelection.mFocusCharRect).get(),
GetRectText(mSelection.mRect).get(), GetRectText(mFirstCharRect).get(),
mCaret.mOffset, GetRectText(mCaret.mRect).get(), mTextRectArray.mStart,
- mTextRectArray.mRects.Length(), mCompositionStart,
- GetRectText(mEditorRect).get()));
+ mTextRectArray.mRects.Length(), GetBoolName(mIsComposing),
+ mCompositionStart, GetRectText(mEditorRect).get()));
}
bool
ContentCacheInParent::HandleQueryContentEvent(WidgetQueryContentEvent& aEvent,
nsIWidget* aWidget) const
{
MOZ_ASSERT(aWidget);
--- a/widget/ContentCache.h
+++ b/widget/ContentCache.h
@@ -275,16 +275,17 @@ public:
ContentCacheInParent();
/**
* AssignContent() is called when TabParent receives ContentCache from
* the content process. This doesn't copy composition information because
* it's managed by TabParent itself.
*/
void AssignContent(const ContentCache& aOther,
+ nsIWidget* aWidget,
const IMENotification* aNotification = nullptr);
/**
* HandleQueryContentEvent() sets content data to aEvent.mReply.
*
* For eQuerySelectedText, fail if the cache doesn't contain the whole
* selected range. (This shouldn't happen because PuppetWidget should have
* already sent the whole selection.)