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 |