Bug 1166436 part.10 Optimize IME notification handling in PuppetWidget r=m_kato

This commit is contained in:
Masayuki Nakano 2015-06-05 18:28:20 +09:00
Родитель 496d6e76c8
Коммит dcfea181de
8 изменённых файлов: 59 добавлений и 49 удалений

Просмотреть файл

@ -1179,6 +1179,9 @@ IMEContentObserver::FlushMergeableNotifications()
nsContentUtils::AddScriptRunner(new TextChangeEvent(this, mTextChangeData));
}
// Be aware, PuppetWidget depends on the order of this. A selection change
// notification should not be sent before a text change notification because
// PuppetWidget shouldn't query new text content every selection change.
if (mIsSelectionChangeEventPending) {
mIsSelectionChangeEventPending = false;
nsContentUtils::AddScriptRunner(

Просмотреть файл

@ -215,11 +215,12 @@ parent:
bool causedByComposition);
/**
* Notifies chrome to refresh its text cache
* Notifies chrome of updating its content cache.
* This is useful if content is modified but we don't need to notify IME.
*
* contentCache Cache of content
*/
prio(urgent) async NotifyIMETextHint(ContentCache contentCache);
prio(urgent) async UpdateContentCache(ContentCache contentCache);
/**
* Notifies IME of mouse button event on a character in focused editor.
@ -229,13 +230,6 @@ parent:
prio(urgent) sync NotifyIMEMouseButtonEvent(IMENotification notification)
returns (bool consumedByIME);
/**
* Notifies chrome to currect editor rect
*
* contentCache Cache of content
*/
prio(urgent) async NotifyIMEEditorRect(ContentCache contentCache);
/**
* Notifies chrome to position change
*

Просмотреть файл

@ -1977,8 +1977,13 @@ TabParent::RecvNotifyIMESelection(const ContentCache& aContentCache,
}
bool
TabParent::RecvNotifyIMETextHint(const ContentCache& aContentCache)
TabParent::RecvUpdateContentCache(const ContentCache& aContentCache)
{
nsCOMPtr<nsIWidget> widget = GetWidget();
if (!widget) {
return true;
}
mContentCache.AssignContent(aContentCache);
return true;
}
@ -1999,13 +2004,6 @@ TabParent::RecvNotifyIMEMouseButtonEvent(
return true;
}
bool
TabParent::RecvNotifyIMEEditorRect(const ContentCache& aContentCache)
{
mContentCache.AssignContent(aContentCache);
return true;
}
bool
TabParent::RecvNotifyIMEPositionChange(const ContentCache& aContentCache)
{

Просмотреть файл

@ -172,10 +172,9 @@ public:
virtual bool RecvNotifyIMESelectedCompositionRect(const ContentCache& aContentCache) override;
virtual bool RecvNotifyIMESelection(const ContentCache& aContentCache,
const bool& aCausedByComposition) override;
virtual bool RecvNotifyIMETextHint(const ContentCache& aContentCache) override;
virtual bool RecvUpdateContentCache(const ContentCache& aContentCache) override;
virtual bool RecvNotifyIMEMouseButtonEvent(const widget::IMENotification& aEventMessage,
bool* aConsumedByIME) override;
virtual bool RecvNotifyIMEEditorRect(const ContentCache& aContentCache) override;
virtual bool RecvNotifyIMEPositionChange(const ContentCache& aContentCache) override;
virtual bool RecvEndIMEComposition(const bool& aCancel,
bool* aNoCompositionEvent,

Просмотреть файл

@ -25,6 +25,7 @@ ContentCache::ContentCache()
, mCompositionEventsDuringRequest(0)
, mIsComposing(false)
, mRequestedToCommitOrCancelComposition(false)
, mIsChrome(XRE_GetProcessType() == GeckoProcessType_Default)
{
}
@ -32,6 +33,10 @@ void
ContentCache::Clear()
{
mText.Truncate();
mSelection.Clear();
mCaret.Clear();
mTextRectArray.Clear();
mEditorRect.SetEmpty();
}
bool
@ -111,6 +116,11 @@ ContentCache::HandleQueryContentEvent(WidgetQueryContentEvent& aEvent,
bool
ContentCache::CacheAll(nsIWidget* aWidget)
{
// CacheAll() must be called in content process.
if (NS_WARN_IF(mIsChrome)) {
return false;
}
if (NS_WARN_IF(!CacheText(aWidget)) ||
NS_WARN_IF(!CacheSelection(aWidget)) ||
NS_WARN_IF(!CacheTextRects(aWidget)) ||
@ -123,6 +133,11 @@ ContentCache::CacheAll(nsIWidget* aWidget)
bool
ContentCache::CacheSelection(nsIWidget* aWidget)
{
// CacheSelection() must be called in content process.
if (NS_WARN_IF(mIsChrome)) {
return false;
}
mCaret.Clear();
mSelection.Clear();
@ -166,6 +181,11 @@ ContentCache::CacheSelection(nsIWidget* aWidget)
bool
ContentCache::CacheEditorRect(nsIWidget* aWidget)
{
// CacheEditorRect() must be called in content process.
if (NS_WARN_IF(mIsChrome)) {
return false;
}
nsEventStatus status = nsEventStatus_eIgnore;
WidgetQueryContentEvent editorRectEvent(true, NS_QUERY_EDITOR_RECT, aWidget);
aWidget->DispatchEvent(&editorRectEvent, status);
@ -179,6 +199,11 @@ ContentCache::CacheEditorRect(nsIWidget* aWidget)
bool
ContentCache::CacheText(nsIWidget* aWidget)
{
// CacheText() must be called in content process.
if (NS_WARN_IF(mIsChrome)) {
return false;
}
nsEventStatus status = nsEventStatus_eIgnore;
WidgetQueryContentEvent queryText(true, NS_QUERY_TEXT_CONTENT, aWidget);
queryText.InitForQueryTextContent(0, UINT32_MAX);
@ -194,6 +219,11 @@ ContentCache::CacheText(nsIWidget* aWidget)
bool
ContentCache::CacheTextRects(nsIWidget* aWidget)
{
// CacheTextRects() must be called in content process.
if (NS_WARN_IF(mIsChrome)) {
return false;
}
mTextRectArray.Clear();
nsRefPtr<TextComposition> textComposition =

Просмотреть файл

@ -278,6 +278,7 @@ private:
bool mIsComposing;
bool mRequestedToCommitOrCancelComposition;
bool mIsChrome;
friend struct IPC::ParamTraits<ContentCache>;
};

Просмотреть файл

@ -674,11 +674,12 @@ PuppetWidget::NotifyIMEOfFocusChange(bool aFocus)
return NS_ERROR_FAILURE;
if (aFocus) {
if (NS_WARN_IF(!mContentCache.CacheText(this))) {
// When IME gets focus, we should initalize all information of the content.
if (NS_WARN_IF(!mContentCache.CacheAll(this))) {
return NS_ERROR_FAILURE;
}
mTabChild->SendNotifyIMETextHint(mContentCache);
} else {
// When IME loses focus, we don't need to store anything.
mContentCache.Clear();
}
@ -687,14 +688,6 @@ PuppetWidget::NotifyIMEOfFocusChange(bool aFocus)
&mIMEPreferenceOfParent)) {
return NS_ERROR_FAILURE;
}
// TODO: Optimize this later.
if (aFocus) {
IMENotification notification(NOTIFY_IME_OF_SELECTION_CHANGE);
notification.mSelectionChangeData.mCausedByComposition = false;
NotifyIMEOfSelectionChange(notification); // Update selection
NotifyIMEOfEditorRect();
}
return NS_OK;
}
@ -715,23 +708,6 @@ PuppetWidget::NotifyIMEOfUpdateComposition()
return NS_OK;
}
nsresult
PuppetWidget::NotifyIMEOfEditorRect()
{
#ifndef MOZ_CROSS_PROCESS_IME
return NS_OK;
#endif
if (NS_WARN_IF(!mTabChild)) {
return NS_ERROR_FAILURE;
}
if (NS_WARN_IF(!mContentCache.CacheEditorRect(this))) {
return NS_ERROR_FAILURE;
}
mTabChild->SendNotifyIMEEditorRect(mContentCache);
return NS_OK;
}
nsIMEUpdatePreference
PuppetWidget::GetIMEUpdatePreference()
{
@ -760,10 +736,16 @@ PuppetWidget::NotifyIMEOfTextChange(const IMENotification& aIMENotification)
if (!mTabChild)
return NS_ERROR_FAILURE;
if (NS_WARN_IF(!mContentCache.CacheText(this))) {
// FYI: text change notification is the first notification after
// a user operation changes the content. So, we need to modify
// the cache as far as possible here.
// When text is changed, selection and text rects must be changed too.
if (NS_WARN_IF(!mContentCache.CacheText(this)) ||
NS_WARN_IF(!mContentCache.CacheTextRects(this)) ||
NS_WARN_IF(!mContentCache.CacheSelection(this))) {
return NS_ERROR_FAILURE;
}
mTabChild->SendNotifyIMETextHint(mContentCache);
// TabParent doesn't this this to cache. we don't send the notification
// if parent process doesn't request NOTIFY_TEXT_CHANGE.
@ -776,6 +758,8 @@ PuppetWidget::NotifyIMEOfTextChange(const IMENotification& aIMENotification)
aIMENotification.mTextChangeData.mOldEndOffset,
aIMENotification.mTextChangeData.mNewEndOffset,
aIMENotification.mTextChangeData.mCausedByComposition);
} else {
mTabChild->SendUpdateContentCache(mContentCache);
}
return NS_OK;
}
@ -794,6 +778,8 @@ PuppetWidget::NotifyIMEOfSelectionChange(
if (!mTabChild)
return NS_ERROR_FAILURE;
// Note that selection change must be notified after text change if it occurs.
// Therefore, we don't need to query text content again here.
mContentCache.SetSelection(
aIMENotification.mSelectionChangeData.mOffset,
aIMENotification.mSelectionChangeData.mLength,

Просмотреть файл

@ -262,7 +262,6 @@ private:
nsresult NotifyIMEOfUpdateComposition();
nsresult NotifyIMEOfTextChange(const IMENotification& aIMENotification);
nsresult NotifyIMEOfMouseButtonEvent(const IMENotification& aIMENotification);
nsresult NotifyIMEOfEditorRect();
nsresult NotifyIMEOfPositionChange();
bool CacheEditorRect();