Bug 1172466 part.4 Don't notify IME during reflow r=smaug

This commit is contained in:
Masayuki Nakano 2015-06-17 10:03:57 +09:00
Родитель 81de1dd26c
Коммит 94bb7f1516
2 изменённых файлов: 117 добавлений и 19 удалений

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

@ -201,6 +201,10 @@ IMEContentObserver::Init(nsIWidget* aWidget,
mDocShell = aPresContext->GetDocShell();
ObserveEditableNode();
// Some change events may wait to notify IME because this was being
// initialized. It is the time to flush them.
FlushMergeableNotifications();
}
void
@ -994,23 +998,21 @@ IMEContentObserver::CancelEditAction()
}
void
IMEContentObserver::MaybeNotifyIMEOfFocusSet()
IMEContentObserver::PostFocusSetNotification()
{
mIsFocusEventPending = true;
FlushMergeableNotifications();
}
void
IMEContentObserver::MaybeNotifyIMEOfTextChange(const TextChangeData& aData)
IMEContentObserver::PostTextChangeNotification(const TextChangeData& aData)
{
StoreTextChangeData(aData);
MOZ_ASSERT(mTextChangeData.mStored,
"mTextChangeData must have text change data");
FlushMergeableNotifications();
}
void
IMEContentObserver::MaybeNotifyIMEOfSelectionChange(bool aCausedByComposition)
IMEContentObserver::PostSelectionChangeNotification(bool aCausedByComposition)
{
if (!mIsSelectionChangeEventPending) {
mSelectionChangeCausedOnlyByComposition = aCausedByComposition;
@ -1019,34 +1021,70 @@ IMEContentObserver::MaybeNotifyIMEOfSelectionChange(bool aCausedByComposition)
mSelectionChangeCausedOnlyByComposition && aCausedByComposition;
}
mIsSelectionChangeEventPending = true;
FlushMergeableNotifications();
}
void
IMEContentObserver::MaybeNotifyIMEOfPositionChange()
IMEContentObserver::PostPositionChangeNotification()
{
mIsPositionChangeEventPending = true;
FlushMergeableNotifications();
}
void
IMEContentObserver::FlushMergeableNotifications()
bool
IMEContentObserver::IsReflowLocked() const
{
nsPresContext* presContext = GetPresContext();
if (NS_WARN_IF(!presContext)) {
return false;
}
nsIPresShell* presShell = presContext->GetPresShell();
if (NS_WARN_IF(!presShell)) {
return false;
}
// During reflow, we shouldn't notify IME because IME may query content
// synchronously. Then, it causes ContentEventHandler will try to flush
// pending notifications during reflow.
return presShell->IsReflowLocked();
}
bool
IMEContentObserver::IsSafeToNotifyIME() const
{
// If this is already detached from the widget, this doesn't need to notify
// anything.
if (!mWidget) {
return;
return false;
}
// Don't notify IME of anything if it's not good time to do it.
if (mSuppressNotifications) {
return;
return false;
}
if (!mESM || NS_WARN_IF(!GetPresContext())) {
return false;
}
// If it's in reflow, we should wait to finish the reflow.
// FYI: This should be called again from Reflow() or ReflowInterruptible().
if (IsReflowLocked()) {
return false;
}
// If we're in handling an edit action, this method will be called later.
bool isInEditAction = false;
if (mEditor && NS_SUCCEEDED(mEditor->GetIsInEditAction(&isInEditAction)) &&
isInEditAction) {
return false;
}
return true;
}
void
IMEContentObserver::FlushMergeableNotifications()
{
if (!IsSafeToNotifyIME()) {
// So, if this is already called, this should do nothing.
return;
}
@ -1584,6 +1622,23 @@ IMEContentObserver::AChangeEvent::CanNotifyIME() const
return true;
}
bool
IMEContentObserver::AChangeEvent::IsSafeToNotifyIME() const
{
if (NS_WARN_IF(!nsContentUtils::IsSafeToRunScript())) {
return false;
}
State state = mIMEContentObserver->GetState();
if (mChangeEventType == eChangeEventType_Focus) {
if (NS_WARN_IF(state != eState_Initializing && state != eState_Observing)) {
return false;
}
} else if (state != eState_Observing) {
return false;
}
return mIMEContentObserver->IsSafeToNotifyIME();
}
/******************************************************************************
* mozilla::IMEContentObserver::FocusSetEvent
******************************************************************************/
@ -1598,6 +1653,11 @@ IMEContentObserver::FocusSetEvent::Run()
return NS_OK;
}
if (!IsSafeToNotifyIME()) {
mIMEContentObserver->PostFocusSetNotification();
return NS_OK;
}
mIMEContentObserver->mIMEHasFocus = true;
mIMEContentObserver->mWidget->NotifyIME(IMENotification(NOTIFY_IME_OF_FOCUS));
return NS_OK;
@ -1614,8 +1674,8 @@ IMEContentObserver::SelectionChangeEvent::Run()
return NS_OK;
}
nsPresContext* presContext = mIMEContentObserver->GetPresContext();
if (!presContext) {
if (!IsSafeToNotifyIME()) {
mIMEContentObserver->PostSelectionChangeNotification(mCausedByComposition);
return NS_OK;
}
@ -1623,7 +1683,7 @@ IMEContentObserver::SelectionChangeEvent::Run()
// selection offset and writing mode?
WidgetQueryContentEvent selection(true, NS_QUERY_SELECTED_TEXT,
mIMEContentObserver->mWidget);
ContentEventHandler handler(presContext);
ContentEventHandler handler(mIMEContentObserver->GetPresContext());
handler.OnQuerySelectedText(&selection);
if (NS_WARN_IF(!selection.mSucceeded)) {
return NS_OK;
@ -1659,6 +1719,11 @@ IMEContentObserver::TextChangeEvent::Run()
return NS_OK;
}
if (!IsSafeToNotifyIME()) {
mIMEContentObserver->PostTextChangeNotification(mData);
return NS_OK;
}
IMENotification notification(NOTIFY_IME_OF_TEXT_CHANGE);
notification.mTextChangeData.mStartOffset = mData.mStartOffset;
notification.mTextChangeData.mOldEndOffset = mData.mRemovedEndOffset;
@ -1680,6 +1745,11 @@ IMEContentObserver::PositionChangeEvent::Run()
return NS_OK;
}
if (!IsSafeToNotifyIME()) {
mIMEContentObserver->PostPositionChangeNotification();
return NS_OK;
}
mIMEContentObserver->mWidget->NotifyIME(
IMENotification(NOTIFY_IME_OF_POSITION_CHANGE));
return NS_OK;

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

