зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1218032 part.4 Notify IMEContentObserver of enough safe timing to notify IME of something r=smaug
This commit is contained in:
Родитель
0727f7951c
Коммит
8973128bba
|
@ -26,6 +26,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=976673
|
|||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
// In e10s mode, ContentCacheInChild tries to retrieve selected text and
|
||||
// caret position when IMEContentObserver notifies IME of focus. At this time,
|
||||
// we hit assertion in nsContentIterator.
|
||||
SimpleTest.expectAssertions(0, 6);
|
||||
|
||||
window.addEventListener("mousedown", function (aEvent) { aEvent.preventDefault(); }, false);
|
||||
|
||||
function testSetFocus(aEventType, aCallback)
|
||||
|
|
|
@ -473,6 +473,14 @@ EventStateManager::OnStopObservingContent(
|
|||
mIMEContentObserver = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
EventStateManager::TryToFlushPendingNotificationsToIME()
|
||||
{
|
||||
if (mIMEContentObserver) {
|
||||
mIMEContentObserver->TryToFlushPendingNotifications();
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
EventStateManager::PreHandleEvent(nsPresContext* aPresContext,
|
||||
WidgetEvent* aEvent,
|
||||
|
|
|
@ -146,6 +146,12 @@ public:
|
|||
void OnStartToObserveContent(IMEContentObserver* aIMEContentObserver);
|
||||
void OnStopObservingContent(IMEContentObserver* aIMEContentObserver);
|
||||
|
||||
/**
|
||||
* TryToFlushPendingNotificationsToIME() suggests flushing pending
|
||||
* notifications to IME to IMEContentObserver.
|
||||
*/
|
||||
void TryToFlushPendingNotificationsToIME();
|
||||
|
||||
/**
|
||||
* Register accesskey on the given element. When accesskey is activated then
|
||||
* the element will be notified via nsIContent::PerformAccesskey() method.
|
||||
|
|
|
@ -1395,6 +1395,19 @@ IMEContentObserver::FlushMergeableNotifications()
|
|||
"finished", this));
|
||||
}
|
||||
|
||||
void
|
||||
IMEContentObserver::TryToFlushPendingNotifications()
|
||||
{
|
||||
if (!mQueuedSender || mSendingNotification != NOTIFY_IME_OF_NOTHING) {
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_LOG(sIMECOLog, LogLevel::Debug,
|
||||
("IMECO: 0x%p IMEContentObserver::TryToFlushPendingNotifications(), "
|
||||
"performing queued IMENotificationSender forcibly", this));
|
||||
mQueuedSender->Run();
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* mozilla::IMEContentObserver::AChangeEvent
|
||||
******************************************************************************/
|
||||
|
@ -1461,7 +1474,20 @@ IMEContentObserver::AChangeEvent::IsSafeToNotifyIME(
|
|||
NS_IMETHODIMP
|
||||
IMEContentObserver::IMENotificationSender::Run()
|
||||
{
|
||||
MOZ_ASSERT(mIMEContentObserver->mQueuedSender);
|
||||
if (NS_WARN_IF(mIsRunning)) {
|
||||
MOZ_LOG(sIMECOLog, LogLevel::Error,
|
||||
("IMECO: 0x%p IMEContentObserver::IMENotificationSender::Run(), FAILED, "
|
||||
"called recursively", this));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
AutoRestore<bool> running(mIsRunning);
|
||||
mIsRunning = true;
|
||||
|
||||
// This instance was already performed forcibly.
|
||||
if (mIMEContentObserver->mQueuedSender != this) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// NOTE: Reset each pending flag because sending notification may cause
|
||||
// another change.
|
||||
|
|
|
@ -103,6 +103,12 @@ public:
|
|||
nsresult GetSelectionAndRoot(nsISelection** aSelection,
|
||||
nsIContent** aRoot) const;
|
||||
|
||||
/**
|
||||
* TryToFlushPendingNotifications() should be called when pending events
|
||||
* should be flushed. This tries to run the queued IMENotificationSender.
|
||||
*/
|
||||
void TryToFlushPendingNotifications();
|
||||
|
||||
private:
|
||||
~IMEContentObserver() {}
|
||||
|
||||
|
@ -223,6 +229,7 @@ private:
|
|||
public:
|
||||
explicit IMENotificationSender(IMEContentObserver* aIMEContentObserver)
|
||||
: AChangeEvent(aIMEContentObserver)
|
||||
, mIsRunning(false)
|
||||
{
|
||||
}
|
||||
NS_IMETHOD Run() override;
|
||||
|
@ -232,6 +239,8 @@ private:
|
|||
void SendSelectionChange();
|
||||
void SendTextChange();
|
||||
void SendPositionChange();
|
||||
|
||||
bool mIsRunning;
|
||||
};
|
||||
|
||||
// mQueuedSender is, it was put into the event queue but not run yet.
|
||||
|
|
|
@ -515,6 +515,13 @@ IMEStateManager::OnChangeFocusInternal(nsPresContext* aPresContext,
|
|||
// editor.
|
||||
if (newState.mEnabled == IMEState::PLUGIN) {
|
||||
CreateIMEContentObserver(nullptr);
|
||||
if (sActiveIMEContentObserver) {
|
||||
MOZ_LOG(sISMLog, LogLevel::Debug,
|
||||
("ISM: IMEStateManager::OnChangeFocusInternal(), an "
|
||||
"IMEContentObserver instance is created for plugin and trying to "
|
||||
"flush its pending notifications..."));
|
||||
sActiveIMEContentObserver->TryToFlushPendingNotifications();
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -684,6 +691,14 @@ IMEStateManager::OnFocusInEditor(nsPresContext* aPresContext,
|
|||
}
|
||||
|
||||
CreateIMEContentObserver(aEditor);
|
||||
|
||||
// Let's flush the focus notification now.
|
||||
if (sActiveIMEContentObserver) {
|
||||
MOZ_LOG(sISMLog, LogLevel::Debug,
|
||||
("ISM: IMEStateManager::OnFocusInEditor(), new IMEContentObserver is "
|
||||
"created, trying to flush pending notifications..."));
|
||||
sActiveIMEContentObserver->TryToFlushPendingNotifications();
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
|
@ -797,6 +812,9 @@ IMEStateManager::UpdateIMEState(const IMEState& aNewIMEState,
|
|||
}
|
||||
|
||||
if (createTextStateManager) {
|
||||
// XXX In this case, it might not be enough safe to notify IME of anything.
|
||||
// So, don't try to flush pending notifications of IMEContentObserver
|
||||
// here.
|
||||
CreateIMEContentObserver(aEditor);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6988,7 +6988,7 @@ PresShell::HandleEvent(nsIFrame* aFrame,
|
|||
aFrame = targetContent->GetPrimaryFrame();
|
||||
if (!aFrame) {
|
||||
PushCurrentEventInfo(aFrame, targetContent);
|
||||
nsresult rv = HandleEventInternal(aEvent, aEventStatus);
|
||||
nsresult rv = HandleEventInternal(aEvent, aEventStatus, true);
|
||||
PopCurrentEventInfo();
|
||||
return rv;
|
||||
}
|
||||
|
@ -7645,7 +7645,7 @@ PresShell::HandleEvent(nsIFrame* aFrame,
|
|||
mCurrentEventFrame = frame;
|
||||
}
|
||||
if (GetCurrentEventFrame()) {
|
||||
rv = HandleEventInternal(aEvent, aEventStatus);
|
||||
rv = HandleEventInternal(aEvent, aEventStatus, true);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -7658,7 +7658,7 @@ PresShell::HandleEvent(nsIFrame* aFrame,
|
|||
|
||||
if (!NS_EVENT_NEEDS_FRAME(aEvent)) {
|
||||
mCurrentEventFrame = nullptr;
|
||||
return HandleEventInternal(aEvent, aEventStatus);
|
||||
return HandleEventInternal(aEvent, aEventStatus, true);
|
||||
}
|
||||
else if (aEvent->HasKeyEventMessage()) {
|
||||
// Keypress events in new blank tabs should not be completely thrown away.
|
||||
|
@ -7761,7 +7761,7 @@ PresShell::HandlePositionedEvent(nsIFrame* aTargetFrame,
|
|||
}
|
||||
|
||||
if (GetCurrentEventFrame()) {
|
||||
rv = HandleEventInternal(aEvent, aEventStatus);
|
||||
rv = HandleEventInternal(aEvent, aEventStatus, true);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -7787,13 +7787,15 @@ PresShell::HandleEventWithTarget(WidgetEvent* aEvent, nsIFrame* aFrame,
|
|||
NS_ENSURE_STATE(!aContent || aContent->GetCrossShadowCurrentDoc() == mDocument);
|
||||
|
||||
PushCurrentEventInfo(aFrame, aContent);
|
||||
nsresult rv = HandleEventInternal(aEvent, aStatus);
|
||||
nsresult rv = HandleEventInternal(aEvent, aStatus, false);
|
||||
PopCurrentEventInfo();
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
PresShell::HandleEventInternal(WidgetEvent* aEvent, nsEventStatus* aStatus)
|
||||
PresShell::HandleEventInternal(WidgetEvent* aEvent,
|
||||
nsEventStatus* aStatus,
|
||||
bool aIsHandlingNativeEvent)
|
||||
{
|
||||
RefPtr<EventStateManager> manager = mPresContext->EventStateManager();
|
||||
nsresult rv = NS_OK;
|
||||
|
@ -7939,6 +7941,14 @@ PresShell::HandleEventInternal(WidgetEvent* aEvent, nsEventStatus* aStatus)
|
|||
}
|
||||
}
|
||||
|
||||
if (!mIsDestroying && aIsHandlingNativeEvent) {
|
||||
// Ensure that notifications to IME should be sent before getting next
|
||||
// native event from the event queue.
|
||||
// XXX Should we check the event message or event class instead of
|
||||
// using aIsHandlingNativeEvent?
|
||||
manager->TryToFlushPendingNotificationsToIME();
|
||||
}
|
||||
|
||||
switch (aEvent->mMessage) {
|
||||
case eKeyPress:
|
||||
case eKeyDown:
|
||||
|
|
|
@ -580,7 +580,7 @@ protected:
|
|||
mCurrentEventContent = aTarget;
|
||||
nsresult rv = NS_OK;
|
||||
if (GetCurrentEventFrame()) {
|
||||
rv = HandleEventInternal(aEvent, aStatus);
|
||||
rv = HandleEventInternal(aEvent, aStatus, true);
|
||||
}
|
||||
PopCurrentEventInfo();
|
||||
return rv;
|
||||
|
@ -669,8 +669,14 @@ protected:
|
|||
nsEventStatus* aEventStatus);
|
||||
void PushCurrentEventInfo(nsIFrame* aFrame, nsIContent* aContent);
|
||||
void PopCurrentEventInfo();
|
||||
/**
|
||||
* @param aIsHandlingNativeEvent true when the caller (perhaps) handles
|
||||
* an event which is caused by native
|
||||
* event. Otherwise, false.
|
||||
*/
|
||||
nsresult HandleEventInternal(mozilla::WidgetEvent* aEvent,
|
||||
nsEventStatus* aStatus);
|
||||
nsEventStatus* aStatus,
|
||||
bool aIsHandlingNativeEvent);
|
||||
nsresult HandlePositionedEvent(nsIFrame* aTargetFrame,
|
||||
mozilla::WidgetGUIEvent* aEvent,
|
||||
nsEventStatus* aEventStatus);
|
||||
|
|
Загрузка…
Ссылка в новой задаче