Bug 705057 part.4 Emulate the behavior of nsIWidget::ResetInputState() and nsIWidget::CancelIMEComposition() if the composition is synthesized r=smaug+roc, sr=roc

This commit is contained in:
Masayuki Nakano 2012-09-26 14:47:51 +09:00
Родитель b1133a0c74
Коммит affac42d19
8 изменённых файлов: 99 добавлений и 19 удалений

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

@ -26,7 +26,9 @@ TextComposition::TextComposition(nsPresContext* aPresContext,
mPresContext(aPresContext), mNode(aNode),
// temporarily, we should assume that one native IME context is per native
// widget.
mNativeContext(aEvent->widget)
mNativeContext(aEvent->widget),
mIsSynthesizedForTests(
(aEvent->flags & NS_EVENT_FLAG_SYNTHETIC_TEST_EVENT) != 0)
{
}
@ -36,6 +38,7 @@ TextComposition::TextComposition(const TextComposition& aOther)
mPresContext = aOther.mPresContext;
mNode = aOther.mNode;
mLastData = aOther.mLastData;
mIsSynthesizedForTests = aOther.mIsSynthesizedForTests;
}
bool

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

@ -48,6 +48,9 @@ public:
nsINode* GetEventTargetNode() const { return mNode; }
// The latest CompositionEvent.data value except compositionstart event.
const nsString& GetLastData() const { return mLastData; }
// Returns true if the composition is started with synthesized event which
// came from nsDOMWindowUtils.
bool IsSynthesizedForTests() const { return mIsSynthesizedForTests; }
bool MatchesNativeContext(nsIWidget* aWidget) const;
bool MatchesEventTarget(nsPresContext* aPresContext,
@ -83,6 +86,9 @@ private:
// the compositionstart event).
nsString mLastData;
// See the comment for IsSynthesizedForTests().
bool mIsSynthesizedForTests;
// Hide the default constructor
TextComposition() {}

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

@ -508,16 +508,83 @@ nsIMEStateManager::NotifyIME(NotificationToIME aNotification,
if (sTextCompositions) {
composition = sTextCompositions->GetCompositionFor(aWidget);
}
if (!composition || !composition->IsSynthesizedForTests()) {
switch (aNotification) {
case NOTIFY_IME_OF_CURSOR_POS_CHANGED:
return aWidget->ResetInputState();
case REQUEST_TO_COMMIT_COMPOSITION:
return composition ? aWidget->ResetInputState() : NS_OK;
case REQUEST_TO_CANCEL_COMPOSITION:
return composition ? aWidget->CancelIMEComposition() : NS_OK;
default:
MOZ_NOT_REACHED("Unsupported notification");
return NS_ERROR_INVALID_ARG;
}
MOZ_NOT_REACHED(
"Failed to handle the notification for non-synthesized composition");
}
// If the composition is synthesized events for automated tests, we should
// dispatch composition events for emulating the native composition behavior.
// NOTE: The dispatched events are discarded if it's not safe to run script.
switch (aNotification) {
case NOTIFY_IME_OF_CURSOR_POS_CHANGED:
return aWidget->ResetInputState();
case REQUEST_TO_COMMIT_COMPOSITION:
return composition ? aWidget->ResetInputState() : NS_OK;
case REQUEST_TO_CANCEL_COMPOSITION:
return composition ? aWidget->CancelIMEComposition() : NS_OK;
case REQUEST_TO_COMMIT_COMPOSITION: {
nsCOMPtr<nsIWidget> widget(aWidget);
TextComposition backup = *composition;
nsEventStatus status = nsEventStatus_eIgnore;
if (!backup.GetLastData().IsEmpty()) {
nsTextEvent textEvent(true, NS_TEXT_TEXT, widget);
textEvent.theText = backup.GetLastData();
textEvent.flags |= NS_EVENT_FLAG_SYNTHETIC_TEST_EVENT;
widget->DispatchEvent(&textEvent, status);
if (widget->Destroyed()) {
return NS_OK;
}
}
status = nsEventStatus_eIgnore;
nsCompositionEvent endEvent(true, NS_COMPOSITION_END, widget);
endEvent.data = backup.GetLastData();
endEvent.flags |= NS_EVENT_FLAG_SYNTHETIC_TEST_EVENT;
widget->DispatchEvent(&endEvent, status);
return NS_OK;
}
case REQUEST_TO_CANCEL_COMPOSITION: {
nsCOMPtr<nsIWidget> widget(aWidget);
TextComposition backup = *composition;
nsEventStatus status = nsEventStatus_eIgnore;
if (!backup.GetLastData().IsEmpty()) {
nsCompositionEvent updateEvent(true, NS_COMPOSITION_UPDATE, widget);
updateEvent.data = backup.GetLastData();
updateEvent.flags |= NS_EVENT_FLAG_SYNTHETIC_TEST_EVENT;
widget->DispatchEvent(&updateEvent, status);
if (widget->Destroyed()) {
return NS_OK;
}
status = nsEventStatus_eIgnore;
nsTextEvent textEvent(true, NS_TEXT_TEXT, widget);
textEvent.theText = backup.GetLastData();
textEvent.flags |= NS_EVENT_FLAG_SYNTHETIC_TEST_EVENT;
widget->DispatchEvent(&textEvent, status);
if (widget->Destroyed()) {
return NS_OK;
}
}
status = nsEventStatus_eIgnore;
nsCompositionEvent endEvent(true, NS_COMPOSITION_END, widget);
endEvent.data = backup.GetLastData();
endEvent.flags |= NS_EVENT_FLAG_SYNTHETIC_TEST_EVENT;
widget->DispatchEvent(&endEvent, status);
return NS_OK;
}
default:
MOZ_NOT_REACHED("Unsupported notification");
return NS_ERROR_INVALID_ARG;
return NS_OK;
}
}

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

@ -1598,6 +1598,8 @@ nsDOMWindowUtils::SendCompositionEvent(const nsAString& aType,
compositionEvent.data = aData;
}
compositionEvent.flags |= NS_EVENT_FLAG_SYNTHETIC_TEST_EVENT;
nsEventStatus status;
nsresult rv = widget->DispatchEvent(&compositionEvent, status);
NS_ENSURE_SUCCESS(rv, rv);
@ -1675,6 +1677,8 @@ nsDOMWindowUtils::SendTextEvent(const nsAString& aCompositionString,
textEvent.rangeCount = textRanges.Length();
textEvent.rangeArray = textRanges.Elements();
textEvent.flags |= NS_EVENT_FLAG_SYNTHETIC_TEST_EVENT;
nsEventStatus status;
nsresult rv = widget->DispatchEvent(&textEvent, status);
NS_ENSURE_SUCCESS(rv, rv);

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

@ -409,6 +409,7 @@ class nsIWidget : public nsISupports {
nsIWidget()
: mLastChild(nullptr)
, mPrevSibling(nullptr)
, mOnDestroyCalled(false)
{}
@ -511,6 +512,12 @@ class nsIWidget : public nsISupports {
NS_IMETHOD Destroy(void) = 0;
/**
* Destroyed() returns true if Destroy() has been called already.
* Otherwise, false.
*/
bool Destroyed() const { return mOnDestroyCalled; }
/**
* Reparent a widget
@ -1654,6 +1661,8 @@ protected:
nsIWidget* mLastChild;
nsCOMPtr<nsIWidget> mNextSibling;
nsIWidget* mPrevSibling;
// When Destroy() is called, the sub class should set this true.
bool mOnDestroyCalled;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIWidget, NS_IWIDGET_IID)

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

@ -251,7 +251,7 @@ bool
TaskbarPreview::IsWindowAvailable() const {
if (mWnd) {
nsWindow* win = WinUtils::GetNSWindowPtr(mWnd);
if(win && !win->HasDestroyStarted()) {
if(win && !win->Destroyed()) {
return true;
}
}

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

@ -90,7 +90,6 @@ nsBaseWidget::nsBaseWidget()
, mCursor(eCursor_standard)
, mWindowType(eWindowType_child)
, mBorderStyle(eBorderStyle_none)
, mOnDestroyCalled(false)
, mUseAcceleratedRendering(false)
, mForceLayersAcceleration(false)
, mTemporarilyUseBasicLayerManager(false)

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

@ -228,13 +228,6 @@ public:
};
friend class AutoUseBasicLayerManager;
bool HasDestroyStarted() const
{
return mOnDestroyCalled;
}
bool Destroyed() { return mOnDestroyCalled; }
nsWindowType GetWindowType() { return mWindowType; }
virtual bool UseOffMainThreadCompositing();
@ -341,7 +334,6 @@ protected:
nsCursor mCursor;
nsWindowType mWindowType;
nsBorderStyle mBorderStyle;
bool mOnDestroyCalled;
bool mUseAcceleratedRendering;
bool mForceLayersAcceleration;
bool mTemporarilyUseBasicLayerManager;