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