OLD | NEW |
---|---|
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 10 matching lines...) Expand all Loading... | |
21 #endif | 21 #endif |
22 #include "chrome/browser/renderer_host/render_widget_host.h" | 22 #include "chrome/browser/renderer_host/render_widget_host.h" |
23 #include "chrome/browser/renderer_host/render_widget_host_view_gtk.h" | 23 #include "chrome/browser/renderer_host/render_widget_host_view_gtk.h" |
24 #include "chrome/common/native_web_keyboard_event.h" | 24 #include "chrome/common/native_web_keyboard_event.h" |
25 #include "chrome/common/render_messages.h" | 25 #include "chrome/common/render_messages.h" |
26 #include "gfx/gtk_util.h" | 26 #include "gfx/gtk_util.h" |
27 #include "gfx/rect.h" | 27 #include "gfx/rect.h" |
28 #include "grit/generated_resources.h" | 28 #include "grit/generated_resources.h" |
29 #include "third_party/skia/include/core/SkColor.h" | 29 #include "third_party/skia/include/core/SkColor.h" |
30 | 30 |
31 namespace { | |
32 // Copied from third_party/WebKit/WebCore/page/EventHandler.cpp | |
33 // | |
34 // Match key code of composition keydown event on windows. | |
35 // IE sends VK_PROCESSKEY which has value 229; | |
36 // | |
37 // Please refer to following documents for detals: | |
38 // - Virtual-Key Codes | |
39 // http://msdn.microsoft.com/en-us/library/ms645540(VS.85).aspx | |
40 // - How the IME System Works | |
41 // http://msdn.microsoft.com/en-us/library/cc194848.aspx | |
42 // - ImmGetVirtualKey Function | |
43 // http://msdn.microsoft.com/en-us/library/dd318570(VS.85).aspx | |
44 const int kCompositionEventKeyCode = 229; | |
45 } // namespace | |
46 | |
31 GtkIMContextWrapper::GtkIMContextWrapper(RenderWidgetHostViewGtk* host_view) | 47 GtkIMContextWrapper::GtkIMContextWrapper(RenderWidgetHostViewGtk* host_view) |
32 : host_view_(host_view), | 48 : host_view_(host_view), |
33 context_(gtk_im_multicontext_new()), | 49 context_(gtk_im_multicontext_new()), |
34 context_simple_(gtk_im_context_simple_new()), | 50 context_simple_(gtk_im_context_simple_new()), |
35 is_focused_(false), | 51 is_focused_(false), |
36 is_composing_text_(false), | 52 is_composing_text_(false), |
37 is_enabled_(false), | 53 is_enabled_(false), |
38 is_in_key_event_handler_(false), | 54 is_in_key_event_handler_(false), |
39 preedit_selection_start_(0), | 55 preedit_selection_start_(0), |
40 preedit_selection_end_(0), | 56 preedit_selection_end_(0), |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
310 // If there is no composition text and has only one character to be | 326 // If there is no composition text and has only one character to be |
311 // committed, then the character will be send to webkit as a Char event | 327 // committed, then the character will be send to webkit as a Char event |
312 // instead of a confirmed composition text. | 328 // instead of a confirmed composition text. |
313 // It should be fine to handle BMP character only, as non-BMP characters | 329 // It should be fine to handle BMP character only, as non-BMP characters |
314 // can always be committed as confirmed composition text. | 330 // can always be committed as confirmed composition text. |
315 return !is_composing_text_ && commit_text_.length() == 1; | 331 return !is_composing_text_ && commit_text_.length() == 1; |
316 } | 332 } |
317 | 333 |
318 void GtkIMContextWrapper::ProcessFilteredKeyPressEvent( | 334 void GtkIMContextWrapper::ProcessFilteredKeyPressEvent( |
319 NativeWebKeyboardEvent* wke) { | 335 NativeWebKeyboardEvent* wke) { |
320 // Copied from third_party/WebKit/WebCore/page/EventHandler.cpp | |
321 // | |
322 // Match key code of composition keydown event on windows. | |
323 // IE sends VK_PROCESSKEY which has value 229; | |
324 // | |
325 // Please refer to following documents for detals: | |
326 // - Virtual-Key Codes | |
327 // http://msdn.microsoft.com/en-us/library/ms645540(VS.85).aspx | |
328 // - How the IME System Works | |
329 // http://msdn.microsoft.com/en-us/library/cc194848.aspx | |
330 // - ImmGetVirtualKey Function | |
331 // http://msdn.microsoft.com/en-us/library/dd318570(VS.85).aspx | |
332 const int kCompositionEventKeyCode = 229; | |
333 | |
334 // If IME has filtered this event, then replace virtual key code with | 336 // If IME has filtered this event, then replace virtual key code with |
335 // VK_PROCESSKEY. See comment in ProcessKeyEvent() for details. | 337 // VK_PROCESSKEY. See comment in ProcessKeyEvent() for details. |
336 // It's only required for keydown events. | 338 // It's only required for keydown events. |
337 // To emulate windows behavior, when input method is enabled, if the commit | 339 // To emulate windows behavior, when input method is enabled, if the commit |
338 // text can be emulated by a Char event, then don't do this replacement. | 340 // text can be emulated by a Char event, then don't do this replacement. |
339 if (!NeedCommitByForwardingCharEvent()) { | 341 if (!NeedCommitByForwardingCharEvent()) { |
340 wke->windowsKeyCode = kCompositionEventKeyCode; | 342 wke->windowsKeyCode = kCompositionEventKeyCode; |
341 // keyidentifier must be updated accordingly, otherwise this key event may | 343 // keyidentifier must be updated accordingly, otherwise this key event may |
342 // still be processed by webkit. | 344 // still be processed by webkit. |
343 wke->setKeyIdentifierFromWindowsKeyCode(); | 345 wke->setKeyIdentifierFromWindowsKeyCode(); |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
443 | 445 |
444 // Append the text to the buffer, because commit signal might be fired | 446 // Append the text to the buffer, because commit signal might be fired |
445 // multiple times when processing a key event. | 447 // multiple times when processing a key event. |
446 commit_text_.append(text); | 448 commit_text_.append(text); |
447 // Nothing needs to do, if it's currently in ProcessKeyEvent() | 449 // Nothing needs to do, if it's currently in ProcessKeyEvent() |
448 // handler, which will send commit text to webkit later. Otherwise, | 450 // handler, which will send commit text to webkit later. Otherwise, |
449 // we need send it here. | 451 // we need send it here. |
450 // It's possible that commit signal is fired without a key event, for | 452 // It's possible that commit signal is fired without a key event, for |
451 // example when user input via a voice or handwriting recognition software. | 453 // example when user input via a voice or handwriting recognition software. |
452 // In this case, the text must be committed directly. | 454 // In this case, the text must be committed directly. |
453 if (!is_in_key_event_handler_ && host_view_->GetRenderWidgetHost()) | 455 if (!is_in_key_event_handler_ && host_view_->GetRenderWidgetHost()) { |
456 // Workaround http://crbug.com/45478 by sending fake key down/up events. | |
457 NativeWebKeyboardEvent fake_event; | |
458 fake_event.windowsKeyCode = kCompositionEventKeyCode; | |
459 fake_event.skip_in_browser = true; | |
460 fake_event.type = WebKit::WebInputEvent::RawKeyDown; | |
461 host_view_->ForwardKeyboardEvent(fake_event); | |
462 | |
454 host_view_->GetRenderWidgetHost()->ImeConfirmComposition(text); | 463 host_view_->GetRenderWidgetHost()->ImeConfirmComposition(text); |
464 | |
465 fake_event.type = WebKit::WebInputEvent::KeyUp; | |
466 host_view_->ForwardKeyboardEvent(fake_event); | |
467 } | |
455 } | 468 } |
456 | 469 |
457 void GtkIMContextWrapper::HandlePreeditStart() { | 470 void GtkIMContextWrapper::HandlePreeditStart() { |
458 // Ignore preedit related signals triggered by CancelComposition() method. | 471 // Ignore preedit related signals triggered by CancelComposition() method. |
459 if (suppress_next_commit_) | 472 if (suppress_next_commit_) |
460 return; | 473 return; |
461 is_composing_text_ = true; | 474 is_composing_text_ = true; |
462 } | 475 } |
463 | 476 |
464 void GtkIMContextWrapper::HandlePreeditChanged(const gchar* text, | 477 void GtkIMContextWrapper::HandlePreeditChanged(const gchar* text, |
(...skipping 18 matching lines...) Expand all Loading... | |
483 // In case we are using a buggy input method which doesn't fire | 496 // In case we are using a buggy input method which doesn't fire |
484 // "preedit_start" signal. | 497 // "preedit_start" signal. |
485 if (preedit_text_.length()) | 498 if (preedit_text_.length()) |
486 is_composing_text_ = true; | 499 is_composing_text_ = true; |
487 | 500 |
488 // Nothing needs to do, if it's currently in ProcessKeyEvent() | 501 // Nothing needs to do, if it's currently in ProcessKeyEvent() |
489 // handler, which will send preedit text to webkit later. | 502 // handler, which will send preedit text to webkit later. |
490 // Otherwise, we need send it here if it's been changed. | 503 // Otherwise, we need send it here if it's been changed. |
491 if (!is_in_key_event_handler_ && is_composing_text_ && | 504 if (!is_in_key_event_handler_ && is_composing_text_ && |
492 host_view_->GetRenderWidgetHost()) { | 505 host_view_->GetRenderWidgetHost()) { |
506 // Workaround http://crbug.com/45478 by sending fake key down/up events. | |
507 NativeWebKeyboardEvent fake_event; | |
508 fake_event.windowsKeyCode = kCompositionEventKeyCode; | |
509 fake_event.skip_in_browser = true; | |
510 fake_event.type = WebKit::WebInputEvent::RawKeyDown; | |
511 host_view_->ForwardKeyboardEvent(fake_event); | |
Evan Martin
2010/12/13 22:46:00
Since this occurs twice, maybe this could be refac
| |
512 | |
493 host_view_->GetRenderWidgetHost()->ImeSetComposition( | 513 host_view_->GetRenderWidgetHost()->ImeSetComposition( |
494 preedit_text_, preedit_underlines_, preedit_selection_start_, | 514 preedit_text_, preedit_underlines_, preedit_selection_start_, |
495 preedit_selection_end_); | 515 preedit_selection_end_); |
516 | |
517 fake_event.type = WebKit::WebInputEvent::KeyUp; | |
518 host_view_->ForwardKeyboardEvent(fake_event); | |
496 } | 519 } |
497 } | 520 } |
498 | 521 |
499 void GtkIMContextWrapper::HandlePreeditEnd() { | 522 void GtkIMContextWrapper::HandlePreeditEnd() { |
500 if (preedit_text_.length()) { | 523 if (preedit_text_.length()) { |
501 // The composition session has been finished. | 524 // The composition session has been finished. |
502 preedit_text_.clear(); | 525 preedit_text_.clear(); |
503 preedit_underlines_.clear(); | 526 preedit_underlines_.clear(); |
504 is_preedit_changed_ = true; | 527 is_preedit_changed_ = true; |
505 | 528 |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
651 } while (pango_attr_iterator_next(iter)); | 674 } while (pango_attr_iterator_next(iter)); |
652 pango_attr_iterator_destroy(iter); | 675 pango_attr_iterator_destroy(iter); |
653 } | 676 } |
654 | 677 |
655 // Use a black thin underline by default. | 678 // Use a black thin underline by default. |
656 if (underlines->empty()) { | 679 if (underlines->empty()) { |
657 underlines->push_back( | 680 underlines->push_back( |
658 WebKit::WebCompositionUnderline(0, length, SK_ColorBLACK, false)); | 681 WebKit::WebCompositionUnderline(0, length, SK_ColorBLACK, false)); |
659 } | 682 } |
660 } | 683 } |
OLD | NEW |