@ -161,10 +161,33 @@ private:
State GetState() const;
bool IsObservingContent(nsPresContext* aPresContext,
nsIContent* aContent) const;
void MaybeNotifyIMEOfFocusSet();
void MaybeNotifyIMEOfTextChange(const TextChangeData& aTextChangeData);
void MaybeNotifyIMEOfSelectionChange(bool aCausedByComposition);
void MaybeNotifyIMEOfPositionChange();
bool IsReflowLocked() const;
bool IsSafeToNotifyIME() const;
void PostFocusSetNotification();
void MaybeNotifyIMEOfFocusSet()
{
PostFocusSetNotification();
FlushMergeableNotifications();
}
void PostTextChangeNotification(const TextChangeData& aTextChangeData);
void MaybeNotifyIMEOfTextChange(const TextChangeData& aTextChangeData)
{
PostTextChangeNotification(aTextChangeData);
FlushMergeableNotifications();
}
void PostSelectionChangeNotification(bool aCausedByComposition);
void MaybeNotifyIMEOfSelectionChange(bool aCausedByComposition)
{
PostSelectionChangeNotification(aCausedByComposition);
FlushMergeableNotifications();
}
void PostPositionChangeNotification();
void MaybeNotifyIMEOfPositionChange()
{
PostPositionChangeNotification();
FlushMergeableNotifications();
}
void NotifyContentAdded(nsINode* aContainer, int32_t aStart, int32_t aEnd);
void ObserveEditableNode();
@ -300,6 +323,11 @@ private:
* CanNotifyIME() checks if mIMEContentObserver can and should notify IME.
*/
bool CanNotifyIME() const;
/**
* IsSafeToNotifyIME() checks if it's safe to noitify IME.
*/
bool IsSafeToNotifyIME() const;
};
class FocusSetEvent: public AChangeEvent