Bug 1130937 part.3 nsGtkIMModule should adjust candidate window position when layout is changed r=m_kato
authorMasayuki Nakano <masayuki@d-toybox.com>
Thu, 11 Jun 2015 19:50:15 +0900
changeset 267829 c6fb4870676c54778577e8ef58bcc0a6731d7b33
parent 267828 1810110176bf29b6bae77cef1815dd9280d168fc
child 267830 d263646f22c02c540b5da295be78a57b081e5f4b
push id8157
push userjlund@mozilla.com
push dateMon, 29 Jun 2015 20:36:23 +0000
treeherdermozilla-aurora@d480e05bd276 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersm_kato
bugs1130937
milestone41.0a1
Bug 1130937 part.3 nsGtkIMModule should adjust candidate window position when layout is changed r=m_kato
widget/gtk/nsGtkIMModule.cpp
widget/gtk/nsGtkIMModule.h
widget/gtk/nsWindow.cpp
--- a/widget/gtk/nsGtkIMModule.cpp
+++ b/widget/gtk/nsGtkIMModule.cpp
@@ -110,16 +110,17 @@ nsGtkIMModule::nsGtkIMModule(nsWindow* a
     , mSimpleContext(nullptr)
     , mDummyContext(nullptr)
     , mComposingContext(nullptr)
     , mCompositionStart(UINT32_MAX)
     , mProcessingKeyEvent(nullptr)
     , mCompositionState(eCompositionState_NotComposing)
     , mIsIMFocused(false)
     , mIsDeletingSurrounding(false)
+    , mLayoutChanged(false)
 {
     if (!gGtkIMLog) {
         gGtkIMLog = PR_NewLogModule("nsGtkIMModuleWidgets");
     }
     static bool sFirstInstance = true;
     if (sFirstInstance) {
         sFirstInstance = false;
         sUseSimpleContext =
@@ -524,23 +525,38 @@ nsGtkIMModule::EndIMEComposition(nsWindo
     //     environments.  We should emulate focus change too because some IMEs
     //     may commit or cancel composition at blur.
     ResetIME();
 
     return NS_OK;
 }
 
 void
+nsGtkIMModule::OnLayoutChange()
+{
+    if (MOZ_UNLIKELY(IsDestroyed())) {
+        return;
+    }
+
+    SetCursorPosition(GetActiveContext());
+    mLayoutChanged = true;
+}
+
+void
 nsGtkIMModule::OnUpdateComposition()
 {
     if (MOZ_UNLIKELY(IsDestroyed())) {
         return;
     }
 
-    SetCursorPosition(GetActiveContext());
+    // If we've already set candidate window position, we don't need to update
+    // the position with update composition notification.
+    if (!mLayoutChanged) {
+        SetCursorPosition(GetActiveContext());
+    }
 }
 
 void
 nsGtkIMModule::SetInputContext(nsWindow* aCaller,
                                const InputContext* aContext,
                                const InputContextAction* aAction)
 {
     if (MOZ_UNLIKELY(IsDestroyed())) {
@@ -1179,32 +1195,32 @@ nsGtkIMModule::DispatchCompositionChange
       mDispatchedCompositionString = aCompositionString;
 
     compositionChangeEvent.mRanges =
       CreateTextRangeArray(aContext, mDispatchedCompositionString);
     targetOffset += compositionChangeEvent.mRanges->TargetClauseOffset();
 
     mCompositionState = eCompositionState_CompositionChangeEventDispatched;
 
+    // We cannot call SetCursorPosition for e10s-aware.
+    // DispatchEvent is async on e10s, so composition rect isn't updated now
+    // on tab parent.
+    mLayoutChanged = false;
+    mCompositionTargetRange.mOffset = targetOffset;
+    mCompositionTargetRange.mLength =
+        compositionChangeEvent.mRanges->TargetClauseLength();
+
     mLastFocusedWindow->DispatchEvent(&compositionChangeEvent, status);
     if (lastFocusedWindow->IsDestroyed() ||
         lastFocusedWindow != mLastFocusedWindow) {
         MOZ_LOG(gGtkIMLog, LogLevel::Info,
             ("    NOTE, the focused widget was destroyed/changed by "
              "compositionchange event"));
         return false;
     }
-
-    // We cannot call SetCursorPosition for e10s-aware.
-    // DispatchEvent is async on e10s, so composition rect isn't updated now
-    // on tab parent.
-    mCompositionTargetRange.mOffset = targetOffset;
-    mCompositionTargetRange.mLength =
-        compositionChangeEvent.mRanges->TargetClauseLength();
-
     return true;
 }
 
 bool
 nsGtkIMModule::DispatchCompositionCommitEvent(
                    GtkIMContext* aContext,
                    const nsAString* aCommitString)
 {
--- a/widget/gtk/nsGtkIMModule.h
+++ b/widget/gtk/nsGtkIMModule.h
@@ -64,16 +64,17 @@ public:
 
     // IME related nsIWidget methods.
     nsresult EndIMEComposition(nsWindow* aCaller);
     void SetInputContext(nsWindow* aCaller,
                          const InputContext* aContext,
                          const InputContextAction* aAction);
     InputContext GetInputContext();
     void OnUpdateComposition();
+    void OnLayoutChange();
 
 protected:
     ~nsGtkIMModule();
 
     // Owner of an instance of this class. This should be top level window.
     // The owner window must release the contexts when it's destroyed because
     // the IME contexts need the native window.  If OnDestroyWindow() is called
     // with the owner window, it'll release IME contexts.  Otherwise, it'll
@@ -250,16 +251,19 @@ protected:
     // DispatchCompositionStart().  DispatchCompositionStart() dispatches
     // a keydown event if the composition start is caused by a native
     // keypress event.  If this is true, the keydown event has been dispatched.
     // Then, DispatchCompositionStart() doesn't dispatch keydown event.
     bool mKeyDownEventWasSent;
     // mIsDeletingSurrounding is true while OnDeleteSurroundingNative() is
     // trying to delete the surrounding text.
     bool mIsDeletingSurrounding;
+    // mLayoutChanged is true after OnLayoutChange() is called.  This is reset
+    // when NS_COMPOSITION_CHANGE is being dispatched.
+    bool mLayoutChanged;
 
     // sLastFocusedModule is a pointer to the last focused instance of this
     // class.  When a instance is destroyed and sLastFocusedModule refers it,
     // this is cleared.  So, this refers valid pointer always.
     static nsGtkIMModule* sLastFocusedModule;
 
     // sUseSimpleContext indeicates if password editors and editors with
     // |ime-mode: disabled;| should use GtkIMContextSimple.
--- a/widget/gtk/nsWindow.cpp
+++ b/widget/gtk/nsWindow.cpp
@@ -5946,16 +5946,19 @@ nsWindow::NotifyIMEInternal(const IMENot
         case REQUEST_TO_CANCEL_COMPOSITION:
             return mIMModule->EndIMEComposition(this);
         case NOTIFY_IME_OF_FOCUS:
             mIMModule->OnFocusChangeInGecko(true);
             return NS_OK;
         case NOTIFY_IME_OF_BLUR:
             mIMModule->OnFocusChangeInGecko(false);
             return NS_OK;
+        case NOTIFY_IME_OF_POSITION_CHANGE:
+            mIMModule->OnLayoutChange();
+            return NS_OK;
         case NOTIFY_IME_OF_COMPOSITION_UPDATE:
             mIMModule->OnUpdateComposition();
             return NS_OK;
         case NOTIFY_IME_OF_SELECTION_CHANGE:
             mIMModule->OnSelectionChange(this, aIMENotification);
             return NS_OK;
         default:
             return NS_ERROR_NOT_IMPLEMENTED;
@@ -5989,17 +5992,18 @@ nsWindow::GetInputContext()
   }
   return context;
 }
 
 nsIMEUpdatePreference
 nsWindow::GetIMEUpdatePreference()
 {
     nsIMEUpdatePreference updatePreference(
-        nsIMEUpdatePreference::NOTIFY_SELECTION_CHANGE);
+        nsIMEUpdatePreference::NOTIFY_SELECTION_CHANGE |
+        nsIMEUpdatePreference::NOTIFY_POSITION_CHANGE);
     // We shouldn't notify IME of selection change caused by changes of
     // composition string.  Therefore, we don't need to be notified selection
     // changes which are caused by compositionchange events handled.
     updatePreference.DontNotifyChangesCausedByComposition();
     return updatePreference;
 }
 
 bool