| Index: chrome/browser/ui/views/omnibox/omnibox_view_win.cc
|
| diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_win.cc b/chrome/browser/ui/views/omnibox/omnibox_view_win.cc
|
| index a881053eff79fde42adca6ee578942d24c66b7b6..17808d12f0460252d66469cd096d41a47560b574 100644
|
| --- a/chrome/browser/ui/views/omnibox/omnibox_view_win.cc
|
| +++ b/chrome/browser/ui/views/omnibox/omnibox_view_win.cc
|
| @@ -760,11 +760,41 @@ void OmniboxViewWin::UpdatePopup() {
|
|
|
| void OmniboxViewWin::SetFocus() {
|
| ::SetFocus(m_hWnd);
|
| + // Restore caret visibility if focused explicitly. We need to do this here
|
| + // because if we already have invisible focus, the ::SetFocus call above will
|
| + // short-circuit, preventing us from reaching OmniboxEditModel::OnSetFocus(),
|
| + // which handles restoring visibility when we didn't previously have focus.
|
| + model()->SetCaretVisibility(true);
|
| }
|
|
|
| void OmniboxViewWin::ApplyCaretVisibility() {
|
| - // TODO(mathp): implement for Windows.
|
| - NOTIMPLEMENTED();
|
| + // We hide the caret just before destroying it, since destroying a caret that
|
| + // is in the "solid" phase of its blinking will leave a solid vertical bar.
|
| + // We even hide and destroy the caret if we're going to create it again below.
|
| + // If the caret was already visible on entry to this function, the
|
| + // CreateCaret() call (which first destroys the old caret) might leave a solid
|
| + // vertical bar for the same reason as above. Unconditionally hiding prevents
|
| + // this. The caret could be visible on entry to this function if the
|
| + // underlying edit control had re-created it automatically (see comments in
|
| + // OnPaint()).
|
| + HideCaret();
|
| + // We use DestroyCaret()/CreateCaret() instead of simply HideCaret()/
|
| + // ShowCaret() because HideCaret() is not sticky across paint events, e.g. a
|
| + // window resize will effectively restore caret visibility, regardless of
|
| + // whether HideCaret() was called before. While we do catch and handle these
|
| + // paint events (see OnPaint()), it doesn't seem to be enough to simply call
|
| + // HideCaret() while handling them because of the unpredictability of this
|
| + // Windows API. According to the documentation, it should be a cumulative call
|
| + // e.g. 5 hide calls should be balanced by 5 show calls. We have not found
|
| + // this to be true, which may be explained by the fact that this API is called
|
| + // internally in Windows, as well.
|
| + ::DestroyCaret();
|
| + if (model()->is_caret_visible()) {
|
| + ::CreateCaret(m_hWnd, (HBITMAP) NULL, 1, font_.GetHeight());
|
| + // According to the Windows API documentation, a newly created caret needs
|
| + // ShowCaret to be visible.
|
| + ShowCaret();
|
| + }
|
| }
|
|
|
| void OmniboxViewWin::SetDropHighlightPosition(int position) {
|
| @@ -1741,7 +1771,7 @@ LRESULT OmniboxViewWin::OnMouseActivate(HWND window,
|
| // reached before OnXButtonDown(), preventing us from detecting this properly
|
| // there. Also in those cases, we need to already know in OnSetFocus() that
|
| // we should not restore the saved selection.
|
| - if (!model()->has_focus() &&
|
| + if ((!model()->has_focus() || !model()->is_caret_visible()) &&
|
| ((mouse_message == WM_LBUTTONDOWN || mouse_message == WM_RBUTTONDOWN)) &&
|
| (result == MA_ACTIVATE)) {
|
| if (gaining_focus_) {
|
| @@ -1751,6 +1781,11 @@ LRESULT OmniboxViewWin::OnMouseActivate(HWND window,
|
| return result;
|
| }
|
| gaining_focus_.reset(new ScopedFreeze(this, GetTextObjectModel()));
|
| +
|
| + // Explicitely set focus visibility in the case of clicking on the omnibox,
|
| + // which will remove invisible focus if present.
|
| + model()->SetCaretVisibility(true);
|
| +
|
| // NOTE: Despite |mouse_message| being WM_XBUTTONDOWN here, we're not
|
| // guaranteed to call OnXButtonDown() later! Specifically, if this is the
|
| // second click of a double click, we'll reach here but later call
|
| @@ -1899,6 +1934,12 @@ void OmniboxViewWin::OnPaint(HDC bogus_hdc) {
|
| rect.left, rect.top, SRCCOPY);
|
| memory_dc.SelectBitmap(old_bitmap);
|
| edit_hwnd = old_edit_hwnd;
|
| +
|
| + // This needs to be called regardless of the current state of the caret, even
|
| + // if reaffirming a current state (hidden or shown). This is because the
|
| + // underlying edit control will automatically re-create the caret when it
|
| + // receives certain events that trigger repaints, e.g. window resize events.
|
| + ApplyCaretVisibility();
|
| }
|
|
|
| void OmniboxViewWin::OnPaste() {
|
|
|