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

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

Issue 5787004: [Linux] Workaround issue 45478: IME dysfunctional after BACKSPACE (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rename SendFakeKeyEvent to SendFakeCompositionKeyEvent. Created 10 years 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 | Annotate | Revision Log
« no previous file with comments | « chrome/browser/renderer_host/gtk_im_context_wrapper.h ('k') | 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 10 matching lines...) Expand all
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
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
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 SendFakeCompositionKeyEvent(WebKit::WebInputEvent::RawKeyDown);
454 host_view_->GetRenderWidgetHost()->ImeConfirmComposition(text); 458 host_view_->GetRenderWidgetHost()->ImeConfirmComposition(text);
459 SendFakeCompositionKeyEvent(WebKit::WebInputEvent::KeyUp);
460 }
455 } 461 }
456 462
457 void GtkIMContextWrapper::HandlePreeditStart() { 463 void GtkIMContextWrapper::HandlePreeditStart() {
458 // Ignore preedit related signals triggered by CancelComposition() method. 464 // Ignore preedit related signals triggered by CancelComposition() method.
459 if (suppress_next_commit_) 465 if (suppress_next_commit_)
460 return; 466 return;
461 is_composing_text_ = true; 467 is_composing_text_ = true;
462 } 468 }
463 469
464 void GtkIMContextWrapper::HandlePreeditChanged(const gchar* text, 470 void GtkIMContextWrapper::HandlePreeditChanged(const gchar* text,
(...skipping 18 matching lines...) Expand all
483 // In case we are using a buggy input method which doesn't fire 489 // In case we are using a buggy input method which doesn't fire
484 // "preedit_start" signal. 490 // "preedit_start" signal.
485 if (preedit_text_.length()) 491 if (preedit_text_.length())
486 is_composing_text_ = true; 492 is_composing_text_ = true;
487 493
488 // Nothing needs to do, if it's currently in ProcessKeyEvent() 494 // Nothing needs to do, if it's currently in ProcessKeyEvent()
489 // handler, which will send preedit text to webkit later. 495 // handler, which will send preedit text to webkit later.
490 // Otherwise, we need send it here if it's been changed. 496 // Otherwise, we need send it here if it's been changed.
491 if (!is_in_key_event_handler_ && is_composing_text_ && 497 if (!is_in_key_event_handler_ && is_composing_text_ &&
492 host_view_->GetRenderWidgetHost()) { 498 host_view_->GetRenderWidgetHost()) {
499 // Workaround http://crbug.com/45478 by sending fake key down/up events.
500 SendFakeCompositionKeyEvent(WebKit::WebInputEvent::RawKeyDown);
493 host_view_->GetRenderWidgetHost()->ImeSetComposition( 501 host_view_->GetRenderWidgetHost()->ImeSetComposition(
494 preedit_text_, preedit_underlines_, preedit_selection_start_, 502 preedit_text_, preedit_underlines_, preedit_selection_start_,
495 preedit_selection_end_); 503 preedit_selection_end_);
504 SendFakeCompositionKeyEvent(WebKit::WebInputEvent::KeyUp);
496 } 505 }
497 } 506 }
498 507
499 void GtkIMContextWrapper::HandlePreeditEnd() { 508 void GtkIMContextWrapper::HandlePreeditEnd() {
500 if (preedit_text_.length()) { 509 if (preedit_text_.length()) {
501 // The composition session has been finished. 510 // The composition session has been finished.
502 preedit_text_.clear(); 511 preedit_text_.clear();
503 preedit_underlines_.clear(); 512 preedit_underlines_.clear();
504 is_preedit_changed_ = true; 513 is_preedit_changed_ = true;
505 514
(...skipping 16 matching lines...) Expand all
522 gtk_im_context_set_client_window(context_, widget->window); 531 gtk_im_context_set_client_window(context_, widget->window);
523 gtk_im_context_set_client_window(context_simple_, widget->window); 532 gtk_im_context_set_client_window(context_simple_, widget->window);
524 } 533 }
525 } 534 }
526 535
527 void GtkIMContextWrapper::HandleHostViewUnrealize() { 536 void GtkIMContextWrapper::HandleHostViewUnrealize() {
528 gtk_im_context_set_client_window(context_, NULL); 537 gtk_im_context_set_client_window(context_, NULL);
529 gtk_im_context_set_client_window(context_simple_, NULL); 538 gtk_im_context_set_client_window(context_simple_, NULL);
530 } 539 }
531 540
541 void GtkIMContextWrapper::SendFakeCompositionKeyEvent(
542 WebKit::WebInputEvent::Type type) {
543 NativeWebKeyboardEvent fake_event;
544 fake_event.windowsKeyCode = kCompositionEventKeyCode;
545 fake_event.skip_in_browser = true;
546 fake_event.type = type;
547 host_view_->ForwardKeyboardEvent(fake_event);
548 }
549
532 void GtkIMContextWrapper::HandleCommitThunk( 550 void GtkIMContextWrapper::HandleCommitThunk(
533 GtkIMContext* context, gchar* text, GtkIMContextWrapper* self) { 551 GtkIMContext* context, gchar* text, GtkIMContextWrapper* self) {
534 self->HandleCommit(UTF8ToUTF16(text)); 552 self->HandleCommit(UTF8ToUTF16(text));
535 } 553 }
536 554
537 void GtkIMContextWrapper::HandlePreeditStartThunk( 555 void GtkIMContextWrapper::HandlePreeditStartThunk(
538 GtkIMContext* context, GtkIMContextWrapper* self) { 556 GtkIMContext* context, GtkIMContextWrapper* self) {
539 self->HandlePreeditStart(); 557 self->HandlePreeditStart();
540 } 558 }
541 559
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
651 } while (pango_attr_iterator_next(iter)); 669 } while (pango_attr_iterator_next(iter));
652 pango_attr_iterator_destroy(iter); 670 pango_attr_iterator_destroy(iter);
653 } 671 }
654 672
655 // Use a black thin underline by default. 673 // Use a black thin underline by default.
656 if (underlines->empty()) { 674 if (underlines->empty()) {
657 underlines->push_back( 675 underlines->push_back(
658 WebKit::WebCompositionUnderline(0, length, SK_ColorBLACK, false)); 676 WebKit::WebCompositionUnderline(0, length, SK_ColorBLACK, false));
659 } 677 }
660 } 678 }
OLDNEW
« no previous file with comments | « chrome/browser/renderer_host/gtk_im_context_wrapper.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698