| Index: ash/display/display_controller.cc
|
| diff --git a/ash/display/display_controller.cc b/ash/display/display_controller.cc
|
| index 7954d44ac9e84e8d0762880499c8ca11290bd3fb..39151237bda212dd55d42b5a2a9a3096cb215a14 100644
|
| --- a/ash/display/display_controller.cc
|
| +++ b/ash/display/display_controller.cc
|
| @@ -15,6 +15,9 @@
|
| #include "ash/wm/property_util.h"
|
| #include "ash/wm/window_util.h"
|
| #include "base/command_line.h"
|
| +#include "base/json/json_value_converter.h"
|
| +#include "base/string_piece.h"
|
| +#include "base/values.h"
|
| #include "ui/aura/client/screen_position_client.h"
|
| #include "ui/aura/env.h"
|
| #include "ui/aura/root_window.h"
|
| @@ -27,16 +30,85 @@ namespace ash {
|
| namespace internal {
|
| namespace {
|
|
|
| +// The maximum value for 'offset' in DisplayLayout in case of outliers. Need
|
| +// to change this value in case to support even larger displays.
|
| +const int kMaxValidOffset = 10000;
|
| +
|
| // The number of pixels to overlap between the primary and secondary displays,
|
| // in case that the offset value is too large.
|
| const int kMinimumOverlapForInvalidOffset = 50;
|
|
|
| +bool GetPositionFromString(const base::StringPiece& position,
|
| + DisplayLayout::Position* field) {
|
| + if (position == "top") {
|
| + *field = DisplayLayout::TOP;
|
| + return true;
|
| + } else if (position == "bottom") {
|
| + *field = DisplayLayout::BOTTOM;
|
| + return true;
|
| + } else if (position == "right") {
|
| + *field = DisplayLayout::RIGHT;
|
| + return true;
|
| + } else if (position == "left") {
|
| + *field = DisplayLayout::LEFT;
|
| + return true;
|
| + }
|
| + LOG(ERROR) << "Invalid position value: " << position;
|
| +
|
| + return false;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +DisplayLayout::DisplayLayout()
|
| + : position(RIGHT), offset(0) {}
|
| +
|
| +DisplayLayout::DisplayLayout(DisplayLayout::Position position, int offset)
|
| + : position(position), offset(offset) {
|
| + DCHECK_LE(TOP, position);
|
| + DCHECK_GE(LEFT, position);
|
| +
|
| + // Set the default value to |position| in case position is invalid. DCHECKs
|
| + // above doesn't stop in Release builds.
|
| + if (TOP > position || LEFT < position)
|
| + this->position = RIGHT;
|
| +
|
| + DCHECK_GE(kMaxValidOffset, abs(offset));
|
| +}
|
| +
|
| +void DisplayLayout::RegisterJSONConverter(
|
| + base::JSONValueConverter<DisplayLayout>* converter) {
|
| + converter->RegisterCustomField<Position>(
|
| + "position", &DisplayLayout::position, &GetPositionFromString);
|
| + converter->RegisterIntField("offset", &DisplayLayout::offset);
|
| +}
|
| +
|
| +bool DisplayLayout::ConvertToValue(base::DictionaryValue* value) {
|
| + std::string position_value;
|
| + switch (position) {
|
| + case TOP:
|
| + position_value = "top";
|
| + break;
|
| + case BOTTOM:
|
| + position_value = "bottom";
|
| + break;
|
| + case RIGHT:
|
| + position_value = "right";
|
| + break;
|
| + case LEFT:
|
| + position_value = "left";
|
| + break;
|
| + default:
|
| + return false;
|
| + }
|
| +
|
| + value->SetString("position", position_value);
|
| + value->SetInteger("offset", offset);
|
| + return true;
|
| }
|
|
|
| DisplayController::DisplayController()
|
| - : secondary_display_layout_(RIGHT),
|
| - secondary_display_offset_(0),
|
| - dont_warp_mouse_(false) {
|
| + : dont_warp_mouse_(false) {
|
| aura::Env::GetInstance()->display_manager()->AddObserver(this);
|
| }
|
|
|
| @@ -128,17 +200,27 @@ DisplayController::GetAllRootWindowControllers() {
|
| return controllers;
|
| }
|
|
|
| -void DisplayController::SetSecondaryDisplayLayout(
|
| - SecondaryDisplayLayout layout) {
|
| - secondary_display_layout_ = layout;
|
| +void DisplayController::SetDefaultDisplayLayout(const DisplayLayout& layout) {
|
| + default_display_layout_ = layout;
|
| UpdateDisplayBoundsForLayout();
|
| }
|
|
|
| -void DisplayController::SetSecondaryDisplayOffset(int offset) {
|
| - secondary_display_offset_ = offset;
|
| +void DisplayController::SetLayoutForDisplayName(const std::string& name,
|
| + const DisplayLayout& layout) {
|
| + secondary_layouts_[name] = layout;
|
| UpdateDisplayBoundsForLayout();
|
| }
|
|
|
| +const DisplayLayout& DisplayController::GetLayoutForDisplayName(
|
| + const std::string& name) {
|
| + std::map<std::string, DisplayLayout>::const_iterator it =
|
| + secondary_layouts_.find(name);
|
| +
|
| + if (it != secondary_layouts_.end())
|
| + return it->second;
|
| + return default_display_layout_;
|
| +}
|
| +
|
| bool DisplayController::WarpMouseCursorIfNecessary(
|
| aura::RootWindow* current_root,
|
| const gfx::Point& point_in_root) {
|
| @@ -255,15 +337,22 @@ void DisplayController::UpdateDisplayBoundsForLayout() {
|
| aura::Env::GetInstance()->display_manager();
|
| const gfx::Rect& primary_bounds = display_manager->GetDisplayAt(0)->bounds();
|
| gfx::Display* secondary_display = display_manager->GetDisplayAt(1);
|
| + const std::string& secondary_name = display_manager->GetDisplayNameAt(1);
|
| const gfx::Rect& secondary_bounds = secondary_display->bounds();
|
| gfx::Point new_secondary_origin = primary_bounds.origin();
|
|
|
| - // TODO(oshima|mukai): Implement more flexible layout.
|
| + const DisplayLayout* layout = &default_display_layout_;
|
| + std::map<std::string, DisplayLayout>::const_iterator iter =
|
| + secondary_layouts_.find(secondary_name);
|
| + if (iter != secondary_layouts_.end())
|
| + layout = &iter->second;
|
| +
|
| + DisplayLayout::Position position = layout->position;
|
|
|
| // Ignore the offset in case the secondary display doesn't share edges with
|
| // the primary display.
|
| - int offset = secondary_display_offset_;
|
| - if (secondary_display_layout_ == TOP || secondary_display_layout_ == BOTTOM) {
|
| + int offset = layout->offset;
|
| + if (position == DisplayLayout::TOP || position == DisplayLayout::BOTTOM) {
|
| offset = std::min(
|
| offset, primary_bounds.width() - kMinimumOverlapForInvalidOffset);
|
| offset = std::max(
|
| @@ -274,17 +363,17 @@ void DisplayController::UpdateDisplayBoundsForLayout() {
|
| offset = std::max(
|
| offset, -secondary_bounds.height() + kMinimumOverlapForInvalidOffset);
|
| }
|
| - switch (secondary_display_layout_) {
|
| - case TOP:
|
| + switch (position) {
|
| + case DisplayLayout::TOP:
|
| new_secondary_origin.Offset(offset, -secondary_bounds.height());
|
| break;
|
| - case RIGHT:
|
| + case DisplayLayout::RIGHT:
|
| new_secondary_origin.Offset(primary_bounds.width(), offset);
|
| break;
|
| - case BOTTOM:
|
| + case DisplayLayout::BOTTOM:
|
| new_secondary_origin.Offset(offset, primary_bounds.height());
|
| break;
|
| - case LEFT:
|
| + case DisplayLayout::LEFT:
|
| new_secondary_origin.Offset(-secondary_bounds.width(), offset);
|
| break;
|
| }
|
|
|