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 248291 c6fb4870676c54778577e8ef58bcc0a6731d7b33
parent 248290 1810110176bf29b6bae77cef1815dd9280d168fc
child 248292 d263646f22c02c540b5da295be78a57b081e5f4b
push id28893
push userkwierso@gmail.com
push dateFri, 12 Jun 2015 00:02:58 +0000
treeherdermozilla-central@8cf9d3e497f9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersm_kato
bugs1130937
milestone41.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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