search_result_page_anchored_dialog.cc 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. // Copyright 2020 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 "ash/app_list/views/search_result_page_anchored_dialog.h"
  5. #include <utility>
  6. #include "ash/constants/ash_features.h"
  7. #include "ui/compositor/layer.h"
  8. #include "ui/gfx/geometry/point.h"
  9. #include "ui/gfx/geometry/rect.h"
  10. #include "ui/gfx/geometry/size.h"
  11. #include "ui/gfx/geometry/transform.h"
  12. #include "ui/views/view.h"
  13. #include "ui/views/window/dialog_delegate.h"
  14. #include "ui/views/window/non_client_view.h"
  15. #include "ui/wm/core/coordinate_conversion.h"
  16. namespace ash {
  17. namespace {
  18. // The intended offset the dialog should have from the top of the anchor view
  19. // bounds.
  20. constexpr int kDialogVerticalMargin = 32;
  21. } // namespace
  22. SearchResultPageAnchoredDialog::SearchResultPageAnchoredDialog(
  23. std::unique_ptr<views::WidgetDelegate> dialog,
  24. views::View* host_view,
  25. base::OnceClosure callback)
  26. : host_view_(host_view), callback_(std::move(callback)) {
  27. DCHECK(!dialog->GetWidget());
  28. views::Widget* const parent = host_view_->GetWidget();
  29. widget_ = new views::Widget();
  30. views::Widget::InitParams params;
  31. // Pre-productivity launcher uses DialogDelegateView for the dialog, while the
  32. // productivity launcher expects a frameless widget.
  33. if (features::IsProductivityLauncherEnabled()) {
  34. params.type = views::Widget::InitParams::TYPE_WINDOW_FRAMELESS;
  35. params.layer_type = ui::LAYER_NOT_DRAWN;
  36. params.parent = parent->GetNativeWindow();
  37. params.delegate = dialog.release();
  38. } else {
  39. params = views::DialogDelegateView::GetDialogWidgetInitParams(
  40. dialog.release(), parent->GetNativeWindow(), parent->GetNativeWindow(),
  41. gfx::Rect());
  42. }
  43. widget_->Init(std::move(params));
  44. // The |dialog| ownership is passed to the window hierarchy.
  45. widget_observations_.AddObservation(widget_);
  46. widget_observations_.AddObservation(parent);
  47. view_observations_.AddObservation(host_view_);
  48. view_observations_.AddObservation(widget_->GetContentsView());
  49. }
  50. SearchResultPageAnchoredDialog::~SearchResultPageAnchoredDialog() {
  51. view_observations_.RemoveAllObservations();
  52. widget_observations_.RemoveAllObservations();
  53. if (widget_)
  54. widget_->Close();
  55. }
  56. void SearchResultPageAnchoredDialog::UpdateBounds() {
  57. if (!widget_)
  58. return;
  59. gfx::Point anchor_point_in_screen(host_view_->width() / 2, 0);
  60. views::View::ConvertPointToScreen(host_view_, &anchor_point_in_screen);
  61. const int offset_for_frame_insets =
  62. widget_->non_client_view() && widget_->non_client_view()->frame_view()
  63. ? widget_->non_client_view()->frame_view()->GetInsets().top()
  64. : 0;
  65. const int vertical_offset = kDialogVerticalMargin - offset_for_frame_insets;
  66. gfx::Size dialog_size = widget_->GetContentsView()->GetPreferredSize();
  67. widget_->SetBounds(
  68. gfx::Rect(gfx::Point(anchor_point_in_screen.x() - dialog_size.width() / 2,
  69. anchor_point_in_screen.y() + vertical_offset),
  70. dialog_size));
  71. }
  72. float SearchResultPageAnchoredDialog::AdjustVerticalTransformOffset(
  73. float default_offset) {
  74. // In addition to the host view (in host view coordinates), the
  75. // widget has to consider the parent (app list view) widget transform to
  76. // correctly follow the anchor view animation.
  77. const float parent_offset =
  78. host_view_->GetWidget()->GetLayer()->transform().To2dTranslation().y();
  79. return default_offset + parent_offset;
  80. }
  81. void SearchResultPageAnchoredDialog::OnWidgetDestroying(views::Widget* widget) {
  82. widget_ = nullptr;
  83. widget_observations_.RemoveAllObservations();
  84. if (callback_)
  85. std::move(callback_).Run();
  86. }
  87. void SearchResultPageAnchoredDialog::OnWidgetBoundsChanged(
  88. views::Widget* widget,
  89. const gfx::Rect& new_bounds) {
  90. // Reposition the dialog widget if the host widget bounds change (if the
  91. // bounds size remained the same, the host widget bounds change may not cause
  92. // app list layout, and thus the anchor bounds in the host view coordinates
  93. // may not change).
  94. if (widget == host_view_->GetWidget())
  95. UpdateBounds();
  96. }
  97. void SearchResultPageAnchoredDialog::OnViewBoundsChanged(
  98. views::View* observed_view) {
  99. UpdateBounds();
  100. }
  101. void SearchResultPageAnchoredDialog::OnViewPreferredSizeChanged(
  102. views::View* observed_view) {
  103. UpdateBounds();
  104. }
  105. } // namespace ash