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