Home | History | Annotate | Download | only in display
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "ash/display/display_manager.h"
      6 
      7 #include <cmath>
      8 #include <set>
      9 #include <string>
     10 #include <vector>
     11 
     12 #include "ash/ash_switches.h"
     13 #include "ash/display/display_layout_store.h"
     14 #include "ash/screen_ash.h"
     15 #include "ash/shell.h"
     16 #include "base/auto_reset.h"
     17 #include "base/command_line.h"
     18 #include "base/logging.h"
     19 #include "base/strings/string_number_conversions.h"
     20 #include "base/strings/string_split.h"
     21 #include "base/strings/stringprintf.h"
     22 #include "base/strings/utf_string_conversions.h"
     23 #include "grit/ash_strings.h"
     24 #include "ui/base/l10n/l10n_util.h"
     25 #include "ui/gfx/display.h"
     26 #include "ui/gfx/rect.h"
     27 #include "ui/gfx/screen.h"
     28 #include "ui/gfx/size_conversions.h"
     29 
     30 #if defined(USE_X11)
     31 #include "ui/base/x/x11_util.h"
     32 #endif
     33 
     34 #if defined(OS_CHROMEOS)
     35 #include "ash/display/output_configurator_animation.h"
     36 #include "base/chromeos/chromeos_version.h"
     37 #include "chromeos/display/output_configurator.h"
     38 #endif
     39 
     40 #if defined(OS_WIN)
     41 #include "base/win/windows_version.h"
     42 #endif
     43 
     44 namespace ash {
     45 namespace internal {
     46 typedef std::vector<gfx::Display> DisplayList;
     47 typedef std::vector<DisplayInfo> DisplayInfoList;
     48 
     49 namespace {
     50 
     51 // The number of pixels to overlap between the primary and secondary displays,
     52 // in case that the offset value is too large.
     53 const int kMinimumOverlapForInvalidOffset = 100;
     54 
     55 // List of value UI Scale values. Scales for 2x are equivalent to 640,
     56 // 800, 1024, 1280, 1440, 1600 and 1920 pixel width respectively on
     57 // 2560 pixel width 2x density display. Please see crbug.com/233375
     58 // for the full list of resolutions.
     59 const float kUIScalesFor2x[] = {0.5f, 0.625f, 0.8f, 1.0f, 1.125f, 1.25f, 1.5f};
     60 const float kUIScalesFor1280[] = {0.5f, 0.625f, 0.8f, 1.0f, 1.125f };
     61 const float kUIScalesFor1366[] = {0.5f, 0.6f, 0.75f, 1.0f, 1.125f };
     62 
     63 struct DisplaySortFunctor {
     64   bool operator()(const gfx::Display& a, const gfx::Display& b) {
     65     return a.id() < b.id();
     66   }
     67 };
     68 
     69 struct DisplayInfoSortFunctor {
     70   bool operator()(const DisplayInfo& a, const DisplayInfo& b) {
     71     return a.id() < b.id();
     72   }
     73 };
     74 
     75 struct ScaleComparator {
     76   ScaleComparator(float s) : scale(s) {}
     77 
     78   bool operator()(float s) const {
     79     const float kEpsilon = 0.0001f;
     80     return std::abs(scale - s) < kEpsilon;
     81   }
     82   float scale;
     83 };
     84 
     85 gfx::Display& GetInvalidDisplay() {
     86   static gfx::Display* invalid_display = new gfx::Display();
     87   return *invalid_display;
     88 }
     89 
     90 // Scoped objects used to either create or close the mirror window
     91 // at specific timing.
     92 class MirrorWindowCreator {
     93  public:
     94   MirrorWindowCreator(DisplayManager::Delegate* delegate,
     95                       const DisplayInfo& display_info)
     96       : delegate_(delegate),
     97         display_info_(display_info) {
     98   }
     99 
    100   virtual ~MirrorWindowCreator() {
    101     if (delegate_)
    102       delegate_->CreateOrUpdateMirrorWindow(display_info_);
    103   }
    104 
    105  private:
    106   DisplayManager::Delegate* delegate_;
    107   const DisplayInfo display_info_;
    108   DISALLOW_COPY_AND_ASSIGN(MirrorWindowCreator);
    109 };
    110 
    111 class MirrorWindowCloser {
    112  public:
    113   explicit MirrorWindowCloser(DisplayManager::Delegate* delegate)
    114       : delegate_(delegate)  {}
    115 
    116   virtual ~MirrorWindowCloser() {
    117     if (delegate_)
    118       delegate_->CloseMirrorWindow();
    119   }
    120 
    121  private:
    122   DisplayManager::Delegate* delegate_;
    123 
    124   DISALLOW_COPY_AND_ASSIGN(MirrorWindowCloser);
    125 };
    126 
    127 }  // namespace
    128 
    129 using std::string;
    130 using std::vector;
    131 
    132 DisplayManager::DisplayManager()
    133     : delegate_(NULL),
    134       layout_store_(new DisplayLayoutStore),
    135       first_display_id_(gfx::Display::kInvalidDisplayID),
    136       num_connected_displays_(0),
    137       force_bounds_changed_(false),
    138       change_display_upon_host_resize_(false),
    139       software_mirroring_enabled_(false) {
    140 #if defined(OS_CHROMEOS)
    141   change_display_upon_host_resize_ = !base::chromeos::IsRunningOnChromeOS();
    142 #endif
    143 }
    144 
    145 DisplayManager::~DisplayManager() {
    146 }
    147 
    148 // static
    149 std::vector<float> DisplayManager::GetScalesForDisplay(
    150     const DisplayInfo& info) {
    151   std::vector<float> ret;
    152   if (info.device_scale_factor() == 2.0f) {
    153     ret.assign(kUIScalesFor2x, kUIScalesFor2x + arraysize(kUIScalesFor2x));
    154     return ret;
    155   }
    156   switch (info.bounds_in_pixel().width()) {
    157     case 1280:
    158       ret.assign(kUIScalesFor1280,
    159                  kUIScalesFor1280 + arraysize(kUIScalesFor1280));
    160       break;
    161     case 1366:
    162       ret.assign(kUIScalesFor1366,
    163                  kUIScalesFor1366 + arraysize(kUIScalesFor1366));
    164       break;
    165     default:
    166       ret.assign(kUIScalesFor1280,
    167                  kUIScalesFor1280 + arraysize(kUIScalesFor1280));
    168 #if defined(OS_CHROMEOS)
    169       if (base::chromeos::IsRunningOnChromeOS())
    170         NOTREACHED() << "Unknown resolution:" << info.ToString();
    171 #endif
    172   }
    173   return ret;
    174 }
    175 
    176 // static
    177 float DisplayManager::GetNextUIScale(const DisplayInfo& info, bool up) {
    178   float scale = info.ui_scale();
    179   std::vector<float> scales = GetScalesForDisplay(info);
    180   for (size_t i = 0; i < scales.size(); ++i) {
    181     if (ScaleComparator(scales[i])(scale)) {
    182       if (up && i != scales.size() - 1)
    183         return scales[i + 1];
    184       if (!up && i != 0)
    185         return scales[i - 1];
    186       return scales[i];
    187     }
    188   }
    189   // Fallback to 1.0f if the |scale| wasn't in the list.
    190   return 1.0f;
    191 }
    192 
    193 void DisplayManager::InitFromCommandLine() {
    194   DisplayInfoList info_list;
    195 
    196   const string size_str = CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
    197       switches::kAshHostWindowBounds);
    198   vector<string> parts;
    199   base::SplitString(size_str, ',', &parts);
    200   for (vector<string>::const_iterator iter = parts.begin();
    201        iter != parts.end(); ++iter) {
    202     info_list.push_back(DisplayInfo::CreateFromSpec(*iter));
    203   }
    204   CommandLine* command_line = CommandLine::ForCurrentProcess();
    205   if (command_line->HasSwitch(switches::kAshUseFirstDisplayAsInternal))
    206     gfx::Display::SetInternalDisplayId(info_list[0].id());
    207   OnNativeDisplaysChanged(info_list);
    208 }
    209 
    210 // static
    211 void DisplayManager::UpdateDisplayBoundsForLayoutById(
    212     const DisplayLayout& layout,
    213     const gfx::Display& primary_display,
    214     int64 secondary_display_id) {
    215   DCHECK_NE(gfx::Display::kInvalidDisplayID, secondary_display_id);
    216   UpdateDisplayBoundsForLayout(
    217       layout, primary_display,
    218       Shell::GetInstance()->display_manager()->
    219       FindDisplayForId(secondary_display_id));
    220 }
    221 
    222 bool DisplayManager::IsActiveDisplay(const gfx::Display& display) const {
    223   for (DisplayList::const_iterator iter = displays_.begin();
    224        iter != displays_.end(); ++iter) {
    225     if ((*iter).id() == display.id())
    226       return true;
    227   }
    228   return false;
    229 }
    230 
    231 bool DisplayManager::HasInternalDisplay() const {
    232   return gfx::Display::InternalDisplayId() != gfx::Display::kInvalidDisplayID;
    233 }
    234 
    235 bool DisplayManager::IsInternalDisplayId(int64 id) const {
    236   return gfx::Display::InternalDisplayId() == id;
    237 }
    238 
    239 const gfx::Display& DisplayManager::GetDisplayForId(int64 id) const {
    240   gfx::Display* display =
    241       const_cast<DisplayManager*>(this)->FindDisplayForId(id);
    242   return display ? *display : GetInvalidDisplay();
    243 }
    244 
    245 const gfx::Display& DisplayManager::FindDisplayContainingPoint(
    246     const gfx::Point& point_in_screen) const {
    247   for (DisplayList::const_iterator iter = displays_.begin();
    248        iter != displays_.end(); ++iter) {
    249     const gfx::Display& display = *iter;
    250     if (display.bounds().Contains(point_in_screen))
    251       return display;
    252   }
    253   return GetInvalidDisplay();
    254 }
    255 
    256 bool DisplayManager::UpdateWorkAreaOfDisplay(int64 display_id,
    257                                              const gfx::Insets& insets) {
    258   gfx::Display* display = FindDisplayForId(display_id);
    259   DCHECK(display);
    260   gfx::Rect old_work_area = display->work_area();
    261   display->UpdateWorkAreaFromInsets(insets);
    262   return old_work_area != display->work_area();
    263 }
    264 
    265 void DisplayManager::SetOverscanInsets(int64 display_id,
    266                                        const gfx::Insets& insets_in_dip) {
    267   display_info_[display_id].SetOverscanInsets(insets_in_dip);
    268   DisplayInfoList display_info_list;
    269   for (DisplayList::const_iterator iter = displays_.begin();
    270        iter != displays_.end(); ++iter) {
    271     display_info_list.push_back(GetDisplayInfo(iter->id()));
    272   }
    273   AddMirrorDisplayInfoIfAny(&display_info_list);
    274   UpdateDisplays(display_info_list);
    275 }
    276 
    277 void DisplayManager::SetDisplayRotation(int64 display_id,
    278                                         gfx::Display::Rotation rotation) {
    279   if (!IsDisplayRotationEnabled())
    280     return;
    281   DisplayInfoList display_info_list;
    282   for (DisplayList::const_iterator iter = displays_.begin();
    283        iter != displays_.end(); ++iter) {
    284     DisplayInfo info = GetDisplayInfo(iter->id());
    285     if (info.id() == display_id) {
    286       if (info.rotation() == rotation)
    287         return;
    288       info.set_rotation(rotation);
    289     }
    290     display_info_list.push_back(info);
    291   }
    292   AddMirrorDisplayInfoIfAny(&display_info_list);
    293   UpdateDisplays(display_info_list);
    294 }
    295 
    296 void DisplayManager::SetDisplayUIScale(int64 display_id,
    297                                        float ui_scale) {
    298   if (!IsDisplayUIScalingEnabled() ||
    299       gfx::Display::InternalDisplayId() != display_id) {
    300     return;
    301   }
    302 
    303   DisplayInfoList display_info_list;
    304   for (DisplayList::const_iterator iter = displays_.begin();
    305        iter != displays_.end(); ++iter) {
    306     DisplayInfo info = GetDisplayInfo(iter->id());
    307     if (info.id() == display_id) {
    308       if (info.ui_scale() == ui_scale)
    309         return;
    310       std::vector<float> scales = GetScalesForDisplay(info);
    311       ScaleComparator comparator(ui_scale);
    312       if (std::find_if(scales.begin(), scales.end(), comparator) ==
    313           scales.end()) {
    314         return;
    315       }
    316       info.set_ui_scale(ui_scale);
    317     }
    318     display_info_list.push_back(info);
    319   }
    320   AddMirrorDisplayInfoIfAny(&display_info_list);
    321   UpdateDisplays(display_info_list);
    322 }
    323 
    324 void DisplayManager::SetDisplayResolution(int64 display_id,
    325                                           const gfx::Size& resolution) {
    326   DCHECK_NE(gfx::Display::InternalDisplayId(), display_id);
    327   if (gfx::Display::InternalDisplayId() == display_id)
    328     return;
    329   resolutions_[display_id] = resolution;
    330 #if defined(OS_CHROMEOS) && defined(USE_X11)
    331   if (base::chromeos::IsRunningOnChromeOS())
    332     Shell::GetInstance()->output_configurator()->ScheduleConfigureOutputs();
    333 #endif
    334 }
    335 
    336 void DisplayManager::RegisterDisplayProperty(
    337     int64 display_id,
    338     gfx::Display::Rotation rotation,
    339     float ui_scale,
    340     const gfx::Insets* overscan_insets,
    341     const gfx::Size& resolution_in_pixels) {
    342   if (display_info_.find(display_id) == display_info_.end()) {
    343     display_info_[display_id] =
    344         DisplayInfo(display_id, std::string(""), false);
    345   }
    346 
    347   display_info_[display_id].set_rotation(rotation);
    348   // Just in case the preference file was corrupted.
    349   if (0.5f <= ui_scale && ui_scale <= 2.0f)
    350     display_info_[display_id].set_ui_scale(ui_scale);
    351   if (overscan_insets)
    352     display_info_[display_id].SetOverscanInsets(*overscan_insets);
    353   if (!resolution_in_pixels.IsEmpty())
    354     resolutions_[display_id] = resolution_in_pixels;
    355 }
    356 
    357 bool DisplayManager::GetSelectedResolutionForDisplayId(
    358     int64 id,
    359     gfx::Size* resolution_out) const {
    360   std::map<int64, gfx::Size>::const_iterator iter =
    361       resolutions_.find(id);
    362   if (iter == resolutions_.end())
    363     return false;
    364   *resolution_out = iter->second;
    365   return true;
    366 }
    367 
    368 bool DisplayManager::IsDisplayRotationEnabled() const {
    369   static bool enabled = !CommandLine::ForCurrentProcess()->
    370       HasSwitch(switches::kAshDisableDisplayRotation);
    371   return enabled;
    372 }
    373 
    374 bool DisplayManager::IsDisplayUIScalingEnabled() const {
    375   static bool enabled = !CommandLine::ForCurrentProcess()->
    376       HasSwitch(switches::kAshDisableUIScaling);
    377   if (!enabled)
    378     return false;
    379   return GetDisplayIdForUIScaling() != gfx::Display::kInvalidDisplayID;
    380 }
    381 
    382 gfx::Insets DisplayManager::GetOverscanInsets(int64 display_id) const {
    383   std::map<int64, DisplayInfo>::const_iterator it =
    384       display_info_.find(display_id);
    385   return (it != display_info_.end()) ?
    386       it->second.overscan_insets_in_dip() : gfx::Insets();
    387 }
    388 
    389 void DisplayManager::OnNativeDisplaysChanged(
    390     const std::vector<DisplayInfo>& updated_displays) {
    391   if (updated_displays.empty()) {
    392     // If the device is booted without display, or chrome is started
    393     // without --ash-host-window-bounds on linux desktop, use the
    394     // default display.
    395     if (displays_.empty()) {
    396       std::vector<DisplayInfo> init_displays;
    397       init_displays.push_back(DisplayInfo::CreateFromSpec(std::string()));
    398       OnNativeDisplaysChanged(init_displays);
    399     } else {
    400       // Otherwise don't update the displays when all displays are disconnected.
    401       // This happens when:
    402       // - the device is idle and powerd requested to turn off all displays.
    403       // - the device is suspended. (kernel turns off all displays)
    404       // - the internal display's brightness is set to 0 and no external
    405       //   display is connected.
    406       // - the internal display's brightness is 0 and external display is
    407       //   disconnected.
    408       // The display will be updated when one of displays is turned on, and the
    409       // display list will be updated correctly.
    410     }
    411     return;
    412   }
    413   first_display_id_ = updated_displays[0].id();
    414   std::set<gfx::Point> origins;
    415 
    416   if (updated_displays.size() == 1) {
    417     VLOG(1) << "OnNativeDisplaysChanged(1):" << updated_displays[0].ToString();
    418   } else {
    419     VLOG(1) << "OnNativeDisplaysChanged(" << updated_displays.size()
    420             << ") [0]=" << updated_displays[0].ToString()
    421             << ", [1]=" << updated_displays[1].ToString();
    422   }
    423 
    424   bool internal_display_connected = false;
    425   num_connected_displays_ = updated_displays.size();
    426   mirrored_display_ = gfx::Display();
    427   DisplayInfoList new_display_info_list;
    428   for (DisplayInfoList::const_iterator iter = updated_displays.begin();
    429        iter != updated_displays.end();
    430        ++iter) {
    431     if (!internal_display_connected)
    432       internal_display_connected = IsInternalDisplayId(iter->id());
    433     // Mirrored monitors have the same origins.
    434     gfx::Point origin = iter->bounds_in_pixel().origin();
    435     if (origins.find(origin) != origins.end()) {
    436       InsertAndUpdateDisplayInfo(*iter);
    437       mirrored_display_ = CreateDisplayFromDisplayInfoById(iter->id());
    438     } else {
    439       origins.insert(origin);
    440       new_display_info_list.push_back(*iter);
    441     }
    442   }
    443   if (HasInternalDisplay() &&
    444       !internal_display_connected &&
    445       display_info_.find(gfx::Display::InternalDisplayId()) ==
    446       display_info_.end()) {
    447     DisplayInfo internal_display_info(
    448         gfx::Display::InternalDisplayId(),
    449         l10n_util::GetStringUTF8(IDS_ASH_INTERNAL_DISPLAY_NAME),
    450         false  /*Internal display must not have overscan */);
    451     internal_display_info.SetBounds(gfx::Rect(0, 0, 800, 600));
    452     display_info_[gfx::Display::InternalDisplayId()] = internal_display_info;
    453   }
    454   UpdateDisplays(new_display_info_list);
    455 }
    456 
    457 void DisplayManager::UpdateDisplays() {
    458   DisplayInfoList display_info_list;
    459   for (DisplayList::const_iterator iter = displays_.begin();
    460        iter != displays_.end(); ++iter) {
    461     display_info_list.push_back(GetDisplayInfo(iter->id()));
    462   }
    463   AddMirrorDisplayInfoIfAny(&display_info_list);
    464   UpdateDisplays(display_info_list);
    465 }
    466 
    467 void DisplayManager::UpdateDisplays(
    468     const std::vector<DisplayInfo>& updated_display_info_list) {
    469 #if defined(OS_WIN)
    470   if (base::win::GetVersion() >= base::win::VERSION_WIN8) {
    471     DCHECK_EQ(1u, updated_display_info_list.size()) <<
    472         "Multiple display test does not work on Win8 bots. Please "
    473         "skip (don't disable) the test using SupportsMultipleDisplays()";
    474   }
    475 #endif
    476 
    477   DisplayInfoList new_display_info_list = updated_display_info_list;
    478   std::sort(displays_.begin(), displays_.end(), DisplaySortFunctor());
    479   std::sort(new_display_info_list.begin(),
    480             new_display_info_list.end(),
    481             DisplayInfoSortFunctor());
    482   DisplayList removed_displays;
    483   std::vector<size_t> changed_display_indices;
    484   std::vector<size_t> added_display_indices;
    485 
    486   DisplayList::iterator curr_iter = displays_.begin();
    487   DisplayInfoList::const_iterator new_info_iter = new_display_info_list.begin();
    488 
    489   DisplayList new_displays;
    490 
    491   scoped_ptr<MirrorWindowCreator> mirror_window_creater;
    492 
    493   // Use the internal display or 1st as the mirror source, then scale
    494   // the root window so that it matches the external display's
    495   // resolution. This is necessary in order for scaling to work while
    496   // mirrored.
    497   int64 mirrored_display_id = gfx::Display::kInvalidDisplayID;
    498   if (software_mirroring_enabled_ && new_display_info_list.size() == 2)
    499     mirrored_display_id = new_display_info_list[1].id();
    500 
    501   while (curr_iter != displays_.end() ||
    502          new_info_iter != new_display_info_list.end()) {
    503     if (new_info_iter != new_display_info_list.end() &&
    504         mirrored_display_id == new_info_iter->id()) {
    505       DisplayInfo info = *new_info_iter;
    506       info.SetOverscanInsets(gfx::Insets());
    507       InsertAndUpdateDisplayInfo(info);
    508 
    509       mirrored_display_ = CreateDisplayFromDisplayInfoById(new_info_iter->id());
    510       mirror_window_creater.reset(new MirrorWindowCreator(
    511           delegate_, display_info_[new_info_iter->id()]));
    512       ++new_info_iter;
    513       // Remove existing external dispaly if it is going to be mirrored.
    514       if (curr_iter != displays_.end() &&
    515           curr_iter->id() == mirrored_display_id) {
    516         removed_displays.push_back(*curr_iter);
    517         ++curr_iter;
    518       }
    519       continue;
    520     }
    521 
    522     if (curr_iter == displays_.end()) {
    523       // more displays in new list.
    524       added_display_indices.push_back(new_displays.size());
    525       InsertAndUpdateDisplayInfo(*new_info_iter);
    526       new_displays.push_back(
    527           CreateDisplayFromDisplayInfoById(new_info_iter->id()));
    528       ++new_info_iter;
    529     } else if (new_info_iter == new_display_info_list.end()) {
    530       // more displays in current list.
    531       removed_displays.push_back(*curr_iter);
    532       ++curr_iter;
    533     } else if (curr_iter->id() == new_info_iter->id()) {
    534       const gfx::Display& current_display = *curr_iter;
    535       // Copy the info because |CreateDisplayFromInfo| updates the instance.
    536       const DisplayInfo current_display_info =
    537           GetDisplayInfo(current_display.id());
    538       InsertAndUpdateDisplayInfo(*new_info_iter);
    539       gfx::Display new_display =
    540           CreateDisplayFromDisplayInfoById(new_info_iter->id());
    541       const DisplayInfo& new_display_info = GetDisplayInfo(new_display.id());
    542 
    543       bool host_window_bounds_changed =
    544           current_display_info.bounds_in_pixel() !=
    545           new_display_info.bounds_in_pixel();
    546 
    547       if (force_bounds_changed_ ||
    548           host_window_bounds_changed ||
    549           (current_display.device_scale_factor() !=
    550            new_display.device_scale_factor()) ||
    551           (current_display_info.size_in_pixel() !=
    552            new_display.GetSizeInPixel()) ||
    553           (current_display.rotation() != new_display.rotation())) {
    554 
    555         changed_display_indices.push_back(new_displays.size());
    556       }
    557 
    558       new_display.UpdateWorkAreaFromInsets(current_display.GetWorkAreaInsets());
    559       new_displays.push_back(new_display);
    560       ++curr_iter;
    561       ++new_info_iter;
    562     } else if (curr_iter->id() < new_info_iter->id()) {
    563       // more displays in current list between ids, which means it is deleted.
    564       removed_displays.push_back(*curr_iter);
    565       ++curr_iter;
    566     } else {
    567       // more displays in new list between ids, which means it is added.
    568       added_display_indices.push_back(new_displays.size());
    569       InsertAndUpdateDisplayInfo(*new_info_iter);
    570       new_displays.push_back(
    571           CreateDisplayFromDisplayInfoById(new_info_iter->id()));
    572       ++new_info_iter;
    573     }
    574   }
    575 
    576   scoped_ptr<MirrorWindowCloser> mirror_window_closer;
    577   // Try to close mirror window unless mirror window is necessary.
    578   if (!mirror_window_creater.get())
    579     mirror_window_closer.reset(new MirrorWindowCloser(delegate_));
    580 
    581   // Do not update |displays_| if there's nothing to be updated. Without this,
    582   // it will not update the display layout, which causes the bug
    583   // http://crbug.com/155948.
    584   if (changed_display_indices.empty() && added_display_indices.empty() &&
    585       removed_displays.empty()) {
    586     return;
    587   }
    588   if (delegate_)
    589     delegate_->PreDisplayConfigurationChange();
    590 
    591   size_t updated_index;
    592   if (UpdateSecondaryDisplayBoundsForLayout(&new_displays, &updated_index) &&
    593       std::find(added_display_indices.begin(),
    594                 added_display_indices.end(),
    595                 updated_index) == added_display_indices.end() &&
    596       std::find(changed_display_indices.begin(),
    597                 changed_display_indices.end(),
    598                 updated_index) == changed_display_indices.end()) {
    599     changed_display_indices.push_back(updated_index);
    600   }
    601 
    602   displays_ = new_displays;
    603 
    604   base::AutoReset<bool> resetter(&change_display_upon_host_resize_, false);
    605 
    606   // Temporarily add displays to be removed because display object
    607   // being removed are accessed during shutting down the root.
    608   displays_.insert(displays_.end(), removed_displays.begin(),
    609                    removed_displays.end());
    610 
    611   for (DisplayList::const_reverse_iterator iter = removed_displays.rbegin();
    612        iter != removed_displays.rend(); ++iter) {
    613     Shell::GetInstance()->screen()->NotifyDisplayRemoved(displays_.back());
    614     displays_.pop_back();
    615   }
    616   // Close the mirror window here to avoid creating two compositor on
    617   // one display.
    618   mirror_window_closer.reset();
    619   for (std::vector<size_t>::iterator iter = added_display_indices.begin();
    620        iter != added_display_indices.end(); ++iter) {
    621     Shell::GetInstance()->screen()->NotifyDisplayAdded(displays_[*iter]);
    622   }
    623   // Create the mirror window after all displays are added so that
    624   // it can mirror the display newly added. This can happen when switching
    625   // from dock mode to software mirror mode.
    626   mirror_window_creater.reset();
    627   for (std::vector<size_t>::iterator iter = changed_display_indices.begin();
    628        iter != changed_display_indices.end(); ++iter) {
    629     Shell::GetInstance()->screen()->NotifyBoundsChanged(displays_[*iter]);
    630   }
    631   if (delegate_)
    632     delegate_->PostDisplayConfigurationChange();
    633 
    634 #if defined(USE_X11) && defined(OS_CHROMEOS)
    635   if (!changed_display_indices.empty() && base::chromeos::IsRunningOnChromeOS())
    636     ui::ClearX11DefaultRootWindow();
    637 #endif
    638 }
    639 
    640 const gfx::Display& DisplayManager::GetDisplayAt(size_t index) const {
    641   DCHECK_LT(index, displays_.size());
    642   return displays_[index];
    643 }
    644 
    645 const gfx::Display* DisplayManager::GetPrimaryDisplayCandidate() const {
    646   const gfx::Display* primary_candidate = &displays_[0];
    647 #if defined(OS_CHROMEOS)
    648   if (base::chromeos::IsRunningOnChromeOS()) {
    649     // On ChromeOS device, root windows are stacked vertically, and
    650     // default primary is the one on top.
    651     int count = GetNumDisplays();
    652     int y = GetDisplayInfo(primary_candidate->id()).bounds_in_pixel().y();
    653     for (int i = 1; i < count; ++i) {
    654       const gfx::Display* display = &displays_[i];
    655       const DisplayInfo& display_info = GetDisplayInfo(display->id());
    656       if (display->IsInternal()) {
    657         primary_candidate = display;
    658         break;
    659       } else if (display_info.bounds_in_pixel().y() < y) {
    660         primary_candidate = display;
    661         y = display_info.bounds_in_pixel().y();
    662       }
    663     }
    664   }
    665 #endif
    666   return primary_candidate;
    667 }
    668 
    669 size_t DisplayManager::GetNumDisplays() const {
    670   return displays_.size();
    671 }
    672 
    673 bool DisplayManager::IsMirrored() const {
    674   return mirrored_display_.id() != gfx::Display::kInvalidDisplayID;
    675 }
    676 
    677 const DisplayInfo& DisplayManager::GetDisplayInfo(int64 display_id) const {
    678   std::map<int64, DisplayInfo>::const_iterator iter =
    679       display_info_.find(display_id);
    680   CHECK(iter != display_info_.end()) << display_id;
    681   return iter->second;
    682 }
    683 
    684 std::string DisplayManager::GetDisplayNameForId(int64 id) {
    685   if (id == gfx::Display::kInvalidDisplayID)
    686     return l10n_util::GetStringUTF8(IDS_ASH_STATUS_TRAY_UNKNOWN_DISPLAY_NAME);
    687 
    688   std::map<int64, DisplayInfo>::const_iterator iter = display_info_.find(id);
    689   if (iter != display_info_.end() && !iter->second.name().empty())
    690     return iter->second.name();
    691 
    692   return base::StringPrintf("Display %d", static_cast<int>(id));
    693 }
    694 
    695 int64 DisplayManager::GetDisplayIdForUIScaling() const {
    696   // UI Scaling is effective only on internal display.
    697   int64 display_id = gfx::Display::InternalDisplayId();
    698 #if defined(OS_WIN)
    699   display_id = first_display_id();
    700 #endif
    701   return display_id;
    702 }
    703 
    704 void DisplayManager::SetMirrorMode(bool mirrored) {
    705   if (num_connected_displays() <= 1)
    706     return;
    707 
    708 #if defined(OS_CHROMEOS)
    709   if (base::chromeos::IsRunningOnChromeOS()) {
    710     chromeos::OutputState new_state = mirrored ?
    711         chromeos::STATE_DUAL_MIRROR : chromeos::STATE_DUAL_EXTENDED;
    712     Shell::GetInstance()->output_configurator()->SetDisplayMode(new_state);
    713     return;
    714   }
    715 #endif
    716   SetSoftwareMirroring(mirrored);
    717   DisplayInfoList display_info_list;
    718   int count = 0;
    719   for (std::map<int64, DisplayInfo>::const_iterator iter =
    720            display_info_.begin();
    721        count < 2; ++iter, ++count) {
    722     display_info_list.push_back(GetDisplayInfo(iter->second.id()));
    723   }
    724   UpdateDisplays(display_info_list);
    725 #if defined(OS_CHROMEOS)
    726   if (Shell::GetInstance()->output_configurator_animation()) {
    727     Shell::GetInstance()->output_configurator_animation()->
    728         StartFadeInAnimation();
    729   }
    730 #endif
    731 }
    732 
    733 void DisplayManager::AddRemoveDisplay() {
    734   DCHECK(!displays_.empty());
    735   std::vector<DisplayInfo> new_display_info_list;
    736   DisplayInfo first_display = GetDisplayInfo(displays_[0].id());
    737   new_display_info_list.push_back(first_display);
    738   // Add if there is only one display connected.
    739   if (num_connected_displays() == 1) {
    740     // Layout the 2nd display below the primary as with the real device.
    741     gfx::Rect host_bounds = first_display.bounds_in_pixel();
    742     new_display_info_list.push_back(DisplayInfo::CreateFromSpec(
    743         base::StringPrintf(
    744             "%d+%d-500x400", host_bounds.x(), host_bounds.bottom())));
    745   }
    746   num_connected_displays_ = new_display_info_list.size();
    747   mirrored_display_ = gfx::Display();
    748   UpdateDisplays(new_display_info_list);
    749 }
    750 
    751 void DisplayManager::ToggleDisplayScaleFactor() {
    752   DCHECK(!displays_.empty());
    753   std::vector<DisplayInfo> new_display_info_list;
    754   for (DisplayList::const_iterator iter = displays_.begin();
    755        iter != displays_.end(); ++iter) {
    756     DisplayInfo display_info = GetDisplayInfo(iter->id());
    757     display_info.set_device_scale_factor(
    758         display_info.device_scale_factor() == 1.0f ? 2.0f : 1.0f);
    759     new_display_info_list.push_back(display_info);
    760   }
    761   AddMirrorDisplayInfoIfAny(&new_display_info_list);
    762   UpdateDisplays(new_display_info_list);
    763 }
    764 
    765 void DisplayManager::SetSoftwareMirroring(bool enabled) {
    766   software_mirroring_enabled_ = enabled;
    767   mirrored_display_ = gfx::Display();
    768 }
    769 
    770 bool DisplayManager::UpdateDisplayBounds(int64 display_id,
    771                                          const gfx::Rect& new_bounds) {
    772   if (change_display_upon_host_resize_) {
    773     display_info_[display_id].SetBounds(new_bounds);
    774     // Don't notify observers if the mirrored window has changed.
    775     if (software_mirroring_enabled_ && mirrored_display_.id() == display_id)
    776       return false;
    777     gfx::Display* display = FindDisplayForId(display_id);
    778     display->SetSize(display_info_[display_id].size_in_pixel());
    779     Shell::GetInstance()->screen()->NotifyBoundsChanged(*display);
    780     return true;
    781   }
    782   return false;
    783 }
    784 
    785 gfx::Display* DisplayManager::FindDisplayForId(int64 id) {
    786   for (DisplayList::iterator iter = displays_.begin();
    787        iter != displays_.end(); ++iter) {
    788     if ((*iter).id() == id)
    789       return &(*iter);
    790   }
    791   DLOG(WARNING) << "Could not find display:" << id;
    792   return NULL;
    793 }
    794 
    795 void DisplayManager::AddMirrorDisplayInfoIfAny(
    796     std::vector<DisplayInfo>* display_info_list) {
    797   if (software_mirroring_enabled_ && mirrored_display_.is_valid())
    798     display_info_list->push_back(GetDisplayInfo(mirrored_display_.id()));
    799 }
    800 
    801 void DisplayManager::InsertAndUpdateDisplayInfo(const DisplayInfo& new_info) {
    802   std::map<int64, DisplayInfo>::iterator info =
    803       display_info_.find(new_info.id());
    804   if (info != display_info_.end())
    805     info->second.Copy(new_info);
    806   else {
    807     display_info_[new_info.id()] = new_info;
    808     display_info_[new_info.id()].set_native(false);
    809   }
    810   display_info_[new_info.id()].UpdateDisplaySize();
    811 }
    812 
    813 gfx::Display DisplayManager::CreateDisplayFromDisplayInfoById(int64 id) {
    814   DCHECK(display_info_.find(id) != display_info_.end());
    815   const DisplayInfo& display_info = display_info_[id];
    816 
    817   gfx::Display new_display(display_info.id());
    818   gfx::Rect bounds_in_pixel(display_info.size_in_pixel());
    819 
    820   // Simply set the origin to (0,0).  The primary display's origin is
    821   // always (0,0) and the secondary display's bounds will be updated
    822   // in |UpdateSecondaryDisplayBoundsForLayout| called in |UpdateDisplay|.
    823   new_display.SetScaleAndBounds(
    824       display_info.device_scale_factor(), gfx::Rect(bounds_in_pixel.size()));
    825   new_display.set_rotation(display_info.rotation());
    826   return new_display;
    827 }
    828 
    829 bool DisplayManager::UpdateSecondaryDisplayBoundsForLayout(
    830     DisplayList* displays,
    831     size_t* updated_index) const {
    832   if (displays->size() != 2U)
    833     return false;
    834 
    835   int64 id_at_zero = displays->at(0).id();
    836   DisplayIdPair pair =
    837       (id_at_zero == first_display_id_ ||
    838        id_at_zero == gfx::Display::InternalDisplayId()) ?
    839       std::make_pair(id_at_zero, displays->at(1).id()) :
    840       std::make_pair(displays->at(1).id(), id_at_zero) ;
    841   DisplayLayout layout =
    842       layout_store_->ComputeDisplayLayoutForDisplayIdPair(pair);
    843 
    844   // Ignore if a user has a old format (should be extremely rare)
    845   // and this will be replaced with DCHECK.
    846   if (layout.primary_id != gfx::Display::kInvalidDisplayID) {
    847     size_t primary_index, secondary_index;
    848     if (displays->at(0).id() == layout.primary_id) {
    849       primary_index = 0;
    850       secondary_index = 1;
    851     } else {
    852       primary_index = 1;
    853       secondary_index = 0;
    854     }
    855     gfx::Rect bounds =
    856         GetDisplayForId(displays->at(secondary_index).id()).bounds();
    857     UpdateDisplayBoundsForLayout(
    858         layout, displays->at(primary_index), &displays->at(secondary_index));
    859     *updated_index = secondary_index;
    860     return bounds != displays->at(secondary_index).bounds();
    861   }
    862   return false;
    863 }
    864 
    865 // static
    866 void DisplayManager::UpdateDisplayBoundsForLayout(
    867     const DisplayLayout& layout,
    868     const gfx::Display& primary_display,
    869     gfx::Display* secondary_display) {
    870   DCHECK_EQ("0,0", primary_display.bounds().origin().ToString());
    871 
    872   const gfx::Rect& primary_bounds = primary_display.bounds();
    873   const gfx::Rect& secondary_bounds = secondary_display->bounds();
    874   gfx::Point new_secondary_origin = primary_bounds.origin();
    875 
    876   DisplayLayout::Position position = layout.position;
    877 
    878   // Ignore the offset in case the secondary display doesn't share edges with
    879   // the primary display.
    880   int offset = layout.offset;
    881   if (position == DisplayLayout::TOP || position == DisplayLayout::BOTTOM) {
    882     offset = std::min(
    883         offset, primary_bounds.width() - kMinimumOverlapForInvalidOffset);
    884     offset = std::max(
    885         offset, -secondary_bounds.width() + kMinimumOverlapForInvalidOffset);
    886   } else {
    887     offset = std::min(
    888         offset, primary_bounds.height() - kMinimumOverlapForInvalidOffset);
    889     offset = std::max(
    890         offset, -secondary_bounds.height() + kMinimumOverlapForInvalidOffset);
    891   }
    892   switch (position) {
    893     case DisplayLayout::TOP:
    894       new_secondary_origin.Offset(offset, -secondary_bounds.height());
    895       break;
    896     case DisplayLayout::RIGHT:
    897       new_secondary_origin.Offset(primary_bounds.width(), offset);
    898       break;
    899     case DisplayLayout::BOTTOM:
    900       new_secondary_origin.Offset(offset, primary_bounds.height());
    901       break;
    902     case DisplayLayout::LEFT:
    903       new_secondary_origin.Offset(-secondary_bounds.width(), offset);
    904       break;
    905   }
    906   gfx::Insets insets = secondary_display->GetWorkAreaInsets();
    907   secondary_display->set_bounds(
    908       gfx::Rect(new_secondary_origin, secondary_bounds.size()));
    909   secondary_display->UpdateWorkAreaFromInsets(insets);
    910 }
    911 
    912 }  // namespace internal
    913 }  // namespace ash
    914