Chromium Code Reviews| 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 |