12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ash/display/display_manager.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <algorithm>
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <cmath>
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <set>
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <string>
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <vector>
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ash/ash_switches.h"
147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "ash/display/display_layout_store.h"
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/display/screen_ash.h"
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/screen_util.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ash/shell.h"
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/auto_reset.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/command_line.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h"
21effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "base/metrics/histogram.h"
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_split.h"
24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "grit/ash_strings.h"
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/display.h"
29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/gfx/display_observer.h"
3003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "ui/gfx/font_render_params.h"
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/rect.h"
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/screen.h"
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/size_conversions.h"
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(USE_X11)
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/base/x/x11_util.h"
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_CHROMEOS)
405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "ash/display/display_configurator_animation.h"
414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/sys_info.h"
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_WIN)
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/win/windows_version.h"
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace ash {
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)typedef std::vector<gfx::Display> DisplayList;
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)typedef std::vector<DisplayInfo> DisplayInfoList;
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// We need to keep this in order for unittests to tell if
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// the object in gfx::Screen::GetScreenByType is for shutdown.
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)gfx::Screen* screen_for_shutdown = NULL;
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// The number of pixels to overlap between the primary and secondary displays,
59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// in case that the offset value is too large.
60eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst int kMinimumOverlapForInvalidOffset = 100;
61eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// List of value UI Scale values. Scales for 2x are equivalent to 640,
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// 800, 1024, 1280, 1440, 1600 and 1920 pixel width respectively on
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// 2560 pixel width 2x density display. Please see crbug.com/233375
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// for the full list of resolutions.
66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const float kUIScalesFor2x[] =
67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    {0.5f, 0.625f, 0.8f, 1.0f, 1.125f, 1.25f, 1.5f, 2.0f};
685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const float kUIScalesFor1_25x[] = {0.5f, 0.625f, 0.8f, 1.0f, 1.25f };
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const float kUIScalesFor1280[] = {0.5f, 0.625f, 0.8f, 1.0f, 1.125f };
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const float kUIScalesFor1366[] = {0.5f, 0.6f, 0.75f, 1.0f, 1.125f };
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct DisplaySortFunctor {
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool operator()(const gfx::Display& a, const gfx::Display& b) {
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return a.id() < b.id();
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct DisplayInfoSortFunctor {
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool operator()(const DisplayInfo& a, const DisplayInfo& b) {
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return a.id() < b.id();
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)struct DisplayModeMatcher {
855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DisplayModeMatcher(const DisplayMode& target_mode)
865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      : target_mode(target_mode) {}
875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  bool operator()(const DisplayMode& mode) {
885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return target_mode.IsEquivalent(mode);
895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DisplayMode target_mode;
913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)};
923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)struct ScaleComparator {
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  explicit ScaleComparator(float s) : scale(s) {}
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool operator()(float s) const {
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const float kEpsilon = 0.0001f;
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return std::abs(scale - s) < kEpsilon;
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  float scale;
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)gfx::Display& GetInvalidDisplay() {
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static gfx::Display* invalid_display = new gfx::Display();
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return *invalid_display;
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void MaybeInitInternalDisplay(int64 id) {
1093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  CommandLine* command_line = CommandLine::ForCurrentProcess();
1103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (command_line->HasSwitch(switches::kAshUseFirstDisplayAsInternal))
1113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    gfx::Display::SetInternalDisplayId(id);
1123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
1133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Scoped objects used to either create or close the non desktop window
1157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// at specific timing.
1161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)class NonDesktopDisplayUpdater {
11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) public:
1181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  NonDesktopDisplayUpdater(DisplayManager* manager,
1191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                           DisplayManager::Delegate* delegate)
12068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      : manager_(manager),
12168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        delegate_(delegate),
1221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        enabled_(manager_->second_display_mode() != DisplayManager::EXTENDED &&
1231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                 manager_->non_desktop_display().is_valid()) {
12468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
12568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
1261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  ~NonDesktopDisplayUpdater() {
12768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (!delegate_)
12868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      return;
12968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
13068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (enabled_) {
13168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      DisplayInfo display_info = manager_->GetDisplayInfo(
1321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          manager_->non_desktop_display().id());
1331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      delegate_->CreateOrUpdateNonDesktopDisplay(display_info);
13468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    } else {
1351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      delegate_->CloseNonDesktopDisplay();
13668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
13790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
13968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  bool enabled() const { return enabled_; }
14068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
14190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) private:
14268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DisplayManager* manager_;
1437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DisplayManager::Delegate* delegate_;
14468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  bool enabled_;
1451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(NonDesktopDisplayUpdater);
14690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)};
14790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using std::string;
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using std::vector;
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DisplayManager::DisplayManager()
1547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    : delegate_(NULL),
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      screen_ash_(new ScreenAsh),
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      screen_(screen_ash_.get()),
1577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      layout_store_(new DisplayLayoutStore),
1587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      first_display_id_(gfx::Display::kInvalidDisplayID),
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      num_connected_displays_(0),
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      force_bounds_changed_(false),
16190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      change_display_upon_host_resize_(false),
1621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      second_display_mode_(EXTENDED),
16303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      mirrored_display_id_(gfx::Display::kInvalidDisplayID),
16403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      registered_internal_display_rotation_lock_(false),
16503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      registered_internal_display_rotation_(gfx::Display::ROTATE_0) {
1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_CHROMEOS)
1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Enable only on the device so that DisplayManagerFontTest passes.
1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (base::SysInfo::IsRunningOnChromeOS())
1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    DisplayInfo::SetUse125DSFForUIScaling(true);
1711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  change_display_upon_host_resize_ = !base::SysInfo::IsRunningOnChromeOS();
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_ALTERNATE,
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 screen_ash_.get());
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gfx::Screen* current_native =
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      gfx::Screen::GetScreenByType(gfx::SCREEN_TYPE_NATIVE);
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // If there is no native, or the native was for shutdown,
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // use ash's screen.
1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!current_native ||
1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      current_native == screen_for_shutdown) {
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE,
1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   screen_ash_.get());
1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DisplayManager::~DisplayManager() {
18803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#if defined(OS_CHROMEOS)
18903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Reset the font params.
19003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  gfx::SetFontRenderParamsDeviceScaleFactor(1.0f);
19103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#endif
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
19590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)std::vector<float> DisplayManager::GetScalesForDisplay(
19690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const DisplayInfo& info) {
1975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define ASSIGN_ARRAY(v, a) v.assign(a, a + arraysize(a))
1995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
20090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::vector<float> ret;
20190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (info.device_scale_factor() == 2.0f) {
2025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ASSIGN_ARRAY(ret, kUIScalesFor2x);
2035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return ret;
2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  } else if (info.device_scale_factor() == 1.25f) {
2055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ASSIGN_ARRAY(ret, kUIScalesFor1_25x);
20690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return ret;
20790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
20868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  switch (info.bounds_in_native().width()) {
20990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case 1280:
2105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      ASSIGN_ARRAY(ret, kUIScalesFor1280);
21190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
21290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case 1366:
2135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      ASSIGN_ARRAY(ret, kUIScalesFor1366);
21490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
21590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    default:
2165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      ASSIGN_ARRAY(ret, kUIScalesFor1280);
21790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#if defined(OS_CHROMEOS)
2184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      if (base::SysInfo::IsRunningOnChromeOS())
21990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        NOTREACHED() << "Unknown resolution:" << info.ToString();
22090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif
22190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
22290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return ret;
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)float DisplayManager::GetNextUIScale(const DisplayInfo& info, bool up) {
227f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  float scale = info.configured_ui_scale();
228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::vector<float> scales = GetScalesForDisplay(info);
229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (size_t i = 0; i < scales.size(); ++i) {
230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (ScaleComparator(scales[i])(scale)) {
231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (up && i != scales.size() - 1)
232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return scales[i + 1];
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!up && i != 0)
234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return scales[i - 1];
235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return scales[i];
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Fallback to 1.0f if the |scale| wasn't in the list.
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 1.0f;
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2420f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)bool DisplayManager::InitFromCommandLine() {
2437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DisplayInfoList info_list;
24468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  CommandLine* command_line = CommandLine::ForCurrentProcess();
2450f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  if (!command_line->HasSwitch(switches::kAshHostWindowBounds))
2460f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    return false;
24768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const string size_str =
24868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      command_line->GetSwitchValueASCII(switches::kAshHostWindowBounds);
2497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  vector<string> parts;
2507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  base::SplitString(size_str, ',', &parts);
2517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  for (vector<string>::const_iterator iter = parts.begin();
2527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch       iter != parts.end(); ++iter) {
2537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    info_list.push_back(DisplayInfo::CreateFromSpec(*iter));
2541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    info_list.back().set_native(true);
2557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2560f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  MaybeInitInternalDisplay(info_list[0].id());
25768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (info_list.size() > 1 &&
25868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      command_line->HasSwitch(switches::kAshEnableSoftwareMirroring)) {
2591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    SetSecondDisplayMode(MIRRORING);
26068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
2617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  OnNativeDisplaysChanged(info_list);
2620f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  return true;
2630f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
2640f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
2650f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void DisplayManager::InitDefaultDisplay() {
2660f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  DisplayInfoList info_list;
2670f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  info_list.push_back(DisplayInfo::CreateFromSpec(std::string()));
2681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  info_list.back().set_native(true);
2690f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  MaybeInitInternalDisplay(info_list[0].id());
2700f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  OnNativeDisplaysChanged(info_list);
2717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
27303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void DisplayManager::InitFontParams() {
27403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#if defined(OS_CHROMEOS)
27503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (!HasInternalDisplay())
27603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return;
27703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  const DisplayInfo& display_info =
27803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      GetDisplayInfo(gfx::Display::InternalDisplayId());
27903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  gfx::SetFontRenderParamsDeviceScaleFactor(
2801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      display_info.GetEffectiveDeviceScaleFactor());
28103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#endif  // OS_CHROMEOS
28203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
28303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
284ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// static
285ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid DisplayManager::UpdateDisplayBoundsForLayoutById(
286eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const DisplayLayout& layout,
287eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const gfx::Display& primary_display,
288ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    int64 secondary_display_id) {
289ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DCHECK_NE(gfx::Display::kInvalidDisplayID, secondary_display_id);
290ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  UpdateDisplayBoundsForLayout(
291ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      layout, primary_display,
292ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      Shell::GetInstance()->display_manager()->
293ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      FindDisplayForId(secondary_display_id));
294eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
295eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool DisplayManager::IsActiveDisplay(const gfx::Display& display) const {
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (DisplayList::const_iterator iter = displays_.begin();
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       iter != displays_.end(); ++iter) {
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if ((*iter).id() == display.id())
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return false;
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool DisplayManager::HasInternalDisplay() const {
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return gfx::Display::InternalDisplayId() != gfx::Display::kInvalidDisplayID;
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool DisplayManager::IsInternalDisplayId(int64 id) const {
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return gfx::Display::InternalDisplayId() == id;
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)DisplayLayout DisplayManager::GetCurrentDisplayLayout() {
3143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK_EQ(2U, num_connected_displays());
3153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Invert if the primary was swapped.
3163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (num_connected_displays() > 1) {
3173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    DisplayIdPair pair = GetCurrentDisplayIdPair();
3183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return layout_store_->ComputeDisplayLayoutForDisplayIdPair(pair);
3193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
3203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  NOTREACHED() << "DisplayLayout is requested for single display";
3213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // On release build, just fallback to default instead of blowing up.
3223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DisplayLayout layout =
3233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      layout_store_->default_display_layout();
3243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  layout.primary_id = displays_[0].id();
3253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return layout;
3263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
3273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)DisplayIdPair DisplayManager::GetCurrentDisplayIdPair() const {
3293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (IsMirrored()) {
3305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (software_mirroring_enabled()) {
3315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      CHECK_EQ(2u, num_connected_displays());
3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // This comment is to make it easy to distinguish the crash
3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // between two checks.
3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      CHECK_EQ(1u, displays_.size());
3355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
3361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return std::make_pair(displays_[0].id(), mirrored_display_id_);
3373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  } else {
3388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    CHECK_GE(2u, displays_.size());
3393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 id_at_zero = displays_[0].id();
3403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (id_at_zero == gfx::Display::InternalDisplayId() ||
3413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        id_at_zero == first_display_id()) {
3423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return std::make_pair(id_at_zero, displays_[1].id());
3433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    } else {
3443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return std::make_pair(displays_[1].id(), id_at_zero);
3453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
3463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
3473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
3483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void DisplayManager::SetLayoutForCurrentDisplays(
3508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    const DisplayLayout& layout_relative_to_primary) {
3518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK_EQ(2U, GetNumDisplays());
3528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (GetNumDisplays() < 2)
3538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return;
3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const gfx::Display& primary = screen_->GetPrimaryDisplay();
3558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  const DisplayIdPair pair = GetCurrentDisplayIdPair();
3568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // Invert if the primary was swapped.
3578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DisplayLayout to_set = pair.first == primary.id() ?
3588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      layout_relative_to_primary : layout_relative_to_primary.Invert();
3598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
3608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DisplayLayout current_layout =
3618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      layout_store_->GetRegisteredDisplayLayout(pair);
3628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (to_set.position != current_layout.position ||
3638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      to_set.offset != current_layout.offset) {
3648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    to_set.primary_id = primary.id();
3658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    layout_store_->RegisterLayoutForDisplayIdPair(
3668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        pair.first, pair.second, to_set);
3678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (delegate_)
3688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      delegate_->PreDisplayConfigurationChange(false);
3698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // PreDisplayConfigurationChange(false);
3708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // TODO(oshima): Call UpdateDisplays instead.
3718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    const DisplayLayout layout = GetCurrentDisplayLayout();
3728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    UpdateDisplayBoundsForLayoutById(
3738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        layout, primary,
3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        ScreenUtil::GetSecondaryDisplay().id());
3758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
3768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // Primary's bounds stay the same. Just notify bounds change
3778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // on the secondary.
378cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    screen_ash_->NotifyMetricsChanged(
379cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        ScreenUtil::GetSecondaryDisplay(),
380cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        gfx::DisplayObserver::DISPLAY_METRIC_BOUNDS |
381cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            gfx::DisplayObserver::DISPLAY_METRIC_WORK_AREA);
3828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (delegate_)
3838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      delegate_->PostDisplayConfigurationChange();
3848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
3858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
3868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const gfx::Display& DisplayManager::GetDisplayForId(int64 id) const {
388ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  gfx::Display* display =
389ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      const_cast<DisplayManager*>(this)->FindDisplayForId(id);
390ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return display ? *display : GetInvalidDisplay();
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const gfx::Display& DisplayManager::FindDisplayContainingPoint(
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const gfx::Point& point_in_screen) const {
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (DisplayList::const_iterator iter = displays_.begin();
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       iter != displays_.end(); ++iter) {
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const gfx::Display& display = *iter;
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (display.bounds().Contains(point_in_screen))
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return display;
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return GetInvalidDisplay();
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
404ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochbool DisplayManager::UpdateWorkAreaOfDisplay(int64 display_id,
405ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                             const gfx::Insets& insets) {
406ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  gfx::Display* display = FindDisplayForId(display_id);
407ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DCHECK(display);
408ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  gfx::Rect old_work_area = display->work_area();
409ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  display->UpdateWorkAreaFromInsets(insets);
410ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return old_work_area != display->work_area();
411ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
412ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DisplayManager::SetOverscanInsets(int64 display_id,
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       const gfx::Insets& insets_in_dip) {
415eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  display_info_[display_id].SetOverscanInsets(insets_in_dip);
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DisplayInfoList display_info_list;
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (DisplayList::const_iterator iter = displays_.begin();
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       iter != displays_.end(); ++iter) {
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    display_info_list.push_back(GetDisplayInfo(iter->id()));
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
421868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddMirrorDisplayInfoIfAny(&display_info_list);
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateDisplays(display_info_list);
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DisplayManager::SetDisplayRotation(int64 display_id,
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        gfx::Display::Rotation rotation) {
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DisplayInfoList display_info_list;
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (DisplayList::const_iterator iter = displays_.begin();
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       iter != displays_.end(); ++iter) {
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DisplayInfo info = GetDisplayInfo(iter->id());
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (info.id() == display_id) {
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (info.rotation() == rotation)
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return;
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      info.set_rotation(rotation);
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    display_info_list.push_back(info);
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
438868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddMirrorDisplayInfoIfAny(&display_info_list);
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateDisplays(display_info_list);
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DisplayManager::SetDisplayUIScale(int64 display_id,
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       float ui_scale) {
444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!IsDisplayUIScalingEnabled() ||
445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      gfx::Display::InternalDisplayId() != display_id) {
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
447c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // TODO(mukai): merge this implementation into SetDisplayMode().
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DisplayInfoList display_info_list;
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (DisplayList::const_iterator iter = displays_.begin();
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       iter != displays_.end(); ++iter) {
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DisplayInfo info = GetDisplayInfo(iter->id());
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (info.id() == display_id) {
455f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (info.configured_ui_scale() == ui_scale)
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return;
457c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      std::vector<float> scales = GetScalesForDisplay(info);
458c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ScaleComparator comparator(ui_scale);
459c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (std::find_if(scales.begin(), scales.end(), comparator) ==
460c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          scales.end()) {
461c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return;
462c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
463f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      info.set_configured_ui_scale(ui_scale);
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    display_info_list.push_back(info);
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
467868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddMirrorDisplayInfoIfAny(&display_info_list);
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateDisplays(display_info_list);
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
471a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void DisplayManager::SetDisplayResolution(int64 display_id,
472a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                          const gfx::Size& resolution) {
473a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DCHECK_NE(gfx::Display::InternalDisplayId(), display_id);
474a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (gfx::Display::InternalDisplayId() == display_id)
475a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return;
4763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const DisplayInfo& display_info = GetDisplayInfo(display_id);
4775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const std::vector<DisplayMode>& modes = display_info.display_modes();
4785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK_NE(0u, modes.size());
4795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DisplayMode target_mode;
4805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  target_mode.size = resolution;
4815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::vector<DisplayMode>::const_iterator iter =
4825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      std::find_if(modes.begin(), modes.end(), DisplayModeMatcher(target_mode));
4835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (iter == modes.end()) {
4843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    LOG(WARNING) << "Unsupported resolution was requested:"
4853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 << resolution.ToString();
4863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return;
4873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
4885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  display_modes_[display_id] = *iter;
489effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#if defined(OS_CHROMEOS)
4904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (base::SysInfo::IsRunningOnChromeOS())
491c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    Shell::GetInstance()->display_configurator()->OnConfigurationChanged();
492a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#endif
493a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
494a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
4955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool DisplayManager::SetDisplayMode(int64 display_id,
4965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                    const DisplayMode& display_mode) {
4975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (IsInternalDisplayId(display_id)) {
4985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    SetDisplayUIScale(display_id, display_mode.ui_scale);
4995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return false;
5005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
5015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DisplayInfoList display_info_list;
5035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  bool display_property_changed = false;
5045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  bool resolution_changed = false;
5055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  for (DisplayList::const_iterator iter = displays_.begin();
5065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)       iter != displays_.end(); ++iter) {
5075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    DisplayInfo info = GetDisplayInfo(iter->id());
5085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (info.id() == display_id) {
5095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      const std::vector<DisplayMode>& modes = info.display_modes();
5105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      std::vector<DisplayMode>::const_iterator iter =
5115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          std::find_if(modes.begin(),
5125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                       modes.end(),
5135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                       DisplayModeMatcher(display_mode));
5145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if (iter == modes.end()) {
5155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        LOG(WARNING) << "Unsupported resolution was requested:"
5165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                     << display_mode.size.ToString();
5175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return false;
5185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      }
5195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      display_modes_[display_id] = *iter;
5205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if (info.bounds_in_native().size() != display_mode.size)
5215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        resolution_changed = true;
5225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if (info.device_scale_factor() != display_mode.device_scale_factor) {
5235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        info.set_device_scale_factor(display_mode.device_scale_factor);
5245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        display_property_changed = true;
5255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      }
5265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
5275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    display_info_list.push_back(info);
5285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
5295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (display_property_changed) {
5305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    AddMirrorDisplayInfoIfAny(&display_info_list);
5315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    UpdateDisplays(display_info_list);
5325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
5335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(OS_CHROMEOS)
5345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (resolution_changed && base::SysInfo::IsRunningOnChromeOS())
5355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Shell::GetInstance()->display_configurator()->OnConfigurationChanged();
5365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif
5375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return resolution_changed;
5385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
5395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DisplayManager::RegisterDisplayProperty(
5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int64 display_id,
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    gfx::Display::Rotation rotation,
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    float ui_scale,
544a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const gfx::Insets* overscan_insets,
545effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    const gfx::Size& resolution_in_pixels,
5466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    float device_scale_factor,
547effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    ui::ColorCalibrationProfile color_profile) {
5485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (display_info_.find(display_id) == display_info_.end())
5495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    display_info_[display_id] = DisplayInfo(display_id, std::string(), false);
5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  display_info_[display_id].set_rotation(rotation);
552effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  display_info_[display_id].SetColorProfile(color_profile);
553c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Just in case the preference file was corrupted.
5545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // TODO(mukai): register |display_modes_| here as well, so the lookup for the
5555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // default mode in GetActiveModeForDisplayId() gets much simpler.
556c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (0.5f <= ui_scale && ui_scale <= 2.0f)
557f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    display_info_[display_id].set_configured_ui_scale(ui_scale);
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (overscan_insets)
559eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    display_info_[display_id].SetOverscanInsets(*overscan_insets);
5605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!resolution_in_pixels.IsEmpty()) {
5616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    DCHECK(!IsInternalDisplayId(display_id));
5625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Default refresh rate, until OnNativeDisplaysChanged() updates us with the
5635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // actual display info, is 60 Hz.
5646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    DisplayMode mode(resolution_in_pixels, 60.0f, false, false);
5656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    mode.device_scale_factor = device_scale_factor;
5666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    display_modes_[display_id] = mode;
5675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
568a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
569a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
5705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)DisplayMode DisplayManager::GetActiveModeForDisplayId(int64 display_id) const {
5715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DisplayMode selected_mode;
5725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (GetSelectedModeForDisplayId(display_id, &selected_mode))
5735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return selected_mode;
5745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // If 'selected' mode is empty, it should return the default mode. This means
5765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // the native mode for the external display. Unfortunately this is not true
5775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // for the internal display because restoring UI-scale doesn't register the
5785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // restored mode to |display_mode_|, so it needs to look up the mode whose
5795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // UI-scale value matches. See the TODO in RegisterDisplayProperty().
5805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const DisplayInfo& info = GetDisplayInfo(display_id);
5815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const std::vector<DisplayMode>& display_modes = info.display_modes();
5825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (IsInternalDisplayId(display_id)) {
5845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    for (size_t i = 0; i < display_modes.size(); ++i) {
5855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if (info.configured_ui_scale() == display_modes[i].ui_scale)
5865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return display_modes[i];
5875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
5885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  } else {
5895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    for (size_t i = 0; i < display_modes.size(); ++i) {
5905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if (display_modes[i].native)
5915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return display_modes[i];
5925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
5935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
5945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return selected_mode;
5955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
5965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
59703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void DisplayManager::RegisterDisplayRotationProperties(bool rotation_lock,
59803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    gfx::Display::Rotation rotation) {
59903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (delegate_)
60003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    delegate_->PreDisplayConfigurationChange(false);
60103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  registered_internal_display_rotation_lock_ = rotation_lock;
60203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  registered_internal_display_rotation_ = rotation;
60303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (delegate_)
60403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    delegate_->PostDisplayConfigurationChange();
60503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
60603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
6075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool DisplayManager::GetSelectedModeForDisplayId(int64 id,
6085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                 DisplayMode* mode_out) const {
6095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::map<int64, DisplayMode>::const_iterator iter = display_modes_.find(id);
6105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (iter == display_modes_.end())
611a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return false;
6125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  *mode_out = iter->second;
613a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return true;
6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool DisplayManager::IsDisplayUIScalingEnabled() const {
617c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return GetDisplayIdForUIScaling() != gfx::Display::kInvalidDisplayID;
6182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)gfx::Insets DisplayManager::GetOverscanInsets(int64 display_id) const {
6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::map<int64, DisplayInfo>::const_iterator it =
6222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      display_info_.find(display_id);
6232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return (it != display_info_.end()) ?
6242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      it->second.overscan_insets_in_dip() : gfx::Insets();
6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
627effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid DisplayManager::SetColorCalibrationProfile(
628effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    int64 display_id,
629effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    ui::ColorCalibrationProfile profile) {
630effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#if defined(OS_CHROMEOS)
631effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (!display_info_[display_id].IsColorProfileAvailable(profile))
632effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return;
633effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
634effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (delegate_)
635effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    delegate_->PreDisplayConfigurationChange(false);
636e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // Just sets color profile if it's not running on ChromeOS (like tests).
637e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  if (!base::SysInfo::IsRunningOnChromeOS() ||
638c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      Shell::GetInstance()->display_configurator()->SetColorCalibrationProfile(
639effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          display_id, profile)) {
640effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    display_info_[display_id].SetColorProfile(profile);
641effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    UMA_HISTOGRAM_ENUMERATION(
642effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        "ChromeOS.Display.ColorProfile", profile, ui::NUM_COLOR_PROFILES);
643effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
644effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (delegate_)
645effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    delegate_->PostDisplayConfigurationChange();
646effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#endif
647effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
648effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DisplayManager::OnNativeDisplaysChanged(
6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::vector<DisplayInfo>& updated_displays) {
6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (updated_displays.empty()) {
6521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    VLOG(1) << "OnNativeDisplaysChanged(0): # of current displays="
653f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            << displays_.size();
6547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // If the device is booted without display, or chrome is started
6557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // without --ash-host-window-bounds on linux desktop, use the
6567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // default display.
6577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (displays_.empty()) {
6587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      std::vector<DisplayInfo> init_displays;
6597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      init_displays.push_back(DisplayInfo::CreateFromSpec(std::string()));
6603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      MaybeInitInternalDisplay(init_displays[0].id());
6617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      OnNativeDisplaysChanged(init_displays);
6627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    } else {
6637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      // Otherwise don't update the displays when all displays are disconnected.
6647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      // This happens when:
6657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      // - the device is idle and powerd requested to turn off all displays.
6667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      // - the device is suspended. (kernel turns off all displays)
6677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      // - the internal display's brightness is set to 0 and no external
6687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      //   display is connected.
6697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      // - the internal display's brightness is 0 and external display is
6707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      //   disconnected.
6717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      // The display will be updated when one of displays is turned on, and the
6727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      // display list will be updated correctly.
6737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
6742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
6752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  first_display_id_ = updated_displays[0].id();
6777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::set<gfx::Point> origins;
6787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
679c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (updated_displays.size() == 1) {
680c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    VLOG(1) << "OnNativeDisplaysChanged(1):" << updated_displays[0].ToString();
681c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
682c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    VLOG(1) << "OnNativeDisplaysChanged(" << updated_displays.size()
683c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            << ") [0]=" << updated_displays[0].ToString()
684c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            << ", [1]=" << updated_displays[1].ToString();
685c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
686c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool internal_display_connected = false;
6882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  num_connected_displays_ = updated_displays.size();
6891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  mirrored_display_id_ = gfx::Display::kInvalidDisplayID;
6901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  non_desktop_display_ = gfx::Display();
6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DisplayInfoList new_display_info_list;
6922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (DisplayInfoList::const_iterator iter = updated_displays.begin();
6932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       iter != updated_displays.end();
6942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++iter) {
695c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!internal_display_connected)
6962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      internal_display_connected = IsInternalDisplayId(iter->id());
6977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // Mirrored monitors have the same origins.
69868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    gfx::Point origin = iter->bounds_in_native().origin();
6997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (origins.find(origin) != origins.end()) {
7002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      InsertAndUpdateDisplayInfo(*iter);
7011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      mirrored_display_id_ = iter->id();
7022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
7037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      origins.insert(origin);
7042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new_display_info_list.push_back(*iter);
7052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
7065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    DisplayMode new_mode;
7085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    new_mode.size = iter->bounds_in_native().size();
7095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    new_mode.device_scale_factor = iter->device_scale_factor();
7105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    new_mode.ui_scale = iter->configured_ui_scale();
7115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::vector<DisplayMode>& display_modes = iter->display_modes();
7125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // This is empty the displays are initialized from InitFromCommandLine.
7135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!display_modes.size())
7145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      continue;
7155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    std::vector<DisplayMode>::const_iterator display_modes_iter =
7165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        std::find_if(display_modes.begin(),
7175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     display_modes.end(),
7185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                     DisplayModeMatcher(new_mode));
7195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Update the actual resolution selected as the resolution request may fail.
7205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (display_modes_iter == display_modes.end())
7215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      display_modes_.erase(iter->id());
7225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    else if (display_modes_.find(iter->id()) != display_modes_.end())
7235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      display_modes_[iter->id()] = *display_modes_iter;
7242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
725c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (HasInternalDisplay() &&
726c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      !internal_display_connected &&
727c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      display_info_.find(gfx::Display::InternalDisplayId()) ==
728c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      display_info_.end()) {
729c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DisplayInfo internal_display_info(
730c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        gfx::Display::InternalDisplayId(),
731c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        l10n_util::GetStringUTF8(IDS_ASH_INTERNAL_DISPLAY_NAME),
732c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        false  /*Internal display must not have overscan */);
733c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    internal_display_info.SetBounds(gfx::Rect(0, 0, 800, 600));
734c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    display_info_[gfx::Display::InternalDisplayId()] = internal_display_info;
7352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateDisplays(new_display_info_list);
7372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DisplayManager::UpdateDisplays() {
7402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DisplayInfoList display_info_list;
7412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (DisplayList::const_iterator iter = displays_.begin();
7422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       iter != displays_.end(); ++iter) {
7432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    display_info_list.push_back(GetDisplayInfo(iter->id()));
7442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
745868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddMirrorDisplayInfoIfAny(&display_info_list);
7462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateDisplays(display_info_list);
7472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DisplayManager::UpdateDisplays(
7502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::vector<DisplayInfo>& updated_display_info_list) {
7517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#if defined(OS_WIN)
752cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK_EQ(1u, updated_display_info_list.size()) <<
753cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      ": Multiple display test does not work on Windows bots. Please "
754cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      "skip (don't disable) the test using SupportsMultipleDisplays()";
7557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#endif
7567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
7572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DisplayInfoList new_display_info_list = updated_display_info_list;
7582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::sort(displays_.begin(), displays_.end(), DisplaySortFunctor());
7592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::sort(new_display_info_list.begin(),
7602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            new_display_info_list.end(),
7612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            DisplayInfoSortFunctor());
7622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DisplayList removed_displays;
763cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::map<size_t, uint32_t> display_changes;
7642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<size_t> added_display_indices;
7652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DisplayList::iterator curr_iter = displays_.begin();
7672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DisplayInfoList::const_iterator new_info_iter = new_display_info_list.begin();
7682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DisplayList new_displays;
770c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
771868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Use the internal display or 1st as the mirror source, then scale
772868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // the root window so that it matches the external display's
773868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // resolution. This is necessary in order for scaling to work while
774868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // mirrored.
7751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  int64 non_desktop_display_id = gfx::Display::kInvalidDisplayID;
7761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
7771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (second_display_mode_ != EXTENDED && new_display_info_list.size() == 2) {
7784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    bool zero_is_source =
7794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        first_display_id_ == new_display_info_list[0].id() ||
7804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        gfx::Display::InternalDisplayId() == new_display_info_list[0].id();
7811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (second_display_mode_ == MIRRORING) {
7821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      mirrored_display_id_ = new_display_info_list[zero_is_source ? 1 : 0].id();
7831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      non_desktop_display_id = mirrored_display_id_;
7841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    } else {
7851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // TODO(oshima|bshe): The virtual keyboard is currently assigned to
7861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // the 1st display.
7871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      non_desktop_display_id =
7881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          new_display_info_list[zero_is_source ? 0 : 1].id();
7891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
7904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
79190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
7922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  while (curr_iter != displays_.end() ||
7932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         new_info_iter != new_display_info_list.end()) {
79490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (new_info_iter != new_display_info_list.end() &&
7951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        non_desktop_display_id == new_info_iter->id()) {
796868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      DisplayInfo info = *new_info_iter;
797eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      info.SetOverscanInsets(gfx::Insets());
798868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      InsertAndUpdateDisplayInfo(info);
7991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      non_desktop_display_ =
8001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          CreateDisplayFromDisplayInfoById(non_desktop_display_id);
80190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      ++new_info_iter;
8025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // Remove existing external display if it is going to be used as
8031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // non desktop.
80490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (curr_iter != displays_.end() &&
8051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          curr_iter->id() == non_desktop_display_id) {
80690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        removed_displays.push_back(*curr_iter);
80790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        ++curr_iter;
80890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      }
80990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      continue;
81090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
81190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
8122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (curr_iter == displays_.end()) {
8132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // more displays in new list.
8142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      added_display_indices.push_back(new_displays.size());
8152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      InsertAndUpdateDisplayInfo(*new_info_iter);
8162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new_displays.push_back(
8172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          CreateDisplayFromDisplayInfoById(new_info_iter->id()));
8182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ++new_info_iter;
8192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else if (new_info_iter == new_display_info_list.end()) {
8202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // more displays in current list.
8212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      removed_displays.push_back(*curr_iter);
8222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ++curr_iter;
8232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else if (curr_iter->id() == new_info_iter->id()) {
8242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const gfx::Display& current_display = *curr_iter;
8252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Copy the info because |CreateDisplayFromInfo| updates the instance.
8262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const DisplayInfo current_display_info =
8272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          GetDisplayInfo(current_display.id());
8282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      InsertAndUpdateDisplayInfo(*new_info_iter);
8292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      gfx::Display new_display =
8302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          CreateDisplayFromDisplayInfoById(new_info_iter->id());
8312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const DisplayInfo& new_display_info = GetDisplayInfo(new_display.id());
832c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
833cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      uint32_t metrics = gfx::DisplayObserver::DISPLAY_METRIC_NONE;
834c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
835cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // At that point the new Display objects we have are not entirely updated,
836cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // they are missing the translation related to the Display disposition in
837cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // the layout.
838cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // Using display.bounds() and display.work_area() would fail most of the
839cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // time.
840cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (force_bounds_changed_ || (current_display_info.bounds_in_native() !=
841cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                    new_display_info.bounds_in_native()) ||
8422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          (current_display_info.size_in_pixel() !=
843cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)           new_display.GetSizeInPixel())) {
844cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        metrics |= gfx::DisplayObserver::DISPLAY_METRIC_BOUNDS |
845cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   gfx::DisplayObserver::DISPLAY_METRIC_WORK_AREA;
846cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      }
847cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
848cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (current_display.device_scale_factor() !=
849cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          new_display.device_scale_factor()) {
850cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        metrics |= gfx::DisplayObserver::DISPLAY_METRIC_DEVICE_SCALE_FACTOR;
851cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      }
852cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
853cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (current_display.rotation() != new_display.rotation())
854cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        metrics |= gfx::DisplayObserver::DISPLAY_METRIC_ROTATION;
855cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
856cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (metrics != gfx::DisplayObserver::DISPLAY_METRIC_NONE) {
857cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        display_changes.insert(
858cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            std::pair<size_t, uint32_t>(new_displays.size(), metrics));
8592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
8602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new_display.UpdateWorkAreaFromInsets(current_display.GetWorkAreaInsets());
8622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new_displays.push_back(new_display);
8632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ++curr_iter;
8642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ++new_info_iter;
8652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else if (curr_iter->id() < new_info_iter->id()) {
8662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // more displays in current list between ids, which means it is deleted.
8672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      removed_displays.push_back(*curr_iter);
8682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ++curr_iter;
8692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
8702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // more displays in new list between ids, which means it is added.
8712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      added_display_indices.push_back(new_displays.size());
8722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      InsertAndUpdateDisplayInfo(*new_info_iter);
8732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new_displays.push_back(
8742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          CreateDisplayFromDisplayInfoById(new_info_iter->id()));
8752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ++new_info_iter;
8762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
8772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  scoped_ptr<NonDesktopDisplayUpdater> non_desktop_display_updater(
8801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      new NonDesktopDisplayUpdater(this, delegate_));
88190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
882f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Clear focus if the display has been removed, but don't clear focus if
883f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // the destkop has been moved from one display to another
884f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // (mirror -> docked, docked -> single internal).
885f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  bool clear_focus =
886f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      !removed_displays.empty() &&
887f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      !(removed_displays.size() == 1 && added_display_indices.size() == 1);
8887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (delegate_)
889f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    delegate_->PreDisplayConfigurationChange(clear_focus);
890c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
8911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Do not update |displays_| if there's nothing to be updated. Without this,
8921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // it will not update the display layout, which causes the bug
8931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // http://crbug.com/155948.
8941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (display_changes.empty() && added_display_indices.empty() &&
8951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      removed_displays.empty()) {
8961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // When changing from software mirroring mode to sinlge display mode, it
8971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // is possible there is no need to update |displays_| and we early out
8981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // here. But we still want to run the PostDisplayConfigurationChange()
8991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // cause there are some clients need to act on this, e.g.
9001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // TouchTransformerController needs to adjust the TouchTransformer when
9011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // switching from dual displays to single display.
9021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (delegate_)
9031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      delegate_->PostDisplayConfigurationChange();
9041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
9051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
9061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
907eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  size_t updated_index;
908eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (UpdateSecondaryDisplayBoundsForLayout(&new_displays, &updated_index) &&
909eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      std::find(added_display_indices.begin(),
910eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                added_display_indices.end(),
911cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                updated_index) == added_display_indices.end()) {
912cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    uint32_t metrics = gfx::DisplayObserver::DISPLAY_METRIC_BOUNDS |
913cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                       gfx::DisplayObserver::DISPLAY_METRIC_WORK_AREA;
914cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (display_changes.find(updated_index) != display_changes.end())
915cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      metrics |= display_changes[updated_index];
916cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
917cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    display_changes[updated_index] = metrics;
918eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
919eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
9202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  displays_ = new_displays;
9212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
922c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::AutoReset<bool> resetter(&change_display_upon_host_resize_, false);
923c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
9242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Temporarily add displays to be removed because display object
9252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // being removed are accessed during shutting down the root.
9262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  displays_.insert(displays_.end(), removed_displays.begin(),
9272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   removed_displays.end());
9282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (DisplayList::const_reverse_iterator iter = removed_displays.rbegin();
9302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       iter != removed_displays.rend(); ++iter) {
9315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    screen_ash_->NotifyDisplayRemoved(displays_.back());
9322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    displays_.pop_back();
9332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
9341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Close the non desktop window here to avoid creating two compositor on
9357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // one display.
9361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (!non_desktop_display_updater->enabled())
9371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    non_desktop_display_updater.reset();
9382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (std::vector<size_t>::iterator iter = added_display_indices.begin();
9392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       iter != added_display_indices.end(); ++iter) {
9405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    screen_ash_->NotifyDisplayAdded(displays_[*iter]);
9412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
9421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Create the non destkop window after all displays are added so that
9437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // it can mirror the display newly added. This can happen when switching
9447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // from dock mode to software mirror mode.
9451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  non_desktop_display_updater.reset();
946cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (std::map<size_t, uint32_t>::iterator iter = display_changes.begin();
947cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)       iter != display_changes.end();
948cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)       ++iter) {
949cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    screen_ash_->NotifyMetricsChanged(displays_[iter->first], iter->second);
9502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
9517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (delegate_)
9527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    delegate_->PostDisplayConfigurationChange();
9532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(USE_X11) && defined(OS_CHROMEOS)
955cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!display_changes.empty() && base::SysInfo::IsRunningOnChromeOS())
9562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ui::ClearX11DefaultRootWindow();
9572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
9582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
960ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochconst gfx::Display& DisplayManager::GetDisplayAt(size_t index) const {
961ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DCHECK_LT(index, displays_.size());
962ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return displays_[index];
9632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)const gfx::Display& DisplayManager::GetPrimaryDisplayCandidate() const {
9661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (GetNumDisplays() == 1)
9673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return displays_[0];
9683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DisplayLayout layout = layout_store_->GetRegisteredDisplayLayout(
9693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      GetCurrentDisplayIdPair());
9703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return GetDisplayForId(layout.primary_id);
9712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t DisplayManager::GetNumDisplays() const {
9742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return displays_.size();
9752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool DisplayManager::IsMirrored() const {
9781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return mirrored_display_id_ != gfx::Display::kInvalidDisplayID;
9792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const DisplayInfo& DisplayManager::GetDisplayInfo(int64 display_id) const {
9820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  DCHECK_NE(gfx::Display::kInvalidDisplayID, display_id);
9830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
9842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::map<int64, DisplayInfo>::const_iterator iter =
9852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      display_info_.find(display_id);
986868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  CHECK(iter != display_info_.end()) << display_id;
9872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return iter->second;
9882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string DisplayManager::GetDisplayNameForId(int64 id) {
9912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (id == gfx::Display::kInvalidDisplayID)
9922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return l10n_util::GetStringUTF8(IDS_ASH_STATUS_TRAY_UNKNOWN_DISPLAY_NAME);
9932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::map<int64, DisplayInfo>::const_iterator iter = display_info_.find(id);
9952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (iter != display_info_.end() && !iter->second.name().empty())
9962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return iter->second.name();
9972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return base::StringPrintf("Display %d", static_cast<int>(id));
9992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1001eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint64 DisplayManager::GetDisplayIdForUIScaling() const {
1002eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // UI Scaling is effective only on internal display.
1003eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int64 display_id = gfx::Display::InternalDisplayId();
1004eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(OS_WIN)
1005eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  display_id = first_display_id();
1006eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif
1007eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return display_id;
1008eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
1009eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
101090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void DisplayManager::SetMirrorMode(bool mirrored) {
101190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (num_connected_displays() <= 1)
101290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
101390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
101490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#if defined(OS_CHROMEOS)
10154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (base::SysInfo::IsRunningOnChromeOS()) {
1016c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    ui::MultipleDisplayState new_state =
1017c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        mirrored ? ui::MULTIPLE_DISPLAY_STATE_DUAL_MIRROR :
1018c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                   ui::MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED;
1019c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    Shell::GetInstance()->display_configurator()->SetDisplayMode(new_state);
102090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
102190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
102290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif
10231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // This is fallback path to emulate mirroroing on desktop.
10241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  SetSecondDisplayMode(mirrored ? MIRRORING : EXTENDED);
102590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DisplayInfoList display_info_list;
102690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int count = 0;
102790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for (std::map<int64, DisplayInfo>::const_iterator iter =
102890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)           display_info_.begin();
102990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)       count < 2; ++iter, ++count) {
103090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    display_info_list.push_back(GetDisplayInfo(iter->second.id()));
103190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
103290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  UpdateDisplays(display_info_list);
103390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#if defined(OS_CHROMEOS)
10345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (Shell::GetInstance()->display_configurator_animation()) {
10355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    Shell::GetInstance()->display_configurator_animation()->
103690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        StartFadeInAnimation();
103790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
103890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif
103990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
104090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
104190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void DisplayManager::AddRemoveDisplay() {
104290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(!displays_.empty());
104390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::vector<DisplayInfo> new_display_info_list;
10443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const DisplayInfo& first_display = GetDisplayInfo(displays_[0].id());
10457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  new_display_info_list.push_back(first_display);
104690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Add if there is only one display connected.
104790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (num_connected_displays() == 1) {
104890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Layout the 2nd display below the primary as with the real device.
104968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    gfx::Rect host_bounds = first_display.bounds_in_native();
105090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    new_display_info_list.push_back(DisplayInfo::CreateFromSpec(
105190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        base::StringPrintf(
105290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            "%d+%d-500x400", host_bounds.x(), host_bounds.bottom())));
105390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
105490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  num_connected_displays_ = new_display_info_list.size();
10551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  mirrored_display_id_ = gfx::Display::kInvalidDisplayID;
1056f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  non_desktop_display_ = gfx::Display();
105790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  UpdateDisplays(new_display_info_list);
105890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
105990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
106090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void DisplayManager::ToggleDisplayScaleFactor() {
106190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(!displays_.empty());
106290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::vector<DisplayInfo> new_display_info_list;
106390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for (DisplayList::const_iterator iter = displays_.begin();
106490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)       iter != displays_.end(); ++iter) {
106590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    DisplayInfo display_info = GetDisplayInfo(iter->id());
106690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    display_info.set_device_scale_factor(
106790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        display_info.device_scale_factor() == 1.0f ? 2.0f : 1.0f);
106890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    new_display_info_list.push_back(display_info);
106990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
1070868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddMirrorDisplayInfoIfAny(&new_display_info_list);
107190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  UpdateDisplays(new_display_info_list);
107290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
107390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
10741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#if defined(OS_CHROMEOS)
107590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void DisplayManager::SetSoftwareMirroring(bool enabled) {
10761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  SetSecondDisplayMode(enabled ? MIRRORING : EXTENDED);
10771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1078cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1079cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool DisplayManager::SoftwareMirroringEnabled() const {
1080cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return software_mirroring_enabled();
1081cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
10821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#endif
10831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
10841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void DisplayManager::SetSecondDisplayMode(SecondDisplayMode mode) {
10851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  second_display_mode_ = mode;
10861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  mirrored_display_id_ = gfx::Display::kInvalidDisplayID;
10871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  non_desktop_display_ = gfx::Display();
108890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
108990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
10907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool DisplayManager::UpdateDisplayBounds(int64 display_id,
10917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                         const gfx::Rect& new_bounds) {
10927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (change_display_upon_host_resize_) {
10937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    display_info_[display_id].SetBounds(new_bounds);
10947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // Don't notify observers if the mirrored window has changed.
10951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (software_mirroring_enabled() && mirrored_display_id_ == display_id)
10967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      return false;
1097ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    gfx::Display* display = FindDisplayForId(display_id);
1098ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    display->SetSize(display_info_[display_id].size_in_pixel());
1099cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    screen_ash_->NotifyMetricsChanged(
1100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        *display, gfx::DisplayObserver::DISPLAY_METRIC_BOUNDS);
11017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return true;
11027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
11037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return false;
11047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
11057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
110668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void DisplayManager::CreateMirrorWindowIfAny() {
11071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  NonDesktopDisplayUpdater updater(this, delegate_);
110868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
110968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
11105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void DisplayManager::CreateScreenForShutdown() const {
11115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool native_is_ash =
11125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      gfx::Screen::GetScreenByType(gfx::SCREEN_TYPE_NATIVE) ==
11135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      screen_ash_.get();
11145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  delete screen_for_shutdown;
11155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  screen_for_shutdown = screen_ash_->CloneForShutdown();
11165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_ALTERNATE,
11175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 screen_for_shutdown);
11185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (native_is_ash) {
11195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE,
11205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   screen_for_shutdown);
11215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
11225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
11235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1124ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochgfx::Display* DisplayManager::FindDisplayForId(int64 id) {
1125ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  for (DisplayList::iterator iter = displays_.begin();
1126ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch       iter != displays_.end(); ++iter) {
1127ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    if ((*iter).id() == id)
1128ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      return &(*iter);
1129ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
1130ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DLOG(WARNING) << "Could not find display:" << id;
1131ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return NULL;
1132ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
1133ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1134868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void DisplayManager::AddMirrorDisplayInfoIfAny(
1135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    std::vector<DisplayInfo>* display_info_list) {
11361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (software_mirroring_enabled() && IsMirrored())
11371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    display_info_list->push_back(GetDisplayInfo(mirrored_display_id_));
1138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
11402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DisplayManager::InsertAndUpdateDisplayInfo(const DisplayInfo& new_info) {
11412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::map<int64, DisplayInfo>::iterator info =
11422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      display_info_.find(new_info.id());
11435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (info != display_info_.end()) {
11442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    info->second.Copy(new_info);
11455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
11462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    display_info_[new_info.id()] = new_info;
11472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    display_info_[new_info.id()].set_native(false);
11482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
11492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  display_info_[new_info.id()].UpdateDisplaySize();
1150effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
1151effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  OnDisplayInfoUpdated(display_info_[new_info.id()]);
1152effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
1153effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
1154effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid DisplayManager::OnDisplayInfoUpdated(const DisplayInfo& display_info) {
1155effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#if defined(OS_CHROMEOS)
1156effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  ui::ColorCalibrationProfile color_profile = display_info.color_profile();
1157effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (color_profile != ui::COLOR_PROFILE_STANDARD) {
1158c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    Shell::GetInstance()->display_configurator()->SetColorCalibrationProfile(
1159effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        display_info.id(), color_profile);
1160effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
1161effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#endif
11622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
11632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)gfx::Display DisplayManager::CreateDisplayFromDisplayInfoById(int64 id) {
11652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(display_info_.find(id) != display_info_.end());
11662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const DisplayInfo& display_info = display_info_[id];
11672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Display new_display(display_info.id());
116968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  gfx::Rect bounds_in_native(display_info.size_in_pixel());
1170a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  float device_scale_factor = display_info.GetEffectiveDeviceScaleFactor();
11712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Simply set the origin to (0,0).  The primary display's origin is
11732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // always (0,0) and the secondary display's bounds will be updated
1174eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // in |UpdateSecondaryDisplayBoundsForLayout| called in |UpdateDisplay|.
11752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  new_display.SetScaleAndBounds(
1176f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      device_scale_factor, gfx::Rect(bounds_in_native.size()));
11772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  new_display.set_rotation(display_info.rotation());
11781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  new_display.set_touch_support(display_info.touch_support());
11792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return new_display;
11802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
11812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool DisplayManager::UpdateSecondaryDisplayBoundsForLayout(
1183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    DisplayList* displays,
1184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    size_t* updated_index) const {
1185eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (displays->size() != 2U)
1186eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return false;
1187eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1188eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int64 id_at_zero = displays->at(0).id();
1189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DisplayIdPair pair =
1190eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      (id_at_zero == first_display_id_ ||
1191eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch       id_at_zero == gfx::Display::InternalDisplayId()) ?
1192eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      std::make_pair(id_at_zero, displays->at(1).id()) :
11935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      std::make_pair(displays->at(1).id(), id_at_zero);
1194eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DisplayLayout layout =
11957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      layout_store_->ComputeDisplayLayoutForDisplayIdPair(pair);
1196eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1197eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Ignore if a user has a old format (should be extremely rare)
1198eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // and this will be replaced with DCHECK.
1199eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (layout.primary_id != gfx::Display::kInvalidDisplayID) {
1200eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    size_t primary_index, secondary_index;
1201eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (displays->at(0).id() == layout.primary_id) {
1202eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      primary_index = 0;
1203eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      secondary_index = 1;
1204eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    } else {
1205eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      primary_index = 1;
1206eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      secondary_index = 0;
1207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
12083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    // This function may be called before the secondary display is
12093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    // registered. The bounds is empty in that case and will
12103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    // return true.
1211eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    gfx::Rect bounds =
1212eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        GetDisplayForId(displays->at(secondary_index).id()).bounds();
1213eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    UpdateDisplayBoundsForLayout(
1214eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        layout, displays->at(primary_index), &displays->at(secondary_index));
1215eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    *updated_index = secondary_index;
1216eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return bounds != displays->at(secondary_index).bounds();
1217eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
1218eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return false;
1219eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
1220eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1221ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// static
1222ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid DisplayManager::UpdateDisplayBoundsForLayout(
1223ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const DisplayLayout& layout,
1224ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const gfx::Display& primary_display,
1225ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    gfx::Display* secondary_display) {
1226ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DCHECK_EQ("0,0", primary_display.bounds().origin().ToString());
1227ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1228ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  const gfx::Rect& primary_bounds = primary_display.bounds();
1229ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  const gfx::Rect& secondary_bounds = secondary_display->bounds();
1230ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  gfx::Point new_secondary_origin = primary_bounds.origin();
1231ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1232ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DisplayLayout::Position position = layout.position;
1233ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1234ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Ignore the offset in case the secondary display doesn't share edges with
1235ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // the primary display.
1236ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  int offset = layout.offset;
1237ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (position == DisplayLayout::TOP || position == DisplayLayout::BOTTOM) {
1238ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    offset = std::min(
1239ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        offset, primary_bounds.width() - kMinimumOverlapForInvalidOffset);
1240ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    offset = std::max(
1241ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        offset, -secondary_bounds.width() + kMinimumOverlapForInvalidOffset);
1242ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  } else {
1243ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    offset = std::min(
1244ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        offset, primary_bounds.height() - kMinimumOverlapForInvalidOffset);
1245ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    offset = std::max(
1246ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        offset, -secondary_bounds.height() + kMinimumOverlapForInvalidOffset);
1247ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
1248ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  switch (position) {
1249ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    case DisplayLayout::TOP:
1250ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      new_secondary_origin.Offset(offset, -secondary_bounds.height());
1251ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      break;
1252ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    case DisplayLayout::RIGHT:
1253ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      new_secondary_origin.Offset(primary_bounds.width(), offset);
1254ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      break;
1255ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    case DisplayLayout::BOTTOM:
1256ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      new_secondary_origin.Offset(offset, primary_bounds.height());
1257ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      break;
1258ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    case DisplayLayout::LEFT:
1259ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      new_secondary_origin.Offset(-secondary_bounds.width(), offset);
1260ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      break;
1261ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
1262ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  gfx::Insets insets = secondary_display->GetWorkAreaInsets();
1263ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  secondary_display->set_bounds(
1264ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      gfx::Rect(new_secondary_origin, secondary_bounds.size()));
1265ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  secondary_display->UpdateWorkAreaFromInsets(insets);
1266ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
1267ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
12682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace ash
1269