| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/renderer_host/gtk_im_context_wrapper.h" | 5 #include "chrome/browser/renderer_host/gtk_im_context_wrapper.h" |
| 6 | 6 |
| 7 #include <gdk/gdk.h> | 7 #include <gdk/gdk.h> |
| 8 #include <gdk/gdkkeysyms.h> | 8 #include <gdk/gdkkeysyms.h> |
| 9 #include <gtk/gtk.h> | 9 #include <gtk/gtk.h> |
| 10 | 10 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 44 G_CALLBACK(HandleCommitThunk), this); | 44 G_CALLBACK(HandleCommitThunk), this); |
| 45 | 45 |
| 46 g_signal_connect(context_simple_, "preedit_start", | 46 g_signal_connect(context_simple_, "preedit_start", |
| 47 G_CALLBACK(HandlePreeditStartThunk), this); | 47 G_CALLBACK(HandlePreeditStartThunk), this); |
| 48 g_signal_connect(context_simple_, "preedit_end", | 48 g_signal_connect(context_simple_, "preedit_end", |
| 49 G_CALLBACK(HandlePreeditEndThunk), this); | 49 G_CALLBACK(HandlePreeditEndThunk), this); |
| 50 g_signal_connect(context_simple_, "preedit_changed", | 50 g_signal_connect(context_simple_, "preedit_changed", |
| 51 G_CALLBACK(HandlePreeditChangedThunk), this); | 51 G_CALLBACK(HandlePreeditChangedThunk), this); |
| 52 g_signal_connect(context_simple_, "commit", | 52 g_signal_connect(context_simple_, "commit", |
| 53 G_CALLBACK(HandleCommitThunk), this); | 53 G_CALLBACK(HandleCommitThunk), this); |
| 54 |
| 55 GtkWidget* widget = host_view->native_view(); |
| 56 DCHECK(widget); |
| 57 |
| 58 g_signal_connect(widget, "realize", |
| 59 G_CALLBACK(HandleHostViewRealizeThunk), this); |
| 60 g_signal_connect(widget, "unrealize", |
| 61 G_CALLBACK(HandleHostViewUnrealizeThunk), this); |
| 62 |
| 63 // Set client window if the widget is already realized. |
| 64 HandleHostViewRealize(widget); |
| 54 } | 65 } |
| 55 | 66 |
| 56 GtkIMContextWrapper::~GtkIMContextWrapper() { | 67 GtkIMContextWrapper::~GtkIMContextWrapper() { |
| 57 if (context_) | 68 if (context_) |
| 58 g_object_unref(context_); | 69 g_object_unref(context_); |
| 59 if (context_simple_) | 70 if (context_simple_) |
| 60 g_object_unref(context_simple_); | 71 g_object_unref(context_simple_); |
| 61 } | 72 } |
| 62 | 73 |
| 63 void GtkIMContextWrapper::ProcessKeyEvent(GdkEventKey* event) { | 74 void GtkIMContextWrapper::ProcessKeyEvent(GdkEventKey* event) { |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 186 } | 197 } |
| 187 | 198 |
| 188 void GtkIMContextWrapper::OnFocusIn() { | 199 void GtkIMContextWrapper::OnFocusIn() { |
| 189 if (is_focused_) | 200 if (is_focused_) |
| 190 return; | 201 return; |
| 191 | 202 |
| 192 // Tracks the focused state so that we can give focus to the | 203 // Tracks the focused state so that we can give focus to the |
| 193 // GtkIMContext object correctly later when IME is enabled by WebKit. | 204 // GtkIMContext object correctly later when IME is enabled by WebKit. |
| 194 is_focused_ = true; | 205 is_focused_ = true; |
| 195 | 206 |
| 196 // We should call gtk_im_context_set_client_window() only when this window | |
| 197 // gain (or release) the window focus because an immodule may reset its | |
| 198 // internal status when processing this function. | |
| 199 gtk_im_context_set_client_window(context_, | |
| 200 host_view_->native_view()->window); | |
| 201 | |
| 202 // Notify the GtkIMContext object of this focus-in event only if IME is | 207 // Notify the GtkIMContext object of this focus-in event only if IME is |
| 203 // enabled by WebKit. | 208 // enabled by WebKit. |
| 204 if (is_enabled_) | 209 if (is_enabled_) |
| 205 gtk_im_context_focus_in(context_); | 210 gtk_im_context_focus_in(context_); |
| 206 | 211 |
| 207 // Actually current GtkIMContextSimple implementation doesn't care about | |
| 208 // client window. This line is just for safe. | |
| 209 gtk_im_context_set_client_window(context_simple_, | |
| 210 host_view_->native_view()->window); | |
| 211 | |
| 212 // context_simple_ is always enabled. | 212 // context_simple_ is always enabled. |
| 213 // Actually it doesn't care focus state at all. | 213 // Actually it doesn't care focus state at all. |
| 214 gtk_im_context_focus_in(context_simple_); | 214 gtk_im_context_focus_in(context_simple_); |
| 215 | 215 |
| 216 // Enables RenderWidget's IME related events, so that we can be notified | 216 // Enables RenderWidget's IME related events, so that we can be notified |
| 217 // when WebKit wants to enable or disable IME. | 217 // when WebKit wants to enable or disable IME. |
| 218 host_view_->GetRenderWidgetHost()->ImeSetInputMode(true); | 218 host_view_->GetRenderWidgetHost()->ImeSetInputMode(true); |
| 219 } | 219 } |
| 220 | 220 |
| 221 void GtkIMContextWrapper::OnFocusOut() { | 221 void GtkIMContextWrapper::OnFocusOut() { |
| 222 if (!is_focused_) | 222 if (!is_focused_) |
| 223 return; | 223 return; |
| 224 | 224 |
| 225 // Tracks the focused state so that we won't give focus to the | 225 // Tracks the focused state so that we won't give focus to the |
| 226 // GtkIMContext object unexpectly. | 226 // GtkIMContext object unexpectly. |
| 227 is_focused_ = false; | 227 is_focused_ = false; |
| 228 | 228 |
| 229 // Notify the GtkIMContext object of this focus-out event only if IME is | 229 // Notify the GtkIMContext object of this focus-out event only if IME is |
| 230 // enabled by WebKit. | 230 // enabled by WebKit. |
| 231 if (is_enabled_) { | 231 if (is_enabled_) { |
| 232 // To reset the GtkIMContext object and prevent data loss. | 232 // To reset the GtkIMContext object and prevent data loss. |
| 233 CompleteComposition(); | 233 CompleteComposition(); |
| 234 gtk_im_context_focus_out(context_); | 234 gtk_im_context_focus_out(context_); |
| 235 } | 235 } |
| 236 | 236 |
| 237 // Detach this GtkIMContext object from this window. | |
| 238 gtk_im_context_set_client_window(context_, NULL); | |
| 239 | |
| 240 // To make sure it'll be in correct state when focused in again. | 237 // To make sure it'll be in correct state when focused in again. |
| 241 gtk_im_context_reset(context_simple_); | 238 gtk_im_context_reset(context_simple_); |
| 242 gtk_im_context_focus_out(context_simple_); | 239 gtk_im_context_focus_out(context_simple_); |
| 243 gtk_im_context_set_client_window(context_simple_, NULL); | |
| 244 | 240 |
| 245 // Reset stored IME status. | 241 // Reset stored IME status. |
| 246 is_composing_text_ = false; | 242 is_composing_text_ = false; |
| 247 preedit_text_.clear(); | 243 preedit_text_.clear(); |
| 248 preedit_cursor_position_ = 0; | 244 preedit_cursor_position_ = 0; |
| 249 | 245 |
| 250 // Disable RenderWidget's IME related events to save bandwidth. | 246 // Disable RenderWidget's IME related events to save bandwidth. |
| 251 host_view_->GetRenderWidgetHost()->ImeSetInputMode(false); | 247 host_view_->GetRenderWidgetHost()->ImeSetInputMode(false); |
| 252 } | 248 } |
| 253 | 249 |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 465 // we need inform webkit to clear it. | 461 // we need inform webkit to clear it. |
| 466 // It's only necessary when it's not in ProcessKeyEvent (). | 462 // It's only necessary when it's not in ProcessKeyEvent (). |
| 467 if (!is_in_key_event_handler_ && changed) { | 463 if (!is_in_key_event_handler_ && changed) { |
| 468 host_view_->GetRenderWidgetHost()->ImeCancelComposition(); | 464 host_view_->GetRenderWidgetHost()->ImeCancelComposition(); |
| 469 } | 465 } |
| 470 | 466 |
| 471 // Don't set is_composing_text_ to false here, because "preedit_end" | 467 // Don't set is_composing_text_ to false here, because "preedit_end" |
| 472 // signal may be fired before "commit" signal. | 468 // signal may be fired before "commit" signal. |
| 473 } | 469 } |
| 474 | 470 |
| 471 void GtkIMContextWrapper::HandleHostViewRealize(GtkWidget* widget) { |
| 472 // We should only set im context's client window once, because when setting |
| 473 // client window.im context may destroy and recreate its internal states and |
| 474 // objects. |
| 475 if (widget->window) { |
| 476 gtk_im_context_set_client_window(context_, widget->window); |
| 477 gtk_im_context_set_client_window(context_simple_, widget->window); |
| 478 } |
| 479 } |
| 480 |
| 481 void GtkIMContextWrapper::HandleHostViewUnrealize() { |
| 482 gtk_im_context_set_client_window(context_, NULL); |
| 483 gtk_im_context_set_client_window(context_simple_, NULL); |
| 484 } |
| 485 |
| 475 void GtkIMContextWrapper::HandleCommitThunk( | 486 void GtkIMContextWrapper::HandleCommitThunk( |
| 476 GtkIMContext* context, gchar* text, GtkIMContextWrapper* self) { | 487 GtkIMContext* context, gchar* text, GtkIMContextWrapper* self) { |
| 477 self->HandleCommit(UTF8ToUTF16(text)); | 488 self->HandleCommit(UTF8ToUTF16(text)); |
| 478 } | 489 } |
| 479 | 490 |
| 480 void GtkIMContextWrapper::HandlePreeditStartThunk( | 491 void GtkIMContextWrapper::HandlePreeditStartThunk( |
| 481 GtkIMContext* context, GtkIMContextWrapper* self) { | 492 GtkIMContext* context, GtkIMContextWrapper* self) { |
| 482 self->HandlePreeditStart(); | 493 self->HandlePreeditStart(); |
| 483 } | 494 } |
| 484 | 495 |
| 485 void GtkIMContextWrapper::HandlePreeditChangedThunk( | 496 void GtkIMContextWrapper::HandlePreeditChangedThunk( |
| 486 GtkIMContext* context, GtkIMContextWrapper* self) { | 497 GtkIMContext* context, GtkIMContextWrapper* self) { |
| 487 gchar* text = NULL; | 498 gchar* text = NULL; |
| 488 gint cursor_position = 0; | 499 gint cursor_position = 0; |
| 489 gtk_im_context_get_preedit_string(context, &text, NULL, &cursor_position); | 500 gtk_im_context_get_preedit_string(context, &text, NULL, &cursor_position); |
| 490 self->HandlePreeditChanged(UTF8ToUTF16(text), cursor_position); | 501 self->HandlePreeditChanged(UTF8ToUTF16(text), cursor_position); |
| 491 g_free(text); | 502 g_free(text); |
| 492 } | 503 } |
| 493 | 504 |
| 494 void GtkIMContextWrapper::HandlePreeditEndThunk( | 505 void GtkIMContextWrapper::HandlePreeditEndThunk( |
| 495 GtkIMContext* context, GtkIMContextWrapper* self) { | 506 GtkIMContext* context, GtkIMContextWrapper* self) { |
| 496 self->HandlePreeditEnd(); | 507 self->HandlePreeditEnd(); |
| 497 } | 508 } |
| 509 |
| 510 void GtkIMContextWrapper::HandleHostViewRealizeThunk( |
| 511 GtkWidget* widget, GtkIMContextWrapper* self) { |
| 512 self->HandleHostViewRealize(widget); |
| 513 } |
| 514 |
| 515 void GtkIMContextWrapper::HandleHostViewUnrealizeThunk( |
| 516 GtkWidget* widget, GtkIMContextWrapper* self) { |
| 517 self->HandleHostViewUnrealize(); |
| 518 } |
| OLD | NEW |