default_frame_header.cc 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. // Copyright 2014 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 "chromeos/ui/frame/default_frame_header.h"
  5. #include "base/logging.h" // DCHECK
  6. #include "chromeos/ui/base/chromeos_ui_constants.h"
  7. #include "chromeos/ui/base/window_properties.h"
  8. #include "chromeos/ui/base/window_state_type.h"
  9. #include "chromeos/ui/frame/caption_buttons/caption_button_model.h"
  10. #include "chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.h"
  11. #include "third_party/skia/include/core/SkPath.h"
  12. #include "ui/compositor/layer.h"
  13. #include "ui/gfx/canvas.h"
  14. #include "ui/gfx/color_utils.h"
  15. #include "ui/gfx/geometry/rect.h"
  16. #include "ui/gfx/scoped_canvas.h"
  17. #include "ui/views/view.h"
  18. #include "ui/views/widget/native_widget_aura.h"
  19. #include "ui/views/widget/widget.h"
  20. #include "ui/views/widget/widget_delegate.h"
  21. #include "ui/views/window/caption_button_layout_constants.h"
  22. using views::Widget;
  23. namespace {
  24. // Tiles an image into an area, rounding the top corners.
  25. void TileRoundRect(gfx::Canvas* canvas,
  26. const cc::PaintFlags& flags,
  27. const gfx::Rect& bounds,
  28. int corner_radius) {
  29. SkRect rect = gfx::RectToSkRect(bounds);
  30. const SkScalar corner_radius_scalar = SkIntToScalar(corner_radius);
  31. SkScalar radii[8] = {corner_radius_scalar,
  32. corner_radius_scalar, // top-left
  33. corner_radius_scalar,
  34. corner_radius_scalar, // top-right
  35. 0,
  36. 0, // bottom-right
  37. 0,
  38. 0}; // bottom-left
  39. // Antialiasing can result in blending a transparent pixel and
  40. // leave non opaque alpha between the frame and the client area.
  41. // Extend 1dp to make sure it's fully opaque.
  42. rect.fBottom += 1;
  43. SkPath path;
  44. path.addRoundRect(rect, radii, SkPathDirection::kCW);
  45. canvas->DrawPath(path, flags);
  46. }
  47. } // namespace
  48. namespace chromeos {
  49. ///////////////////////////////////////////////////////////////////////////////
  50. // DefaultFrameHeader, public:
  51. DefaultFrameHeader::DefaultFrameHeader(
  52. views::Widget* target_widget,
  53. views::View* header_view,
  54. chromeos::FrameCaptionButtonContainerView* caption_button_container)
  55. : FrameHeader(target_widget, header_view) {
  56. DCHECK(caption_button_container);
  57. SetCaptionButtonContainer(caption_button_container);
  58. }
  59. DefaultFrameHeader::~DefaultFrameHeader() = default;
  60. void DefaultFrameHeader::SetWidthInPixels(int width_in_pixels) {
  61. if (width_in_pixels_ == width_in_pixels)
  62. return;
  63. width_in_pixels_ = width_in_pixels;
  64. SchedulePaintForTitle();
  65. }
  66. void DefaultFrameHeader::UpdateFrameColors() {
  67. aura::Window* target_window = GetTargetWindow();
  68. const SkColor active_frame_color =
  69. target_window->GetProperty(kFrameActiveColorKey);
  70. const SkColor inactive_frame_color =
  71. target_window->GetProperty(kFrameInactiveColorKey);
  72. bool updated = false;
  73. // Update the frame if the frame color for the current active state chagnes.
  74. if (active_frame_color_ != active_frame_color) {
  75. active_frame_color_ = active_frame_color;
  76. updated = mode() == Mode::MODE_ACTIVE;
  77. }
  78. if (inactive_frame_color_ != inactive_frame_color) {
  79. inactive_frame_color_ = inactive_frame_color;
  80. updated |= mode() == Mode::MODE_INACTIVE;
  81. }
  82. if (updated) {
  83. UpdateCaptionButtonColors();
  84. StartTransitionAnimation(kDefaultFrameColorChangeAnimationDuration);
  85. }
  86. }
  87. ///////////////////////////////////////////////////////////////////////////////
  88. // DefaultFrameHeader, protected:
  89. void DefaultFrameHeader::DoPaintHeader(gfx::Canvas* canvas) {
  90. int corner_radius = IsNormalWindowStateType(GetTargetWindow()->GetProperty(
  91. chromeos::kWindowStateTypeKey))
  92. ? chromeos::kTopCornerRadiusWhenRestored
  93. : 0;
  94. cc::PaintFlags flags;
  95. flags.setColor(mode() == Mode::MODE_ACTIVE ? active_frame_color_
  96. : inactive_frame_color_);
  97. flags.setAntiAlias(true);
  98. if (width_in_pixels_ > 0) {
  99. canvas->Save();
  100. float layer_scale =
  101. target_widget()->GetNativeWindow()->layer()->device_scale_factor();
  102. float canvas_scale = canvas->UndoDeviceScaleFactor();
  103. gfx::Rect rect =
  104. ScaleToEnclosingRect(GetPaintedBounds(), canvas_scale, canvas_scale);
  105. rect.set_width(width_in_pixels_ * canvas_scale / layer_scale);
  106. TileRoundRect(canvas, flags, rect,
  107. static_cast<int>(corner_radius * canvas_scale));
  108. canvas->Restore();
  109. } else {
  110. TileRoundRect(canvas, flags, GetPaintedBounds(), corner_radius);
  111. }
  112. PaintTitleBar(canvas);
  113. }
  114. views::CaptionButtonLayoutSize DefaultFrameHeader::GetButtonLayoutSize() const {
  115. return views::CaptionButtonLayoutSize::kNonBrowserCaption;
  116. }
  117. SkColor DefaultFrameHeader::GetTitleColor() const {
  118. // Use IsDark() to change target colors instead of PickContrastingColor(), so
  119. // that FrameCaptionButton::GetButtonColor() (which uses different target
  120. // colors) can change between light/dark targets at the same time. It looks
  121. // bad when the title and caption buttons disagree about whether to be light
  122. // or dark.
  123. const SkColor frame_color = GetCurrentFrameColor();
  124. const SkColor desired_color = color_utils::IsDark(frame_color)
  125. ? SK_ColorWHITE
  126. : SkColorSetRGB(40, 40, 40);
  127. return color_utils::BlendForMinContrast(desired_color, frame_color).color;
  128. }
  129. ///////////////////////////////////////////////////////////////////////////////
  130. // DefaultFrameHeader, private:
  131. aura::Window* DefaultFrameHeader::GetTargetWindow() {
  132. return target_widget()->GetNativeWindow();
  133. }
  134. SkColor DefaultFrameHeader::GetCurrentFrameColor() const {
  135. return mode() == MODE_ACTIVE ? active_frame_color_ : inactive_frame_color_;
  136. }
  137. SkColor DefaultFrameHeader::GetActiveFrameColorForPaintForTest() {
  138. return active_frame_color_;
  139. }
  140. } // namespace chromeos