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

Side by Side Diff: ui/views/controls/textfield/native_textfield_win.cc

Issue 11305002: Support TSF related event handling on NativeTextField (Closed) Base URL: http://git.chromium.org/chromium/src.git@findbar_fix
Patch Set: Reorder functions Created 8 years, 1 month 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
OLDNEW
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 "ui/views/controls/textfield/native_textfield_win.h" 5 #include "ui/views/controls/textfield/native_textfield_win.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/i18n/case_conversion.h" 9 #include "base/i18n/case_conversion.h"
10 #include "base/i18n/rtl.h" 10 #include "base/i18n/rtl.h"
11 #include "base/string_util.h" 11 #include "base/string_util.h"
12 #include "base/utf_string_conversions.h" 12 #include "base/utf_string_conversions.h"
13 #include "base/win/metro.h" 13 #include "base/win/metro.h"
14 #include "base/win/windows_version.h" 14 #include "base/win/windows_version.h"
15 #include "grit/ui_strings.h" 15 #include "grit/ui_strings.h"
16 #include "skia/ext/skia_utils_win.h" 16 #include "skia/ext/skia_utils_win.h"
17 #include "ui/base/accessibility/accessible_view_state.h" 17 #include "ui/base/accessibility/accessible_view_state.h"
18 #include "ui/base/clipboard/clipboard.h" 18 #include "ui/base/clipboard/clipboard.h"
19 #include "ui/base/clipboard/scoped_clipboard_writer.h" 19 #include "ui/base/clipboard/scoped_clipboard_writer.h"
20 #include "ui/base/events/event.h" 20 #include "ui/base/events/event.h"
21 #include "ui/base/keycodes/keyboard_codes.h" 21 #include "ui/base/keycodes/keyboard_codes.h"
22 #include "ui/base/ime/win/tsf_bridge.h"
22 #include "ui/base/l10n/l10n_util.h" 23 #include "ui/base/l10n/l10n_util.h"
23 #include "ui/base/l10n/l10n_util_win.h" 24 #include "ui/base/l10n/l10n_util_win.h"
24 #include "ui/base/native_theme/native_theme_win.h" 25 #include "ui/base/native_theme/native_theme_win.h"
25 #include "ui/base/range/range.h" 26 #include "ui/base/range/range.h"
26 #include "ui/base/win/mouse_wheel_util.h" 27 #include "ui/base/win/mouse_wheel_util.h"
27 #include "ui/views/controls/label.h" 28 #include "ui/views/controls/label.h"
28 #include "ui/views/controls/menu/menu_item_view.h" 29 #include "ui/views/controls/menu/menu_item_view.h"
29 #include "ui/views/controls/menu/menu_model_adapter.h" 30 #include "ui/views/controls/menu/menu_model_adapter.h"
30 #include "ui/views/controls/menu/menu_runner.h" 31 #include "ui/views/controls/menu/menu_runner.h"
31 #include "ui/views/controls/native/native_view_host.h" 32 #include "ui/views/controls/native/native_view_host.h"
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
88 NativeTextfieldWin::NativeTextfieldWin(Textfield* textfield) 89 NativeTextfieldWin::NativeTextfieldWin(Textfield* textfield)
89 : textfield_(textfield), 90 : textfield_(textfield),
90 tracking_double_click_(false), 91 tracking_double_click_(false),
91 double_click_time_(0), 92 double_click_time_(0),
92 can_discard_mousemove_(false), 93 can_discard_mousemove_(false),
93 contains_mouse_(false), 94 contains_mouse_(false),
94 ime_discard_composition_(false), 95 ime_discard_composition_(false),
95 ime_composition_start_(0), 96 ime_composition_start_(0),
96 ime_composition_length_(0), 97 ime_composition_length_(0),
97 container_view_(new NativeViewHost), 98 container_view_(new NativeViewHost),
98 bg_color_(0) { 99 bg_color_(0),
100 ALLOW_THIS_IN_INITIALIZER_LIST(
101 tsf_event_router_(base::win::IsTsfAwareRequired() ?
102 new ui::TsfEventRouter(this) : NULL)) {
99 if (!loaded_libarary_module_) { 103 if (!loaded_libarary_module_) {
100 // msftedit.dll is RichEdit ver 4.1. 104 // msftedit.dll is RichEdit ver 4.1.
101 // This version is available from WinXP SP1 and has TSF support. 105 // This version is available from WinXP SP1 and has TSF support.
102 loaded_libarary_module_ = LoadLibrary(L"msftedit.dll"); 106 loaded_libarary_module_ = LoadLibrary(L"msftedit.dll");
103 } 107 }
104 108
105 DWORD style = kDefaultEditStyle | ES_AUTOHSCROLL; 109 DWORD style = kDefaultEditStyle | ES_AUTOHSCROLL;
106 if (textfield_->style() & Textfield::STYLE_OBSCURED) 110 if (textfield_->style() & Textfield::STYLE_OBSCURED)
107 style |= ES_PASSWORD; 111 style |= ES_PASSWORD;
108 112
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after
337 } 341 }
338 342
339 gfx::NativeView NativeTextfieldWin::GetTestingHandle() const { 343 gfx::NativeView NativeTextfieldWin::GetTestingHandle() const {
340 return m_hWnd; 344 return m_hWnd;
341 } 345 }
342 346
343 bool NativeTextfieldWin::IsIMEComposing() const { 347 bool NativeTextfieldWin::IsIMEComposing() const {
344 // Retrieve the length of the composition string to check if an IME is 348 // Retrieve the length of the composition string to check if an IME is
345 // composing text. (If this length is > 0 then an IME is being used to compose 349 // composing text. (If this length is > 0 then an IME is being used to compose
346 // text.) 350 // text.)
351 if (base::win::IsTsfAwareRequired())
352 return tsf_event_router_->IsImeComposing();
353
347 HIMC imm_context = ImmGetContext(m_hWnd); 354 HIMC imm_context = ImmGetContext(m_hWnd);
348 if (!imm_context) 355 if (!imm_context)
349 return false; 356 return false;
350 357
351 const int composition_size = ImmGetCompositionString(imm_context, GCS_COMPSTR, 358 const int composition_size = ImmGetCompositionString(imm_context, GCS_COMPSTR,
352 NULL, 0); 359 NULL, 0);
353 ImmReleaseContext(m_hWnd, imm_context); 360 ImmReleaseContext(m_hWnd, imm_context);
354 return composition_size > 0; 361 return composition_size > 0;
355 } 362 }
356 363
357 void NativeTextfieldWin::GetSelectedRange(ui::Range* range) const { 364 void NativeTextfieldWin::GetSelectedRange(ui::Range* range) const {
358 // TODO(tommi): Implement. 365 // TODO(tommi): Implement.
359 NOTIMPLEMENTED(); 366 //NOTIMPLEMENTED();
Peter Kasting 2012/10/27 22:29:50 This shouldn't be checked in. Either remove both
Seigo Nonaka 2012/10/28 01:50:44 Opps, sorry reverted. On 2012/10/27 22:29:50, Pete
360 range->set_start(0); 367 range->set_start(0);
361 range->set_end(0); 368 range->set_end(0);
362 } 369 }
363 370
364 void NativeTextfieldWin::SelectRange(const ui::Range& range) { 371 void NativeTextfieldWin::SelectRange(const ui::Range& range) {
365 // TODO(tommi): Implement. 372 // TODO(tommi): Implement.
366 NOTIMPLEMENTED(); 373 NOTIMPLEMENTED();
367 } 374 }
368 375
369 void NativeTextfieldWin::GetSelectionModel(gfx::SelectionModel* sel) const { 376 void NativeTextfieldWin::GetSelectionModel(gfx::SelectionModel* sel) const {
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
461 case IDS_APP_UNDO: Undo(); break; 468 case IDS_APP_UNDO: Undo(); break;
462 case IDS_APP_CUT: Cut(); break; 469 case IDS_APP_CUT: Cut(); break;
463 case IDS_APP_COPY: Copy(); break; 470 case IDS_APP_COPY: Copy(); break;
464 case IDS_APP_PASTE: Paste(); break; 471 case IDS_APP_PASTE: Paste(); break;
465 case IDS_APP_SELECT_ALL: SelectAll(false); break; 472 case IDS_APP_SELECT_ALL: SelectAll(false); break;
466 default: NOTREACHED(); break; 473 default: NOTREACHED(); break;
467 } 474 }
468 OnAfterPossibleChange(true); 475 OnAfterPossibleChange(true);
469 } 476 }
470 477
478 void NativeTextfieldWin::OnTextUpdated(const ui::Range& composition_range) {
479 if (ime_discard_composition_) {
480 ime_composition_start_ = composition_range.start();
481 ime_composition_length_ = composition_range.length();
482 } else {
483 ime_composition_start_ = 0;
484 ime_composition_length_ = 0;
485 }
486 OnAfterPossibleChange(false);
487 text_before_change_.clear();
488 }
489
490 void NativeTextfieldWin::OnCandidateWindowCountChanged(size_t window_count) {
491 }
492
493 void NativeTextfieldWin::OnImeStartCompositionInternal() {
494 // Users may press alt+shift or control+shift keys to change their keyboard
495 // layouts. So, we retrieve the input locale identifier everytime we start
496 // an IME composition.
497 int language_id = PRIMARYLANGID(GetKeyboardLayout(0));
498 ime_discard_composition_ =
499 language_id == LANG_JAPANESE || language_id == LANG_CHINESE;
500 ime_composition_start_ = 0;
501 ime_composition_length_ = 0;
502 }
503
504 void NativeTextfieldWin::OnImeEndCompositionInternal() {
505 // Bug 11863: Korean IMEs send a WM_IME_ENDCOMPOSITION message without
506 // sending any WM_IME_COMPOSITION messages when a user deletes all
507 // composition characters, i.e. a composition string becomes empty. To handle
508 // this case, we need to update the find results when a composition is
509 // finished or canceled.
510 textfield_->SyncText();
511 }
512
513 void NativeTextfieldWin::OnTsfStartComposition() {
514 OnImeStartCompositionInternal();
515 }
516
517 void NativeTextfieldWin::OnTsfEndComposition() {
518 OnImeEndCompositionInternal();
519 }
520
471 void NativeTextfieldWin::InitializeAccessibilityInfo() { 521 void NativeTextfieldWin::InitializeAccessibilityInfo() {
472 // Set the accessible state. 522 // Set the accessible state.
473 accessibility_state_ = 0; 523 accessibility_state_ = 0;
474 524
475 base::win::ScopedComPtr<IAccPropServices> pAccPropServices; 525 base::win::ScopedComPtr<IAccPropServices> pAccPropServices;
476 HRESULT hr = CoCreateInstance(CLSID_AccPropServices, NULL, CLSCTX_SERVER, 526 HRESULT hr = CoCreateInstance(CLSID_AccPropServices, NULL, CLSCTX_SERVER,
477 IID_IAccPropServices, reinterpret_cast<void**>(&pAccPropServices)); 527 IID_IAccPropServices, reinterpret_cast<void**>(&pAccPropServices));
478 if (!SUCCEEDED(hr)) 528 if (!SUCCEEDED(hr))
479 return; 529 return;
480 530
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
569 ui::Clipboard::GetForCurrentThread(), 619 ui::Clipboard::GetForCurrentThread(),
570 ui::Clipboard::BUFFER_STANDARD); 620 ui::Clipboard::BUFFER_STANDARD);
571 scw.WriteText(text); 621 scw.WriteText(text);
572 } 622 }
573 } 623 }
574 624
575 LRESULT NativeTextfieldWin::OnCreate(const CREATESTRUCTW* /*create_struct*/) { 625 LRESULT NativeTextfieldWin::OnCreate(const CREATESTRUCTW* /*create_struct*/) {
576 if (base::win::IsTsfAwareRequired()) { 626 if (base::win::IsTsfAwareRequired()) {
577 // Enable TSF support of RichEdit. 627 // Enable TSF support of RichEdit.
578 SetEditStyle(SES_USECTF, SES_USECTF); 628 SetEditStyle(SES_USECTF, SES_USECTF);
629
630 // When TSF is enabled, OnTextUpdated() may be called without any previous
631 // call that would have indicated the start of an editing session. In order
632 // to guarantee we've always called OnBeforePossibleChange() before
633 // OnAfterPossibleChange(), we therefore call that here. Note that multiple
634 // (i.e. unmatched) calls to this function in a row are safe.
635 OnBeforePossibleChange();
579 } 636 }
580 SetMsgHandled(FALSE); 637 SetMsgHandled(FALSE);
581 return 0; 638 return 0;
582 } 639 }
583 640
584 void NativeTextfieldWin::OnCut() { 641 void NativeTextfieldWin::OnCut() {
585 if (textfield_->read_only() || textfield_->IsObscured()) 642 if (textfield_->read_only() || textfield_->IsObscured())
586 return; 643 return;
587 644
588 OnCopy(); 645 OnCopy();
(...skipping 21 matching lines...) Expand all
610 // WM_IME_CHAR message while it is processing a WM_IME_COMPOSITION message. 667 // WM_IME_CHAR message while it is processing a WM_IME_COMPOSITION message.
611 // Since view controls don't need WM_IME_CHAR messages, we prevent WM_IME_CHAR 668 // Since view controls don't need WM_IME_CHAR messages, we prevent WM_IME_CHAR
612 // messages from being dispatched to view controls via the CallWindowProc() 669 // messages from being dispatched to view controls via the CallWindowProc()
613 // call. 670 // call.
614 return 0; 671 return 0;
615 } 672 }
616 673
617 LRESULT NativeTextfieldWin::OnImeStartComposition(UINT message, 674 LRESULT NativeTextfieldWin::OnImeStartComposition(UINT message,
618 WPARAM wparam, 675 WPARAM wparam,
619 LPARAM lparam) { 676 LPARAM lparam) {
620 // Users may press alt+shift or control+shift keys to change their keyboard 677 OnImeStartCompositionInternal();
621 // layouts. So, we retrieve the input locale identifier everytime we start
622 // an IME composition.
623 int language_id = PRIMARYLANGID(GetKeyboardLayout(0));
624 ime_discard_composition_ =
625 language_id == LANG_JAPANESE || language_id == LANG_CHINESE;
626 ime_composition_start_ = 0;
627 ime_composition_length_ = 0;
628
629 return DefWindowProc(message, wparam, lparam); 678 return DefWindowProc(message, wparam, lparam);
630 } 679 }
631 680
632 LRESULT NativeTextfieldWin::OnImeComposition(UINT message, 681 LRESULT NativeTextfieldWin::OnImeComposition(UINT message,
633 WPARAM wparam, 682 WPARAM wparam,
634 LPARAM lparam) { 683 LPARAM lparam) {
635 text_before_change_.clear(); 684 text_before_change_.clear();
636 LRESULT result = DefWindowProc(message, wparam, lparam); 685 LRESULT result = DefWindowProc(message, wparam, lparam);
637 686
638 ime_composition_start_ = 0; 687 ime_composition_start_ = 0;
(...skipping 26 matching lines...) Expand all
665 // setting the edit's text directly, which can cancel the current IME 714 // setting the edit's text directly, which can cancel the current IME
666 // composition or cause other adverse affects. So we set |should_redraw_text| 715 // composition or cause other adverse affects. So we set |should_redraw_text|
667 // to false. 716 // to false.
668 OnAfterPossibleChange(false); 717 OnAfterPossibleChange(false);
669 return result; 718 return result;
670 } 719 }
671 720
672 LRESULT NativeTextfieldWin::OnImeEndComposition(UINT message, 721 LRESULT NativeTextfieldWin::OnImeEndComposition(UINT message,
673 WPARAM wparam, 722 WPARAM wparam,
674 LPARAM lparam) { 723 LPARAM lparam) {
675 // Bug 11863: Korean IMEs send a WM_IME_ENDCOMPOSITION message without 724 OnImeEndCompositionInternal();
676 // sending any WM_IME_COMPOSITION messages when a user deletes all
677 // composition characters, i.e. a composition string becomes empty. To handle
678 // this case, we need to update the find results when a composition is
679 // finished or canceled.
680 textfield_->SyncText();
681 return DefWindowProc(message, wparam, lparam); 725 return DefWindowProc(message, wparam, lparam);
682 } 726 }
683 727
684 LRESULT NativeTextfieldWin::OnPointerDown(UINT message, WPARAM wparam, 728 LRESULT NativeTextfieldWin::OnPointerDown(UINT message, WPARAM wparam,
685 LPARAM lparam) { 729 LPARAM lparam) {
686 SetFocus(); 730 SetFocus();
687 SetMsgHandled(FALSE); 731 SetMsgHandled(FALSE);
688 return 0; 732 return 0;
689 } 733 }
690 734
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after
1004 1048
1005 void NativeTextfieldWin::OnSetFocus(HWND hwnd) { 1049 void NativeTextfieldWin::OnSetFocus(HWND hwnd) {
1006 SetMsgHandled(FALSE); // We still want the default processing of the message. 1050 SetMsgHandled(FALSE); // We still want the default processing of the message.
1007 1051
1008 views::FocusManager* focus_manager = textfield_->GetFocusManager(); 1052 views::FocusManager* focus_manager = textfield_->GetFocusManager();
1009 if (!focus_manager) { 1053 if (!focus_manager) {
1010 NOTREACHED(); 1054 NOTREACHED();
1011 return; 1055 return;
1012 } 1056 }
1013 focus_manager->SetFocusedView(textfield_); 1057 focus_manager->SetFocusedView(textfield_);
1058
1059 if (!base::win::IsTsfAwareRequired()) {
1060 return;
1061 }
1062
1063 DefWindowProc();
1064
1065 // Document manager created by RichEdit can be obtained only after
1066 // WM_SET_FOCUS event is handled.
1067 tsf_event_router_->SetManager(
1068 ui::TsfBridge::GetInstance()->GetThreadManager());
1069 SetMsgHandled(TRUE);
1070 }
1071
1072 void NativeTextfieldWin::OnKillFocus(HWND hwnd) {
1073 if(tsf_event_router_)
1074 tsf_event_router_->SetManager(NULL);
1014 } 1075 }
1015 1076
1016 void NativeTextfieldWin::OnSysChar(TCHAR ch, UINT repeat_count, UINT flags) { 1077 void NativeTextfieldWin::OnSysChar(TCHAR ch, UINT repeat_count, UINT flags) {
1017 // Nearly all alt-<xxx> combos result in beeping rather than doing something 1078 // Nearly all alt-<xxx> combos result in beeping rather than doing something
1018 // useful, so we discard most. Exceptions: 1079 // useful, so we discard most. Exceptions:
1019 // * ctrl-alt-<xxx>, which is sometimes important, generates WM_CHAR instead 1080 // * ctrl-alt-<xxx>, which is sometimes important, generates WM_CHAR instead
1020 // of WM_SYSCHAR, so it doesn't need to be handled here. 1081 // of WM_SYSCHAR, so it doesn't need to be handled here.
1021 // * alt-space gets translated by the default WM_SYSCHAR handler to a 1082 // * alt-space gets translated by the default WM_SYSCHAR handler to a
1022 // WM_SYSCOMMAND to open the application context menu, so we need to allow 1083 // WM_SYSCOMMAND to open the application context menu, so we need to allow
1023 // it through. 1084 // it through.
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
1216 context_menu_contents_->AddSeparator(ui::NORMAL_SEPARATOR); 1277 context_menu_contents_->AddSeparator(ui::NORMAL_SEPARATOR);
1217 context_menu_contents_->AddItemWithStringId(IDS_APP_CUT, IDS_APP_CUT); 1278 context_menu_contents_->AddItemWithStringId(IDS_APP_CUT, IDS_APP_CUT);
1218 context_menu_contents_->AddItemWithStringId(IDS_APP_COPY, IDS_APP_COPY); 1279 context_menu_contents_->AddItemWithStringId(IDS_APP_COPY, IDS_APP_COPY);
1219 context_menu_contents_->AddItemWithStringId(IDS_APP_PASTE, IDS_APP_PASTE); 1280 context_menu_contents_->AddItemWithStringId(IDS_APP_PASTE, IDS_APP_PASTE);
1220 context_menu_contents_->AddSeparator(ui::NORMAL_SEPARATOR); 1281 context_menu_contents_->AddSeparator(ui::NORMAL_SEPARATOR);
1221 context_menu_contents_->AddItemWithStringId(IDS_APP_SELECT_ALL, 1282 context_menu_contents_->AddItemWithStringId(IDS_APP_SELECT_ALL,
1222 IDS_APP_SELECT_ALL); 1283 IDS_APP_SELECT_ALL);
1223 } 1284 }
1224 1285
1225 } // namespace views 1286 } // namespace views
OLDNEW
« ui/base/ime/win/tsf_event_router.h ('K') | « ui/views/controls/textfield/native_textfield_win.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698