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 465 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 | 534 // 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. | 535 // install our own. Revoking automatically deletes the existing one. |
| 533 HRESULT hr = RevokeDragDrop(m_hWnd); | 536 HRESULT hr = RevokeDragDrop(m_hWnd); |
| 534 DCHECK_EQ(S_OK, hr); | 537 DCHECK_EQ(S_OK, hr); |
| 535 | 538 |
| 536 // Register our drop target. The scoped_refptr here will delete the drop | 539 // 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, | 540 // 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 | 541 // the edit control will invoke RevokeDragDrop when it's being destroyed, so |
| 539 // we don't have to do so. | 542 // we don't have to do so. |
| 540 scoped_refptr<EditDropTarget> drop_target(new EditDropTarget(this)); | 543 scoped_refptr<EditDropTarget> drop_target(new EditDropTarget(this)); |
| 544 | |
| 545 if (base::win::IsTsfAwareRequired()) | |
| 546 tsf_event_router_ = ui::TsfEventRouter::Create(); | |
| 541 } | 547 } |
| 542 } | 548 } |
| 543 | 549 |
| 544 OmniboxViewWin::~OmniboxViewWin() { | 550 OmniboxViewWin::~OmniboxViewWin() { |
| 545 // Explicitly release the text object model now that we're done with it, and | 551 // 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 | 552 // 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 | 553 // released, it becomes garbage. Note that since text_object_model_ is lazy |
| 548 // initialized, it may still be null. | 554 // initialized, it may still be null. |
| 549 if (text_object_model_) | 555 if (text_object_model_) |
| 550 text_object_model_->Release(); | 556 text_object_model_->Release(); |
| 551 | 557 |
| 552 // We balance our reference count and unpatch when the last instance has | 558 // We balance our reference count and unpatch when the last instance has |
| 553 // been destroyed. This prevents us from relying on the AtExit or static | 559 // been destroyed. This prevents us from relying on the AtExit or static |
| 554 // destructor sequence to do our unpatching, which is generally fragile. | 560 // destructor sequence to do our unpatching, which is generally fragile. |
| 555 g_paint_patcher.Pointer()->DerefPatch(); | 561 g_paint_patcher.Pointer()->DerefPatch(); |
| 562 | |
| 563 if (tsf_event_router_) | |
|
Peter Kasting
2012/10/19 18:40:57
Tiny nit: This should probably go above the paint
Seigo Nonaka
2012/10/22 03:11:04
Done.
| |
| 564 tsf_event_router_->SetManager(NULL, NULL); | |
| 556 } | 565 } |
| 557 | 566 |
| 558 views::View* OmniboxViewWin::parent_view() const { | 567 views::View* OmniboxViewWin::parent_view() const { |
| 559 return parent_view_; | 568 return parent_view_; |
| 560 } | 569 } |
| 561 | 570 |
| 562 void OmniboxViewWin::SaveStateToTab(WebContents* tab) { | 571 void OmniboxViewWin::SaveStateToTab(WebContents* tab) { |
| 563 DCHECK(tab); | 572 DCHECK(tab); |
| 564 | 573 |
| 565 const OmniboxEditModel::State model_state(model()->GetStateForTabSwitch()); | 574 const OmniboxEditModel::State model_state(model()->GetStateForTabSwitch()); |
| (...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 906 native_view_host_, | 915 native_view_host_, |
| 907 ui::AccessibilityTypes::EVENT_SELECTION_CHANGED, | 916 ui::AccessibilityTypes::EVENT_SELECTION_CHANGED, |
| 908 true); | 917 true); |
| 909 } else if (delete_at_end_pressed_) { | 918 } else if (delete_at_end_pressed_) { |
| 910 model()->OnChanged(); | 919 model()->OnChanged(); |
| 911 } | 920 } |
| 912 | 921 |
| 913 return something_changed; | 922 return something_changed; |
| 914 } | 923 } |
| 915 | 924 |
| 925 void OmniboxViewWin::OnTextUpdated() { | |
| 926 if (ignore_ime_messages_) | |
| 927 return; | |
| 928 OnAfterPossibleChangeInternal(true); | |
| 929 // Call OnBeforePossibleChange function here to get correct diff in next IME | |
| 930 // update. The Text Services Framework does not provide any notification | |
| 931 // before entering edit session, therefore we don't have good place to call | |
| 932 // OnBeforePossibleChange. | |
| 933 OnBeforePossibleChange(); | |
| 934 } | |
| 935 | |
| 936 void OmniboxViewWin::OnCandidateWindowCountChanged(size_t window_count) { | |
| 937 ime_candidate_window_open_ = (window_count != 0); | |
| 938 if (ime_candidate_window_open_) { | |
| 939 CloseOmniboxPopup(); | |
| 940 } else if (model()->user_input_in_progress()) { | |
| 941 // UpdatePopup assumes user input is in progress, so only call it if | |
| 942 // that's the case. Otherwise, autocomplete may run on an empty user | |
| 943 // text. | |
| 944 UpdatePopup(); | |
| 945 } | |
| 946 } | |
| 947 | |
| 916 gfx::NativeView OmniboxViewWin::GetNativeView() const { | 948 gfx::NativeView OmniboxViewWin::GetNativeView() const { |
| 917 return m_hWnd; | 949 return m_hWnd; |
| 918 } | 950 } |
| 919 | 951 |
| 920 // static | 952 // static |
| 921 gfx::NativeView OmniboxViewWin::GetRelativeWindowForNativeView( | 953 gfx::NativeView OmniboxViewWin::GetRelativeWindowForNativeView( |
| 922 gfx::NativeView edit_native_view) { | 954 gfx::NativeView edit_native_view) { |
| 923 // When an IME is attached to the rich-edit control, retrieve its window | 955 // 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 | 956 // handle, and the popup window of OmniboxPopupView will be shown under the |
| 925 // IME windows. | 957 // IME windows. |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 941 | 973 |
| 942 int OmniboxViewWin::TextWidth() const { | 974 int OmniboxViewWin::TextWidth() const { |
| 943 return WidthNeededToDisplay(GetText()); | 975 return WidthNeededToDisplay(GetText()); |
| 944 } | 976 } |
| 945 | 977 |
| 946 string16 OmniboxViewWin::GetInstantSuggestion() const { | 978 string16 OmniboxViewWin::GetInstantSuggestion() const { |
| 947 return parent_view_->GetInstantSuggestion(); | 979 return parent_view_->GetInstantSuggestion(); |
| 948 } | 980 } |
| 949 | 981 |
| 950 bool OmniboxViewWin::IsImeComposing() const { | 982 bool OmniboxViewWin::IsImeComposing() const { |
| 983 if (tsf_event_router_) | |
| 984 return tsf_event_router_->IsImeComposing(); | |
| 951 bool ime_composing = false; | 985 bool ime_composing = false; |
| 952 HIMC context = ImmGetContext(m_hWnd); | 986 HIMC context = ImmGetContext(m_hWnd); |
| 953 if (context) { | 987 if (context) { |
| 954 ime_composing = !!ImmGetCompositionString(context, GCS_COMPSTR, NULL, 0); | 988 ime_composing = !!ImmGetCompositionString(context, GCS_COMPSTR, NULL, 0); |
| 955 ImmReleaseContext(m_hWnd, context); | 989 ImmReleaseContext(m_hWnd, context); |
| 956 } | 990 } |
| 957 return ime_composing; | 991 return ime_composing; |
| 958 } | 992 } |
| 959 | 993 |
| 960 int OmniboxViewWin::GetMaxEditWidth(int entry_width) const { | 994 int OmniboxViewWin::GetMaxEditWidth(int entry_width) const { |
| (...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1369 LRESULT OmniboxViewWin::OnCreate(const CREATESTRUCTW* /*create_struct*/) { | 1403 LRESULT OmniboxViewWin::OnCreate(const CREATESTRUCTW* /*create_struct*/) { |
| 1370 if (base::win::IsTsfAwareRequired()) { | 1404 if (base::win::IsTsfAwareRequired()) { |
| 1371 // Enable TSF support of RichEdit. | 1405 // Enable TSF support of RichEdit. |
| 1372 SetEditStyle(SES_USECTF, SES_USECTF); | 1406 SetEditStyle(SES_USECTF, SES_USECTF); |
| 1373 } | 1407 } |
| 1374 if (base::win::GetVersion() >= base::win::VERSION_WIN8) { | 1408 if (base::win::GetVersion() >= base::win::VERSION_WIN8) { |
| 1375 BOOL touch_mode = RegisterTouchWindow(m_hWnd, TWF_WANTPALM); | 1409 BOOL touch_mode = RegisterTouchWindow(m_hWnd, TWF_WANTPALM); |
| 1376 DCHECK(touch_mode); | 1410 DCHECK(touch_mode); |
| 1377 } | 1411 } |
| 1378 SetMsgHandled(FALSE); | 1412 SetMsgHandled(FALSE); |
| 1413 | |
| 1414 // To ensure OnBeforePossibleChange is called before any | |
| 1415 // OnAfterPossibleChange call, we call OnBeforePossibleChange here. In the | |
| 1416 // case of a pure TSF environment like on Metro UI, we can't get any chance | |
| 1417 // to call OnBeforePossibleChange at the beginning of an edit session, if we | |
|
Peter Kasting
2012/10/19 18:40:57
Nit: Slightly clearer:
// When TSF is enabled,
Seigo Nonaka
2012/10/22 03:11:04
Done.
| |
| 1418 // do not call OnBeforePossibleChange here, we would call | |
| 1419 // OnAfterPossibleChange on the end of edit session without any | |
| 1420 // OnBeforePossibleChange call. | |
| 1421 OnBeforePossibleChange(); | |
|
Peter Kasting
2012/10/19 18:40:57
You should only do this when |tsf_event_router_| i
Seigo Nonaka
2012/10/22 03:11:04
Done.
| |
| 1379 return 0; | 1422 return 0; |
| 1380 } | 1423 } |
| 1381 | 1424 |
| 1382 void OmniboxViewWin::OnCut() { | 1425 void OmniboxViewWin::OnCut() { |
| 1383 OnCopy(); | 1426 OnCopy(); |
| 1384 | 1427 |
| 1385 // This replace selection will have no effect (even on the undo stack) if the | 1428 // This replace selection will have no effect (even on the undo stack) if the |
| 1386 // current selection is empty. | 1429 // current selection is empty. |
| 1387 ReplaceSel(L"", true); | 1430 ReplaceSel(L"", true); |
| 1388 } | 1431 } |
| (...skipping 186 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, | 1618 // 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. | 1619 // resulting in the string jumping unexpectedly to the front of the edit. |
| 1577 // | 1620 // |
| 1578 // Crazy hack: If we just do PlaceCaretAt(0), and the beginning of the text is | 1621 // 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 | 1622 // 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 | 1623 // 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 | 1624 // first doing a reverse-select-all to scroll the beginning of the text into |
| 1582 // view, we work around this CRichEditCtrl bug. | 1625 // view, we work around this CRichEditCtrl bug. |
| 1583 SelectAll(true); | 1626 SelectAll(true); |
| 1584 PlaceCaretAt(0); | 1627 PlaceCaretAt(0); |
| 1628 | |
| 1629 if (tsf_event_router_) | |
| 1630 tsf_event_router_->SetManager(NULL, NULL); | |
| 1585 } | 1631 } |
| 1586 | 1632 |
| 1587 void OmniboxViewWin::OnLButtonDblClk(UINT keys, const CPoint& point) { | 1633 void OmniboxViewWin::OnLButtonDblClk(UINT keys, const CPoint& point) { |
| 1588 // Save the double click info for later triple-click detection. | 1634 // Save the double click info for later triple-click detection. |
| 1589 tracking_double_click_ = true; | 1635 tracking_double_click_ = true; |
| 1590 double_click_point_ = point; | 1636 double_click_point_ = point; |
| 1591 double_click_time_ = GetCurrentMessage()->time; | 1637 double_click_time_ = GetCurrentMessage()->time; |
| 1592 possible_drag_ = false; | 1638 possible_drag_ = false; |
| 1593 | 1639 |
| 1594 // Modifying the selection counts as accepting any inline autocompletion, so | 1640 // Modifying the selection counts as accepting any inline autocompletion, so |
| (...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1902 } | 1948 } |
| 1903 | 1949 |
| 1904 model()->OnSetFocus(GetKeyState(VK_CONTROL) < 0); | 1950 model()->OnSetFocus(GetKeyState(VK_CONTROL) < 0); |
| 1905 | 1951 |
| 1906 // Restore saved selection if available. | 1952 // Restore saved selection if available. |
| 1907 if (saved_selection_for_focus_change_.cpMin != -1) { | 1953 if (saved_selection_for_focus_change_.cpMin != -1) { |
| 1908 SetSelectionRange(saved_selection_for_focus_change_); | 1954 SetSelectionRange(saved_selection_for_focus_change_); |
| 1909 saved_selection_for_focus_change_.cpMin = -1; | 1955 saved_selection_for_focus_change_.cpMin = -1; |
| 1910 } | 1956 } |
| 1911 | 1957 |
| 1912 SetMsgHandled(false); | 1958 if (!tsf_event_router_) { |
| 1959 SetMsgHandled(false); | |
| 1960 } else { | |
| 1961 DefWindowProc(); | |
| 1962 // Document manager created by RichEdit can be obtained only after | |
| 1963 // WM_SETFOCUS event is handled. | |
| 1964 tsf_event_router_->SetManager( | |
| 1965 ui::TsfBridge::GetInstance()->GetThreadManager(), | |
| 1966 this); | |
| 1967 SetMsgHandled(true); | |
| 1968 } | |
| 1913 } | 1969 } |
| 1914 | 1970 |
| 1915 LRESULT OmniboxViewWin::OnSetText(const wchar_t* text) { | 1971 LRESULT OmniboxViewWin::OnSetText(const wchar_t* text) { |
| 1916 // Ignore all IME messages while we process this WM_SETTEXT message. | 1972 // Ignore all IME messages while we process this WM_SETTEXT message. |
| 1917 // When SetWindowText() is called while an IME is composing text, the IME | 1973 // 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 | 1974 // 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 | 1975 // this WM_IME_COMPOSITION message, we update the omnibox and may call |
| 1920 // SetWindowText() again. To stop this recursive message-handler call, we | 1976 // SetWindowText() again. To stop this recursive message-handler call, we |
| 1921 // stop updating the omnibox while we process a WM_SETTEXT message. | 1977 // 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 | 1978 // 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); | 2758 return (rect.left - client_rect.left) + (client_rect.right - rect.right); |
| 2703 } | 2759 } |
| 2704 | 2760 |
| 2705 int OmniboxViewWin::WidthNeededToDisplay(const string16& text) const { | 2761 int OmniboxViewWin::WidthNeededToDisplay(const string16& text) const { |
| 2706 // Use font_.GetStringWidth() instead of | 2762 // Use font_.GetStringWidth() instead of |
| 2707 // PosFromChar(location_entry_->GetTextLength()) because PosFromChar() is | 2763 // PosFromChar(location_entry_->GetTextLength()) because PosFromChar() is |
| 2708 // apparently buggy. In both LTR UI and RTL UI with left-to-right layout, | 2764 // 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. | 2765 // PosFromChar(i) might return 0 when i is greater than 1. |
| 2710 return font_.GetStringWidth(text) + GetHorizontalMargin(); | 2766 return font_.GetStringWidth(text) + GetHorizontalMargin(); |
| 2711 } | 2767 } |
| OLD | NEW |