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