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 |
| 558 if (tsf_event_router_) |
| 559 tsf_event_router_->SetManager(NULL, NULL); |
| 560 |
552 // We balance our reference count and unpatch when the last instance has | 561 // 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 | 562 // been destroyed. This prevents us from relying on the AtExit or static |
554 // destructor sequence to do our unpatching, which is generally fragile. | 563 // destructor sequence to do our unpatching, which is generally fragile. |
555 g_paint_patcher.Pointer()->DerefPatch(); | 564 g_paint_patcher.Pointer()->DerefPatch(); |
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 |
(...skipping 344 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 // When TSF is enabled, OnTextUpdated() may be called without any previous |
| 1415 // call that would have indicated the start of an editing session. In order |
| 1416 // to guarantee we've always called OnBeforePossibleChange() before |
| 1417 // OnAfterPossibleChange(), we therefore call that here. Note that multiple |
| 1418 // (i.e. unmatched) calls to this function in a row are safe. |
| 1419 if (base::win::IsTsfAwareRequired()) |
| 1420 OnBeforePossibleChange(); |
1379 return 0; | 1421 return 0; |
1380 } | 1422 } |
1381 | 1423 |
1382 void OmniboxViewWin::OnCut() { | 1424 void OmniboxViewWin::OnCut() { |
1383 OnCopy(); | 1425 OnCopy(); |
1384 | 1426 |
1385 // This replace selection will have no effect (even on the undo stack) if the | 1427 // This replace selection will have no effect (even on the undo stack) if the |
1386 // current selection is empty. | 1428 // current selection is empty. |
1387 ReplaceSel(L"", true); | 1429 ReplaceSel(L"", true); |
1388 } | 1430 } |
(...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, | 1617 // 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. | 1618 // resulting in the string jumping unexpectedly to the front of the edit. |
1577 // | 1619 // |
1578 // Crazy hack: If we just do PlaceCaretAt(0), and the beginning of the text is | 1620 // 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 | 1621 // 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 | 1622 // 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 | 1623 // first doing a reverse-select-all to scroll the beginning of the text into |
1582 // view, we work around this CRichEditCtrl bug. | 1624 // view, we work around this CRichEditCtrl bug. |
1583 SelectAll(true); | 1625 SelectAll(true); |
1584 PlaceCaretAt(0); | 1626 PlaceCaretAt(0); |
| 1627 |
| 1628 if (tsf_event_router_) |
| 1629 tsf_event_router_->SetManager(NULL, NULL); |
1585 } | 1630 } |
1586 | 1631 |
1587 void OmniboxViewWin::OnLButtonDblClk(UINT keys, const CPoint& point) { | 1632 void OmniboxViewWin::OnLButtonDblClk(UINT keys, const CPoint& point) { |
1588 // Save the double click info for later triple-click detection. | 1633 // Save the double click info for later triple-click detection. |
1589 tracking_double_click_ = true; | 1634 tracking_double_click_ = true; |
1590 double_click_point_ = point; | 1635 double_click_point_ = point; |
1591 double_click_time_ = GetCurrentMessage()->time; | 1636 double_click_time_ = GetCurrentMessage()->time; |
1592 possible_drag_ = false; | 1637 possible_drag_ = false; |
1593 | 1638 |
1594 // Modifying the selection counts as accepting any inline autocompletion, so | 1639 // Modifying the selection counts as accepting any inline autocompletion, so |
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1902 } | 1947 } |
1903 | 1948 |
1904 model()->OnSetFocus(GetKeyState(VK_CONTROL) < 0); | 1949 model()->OnSetFocus(GetKeyState(VK_CONTROL) < 0); |
1905 | 1950 |
1906 // Restore saved selection if available. | 1951 // Restore saved selection if available. |
1907 if (saved_selection_for_focus_change_.cpMin != -1) { | 1952 if (saved_selection_for_focus_change_.cpMin != -1) { |
1908 SetSelectionRange(saved_selection_for_focus_change_); | 1953 SetSelectionRange(saved_selection_for_focus_change_); |
1909 saved_selection_for_focus_change_.cpMin = -1; | 1954 saved_selection_for_focus_change_.cpMin = -1; |
1910 } | 1955 } |
1911 | 1956 |
1912 SetMsgHandled(false); | 1957 if (!tsf_event_router_) { |
| 1958 SetMsgHandled(false); |
| 1959 } else { |
| 1960 DefWindowProc(); |
| 1961 // Document manager created by RichEdit can be obtained only after |
| 1962 // WM_SETFOCUS event is handled. |
| 1963 tsf_event_router_->SetManager( |
| 1964 ui::TsfBridge::GetInstance()->GetThreadManager(), |
| 1965 this); |
| 1966 SetMsgHandled(true); |
| 1967 } |
1913 } | 1968 } |
1914 | 1969 |
1915 LRESULT OmniboxViewWin::OnSetText(const wchar_t* text) { | 1970 LRESULT OmniboxViewWin::OnSetText(const wchar_t* text) { |
1916 // Ignore all IME messages while we process this WM_SETTEXT message. | 1971 // Ignore all IME messages while we process this WM_SETTEXT message. |
1917 // When SetWindowText() is called while an IME is composing text, the IME | 1972 // 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 | 1973 // 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 | 1974 // this WM_IME_COMPOSITION message, we update the omnibox and may call |
1920 // SetWindowText() again. To stop this recursive message-handler call, we | 1975 // SetWindowText() again. To stop this recursive message-handler call, we |
1921 // stop updating the omnibox while we process a WM_SETTEXT message. | 1976 // 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 | 1977 // 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); | 2757 return (rect.left - client_rect.left) + (client_rect.right - rect.right); |
2703 } | 2758 } |
2704 | 2759 |
2705 int OmniboxViewWin::WidthNeededToDisplay(const string16& text) const { | 2760 int OmniboxViewWin::WidthNeededToDisplay(const string16& text) const { |
2706 // Use font_.GetStringWidth() instead of | 2761 // Use font_.GetStringWidth() instead of |
2707 // PosFromChar(location_entry_->GetTextLength()) because PosFromChar() is | 2762 // PosFromChar(location_entry_->GetTextLength()) because PosFromChar() is |
2708 // apparently buggy. In both LTR UI and RTL UI with left-to-right layout, | 2763 // 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. | 2764 // PosFromChar(i) might return 0 when i is greater than 1. |
2710 return font_.GetStringWidth(text) + GetHorizontalMargin(); | 2765 return font_.GetStringWidth(text) + GetHorizontalMargin(); |
2711 } | 2766 } |
OLD | NEW |