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 |