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/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 "base/win/metro.h" |
22 #include "base/win/scoped_hdc.h" | 23 #include "base/win/scoped_hdc.h" |
23 #include "base/win/scoped_select_object.h" | 24 #include "base/win/scoped_select_object.h" |
24 #include "base/win/windows_version.h" | 25 #include "base/win/windows_version.h" |
25 #include "chrome/app/chrome_command_ids.h" | 26 #include "chrome/app/chrome_command_ids.h" |
26 #include "chrome/browser/autocomplete/autocomplete_input.h" | 27 #include "chrome/browser/autocomplete/autocomplete_input.h" |
27 #include "chrome/browser/autocomplete/autocomplete_match.h" | 28 #include "chrome/browser/autocomplete/autocomplete_match.h" |
28 #include "chrome/browser/autocomplete/keyword_provider.h" | 29 #include "chrome/browser/autocomplete/keyword_provider.h" |
29 #include "chrome/browser/browser_process.h" | 30 #include "chrome/browser/browser_process.h" |
30 #include "chrome/browser/command_updater.h" | 31 #include "chrome/browser/command_updater.h" |
31 #include "chrome/browser/net/url_fixer_upper.h" | 32 #include "chrome/browser/net/url_fixer_upper.h" |
(...skipping 27 matching lines...) Expand all Loading... |
59 #include "ui/gfx/canvas.h" | 60 #include "ui/gfx/canvas.h" |
60 #include "ui/gfx/image/image.h" | 61 #include "ui/gfx/image/image.h" |
61 #include "ui/views/button_drag_utils.h" | 62 #include "ui/views/button_drag_utils.h" |
62 #include "ui/views/controls/menu/menu_item_view.h" | 63 #include "ui/views/controls/menu/menu_item_view.h" |
63 #include "ui/views/controls/menu/menu_model_adapter.h" | 64 #include "ui/views/controls/menu/menu_model_adapter.h" |
64 #include "ui/views/controls/menu/menu_runner.h" | 65 #include "ui/views/controls/menu/menu_runner.h" |
65 #include "ui/views/controls/textfield/native_textfield_win.h" | 66 #include "ui/views/controls/textfield/native_textfield_win.h" |
66 #include "ui/views/widget/widget.h" | 67 #include "ui/views/widget/widget.h" |
67 | 68 |
68 #pragma comment(lib, "oleacc.lib") // Needed for accessibility support. | 69 #pragma comment(lib, "oleacc.lib") // Needed for accessibility support. |
69 #pragma comment(lib, "riched20.lib") // Needed for the richedit control. | |
70 | 70 |
71 using content::UserMetricsAction; | 71 using content::UserMetricsAction; |
72 using content::WebContents; | 72 using content::WebContents; |
73 | 73 |
74 namespace { | 74 namespace { |
75 | 75 |
76 // A helper method for determining a valid DROPEFFECT given the allowed | 76 // A helper method for determining a valid DROPEFFECT given the allowed |
77 // DROPEFFECTS. We prefer copy over link. | 77 // DROPEFFECTS. We prefer copy over link. |
78 DWORD CopyOrLinkDropEffect(DWORD effect) { | 78 DWORD CopyOrLinkDropEffect(DWORD effect) { |
79 if (effect & DROPEFFECT_COPY) | 79 if (effect & DROPEFFECT_COPY) |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
111 const OmniboxViewWin::State view_state; | 111 const OmniboxViewWin::State view_state; |
112 }; | 112 }; |
113 | 113 |
114 // Returns true if the current point is far enough from the origin that it | 114 // Returns true if the current point is far enough from the origin that it |
115 // would be considered a drag. | 115 // would be considered a drag. |
116 bool IsDrag(const POINT& origin, const POINT& current) { | 116 bool IsDrag(const POINT& origin, const POINT& current) { |
117 return views::View::ExceededDragThreshold(current.x - origin.x, | 117 return views::View::ExceededDragThreshold(current.x - origin.x, |
118 current.y - origin.y); | 118 current.y - origin.y); |
119 } | 119 } |
120 | 120 |
| 121 const wchar_t* GetRichEditDLLName() { |
| 122 // msftedit.dll is RichEdit ver 4.1. |
| 123 // This version is available from WinXP SP1 and has TSF support. |
| 124 // To minimize the compatibility risk, ver 4.1 is only used |
| 125 // when TSF-aware is required. |
| 126 // At this moment (2012-08-09), only Windows 8 style UI requires it. |
| 127 return base::win::IsTsfAwareRequired() ? L"msftedit.dll": L"riched20.dll"; |
| 128 } |
| 129 |
121 } // namespace | 130 } // namespace |
122 | 131 |
123 // EditDropTarget is the IDropTarget implementation installed on | 132 // EditDropTarget is the IDropTarget implementation installed on |
124 // OmniboxViewWin. EditDropTarget prefers URL over plain text. A drop | 133 // OmniboxViewWin. EditDropTarget prefers URL over plain text. A drop |
125 // of a URL replaces all the text of the edit and navigates immediately to the | 134 // of a URL replaces all the text of the edit and navigates immediately to the |
126 // URL. A drop of plain text from the same edit either copies or moves the | 135 // URL. A drop of plain text from the same edit either copies or moves the |
127 // selected text, and a drop of plain text from a source other than the edit | 136 // selected text, and a drop of plain text from a source other than the edit |
128 // does a paste and go. | 137 // does a paste and go. |
129 class OmniboxViewWin::EditDropTarget : public ui::DropTarget { | 138 class OmniboxViewWin::EditDropTarget : public ui::DropTarget { |
130 public: | 139 public: |
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
398 } | 407 } |
399 | 408 |
400 PaintPatcher::~PaintPatcher() { | 409 PaintPatcher::~PaintPatcher() { |
401 DCHECK_EQ(0U, refcount_); | 410 DCHECK_EQ(0U, refcount_); |
402 } | 411 } |
403 | 412 |
404 void PaintPatcher::RefPatch() { | 413 void PaintPatcher::RefPatch() { |
405 if (refcount_ == 0) { | 414 if (refcount_ == 0) { |
406 DCHECK(!begin_paint_.is_patched()); | 415 DCHECK(!begin_paint_.is_patched()); |
407 DCHECK(!end_paint_.is_patched()); | 416 DCHECK(!end_paint_.is_patched()); |
408 begin_paint_.Patch(L"riched20.dll", "user32.dll", "BeginPaint", | 417 const wchar_t* rich_edit_dll_name = GetRichEditDLLName(); |
| 418 begin_paint_.Patch(rich_edit_dll_name, "user32.dll", "BeginPaint", |
409 &BeginPaintIntercept); | 419 &BeginPaintIntercept); |
410 end_paint_.Patch(L"riched20.dll", "user32.dll", "EndPaint", | 420 end_paint_.Patch(rich_edit_dll_name, "user32.dll", "EndPaint", |
411 &EndPaintIntercept); | 421 &EndPaintIntercept); |
412 } | 422 } |
413 ++refcount_; | 423 ++refcount_; |
414 } | 424 } |
415 | 425 |
416 void PaintPatcher::DerefPatch() { | 426 void PaintPatcher::DerefPatch() { |
417 DCHECK(begin_paint_.is_patched()); | 427 DCHECK(begin_paint_.is_patched()); |
418 DCHECK(end_paint_.is_patched()); | 428 DCHECK(end_paint_.is_patched()); |
419 --refcount_; | 429 --refcount_; |
420 if (refcount_ == 0) { | 430 if (refcount_ == 0) { |
421 begin_paint_.Unpatch(); | 431 begin_paint_.Unpatch(); |
422 end_paint_.Unpatch(); | 432 end_paint_.Unpatch(); |
423 } | 433 } |
424 } | 434 } |
425 | 435 |
426 base::LazyInstance<PaintPatcher> g_paint_patcher = LAZY_INSTANCE_INITIALIZER; | 436 base::LazyInstance<PaintPatcher> g_paint_patcher = LAZY_INSTANCE_INITIALIZER; |
427 | 437 |
428 // twips are a unit of type measurement, and RichEdit controls use them | 438 // twips are a unit of type measurement, and RichEdit controls use them |
429 // to set offsets. | 439 // to set offsets. |
430 const int kTwipsPerInch = 1440; | 440 const int kTwipsPerInch = 1440; |
431 | 441 |
432 } // namespace | 442 } // namespace |
433 | 443 |
| 444 bool OmniboxViewWin::did_load_library_ = false; |
| 445 |
434 OmniboxViewWin::OmniboxViewWin(OmniboxEditController* controller, | 446 OmniboxViewWin::OmniboxViewWin(OmniboxEditController* controller, |
435 ToolbarModel* toolbar_model, | 447 ToolbarModel* toolbar_model, |
436 LocationBarView* parent_view, | 448 LocationBarView* parent_view, |
437 CommandUpdater* command_updater, | 449 CommandUpdater* command_updater, |
438 bool popup_window_mode, | 450 bool popup_window_mode, |
439 views::View* location_bar, | 451 views::View* location_bar, |
440 views::View* popup_parent_view) | 452 views::View* popup_parent_view) |
441 : OmniboxView(parent_view->profile(), controller, toolbar_model, | 453 : OmniboxView(parent_view->profile(), controller, toolbar_model, |
442 command_updater), | 454 command_updater), |
443 popup_view_(OmniboxPopupContentsView::Create( | 455 popup_view_(OmniboxPopupContentsView::Create( |
(...skipping 11 matching lines...) Expand all Loading... |
455 font_(parent_view->font()), | 467 font_(parent_view->font()), |
456 possible_drag_(false), | 468 possible_drag_(false), |
457 in_drag_(false), | 469 in_drag_(false), |
458 initiated_drag_(false), | 470 initiated_drag_(false), |
459 drop_highlight_position_(-1), | 471 drop_highlight_position_(-1), |
460 ime_candidate_window_open_(false), | 472 ime_candidate_window_open_(false), |
461 background_color_(skia::SkColorToCOLORREF(LocationBarView::GetColor( | 473 background_color_(skia::SkColorToCOLORREF(LocationBarView::GetColor( |
462 ToolbarModel::NONE, LocationBarView::BACKGROUND))), | 474 ToolbarModel::NONE, LocationBarView::BACKGROUND))), |
463 security_level_(ToolbarModel::NONE), | 475 security_level_(ToolbarModel::NONE), |
464 text_object_model_(NULL) { | 476 text_object_model_(NULL) { |
465 // Dummy call to a function exported by riched20.dll to ensure it sets up an | 477 if (!did_load_library_) { |
466 // import dependency on the dll. | 478 did_load_library_ = !!LoadLibrary(GetRichEditDLLName()); |
467 CreateTextServices(NULL, NULL, NULL); | 479 } |
468 | 480 |
469 saved_selection_for_focus_change_.cpMin = -1; | 481 saved_selection_for_focus_change_.cpMin = -1; |
470 | 482 |
471 g_paint_patcher.Pointer()->RefPatch(); | 483 g_paint_patcher.Pointer()->RefPatch(); |
472 | 484 |
473 Create(location_bar->GetWidget()->GetNativeView(), 0, 0, 0, | 485 Create(location_bar->GetWidget()->GetNativeView(), 0, 0, 0, |
474 l10n_util::GetExtendedStyles()); | 486 l10n_util::GetExtendedStyles()); |
475 SetReadOnly(popup_window_mode_); | 487 SetReadOnly(popup_window_mode_); |
476 SetFont(font_.GetNativeFont()); | 488 SetFont(font_.GetNativeFont()); |
477 | 489 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
531 // initialized, it may still be null. | 543 // initialized, it may still be null. |
532 if (text_object_model_) | 544 if (text_object_model_) |
533 text_object_model_->Release(); | 545 text_object_model_->Release(); |
534 | 546 |
535 // We balance our reference count and unpatch when the last instance has | 547 // We balance our reference count and unpatch when the last instance has |
536 // been destroyed. This prevents us from relying on the AtExit or static | 548 // been destroyed. This prevents us from relying on the AtExit or static |
537 // destructor sequence to do our unpatching, which is generally fragile. | 549 // destructor sequence to do our unpatching, which is generally fragile. |
538 g_paint_patcher.Pointer()->DerefPatch(); | 550 g_paint_patcher.Pointer()->DerefPatch(); |
539 } | 551 } |
540 | 552 |
| 553 CWndClassInfo& OmniboxViewWin::GetWndClassInfo() { |
| 554 const wchar_t* kRichEditClass = base::win::IsTsfAwareRequired() ? |
| 555 MSFTEDIT_CLASS : RICHEDIT_CLASS; |
| 556 static CWndClassInfo wc = { |
| 557 {sizeof(WNDCLASSEX), 0, StartWindowProc, |
| 558 0, 0, NULL, NULL, NULL, NULL, NULL, L"Chrome_OmniboxView", NULL}, |
| 559 kRichEditClass, NULL, NULL, TRUE, 0, _T("")}; |
| 560 return wc; |
| 561 } |
| 562 |
541 views::View* OmniboxViewWin::parent_view() const { | 563 views::View* OmniboxViewWin::parent_view() const { |
542 return parent_view_; | 564 return parent_view_; |
543 } | 565 } |
544 | 566 |
545 void OmniboxViewWin::SaveStateToTab(WebContents* tab) { | 567 void OmniboxViewWin::SaveStateToTab(WebContents* tab) { |
546 DCHECK(tab); | 568 DCHECK(tab); |
547 | 569 |
548 const OmniboxEditModel::State model_state(model()->GetStateForTabSwitch()); | 570 const OmniboxEditModel::State model_state(model()->GetStateForTabSwitch()); |
549 | 571 |
550 CHARRANGE selection; | 572 CHARRANGE selection; |
(...skipping 781 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1332 // GetSel() doesn't preserve selection direction, so sel.cpMin will always be | 1354 // GetSel() doesn't preserve selection direction, so sel.cpMin will always be |
1333 // the smaller value. | 1355 // the smaller value. |
1334 model()->AdjustTextForCopy(sel.cpMin, IsSelectAll(), &text, &url, &write_url); | 1356 model()->AdjustTextForCopy(sel.cpMin, IsSelectAll(), &text, &url, &write_url); |
1335 ui::ScopedClipboardWriter scw(g_browser_process->clipboard(), | 1357 ui::ScopedClipboardWriter scw(g_browser_process->clipboard(), |
1336 ui::Clipboard::BUFFER_STANDARD); | 1358 ui::Clipboard::BUFFER_STANDARD); |
1337 scw.WriteText(text); | 1359 scw.WriteText(text); |
1338 if (write_url) | 1360 if (write_url) |
1339 scw.WriteBookmark(text, url.spec()); | 1361 scw.WriteBookmark(text, url.spec()); |
1340 } | 1362 } |
1341 | 1363 |
| 1364 LRESULT OmniboxViewWin::OnCreate(const CREATESTRUCTW* /*create_struct*/) { |
| 1365 if (base::win::IsTsfAwareRequired()) { |
| 1366 // Enable TSF support of RichEdit. |
| 1367 SetEditStyle(SES_USECTF, SES_USECTF); |
| 1368 } |
| 1369 SetMsgHandled(FALSE); |
| 1370 return 0; |
| 1371 } |
| 1372 |
1342 void OmniboxViewWin::OnCut() { | 1373 void OmniboxViewWin::OnCut() { |
1343 OnCopy(); | 1374 OnCopy(); |
1344 | 1375 |
1345 // This replace selection will have no effect (even on the undo stack) if the | 1376 // This replace selection will have no effect (even on the undo stack) if the |
1346 // current selection is empty. | 1377 // current selection is empty. |
1347 ReplaceSel(L"", true); | 1378 ReplaceSel(L"", true); |
1348 } | 1379 } |
1349 | 1380 |
1350 LRESULT OmniboxViewWin::OnGetObject(UINT message, | 1381 LRESULT OmniboxViewWin::OnGetObject(UINT message, |
1351 WPARAM wparam, | 1382 WPARAM wparam, |
(...skipping 1279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2631 return (rect.left - client_rect.left) + (client_rect.right - rect.right); | 2662 return (rect.left - client_rect.left) + (client_rect.right - rect.right); |
2632 } | 2663 } |
2633 | 2664 |
2634 int OmniboxViewWin::WidthNeededToDisplay(const string16& text) const { | 2665 int OmniboxViewWin::WidthNeededToDisplay(const string16& text) const { |
2635 // Use font_.GetStringWidth() instead of | 2666 // Use font_.GetStringWidth() instead of |
2636 // PosFromChar(location_entry_->GetTextLength()) because PosFromChar() is | 2667 // PosFromChar(location_entry_->GetTextLength()) because PosFromChar() is |
2637 // apparently buggy. In both LTR UI and RTL UI with left-to-right layout, | 2668 // apparently buggy. In both LTR UI and RTL UI with left-to-right layout, |
2638 // PosFromChar(i) might return 0 when i is greater than 1. | 2669 // PosFromChar(i) might return 0 when i is greater than 1. |
2639 return font_.GetStringWidth(text) + GetHorizontalMargin(); | 2670 return font_.GetStringWidth(text) + GetHorizontalMargin(); |
2640 } | 2671 } |
OLD | NEW |