Home | History | Annotate | Download | only in display
      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 
      5 #include "chrome/browser/chromeos/display/overscan_calibrator.h"
      6 
      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/gfx/canvas.h"
     16 
     17 namespace chromeos {
     18 namespace {
     19 
     20 // The opacity for the arrows of the overscan calibration.
     21 const float kArrowOpacity = 0.8;
     22 
     23 // The height in pixel for the arrows to show the overscan calibration.
     24 const int kCalibrationArrowHeight = 50;
     25 
     26 // The gap between the boundary and calibration arrows.
     27 const int kArrowGapWidth = 20;
     28 
     29 // Draw the arrow for the overscan calibration to |canvas|.
     30 void DrawTriangle(int x_offset,
     31                   int y_offset,
     32                   double rotation_degree,
     33                   gfx::Canvas* canvas) {
     34   // Draw triangular arrows.
     35   SkPaint content_paint;
     36   content_paint.setStyle(SkPaint::kFill_Style);
     37   content_paint.setColor(SkColorSetA(SK_ColorBLACK, kuint8max * kArrowOpacity));
     38   SkPaint border_paint;
     39   border_paint.setStyle(SkPaint::kStroke_Style);
     40   border_paint.setColor(SkColorSetA(SK_ColorWHITE, kuint8max * kArrowOpacity));
     41 
     42   SkPath base_path;
     43   base_path.moveTo(0, SkIntToScalar(-kCalibrationArrowHeight));
     44   base_path.lineTo(SkIntToScalar(-kCalibrationArrowHeight), 0);
     45   base_path.lineTo(SkIntToScalar(kCalibrationArrowHeight), 0);
     46   base_path.close();
     47 
     48   SkPath path;
     49   gfx::Transform rotate_transform;
     50   rotate_transform.Rotate(rotation_degree);
     51   gfx::Transform move_transform;
     52   move_transform.Translate(x_offset, y_offset);
     53   rotate_transform.ConcatTransform(move_transform);
     54   base_path.transform(rotate_transform.matrix(), &path);
     55 
     56   canvas->DrawPath(path, content_paint);
     57   canvas->DrawPath(path, border_paint);
     58 }
     59 
     60 }  // namespace
     61 
     62 OverscanCalibrator::OverscanCalibrator(
     63     const gfx::Display& target_display, const gfx::Insets& initial_insets)
     64     : display_(target_display),
     65       insets_(initial_insets),
     66       initial_insets_(initial_insets),
     67       committed_(false) {
     68   // Undo the overscan calibration temporarily so that the user can see
     69   // dark boundary and current overscan region.
     70   ash::Shell::GetInstance()->display_controller()->SetOverscanInsets(
     71       display_.id(), gfx::Insets());
     72 
     73   ash::internal::DisplayInfo info = ash::Shell::GetInstance()->
     74       display_manager()->GetDisplayInfo(display_.id());
     75 
     76   aura::Window* root = ash::Shell::GetInstance()->display_controller()->
     77       GetRootWindowForDisplayId(display_.id());
     78   ui::Layer* parent_layer = ash::Shell::GetContainer(
     79       root, ash::internal::kShellWindowId_OverlayContainer)->layer();
     80 
     81   calibration_layer_.reset(new ui::Layer());
     82   calibration_layer_->SetOpacity(0.5f);
     83   calibration_layer_->SetBounds(parent_layer->bounds());
     84   calibration_layer_->set_delegate(this);
     85   parent_layer->Add(calibration_layer_.get());
     86 }
     87 
     88 OverscanCalibrator::~OverscanCalibrator() {
     89   // Overscan calibration has finished without commit, so the display has to
     90   // be the original offset.
     91   if (!committed_) {
     92     ash::Shell::GetInstance()->display_controller()->SetOverscanInsets(
     93         display_.id(), initial_insets_);
     94   }
     95 }
     96 
     97 void OverscanCalibrator::Commit() {
     98   ash::Shell::GetInstance()->display_controller()->SetOverscanInsets(
     99       display_.id(), insets_);
    100   committed_ = true;
    101 }
    102 
    103 void OverscanCalibrator::Reset() {
    104   insets_ = initial_insets_;
    105   calibration_layer_->SchedulePaint(calibration_layer_->bounds());
    106 }
    107 
    108 void OverscanCalibrator::UpdateInsets(const gfx::Insets& insets) {
    109   insets_.Set(std::max(insets.top(), 0),
    110               std::max(insets.left(), 0),
    111               std::max(insets.bottom(), 0),
    112               std::max(insets.right(), 0));
    113   calibration_layer_->SchedulePaint(calibration_layer_->bounds());
    114 }
    115 
    116 void OverscanCalibrator::OnPaintLayer(gfx::Canvas* canvas) {
    117   static const SkColor kTransparent = SkColorSetARGB(0, 0, 0, 0);
    118   gfx::Rect full_bounds = calibration_layer_->bounds();
    119   gfx::Rect inner_bounds = full_bounds;
    120   inner_bounds.Inset(insets_);
    121   canvas->FillRect(full_bounds, SK_ColorBLACK);
    122   canvas->FillRect(inner_bounds, kTransparent, SkXfermode::kClear_Mode);
    123 
    124   gfx::Point center = inner_bounds.CenterPoint();
    125   int vertical_offset = inner_bounds.height() / 2 - kArrowGapWidth;
    126   int horizontal_offset = inner_bounds.width() / 2 - kArrowGapWidth;
    127 
    128   DrawTriangle(center.x(), center.y() + vertical_offset, 0, canvas);
    129   DrawTriangle(center.x(), center.y() - vertical_offset, 180, canvas);
    130   DrawTriangle(center.x() - horizontal_offset, center.y(), 90, canvas);
    131   DrawTriangle(center.x() + horizontal_offset, center.y(), -90, canvas);
    132 }
    133 
    134 void OverscanCalibrator::OnDeviceScaleFactorChanged(
    135     float device_scale_factor) {
    136   // TODO(mukai): Cancel the overscan calibration when the device
    137   // configuration has changed.
    138 }
    139 
    140 base::Closure OverscanCalibrator::PrepareForLayerBoundsChange() {
    141   return base::Closure();
    142 }
    143 
    144 }  // namespace chromeos
    145