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,