tray_container.cc 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. // Copyright 2017 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/system/tray/tray_container.h"
  5. #include <utility>
  6. #include "ash/constants/ash_features.h"
  7. #include "ash/keyboard/ui/keyboard_ui_controller.h"
  8. #include "ash/public/cpp/shelf_config.h"
  9. #include "ash/shelf/shelf.h"
  10. #include "ash/shell.h"
  11. #include "ash/system/tray/tray_background_view.h"
  12. #include "ash/system/tray/tray_constants.h"
  13. #include "ui/compositor/layer.h"
  14. #include "ui/gfx/geometry/insets.h"
  15. #include "ui/views/border.h"
  16. #include "ui/views/highlight_border.h"
  17. #include "ui/views/layout/box_layout.h"
  18. namespace ash {
  19. TrayContainer::TrayContainer(Shelf* shelf,
  20. TrayBackgroundView* tray_background_view)
  21. : shelf_(shelf), tray_background_view_(tray_background_view) {
  22. DCHECK(shelf_);
  23. SetPaintToLayer();
  24. layer()->SetFillsBoundsOpaquely(false);
  25. UpdateLayout();
  26. }
  27. TrayContainer::~TrayContainer() {
  28. }
  29. void TrayContainer::CalculateTargetBounds() {
  30. const LayoutInputs new_layout_inputs = GetLayoutInputs();
  31. const bool is_horizontal = new_layout_inputs.shelf_alignment_is_horizontal;
  32. // Adjust the size of status tray dark background by adding additional
  33. // empty border.
  34. views::BoxLayout::Orientation orientation =
  35. is_horizontal ? views::BoxLayout::Orientation::kHorizontal
  36. : views::BoxLayout::Orientation::kVertical;
  37. gfx::Insets insets(
  38. is_horizontal
  39. ? gfx::Insets::VH(0, new_layout_inputs.status_area_hit_region_padding)
  40. : gfx::Insets::VH(new_layout_inputs.status_area_hit_region_padding,
  41. 0));
  42. border_ = views::CreateEmptyBorder(insets);
  43. int horizontal_margin = new_layout_inputs.main_axis_margin;
  44. int vertical_margin = new_layout_inputs.cross_axis_margin;
  45. if (!is_horizontal)
  46. std::swap(horizontal_margin, vertical_margin);
  47. layout_manager_ = std::make_unique<views::BoxLayout>(
  48. orientation, gfx::Insets::VH(vertical_margin, horizontal_margin),
  49. new_layout_inputs.spacing_between_children);
  50. layout_manager_->set_minimum_cross_axis_size(kTrayItemSize);
  51. }
  52. void TrayContainer::UpdateLayout() {
  53. const LayoutInputs new_layout_inputs = GetLayoutInputs();
  54. if (layout_inputs_ == new_layout_inputs)
  55. return;
  56. if (border_)
  57. SetBorder(std::move(border_));
  58. if (layout_manager_)
  59. views::View::SetLayoutManager(std::move(layout_manager_));
  60. Layout();
  61. layout_inputs_ = new_layout_inputs;
  62. }
  63. void TrayContainer::SetMargin(int main_axis_margin, int cross_axis_margin) {
  64. main_axis_margin_ = main_axis_margin;
  65. cross_axis_margin_ = cross_axis_margin;
  66. UpdateLayout();
  67. }
  68. void TrayContainer::SetSpacingBetweenChildren(int space_dip) {
  69. spacing_between_children_ = space_dip;
  70. UpdateLayout();
  71. }
  72. void TrayContainer::OnPaint(gfx::Canvas* canvas) {
  73. views::View::OnPaint(canvas);
  74. // We only add highlight border to the system tray when it is in tablet mode
  75. // and not in app mode.
  76. if (!features::IsDarkLightModeEnabled() || !Shell::Get()->IsInTabletMode() ||
  77. ShelfConfig::Get()->is_in_app()) {
  78. return;
  79. }
  80. // We add highlight border here since TrayBackgroundView's layer is solid
  81. // color, which hides the border. However, the painting bounds should be the
  82. // layer clip rect defined in the background view, so we calculate that bound
  83. // relative to local bounds and do a custom highlight border paint here.
  84. const gfx::Rect background_bounds =
  85. tray_background_view_->GetBackgroundBounds();
  86. const auto bounds_origin =
  87. (tray_background_view_->GetBoundsInScreen().origin() +
  88. background_bounds.OffsetFromOrigin()) -
  89. GetBoundsInScreen().origin();
  90. const gfx::RoundedCornersF rounded_corners =
  91. tray_background_view_->GetRoundedCorners();
  92. views::HighlightBorder::PaintBorderToCanvas(
  93. canvas, *this,
  94. gfx::Rect(gfx::PointAtOffsetFromOrigin(bounds_origin),
  95. background_bounds.size()),
  96. rounded_corners, views::HighlightBorder::Type::kHighlightBorder2,
  97. /*use_light_colors=*/false);
  98. }
  99. void TrayContainer::ChildPreferredSizeChanged(views::View* child) {
  100. if (layout_manager_)
  101. UpdateLayout();
  102. PreferredSizeChanged();
  103. }
  104. void TrayContainer::ChildVisibilityChanged(View* child) {
  105. if (layout_manager_)
  106. UpdateLayout();
  107. PreferredSizeChanged();
  108. }
  109. void TrayContainer::ViewHierarchyChanged(
  110. const views::ViewHierarchyChangedDetails& details) {
  111. if (details.parent == this)
  112. PreferredSizeChanged();
  113. }
  114. gfx::Rect TrayContainer::GetAnchorBoundsInScreen() const {
  115. if (shelf_->IsHorizontalAlignment()) {
  116. // When the virtual keyboard is up, any anchored widgets should anchor to
  117. // the virtual keyboard instead because it will cover the shelf.
  118. const gfx::Rect occluded_bounds =
  119. keyboard::KeyboardUIController::Get()
  120. ->GetWorkspaceOccludedBoundsInScreen();
  121. if (!occluded_bounds.IsEmpty())
  122. return occluded_bounds;
  123. }
  124. return GetBoundsInScreen();
  125. }
  126. const char* TrayContainer::GetClassName() const {
  127. return "TrayContainer";
  128. }
  129. TrayContainer::LayoutInputs TrayContainer::GetLayoutInputs() const {
  130. return {shelf_->IsHorizontalAlignment(),
  131. ShelfConfig::Get()->status_area_hit_region_padding(),
  132. GetAnchorBoundsInScreen(),
  133. main_axis_margin_,
  134. cross_axis_margin_,
  135. spacing_between_children_};
  136. }
  137. } // namespace ash