Bug 1423693 - Make IMContextWrapper::Init() resolve actual IM if active IM context ID is "xim" and there is XMODIFIERS env r?m_kato draft
authorMasayuki Nakano <masayuki@d-toybox.com>
Mon, 19 Mar 2018 14:22:52 +0900
changeset 769733 a91fa454f3b7bc45e82e6db0c6629ffe2333e1ec
parent 769726 bfb7edfd0436db388bb9e103b8ad817fc50bfdcf
child 769960 d0a14ffb3617a6da5e7fd632273efcf001db2144
push id103212
push usermasayuki@d-toybox.com
push dateTue, 20 Mar 2018 01:10:33 +0000
reviewersm_kato
bugs1423693
milestone61.0a1
Bug 1423693 - Make IMContextWrapper::Init() resolve actual IM if active IM context ID is "xim" and there is XMODIFIERS env r?m_kato On some Linux environment, GTK_IM_MODULE env may be "xim". Then, actual IM is specified with XMODIFIERS env with "@im=". Therefore, if active IM context ID is xim, IMContextWrapper::Init() needs to look for actual IM name in XMODIFIERS. MozReview-Commit-ID: 1aGjBkF4AQn
widget/gtk/IMContextWrapper.cpp
--- a/widget/gtk/IMContextWrapper.cpp
+++ b/widget/gtk/IMContextWrapper.cpp
@@ -334,54 +334,73 @@ IMContextWrapper::Init()
     g_signal_connect(mContext, "delete_surrounding",
         G_CALLBACK(IMContextWrapper::OnDeleteSurroundingCallback), this);
     g_signal_connect(mContext, "commit",
         G_CALLBACK(IMContextWrapper::OnCommitCompositionCallback), this);
     g_signal_connect(mContext, "preedit_start",
         G_CALLBACK(IMContextWrapper::OnStartCompositionCallback), this);
     g_signal_connect(mContext, "preedit_end",
         G_CALLBACK(IMContextWrapper::OnEndCompositionCallback), this);
-    nsDependentCString contextID;
+    nsDependentCSubstring im;
     const char* contextIDChar =
         gtk_im_multicontext_get_context_id(GTK_IM_MULTICONTEXT(mContext));
+    const char* xmodifiersChar = PR_GetEnv("XMODIFIERS");
     if (contextIDChar) {
-        contextID.Rebind(contextIDChar);
+        im.Rebind(contextIDChar, strlen(contextIDChar));
+        // If the context is XIM, actual engine must be specified with
+        // |XMODIFIERS=@im=foo|.
+        if (im.EqualsLiteral("xim") && xmodifiersChar) {
+            nsDependentCString xmodifiers(xmodifiersChar);
+            int32_t atIMValueStart = xmodifiers.Find("@im=") + 4;
+            if (atIMValueStart >= 4 &&
+                xmodifiers.Length() > static_cast<size_t>(atIMValueStart)) {
+                int32_t atIMValueEnd =
+                    xmodifiers.Find("@", false, atIMValueStart);
+                if (atIMValueEnd > atIMValueStart) {
+                    im.Rebind(xmodifiersChar + atIMValueStart,
+                              atIMValueEnd - atIMValueStart);
+                } else if (atIMValueEnd == kNotFound) {
+                    im.Rebind(xmodifiersChar + atIMValueStart,
+                              strlen(xmodifiersChar) - atIMValueStart);
+                }
+            }
+        }
     }
-    if (contextID.EqualsLiteral("ibus")) {
+    if (im.EqualsLiteral("ibus")) {
         mIMContextID = IMContextID::eIBus;
         mIsIMInAsyncKeyHandlingMode = !IsIBusInSyncMode();
         // Although ibus has key snooper mode, it's forcibly disabled on Firefox
         // in default settings by its whitelist since we always send key events
         // to IME before handling shortcut keys.  The whitelist can be
         // customized with env, IBUS_NO_SNOOPER_APPS, but we don't need to
         // support such rare cases for reducing maintenance cost.
         mIsKeySnooped = false;
-    } else if (contextID.EqualsLiteral("fcitx")) {
+    } else if (im.EqualsLiteral("fcitx")) {
         mIMContextID = IMContextID::eFcitx;
         mIsIMInAsyncKeyHandlingMode = !IsFcitxInSyncMode();
         // Although Fcitx has key snooper mode similar to ibus, it's also
         // disabled on Firefox in default settings by its whitelist.  The
         // whitelist can be customized with env, IBUS_NO_SNOOPER_APPS or
         // FCITX_NO_SNOOPER_APPS, but we don't need to support such rare cases
         // for reducing maintenance cost.
         mIsKeySnooped = false;
-    } else if (contextID.EqualsLiteral("uim")) {
+    } else if (im.EqualsLiteral("uim")) {
         mIMContextID = IMContextID::eUim;
         mIsIMInAsyncKeyHandlingMode = false;
         // We cannot know if uim uses key snooper since it's build option of
         // uim.  Therefore, we need to retrieve the consideration from the
         // pref for making users and distributions allowed to choose their
         // preferred value.
         mIsKeySnooped =
             Preferences::GetBool("intl.ime.hack.uim.using_key_snooper", true);
-    } else if (contextID.EqualsLiteral("scim")) {
+    } else if (im.EqualsLiteral("scim")) {
         mIMContextID = IMContextID::eScim;
         mIsIMInAsyncKeyHandlingMode = false;
         mIsKeySnooped = false;
-    } else if (contextID.EqualsLiteral("iiim")) {
+    } else if (im.EqualsLiteral("iiim")) {
         mIMContextID = IMContextID::eIIIMF;
         mIsIMInAsyncKeyHandlingMode = false;
         mIsKeySnooped = false;
     } else {
         mIMContextID = IMContextID::eUnknown;
         mIsIMInAsyncKeyHandlingMode = false;
         mIsKeySnooped = false;
     }
@@ -410,22 +429,23 @@ IMContextWrapper::Init()
             this);
     }
 
     // Dummy context
     mDummyContext = gtk_im_multicontext_new();
     gtk_im_context_set_client_window(mDummyContext, gdkWindow);
 
     MOZ_LOG(gGtkIMLog, LogLevel::Info,
-        ("0x%p Init(), mOwnerWindow=%p, mContext=%p (%s), "
+        ("0x%p Init(), mOwnerWindow=%p, mContext=%p (im=\"%s\"), "
          "mIsIMInAsyncKeyHandlingMode=%s, mIsKeySnooped=%s, "
-         "mSimpleContext=%p, mDummyContext=%p",
-         this, mOwnerWindow, mContext, contextID.get(),
+         "mSimpleContext=%p, mDummyContext=%p, contextIDChar=\"%s\", "
+         "xmodifiersChar=\"%s\"",
+         this, mOwnerWindow, mContext, nsAutoCString(im).get(),
          ToChar(mIsIMInAsyncKeyHandlingMode), ToChar(mIsKeySnooped),
-         mSimpleContext, mDummyContext));
+         mSimpleContext, mDummyContext, contextIDChar, xmodifiersChar));
 }
 
 IMContextWrapper::~IMContextWrapper()
 {
     if (this == sLastFocusedContext) {
         sLastFocusedContext = nullptr;
     }
     MOZ_LOG(gGtkIMLog, LogLevel::Info,