autofill_popup.cc 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  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
  3. // found in the LICENSE file.
  4. #include <algorithm>
  5. #include <utility>
  6. #include <vector>
  7. #include "atom/browser/native_window_views.h"
  8. #include "atom/browser/ui/autofill_popup.h"
  9. #include "atom/common/api/api_messages.h"
  10. #include "base/i18n/rtl.h"
  11. #include "chrome/browser/ui/autofill/popup_view_common.h"
  12. #include "electron/buildflags/buildflags.h"
  13. #include "ui/display/display.h"
  14. #include "ui/display/screen.h"
  15. #include "ui/gfx/geometry/point.h"
  16. #include "ui/gfx/geometry/rect.h"
  17. #include "ui/gfx/geometry/rect_conversions.h"
  18. #include "ui/gfx/geometry/vector2d.h"
  19. #include "ui/gfx/text_utils.h"
  20. #if BUILDFLAG(ENABLE_OSR)
  21. #include "atom/browser/osr/osr_render_widget_host_view.h"
  22. #include "atom/browser/osr/osr_view_proxy.h"
  23. #endif
  24. namespace atom {
  25. class PopupViewCommon : public autofill::PopupViewCommon {
  26. public:
  27. explicit PopupViewCommon(const gfx::Rect& window_bounds)
  28. : window_bounds_(window_bounds) {}
  29. gfx::Rect GetWindowBounds(gfx::NativeView container_view) override {
  30. return window_bounds_;
  31. }
  32. private:
  33. gfx::Rect window_bounds_;
  34. };
  35. AutofillPopup::AutofillPopup() {
  36. bold_font_list_ = gfx::FontList().DeriveWithWeight(gfx::Font::Weight::BOLD);
  37. smaller_font_list_ =
  38. gfx::FontList().DeriveWithSizeDelta(kSmallerFontSizeDelta);
  39. }
  40. AutofillPopup::~AutofillPopup() {
  41. Hide();
  42. }
  43. void AutofillPopup::CreateView(content::RenderFrameHost* frame_host,
  44. content::RenderFrameHost* embedder_frame_host,
  45. bool offscreen,
  46. views::View* parent,
  47. const gfx::RectF& r) {
  48. Hide();
  49. frame_host_ = frame_host;
  50. element_bounds_ = gfx::ToEnclosedRect(r);
  51. gfx::Vector2d height_offset(0, element_bounds_.height());
  52. gfx::Point menu_position(element_bounds_.origin() + height_offset);
  53. views::View::ConvertPointToScreen(parent, &menu_position);
  54. popup_bounds_ = gfx::Rect(menu_position, element_bounds_.size());
  55. parent_ = parent;
  56. parent_->AddObserver(this);
  57. view_ = new AutofillPopupView(this, parent->GetWidget());
  58. #if BUILDFLAG(ENABLE_OSR)
  59. if (offscreen) {
  60. auto* rwhv = frame_host->GetView();
  61. if (embedder_frame_host != nullptr) {
  62. rwhv = embedder_frame_host->GetView();
  63. }
  64. auto* osr_rwhv = static_cast<OffScreenRenderWidgetHostView*>(rwhv);
  65. view_->view_proxy_.reset(new OffscreenViewProxy(view_));
  66. osr_rwhv->AddViewProxy(view_->view_proxy_.get());
  67. }
  68. #endif
  69. // Do this after OSR setup, we check for view_proxy_ when showing
  70. view_->Show();
  71. }
  72. void AutofillPopup::Hide() {
  73. if (parent_) {
  74. parent_->RemoveObserver(this);
  75. parent_ = nullptr;
  76. }
  77. if (view_) {
  78. view_->Hide();
  79. view_ = nullptr;
  80. }
  81. }
  82. void AutofillPopup::SetItems(const std::vector<base::string16>& values,
  83. const std::vector<base::string16>& labels) {
  84. DCHECK(view_);
  85. values_ = values;
  86. labels_ = labels;
  87. UpdatePopupBounds();
  88. view_->OnSuggestionsChanged();
  89. if (view_) // could be hidden after the change
  90. view_->DoUpdateBoundsAndRedrawPopup();
  91. }
  92. void AutofillPopup::AcceptSuggestion(int index) {
  93. frame_host_->Send(new AtomAutofillFrameMsg_AcceptSuggestion(
  94. frame_host_->GetRoutingID(), GetValueAt(index)));
  95. }
  96. void AutofillPopup::UpdatePopupBounds() {
  97. DCHECK(parent_);
  98. gfx::Point origin(element_bounds_.origin());
  99. views::View::ConvertPointToScreen(parent_, &origin);
  100. gfx::Rect bounds(origin, element_bounds_.size());
  101. gfx::Rect window_bounds = parent_->GetBoundsInScreen();
  102. PopupViewCommon popup_view_common(window_bounds);
  103. popup_bounds_ = popup_view_common.CalculatePopupBounds(
  104. GetDesiredPopupWidth(), GetDesiredPopupHeight(), bounds,
  105. gfx::NativeView(), base::i18n::IsRTL());
  106. }
  107. gfx::Rect AutofillPopup::popup_bounds_in_view() {
  108. gfx::Point origin(popup_bounds_.origin());
  109. views::View::ConvertPointFromScreen(parent_, &origin);
  110. return gfx::Rect(origin, popup_bounds_.size());
  111. }
  112. void AutofillPopup::OnViewBoundsChanged(views::View* view) {
  113. UpdatePopupBounds();
  114. view_->DoUpdateBoundsAndRedrawPopup();
  115. }
  116. void AutofillPopup::OnViewIsDeleting(views::View* view) {
  117. Hide();
  118. }
  119. int AutofillPopup::GetDesiredPopupHeight() {
  120. return 2 * kPopupBorderThickness + values_.size() * kRowHeight;
  121. }
  122. int AutofillPopup::GetDesiredPopupWidth() {
  123. int popup_width = element_bounds_.width();
  124. for (size_t i = 0; i < values_.size(); ++i) {
  125. int row_size =
  126. kEndPadding + 2 * kPopupBorderThickness +
  127. gfx::GetStringWidth(GetValueAt(i), GetValueFontListForRow(i)) +
  128. gfx::GetStringWidth(GetLabelAt(i), GetLabelFontListForRow(i));
  129. if (GetLabelAt(i).length() > 0)
  130. row_size += kNamePadding + kEndPadding;
  131. popup_width = std::max(popup_width, row_size);
  132. }
  133. return popup_width;
  134. }
  135. gfx::Rect AutofillPopup::GetRowBounds(int index) {
  136. int top = kPopupBorderThickness + index * kRowHeight;
  137. return gfx::Rect(kPopupBorderThickness, top,
  138. popup_bounds_.width() - 2 * kPopupBorderThickness,
  139. kRowHeight);
  140. }
  141. const gfx::FontList& AutofillPopup::GetValueFontListForRow(int index) const {
  142. return bold_font_list_;
  143. }
  144. const gfx::FontList& AutofillPopup::GetLabelFontListForRow(int index) const {
  145. return smaller_font_list_;
  146. }
  147. ui::NativeTheme::ColorId AutofillPopup::GetBackgroundColorIDForRow(
  148. int index) const {
  149. return (view_ && index == view_->GetSelectedLine())
  150. ? ui::NativeTheme::kColorId_ResultsTableHoveredBackground
  151. : ui::NativeTheme::kColorId_ResultsTableNormalBackground;
  152. }
  153. int AutofillPopup::GetLineCount() {
  154. return values_.size();
  155. }
  156. base::string16 AutofillPopup::GetValueAt(int i) {
  157. return values_.at(i);
  158. }
  159. base::string16 AutofillPopup::GetLabelAt(int i) {
  160. return labels_.at(i);
  161. }
  162. int AutofillPopup::LineFromY(int y) const {
  163. int current_height = kPopupBorderThickness;
  164. for (size_t i = 0; i < values_.size(); ++i) {
  165. current_height += kRowHeight;
  166. if (y <= current_height)
  167. return i;
  168. }
  169. return values_.size() - 1;
  170. }
  171. } // namespace atom