1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/ui/views/autofill/autofill_popup_base_view.h"
8 #include "base/location.h"
9 #include "base/message_loop/message_loop.h"
10 #include "chrome/browser/ui/autofill/popup_constants.h"
11 #include "ui/views/border.h"
12 #include "ui/views/focus/focus_manager.h"
13 #include "ui/views/widget/widget.h"
17 const SkColor
AutofillPopupBaseView::kBorderColor
=
18 SkColorSetARGB(0xFF, 0xC7, 0xCA, 0xCE);
19 const SkColor
AutofillPopupBaseView::kHoveredBackgroundColor
=
20 SkColorSetARGB(0xFF, 0xCD, 0xCD, 0xCD);
21 const SkColor
AutofillPopupBaseView::kItemTextColor
=
22 SkColorSetARGB(0xFF, 0x7F, 0x7F, 0x7F);
23 const SkColor
AutofillPopupBaseView::kPopupBackground
=
24 SkColorSetARGB(0xFF, 0xFF, 0xFF, 0xFF);
25 const SkColor
AutofillPopupBaseView::kValueTextColor
=
26 SkColorSetARGB(0xFF, 0x00, 0x00, 0x00);
27 const SkColor
AutofillPopupBaseView::kWarningTextColor
=
28 SkColorSetARGB(0xFF, 0x7F, 0x7F, 0x7F);
30 AutofillPopupBaseView::AutofillPopupBaseView(
31 AutofillPopupViewDelegate
* delegate
,
32 views::FocusManager
* focus_manager
)
33 : delegate_(delegate
),
34 focus_manager_(focus_manager
),
35 weak_ptr_factory_(this) {}
37 AutofillPopupBaseView::~AutofillPopupBaseView() {
39 delegate_
->ViewDestroyed();
45 void AutofillPopupBaseView::DoShow() {
46 const bool initialize_widget
= !GetWidget();
47 if (initialize_widget
) {
48 focus_manager_
->RegisterAccelerator(
49 ui::Accelerator(ui::VKEY_RETURN
, ui::EF_NONE
),
50 ui::AcceleratorManager::kNormalPriority
,
52 focus_manager_
->RegisterAccelerator(
53 ui::Accelerator(ui::VKEY_ESCAPE
, ui::EF_NONE
),
54 ui::AcceleratorManager::kNormalPriority
,
57 // The widget is destroyed by the corresponding NativeWidget, so we use
58 // a weak pointer to hold the reference and don't have to worry about
60 views::Widget
* widget
= new views::Widget
;
61 views::Widget::InitParams
params(views::Widget::InitParams::TYPE_POPUP
);
62 params
.delegate
= this;
63 params
.parent
= container_view();
65 widget
->SetContentsView(this);
67 // No animation for popup appearance (too distracting).
68 widget
->SetVisibilityAnimationTransition(views::Widget::ANIMATE_HIDE
);
71 SetBorder(views::Border::CreateSolidBorder(kPopupBorderThickness
,
74 DoUpdateBoundsAndRedrawPopup();
77 // Showing the widget can change native focus (which would result in an
78 // immediate hiding of the popup). Only start observing after shown.
79 if (initialize_widget
)
80 views::WidgetFocusManager::GetInstance()->AddFocusChangeListener(this);
83 void AutofillPopupBaseView::DoHide() {
84 // The controller is no longer valid after it hides us.
90 // Don't call CloseNow() because some of the functions higher up the stack
91 // assume the the widget is still valid after this point.
92 // http://crbug.com/229224
93 // NOTE: This deletes |this|.
100 void AutofillPopupBaseView::RemoveObserver() {
101 focus_manager_
->UnregisterAccelerators(this);
102 views::WidgetFocusManager::GetInstance()->RemoveFocusChangeListener(this);
105 void AutofillPopupBaseView::DoUpdateBoundsAndRedrawPopup() {
106 GetWidget()->SetBounds(delegate_
->popup_bounds());
110 void AutofillPopupBaseView::OnNativeFocusChange(
111 gfx::NativeView focused_before
,
112 gfx::NativeView focused_now
) {
113 if (GetWidget() && GetWidget()->GetNativeView() != focused_now
)
117 void AutofillPopupBaseView::OnMouseCaptureLost() {
121 bool AutofillPopupBaseView::OnMouseDragged(const ui::MouseEvent
& event
) {
122 if (HitTestPoint(event
.location())) {
123 SetSelection(event
.location());
125 // We must return true in order to get future OnMouseDragged and
126 // OnMouseReleased events.
130 // If we move off of the popup, we lose the selection.
135 void AutofillPopupBaseView::OnMouseExited(const ui::MouseEvent
& event
) {
136 // Pressing return causes the cursor to hide, which will generate an
137 // OnMouseExited event. Pressing return should activate the current selection
138 // via AcceleratorPressed, so we need to let that run first.
139 base::MessageLoop::current()->PostTask(
141 base::Bind(&AutofillPopupBaseView::ClearSelection
,
142 weak_ptr_factory_
.GetWeakPtr()));
145 void AutofillPopupBaseView::OnMouseMoved(const ui::MouseEvent
& event
) {
146 // A synthesized mouse move will be sent when the popup is first shown.
147 // Don't preview a suggestion if the mouse happens to be hovering there.
148 if (event
.flags() & ui::EF_IS_SYNTHESIZED
)
151 if (HitTestPoint(event
.location()))
152 SetSelection(event
.location());
157 bool AutofillPopupBaseView::OnMousePressed(const ui::MouseEvent
& event
) {
158 return event
.GetClickCount() == 1;
161 void AutofillPopupBaseView::OnMouseReleased(const ui::MouseEvent
& event
) {
162 // We only care about the left click.
163 if (event
.IsOnlyLeftMouseButton() && HitTestPoint(event
.location()))
164 AcceptSelection(event
.location());
167 void AutofillPopupBaseView::OnGestureEvent(ui::GestureEvent
* event
) {
168 switch (event
->type()) {
169 case ui::ET_GESTURE_TAP_DOWN
:
170 case ui::ET_GESTURE_SCROLL_BEGIN
:
171 case ui::ET_GESTURE_SCROLL_UPDATE
:
172 if (HitTestPoint(event
->location()))
173 SetSelection(event
->location());
177 case ui::ET_GESTURE_TAP
:
178 case ui::ET_GESTURE_SCROLL_END
:
179 if (HitTestPoint(event
->location()))
180 AcceptSelection(event
->location());
184 case ui::ET_GESTURE_TAP_CANCEL
:
185 case ui::ET_SCROLL_FLING_START
:
194 bool AutofillPopupBaseView::AcceleratorPressed(
195 const ui::Accelerator
& accelerator
) {
196 DCHECK_EQ(accelerator
.modifiers(), ui::EF_NONE
);
198 if (accelerator
.key_code() == ui::VKEY_ESCAPE
) {
203 if (accelerator
.key_code() == ui::VKEY_RETURN
)
204 return delegate_
->AcceptSelectedLine();
210 void AutofillPopupBaseView::SetSelection(const gfx::Point
& point
) {
212 delegate_
->SetSelectionAtPoint(point
);
215 void AutofillPopupBaseView::AcceptSelection(const gfx::Point
& point
) {
219 delegate_
->SetSelectionAtPoint(point
);
220 delegate_
->AcceptSelectedLine();
223 void AutofillPopupBaseView::ClearSelection() {
225 delegate_
->SelectionCleared();
228 void AutofillPopupBaseView::HideController() {
233 gfx::NativeView
AutofillPopupBaseView::container_view() {
234 return delegate_
->container_view();
237 } // namespace autofill