diff options
author | suzhe@chromium.org <suzhe@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-26 15:16:31 +0000 |
---|---|---|
committer | suzhe@chromium.org <suzhe@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-26 15:16:31 +0000 |
commit | 11a6eee1a07a94700be49b8dc3b72e16d6f44db3 (patch) | |
tree | 4496af0b8298994bc1e1d1482ed71e97a1ee6cdf | |
parent | 60aeeae2c236f22833fa9e8c9372227db2595cc1 (diff) | |
download | chromium_src-11a6eee1a07a94700be49b8dc3b72e16d6f44db3.zip chromium_src-11a6eee1a07a94700be49b8dc3b72e16d6f44db3.tar.gz chromium_src-11a6eee1a07a94700be49b8dc3b72e16d6f44db3.tar.bz2 |
Fix issue 19081: Linux: Not able to switch input method correctly in web page using SCIM
This CL fixes issue 19081 by setting im context's client window when host view's native widget is realized rather than focused in.
When setting im context's client window, GtkIMMulticontext will destroy and recreate its slave im context, which will cause this issue.
BUG=19081: Linux: Not able to switch input method correctly in web page using SCIM
TEST=Export GTK_IM_MODULE=scim then open chrome, open www.google.com and place cursor in search box, hit ctrl-space to open SCIM then click scim bar or tray icon and select another input method, then check if input method was switched correct.
Review URL: http://codereview.chromium.org/174217
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@24442 0039d316-1c4b-4281-b951-d872f2087c98
3 files changed, 55 insertions, 18 deletions
diff --git a/chrome/browser/renderer_host/gtk_im_context_wrapper.cc b/chrome/browser/renderer_host/gtk_im_context_wrapper.cc index cc97d14..6381e9b 100644 --- a/chrome/browser/renderer_host/gtk_im_context_wrapper.cc +++ b/chrome/browser/renderer_host/gtk_im_context_wrapper.cc @@ -51,6 +51,17 @@ GtkIMContextWrapper::GtkIMContextWrapper(RenderWidgetHostViewGtk* host_view) G_CALLBACK(HandlePreeditChangedThunk), this); g_signal_connect(context_simple_, "commit", G_CALLBACK(HandleCommitThunk), this); + + GtkWidget* widget = host_view->native_view(); + DCHECK(widget); + + g_signal_connect(widget, "realize", + G_CALLBACK(HandleHostViewRealizeThunk), this); + g_signal_connect(widget, "unrealize", + G_CALLBACK(HandleHostViewUnrealizeThunk), this); + + // Set client window if the widget is already realized. + HandleHostViewRealize(widget); } GtkIMContextWrapper::~GtkIMContextWrapper() { @@ -193,22 +204,11 @@ void GtkIMContextWrapper::OnFocusIn() { // GtkIMContext object correctly later when IME is enabled by WebKit. is_focused_ = true; - // We should call gtk_im_context_set_client_window() only when this window - // gain (or release) the window focus because an immodule may reset its - // internal status when processing this function. - gtk_im_context_set_client_window(context_, - host_view_->native_view()->window); - // Notify the GtkIMContext object of this focus-in event only if IME is // enabled by WebKit. if (is_enabled_) gtk_im_context_focus_in(context_); - // Actually current GtkIMContextSimple implementation doesn't care about - // client window. This line is just for safe. - gtk_im_context_set_client_window(context_simple_, - host_view_->native_view()->window); - // context_simple_ is always enabled. // Actually it doesn't care focus state at all. gtk_im_context_focus_in(context_simple_); @@ -234,13 +234,9 @@ void GtkIMContextWrapper::OnFocusOut() { gtk_im_context_focus_out(context_); } - // Detach this GtkIMContext object from this window. - gtk_im_context_set_client_window(context_, NULL); - // To make sure it'll be in correct state when focused in again. gtk_im_context_reset(context_simple_); gtk_im_context_focus_out(context_simple_); - gtk_im_context_set_client_window(context_simple_, NULL); // Reset stored IME status. is_composing_text_ = false; @@ -472,6 +468,21 @@ void GtkIMContextWrapper::HandlePreeditEnd() { // signal may be fired before "commit" signal. } +void GtkIMContextWrapper::HandleHostViewRealize(GtkWidget* widget) { + // We should only set im context's client window once, because when setting + // client window.im context may destroy and recreate its internal states and + // objects. + if (widget->window) { + gtk_im_context_set_client_window(context_, widget->window); + gtk_im_context_set_client_window(context_simple_, widget->window); + } +} + +void GtkIMContextWrapper::HandleHostViewUnrealize() { + gtk_im_context_set_client_window(context_, NULL); + gtk_im_context_set_client_window(context_simple_, NULL); +} + void GtkIMContextWrapper::HandleCommitThunk( GtkIMContext* context, gchar* text, GtkIMContextWrapper* self) { self->HandleCommit(UTF8ToUTF16(text)); @@ -495,3 +506,13 @@ void GtkIMContextWrapper::HandlePreeditEndThunk( GtkIMContext* context, GtkIMContextWrapper* self) { self->HandlePreeditEnd(); } + +void GtkIMContextWrapper::HandleHostViewRealizeThunk( + GtkWidget* widget, GtkIMContextWrapper* self) { + self->HandleHostViewRealize(widget); +} + +void GtkIMContextWrapper::HandleHostViewUnrealizeThunk( + GtkWidget* widget, GtkIMContextWrapper* self) { + self->HandleHostViewUnrealize(); +} diff --git a/chrome/browser/renderer_host/gtk_im_context_wrapper.h b/chrome/browser/renderer_host/gtk_im_context_wrapper.h index a57286d..86ff0f0 100644 --- a/chrome/browser/renderer_host/gtk_im_context_wrapper.h +++ b/chrome/browser/renderer_host/gtk_im_context_wrapper.h @@ -17,6 +17,7 @@ class Rect; class RenderWidgetHostViewGtk; class NativeWebKeyboardEvent; typedef struct _GtkIMContext GtkIMContext; +typedef struct _GtkWidget GtkWidget; // This class is a convenience wrapper for GtkIMContext. // It creates and manages two GtkIMContext instances, one is GtkIMMulticontext, @@ -68,6 +69,14 @@ class GtkIMContextWrapper { // Real code of "preedit-end" signal handler. void HandlePreeditEnd(); + // Real code of "realize" signal handler, used for setting im context's client + // window. + void HandleHostViewRealize(GtkWidget* widget); + + // Real code of "unrealize" signal handler, used for unsetting im context's + // client window. + void HandleHostViewUnrealize(); + // Signal handlers of GtkIMContext object. static void HandleCommitThunk(GtkIMContext* context, gchar* text, GtkIMContextWrapper* self); @@ -78,6 +87,12 @@ class GtkIMContextWrapper { static void HandlePreeditEndThunk(GtkIMContext* context, GtkIMContextWrapper* self); + // Signal handlers connecting to |host_view_|'s native view widget. + static void HandleHostViewRealizeThunk(GtkWidget* widget, + GtkIMContextWrapper* self); + static void HandleHostViewUnrealizeThunk(GtkWidget* widget, + GtkIMContextWrapper* self); + // The parent object. RenderWidgetHostViewGtk* host_view_; diff --git a/chrome/browser/renderer_host/render_widget_host_view_gtk.cc b/chrome/browser/renderer_host/render_widget_host_view_gtk.cc index 2353bb9..7516971 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_gtk.cc +++ b/chrome/browser/renderer_host/render_widget_host_view_gtk.cc @@ -85,9 +85,6 @@ class RenderWidgetHostViewGtkWidget { g_signal_connect_after(widget, "scroll-event", G_CALLBACK(MouseScrollEvent), host_view); - // Create GtkIMContext wrapper object. - host_view->im_context_.reset(new GtkIMContextWrapper(host_view)); - return widget; } @@ -300,6 +297,8 @@ RenderWidgetHostViewGtk::~RenderWidgetHostViewGtk() { void RenderWidgetHostViewGtk::InitAsChild() { view_.Own(RenderWidgetHostViewGtkWidget::CreateNewWidget(this)); + // |im_context_| must be created after creating |view_| widget. + im_context_.reset(new GtkIMContextWrapper(this)); plugin_container_manager_.set_host_widget(view_.get()); gtk_widget_show(view_.get()); } @@ -310,6 +309,8 @@ void RenderWidgetHostViewGtk::InitAsPopup( parent_ = parent_host_view->GetNativeView(); GtkWidget* popup = gtk_window_new(GTK_WINDOW_POPUP); view_.Own(RenderWidgetHostViewGtkWidget::CreateNewWidget(this)); + // |im_context_| must be created after creating |view_| widget. + im_context_.reset(new GtkIMContextWrapper(this)); plugin_container_manager_.set_host_widget(view_.get()); gtk_container_add(GTK_CONTAINER(popup), view_.get()); |