autofill_popup_base_view.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
1255e72915d4cbddceb435e13d81601755714e9fSE Android// Copyright 2014 The Chromium Authors. All rights reserved.
2255e72915d4cbddceb435e13d81601755714e9fSE Android// Use of this source code is governed by a BSD-style license that can be
3255e72915d4cbddceb435e13d81601755714e9fSE Android// found in the LICENSE file.
4255e72915d4cbddceb435e13d81601755714e9fSE Android
5255e72915d4cbddceb435e13d81601755714e9fSE Android#include "chrome/browser/ui/views/autofill/autofill_popup_base_view.h"
6255e72915d4cbddceb435e13d81601755714e9fSE Android
7255e72915d4cbddceb435e13d81601755714e9fSE Android#include "chrome/browser/ui/autofill/popup_constants.h"
8255e72915d4cbddceb435e13d81601755714e9fSE Android#include "ui/gfx/point.h"
9255e72915d4cbddceb435e13d81601755714e9fSE Android#include "ui/gfx/screen.h"
10255e72915d4cbddceb435e13d81601755714e9fSE Android#include "ui/views/border.h"
11255e72915d4cbddceb435e13d81601755714e9fSE Android#include "ui/views/event_utils.h"
12255e72915d4cbddceb435e13d81601755714e9fSE Android#include "ui/views/widget/widget.h"
13255e72915d4cbddceb435e13d81601755714e9fSE Android
14255e72915d4cbddceb435e13d81601755714e9fSE Android#if defined(USE_AURA)
15255e72915d4cbddceb435e13d81601755714e9fSE Android#include "ui/views/corewm/window_animations.h"
16255e72915d4cbddceb435e13d81601755714e9fSE Android#endif
17255e72915d4cbddceb435e13d81601755714e9fSE Android
18255e72915d4cbddceb435e13d81601755714e9fSE Androidnamespace autofill {
19255e72915d4cbddceb435e13d81601755714e9fSE Android
20255e72915d4cbddceb435e13d81601755714e9fSE Androidconst SkColor AutofillPopupBaseView::kBorderColor =
21255e72915d4cbddceb435e13d81601755714e9fSE Android    SkColorSetARGB(0xFF, 0xC7, 0xCA, 0xCE);
22255e72915d4cbddceb435e13d81601755714e9fSE Androidconst SkColor AutofillPopupBaseView::kHoveredBackgroundColor =
23255e72915d4cbddceb435e13d81601755714e9fSE Android    SkColorSetARGB(0xFF, 0xCD, 0xCD, 0xCD);
24255e72915d4cbddceb435e13d81601755714e9fSE Androidconst SkColor AutofillPopupBaseView::kItemTextColor =
25255e72915d4cbddceb435e13d81601755714e9fSE Android    SkColorSetARGB(0xFF, 0x7F, 0x7F, 0x7F);
26255e72915d4cbddceb435e13d81601755714e9fSE Androidconst SkColor AutofillPopupBaseView::kPopupBackground =
27255e72915d4cbddceb435e13d81601755714e9fSE Android    SkColorSetARGB(0xFF, 0xFF, 0xFF, 0xFF);
28255e72915d4cbddceb435e13d81601755714e9fSE Androidconst SkColor AutofillPopupBaseView::kValueTextColor =
29255e72915d4cbddceb435e13d81601755714e9fSE Android    SkColorSetARGB(0xFF, 0x00, 0x00, 0x00);
30255e72915d4cbddceb435e13d81601755714e9fSE Androidconst SkColor AutofillPopupBaseView::kWarningTextColor =
31255e72915d4cbddceb435e13d81601755714e9fSE Android    SkColorSetARGB(0xFF, 0x7F, 0x7F, 0x7F);
32255e72915d4cbddceb435e13d81601755714e9fSE Android
33255e72915d4cbddceb435e13d81601755714e9fSE AndroidAutofillPopupBaseView::AutofillPopupBaseView(
34255e72915d4cbddceb435e13d81601755714e9fSE Android    AutofillPopupViewDelegate* delegate,
35255e72915d4cbddceb435e13d81601755714e9fSE Android    views::Widget* observing_widget)
36255e72915d4cbddceb435e13d81601755714e9fSE Android    : delegate_(delegate),
37255e72915d4cbddceb435e13d81601755714e9fSE Android      observing_widget_(observing_widget) {}
38255e72915d4cbddceb435e13d81601755714e9fSE AndroidAutofillPopupBaseView::~AutofillPopupBaseView() {
39255e72915d4cbddceb435e13d81601755714e9fSE Android  if (delegate_) {
40255e72915d4cbddceb435e13d81601755714e9fSE Android    delegate_->ViewDestroyed();
41255e72915d4cbddceb435e13d81601755714e9fSE Android
42255e72915d4cbddceb435e13d81601755714e9fSE Android    RemoveObserver();
43255e72915d4cbddceb435e13d81601755714e9fSE Android  }
44255e72915d4cbddceb435e13d81601755714e9fSE Android}
45255e72915d4cbddceb435e13d81601755714e9fSE Android
46255e72915d4cbddceb435e13d81601755714e9fSE Androidvoid AutofillPopupBaseView::DoShow() {
47255e72915d4cbddceb435e13d81601755714e9fSE Android  if (!GetWidget()) {
48255e72915d4cbddceb435e13d81601755714e9fSE Android    observing_widget_->AddObserver(this);
49255e72915d4cbddceb435e13d81601755714e9fSE Android
50255e72915d4cbddceb435e13d81601755714e9fSE Android    // The widget is destroyed by the corresponding NativeWidget, so we use
51255e72915d4cbddceb435e13d81601755714e9fSE Android    // a weak pointer to hold the reference and don't have to worry about
52255e72915d4cbddceb435e13d81601755714e9fSE Android    // deletion.
53255e72915d4cbddceb435e13d81601755714e9fSE Android    views::Widget* widget = new views::Widget;
54255e72915d4cbddceb435e13d81601755714e9fSE Android    views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
55255e72915d4cbddceb435e13d81601755714e9fSE Android    params.delegate = this;
56255e72915d4cbddceb435e13d81601755714e9fSE Android    params.parent = container_view();
57255e72915d4cbddceb435e13d81601755714e9fSE Android    widget->Init(params);
58255e72915d4cbddceb435e13d81601755714e9fSE Android    widget->SetContentsView(this);
59255e72915d4cbddceb435e13d81601755714e9fSE Android#if defined(USE_AURA)
60255e72915d4cbddceb435e13d81601755714e9fSE Android    // No animation for popup appearance (too distracting).
61255e72915d4cbddceb435e13d81601755714e9fSE Android    views::corewm::SetWindowVisibilityAnimationTransition(
62255e72915d4cbddceb435e13d81601755714e9fSE Android        widget->GetNativeView(), views::corewm::ANIMATE_HIDE);
63255e72915d4cbddceb435e13d81601755714e9fSE Android#endif
64255e72915d4cbddceb435e13d81601755714e9fSE Android  }
65255e72915d4cbddceb435e13d81601755714e9fSE Android
66255e72915d4cbddceb435e13d81601755714e9fSE Android  SetBorder(views::Border::CreateSolidBorder(kPopupBorderThickness,
67255e72915d4cbddceb435e13d81601755714e9fSE Android                                             kBorderColor));
68255e72915d4cbddceb435e13d81601755714e9fSE Android
69255e72915d4cbddceb435e13d81601755714e9fSE Android  DoUpdateBoundsAndRedrawPopup();
70255e72915d4cbddceb435e13d81601755714e9fSE Android  GetWidget()->Show();
71255e72915d4cbddceb435e13d81601755714e9fSE Android
72255e72915d4cbddceb435e13d81601755714e9fSE Android  if (ShouldHideOnOutsideClick())
73255e72915d4cbddceb435e13d81601755714e9fSE Android    GetWidget()->SetCapture(this);
74255e72915d4cbddceb435e13d81601755714e9fSE Android}
75255e72915d4cbddceb435e13d81601755714e9fSE Android
76255e72915d4cbddceb435e13d81601755714e9fSE Androidvoid AutofillPopupBaseView::DoHide() {
77255e72915d4cbddceb435e13d81601755714e9fSE Android  // The controller is no longer valid after it hides us.
78255e72915d4cbddceb435e13d81601755714e9fSE Android  delegate_ = NULL;
79255e72915d4cbddceb435e13d81601755714e9fSE Android
80255e72915d4cbddceb435e13d81601755714e9fSE Android  RemoveObserver();
81255e72915d4cbddceb435e13d81601755714e9fSE Android
82255e72915d4cbddceb435e13d81601755714e9fSE Android  if (GetWidget()) {
83255e72915d4cbddceb435e13d81601755714e9fSE Android    // Don't call CloseNow() because some of the functions higher up the stack
84255e72915d4cbddceb435e13d81601755714e9fSE Android    // assume the the widget is still valid after this point.
85255e72915d4cbddceb435e13d81601755714e9fSE Android    // http://crbug.com/229224
86255e72915d4cbddceb435e13d81601755714e9fSE Android    // NOTE: This deletes |this|.
87255e72915d4cbddceb435e13d81601755714e9fSE Android    GetWidget()->Close();
88255e72915d4cbddceb435e13d81601755714e9fSE Android  } else {
89255e72915d4cbddceb435e13d81601755714e9fSE Android    delete this;
90255e72915d4cbddceb435e13d81601755714e9fSE Android  }
91255e72915d4cbddceb435e13d81601755714e9fSE Android}
92255e72915d4cbddceb435e13d81601755714e9fSE Android
93255e72915d4cbddceb435e13d81601755714e9fSE Androidvoid AutofillPopupBaseView::RemoveObserver() {
94255e72915d4cbddceb435e13d81601755714e9fSE Android  observing_widget_->RemoveObserver(this);
95255e72915d4cbddceb435e13d81601755714e9fSE Android}
96255e72915d4cbddceb435e13d81601755714e9fSE Android
97255e72915d4cbddceb435e13d81601755714e9fSE Androidvoid AutofillPopupBaseView::DoUpdateBoundsAndRedrawPopup() {
98255e72915d4cbddceb435e13d81601755714e9fSE Android  GetWidget()->SetBounds(delegate_->popup_bounds());
99255e72915d4cbddceb435e13d81601755714e9fSE Android  SchedulePaint();
100255e72915d4cbddceb435e13d81601755714e9fSE Android}
101255e72915d4cbddceb435e13d81601755714e9fSE Android
102255e72915d4cbddceb435e13d81601755714e9fSE Androidvoid AutofillPopupBaseView::OnWidgetBoundsChanged(views::Widget* widget,
103255e72915d4cbddceb435e13d81601755714e9fSE Android                                                  const gfx::Rect& new_bounds) {
104255e72915d4cbddceb435e13d81601755714e9fSE Android  DCHECK_EQ(widget, observing_widget_);
105255e72915d4cbddceb435e13d81601755714e9fSE Android  HideController();
106255e72915d4cbddceb435e13d81601755714e9fSE Android}
107255e72915d4cbddceb435e13d81601755714e9fSE Android
108255e72915d4cbddceb435e13d81601755714e9fSE Androidvoid AutofillPopupBaseView::OnMouseCaptureLost() {
109255e72915d4cbddceb435e13d81601755714e9fSE Android  ClearSelection();
110255e72915d4cbddceb435e13d81601755714e9fSE Android}
111255e72915d4cbddceb435e13d81601755714e9fSE Android
112255e72915d4cbddceb435e13d81601755714e9fSE Androidbool AutofillPopupBaseView::OnMouseDragged(const ui::MouseEvent& event) {
113255e72915d4cbddceb435e13d81601755714e9fSE Android  if (HitTestPoint(event.location())) {
114255e72915d4cbddceb435e13d81601755714e9fSE Android    SetSelection(event.location());
115255e72915d4cbddceb435e13d81601755714e9fSE Android
116255e72915d4cbddceb435e13d81601755714e9fSE Android    // We must return true in order to get future OnMouseDragged and
117255e72915d4cbddceb435e13d81601755714e9fSE Android    // OnMouseReleased events.
118255e72915d4cbddceb435e13d81601755714e9fSE Android    return true;
119255e72915d4cbddceb435e13d81601755714e9fSE Android  }
120255e72915d4cbddceb435e13d81601755714e9fSE Android
121255e72915d4cbddceb435e13d81601755714e9fSE Android  // If we move off of the popup, we lose the selection.
122255e72915d4cbddceb435e13d81601755714e9fSE Android  ClearSelection();
123255e72915d4cbddceb435e13d81601755714e9fSE Android  return false;
124255e72915d4cbddceb435e13d81601755714e9fSE Android}
125255e72915d4cbddceb435e13d81601755714e9fSE Android
126255e72915d4cbddceb435e13d81601755714e9fSE Androidvoid AutofillPopupBaseView::OnMouseExited(const ui::MouseEvent& event) {
127255e72915d4cbddceb435e13d81601755714e9fSE Android  ClearSelection();
128255e72915d4cbddceb435e13d81601755714e9fSE Android}
129255e72915d4cbddceb435e13d81601755714e9fSE Android
130255e72915d4cbddceb435e13d81601755714e9fSE Androidvoid AutofillPopupBaseView::OnMouseMoved(const ui::MouseEvent& event) {
131255e72915d4cbddceb435e13d81601755714e9fSE Android  if (HitTestPoint(event.location()))
132255e72915d4cbddceb435e13d81601755714e9fSE Android    SetSelection(event.location());
133255e72915d4cbddceb435e13d81601755714e9fSE Android  else
134255e72915d4cbddceb435e13d81601755714e9fSE Android    ClearSelection();
135255e72915d4cbddceb435e13d81601755714e9fSE Android}
136255e72915d4cbddceb435e13d81601755714e9fSE Android
137255e72915d4cbddceb435e13d81601755714e9fSE Androidbool AutofillPopupBaseView::OnMousePressed(const ui::MouseEvent& event) {
138255e72915d4cbddceb435e13d81601755714e9fSE Android  if (HitTestPoint(event.location()))
139255e72915d4cbddceb435e13d81601755714e9fSE Android    return true;
140255e72915d4cbddceb435e13d81601755714e9fSE Android
141255e72915d4cbddceb435e13d81601755714e9fSE Android  if (ShouldHideOnOutsideClick()) {
142255e72915d4cbddceb435e13d81601755714e9fSE Android    GetWidget()->ReleaseCapture();
143255e72915d4cbddceb435e13d81601755714e9fSE Android
144255e72915d4cbddceb435e13d81601755714e9fSE Android    gfx::Point screen_loc = event.location();
145255e72915d4cbddceb435e13d81601755714e9fSE Android    views::View::ConvertPointToScreen(this, &screen_loc);
146255e72915d4cbddceb435e13d81601755714e9fSE Android
147255e72915d4cbddceb435e13d81601755714e9fSE Android    ui::MouseEvent mouse_event = event;
148255e72915d4cbddceb435e13d81601755714e9fSE Android    mouse_event.set_location(screen_loc);
149255e72915d4cbddceb435e13d81601755714e9fSE Android
150255e72915d4cbddceb435e13d81601755714e9fSE Android    if (ShouldRepostEvent(mouse_event)) {
151255e72915d4cbddceb435e13d81601755714e9fSE Android      gfx::NativeView native_view = GetWidget()->GetNativeView();
152255e72915d4cbddceb435e13d81601755714e9fSE Android      gfx::Screen* screen = gfx::Screen::GetScreenFor(native_view);
153255e72915d4cbddceb435e13d81601755714e9fSE Android      gfx::NativeWindow window = screen->GetWindowAtScreenPoint(screen_loc);
154255e72915d4cbddceb435e13d81601755714e9fSE Android      views::RepostLocatedEvent(window, mouse_event);
155255e72915d4cbddceb435e13d81601755714e9fSE Android    }
156255e72915d4cbddceb435e13d81601755714e9fSE Android
157255e72915d4cbddceb435e13d81601755714e9fSE Android    HideController();
158255e72915d4cbddceb435e13d81601755714e9fSE Android    // |this| is now deleted.
159255e72915d4cbddceb435e13d81601755714e9fSE Android  }
160255e72915d4cbddceb435e13d81601755714e9fSE Android
161255e72915d4cbddceb435e13d81601755714e9fSE Android  return false;
162255e72915d4cbddceb435e13d81601755714e9fSE Android}
163255e72915d4cbddceb435e13d81601755714e9fSE Android
164255e72915d4cbddceb435e13d81601755714e9fSE Androidvoid AutofillPopupBaseView::OnMouseReleased(const ui::MouseEvent& event) {
165255e72915d4cbddceb435e13d81601755714e9fSE Android  // Because this view can can be shown in response to a mouse press, it can
166255e72915d4cbddceb435e13d81601755714e9fSE Android  // receive an OnMouseReleased event just after showing. This breaks the mouse
167255e72915d4cbddceb435e13d81601755714e9fSE Android  // capture, so restart capturing here.
168255e72915d4cbddceb435e13d81601755714e9fSE Android  if (ShouldHideOnOutsideClick() && GetWidget())
169255e72915d4cbddceb435e13d81601755714e9fSE Android    GetWidget()->SetCapture(this);
170255e72915d4cbddceb435e13d81601755714e9fSE Android
171255e72915d4cbddceb435e13d81601755714e9fSE Android  // We only care about the left click.
172255e72915d4cbddceb435e13d81601755714e9fSE Android  if (event.IsOnlyLeftMouseButton() && HitTestPoint(event.location()))
173255e72915d4cbddceb435e13d81601755714e9fSE Android    AcceptSelection(event.location());
174255e72915d4cbddceb435e13d81601755714e9fSE Android}
175255e72915d4cbddceb435e13d81601755714e9fSE Android
176255e72915d4cbddceb435e13d81601755714e9fSE Androidvoid AutofillPopupBaseView::OnGestureEvent(ui::GestureEvent* event) {
177255e72915d4cbddceb435e13d81601755714e9fSE Android  switch (event->type()) {
178255e72915d4cbddceb435e13d81601755714e9fSE Android    case ui::ET_GESTURE_TAP_DOWN:
179255e72915d4cbddceb435e13d81601755714e9fSE Android    case ui::ET_GESTURE_SCROLL_BEGIN:
180255e72915d4cbddceb435e13d81601755714e9fSE Android    case ui::ET_GESTURE_SCROLL_UPDATE:
181255e72915d4cbddceb435e13d81601755714e9fSE Android      if (HitTestPoint(event->location()))
182255e72915d4cbddceb435e13d81601755714e9fSE Android        SetSelection(event->location());
183255e72915d4cbddceb435e13d81601755714e9fSE Android      else
184255e72915d4cbddceb435e13d81601755714e9fSE Android        ClearSelection();
185255e72915d4cbddceb435e13d81601755714e9fSE Android      break;
186255e72915d4cbddceb435e13d81601755714e9fSE Android    case ui::ET_GESTURE_TAP:
187255e72915d4cbddceb435e13d81601755714e9fSE Android    case ui::ET_GESTURE_SCROLL_END:
188255e72915d4cbddceb435e13d81601755714e9fSE Android      if (HitTestPoint(event->location()))
189255e72915d4cbddceb435e13d81601755714e9fSE Android        SetSelection(event->location());
190255e72915d4cbddceb435e13d81601755714e9fSE Android      else
191255e72915d4cbddceb435e13d81601755714e9fSE Android        ClearSelection();
192255e72915d4cbddceb435e13d81601755714e9fSE Android      break;
193255e72915d4cbddceb435e13d81601755714e9fSE Android    case ui::ET_GESTURE_TAP_CANCEL:
194255e72915d4cbddceb435e13d81601755714e9fSE Android    case ui::ET_SCROLL_FLING_START:
195255e72915d4cbddceb435e13d81601755714e9fSE Android      ClearSelection();
196255e72915d4cbddceb435e13d81601755714e9fSE Android      break;
197255e72915d4cbddceb435e13d81601755714e9fSE Android    default:
198255e72915d4cbddceb435e13d81601755714e9fSE Android      return;
199255e72915d4cbddceb435e13d81601755714e9fSE Android  }
200255e72915d4cbddceb435e13d81601755714e9fSE Android  event->SetHandled();
201255e72915d4cbddceb435e13d81601755714e9fSE Android}
202255e72915d4cbddceb435e13d81601755714e9fSE Android
203255e72915d4cbddceb435e13d81601755714e9fSE Androidvoid AutofillPopupBaseView::SetSelection(const gfx::Point& point) {
204255e72915d4cbddceb435e13d81601755714e9fSE Android  if (delegate_)
205255e72915d4cbddceb435e13d81601755714e9fSE Android    delegate_->SetSelectionAtPoint(point);
206255e72915d4cbddceb435e13d81601755714e9fSE Android}
207
208void AutofillPopupBaseView::AcceptSelection(const gfx::Point& point) {
209  if (delegate_)
210    delegate_->AcceptSelectionAtPoint(point);
211}
212
213void AutofillPopupBaseView::ClearSelection() {
214  if (delegate_)
215    delegate_->SelectionCleared();
216}
217
218bool AutofillPopupBaseView::ShouldHideOnOutsideClick() {
219  if (delegate_)
220    return delegate_->ShouldHideOnOutsideClick();
221
222  // |this| instance should be in the process of being destroyed, so the return
223  // value shouldn't matter.
224  return false;
225}
226
227void AutofillPopupBaseView::HideController() {
228  if (delegate_)
229    delegate_->Hide();
230}
231
232bool AutofillPopupBaseView::ShouldRepostEvent(const ui::MouseEvent& event) {
233  return delegate_->ShouldRepostEvent(event);
234}
235
236gfx::NativeView AutofillPopupBaseView::container_view() {
237  return delegate_->container_view();
238}
239
240
241}  // namespace autofill
242