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::DisplayInfo info =
     74       ash::Shell::GetInstance()->display_manager()->GetDisplayInfo(
     75           display_.id());
     76 
     77   aura::Window* root = ash::Shell::GetInstance()->display_controller()->
     78       GetRootWindowForDisplayId(display_.id());
     79   ui::Layer* parent_layer =
     80       ash::Shell::GetContainer(root, ash::kShellWindowId_OverlayContainer)
     81           ->layer();
     82 
     83   calibration_layer_.reset(new ui::Layer());
     84   calibration_layer_->SetOpacity(0.5f);
     85   calibration_layer_->SetBounds(parent_layer->bounds());
     86   calibration_layer_->set_delegate(this);
     87   parent_layer->Add(calibration_layer_.get());
     88 }
     89 
     90 OverscanCalibrator::~OverscanCalibrator() {
     91   // Overscan calibration has finished without commit, so the display has to
     92   // be the original offset.
     93   if (!committed_) {
     94     ash::Shell::GetInstance()->display_controller()->SetOverscanInsets(
     95         display_.id(), initial_insets_);
     96   }
     97 }
     98 
     99 void OverscanCalibrator::Commit() {
    100   ash::Shell::GetInstance()->display_controller()->SetOverscanInsets(
    101       display_.id(), insets_);
    102   committed_ = true;
    103 }
    104 
    105 void OverscanCalibrator::Reset() {
    106   insets_ = initial_insets_;
    107   calibration_layer_->SchedulePaint(calibration_layer_->bounds());
    108 }
    109 
    110 void OverscanCalibrator::UpdateInsets(const gfx::Insets& insets) {
    111   insets_.Set(std::max(insets.top(), 0),
    112               std::max(insets.left(), 0),
    113               std::max(insets.bottom(), 0),
    114               std::max(insets.right(), 0));
    115   calibration_layer_->SchedulePaint(calibration_layer_->bounds());
    116 }
    117 
    118 void OverscanCalibrator::OnPaintLayer(gfx::Canvas* canvas) {
    119   static const SkColor kTransparent = SkColorSetARGB(0, 0, 0, 0);
    120   gfx::Rect full_bounds = calibration_layer_->bounds();
    121   gfx::Rect inner_bounds = full_bounds;
    122   inner_bounds.Inset(insets_);
    123   canvas->FillRect(full_bounds, SK_ColorBLACK);
    124   canvas->FillRect(inner_bounds, kTransparent, SkXfermode::kClear_Mode);
    125 
    126   gfx::Point center = inner_bounds.CenterPoint();
    127   int vertical_offset = inner_bounds.height() / 2 - kArrowGapWidth;
    128   int horizontal_offset = inner_bounds.width() / 2 - kArrowGapWidth;
    129 
    130   DrawTriangle(center.x(), center.y() + vertical_offset, 0, canvas);
    131   DrawTriangle(center.x(), center.y() - vertical_offset, 180, canvas);
    132   DrawTriangle(center.x() - horizontal_offset, center.y(), 90, canvas);
    133   DrawTriangle(center.x() + horizontal_offset, center.y(), -90, canvas);
    134 }
    135 
    136 void OverscanCalibrator::OnDelegatedFrameDamage(
    137     const gfx::Rect& damage_rect_in_dip) {
    138 }
    139 
    140 void OverscanCalibrator::OnDeviceScaleFactorChanged(
    141     float device_scale_factor) {
    142   // TODO(mukai): Cancel the overscan calibration when the device
    143   // configuration has changed.
    144 }
    145 
    146 base::Closure OverscanCalibrator::PrepareForLayerBoundsChange() {
    147   return base::Closure();
    148 }
    149 
    150 }  // namespace chromeos
    151