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.
5 #include "chrome/browser/chromeos/display/overscan_calibrator.h"
7 #include "ash/display/display_controller.h"
8 #include "ash/display/display_info.h"
9 #include "ash/display/display_manager.h"
10 #include "ash/shell.h"
11 #include "ash/shell_window_ids.h"
12 #include "base/callback.h"
13 #include "ui/aura/window.h"
14 #include "ui/compositor/layer.h"
15 #include "ui/compositor/paint_recorder.h"
16 #include "ui/gfx/canvas.h"
21 // The opacity for the arrows of the overscan calibration.
22 const float kArrowOpacity
= 0.8;
24 // The height in pixel for the arrows to show the overscan calibration.
25 const int kCalibrationArrowHeight
= 50;
27 // The gap between the boundary and calibration arrows.
28 const int kArrowGapWidth
= 20;
30 // Draw the arrow for the overscan calibration to |canvas|.
31 void DrawTriangle(int x_offset
,
33 double rotation_degree
,
34 gfx::Canvas
* canvas
) {
35 // Draw triangular arrows.
36 SkPaint content_paint
;
37 content_paint
.setStyle(SkPaint::kFill_Style
);
38 content_paint
.setColor(SkColorSetA(SK_ColorBLACK
, kuint8max
* kArrowOpacity
));
40 border_paint
.setStyle(SkPaint::kStroke_Style
);
41 border_paint
.setColor(SkColorSetA(SK_ColorWHITE
, kuint8max
* kArrowOpacity
));
44 base_path
.moveTo(0, SkIntToScalar(-kCalibrationArrowHeight
));
45 base_path
.lineTo(SkIntToScalar(-kCalibrationArrowHeight
), 0);
46 base_path
.lineTo(SkIntToScalar(kCalibrationArrowHeight
), 0);
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(), &path
);
57 canvas
->DrawPath(path
, content_paint
);
58 canvas
->DrawPath(path
, border_paint
);
63 OverscanCalibrator::OverscanCalibrator(
64 const gfx::Display
& target_display
, const gfx::Insets
& initial_insets
)
65 : display_(target_display
),
66 insets_(initial_insets
),
67 initial_insets_(initial_insets
),
69 // Undo the overscan calibration temporarily so that the user can see
70 // dark boundary and current overscan region.
71 ash::Shell::GetInstance()->display_controller()->SetOverscanInsets(
72 display_
.id(), gfx::Insets());
74 ash::DisplayInfo info
=
75 ash::Shell::GetInstance()->display_manager()->GetDisplayInfo(
78 aura::Window
* root
= ash::Shell::GetInstance()->display_controller()->
79 GetRootWindowForDisplayId(display_
.id());
80 ui::Layer
* parent_layer
=
81 ash::Shell::GetContainer(root
, ash::kShellWindowId_OverlayContainer
)
84 calibration_layer_
.reset(new ui::Layer());
85 calibration_layer_
->SetOpacity(0.5f
);
86 calibration_layer_
->SetBounds(parent_layer
->bounds());
87 calibration_layer_
->set_delegate(this);
88 parent_layer
->Add(calibration_layer_
.get());
91 OverscanCalibrator::~OverscanCalibrator() {
92 // Overscan calibration has finished without commit, so the display has to
93 // be the original offset.
95 ash::Shell::GetInstance()->display_controller()->SetOverscanInsets(
96 display_
.id(), initial_insets_
);
100 void OverscanCalibrator::Commit() {
101 ash::Shell::GetInstance()->display_controller()->SetOverscanInsets(
102 display_
.id(), insets_
);
106 void OverscanCalibrator::Reset() {
107 insets_
= initial_insets_
;
108 calibration_layer_
->SchedulePaint(calibration_layer_
->bounds());
111 void OverscanCalibrator::UpdateInsets(const gfx::Insets
& insets
) {
112 insets_
.Set(std::max(insets
.top(), 0),
113 std::max(insets
.left(), 0),
114 std::max(insets
.bottom(), 0),
115 std::max(insets
.right(), 0));
116 calibration_layer_
->SchedulePaint(calibration_layer_
->bounds());
119 void OverscanCalibrator::OnPaintLayer(const ui::PaintContext
& context
) {
120 ui::PaintRecorder
recorder(context
, calibration_layer_
->size());
121 static const SkColor kTransparent
= SkColorSetARGB(0, 0, 0, 0);
122 gfx::Rect full_bounds
= calibration_layer_
->bounds();
123 gfx::Rect inner_bounds
= full_bounds
;
124 inner_bounds
.Inset(insets_
);
125 recorder
.canvas()->FillRect(full_bounds
, SK_ColorBLACK
);
126 recorder
.canvas()->FillRect(inner_bounds
, kTransparent
,
127 SkXfermode::kClear_Mode
);
129 gfx::Point center
= inner_bounds
.CenterPoint();
130 int vertical_offset
= inner_bounds
.height() / 2 - kArrowGapWidth
;
131 int horizontal_offset
= inner_bounds
.width() / 2 - kArrowGapWidth
;
133 gfx::Canvas
* canvas
= recorder
.canvas();
134 DrawTriangle(center
.x(), center
.y() + vertical_offset
, 0, canvas
);
135 DrawTriangle(center
.x(), center
.y() - vertical_offset
, 180, canvas
);
136 DrawTriangle(center
.x() - horizontal_offset
, center
.y(), 90, canvas
);
137 DrawTriangle(center
.x() + horizontal_offset
, center
.y(), -90, canvas
);
140 void OverscanCalibrator::OnDelegatedFrameDamage(
141 const gfx::Rect
& damage_rect_in_dip
) {
144 void OverscanCalibrator::OnDeviceScaleFactorChanged(
145 float device_scale_factor
) {
146 // TODO(mukai): Cancel the overscan calibration when the device
147 // configuration has changed.
150 base::Closure
OverscanCalibrator::PrepareForLayerBoundsChange() {
151 return base::Closure();
154 } // namespace chromeos