зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
b1133a0c74
Коммит
affac42d19
|
@ -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,6 +508,7 @@ 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();
|
||||
|
@ -519,6 +520,72 @@ nsIMEStateManager::NotifyIME(NotificationToIME aNotification,
|
|||
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 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:
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче