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 "chrome/browser/ui/views/omnibox/omnibox_view_win.h" | 5 #include "chrome/browser/ui/views/omnibox/omnibox_view_win.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <locale> | 8 #include <locale> |
9 #include <string> | 9 #include <string> |
10 | 10 |
11 #include <richedit.h> | 11 #include <richedit.h> |
12 #include <textserv.h> | 12 #include <textserv.h> |
13 | 13 |
14 #include "base/auto_reset.h" | 14 #include "base/auto_reset.h" |
15 #include "base/basictypes.h" | 15 #include "base/basictypes.h" |
16 #include "base/bind.h" | |
16 #include "base/i18n/rtl.h" | 17 #include "base/i18n/rtl.h" |
17 #include "base/lazy_instance.h" | 18 #include "base/lazy_instance.h" |
18 #include "base/memory/ref_counted.h" | 19 #include "base/memory/ref_counted.h" |
19 #include "base/string_util.h" | 20 #include "base/string_util.h" |
20 #include "base/utf_string_conversions.h" | 21 #include "base/utf_string_conversions.h" |
21 #include "base/win/iat_patch_function.h" | 22 #include "base/win/iat_patch_function.h" |
22 #include "base/win/metro.h" | 23 #include "base/win/metro.h" |
23 #include "base/win/scoped_hdc.h" | 24 #include "base/win/scoped_hdc.h" |
24 #include "base/win/scoped_select_object.h" | 25 #include "base/win/scoped_select_object.h" |
25 #include "base/win/windows_version.h" | 26 #include "base/win/windows_version.h" |
(...skipping 20 matching lines...) Expand all Loading... | |
46 #include "ui/base/accessibility/accessible_view_state.h" | 47 #include "ui/base/accessibility/accessible_view_state.h" |
47 #include "ui/base/clipboard/clipboard.h" | 48 #include "ui/base/clipboard/clipboard.h" |
48 #include "ui/base/clipboard/scoped_clipboard_writer.h" | 49 #include "ui/base/clipboard/scoped_clipboard_writer.h" |
49 #include "ui/base/dragdrop/drag_drop_types.h" | 50 #include "ui/base/dragdrop/drag_drop_types.h" |
50 #include "ui/base/dragdrop/drag_source.h" | 51 #include "ui/base/dragdrop/drag_source.h" |
51 #include "ui/base/dragdrop/drop_target.h" | 52 #include "ui/base/dragdrop/drop_target.h" |
52 #include "ui/base/dragdrop/os_exchange_data.h" | 53 #include "ui/base/dragdrop/os_exchange_data.h" |
53 #include "ui/base/dragdrop/os_exchange_data_provider_win.h" | 54 #include "ui/base/dragdrop/os_exchange_data_provider_win.h" |
54 #include "ui/base/events/event.h" | 55 #include "ui/base/events/event.h" |
55 #include "ui/base/events/event_constants.h" | 56 #include "ui/base/events/event_constants.h" |
57 #include "ui/base/ime/win/tsf_bridge.h" | |
58 #include "ui/base/ime/win/tsf_event_router.h" | |
56 #include "ui/base/keycodes/keyboard_codes.h" | 59 #include "ui/base/keycodes/keyboard_codes.h" |
57 #include "ui/base/l10n/l10n_util.h" | 60 #include "ui/base/l10n/l10n_util.h" |
58 #include "ui/base/l10n/l10n_util_win.h" | 61 #include "ui/base/l10n/l10n_util_win.h" |
59 #include "ui/base/win/mouse_wheel_util.h" | 62 #include "ui/base/win/mouse_wheel_util.h" |
60 #include "ui/gfx/canvas.h" | 63 #include "ui/gfx/canvas.h" |
61 #include "ui/gfx/image/image.h" | 64 #include "ui/gfx/image/image.h" |
62 #include "ui/views/button_drag_utils.h" | 65 #include "ui/views/button_drag_utils.h" |
63 #include "ui/views/controls/menu/menu_item_view.h" | 66 #include "ui/views/controls/menu/menu_item_view.h" |
64 #include "ui/views/controls/menu/menu_model_adapter.h" | 67 #include "ui/views/controls/menu/menu_model_adapter.h" |
65 #include "ui/views/controls/menu/menu_runner.h" | 68 #include "ui/views/controls/menu/menu_runner.h" |
(...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
470 font_(parent_view->font()), | 473 font_(parent_view->font()), |
471 possible_drag_(false), | 474 possible_drag_(false), |
472 in_drag_(false), | 475 in_drag_(false), |
473 initiated_drag_(false), | 476 initiated_drag_(false), |
474 drop_highlight_position_(-1), | 477 drop_highlight_position_(-1), |
475 ime_candidate_window_open_(false), | 478 ime_candidate_window_open_(false), |
476 background_color_(skia::SkColorToCOLORREF(LocationBarView::GetColor( | 479 background_color_(skia::SkColorToCOLORREF(LocationBarView::GetColor( |
477 chrome::search::IsInstantExtendedAPIEnabled(parent_view_->profile()), | 480 chrome::search::IsInstantExtendedAPIEnabled(parent_view_->profile()), |
478 ToolbarModel::NONE, LocationBarView::BACKGROUND))), | 481 ToolbarModel::NONE, LocationBarView::BACKGROUND))), |
479 security_level_(ToolbarModel::NONE), | 482 security_level_(ToolbarModel::NONE), |
480 text_object_model_(NULL) { | 483 text_object_model_(NULL), |
484 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { | |
481 if (!loaded_library_module_) | 485 if (!loaded_library_module_) |
482 loaded_library_module_ = LoadLibrary(kRichEditDLLName); | 486 loaded_library_module_ = LoadLibrary(kRichEditDLLName); |
483 | 487 |
484 saved_selection_for_focus_change_.cpMin = -1; | 488 saved_selection_for_focus_change_.cpMin = -1; |
485 | 489 |
486 g_paint_patcher.Pointer()->RefPatch(); | 490 g_paint_patcher.Pointer()->RefPatch(); |
487 | 491 |
488 Create(location_bar->GetWidget()->GetNativeView(), 0, 0, 0, | 492 Create(location_bar->GetWidget()->GetNativeView(), 0, 0, 0, |
489 l10n_util::GetExtendedStyles()); | 493 l10n_util::GetExtendedStyles()); |
490 SetReadOnly(popup_window_mode_); | 494 SetReadOnly(popup_window_mode_); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
531 // Non-read-only edit controls have a drop target. Revoke it so that we can | 535 // Non-read-only edit controls have a drop target. Revoke it so that we can |
532 // install our own. Revoking automatically deletes the existing one. | 536 // install our own. Revoking automatically deletes the existing one. |
533 HRESULT hr = RevokeDragDrop(m_hWnd); | 537 HRESULT hr = RevokeDragDrop(m_hWnd); |
534 DCHECK_EQ(S_OK, hr); | 538 DCHECK_EQ(S_OK, hr); |
535 | 539 |
536 // Register our drop target. The scoped_refptr here will delete the drop | 540 // Register our drop target. The scoped_refptr here will delete the drop |
537 // target if it fails to register itself correctly on |m_hWnd|. Otherwise, | 541 // target if it fails to register itself correctly on |m_hWnd|. Otherwise, |
538 // the edit control will invoke RevokeDragDrop when it's being destroyed, so | 542 // the edit control will invoke RevokeDragDrop when it's being destroyed, so |
539 // we don't have to do so. | 543 // we don't have to do so. |
540 scoped_refptr<EditDropTarget> drop_target(new EditDropTarget(this)); | 544 scoped_refptr<EditDropTarget> drop_target(new EditDropTarget(this)); |
545 | |
546 if (base::win::IsTsfAwareRequired()) { | |
547 // Register TsfEventRouter to catch TSF related event. | |
548 tsf_event_router_ = ui::TsfEventRouter::Create(); | |
549 tsf_event_router_->SetTextUpdatedCallback( | |
550 base::Bind(&OmniboxViewWin::OnTextUpdatedByTsf, | |
551 weak_ptr_factory_.GetWeakPtr())); | |
552 tsf_event_router_->SetCandidateWindowStatusChangedCallback( | |
553 base::Bind(&OmniboxViewWin::OnCandidateWindowCountChangedByTsf, | |
554 weak_ptr_factory_.GetWeakPtr())); | |
555 } | |
541 } | 556 } |
542 } | 557 } |
543 | 558 |
544 OmniboxViewWin::~OmniboxViewWin() { | 559 OmniboxViewWin::~OmniboxViewWin() { |
545 // Explicitly release the text object model now that we're done with it, and | 560 // Explicitly release the text object model now that we're done with it, and |
546 // before we free the library. If the library gets unloaded before this | 561 // before we free the library. If the library gets unloaded before this |
547 // released, it becomes garbage. Note that since text_object_model_ is lazy | 562 // released, it becomes garbage. Note that since text_object_model_ is lazy |
548 // initialized, it may still be null. | 563 // initialized, it may still be null. |
549 if (text_object_model_) | 564 if (text_object_model_) |
550 text_object_model_->Release(); | 565 text_object_model_->Release(); |
(...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
906 native_view_host_, | 921 native_view_host_, |
907 ui::AccessibilityTypes::EVENT_SELECTION_CHANGED, | 922 ui::AccessibilityTypes::EVENT_SELECTION_CHANGED, |
908 true); | 923 true); |
909 } else if (delete_at_end_pressed_) { | 924 } else if (delete_at_end_pressed_) { |
910 model()->OnChanged(); | 925 model()->OnChanged(); |
911 } | 926 } |
912 | 927 |
913 return something_changed; | 928 return something_changed; |
914 } | 929 } |
915 | 930 |
931 void OmniboxViewWin::OnTextUpdatedByTsf() { | |
932 if (ignore_ime_messages_) | |
933 return; | |
934 OnAfterPossibleChangeInternal(true); | |
935 // Call OnBeforePossibleChange function here to get correct diff in next IME | |
936 // update. The Text Services Framework does not provide any notification | |
937 // before entering edit session, therefore we don't have good place to call | |
938 // OnbeforePossibleChange. | |
falken
2012/10/18 02:15:54
nit: "OnBeforePossibleChange"
Seigo Nonaka
2012/10/18 10:02:23
Done.
| |
939 OnBeforePossibleChange(); | |
940 } | |
941 | |
942 void OmniboxViewWin::OnCandidateWindowCountChangedByTsf(size_t window_count) { | |
943 ime_candidate_window_open_ = (window_count != 0); | |
944 if (ime_candidate_window_open_) { | |
945 CloseOmniboxPopup(); | |
946 } else { | |
947 // UpdatePopup assumes user input is in progress, so only call it if | |
948 // that's the case. Otherwise, autocomplete may run on an empty user | |
949 // text. For example, Baidu Japanese IME sends IMN_CLOSECANDIDATE when | |
falken
2012/10/18 02:15:54
In TSF you don't get IMN_CLOSECANDIDATE messages,
Seigo Nonaka
2012/10/18 10:02:23
Done.
| |
950 // composition mode is entered, but the user may not have input anything | |
951 // yet. | |
952 if (model()->user_input_in_progress()) | |
953 UpdatePopup(); | |
954 } | |
955 } | |
956 | |
916 gfx::NativeView OmniboxViewWin::GetNativeView() const { | 957 gfx::NativeView OmniboxViewWin::GetNativeView() const { |
917 return m_hWnd; | 958 return m_hWnd; |
918 } | 959 } |
919 | 960 |
920 // static | 961 // static |
921 gfx::NativeView OmniboxViewWin::GetRelativeWindowForNativeView( | 962 gfx::NativeView OmniboxViewWin::GetRelativeWindowForNativeView( |
922 gfx::NativeView edit_native_view) { | 963 gfx::NativeView edit_native_view) { |
923 // When an IME is attached to the rich-edit control, retrieve its window | 964 // When an IME is attached to the rich-edit control, retrieve its window |
924 // handle, and the popup window of OmniboxPopupView will be shown under the | 965 // handle, and the popup window of OmniboxPopupView will be shown under the |
925 // IME windows. | 966 // IME windows. |
(...skipping 15 matching lines...) Expand all Loading... | |
941 | 982 |
942 int OmniboxViewWin::TextWidth() const { | 983 int OmniboxViewWin::TextWidth() const { |
943 return WidthNeededToDisplay(GetText()); | 984 return WidthNeededToDisplay(GetText()); |
944 } | 985 } |
945 | 986 |
946 string16 OmniboxViewWin::GetInstantSuggestion() const { | 987 string16 OmniboxViewWin::GetInstantSuggestion() const { |
947 return parent_view_->GetInstantSuggestion(); | 988 return parent_view_->GetInstantSuggestion(); |
948 } | 989 } |
949 | 990 |
950 bool OmniboxViewWin::IsImeComposing() const { | 991 bool OmniboxViewWin::IsImeComposing() const { |
951 bool ime_composing = false; | 992 if (base::win::IsTsfAwareRequired()) { |
952 HIMC context = ImmGetContext(m_hWnd); | 993 return tsf_event_router_->IsImeComposing(); |
953 if (context) { | 994 } else { |
954 ime_composing = !!ImmGetCompositionString(context, GCS_COMPSTR, NULL, 0); | 995 bool ime_composing = false; |
955 ImmReleaseContext(m_hWnd, context); | 996 HIMC context = ImmGetContext(m_hWnd); |
997 if (context) { | |
998 ime_composing = !!ImmGetCompositionString(context, GCS_COMPSTR, NULL, 0); | |
999 ImmReleaseContext(m_hWnd, context); | |
1000 } | |
1001 return ime_composing; | |
956 } | 1002 } |
957 return ime_composing; | |
958 } | 1003 } |
959 | 1004 |
960 int OmniboxViewWin::GetMaxEditWidth(int entry_width) const { | 1005 int OmniboxViewWin::GetMaxEditWidth(int entry_width) const { |
961 RECT formatting_rect; | 1006 RECT formatting_rect; |
962 GetRect(&formatting_rect); | 1007 GetRect(&formatting_rect); |
963 RECT edit_bounds; | 1008 RECT edit_bounds; |
964 GetClientRect(&edit_bounds); | 1009 GetClientRect(&edit_bounds); |
965 return entry_width - formatting_rect.left - | 1010 return entry_width - formatting_rect.left - |
966 (edit_bounds.right - formatting_rect.right); | 1011 (edit_bounds.right - formatting_rect.right); |
967 } | 1012 } |
(...skipping 607 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1575 // an in-progress IME composition will be completed at the new caret position, | 1620 // an in-progress IME composition will be completed at the new caret position, |
1576 // resulting in the string jumping unexpectedly to the front of the edit. | 1621 // resulting in the string jumping unexpectedly to the front of the edit. |
1577 // | 1622 // |
1578 // Crazy hack: If we just do PlaceCaretAt(0), and the beginning of the text is | 1623 // Crazy hack: If we just do PlaceCaretAt(0), and the beginning of the text is |
1579 // currently scrolled out of view, we can wind up with a blinking cursor in | 1624 // currently scrolled out of view, we can wind up with a blinking cursor in |
1580 // the toolbar at the current X coordinate of the beginning of the text. By | 1625 // the toolbar at the current X coordinate of the beginning of the text. By |
1581 // first doing a reverse-select-all to scroll the beginning of the text into | 1626 // first doing a reverse-select-all to scroll the beginning of the text into |
1582 // view, we work around this CRichEditCtrl bug. | 1627 // view, we work around this CRichEditCtrl bug. |
1583 SelectAll(true); | 1628 SelectAll(true); |
1584 PlaceCaretAt(0); | 1629 PlaceCaretAt(0); |
1630 | |
1631 if (base::win::IsTsfAwareRequired()) | |
1632 tsf_event_router_->SetManager(NULL); | |
1585 } | 1633 } |
1586 | 1634 |
1587 void OmniboxViewWin::OnLButtonDblClk(UINT keys, const CPoint& point) { | 1635 void OmniboxViewWin::OnLButtonDblClk(UINT keys, const CPoint& point) { |
1588 // Save the double click info for later triple-click detection. | 1636 // Save the double click info for later triple-click detection. |
1589 tracking_double_click_ = true; | 1637 tracking_double_click_ = true; |
1590 double_click_point_ = point; | 1638 double_click_point_ = point; |
1591 double_click_time_ = GetCurrentMessage()->time; | 1639 double_click_time_ = GetCurrentMessage()->time; |
1592 possible_drag_ = false; | 1640 possible_drag_ = false; |
1593 | 1641 |
1594 // Modifying the selection counts as accepting any inline autocompletion, so | 1642 // Modifying the selection counts as accepting any inline autocompletion, so |
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1902 } | 1950 } |
1903 | 1951 |
1904 model()->OnSetFocus(GetKeyState(VK_CONTROL) < 0); | 1952 model()->OnSetFocus(GetKeyState(VK_CONTROL) < 0); |
1905 | 1953 |
1906 // Restore saved selection if available. | 1954 // Restore saved selection if available. |
1907 if (saved_selection_for_focus_change_.cpMin != -1) { | 1955 if (saved_selection_for_focus_change_.cpMin != -1) { |
1908 SetSelectionRange(saved_selection_for_focus_change_); | 1956 SetSelectionRange(saved_selection_for_focus_change_); |
1909 saved_selection_for_focus_change_.cpMin = -1; | 1957 saved_selection_for_focus_change_.cpMin = -1; |
1910 } | 1958 } |
1911 | 1959 |
1912 SetMsgHandled(false); | 1960 if (!base::win::IsTsfAwareRequired()) { |
1961 SetMsgHandled(false); | |
1962 } else { | |
1963 DefWindowProc(); | |
1964 // Document manager created by RichEdit can be obtained only after | |
1965 // WM_SETFOCUS event is handled. | |
1966 tsf_event_router_->SetManager( | |
1967 ui::TsfBridge::GetInstance()->GetThreadManager()); | |
1968 SetMsgHandled(true); | |
1969 } | |
1913 } | 1970 } |
1914 | 1971 |
1915 LRESULT OmniboxViewWin::OnSetText(const wchar_t* text) { | 1972 LRESULT OmniboxViewWin::OnSetText(const wchar_t* text) { |
1916 // Ignore all IME messages while we process this WM_SETTEXT message. | 1973 // Ignore all IME messages while we process this WM_SETTEXT message. |
1917 // When SetWindowText() is called while an IME is composing text, the IME | 1974 // When SetWindowText() is called while an IME is composing text, the IME |
1918 // calls SendMessage() to send a WM_IME_COMPOSITION message. When we receive | 1975 // calls SendMessage() to send a WM_IME_COMPOSITION message. When we receive |
1919 // this WM_IME_COMPOSITION message, we update the omnibox and may call | 1976 // this WM_IME_COMPOSITION message, we update the omnibox and may call |
1920 // SetWindowText() again. To stop this recursive message-handler call, we | 1977 // SetWindowText() again. To stop this recursive message-handler call, we |
1921 // stop updating the omnibox while we process a WM_SETTEXT message. | 1978 // stop updating the omnibox while we process a WM_SETTEXT message. |
1922 // We wouldn't need to do this update anyway, because either we're in the | 1979 // We wouldn't need to do this update anyway, because either we're in the |
(...skipping 779 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2702 return (rect.left - client_rect.left) + (client_rect.right - rect.right); | 2759 return (rect.left - client_rect.left) + (client_rect.right - rect.right); |
2703 } | 2760 } |
2704 | 2761 |
2705 int OmniboxViewWin::WidthNeededToDisplay(const string16& text) const { | 2762 int OmniboxViewWin::WidthNeededToDisplay(const string16& text) const { |
2706 // Use font_.GetStringWidth() instead of | 2763 // Use font_.GetStringWidth() instead of |
2707 // PosFromChar(location_entry_->GetTextLength()) because PosFromChar() is | 2764 // PosFromChar(location_entry_->GetTextLength()) because PosFromChar() is |
2708 // apparently buggy. In both LTR UI and RTL UI with left-to-right layout, | 2765 // apparently buggy. In both LTR UI and RTL UI with left-to-right layout, |
2709 // PosFromChar(i) might return 0 when i is greater than 1. | 2766 // PosFromChar(i) might return 0 when i is greater than 1. |
2710 return font_.GetStringWidth(text) + GetHorizontalMargin(); | 2767 return font_.GetStringWidth(text) + GetHorizontalMargin(); |
2711 } | 2768 } |
OLD | NEW |