root/chrome/browser/chromeos/display/overscan_calibrator.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. DrawTriangle
  2. committed_
  3. Commit
  4. Reset
  5. UpdateInsets
  6. OnPaintLayer
  7. OnDeviceScaleFactorChanged
  8. PrepareForLayerBoundsChange

// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/display/overscan_calibrator.h"

#include "ash/display/display_controller.h"
#include "ash/display/display_info.h"
#include "ash/display/display_manager.h"
#include "ash/shell.h"
#include "ash/shell_window_ids.h"
#include "base/callback.h"
#include "ui/aura/window.h"
#include "ui/compositor/layer.h"
#include "ui/gfx/canvas.h"

namespace chromeos {
namespace {

// The opacity for the arrows of the overscan calibration.
const float kArrowOpacity = 0.8;

// The height in pixel for the arrows to show the overscan calibration.
const int kCalibrationArrowHeight = 50;

// The gap between the boundary and calibration arrows.
const int kArrowGapWidth = 20;

// Draw the arrow for the overscan calibration to |canvas|.
void DrawTriangle(int x_offset,
                  int y_offset,
                  double rotation_degree,
                  gfx::Canvas* canvas) {
  // Draw triangular arrows.
  SkPaint content_paint;
  content_paint.setStyle(SkPaint::kFill_Style);
  content_paint.setColor(SkColorSetA(SK_ColorBLACK, kuint8max * kArrowOpacity));
  SkPaint border_paint;
  border_paint.setStyle(SkPaint::kStroke_Style);
  border_paint.setColor(SkColorSetA(SK_ColorWHITE, kuint8max * kArrowOpacity));

  SkPath base_path;
  base_path.moveTo(0, SkIntToScalar(-kCalibrationArrowHeight));
  base_path.lineTo(SkIntToScalar(-kCalibrationArrowHeight), 0);
  base_path.lineTo(SkIntToScalar(kCalibrationArrowHeight), 0);
  base_path.close();

  SkPath path;
  gfx::Transform rotate_transform;
  rotate_transform.Rotate(rotation_degree);
  gfx::Transform move_transform;
  move_transform.Translate(x_offset, y_offset);
  rotate_transform.ConcatTransform(move_transform);
  base_path.transform(rotate_transform.matrix(), &path);

  canvas->DrawPath(path, content_paint);
  canvas->DrawPath(path, border_paint);
}

}  // namespace

OverscanCalibrator::OverscanCalibrator(
    const gfx::Display& target_display, const gfx::Insets& initial_insets)
    : display_(target_display),
      insets_(initial_insets),
      initial_insets_(initial_insets),
      committed_(false) {
  // Undo the overscan calibration temporarily so that the user can see
  // dark boundary and current overscan region.
  ash::Shell::GetInstance()->display_controller()->SetOverscanInsets(
      display_.id(), gfx::Insets());

  ash::DisplayInfo info =
      ash::Shell::GetInstance()->display_manager()->GetDisplayInfo(
          display_.id());

  aura::Window* root = ash::Shell::GetInstance()->display_controller()->
      GetRootWindowForDisplayId(display_.id());
  ui::Layer* parent_layer =
      ash::Shell::GetContainer(root, ash::kShellWindowId_OverlayContainer)
          ->layer();

  calibration_layer_.reset(new ui::Layer());
  calibration_layer_->SetOpacity(0.5f);
  calibration_layer_->SetBounds(parent_layer->bounds());
  calibration_layer_->set_delegate(this);
  parent_layer->Add(calibration_layer_.get());
}

OverscanCalibrator::~OverscanCalibrator() {
  // Overscan calibration has finished without commit, so the display has to
  // be the original offset.
  if (!committed_) {
    ash::Shell::GetInstance()->display_controller()->SetOverscanInsets(
        display_.id(), initial_insets_);
  }
}

void OverscanCalibrator::Commit() {
  ash::Shell::GetInstance()->display_controller()->SetOverscanInsets(
      display_.id(), insets_);
  committed_ = true;
}

void OverscanCalibrator::Reset() {
  insets_ = initial_insets_;
  calibration_layer_->SchedulePaint(calibration_layer_->bounds());
}

void OverscanCalibrator::UpdateInsets(const gfx::Insets& insets) {
  insets_.Set(std::max(insets.top(), 0),
              std::max(insets.left(), 0),
              std::max(insets.bottom(), 0),
              std::max(insets.right(), 0));
  calibration_layer_->SchedulePaint(calibration_layer_->bounds());
}

void OverscanCalibrator::OnPaintLayer(gfx::Canvas* canvas) {
  static const SkColor kTransparent = SkColorSetARGB(0, 0, 0, 0);
  gfx::Rect full_bounds = calibration_layer_->bounds();
  gfx::Rect inner_bounds = full_bounds;
  inner_bounds.Inset(insets_);
  canvas->FillRect(full_bounds, SK_ColorBLACK);
  canvas->FillRect(inner_bounds, kTransparent, SkXfermode::kClear_Mode);

  gfx::Point center = inner_bounds.CenterPoint();
  int vertical_offset = inner_bounds.height() / 2 - kArrowGapWidth;
  int horizontal_offset = inner_bounds.width() / 2 - kArrowGapWidth;

  DrawTriangle(center.x(), center.y() + vertical_offset, 0, canvas);
  DrawTriangle(center.x(), center.y() - vertical_offset, 180, canvas);
  DrawTriangle(center.x() - horizontal_offset, center.y(), 90, canvas);
  DrawTriangle(center.x() + horizontal_offset, center.y(), -90, canvas);
}

void OverscanCalibrator::OnDeviceScaleFactorChanged(
    float device_scale_factor) {
  // TODO(mukai): Cancel the overscan calibration when the device
  // configuration has changed.
}

base::Closure OverscanCalibrator::PrepareForLayerBoundsChange() {
  return base::Closure();
}

}  // namespace chromeos

/* [<][>][^][v][top][bottom][index][help] */