OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/i18n/rtl.h" | 16 #include "base/i18n/rtl.h" |
17 #include "base/lazy_instance.h" | 17 #include "base/lazy_instance.h" |
18 #include "base/memory/ref_counted.h" | 18 #include "base/memory/ref_counted.h" |
19 #include "base/string_util.h" | 19 #include "base/string_util.h" |
20 #include "base/utf_string_conversions.h" | 20 #include "base/utf_string_conversions.h" |
21 #include "base/win/iat_patch_function.h" | 21 #include "base/win/iat_patch_function.h" |
22 #include "chrome/app/chrome_command_ids.h" | 22 #include "chrome/app/chrome_command_ids.h" |
23 #include "chrome/browser/autocomplete/autocomplete_accessibility.h" | |
24 #include "chrome/browser/autocomplete/autocomplete_match.h" | 23 #include "chrome/browser/autocomplete/autocomplete_match.h" |
25 #include "chrome/browser/autocomplete/autocomplete_popup_model.h" | 24 #include "chrome/browser/autocomplete/autocomplete_popup_model.h" |
26 #include "chrome/browser/autocomplete/keyword_provider.h" | 25 #include "chrome/browser/autocomplete/keyword_provider.h" |
27 #include "chrome/browser/browser_process.h" | 26 #include "chrome/browser/browser_process.h" |
28 #include "chrome/browser/command_updater.h" | 27 #include "chrome/browser/command_updater.h" |
29 #include "chrome/browser/net/url_fixer_upper.h" | 28 #include "chrome/browser/net/url_fixer_upper.h" |
30 #include "chrome/browser/profiles/profile.h" | 29 #include "chrome/browser/profiles/profile.h" |
31 #include "chrome/browser/ui/browser.h" | 30 #include "chrome/browser/ui/browser.h" |
32 #include "chrome/browser/ui/views/location_bar/location_bar_view.h" | 31 #include "chrome/browser/ui/views/location_bar/location_bar_view.h" |
33 #include "chrome/common/chrome_notification_types.h" | 32 #include "chrome/common/chrome_notification_types.h" |
34 #include "content/browser/tab_contents/tab_contents.h" | 33 #include "content/browser/tab_contents/tab_contents.h" |
35 #include "content/browser/user_metrics.h" | 34 #include "content/browser/user_metrics.h" |
36 #include "googleurl/src/url_util.h" | 35 #include "googleurl/src/url_util.h" |
37 #include "grit/generated_resources.h" | 36 #include "grit/generated_resources.h" |
38 #include "net/base/escape.h" | 37 #include "net/base/escape.h" |
39 #include "skia/ext/skia_utils_win.h" | 38 #include "skia/ext/skia_utils_win.h" |
39 #include "ui/base/accessibility/accessible_view_state.h" | |
40 #include "ui/base/clipboard/clipboard.h" | 40 #include "ui/base/clipboard/clipboard.h" |
41 #include "ui/base/clipboard/scoped_clipboard_writer.h" | 41 #include "ui/base/clipboard/scoped_clipboard_writer.h" |
42 #include "ui/base/dragdrop/drag_drop_types.h" | 42 #include "ui/base/dragdrop/drag_drop_types.h" |
43 #include "ui/base/dragdrop/drag_source.h" | 43 #include "ui/base/dragdrop/drag_source.h" |
44 #include "ui/base/dragdrop/drop_target.h" | 44 #include "ui/base/dragdrop/drop_target.h" |
45 #include "ui/base/dragdrop/os_exchange_data.h" | 45 #include "ui/base/dragdrop/os_exchange_data.h" |
46 #include "ui/base/dragdrop/os_exchange_data_provider_win.h" | 46 #include "ui/base/dragdrop/os_exchange_data_provider_win.h" |
47 #include "ui/base/events.h" | 47 #include "ui/base/events.h" |
48 #include "ui/base/keycodes/keyboard_codes.h" | 48 #include "ui/base/keycodes/keyboard_codes.h" |
49 #include "ui/base/l10n/l10n_util.h" | 49 #include "ui/base/l10n/l10n_util.h" |
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
299 if (text_object_model_) | 299 if (text_object_model_) |
300 text_object_model_->Undo(tomSuspend, NULL); | 300 text_object_model_->Undo(tomSuspend, NULL); |
301 } | 301 } |
302 | 302 |
303 OmniboxViewWin::ScopedSuspendUndo::~ScopedSuspendUndo() { | 303 OmniboxViewWin::ScopedSuspendUndo::~ScopedSuspendUndo() { |
304 // Resume Undo processing. | 304 // Resume Undo processing. |
305 if (text_object_model_) | 305 if (text_object_model_) |
306 text_object_model_->Undo(tomResume, NULL); | 306 text_object_model_->Undo(tomResume, NULL); |
307 } | 307 } |
308 | 308 |
309 // A subclass of NativeViewHost that provides accessibility info for the | |
310 // underlying Omnibox view. | |
311 class OmniboxViewWrapper : public views::NativeViewHost { | |
312 public: | |
313 explicit OmniboxViewWrapper(OmniboxViewWin* omnibox_view_win) | |
314 : omnibox_view_win_(omnibox_view_win) { } | |
315 | |
316 gfx::NativeViewAccessible GetNativeViewAccessible() { | |
317 // This forces it to use NativeViewAccessibilityWin rather than | |
318 // any accessibility provided natively by the HWND. | |
319 return View::GetNativeViewAccessible(); | |
320 } | |
321 | |
322 // views::View | |
323 virtual void GetAccessibleState(ui::AccessibleViewState* state) { | |
324 state->name = l10n_util::GetStringUTF16(IDS_ACCNAME_LOCATION); | |
325 state->role = ui::AccessibilityTypes::ROLE_TEXT; | |
326 state->value = omnibox_view_win_->GetText(); | |
327 state->state = ui::AccessibilityTypes::STATE_EDITABLE; | |
328 size_t sel_start; | |
329 size_t sel_end; | |
330 omnibox_view_win_->GetSelectionBounds(&sel_start, &sel_end); | |
331 state->selection_start = sel_start; | |
332 state->selection_end = sel_end; | |
sky
2011/10/25 20:08:45
Is this ok if sel_start > sel_end?
dmazzoni
2011/10/26 16:46:13
Yes, I tested creating a selection using shift+rig
| |
333 } | |
334 | |
335 private: | |
336 OmniboxViewWin* omnibox_view_win_; | |
337 }; | |
sky
2011/10/25 20:08:45
DISALLOW_COPY_AND_ASSIGN
dmazzoni
2011/10/26 16:46:13
Done.
| |
338 | |
309 /////////////////////////////////////////////////////////////////////////////// | 339 /////////////////////////////////////////////////////////////////////////////// |
310 // OmniboxViewWin | 340 // OmniboxViewWin |
311 | 341 |
312 namespace { | 342 namespace { |
313 | 343 |
314 // These are used to hook the CRichEditCtrl's calls to BeginPaint() and | 344 // These are used to hook the CRichEditCtrl's calls to BeginPaint() and |
315 // EndPaint() and provide a memory DC instead. See OnPaint(). | 345 // EndPaint() and provide a memory DC instead. See OnPaint(). |
316 HWND edit_hwnd = NULL; | 346 HWND edit_hwnd = NULL; |
317 PAINTSTRUCT paint_struct; | 347 PAINTSTRUCT paint_struct; |
318 | 348 |
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
660 CHARRANGE selection; | 690 CHARRANGE selection; |
661 GetSel(selection); | 691 GetSel(selection); |
662 return IsSelectAllForRange(selection); | 692 return IsSelectAllForRange(selection); |
663 } | 693 } |
664 | 694 |
665 bool OmniboxViewWin::DeleteAtEndPressed() { | 695 bool OmniboxViewWin::DeleteAtEndPressed() { |
666 return delete_at_end_pressed_; | 696 return delete_at_end_pressed_; |
667 } | 697 } |
668 | 698 |
669 void OmniboxViewWin::GetSelectionBounds(string16::size_type* start, | 699 void OmniboxViewWin::GetSelectionBounds(string16::size_type* start, |
670 string16::size_type* end) { | 700 string16::size_type* end) const { |
671 CHARRANGE selection; | 701 CHARRANGE selection; |
672 GetSel(selection); | 702 GetSel(selection); |
673 *start = static_cast<size_t>(selection.cpMin); | 703 *start = static_cast<size_t>(selection.cpMin); |
674 *end = static_cast<size_t>(selection.cpMax); | 704 *end = static_cast<size_t>(selection.cpMax); |
675 } | 705 } |
676 | 706 |
677 void OmniboxViewWin::SelectAll(bool reversed) { | 707 void OmniboxViewWin::SelectAll(bool reversed) { |
678 if (reversed) | 708 if (reversed) |
679 SetSelection(GetTextLength(), 0); | 709 SetSelection(GetTextLength(), 0); |
680 else | 710 else |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
717 } | 747 } |
718 | 748 |
719 void OmniboxViewWin::ClosePopup() { | 749 void OmniboxViewWin::ClosePopup() { |
720 model_->StopAutocomplete(); | 750 model_->StopAutocomplete(); |
721 } | 751 } |
722 | 752 |
723 void OmniboxViewWin::SetFocus() { | 753 void OmniboxViewWin::SetFocus() { |
724 ::SetFocus(m_hWnd); | 754 ::SetFocus(m_hWnd); |
725 } | 755 } |
726 | 756 |
727 IAccessible* OmniboxViewWin::GetIAccessible() { | |
728 if (!autocomplete_accessibility_) { | |
729 CComObject<AutocompleteAccessibility>* accessibility = NULL; | |
730 if (!SUCCEEDED(CComObject<AutocompleteAccessibility>::CreateInstance( | |
731 &accessibility)) || !accessibility) | |
732 return NULL; | |
733 | |
734 // Wrap the created object in a smart pointer so it won't leak. | |
735 base::win::ScopedComPtr<IAccessible> accessibility_comptr(accessibility); | |
736 if (!SUCCEEDED(accessibility->Initialize(this))) | |
737 return NULL; | |
738 | |
739 // Copy to the class smart pointer, and notify that an instance of | |
740 // IAccessible was allocated for m_hWnd. | |
741 autocomplete_accessibility_ = accessibility_comptr; | |
742 NotifyWinEvent(EVENT_OBJECT_CREATE, m_hWnd, OBJID_CLIENT, CHILDID_SELF); | |
743 } | |
744 // Detach to leave ref counting to the caller. | |
745 return autocomplete_accessibility_.Detach(); | |
746 } | |
747 | |
748 void OmniboxViewWin::SetDropHighlightPosition(int position) { | 757 void OmniboxViewWin::SetDropHighlightPosition(int position) { |
749 if (drop_highlight_position_ != position) { | 758 if (drop_highlight_position_ != position) { |
750 RepaintDropHighlight(drop_highlight_position_); | 759 RepaintDropHighlight(drop_highlight_position_); |
751 drop_highlight_position_ = position; | 760 drop_highlight_position_ = position; |
752 RepaintDropHighlight(drop_highlight_position_); | 761 RepaintDropHighlight(drop_highlight_position_); |
753 } | 762 } |
754 } | 763 } |
755 | 764 |
756 void OmniboxViewWin::MoveSelectedText(int new_position) { | 765 void OmniboxViewWin::MoveSelectedText(int new_position) { |
757 const string16 selected_text(GetSelectedText()); | 766 const string16 selected_text(GetSelectedText()); |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
878 | 887 |
879 if (selection_differs) | 888 if (selection_differs) |
880 controller_->OnSelectionBoundsChanged(); | 889 controller_->OnSelectionBoundsChanged(); |
881 | 890 |
882 if (something_changed && text_differs) | 891 if (something_changed && text_differs) |
883 TextChanged(); | 892 TextChanged(); |
884 | 893 |
885 if (text_differs) { | 894 if (text_differs) { |
886 // Note that a TEXT_CHANGED event implies that the cursor/selection | 895 // Note that a TEXT_CHANGED event implies that the cursor/selection |
887 // probably changed too, so we don't need to send both. | 896 // probably changed too, so we don't need to send both. |
888 parent_view_->GetWidget()->NotifyAccessibilityEvent( | 897 native_view_host_->GetWidget()->NotifyAccessibilityEvent( |
889 parent_view_, ui::AccessibilityTypes::EVENT_TEXT_CHANGED, true); | 898 native_view_host_, ui::AccessibilityTypes::EVENT_TEXT_CHANGED, true); |
890 } else if (selection_differs) { | 899 } else if (selection_differs) { |
891 // Notify assistive technology that the cursor or selection changed. | 900 // Notify assistive technology that the cursor or selection changed. |
892 parent_view_->GetWidget()->NotifyAccessibilityEvent( | 901 native_view_host_->GetWidget()->NotifyAccessibilityEvent( |
893 parent_view_, ui::AccessibilityTypes::EVENT_SELECTION_CHANGED, true); | 902 native_view_host_, |
903 ui::AccessibilityTypes::EVENT_SELECTION_CHANGED, | |
904 true); | |
894 } else if (delete_at_end_pressed_) { | 905 } else if (delete_at_end_pressed_) { |
895 model_->OnChanged(); | 906 model_->OnChanged(); |
896 } | 907 } |
897 | 908 |
898 return something_changed; | 909 return something_changed; |
899 } | 910 } |
900 | 911 |
901 gfx::NativeView OmniboxViewWin::GetNativeView() const { | 912 gfx::NativeView OmniboxViewWin::GetNativeView() const { |
902 return m_hWnd; | 913 return m_hWnd; |
903 } | 914 } |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
940 bool ime_composing = false; | 951 bool ime_composing = false; |
941 HIMC context = ImmGetContext(m_hWnd); | 952 HIMC context = ImmGetContext(m_hWnd); |
942 if (context) { | 953 if (context) { |
943 ime_composing = !!ImmGetCompositionString(context, GCS_COMPSTR, NULL, 0); | 954 ime_composing = !!ImmGetCompositionString(context, GCS_COMPSTR, NULL, 0); |
944 ImmReleaseContext(m_hWnd, context); | 955 ImmReleaseContext(m_hWnd, context); |
945 } | 956 } |
946 return ime_composing; | 957 return ime_composing; |
947 } | 958 } |
948 | 959 |
949 views::View* OmniboxViewWin::AddToView(views::View* parent) { | 960 views::View* OmniboxViewWin::AddToView(views::View* parent) { |
950 views::NativeViewHost* host = new views::NativeViewHost; | 961 native_view_host_ = new OmniboxViewWrapper(this); |
951 parent->AddChildView(host); | 962 parent->AddChildView(native_view_host_); |
952 host->set_focus_view(parent); | 963 native_view_host_->set_focus_view(parent); |
David Tseng
2011/10/25 21:55:25
On Windows, is the focused view the parent? (Locat
dmazzoni
2011/10/26 16:46:13
I think this doesn't affect native focus, it just
David Tseng
2011/10/27 20:42:16
Ok; I did see two native IAccessible's with focuse
| |
953 host->Attach(GetNativeView()); | 964 native_view_host_->Attach(GetNativeView()); |
954 return host; | 965 return native_view_host_; |
955 } | 966 } |
956 | 967 |
957 int OmniboxViewWin::OnPerformDrop(const views::DropTargetEvent& event) { | 968 int OmniboxViewWin::OnPerformDrop(const views::DropTargetEvent& event) { |
958 return OnPerformDropImpl(event, false); | 969 return OnPerformDropImpl(event, false); |
959 } | 970 } |
960 | 971 |
961 int OmniboxViewWin::OnPerformDropImpl(const views::DropTargetEvent& event, | 972 int OmniboxViewWin::OnPerformDropImpl(const views::DropTargetEvent& event, |
962 bool in_drag) { | 973 bool in_drag) { |
963 const ui::OSExchangeData& data = event.data(); | 974 const ui::OSExchangeData& data = event.data(); |
964 | 975 |
(...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1323 } | 1334 } |
1324 | 1335 |
1325 void OmniboxViewWin::OnCut() { | 1336 void OmniboxViewWin::OnCut() { |
1326 OnCopy(); | 1337 OnCopy(); |
1327 | 1338 |
1328 // This replace selection will have no effect (even on the undo stack) if the | 1339 // This replace selection will have no effect (even on the undo stack) if the |
1329 // current selection is empty. | 1340 // current selection is empty. |
1330 ReplaceSel(L"", true); | 1341 ReplaceSel(L"", true); |
1331 } | 1342 } |
1332 | 1343 |
1333 LRESULT OmniboxViewWin::OnGetObject(UINT uMsg, | 1344 LRESULT OmniboxViewWin::OnGetObject(UINT message, |
1334 WPARAM wparam, | 1345 WPARAM wparam, |
1335 LPARAM lparam) { | 1346 LPARAM lparam) { |
1336 // Accessibility readers will send an OBJID_CLIENT message. | 1347 // This is a request for the native accessibility object. |
1337 if (lparam == OBJID_CLIENT) { | 1348 if (lparam == OBJID_CLIENT) { |
1338 // Re-attach for internal re-usage of accessibility pointer. | 1349 return LresultFromObject(IID_IAccessible, wparam, |
1339 autocomplete_accessibility_.Attach(GetIAccessible()); | 1350 native_view_host_->GetNativeViewAccessible()); |
1340 | |
1341 if (autocomplete_accessibility_) { | |
1342 return LresultFromObject(IID_IAccessible, wparam, | |
1343 autocomplete_accessibility_); | |
1344 } | |
1345 } | 1351 } |
1346 return 0; | 1352 return 0; |
1347 } | 1353 } |
1348 | 1354 |
1349 LRESULT OmniboxViewWin::OnImeComposition(UINT message, | 1355 LRESULT OmniboxViewWin::OnImeComposition(UINT message, |
1350 WPARAM wparam, | 1356 WPARAM wparam, |
1351 LPARAM lparam) { | 1357 LPARAM lparam) { |
1352 if (ignore_ime_messages_) { | 1358 if (ignore_ime_messages_) { |
1353 // This message was sent while we're in the middle of meddling with the | 1359 // This message was sent while we're in the middle of meddling with the |
1354 // underlying edit control. If we handle it below, OnAfterPossibleChange() | 1360 // underlying edit control. If we handle it below, OnAfterPossibleChange() |
(...skipping 1257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2612 // PosFromChar(i) might return 0 when i is greater than 1. | 2618 // PosFromChar(i) might return 0 when i is greater than 1. |
2613 return font_.GetStringWidth(text) + GetHorizontalMargin(); | 2619 return font_.GetStringWidth(text) + GetHorizontalMargin(); |
2614 } | 2620 } |
2615 | 2621 |
2616 bool OmniboxViewWin::IsCaretAtEnd() const { | 2622 bool OmniboxViewWin::IsCaretAtEnd() const { |
2617 long length = GetTextLength(); | 2623 long length = GetTextLength(); |
2618 CHARRANGE sel; | 2624 CHARRANGE sel; |
2619 GetSelection(sel); | 2625 GetSelection(sel); |
2620 return sel.cpMin == sel.cpMax && sel.cpMin == length; | 2626 return sel.cpMin == sel.cpMax && sel.cpMin == length; |
2621 } | 2627 } |
OLD | NEW |