Bug 838001 IME management code should use root widget instead of the nearest widget of the PresContext r=smaug, a=akeybl
authorMasayuki Nakano <masayuki@d-toybox.com>
Wed, 06 Feb 2013 22:26:28 +0900
changeset 122745 d37b7d53494fe4aa3cf07a5676c4e5dc7bc97fd8
parent 122744 62edd3b84353197b2358380ba3c5f0ac8f5f0716
child 122746 3e382bb1481787adb335ff10e816a893c86cf8e5
child 122748 dea6d1763544172586e70ff5bd46265a3e6211d1
child 122750 c514a140e0fc10506add103d516625afeb6dc5e1
push id1
push usersledru@mozilla.com
push dateThu, 04 Dec 2014 17:57:20 +0000
reviewerssmaug, akeybl
bugs838001
milestone19.0
Bug 838001 IME management code should use root widget instead of the nearest widget of the PresContext r=smaug, a=akeybl
content/events/src/TextComposition.cpp
content/events/src/nsIMEStateManager.cpp
layout/base/nsPresContext.cpp
layout/base/nsPresContext.h
--- a/content/events/src/TextComposition.cpp
+++ b/content/events/src/TextComposition.cpp
@@ -102,17 +102,17 @@ TextComposition::NotifyIME(widget::Notif
 TextComposition::CompositionEventDispatcher::CompositionEventDispatcher(
                                                nsPresContext* aPresContext,
                                                nsINode* aEventTarget,
                                                uint32_t aEventMessage,
                                                const nsAString& aData) :
   mPresContext(aPresContext), mEventTarget(aEventTarget),
   mEventMessage(aEventMessage), mData(aData)
 {
-  mWidget = mPresContext->GetNearestWidget();
+  mWidget = mPresContext->GetRootWidget();
 }
 
 NS_IMETHODIMP
 TextComposition::CompositionEventDispatcher::Run()
 {
   if (!mPresContext->GetPresShell() ||
       mPresContext->GetPresShell()->IsDestroying()) {
     return NS_OK; // cannot dispatch any events anymore
--- a/content/events/src/nsIMEStateManager.cpp
+++ b/content/events/src/nsIMEStateManager.cpp
@@ -119,17 +119,17 @@ nsIMEStateManager::OnDestroyPresContext(
     }
   }
 
   if (aPresContext != sPresContext)
     return NS_OK;
 
   DestroyTextStateManager();
 
-  nsCOMPtr<nsIWidget> widget = sPresContext->GetNearestWidget();
+  nsCOMPtr<nsIWidget> widget = sPresContext->GetRootWidget();
   if (widget) {
     IMEState newState = GetNewIMEState(sPresContext, nullptr);
     InputContextAction action(InputContextAction::CAUSE_UNKNOWN,
                               InputContextAction::LOST_FOCUS);
     SetIMEState(newState, nullptr, widget, action);
   }
   NS_IF_RELEASE(sContent);
   sPresContext = nullptr;
@@ -149,17 +149,17 @@ nsIMEStateManager::OnRemoveContent(nsPre
 
     if (compositionInContent) {
       // Store the composition before accessing the native IME.
       TextComposition storedComposition = *compositionInContent;
       // Try resetting the native IME state.  Be aware, typically, this method
       // is called during the content being removed.  Then, the native
       // composition events which are caused by following APIs are ignored due
       // to unsafe to run script (in PresShell::HandleEvent()).
-      nsCOMPtr<nsIWidget> widget = aPresContext->GetNearestWidget();
+      nsCOMPtr<nsIWidget> widget = aPresContext->GetRootWidget();
       if (widget) {
         nsresult rv =
           storedComposition.NotifyIME(REQUEST_TO_CANCEL_COMPOSITION);
         if (NS_FAILED(rv)) {
           storedComposition.NotifyIME(REQUEST_TO_COMMIT_COMPOSITION);
         }
         // By calling the APIs, the composition may have been finished normally.
         compositionInContent =
@@ -179,17 +179,17 @@ nsIMEStateManager::OnRemoveContent(nsPre
   if (!sPresContext || !sContent ||
       !nsContentUtils::ContentIsDescendantOf(sContent, aContent)) {
     return NS_OK;
   }
 
   DestroyTextStateManager();
 
   // Current IME transaction should commit
-  nsCOMPtr<nsIWidget> widget = sPresContext->GetNearestWidget();
+  nsCOMPtr<nsIWidget> widget = sPresContext->GetRootWidget();
   if (widget) {
     IMEState newState = GetNewIMEState(sPresContext, nullptr);
     InputContextAction action(InputContextAction::CAUSE_UNKNOWN,
                               InputContextAction::LOST_FOCUS);
     SetIMEState(newState, nullptr, widget, action);
   }
 
   NS_IF_RELEASE(sContent);
@@ -211,17 +211,17 @@ nsresult
 nsIMEStateManager::OnChangeFocusInternal(nsPresContext* aPresContext,
                                          nsIContent* aContent,
                                          InputContextAction aAction)
 {
   bool focusActuallyChanging =
     (sContent != aContent || sPresContext != aPresContext);
 
   nsCOMPtr<nsIWidget> oldWidget =
-    sPresContext ? sPresContext->GetNearestWidget() : nullptr;
+    sPresContext ? sPresContext->GetRootWidget() : nullptr;
   if (oldWidget && focusActuallyChanging) {
     // If we're deactivating, we shouldn't commit composition forcibly because
     // the user may want to continue the composition.
     if (aPresContext) {
       NotifyIME(REQUEST_TO_COMMIT_COMPOSITION, oldWidget);
     }
   }
 
@@ -231,17 +231,17 @@ nsIMEStateManager::OnChangeFocusInternal
   }
 
   if (!aPresContext) {
     return NS_OK;
   }
 
   nsCOMPtr<nsIWidget> widget =
     (sPresContext == aPresContext) ? oldWidget.get() :
-                                     aPresContext->GetNearestWidget();
+                                     aPresContext->GetRootWidget();
   if (!widget) {
     return NS_OK;
   }
 
   // Handle secure input mode for password field input.
   bool contentIsPassword = false;
   if (aContent && aContent->GetNameSpaceID() == kNameSpaceID_XHTML) {
     if (aContent->Tag() == nsGkAtoms::input) {
@@ -318,17 +318,17 @@ void
 nsIMEStateManager::OnClickInEditor(nsPresContext* aPresContext,
                                    nsIContent* aContent,
                                    nsIDOMMouseEvent* aMouseEvent)
 {
   if (sPresContext != aPresContext || sContent != aContent) {
     return;
   }
 
-  nsCOMPtr<nsIWidget> widget = aPresContext->GetNearestWidget();
+  nsCOMPtr<nsIWidget> widget = aPresContext->GetRootWidget();
   NS_ENSURE_TRUE_VOID(widget);
 
   bool isTrusted;
   nsresult rv = aMouseEvent->GetIsTrusted(&isTrusted);
   NS_ENSURE_SUCCESS_VOID(rv);
   if (!isTrusted) {
     return; // ignore untrusted event.
   }
@@ -376,17 +376,17 @@ nsIMEStateManager::OnFocusInEditor(nsPre
 void
 nsIMEStateManager::UpdateIMEState(const IMEState &aNewIMEState,
                                   nsIContent* aContent)
 {
   if (!sPresContext) {
     NS_WARNING("ISM doesn't know which editor has focus");
     return;
   }
-  nsCOMPtr<nsIWidget> widget = sPresContext->GetNearestWidget();
+  nsCOMPtr<nsIWidget> widget = sPresContext->GetRootWidget();
   if (!widget) {
     NS_WARNING("focused widget is not found");
     return;
   }
 
   // If the nsTextStateManager instance isn't managing the editor's current
   // editable root content, the editor frame might be reframed.  We should
   // recreate the instance at that time.
@@ -676,17 +676,17 @@ nsIMEStateManager::NotifyIME(Notificatio
 
 // static
 nsresult
 nsIMEStateManager::NotifyIME(NotificationToIME aNotification,
                              nsPresContext* aPresContext)
 {
   NS_ENSURE_TRUE(aPresContext, NS_ERROR_INVALID_ARG);
 
-  nsIWidget* widget = aPresContext->GetNearestWidget();
+  nsIWidget* widget = aPresContext->GetRootWidget();
   if (!widget) {
     return NS_ERROR_NOT_AVAILABLE;
   }
   return NotifyIME(aNotification, widget);
 }
 
 void
 nsTextStateManager::Init(nsIWidget* aWidget,
@@ -1042,17 +1042,17 @@ void
 nsIMEStateManager::CreateTextStateManager()
 {
   if (sTextStateObserver) {
     NS_WARNING("text state observer has been there already");
     MOZ_ASSERT(sTextStateObserver->IsManaging(sPresContext, sContent));
     return;
   }
 
-  nsCOMPtr<nsIWidget> widget = sPresContext->GetNearestWidget();
+  nsCOMPtr<nsIWidget> widget = sPresContext->GetRootWidget();
   if (!widget) {
     return; // Sometimes, there are no widgets.
   }
 
   // If it's not text ediable, we don't need to create nsTextStateManager.
   if (!IsEditableIMEState(widget)) {
     return;
   }
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -1179,16 +1179,30 @@ nsIWidget*
 nsPresContext::GetNearestWidget(nsPoint* aOffset)
 {
   NS_ENSURE_TRUE(mShell, nullptr);
   nsIFrame* frame = mShell->GetRootFrame();
   NS_ENSURE_TRUE(frame, nullptr);
   return frame->GetView()->GetNearestWidget(aOffset);
 }
 
+nsIWidget*
+nsPresContext::GetRootWidget()
+{
+  NS_ENSURE_TRUE(mShell, nullptr);
+  nsIViewManager* vm = mShell->GetViewManager();
+  if (!vm) {
+    return nullptr;
+  }
+  nsCOMPtr<nsIWidget> widget;
+  nsresult rv = vm->GetRootWidget(getter_AddRefs(widget));
+  NS_ENSURE_SUCCESS(rv, nullptr);
+  return widget.get();
+}
+
 // We may want to replace this with something faster, maybe caching the root prescontext
 nsRootPresContext*
 nsPresContext::GetRootPresContext()
 {
   nsPresContext* pc = this;
   for (;;) {
     nsPresContext* parent = pc->GetParentPresContext();
     if (!parent)
--- a/layout/base/nsPresContext.h
+++ b/layout/base/nsPresContext.h
@@ -208,16 +208,22 @@ public:
    * @param aOffset     If non-null the offset from the origin of the root
    *                    frame's view to the widget's origin (usually positive)
    *                    expressed in appunits of this will be returned in
    *                    aOffset.
    */
   nsIWidget* GetNearestWidget(nsPoint* aOffset = nullptr);
 
   /**
+   * Returns the root widget for this.
+   * Note that the widget is a mediater with IME.
+   */
+  nsIWidget* GetRootWidget();
+
+  /**
    * Return the presentation context for the root of the view manager
    * hierarchy that contains this presentation context, or nullptr if it can't
    * be found (e.g. it's detached).
    */
   nsRootPresContext* GetRootPresContext();
   nsRootPresContext* GetDisplayRootPresContext();
   virtual bool IsRoot() { return false; }