diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js
index edadc5fd4fc9..5311322719a7 100644
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -3847,6 +3847,12 @@ pref("mousewheel.system_scroll_override_on_root_content.enabled", false);
pref("ui.key.menuAccessKeyFocuses", true);
+#if MOZ_WIDGET_GTK == 2
+pref("intl.ime.use_simple_context_on_password_field", true);
+#else
+pref("intl.ime.use_simple_context_on_password_field", false);
+#endif
+
# XP_UNIX
#endif
#endif
diff --git a/widget/gtk/nsGtkIMModule.cpp b/widget/gtk/nsGtkIMModule.cpp
index 25a11c0dfd4a..be360095e40e 100644
--- a/widget/gtk/nsGtkIMModule.cpp
+++ b/widget/gtk/nsGtkIMModule.cpp
@@ -60,7 +60,10 @@ GetEnabledStateName(uint32_t aState)
}
#endif
+const static bool kUseSimpleContextDefault = MOZ_WIDGET_GTK == 2;
+
nsGtkIMModule* nsGtkIMModule::sLastFocusedModule = nullptr;
+bool nsGtkIMModule::sUseSimpleContext;
nsGtkIMModule::nsGtkIMModule(nsWindow* aOwnerWindow) :
mOwnerWindow(aOwnerWindow), mLastFocusedWindow(nullptr),
@@ -77,6 +80,14 @@ nsGtkIMModule::nsGtkIMModule(nsWindow* aOwnerWindow) :
gGtkIMLog = PR_NewLogModule("nsGtkIMModuleWidgets");
}
#endif
+ static bool sFirstInstance = true;
+ if (sFirstInstance) {
+ sFirstInstance = false;
+ sUseSimpleContext =
+ Preferences::GetBool(
+ "intl.ime.use_simple_context_on_password_field",
+ kUseSimpleContextDefault);
+ }
Init();
}
@@ -117,26 +128,28 @@ nsGtkIMModule::Init()
this);
// Simple context
- mSimpleContext = gtk_im_context_simple_new();
- gtk_im_context_set_client_window(mSimpleContext, gdkWindow);
- g_signal_connect(mSimpleContext, "preedit_changed",
- G_CALLBACK(&nsGtkIMModule::OnChangeCompositionCallback),
- this);
- g_signal_connect(mSimpleContext, "retrieve_surrounding",
- G_CALLBACK(&nsGtkIMModule::OnRetrieveSurroundingCallback),
- this);
- g_signal_connect(mSimpleContext, "delete_surrounding",
- G_CALLBACK(&nsGtkIMModule::OnDeleteSurroundingCallback),
- this);
- g_signal_connect(mSimpleContext, "commit",
- G_CALLBACK(&nsGtkIMModule::OnCommitCompositionCallback),
- this);
- g_signal_connect(mSimpleContext, "preedit_start",
- G_CALLBACK(nsGtkIMModule::OnStartCompositionCallback),
- this);
- g_signal_connect(mSimpleContext, "preedit_end",
- G_CALLBACK(nsGtkIMModule::OnEndCompositionCallback),
- this);
+ if (sUseSimpleContext) {
+ mSimpleContext = gtk_im_context_simple_new();
+ gtk_im_context_set_client_window(mSimpleContext, gdkWindow);
+ g_signal_connect(mSimpleContext, "preedit_changed",
+ G_CALLBACK(&nsGtkIMModule::OnChangeCompositionCallback),
+ this);
+ g_signal_connect(mSimpleContext, "retrieve_surrounding",
+ G_CALLBACK(&nsGtkIMModule::OnRetrieveSurroundingCallback),
+ this);
+ g_signal_connect(mSimpleContext, "delete_surrounding",
+ G_CALLBACK(&nsGtkIMModule::OnDeleteSurroundingCallback),
+ this);
+ g_signal_connect(mSimpleContext, "commit",
+ G_CALLBACK(&nsGtkIMModule::OnCommitCompositionCallback),
+ this);
+ g_signal_connect(mSimpleContext, "preedit_start",
+ G_CALLBACK(nsGtkIMModule::OnStartCompositionCallback),
+ this);
+ g_signal_connect(mSimpleContext, "preedit_end",
+ G_CALLBACK(nsGtkIMModule::OnEndCompositionCallback),
+ this);
+ }
// Dummy context
mDummyContext = gtk_im_multicontext_new();
@@ -568,7 +581,25 @@ nsGtkIMModule::SetInputContext(nsWindow* aCaller,
if (context) {
GtkInputPurpose purpose = GTK_INPUT_PURPOSE_FREE_FORM;
const nsString& inputType = mInputContext.mHTMLInputType;
- if (inputType.EqualsLiteral("password")) {
+ // Password case has difficult issue. Desktop IMEs disable
+ // composition if input-purpose is password.
+ // For disabling IME on |ime-mode: disabled;|, we need to check
+ // mEnabled value instead of inputType value. This hack also
+ // enables composition on
+ // .
+ // This is right behavior of ime-mode on desktop.
+ //
+ // On the other hand, IME for tablet devices may provide a
+ // specific software keyboard for password field. If so,
+ // the behavior might look strange on both:
+ //
+ //
+ //
+ // Temporarily, we should focus on desktop environment for now.
+ // I.e., let's ignore tablet devices for now. When somebody
+ // reports actual trouble on tablet devices, we should try to
+ // look for a way to solve actual problem.
+ if (mInputContext.mIMEState.mEnabled == IMEState::PASSWORD) {
purpose = GTK_INPUT_PURPOSE_PASSWORD;
} else if (inputType.EqualsLiteral("email")) {
purpose = GTK_INPUT_PURPOSE_EMAIL;
@@ -626,7 +657,9 @@ bool
nsGtkIMModule::IsEnabled()
{
return mInputContext.mIMEState.mEnabled == IMEState::ENABLED ||
- mInputContext.mIMEState.mEnabled == IMEState::PLUGIN;
+ mInputContext.mIMEState.mEnabled == IMEState::PLUGIN ||
+ (!sUseSimpleContext &&
+ mInputContext.mIMEState.mEnabled == IMEState::PASSWORD);
}
bool
diff --git a/widget/gtk/nsGtkIMModule.h b/widget/gtk/nsGtkIMModule.h
index 704339d2c1d6..c883791c42ac 100644
--- a/widget/gtk/nsGtkIMModule.h
+++ b/widget/gtk/nsGtkIMModule.h
@@ -106,9 +106,9 @@ protected:
GtkIMContext *mContext;
// mSimpleContext is used for the password field and
- // the |ime-mode: disabled;| editors. These editors disable IME.
- // But dead keys should work. Fortunately, the simple IM context of
- // GTK2 support only them.
+ // the |ime-mode: disabled;| editors if sUseSimpleContext is true.
+ // These editors disable IME. But dead keys should work. Fortunately,
+ // the simple IM context of GTK2 support only them.
GtkIMContext *mSimpleContext;
// mDummyContext is a dummy context and will be used in Focus()
@@ -203,6 +203,11 @@ protected:
// 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.
+ // If true, they use GtkIMContextSimple. Otherwise, not.
+ static bool sUseSimpleContext;
+
// Callback methods for native IME events. These methods should call
// the related instance methods simply.
static gboolean OnRetrieveSurroundingCallback(GtkIMContext *aContext,