Bug 1083098 - Allow to handle GTK composition events if given IM context is same as one of our own IM contexts for cleaning up composition state which is being committed asynchronously. r=karlt, a=lsblakk
authorMasayuki Nakano <masayuki@d-toybox.com>
Fri, 24 Oct 2014 02:17:15 +0900
changeset 225804 6459604b7ccc4642a0ad73eb66145c7d77788d55
parent 225803 372443d1753736199bda53d72b024f99e8aee7eb
child 225805 272d21e922037a9d68b5e2265f3436c38a4b636f
push id7187
push userryanvm@gmail.com
push dateFri, 31 Oct 2014 15:59:42 +0000
treeherdermozilla-aurora@272d21e92203 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskarlt, lsblakk
bugs1083098
milestone35.0a2
Bug 1083098 - Allow to handle GTK composition events if given IM context is same as one of our own IM contexts for cleaning up composition state which is being committed asynchronously. r=karlt, a=lsblakk
widget/gtk/nsGtkIMModule.cpp
widget/gtk/nsGtkIMModule.h
--- a/widget/gtk/nsGtkIMModule.cpp
+++ b/widget/gtk/nsGtkIMModule.cpp
@@ -578,16 +578,27 @@ nsGtkIMModule::GetContext()
     }
     if (mInputContext.mIMEState.mEnabled == IMEState::PASSWORD) {
         return mSimpleContext;
     }
     return mDummyContext;
 }
 
 bool
+nsGtkIMModule::IsValidContext(GtkIMContext* aContext) const
+{
+    if (!aContext) {
+        return false;
+    }
+    return aContext == mContext ||
+           aContext == mSimpleContext ||
+           aContext == mDummyContext;
+}
+
+bool
 nsGtkIMModule::IsEnabled()
 {
     return mInputContext.mIMEState.mEnabled == IMEState::ENABLED ||
            mInputContext.mIMEState.mEnabled == IMEState::PLUGIN ||
            (!sUseSimpleContext &&
             mInputContext.mIMEState.mEnabled == IMEState::PASSWORD);
 }
 
@@ -720,17 +731,19 @@ nsGtkIMModule::OnEndCompositionCallback(
 void
 nsGtkIMModule::OnEndCompositionNative(GtkIMContext *aContext)
 {
     PR_LOG(gGtkIMLog, PR_LOG_ALWAYS,
         ("GtkIMModule(%p): OnEndCompositionNative, aContext=%p",
          this, aContext));
 
     // See bug 472635, we should do nothing if IM context doesn't match.
-    if (GetContext() != aContext) {
+    // Note that if this is called after focus move, the context may different
+    // from the result of GetContext().
+    if (!IsValidContext(aContext)) {
         PR_LOG(gGtkIMLog, PR_LOG_ALWAYS,
             ("    FAILED, given context doesn't match, GetContext()=%p",
              GetContext()));
         return;
     }
 
     if (!IsComposing()) {
         // If we already handled the commit event, we should do nothing here.
@@ -752,25 +765,27 @@ nsGtkIMModule::OnChangeCompositionCallba
 void
 nsGtkIMModule::OnChangeCompositionNative(GtkIMContext *aContext)
 {
     PR_LOG(gGtkIMLog, PR_LOG_ALWAYS,
         ("GtkIMModule(%p): OnChangeCompositionNative, aContext=%p",
          this, aContext));
 
     // See bug 472635, we should do nothing if IM context doesn't match.
-    if (GetContext() != aContext) {
+    // Note that if this is called after focus move, the context may different
+    // from the result of GetContext().
+    if (!IsValidContext(aContext)) {
         PR_LOG(gGtkIMLog, PR_LOG_ALWAYS,
             ("    FAILED, given context doesn't match, GetContext()=%p",
              GetContext()));
         return;
     }
 
     nsAutoString compositionString;
-    GetCompositionString(compositionString);
+    GetCompositionString(aContext, compositionString);
     if (!IsComposing() && compositionString.IsEmpty()) {
         mDispatchedCompositionString.Truncate();
         return; // Don't start the composition with empty string.
     }
 
     // Be aware, widget can be gone
     DispatchCompositionChangeEvent(compositionString, false);
 }
@@ -922,22 +937,23 @@ nsGtkIMModule::CommitCompositionBy(const
         return false;
     }
     // We should dispatch the compositionend event here because some IMEs
     // might not fire "preedit_end" native event.
     return DispatchCompositionEnd(); // Be aware, widget can be gone
 }
 
 void
-nsGtkIMModule::GetCompositionString(nsAString &aCompositionString)
+nsGtkIMModule::GetCompositionString(GtkIMContext* aContext,
+                                    nsAString& aCompositionString)
 {
     gchar *preedit_string;
     gint cursor_pos;
     PangoAttrList *feedback_list;
-    gtk_im_context_get_preedit_string(GetContext(), &preedit_string,
+    gtk_im_context_get_preedit_string(aContext, &preedit_string,
                                       &feedback_list, &cursor_pos);
     if (preedit_string && *preedit_string) {
         CopyUTF8toUTF16(preedit_string, aCompositionString);
     } else {
         aCompositionString.Truncate();
     }
 
     PR_LOG(gGtkIMLog, PR_LOG_ALWAYS,
@@ -1567,17 +1583,17 @@ nsGtkIMModule::DeleteText(const int32_t 
         return NS_ERROR_FAILURE;
     }
 
     if (!editorHadCompositionString) {
         return NS_OK;
     }
 
     nsAutoString compositionString;
-    GetCompositionString(compositionString);
+    GetCompositionString(GetContext(), compositionString);
     if (!DispatchCompositionChangeEvent(compositionString, true)) {
         PR_LOG(gGtkIMLog, PR_LOG_ALWAYS,
             ("    FAILED, restoring composition string"));
         return NS_ERROR_FAILURE;
     }
 
     return NS_OK;
 }
--- a/widget/gtk/nsGtkIMModule.h
+++ b/widget/gtk/nsGtkIMModule.h
@@ -159,16 +159,26 @@ protected:
     }
 
     bool EditorHasCompositionString()
     {
         return (mCompositionState ==
                     eCompositionState_CompositionChangeEventDispatched);
     }
 
+    /**
+     * Checks if aContext is valid context for handling composition.
+     *
+     * @param aContext          An IM context which is specified by native
+     *                          composition events.
+     * @return                  true if the context is valid context for
+     *                          handling composition.  Otherwise, false.
+     */
+    bool IsValidContext(GtkIMContext* aContext) const;
+
 #ifdef PR_LOGGING
     const char* GetCompositionStateName()
     {
         switch (mCompositionState) {
             case eCompositionState_NotComposing:
                 return "NotComposing";
             case eCompositionState_CompositionStartDispatched:
                 return "CompositionStartDispatched";
@@ -259,17 +269,18 @@ protected:
     // Initializes the instance.
     void Init();
 
     // Reset the current composition of IME.  All native composition events
     // during this processing are ignored.
     void ResetIME();
 
     // Gets the current composition string by the native APIs.
-    void GetCompositionString(nsAString &aCompositionString);
+    void GetCompositionString(GtkIMContext* aContext,
+                              nsAString& aCompositionString);
 
     // Generates our text range array from current composition string.
     already_AddRefed<mozilla::TextRangeArray> CreateTextRangeArray();
 
     // Sets the offset's cursor position to IME.
     void SetCursorPosition(uint32_t aTargetOffset);
 
     // Queries the current selection offset of the window.