Bug 1349255 - Make PBrowser.NotifyIMEFocus async to avoid UI jank.
MozReview-Commit-ID: 15eUwMJ2Q7H
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -206,19 +206,17 @@ parent:
/**
* Notifies chrome that there is a focus change involving an editable
* object (input, textarea, document, contentEditable. etc.)
*
* contentCache Cache of content
* notification Whole data of the notification
* requests Requests of notification for IME of the native widget
*/
- nested(inside_cpow) sync NotifyIMEFocus(ContentCache contentCache,
- IMENotification notification)
- returns (IMENotificationRequests requests);
+ async NotifyIMEFocus(ContentCache contentCache, IMENotification notification);
/**
* Notifies chrome that there has been a change in text content
* One call can encompass both a delete and an insert operation
* Only called when NotifyIMEFocus returns PR_TRUE for mWantUpdates
*
* contentCache Cache of content
* notification Whole data of the notification
@@ -546,17 +544,16 @@ parent:
async AccessKeyNotHandled(WidgetKeyboardEvent event);
async SetHasBeforeUnload(bool aHasBeforeUnload);
child:
async NativeSynthesisResponse(uint64_t aObserverId, nsCString aResponse);
-
parent:
/**
* Child informs the parent that the graphics objects are ready for
* compositing. This is sent when all pending changes have been
* sent to the compositor and are ready to be shown on the next composite.
* @see PCompositor
* @see RequestNotifyAfterRemotePaint
@@ -619,16 +616,18 @@ child:
* content processes always render to a virtual <0, 0> top-left
* point.
*/
async Show(ScreenIntSize size,
ShowInfo info,
bool parentIsActive,
nsSizeMode sizeMode);
+ async ReplyIMENotificationRequests(IMENotificationRequests requests);
+
async InitRendering(TextureFactoryIdentifier textureFactoryIdentifier,
uint64_t layersId,
CompositorOptions compositorOptions,
bool layersConnected,
nullable PRenderFrame renderFrame);
async LoadURL(nsCString uri, ShowInfo info);
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -2164,16 +2164,27 @@ TabChild::RecvAsyncMessage(const nsStrin
RefPtr<nsFrameMessageManager> mm =
static_cast<nsFrameMessageManager*>(mTabChildGlobal->mMessageManager.get());
mm->ReceiveMessage(static_cast<EventTarget*>(mTabChildGlobal), nullptr,
aMessage, false, &data, &cpows, aPrincipal, nullptr);
return IPC_OK();
}
mozilla::ipc::IPCResult
+TabChild::RecvReplyIMENotificationRequests(const IMENotificationRequests& aRequests)
+{
+ if (NS_WARN_IF(!mPuppetWidget)) {
+ return IPC_OK();
+ }
+
+ mPuppetWidget->HandleReplyIMENotificationRequests(aRequests);
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
TabChild::RecvSwappedWithOtherRemoteLoader(const IPCTabContext& aContext)
{
nsCOMPtr<nsIDocShell> ourDocShell = do_GetInterface(WebNavigation());
if (NS_WARN_IF(!ourDocShell)) {
return IPC_OK();
}
nsCOMPtr<nsPIDOMWindowOuter> ourWindow = ourDocShell->GetWindow();
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -433,16 +433,18 @@ public:
virtual mozilla::ipc::IPCResult RecvLoadRemoteScript(const nsString& aURL,
const bool& aRunInGlobalScope) override;
virtual mozilla::ipc::IPCResult RecvAsyncMessage(const nsString& aMessage,
InfallibleTArray<CpowEntry>&& aCpows,
const IPC::Principal& aPrincipal,
const ClonedMessageData& aData) override;
+ virtual mozilla::ipc::IPCResult
+ RecvReplyIMENotificationRequests(const IMENotificationRequests& aRequests) override;
virtual mozilla::ipc::IPCResult
RecvSwappedWithOtherRemoteLoader(const IPCTabContext& aContext) override;
virtual PDocAccessibleChild*
AllocPDocAccessibleChild(PDocAccessibleChild*, const uint64_t&,
const uint32_t&, const IAccessibleHolder&) override;
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -1684,31 +1684,42 @@ TabParent::RecvHideTooltip()
}
xulBrowserWindow->HideTooltip();
return IPC_OK();
}
mozilla::ipc::IPCResult
TabParent::RecvNotifyIMEFocus(const ContentCache& aContentCache,
- const IMENotification& aIMENotification,
- IMENotificationRequests* aRequests)
+ const IMENotification& aIMENotification)
{
+ if (mIsDestroyed) {
+ return IPC_OK();
+ }
+
nsCOMPtr<nsIWidget> widget = GetWidget();
if (!widget) {
- *aRequests = IMENotificationRequests();
+ if (!SendReplyIMENotificationRequests(IMENotificationRequests())) {
+ NS_WARNING("Failed to SendReplyIMENotificationRequests.");
+ }
return IPC_OK();
}
mContentCache.AssignContent(aContentCache, widget, &aIMENotification);
IMEStateManager::NotifyIME(aIMENotification, widget, true);
+ IMENotificationRequests requests;
if (aIMENotification.mMessage == NOTIFY_IME_OF_FOCUS) {
- *aRequests = widget->IMENotificationRequestsRef();
+ requests = widget->IMENotificationRequestsRef();
}
+
+ if (!SendReplyIMENotificationRequests(requests)) {
+ NS_WARNING("Failed to SendReplyIMENotificationRequests.");
+ }
+
return IPC_OK();
}
mozilla::ipc::IPCResult
TabParent::RecvNotifyIMETextChange(const ContentCache& aContentCache,
const IMENotification& aIMENotification)
{
nsCOMPtr<nsIWidget> widget = GetWidget();
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -198,20 +198,19 @@ public:
const IPC::Principal& aPrincipal,
nsTArray<ipc::StructuredCloneData>* aRetVal) override;
virtual mozilla::ipc::IPCResult RecvAsyncMessage(const nsString& aMessage,
InfallibleTArray<CpowEntry>&& aCpows,
const IPC::Principal& aPrincipal,
const ClonedMessageData& aData) override;
- virtual mozilla::ipc::IPCResult
+virtual mozilla::ipc::IPCResult
RecvNotifyIMEFocus(const ContentCache& aContentCache,
- const widget::IMENotification& aEventMessage,
- widget::IMENotificationRequests* aRequests) override;
+ const widget::IMENotification& aEventMessage) override;
virtual mozilla::ipc::IPCResult
RecvNotifyIMETextChange(const ContentCache& aContentCache,
const widget::IMENotification& aEventMessage) override;
virtual mozilla::ipc::IPCResult
RecvNotifyIMECompositionUpdate(const ContentCache& aContentCache,
const widget::IMENotification& aEventMessage) override;
--- a/ipc/ipdl/sync-messages.ini
+++ b/ipc/ipdl/sync-messages.ini
@@ -816,18 +816,16 @@ description =
[PBrowser::SyncMessage]
description =
[PBrowser::PPluginWidget]
description =
[PBrowser::GetWidgetNativeData]
description =
[PBrowser::DispatchFocusToTopLevelWindow]
description =
-[PBrowser::NotifyIMEFocus]
-description =
[PBrowser::NotifyIMEMouseButtonEvent]
description =
[PBrowser::RequestIMEToCommitComposition]
description =
[PBrowser::StartPluginIME]
description =
[PBrowser::GetInputContext]
description =
--- a/widget/IMEData.h
+++ b/widget/IMEData.h
@@ -46,17 +46,21 @@ struct IMENotificationRequests final
// NOTIFY_MOUSE_BUTTON_EVENT_ON_CHAR is used when mouse button is pressed
// or released on a character in the focused editor. The notification is
// notified to IME as a mouse event. If it's consumed by IME, NotifyIME()
// returns NS_SUCCESS_EVENT_CONSUMED. Otherwise, it returns NS_OK if it's
// handled without any error.
NOTIFY_MOUSE_BUTTON_EVENT_ON_CHAR = 1 << 3,
// NOTE: NOTIFY_DURING_DEACTIVE isn't supported in environments where two
// or more compositions are possible. E.g., Mac and Linux (GTK).
- NOTIFY_DURING_DEACTIVE = 1 << 7
+ NOTIFY_DURING_DEACTIVE = 1 << 7,
+
+ NOTIFY_ALL = NOTIFY_TEXT_CHANGE |
+ NOTIFY_POSITION_CHANGE |
+ NOTIFY_MOUSE_BUTTON_EVENT_ON_CHAR,
};
IMENotificationRequests()
: mWantUpdates(NOTIFY_NOTHING)
{
}
explicit IMENotificationRequests(Notifications aWantUpdates)
@@ -102,17 +106,17 @@ struct IMENotificationRequests final
{
return !!(mWantUpdates & NOTIFY_DURING_DEACTIVE);
}
Notifications mWantUpdates;
};
/**
- * Contains IMEStatus plus information about the current
+ * Contains IMEStatus plus information about the current
* input context that the IME can use as hints if desired.
*/
struct IMEState final
{
/**
* IME enabled states, the mEnabled value of
* SetInputContext()/GetInputContext() should be one value of following
@@ -764,17 +768,17 @@ struct IMENotification final
}
uint32_t NewLength() const
{
MOZ_ASSERT(IsValid());
return mAddedEndOffset - mStartOffset;
}
// Positive if text is added. Negative if text is removed.
- int64_t Difference() const
+ int64_t Difference() const
{
return mAddedEndOffset - mRemovedEndOffset;
}
bool IsInInt32Range() const
{
MOZ_ASSERT(IsValid());
return mStartOffset <= INT32_MAX &&
--- a/widget/PuppetWidget.cpp
+++ b/widget/PuppetWidget.cpp
@@ -23,16 +23,17 @@
#include "mozilla/TextEvents.h"
#include "mozilla/Unused.h"
#include "BasicLayers.h"
#include "PuppetWidget.h"
#include "nsContentUtils.h"
#include "nsIWidgetListener.h"
#include "imgIContainer.h"
#include "nsView.h"
+#include "nsPrintfCString.h"
using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::hal;
using namespace mozilla::gfx;
using namespace mozilla::layers;
using namespace mozilla::widget;
@@ -512,17 +513,17 @@ PuppetWidget::ClearNativeTouchSequence(n
{
AutoObserverNotifier notifier(aObserver, "cleartouch");
if (!mTabChild) {
return NS_ERROR_FAILURE;
}
mTabChild->SendClearNativeTouchSequence(notifier.SaveObserver());
return NS_OK;
}
-
+
void
PuppetWidget::SetConfirmedTargetAPZC(
uint64_t aInputBlockId,
const nsTArray<ScrollableLayerGuid>& aTargets) const
{
if (mTabChild) {
mTabChild->SetTargetAPZC(aInputBlockId, aTargets);
}
@@ -797,24 +798,32 @@ PuppetWidget::NotifyIMEOfFocusChange(con
return NS_ERROR_FAILURE;
}
}
} else {
// When IME loses focus, we don't need to store anything.
mContentCache.Clear();
}
- mIMENotificationRequestsOfParent = IMENotificationRequests();
- if (!mTabChild->SendNotifyIMEFocus(mContentCache, aIMENotification,
- &mIMENotificationRequestsOfParent)) {
+ mIMENotificationRequestsOfParent =
+ IMENotificationRequests(IMENotificationRequests::NOTIFY_ALL);
+ if (!mTabChild->SendNotifyIMEFocus(mContentCache, aIMENotification)) {
return NS_ERROR_FAILURE;
}
+
return NS_OK;
}
+void
+PuppetWidget::HandleReplyIMENotificationRequests(
+ const IMENotificationRequests& aRequests)
+{
+ mIMENotificationRequestsOfParent = aRequests;
+}
+
nsresult
PuppetWidget::NotifyIMEOfCompositionUpdate(
const IMENotification& aIMENotification)
{
if (NS_WARN_IF(!mTabChild)) {
return NS_ERROR_FAILURE;
}
@@ -872,17 +881,17 @@ PuppetWidget::NotifyIMEOfSelectionChange
// available.
if (NS_WARN_IF(mInputContext.mIMEState.mEnabled == IMEState::PLUGIN)) {
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(
- this,
+ this,
aIMENotification.mSelectionChangeData.mOffset,
aIMENotification.mSelectionChangeData.Length(),
aIMENotification.mSelectionChangeData.mReversed,
aIMENotification.mSelectionChangeData.GetWritingMode());
mTabChild->SendNotifyIMESelection(mContentCache, aIMENotification);
return NS_OK;
--- a/widget/PuppetWidget.h
+++ b/widget/PuppetWidget.h
@@ -284,16 +284,19 @@ public:
const FrameMetrics::ViewID& aViewId,
const CSSRect& aRect,
const uint32_t& aFlags) override;
virtual bool HasPendingInputEvent() override;
void HandledWindowedPluginKeyEvent(const NativeEventData& aKeyEventData,
bool aIsConsumed);
+
+ void HandleReplyIMENotificationRequests(const IMENotificationRequests& aRequests);
+
virtual nsresult OnWindowedPluginKeyEvent(
const NativeEventData& aKeyEventData,
nsIKeyEventInPluginCallback* aCallback) override;
virtual void LookUpDictionary(
const nsAString& aText,
const nsTArray<mozilla::FontRange>& aFontRangeArray,
const bool aIsVertical,