| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "content/browser/renderer_host/gtk_im_context_wrapper.h" | 5 #include "content/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 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 276 // enabled by WebKit. | 276 // enabled by WebKit. |
| 277 if (is_enabled_) | 277 if (is_enabled_) |
| 278 gtk_im_context_focus_in(context_); | 278 gtk_im_context_focus_in(context_); |
| 279 | 279 |
| 280 // context_simple_ is always enabled. | 280 // context_simple_ is always enabled. |
| 281 // Actually it doesn't care focus state at all. | 281 // Actually it doesn't care focus state at all. |
| 282 gtk_im_context_focus_in(context_simple_); | 282 gtk_im_context_focus_in(context_simple_); |
| 283 | 283 |
| 284 // Enables RenderWidget's IME related events, so that we can be notified | 284 // Enables RenderWidget's IME related events, so that we can be notified |
| 285 // when WebKit wants to enable or disable IME. | 285 // when WebKit wants to enable or disable IME. |
| 286 if (host_view_->GetRenderWidgetHost()) | 286 if (host_view_->GetRenderWidgetHost()) { |
| 287 static_cast<RenderWidgetHostImpl*>( | 287 RenderWidgetHostImpl::From( |
| 288 host_view_->GetRenderWidgetHost())->SetInputMethodActive(true); | 288 host_view_->GetRenderWidgetHost())->SetInputMethodActive(true); |
| 289 } |
| 289 } | 290 } |
| 290 | 291 |
| 291 void GtkIMContextWrapper::OnFocusOut() { | 292 void GtkIMContextWrapper::OnFocusOut() { |
| 292 if (!is_focused_) | 293 if (!is_focused_) |
| 293 return; | 294 return; |
| 294 | 295 |
| 295 // Tracks the focused state so that we won't give focus to the | 296 // Tracks the focused state so that we won't give focus to the |
| 296 // GtkIMContext object unexpectly. | 297 // GtkIMContext object unexpectly. |
| 297 is_focused_ = false; | 298 is_focused_ = false; |
| 298 | 299 |
| 299 // Notify the GtkIMContext object of this focus-out event only if IME is | 300 // Notify the GtkIMContext object of this focus-out event only if IME is |
| 300 // enabled by WebKit. | 301 // enabled by WebKit. |
| 301 if (is_enabled_) { | 302 if (is_enabled_) { |
| 302 // To reset the GtkIMContext object and prevent data loss. | 303 // To reset the GtkIMContext object and prevent data loss. |
| 303 ConfirmComposition(); | 304 ConfirmComposition(); |
| 304 gtk_im_context_focus_out(context_); | 305 gtk_im_context_focus_out(context_); |
| 305 } | 306 } |
| 306 | 307 |
| 307 // To make sure it'll be in correct state when focused in again. | 308 // To make sure it'll be in correct state when focused in again. |
| 308 gtk_im_context_reset(context_simple_); | 309 gtk_im_context_reset(context_simple_); |
| 309 gtk_im_context_focus_out(context_simple_); | 310 gtk_im_context_focus_out(context_simple_); |
| 310 | 311 |
| 311 is_composing_text_ = false; | 312 is_composing_text_ = false; |
| 312 | 313 |
| 313 // Disable RenderWidget's IME related events to save bandwidth. | 314 // Disable RenderWidget's IME related events to save bandwidth. |
| 314 if (host_view_->GetRenderWidgetHost()) | 315 if (host_view_->GetRenderWidgetHost()) { |
| 315 static_cast<RenderWidgetHostImpl*>( | 316 RenderWidgetHostImpl::From( |
| 316 host_view_->GetRenderWidgetHost())->SetInputMethodActive(false); | 317 host_view_->GetRenderWidgetHost())->SetInputMethodActive(false); |
| 318 } |
| 317 } | 319 } |
| 318 | 320 |
| 319 #if !defined(TOOLKIT_VIEWS) | 321 #if !defined(TOOLKIT_VIEWS) |
| 320 // Not defined for views because the views context menu doesn't | 322 // Not defined for views because the views context menu doesn't |
| 321 // implement input methods yet. | 323 // implement input methods yet. |
| 322 GtkWidget* GtkIMContextWrapper::BuildInputMethodsGtkMenu() { | 324 GtkWidget* GtkIMContextWrapper::BuildInputMethodsGtkMenu() { |
| 323 GtkWidget* submenu = gtk_menu_new(); | 325 GtkWidget* submenu = gtk_menu_new(); |
| 324 gtk_im_multicontext_append_menuitems(GTK_IM_MULTICONTEXT(context_), | 326 gtk_im_multicontext_append_menuitems(GTK_IM_MULTICONTEXT(context_), |
| 325 GTK_MENU_SHELL(submenu)); | 327 GTK_MENU_SHELL(submenu)); |
| 326 return submenu; | 328 return submenu; |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 402 // see WebInputEventFactory::keyboardEvent() for details. | 404 // see WebInputEventFactory::keyboardEvent() for details. |
| 403 if (wke->text[0]) { | 405 if (wke->text[0]) { |
| 404 wke->type = WebKit::WebInputEvent::Char; | 406 wke->type = WebKit::WebInputEvent::Char; |
| 405 wke->skip_in_browser = true; | 407 wke->skip_in_browser = true; |
| 406 host_view_->ForwardKeyboardEvent(*wke); | 408 host_view_->ForwardKeyboardEvent(*wke); |
| 407 } | 409 } |
| 408 } | 410 } |
| 409 | 411 |
| 410 void GtkIMContextWrapper::ProcessInputMethodResult(const GdkEventKey* event, | 412 void GtkIMContextWrapper::ProcessInputMethodResult(const GdkEventKey* event, |
| 411 bool filtered) { | 413 bool filtered) { |
| 412 RenderWidgetHostImpl* host = RenderWidgetHostImpl::FromRWHV(host_view_); | 414 RenderWidgetHostImpl* host = RenderWidgetHostImpl::From( |
| 415 host_view_->GetRenderWidgetHost()); |
| 413 if (!host) | 416 if (!host) |
| 414 return; | 417 return; |
| 415 | 418 |
| 416 bool committed = false; | 419 bool committed = false; |
| 417 // We do commit before preedit change, so that we can optimize some | 420 // We do commit before preedit change, so that we can optimize some |
| 418 // unnecessary preedit changes. | 421 // unnecessary preedit changes. |
| 419 if (commit_text_.length()) { | 422 if (commit_text_.length()) { |
| 420 if (filtered && NeedCommitByForwardingCharEvent()) { | 423 if (filtered && NeedCommitByForwardingCharEvent()) { |
| 421 // Send a Char event when we input a composed character without IMEs | 424 // Send a Char event when we input a composed character without IMEs |
| 422 // so that this event is to be dispatched to onkeypress() handlers, | 425 // so that this event is to be dispatched to onkeypress() handlers, |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 464 } | 467 } |
| 465 } | 468 } |
| 466 | 469 |
| 467 void GtkIMContextWrapper::ConfirmComposition() { | 470 void GtkIMContextWrapper::ConfirmComposition() { |
| 468 if (!is_enabled_) | 471 if (!is_enabled_) |
| 469 return; | 472 return; |
| 470 | 473 |
| 471 DCHECK(!is_in_key_event_handler_); | 474 DCHECK(!is_in_key_event_handler_); |
| 472 | 475 |
| 473 if (is_composing_text_) { | 476 if (is_composing_text_) { |
| 474 if (host_view_->GetRenderWidgetHost()) | 477 if (host_view_->GetRenderWidgetHost()) { |
| 475 static_cast<RenderWidgetHostImpl*>( | 478 RenderWidgetHostImpl::From( |
| 476 host_view_->GetRenderWidgetHost())->ImeConfirmComposition(); | 479 host_view_->GetRenderWidgetHost())->ImeConfirmComposition(); |
| 480 } |
| 477 | 481 |
| 478 // Reset the input method. | 482 // Reset the input method. |
| 479 CancelComposition(); | 483 CancelComposition(); |
| 480 } | 484 } |
| 481 } | 485 } |
| 482 | 486 |
| 483 void GtkIMContextWrapper::HandleCommit(const string16& text) { | 487 void GtkIMContextWrapper::HandleCommit(const string16& text) { |
| 484 if (suppress_next_commit_) { | 488 if (suppress_next_commit_) { |
| 485 suppress_next_commit_ = false; | 489 suppress_next_commit_ = false; |
| 486 return; | 490 return; |
| 487 } | 491 } |
| 488 | 492 |
| 489 // Append the text to the buffer, because commit signal might be fired | 493 // Append the text to the buffer, because commit signal might be fired |
| 490 // multiple times when processing a key event. | 494 // multiple times when processing a key event. |
| 491 commit_text_.append(text); | 495 commit_text_.append(text); |
| 492 // Nothing needs to do, if it's currently in ProcessKeyEvent() | 496 // Nothing needs to do, if it's currently in ProcessKeyEvent() |
| 493 // handler, which will send commit text to webkit later. Otherwise, | 497 // handler, which will send commit text to webkit later. Otherwise, |
| 494 // we need send it here. | 498 // we need send it here. |
| 495 // It's possible that commit signal is fired without a key event, for | 499 // It's possible that commit signal is fired without a key event, for |
| 496 // example when user input via a voice or handwriting recognition software. | 500 // example when user input via a voice or handwriting recognition software. |
| 497 // In this case, the text must be committed directly. | 501 // In this case, the text must be committed directly. |
| 498 if (!is_in_key_event_handler_ && host_view_->GetRenderWidgetHost()) { | 502 if (!is_in_key_event_handler_ && host_view_->GetRenderWidgetHost()) { |
| 499 // Workaround http://crbug.com/45478 by sending fake key down/up events. | 503 // Workaround http://crbug.com/45478 by sending fake key down/up events. |
| 500 SendFakeCompositionKeyEvent(WebKit::WebInputEvent::RawKeyDown); | 504 SendFakeCompositionKeyEvent(WebKit::WebInputEvent::RawKeyDown); |
| 501 static_cast<RenderWidgetHostImpl*>( | 505 RenderWidgetHostImpl::From( |
| 502 host_view_->GetRenderWidgetHost())->ImeConfirmComposition(text); | 506 host_view_->GetRenderWidgetHost())->ImeConfirmComposition(text); |
| 503 SendFakeCompositionKeyEvent(WebKit::WebInputEvent::KeyUp); | 507 SendFakeCompositionKeyEvent(WebKit::WebInputEvent::KeyUp); |
| 504 } | 508 } |
| 505 } | 509 } |
| 506 | 510 |
| 507 void GtkIMContextWrapper::HandlePreeditStart() { | 511 void GtkIMContextWrapper::HandlePreeditStart() { |
| 508 // Ignore preedit related signals triggered by CancelComposition() method. | 512 // Ignore preedit related signals triggered by CancelComposition() method. |
| 509 if (suppress_next_commit_) | 513 if (suppress_next_commit_) |
| 510 return; | 514 return; |
| 511 is_composing_text_ = true; | 515 is_composing_text_ = true; |
| (...skipping 28 matching lines...) Expand all Loading... |
| 540 // Otherwise, we need send it here if it's been changed. | 544 // Otherwise, we need send it here if it's been changed. |
| 541 if (!is_in_key_event_handler_ && is_composing_text_ && | 545 if (!is_in_key_event_handler_ && is_composing_text_ && |
| 542 host_view_->GetRenderWidgetHost()) { | 546 host_view_->GetRenderWidgetHost()) { |
| 543 // Workaround http://crbug.com/45478 by sending fake key down/up events. | 547 // Workaround http://crbug.com/45478 by sending fake key down/up events. |
| 544 SendFakeCompositionKeyEvent(WebKit::WebInputEvent::RawKeyDown); | 548 SendFakeCompositionKeyEvent(WebKit::WebInputEvent::RawKeyDown); |
| 545 // TODO(suzhe): convert both renderer_host and renderer to use | 549 // TODO(suzhe): convert both renderer_host and renderer to use |
| 546 // ui::CompositionText. | 550 // ui::CompositionText. |
| 547 const std::vector<WebKit::WebCompositionUnderline>& underlines = | 551 const std::vector<WebKit::WebCompositionUnderline>& underlines = |
| 548 reinterpret_cast<const std::vector<WebKit::WebCompositionUnderline>&>( | 552 reinterpret_cast<const std::vector<WebKit::WebCompositionUnderline>&>( |
| 549 composition_.underlines); | 553 composition_.underlines); |
| 550 static_cast<RenderWidgetHostImpl*>( | 554 RenderWidgetHostImpl::From( |
| 551 host_view_->GetRenderWidgetHost())->ImeSetComposition( | 555 host_view_->GetRenderWidgetHost())->ImeSetComposition( |
| 552 composition_.text, underlines, composition_.selection.start(), | 556 composition_.text, underlines, composition_.selection.start(), |
| 553 composition_.selection.end()); | 557 composition_.selection.end()); |
| 554 SendFakeCompositionKeyEvent(WebKit::WebInputEvent::KeyUp); | 558 SendFakeCompositionKeyEvent(WebKit::WebInputEvent::KeyUp); |
| 555 } | 559 } |
| 556 } | 560 } |
| 557 | 561 |
| 558 void GtkIMContextWrapper::HandlePreeditEnd() { | 562 void GtkIMContextWrapper::HandlePreeditEnd() { |
| 559 if (composition_.text.length()) { | 563 if (composition_.text.length()) { |
| 560 // The composition session has been finished. | 564 // The composition session has been finished. |
| 561 composition_.Clear(); | 565 composition_.Clear(); |
| 562 is_composition_changed_ = true; | 566 is_composition_changed_ = true; |
| 563 | 567 |
| 564 // If there is still a preedit text when firing "preedit-end" signal, | 568 // If there is still a preedit text when firing "preedit-end" signal, |
| 565 // we need inform webkit to clear it. | 569 // we need inform webkit to clear it. |
| 566 // It's only necessary when it's not in ProcessKeyEvent (). | 570 // It's only necessary when it's not in ProcessKeyEvent (). |
| 567 if (!is_in_key_event_handler_ && host_view_->GetRenderWidgetHost()) | 571 if (!is_in_key_event_handler_ && host_view_->GetRenderWidgetHost()) { |
| 568 static_cast<RenderWidgetHostImpl*>( | 572 RenderWidgetHostImpl::From( |
| 569 host_view_->GetRenderWidgetHost())->ImeCancelComposition(); | 573 host_view_->GetRenderWidgetHost())->ImeCancelComposition(); |
| 574 } |
| 570 } | 575 } |
| 571 | 576 |
| 572 // Don't set is_composing_text_ to false here, because "preedit_end" | 577 // Don't set is_composing_text_ to false here, because "preedit_end" |
| 573 // signal may be fired before "commit" signal. | 578 // signal may be fired before "commit" signal. |
| 574 } | 579 } |
| 575 | 580 |
| 576 gboolean GtkIMContextWrapper::HandleRetrieveSurrounding(GtkIMContext* context) { | 581 gboolean GtkIMContextWrapper::HandleRetrieveSurrounding(GtkIMContext* context) { |
| 577 if (!is_enabled_) | 582 if (!is_enabled_) |
| 578 return TRUE; | 583 return TRUE; |
| 579 | 584 |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 649 | 654 |
| 650 void GtkIMContextWrapper::HandleHostViewRealizeThunk( | 655 void GtkIMContextWrapper::HandleHostViewRealizeThunk( |
| 651 GtkWidget* widget, GtkIMContextWrapper* self) { | 656 GtkWidget* widget, GtkIMContextWrapper* self) { |
| 652 self->HandleHostViewRealize(widget); | 657 self->HandleHostViewRealize(widget); |
| 653 } | 658 } |
| 654 | 659 |
| 655 void GtkIMContextWrapper::HandleHostViewUnrealizeThunk( | 660 void GtkIMContextWrapper::HandleHostViewUnrealizeThunk( |
| 656 GtkWidget* widget, GtkIMContextWrapper* self) { | 661 GtkWidget* widget, GtkIMContextWrapper* self) { |
| 657 self->HandleHostViewUnrealize(); | 662 self->HandleHostViewUnrealize(); |
| 658 } | 663 } |
| OLD | NEW |