Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(373)

Side by Side Diff: chrome/browser/renderer_host/gtk_im_context_wrapper.cc

Issue 2868033: [Linux]Fix a potential crash issue in gtk_im_context_wrapper.cc (Closed) Base URL: http://src.chromium.org/git/chromium.git
Patch Set: Created 10 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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 #include <algorithm> 10 #include <algorithm>
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
201 // enabled by WebKit. 201 // enabled by WebKit.
202 if (is_enabled_) 202 if (is_enabled_)
203 gtk_im_context_focus_in(context_); 203 gtk_im_context_focus_in(context_);
204 204
205 // context_simple_ is always enabled. 205 // context_simple_ is always enabled.
206 // Actually it doesn't care focus state at all. 206 // Actually it doesn't care focus state at all.
207 gtk_im_context_focus_in(context_simple_); 207 gtk_im_context_focus_in(context_simple_);
208 208
209 // Enables RenderWidget's IME related events, so that we can be notified 209 // Enables RenderWidget's IME related events, so that we can be notified
210 // when WebKit wants to enable or disable IME. 210 // when WebKit wants to enable or disable IME.
211 host_view_->GetRenderWidgetHost()->SetInputMethodActive(true); 211 if (host_view_->GetRenderWidgetHost())
satorux1 2010/06/24 04:19:36 host_view_ is guaranteed not to be NULL, right?
James Su 2010/06/24 04:21:46 Yes. GtkIMContextWrapper object will be destroyed
212 host_view_->GetRenderWidgetHost()->SetInputMethodActive(true);
212 } 213 }
213 214
214 void GtkIMContextWrapper::OnFocusOut() { 215 void GtkIMContextWrapper::OnFocusOut() {
215 if (!is_focused_) 216 if (!is_focused_)
216 return; 217 return;
217 218
218 // Tracks the focused state so that we won't give focus to the 219 // Tracks the focused state so that we won't give focus to the
219 // GtkIMContext object unexpectly. 220 // GtkIMContext object unexpectly.
220 is_focused_ = false; 221 is_focused_ = false;
221 222
222 // Notify the GtkIMContext object of this focus-out event only if IME is 223 // Notify the GtkIMContext object of this focus-out event only if IME is
223 // enabled by WebKit. 224 // enabled by WebKit.
224 if (is_enabled_) { 225 if (is_enabled_) {
225 // To reset the GtkIMContext object and prevent data loss. 226 // To reset the GtkIMContext object and prevent data loss.
226 ConfirmComposition(); 227 ConfirmComposition();
227 gtk_im_context_focus_out(context_); 228 gtk_im_context_focus_out(context_);
228 } 229 }
229 230
230 // To make sure it'll be in correct state when focused in again. 231 // To make sure it'll be in correct state when focused in again.
231 gtk_im_context_reset(context_simple_); 232 gtk_im_context_reset(context_simple_);
232 gtk_im_context_focus_out(context_simple_); 233 gtk_im_context_focus_out(context_simple_);
233 234
234 is_composing_text_ = false; 235 is_composing_text_ = false;
235 236
236 // Disable RenderWidget's IME related events to save bandwidth. 237 // Disable RenderWidget's IME related events to save bandwidth.
237 host_view_->GetRenderWidgetHost()->SetInputMethodActive(false); 238 if (host_view_->GetRenderWidgetHost())
239 host_view_->GetRenderWidgetHost()->SetInputMethodActive(false);
238 } 240 }
239 241
240 void GtkIMContextWrapper::AppendInputMethodsContextMenu(MenuGtk* menu) { 242 void GtkIMContextWrapper::AppendInputMethodsContextMenu(MenuGtk* menu) {
241 std::string label = gtk_util::ConvertAcceleratorsFromWindowsStyle( 243 std::string label = gtk_util::ConvertAcceleratorsFromWindowsStyle(
242 l10n_util::GetStringUTF8(IDS_CONTENT_CONTEXT_INPUT_METHODS_MENU)); 244 l10n_util::GetStringUTF8(IDS_CONTENT_CONTEXT_INPUT_METHODS_MENU));
243 GtkWidget* menuitem = gtk_menu_item_new_with_mnemonic(label.c_str()); 245 GtkWidget* menuitem = gtk_menu_item_new_with_mnemonic(label.c_str());
244 GtkWidget* submenu = gtk_menu_new(); 246 GtkWidget* submenu = gtk_menu_new();
245 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu); 247 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu);
246 gtk_im_multicontext_append_menuitems(GTK_IM_MULTICONTEXT(context_), 248 gtk_im_multicontext_append_menuitems(GTK_IM_MULTICONTEXT(context_),
247 GTK_MENU_SHELL(submenu)); 249 GTK_MENU_SHELL(submenu));
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
337 if (wke->text[0]) { 339 if (wke->text[0]) {
338 wke->type = WebKit::WebInputEvent::Char; 340 wke->type = WebKit::WebInputEvent::Char;
339 wke->skip_in_browser = true; 341 wke->skip_in_browser = true;
340 host_view_->ForwardKeyboardEvent(*wke); 342 host_view_->ForwardKeyboardEvent(*wke);
341 } 343 }
342 } 344 }
343 345
344 void GtkIMContextWrapper::ProcessInputMethodResult(const GdkEventKey* event, 346 void GtkIMContextWrapper::ProcessInputMethodResult(const GdkEventKey* event,
345 bool filtered) { 347 bool filtered) {
346 RenderWidgetHost* host = host_view_->GetRenderWidgetHost(); 348 RenderWidgetHost* host = host_view_->GetRenderWidgetHost();
349 if (!host)
350 return;
351
347 bool committed = false; 352 bool committed = false;
348 // We do commit before preedit change, so that we can optimize some 353 // We do commit before preedit change, so that we can optimize some
349 // unnecessary preedit changes. 354 // unnecessary preedit changes.
350 if (commit_text_.length()) { 355 if (commit_text_.length()) {
351 if (filtered && NeedCommitByForwardingCharEvent()) { 356 if (filtered && NeedCommitByForwardingCharEvent()) {
352 // Send a Char event when we input a composed character without IMEs 357 // Send a Char event when we input a composed character without IMEs
353 // so that this event is to be dispatched to onkeypress() handlers, 358 // so that this event is to be dispatched to onkeypress() handlers,
354 // autofill, etc. 359 // autofill, etc.
355 // Only commit text generated by a filtered key down event can be sent 360 // Only commit text generated by a filtered key down event can be sent
356 // as a Char event, because a unfiltered key down event will probably 361 // as a Char event, because a unfiltered key down event will probably
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
389 } 394 }
390 } 395 }
391 396
392 void GtkIMContextWrapper::ConfirmComposition() { 397 void GtkIMContextWrapper::ConfirmComposition() {
393 if (!is_enabled_) 398 if (!is_enabled_)
394 return; 399 return;
395 400
396 DCHECK(!is_in_key_event_handler_); 401 DCHECK(!is_in_key_event_handler_);
397 402
398 if (is_composing_text_) { 403 if (is_composing_text_) {
399 host_view_->GetRenderWidgetHost()->ImeConfirmComposition(); 404 if (host_view_->GetRenderWidgetHost())
405 host_view_->GetRenderWidgetHost()->ImeConfirmComposition();
400 406
401 // Reset the input method. 407 // Reset the input method.
402 CancelComposition(); 408 CancelComposition();
403 } 409 }
404 } 410 }
405 411
406 void GtkIMContextWrapper::HandleCommit(const string16& text) { 412 void GtkIMContextWrapper::HandleCommit(const string16& text) {
407 // Append the text to the buffer, because commit signal might be fired 413 // Append the text to the buffer, because commit signal might be fired
408 // multiple times when processing a key event. 414 // multiple times when processing a key event.
409 commit_text_.append(text); 415 commit_text_.append(text);
410 // Nothing needs to do, if it's currently in ProcessKeyEvent() 416 // Nothing needs to do, if it's currently in ProcessKeyEvent()
411 // handler, which will send commit text to webkit later. Otherwise, 417 // handler, which will send commit text to webkit later. Otherwise,
412 // we need send it here. 418 // we need send it here.
413 // It's possible that commit signal is fired without a key event, for 419 // It's possible that commit signal is fired without a key event, for
414 // example when user input via a voice or handwriting recognition software. 420 // example when user input via a voice or handwriting recognition software.
415 // In this case, the text must be committed directly. 421 // In this case, the text must be committed directly.
416 if (!is_in_key_event_handler_) 422 if (!is_in_key_event_handler_ && host_view_->GetRenderWidgetHost())
417 host_view_->GetRenderWidgetHost()->ImeConfirmComposition(text); 423 host_view_->GetRenderWidgetHost()->ImeConfirmComposition(text);
418 } 424 }
419 425
420 void GtkIMContextWrapper::HandlePreeditStart() { 426 void GtkIMContextWrapper::HandlePreeditStart() {
421 is_composing_text_ = true; 427 is_composing_text_ = true;
422 } 428 }
423 429
424 void GtkIMContextWrapper::HandlePreeditChanged(const gchar* text, 430 void GtkIMContextWrapper::HandlePreeditChanged(const gchar* text,
425 PangoAttrList* attrs, 431 PangoAttrList* attrs,
426 int cursor_position) { 432 int cursor_position) {
(...skipping 10 matching lines...) Expand all
437 &preedit_selection_end_); 443 &preedit_selection_end_);
438 444
439 // In case we are using a buggy input method which doesn't fire 445 // In case we are using a buggy input method which doesn't fire
440 // "preedit_start" signal. 446 // "preedit_start" signal.
441 if (preedit_text_.length()) 447 if (preedit_text_.length())
442 is_composing_text_ = true; 448 is_composing_text_ = true;
443 449
444 // Nothing needs to do, if it's currently in ProcessKeyEvent() 450 // Nothing needs to do, if it's currently in ProcessKeyEvent()
445 // handler, which will send preedit text to webkit later. 451 // handler, which will send preedit text to webkit later.
446 // Otherwise, we need send it here if it's been changed. 452 // Otherwise, we need send it here if it's been changed.
447 if (!is_in_key_event_handler_) { 453 if (!is_in_key_event_handler_ && host_view_->GetRenderWidgetHost()) {
448 host_view_->GetRenderWidgetHost()->ImeSetComposition( 454 host_view_->GetRenderWidgetHost()->ImeSetComposition(
449 preedit_text_, preedit_underlines_, preedit_selection_start_, 455 preedit_text_, preedit_underlines_, preedit_selection_start_,
450 preedit_selection_end_); 456 preedit_selection_end_);
451 } 457 }
452 } 458 }
453 459
454 void GtkIMContextWrapper::HandlePreeditEnd() { 460 void GtkIMContextWrapper::HandlePreeditEnd() {
455 bool changed = false;
456 if (preedit_text_.length()) { 461 if (preedit_text_.length()) {
457 // The composition session has been finished. 462 // The composition session has been finished.
458 preedit_text_.clear(); 463 preedit_text_.clear();
459 preedit_underlines_.clear(); 464 preedit_underlines_.clear();
460 is_preedit_changed_ = true; 465 is_preedit_changed_ = true;
461 changed = true; 466
467 // If there is still a preedit text when firing "preedit-end" signal,
468 // we need inform webkit to clear it.
469 // It's only necessary when it's not in ProcessKeyEvent ().
470 if (!is_in_key_event_handler_ && host_view_->GetRenderWidgetHost())
471 host_view_->GetRenderWidgetHost()->ImeCancelComposition();
462 } 472 }
463 473
464 // If there is still a preedit text when firing "preedit-end" signal,
465 // we need inform webkit to clear it.
466 // It's only necessary when it's not in ProcessKeyEvent ().
467 if (!is_in_key_event_handler_ && changed)
468 host_view_->GetRenderWidgetHost()->ImeCancelComposition();
469
470 // Don't set is_composing_text_ to false here, because "preedit_end" 474 // Don't set is_composing_text_ to false here, because "preedit_end"
471 // signal may be fired before "commit" signal. 475 // signal may be fired before "commit" signal.
472 } 476 }
473 477
474 void GtkIMContextWrapper::HandleHostViewRealize(GtkWidget* widget) { 478 void GtkIMContextWrapper::HandleHostViewRealize(GtkWidget* widget) {
475 // We should only set im context's client window once, because when setting 479 // We should only set im context's client window once, because when setting
476 // client window.im context may destroy and recreate its internal states and 480 // client window.im context may destroy and recreate its internal states and
477 // objects. 481 // objects.
478 if (widget->window) { 482 if (widget->window) {
479 gtk_im_context_set_client_window(context_, widget->window); 483 gtk_im_context_set_client_window(context_, widget->window);
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
608 } while (pango_attr_iterator_next(iter)); 612 } while (pango_attr_iterator_next(iter));
609 pango_attr_iterator_destroy(iter); 613 pango_attr_iterator_destroy(iter);
610 } 614 }
611 615
612 // Use a black thin underline by default. 616 // Use a black thin underline by default.
613 if (underlines->empty()) { 617 if (underlines->empty()) {
614 underlines->push_back( 618 underlines->push_back(
615 WebKit::WebCompositionUnderline(0, length, SK_ColorBLACK, false)); 619 WebKit::WebCompositionUnderline(0, length, SK_ColorBLACK, false));
616 } 620 }
617 } 621 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698