overscan_calibrator.cc 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  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 "ash/display/overscan_calibrator.h"
  5. #include <stdint.h>
  6. #include <limits>
  7. #include <memory>
  8. #include "ash/display/window_tree_host_manager.h"
  9. #include "ash/public/cpp/shell_window_ids.h"
  10. #include "ash/shell.h"
  11. #include "third_party/skia/include/core/SkColor.h"
  12. #include "third_party/skia/include/core/SkPaint.h"
  13. #include "third_party/skia/include/core/SkPath.h"
  14. #include "ui/aura/window.h"
  15. #include "ui/compositor/layer.h"
  16. #include "ui/compositor/paint_recorder.h"
  17. #include "ui/display/manager/display_manager.h"
  18. #include "ui/display/manager/managed_display_info.h"
  19. #include "ui/gfx/canvas.h"
  20. namespace ash {
  21. namespace {
  22. // The opacity for the arrows of the overscan calibration.
  23. const float kArrowOpacity = 0.8;
  24. // The height in pixel for the arrows to show the overscan calibration.
  25. const int kCalibrationArrowHeight = 70;
  26. // The gap between the boundary and calibration arrows.
  27. const int kArrowGapWidth = 0;
  28. // Draw the arrow for the overscan calibration to |canvas|.
  29. void DrawTriangle(int x_offset,
  30. int y_offset,
  31. double rotation_degree,
  32. gfx::Canvas* canvas) {
  33. // Draw triangular arrows.
  34. cc::PaintFlags content_flags;
  35. content_flags.setStyle(cc::PaintFlags::kFill_Style);
  36. content_flags.setColor(SkColorSetA(
  37. SK_ColorBLACK, std::numeric_limits<uint8_t>::max() * kArrowOpacity));
  38. cc::PaintFlags border_flags;
  39. border_flags.setStyle(cc::PaintFlags::kStroke_Style);
  40. border_flags.setColor(SkColorSetA(
  41. SK_ColorWHITE, std::numeric_limits<uint8_t>::max() * kArrowOpacity));
  42. SkPath base_path;
  43. base_path.moveTo(0, 0);
  44. base_path.lineTo(SkIntToScalar(-kCalibrationArrowHeight),
  45. SkIntToScalar(-kCalibrationArrowHeight));
  46. base_path.lineTo(SkIntToScalar(kCalibrationArrowHeight),
  47. SkIntToScalar(-kCalibrationArrowHeight));
  48. base_path.close();
  49. SkPath path;
  50. gfx::Transform rotate_transform;
  51. rotate_transform.Rotate(rotation_degree);
  52. gfx::Transform move_transform;
  53. move_transform.Translate(x_offset, y_offset);
  54. rotate_transform.ConcatTransform(move_transform);
  55. base_path.transform(rotate_transform.matrix().asM33(), &path);
  56. canvas->DrawPath(path, content_flags);
  57. canvas->DrawPath(path, border_flags);
  58. }
  59. gfx::Insets RotateInsets(display::Display::Rotation rotation,
  60. gfx::Insets&& insets) {
  61. switch (rotation) {
  62. case display::Display::ROTATE_0:
  63. return insets;
  64. case display::Display::ROTATE_90:
  65. return gfx::Insets::TLBR(insets.right(), insets.top(), insets.left(),
  66. insets.bottom());
  67. case display::Display::ROTATE_180:
  68. return gfx::Insets::TLBR(insets.bottom(), insets.right(), insets.top(),
  69. insets.left());
  70. case display::Display::ROTATE_270:
  71. return gfx::Insets::TLBR(insets.left(), insets.bottom(), insets.right(),
  72. insets.top());
  73. }
  74. NOTREACHED();
  75. return std::move(insets);
  76. }
  77. gfx::Insets ConvertToDisplay(const display::Display& display,
  78. const gfx::Insets& insets) {
  79. display::ManagedDisplayInfo info =
  80. ash::Shell::Get()->display_manager()->GetDisplayInfo(display.id());
  81. return RotateInsets(
  82. display.rotation(),
  83. gfx::ScaleToFlooredInsets(
  84. insets, info.device_scale_factor() / display.device_scale_factor()));
  85. }
  86. gfx::Insets ConvertToHost(const display::Display& display,
  87. const gfx::Insets& insets) {
  88. display::ManagedDisplayInfo info =
  89. ash::Shell::Get()->display_manager()->GetDisplayInfo(display.id());
  90. display::Display::Rotation inverted_rotation =
  91. static_cast<display::Display::Rotation>(
  92. (4 - static_cast<int>(display.rotation())) % 4);
  93. return RotateInsets(
  94. inverted_rotation,
  95. gfx::ScaleToFlooredInsets(
  96. insets, display.device_scale_factor() / info.device_scale_factor()));
  97. }
  98. } // namespace
  99. OverscanCalibrator::OverscanCalibrator(const display::Display& target_display,
  100. const gfx::Insets& initial_insets)
  101. : display_(target_display),
  102. insets_(ConvertToDisplay(display_, initial_insets)),
  103. initial_insets_(initial_insets),
  104. committed_(false) {
  105. // Undo the overscan calibration temporarily so that the user can see
  106. // dark boundary and current overscan region.
  107. Shell::Get()->window_tree_host_manager()->SetOverscanInsets(display_.id(),
  108. gfx::Insets());
  109. UpdateUILayer();
  110. }
  111. OverscanCalibrator::~OverscanCalibrator() {
  112. // Overscan calibration has finished without commit, so the display has to
  113. // be the original offset.
  114. if (!committed_) {
  115. Shell::Get()->window_tree_host_manager()->SetOverscanInsets(
  116. display_.id(), initial_insets_);
  117. }
  118. }
  119. void OverscanCalibrator::Commit() {
  120. Shell::Get()->window_tree_host_manager()->SetOverscanInsets(
  121. display_.id(), ConvertToHost(display_, insets_));
  122. committed_ = true;
  123. }
  124. void OverscanCalibrator::Reset() {
  125. insets_ = ConvertToDisplay(display_, initial_insets_);
  126. calibration_layer_->SchedulePaint(calibration_layer_->bounds());
  127. }
  128. void OverscanCalibrator::UpdateInsets(const gfx::Insets& insets) {
  129. insets_ = gfx::Insets::TLBR(
  130. std::max(insets.top(), 0), std::max(insets.left(), 0),
  131. std::max(insets.bottom(), 0), std::max(insets.right(), 0));
  132. calibration_layer_->SchedulePaint(calibration_layer_->bounds());
  133. }
  134. void OverscanCalibrator::OnPaintLayer(const ui::PaintContext& context) {
  135. ui::PaintRecorder recorder(context, calibration_layer_->size());
  136. gfx::Rect full_bounds = calibration_layer_->bounds();
  137. gfx::Rect inner_bounds = full_bounds;
  138. inner_bounds.Inset(insets_);
  139. recorder.canvas()->FillRect(full_bounds, SK_ColorBLACK);
  140. recorder.canvas()->FillRect(inner_bounds, SK_ColorTRANSPARENT,
  141. SkBlendMode::kClear);
  142. gfx::Point center = inner_bounds.CenterPoint();
  143. int vertical_offset = inner_bounds.height() / 2 - kArrowGapWidth;
  144. int horizontal_offset = inner_bounds.width() / 2 - kArrowGapWidth;
  145. gfx::Canvas* canvas = recorder.canvas();
  146. DrawTriangle(center.x(), center.y() + vertical_offset, 0, canvas);
  147. DrawTriangle(center.x(), center.y() - vertical_offset, 180, canvas);
  148. DrawTriangle(center.x() - horizontal_offset, center.y(), 90, canvas);
  149. DrawTriangle(center.x() + horizontal_offset, center.y(), -90, canvas);
  150. }
  151. void OverscanCalibrator::OnDeviceScaleFactorChanged(
  152. float old_device_scale_factor,
  153. float new_device_scale_factor) {}
  154. void OverscanCalibrator::OnDisplayMetricsChanged(
  155. const display::Display& display,
  156. uint32_t changed_metrics) {
  157. if (display_.id() != display.id() || committed_)
  158. return;
  159. display_ = display;
  160. UpdateUILayer();
  161. Reset();
  162. }
  163. void OverscanCalibrator::UpdateUILayer() {
  164. display::ManagedDisplayInfo info =
  165. Shell::Get()->display_manager()->GetDisplayInfo(display_.id());
  166. aura::Window* root = Shell::GetRootWindowForDisplayId(display_.id());
  167. ui::Layer* parent_layer =
  168. Shell::GetContainer(root, kShellWindowId_OverlayContainer)->layer();
  169. calibration_layer_ = std::make_unique<ui::Layer>();
  170. calibration_layer_->SetOpacity(0.5f);
  171. calibration_layer_->SetBounds(parent_layer->bounds());
  172. calibration_layer_->set_delegate(this);
  173. parent_layer->Add(calibration_layer_.get());
  174. }
  175. } // namespace ash