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_controller.h"
      6 
      7 #include <algorithm>
      8 #include <cmath>
      9 #include <map>
     10 
     11 #include "ash/ash_switches.h"
     12 #include "ash/display/cursor_window_controller.h"
     13 #include "ash/display/display_layout_store.h"
     14 #include "ash/display/display_manager.h"
     15 #include "ash/display/mirror_window_controller.h"
     16 #include "ash/display/root_window_transformers.h"
     17 #include "ash/host/ash_window_tree_host.h"
     18 #include "ash/host/ash_window_tree_host_init_params.h"
     19 #include "ash/host/root_window_transformer.h"
     20 #include "ash/root_window_controller.h"
     21 #include "ash/root_window_settings.h"
     22 #include "ash/screen_util.h"
     23 #include "ash/shell.h"
     24 #include "ash/shell_delegate.h"
     25 #include "ash/wm/coordinate_conversion.h"
     26 #include "base/command_line.h"
     27 #include "base/stl_util.h"
     28 #include "base/strings/stringprintf.h"
     29 #include "base/strings/utf_string_conversions.h"
     30 #include "ui/aura/client/capture_client.h"
     31 #include "ui/aura/client/focus_client.h"
     32 #include "ui/aura/client/screen_position_client.h"
     33 #include "ui/aura/window.h"
     34 #include "ui/aura/window_event_dispatcher.h"
     35 #include "ui/aura/window_property.h"
     36 #include "ui/aura/window_tracker.h"
     37 #include "ui/aura/window_tree_host.h"
     38 #include "ui/compositor/compositor.h"
     39 #include "ui/compositor/compositor_vsync_manager.h"
     40 #include "ui/gfx/display.h"
     41 #include "ui/gfx/screen.h"
     42 #include "ui/wm/public/activation_client.h"
     43 
     44 #if defined(OS_CHROMEOS)
     45 #include "ash/display/display_configurator_animation.h"
     46 #include "base/sys_info.h"
     47 #include "base/time/time.h"
     48 #endif  // defined(OS_CHROMEOS)
     49 
     50 #if defined(USE_X11)
     51 #include "ui/base/x/x11_util.h"
     52 #include "ui/gfx/x/x11_types.h"
     53 
     54 // Including this at the bottom to avoid other
     55 // potential conflict with chrome headers.
     56 #include <X11/extensions/Xrandr.h>
     57 #undef RootWindow
     58 #endif  // defined(USE_X11)
     59 
     60 
     61 namespace ash {
     62 namespace {
     63 
     64 // Primary display stored in global object as it can be
     65 // accessed after Shell is deleted. A separate display instance is created
     66 // during the shutdown instead of always keeping two display instances
     67 // (one here and another one in display_manager) in sync, which is error prone.
     68 // This is initialized in the constructor, and then in CreatePrimaryHost().
     69 int64 primary_display_id = -1;
     70 
     71 // Specifies how long the display change should have been disabled
     72 // after each display change operations.
     73 // |kCycleDisplayThrottleTimeoutMs| is set to be longer to avoid
     74 // changing the settings while the system is still configurating
     75 // displays. It will be overriden by |kAfterDisplayChangeThrottleTimeoutMs|
     76 // when the display change happens, so the actual timeout is much shorter.
     77 const int64 kAfterDisplayChangeThrottleTimeoutMs = 500;
     78 const int64 kCycleDisplayThrottleTimeoutMs = 4000;
     79 const int64 kSwapDisplayThrottleTimeoutMs = 500;
     80 
     81 DisplayManager* GetDisplayManager() {
     82   return Shell::GetInstance()->display_manager();
     83 }
     84 
     85 void SetDisplayPropertiesOnHost(AshWindowTreeHost* ash_host,
     86                                 const gfx::Display& display) {
     87   DisplayInfo info = GetDisplayManager()->GetDisplayInfo(display.id());
     88   aura::WindowTreeHost* host = ash_host->AsWindowTreeHost();
     89 #if defined(OS_CHROMEOS) && defined(USE_X11)
     90   // Native window property (Atom in X11) that specifies the display's
     91   // rotation, scale factor and if it's internal display.  They are
     92   // read and used by touchpad/mouse driver directly on X (contact
     93   // adlr@ for more details on touchpad/mouse driver side). The value
     94   // of the rotation is one of 0 (normal), 1 (90 degrees clockwise), 2
     95   // (180 degree) or 3 (270 degrees clockwise).  The value of the
     96   // scale factor is in percent (100, 140, 200 etc).
     97   const char kRotationProp[] = "_CHROME_DISPLAY_ROTATION";
     98   const char kScaleFactorProp[] = "_CHROME_DISPLAY_SCALE_FACTOR";
     99   const char kInternalProp[] = "_CHROME_DISPLAY_INTERNAL";
    100   const char kCARDINAL[] = "CARDINAL";
    101   int xrandr_rotation = RR_Rotate_0;
    102   switch (info.rotation()) {
    103     case gfx::Display::ROTATE_0:
    104       xrandr_rotation = RR_Rotate_0;
    105       break;
    106     case gfx::Display::ROTATE_90:
    107       xrandr_rotation = RR_Rotate_90;
    108       break;
    109     case gfx::Display::ROTATE_180:
    110       xrandr_rotation = RR_Rotate_180;
    111       break;
    112     case gfx::Display::ROTATE_270:
    113       xrandr_rotation = RR_Rotate_270;
    114       break;
    115   }
    116 
    117   int internal = display.IsInternal() ? 1 : 0;
    118   gfx::AcceleratedWidget xwindow = host->GetAcceleratedWidget();
    119   ui::SetIntProperty(xwindow, kInternalProp, kCARDINAL, internal);
    120   ui::SetIntProperty(xwindow, kRotationProp, kCARDINAL, xrandr_rotation);
    121   ui::SetIntProperty(xwindow,
    122                      kScaleFactorProp,
    123                      kCARDINAL,
    124                      100 * display.device_scale_factor());
    125 #endif
    126   scoped_ptr<RootWindowTransformer> transformer(
    127       CreateRootWindowTransformerForDisplay(host->window(), display));
    128   ash_host->SetRootWindowTransformer(transformer.Pass());
    129 
    130   DisplayMode mode =
    131       GetDisplayManager()->GetActiveModeForDisplayId(display.id());
    132   if (mode.refresh_rate > 0.0f) {
    133     host->compositor()->vsync_manager()->SetAuthoritativeVSyncInterval(
    134         base::TimeDelta::FromMicroseconds(
    135             base::Time::kMicrosecondsPerSecond / mode.refresh_rate));
    136   }
    137 }
    138 
    139 aura::Window* GetWindow(AshWindowTreeHost* ash_host) {
    140   CHECK(ash_host->AsWindowTreeHost());
    141   return ash_host->AsWindowTreeHost()->window();
    142 }
    143 
    144 }  // namespace
    145 
    146 // A utility class to store/restore focused/active window
    147 // when the display configuration has changed.
    148 class FocusActivationStore {
    149  public:
    150   FocusActivationStore()
    151       : activation_client_(NULL),
    152         capture_client_(NULL),
    153         focus_client_(NULL),
    154         focused_(NULL),
    155         active_(NULL) {
    156   }
    157 
    158   void Store(bool clear_focus) {
    159     if (!activation_client_) {
    160       aura::Window* root = Shell::GetPrimaryRootWindow();
    161       activation_client_ = aura::client::GetActivationClient(root);
    162       capture_client_ = aura::client::GetCaptureClient(root);
    163       focus_client_ = aura::client::GetFocusClient(root);
    164     }
    165     focused_ = focus_client_->GetFocusedWindow();
    166     if (focused_)
    167       tracker_.Add(focused_);
    168     active_ = activation_client_->GetActiveWindow();
    169     if (active_ && focused_ != active_)
    170       tracker_.Add(active_);
    171 
    172     // Deactivate the window to close menu / bubble windows.
    173     if (clear_focus)
    174       activation_client_->DeactivateWindow(active_);
    175 
    176     // Release capture if any.
    177     capture_client_->SetCapture(NULL);
    178     // Clear the focused window if any. This is necessary because a
    179     // window may be deleted when losing focus (fullscreen flash for
    180     // example).  If the focused window is still alive after move, it'll
    181     // be re-focused below.
    182     if (clear_focus)
    183       focus_client_->FocusWindow(NULL);
    184   }
    185 
    186   void Restore() {
    187     // Restore focused or active window if it's still alive.
    188     if (focused_ && tracker_.Contains(focused_)) {
    189       focus_client_->FocusWindow(focused_);
    190     } else if (active_ && tracker_.Contains(active_)) {
    191       activation_client_->ActivateWindow(active_);
    192     }
    193     if (focused_)
    194       tracker_.Remove(focused_);
    195     if (active_)
    196       tracker_.Remove(active_);
    197     focused_ = NULL;
    198     active_ = NULL;
    199   }
    200 
    201  private:
    202   aura::client::ActivationClient* activation_client_;
    203   aura::client::CaptureClient* capture_client_;
    204   aura::client::FocusClient* focus_client_;
    205   aura::WindowTracker tracker_;
    206   aura::Window* focused_;
    207   aura::Window* active_;
    208 
    209   DISALLOW_COPY_AND_ASSIGN(FocusActivationStore);
    210 };
    211 
    212 ////////////////////////////////////////////////////////////////////////////////
    213 // DisplayChangeLimiter
    214 
    215 DisplayController::DisplayChangeLimiter::DisplayChangeLimiter()
    216     : throttle_timeout_(base::Time::Now()) {
    217 }
    218 
    219 void DisplayController::DisplayChangeLimiter::SetThrottleTimeout(
    220     int64 throttle_ms) {
    221   throttle_timeout_ =
    222       base::Time::Now() + base::TimeDelta::FromMilliseconds(throttle_ms);
    223 }
    224 
    225 bool DisplayController::DisplayChangeLimiter::IsThrottled() const {
    226   return base::Time::Now() < throttle_timeout_;
    227 }
    228 
    229 ////////////////////////////////////////////////////////////////////////////////
    230 // DisplayController
    231 
    232 DisplayController::DisplayController()
    233     : primary_tree_host_for_replace_(NULL),
    234       focus_activation_store_(new FocusActivationStore()),
    235       cursor_window_controller_(new CursorWindowController()),
    236       mirror_window_controller_(new MirrorWindowController()),
    237       weak_ptr_factory_(this) {
    238 #if defined(OS_CHROMEOS)
    239   if (base::SysInfo::IsRunningOnChromeOS())
    240     limiter_.reset(new DisplayChangeLimiter);
    241 #endif
    242   // Reset primary display to make sure that tests don't use
    243   // stale display info from previous tests.
    244   primary_display_id = gfx::Display::kInvalidDisplayID;
    245 }
    246 
    247 DisplayController::~DisplayController() {
    248 }
    249 
    250 void DisplayController::Start() {
    251   Shell::GetScreen()->AddObserver(this);
    252   Shell::GetInstance()->display_manager()->set_delegate(this);
    253 }
    254 
    255 void DisplayController::Shutdown() {
    256   // Unset the display manager's delegate here because
    257   // DisplayManager outlives DisplayController.
    258   Shell::GetInstance()->display_manager()->set_delegate(NULL);
    259 
    260   cursor_window_controller_.reset();
    261   mirror_window_controller_.reset();
    262 
    263   Shell::GetScreen()->RemoveObserver(this);
    264 
    265   int64 primary_id = Shell::GetScreen()->GetPrimaryDisplay().id();
    266 
    267   // Delete non primary root window controllers first, then
    268   // delete the primary root window controller.
    269   aura::Window::Windows root_windows = DisplayController::GetAllRootWindows();
    270   std::vector<RootWindowController*> to_delete;
    271   RootWindowController* primary_rwc = NULL;
    272   for (aura::Window::Windows::iterator iter = root_windows.begin();
    273        iter != root_windows.end();
    274        ++iter) {
    275     RootWindowController* rwc = GetRootWindowController(*iter);
    276     if (GetRootWindowSettings(*iter)->display_id == primary_id)
    277       primary_rwc = rwc;
    278     else
    279       to_delete.push_back(rwc);
    280   }
    281   CHECK(primary_rwc);
    282 
    283   STLDeleteElements(&to_delete);
    284   delete primary_rwc;
    285 }
    286 
    287 void DisplayController::CreatePrimaryHost(
    288     const AshWindowTreeHostInitParams& init_params) {
    289   const gfx::Display& primary_candidate =
    290       GetDisplayManager()->GetPrimaryDisplayCandidate();
    291   primary_display_id = primary_candidate.id();
    292   CHECK_NE(gfx::Display::kInvalidDisplayID, primary_display_id);
    293   AddWindowTreeHostForDisplay(primary_candidate, init_params);
    294 }
    295 
    296 void DisplayController::InitDisplays() {
    297   RootWindowController::CreateForPrimaryDisplay(
    298       window_tree_hosts_[primary_display_id]);
    299 
    300   DisplayManager* display_manager = GetDisplayManager();
    301   for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) {
    302     const gfx::Display& display = display_manager->GetDisplayAt(i);
    303     if (primary_display_id != display.id()) {
    304       AshWindowTreeHost* ash_host = AddWindowTreeHostForDisplay(
    305           display, AshWindowTreeHostInitParams());
    306       RootWindowController::CreateForSecondaryDisplay(ash_host);
    307     }
    308   }
    309   UpdateHostWindowNames();
    310 
    311   FOR_EACH_OBSERVER(Observer, observers_, OnDisplaysInitialized());
    312 }
    313 
    314 void DisplayController::AddObserver(Observer* observer) {
    315   observers_.AddObserver(observer);
    316 }
    317 
    318 void DisplayController::RemoveObserver(Observer* observer) {
    319   observers_.RemoveObserver(observer);
    320 }
    321 
    322 // static
    323 int64 DisplayController::GetPrimaryDisplayId() {
    324   CHECK_NE(gfx::Display::kInvalidDisplayID, primary_display_id);
    325   return primary_display_id;
    326 }
    327 
    328 aura::Window* DisplayController::GetPrimaryRootWindow() {
    329   return GetRootWindowForDisplayId(primary_display_id);
    330 }
    331 
    332 aura::Window* DisplayController::GetRootWindowForDisplayId(int64 id) {
    333   CHECK_EQ(1u, window_tree_hosts_.count(id));
    334   AshWindowTreeHost* host = window_tree_hosts_[id];
    335   CHECK(host);
    336   return GetWindow(host);
    337 }
    338 
    339 void DisplayController::CloseChildWindows() {
    340   for (WindowTreeHostMap::const_iterator it = window_tree_hosts_.begin();
    341        it != window_tree_hosts_.end();
    342        ++it) {
    343     aura::Window* root_window = GetWindow(it->second);
    344     RootWindowController* controller = GetRootWindowController(root_window);
    345     if (controller) {
    346       controller->CloseChildWindows();
    347     } else {
    348       while (!root_window->children().empty()) {
    349         aura::Window* child = root_window->children()[0];
    350         delete child;
    351       }
    352     }
    353   }
    354 }
    355 
    356 aura::Window::Windows DisplayController::GetAllRootWindows() {
    357   aura::Window::Windows windows;
    358   for (WindowTreeHostMap::const_iterator it = window_tree_hosts_.begin();
    359        it != window_tree_hosts_.end();
    360        ++it) {
    361     DCHECK(it->second);
    362     if (GetRootWindowController(GetWindow(it->second)))
    363       windows.push_back(GetWindow(it->second));
    364   }
    365   return windows;
    366 }
    367 
    368 gfx::Insets DisplayController::GetOverscanInsets(int64 display_id) const {
    369   return GetDisplayManager()->GetOverscanInsets(display_id);
    370 }
    371 
    372 void DisplayController::SetOverscanInsets(int64 display_id,
    373                                           const gfx::Insets& insets_in_dip) {
    374   GetDisplayManager()->SetOverscanInsets(display_id, insets_in_dip);
    375 }
    376 
    377 std::vector<RootWindowController*>
    378 DisplayController::GetAllRootWindowControllers() {
    379   std::vector<RootWindowController*> controllers;
    380   for (WindowTreeHostMap::const_iterator it = window_tree_hosts_.begin();
    381        it != window_tree_hosts_.end();
    382        ++it) {
    383     RootWindowController* controller =
    384         GetRootWindowController(GetWindow(it->second));
    385     if (controller)
    386       controllers.push_back(controller);
    387   }
    388   return controllers;
    389 }
    390 
    391 void DisplayController::ToggleMirrorMode() {
    392   DisplayManager* display_manager = GetDisplayManager();
    393   if (display_manager->num_connected_displays() <= 1)
    394     return;
    395 
    396   if (limiter_) {
    397     if  (limiter_->IsThrottled())
    398       return;
    399     limiter_->SetThrottleTimeout(kCycleDisplayThrottleTimeoutMs);
    400   }
    401 #if defined(OS_CHROMEOS)
    402   Shell* shell = Shell::GetInstance();
    403   DisplayConfiguratorAnimation* animation =
    404       shell->display_configurator_animation();
    405   animation->StartFadeOutAnimation(
    406       base::Bind(&DisplayController::SetMirrorModeAfterAnimation,
    407                  weak_ptr_factory_.GetWeakPtr(),
    408                  !display_manager->IsMirrored()));
    409 #endif
    410 }
    411 
    412 void DisplayController::SwapPrimaryDisplay() {
    413   if (limiter_) {
    414     if  (limiter_->IsThrottled())
    415       return;
    416     limiter_->SetThrottleTimeout(kSwapDisplayThrottleTimeoutMs);
    417   }
    418 
    419   if (Shell::GetScreen()->GetNumDisplays() > 1) {
    420 #if defined(OS_CHROMEOS)
    421     DisplayConfiguratorAnimation* animation =
    422         Shell::GetInstance()->display_configurator_animation();
    423     if (animation) {
    424       animation->StartFadeOutAnimation(base::Bind(
    425           &DisplayController::OnFadeOutForSwapDisplayFinished,
    426           weak_ptr_factory_.GetWeakPtr()));
    427     } else {
    428       SetPrimaryDisplay(ScreenUtil::GetSecondaryDisplay());
    429     }
    430 #else
    431     SetPrimaryDisplay(ScreenUtil::GetSecondaryDisplay());
    432 #endif
    433   }
    434 }
    435 
    436 void DisplayController::SetPrimaryDisplayId(int64 id) {
    437   DCHECK_NE(gfx::Display::kInvalidDisplayID, id);
    438   if (id == gfx::Display::kInvalidDisplayID || primary_display_id == id)
    439     return;
    440 
    441   const gfx::Display& display = GetDisplayManager()->GetDisplayForId(id);
    442   if (display.is_valid())
    443     SetPrimaryDisplay(display);
    444 }
    445 
    446 void DisplayController::SetPrimaryDisplay(
    447     const gfx::Display& new_primary_display) {
    448   DisplayManager* display_manager = GetDisplayManager();
    449   DCHECK(new_primary_display.is_valid());
    450   DCHECK(display_manager->IsActiveDisplay(new_primary_display));
    451 
    452   if (!new_primary_display.is_valid() ||
    453       !display_manager->IsActiveDisplay(new_primary_display)) {
    454     LOG(ERROR) << "Invalid or non-existent display is requested:"
    455                << new_primary_display.ToString();
    456     return;
    457   }
    458 
    459   if (primary_display_id == new_primary_display.id() ||
    460       window_tree_hosts_.size() < 2) {
    461     return;
    462   }
    463 
    464   AshWindowTreeHost* non_primary_host =
    465       window_tree_hosts_[new_primary_display.id()];
    466   LOG_IF(ERROR, !non_primary_host)
    467       << "Unknown display is requested in SetPrimaryDisplay: id="
    468       << new_primary_display.id();
    469   if (!non_primary_host)
    470     return;
    471 
    472   gfx::Display old_primary_display = Shell::GetScreen()->GetPrimaryDisplay();
    473 
    474   // Swap root windows between current and new primary display.
    475   AshWindowTreeHost* primary_host = window_tree_hosts_[primary_display_id];
    476   CHECK(primary_host);
    477   CHECK_NE(primary_host, non_primary_host);
    478 
    479   window_tree_hosts_[new_primary_display.id()] = primary_host;
    480   GetRootWindowSettings(GetWindow(primary_host))->display_id =
    481       new_primary_display.id();
    482 
    483   window_tree_hosts_[old_primary_display.id()] = non_primary_host;
    484   GetRootWindowSettings(GetWindow(non_primary_host))->display_id =
    485       old_primary_display.id();
    486 
    487   primary_display_id = new_primary_display.id();
    488   GetDisplayManager()->layout_store()->UpdatePrimaryDisplayId(
    489       display_manager->GetCurrentDisplayIdPair(), primary_display_id);
    490 
    491   UpdateWorkAreaOfDisplayNearestWindow(GetWindow(primary_host),
    492                                        old_primary_display.GetWorkAreaInsets());
    493   UpdateWorkAreaOfDisplayNearestWindow(GetWindow(non_primary_host),
    494                                        new_primary_display.GetWorkAreaInsets());
    495 
    496   // Update the dispay manager with new display info.
    497   std::vector<DisplayInfo> display_info_list;
    498   display_info_list.push_back(display_manager->GetDisplayInfo(
    499       primary_display_id));
    500   display_info_list.push_back(display_manager->GetDisplayInfo(
    501       ScreenUtil::GetSecondaryDisplay().id()));
    502   GetDisplayManager()->set_force_bounds_changed(true);
    503   GetDisplayManager()->UpdateDisplays(display_info_list);
    504   GetDisplayManager()->set_force_bounds_changed(false);
    505 }
    506 
    507 void DisplayController::EnsurePointerInDisplays() {
    508   // If the mouse is currently on a display in native location,
    509   // use the same native location. Otherwise find the display closest
    510   // to the current cursor location in screen coordinates.
    511 
    512   gfx::Point point_in_screen = Shell::GetScreen()->GetCursorScreenPoint();
    513   gfx::Point target_location_in_native;
    514   int64 closest_distance_squared = -1;
    515   DisplayManager* display_manager = GetDisplayManager();
    516 
    517   aura::Window* dst_root_window = NULL;
    518   for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) {
    519     const gfx::Display& display = display_manager->GetDisplayAt(i);
    520     const DisplayInfo display_info =
    521         display_manager->GetDisplayInfo(display.id());
    522     aura::Window* root_window = GetRootWindowForDisplayId(display.id());
    523     if (display_info.bounds_in_native().Contains(
    524             cursor_location_in_native_coords_for_restore_)) {
    525       dst_root_window = root_window;
    526       target_location_in_native = cursor_location_in_native_coords_for_restore_;
    527       break;
    528     }
    529     gfx::Point center = display.bounds().CenterPoint();
    530     // Use the distance squared from the center of the dislay. This is not
    531     // exactly "closest" display, but good enough to pick one
    532     // appropriate (and there are at most two displays).
    533     // We don't care about actual distance, only relative to other displays, so
    534     // using the LengthSquared() is cheaper than Length().
    535 
    536     int64 distance_squared = (center - point_in_screen).LengthSquared();
    537     if (closest_distance_squared < 0 ||
    538         closest_distance_squared > distance_squared) {
    539       aura::Window* root_window = GetRootWindowForDisplayId(display.id());
    540       aura::client::ScreenPositionClient* client =
    541           aura::client::GetScreenPositionClient(root_window);
    542       client->ConvertPointFromScreen(root_window, &center);
    543       root_window->GetHost()->ConvertPointToNativeScreen(&center);
    544       dst_root_window = root_window;
    545       target_location_in_native = center;
    546       closest_distance_squared = distance_squared;
    547     }
    548   }
    549   dst_root_window->GetHost()->ConvertPointFromNativeScreen(
    550       &target_location_in_native);
    551   dst_root_window->MoveCursorTo(target_location_in_native);
    552 }
    553 
    554 bool DisplayController::UpdateWorkAreaOfDisplayNearestWindow(
    555     const aura::Window* window,
    556     const gfx::Insets& insets) {
    557   const aura::Window* root_window = window->GetRootWindow();
    558   int64 id = GetRootWindowSettings(root_window)->display_id;
    559   // if id is |kInvaildDisplayID|, it's being deleted.
    560   DCHECK(id != gfx::Display::kInvalidDisplayID);
    561   return GetDisplayManager()->UpdateWorkAreaOfDisplay(id, insets);
    562 }
    563 
    564 void DisplayController::OnDisplayAdded(const gfx::Display& display) {
    565   if (primary_tree_host_for_replace_) {
    566     DCHECK(window_tree_hosts_.empty());
    567     primary_display_id = display.id();
    568     window_tree_hosts_[display.id()] = primary_tree_host_for_replace_;
    569     GetRootWindowSettings(GetWindow(primary_tree_host_for_replace_))
    570         ->display_id = display.id();
    571     primary_tree_host_for_replace_ = NULL;
    572     const DisplayInfo& display_info =
    573         GetDisplayManager()->GetDisplayInfo(display.id());
    574     AshWindowTreeHost* ash_host = window_tree_hosts_[display.id()];
    575     ash_host->AsWindowTreeHost()->SetBounds(display_info.bounds_in_native());
    576     SetDisplayPropertiesOnHost(ash_host, display);
    577   } else {
    578     if (primary_display_id == gfx::Display::kInvalidDisplayID)
    579       primary_display_id = display.id();
    580     DCHECK(!window_tree_hosts_.empty());
    581     AshWindowTreeHost* ash_host = AddWindowTreeHostForDisplay(
    582         display, AshWindowTreeHostInitParams());
    583     RootWindowController::CreateForSecondaryDisplay(ash_host);
    584   }
    585 }
    586 
    587 void DisplayController::OnDisplayRemoved(const gfx::Display& display) {
    588   AshWindowTreeHost* host_to_delete = window_tree_hosts_[display.id()];
    589   CHECK(host_to_delete) << display.ToString();
    590 
    591   // Display for root window will be deleted when the Primary RootWindow
    592   // is deleted by the Shell.
    593   window_tree_hosts_.erase(display.id());
    594 
    595   // When the primary root window's display is removed, move the primary
    596   // root to the other display.
    597   if (primary_display_id == display.id()) {
    598     // Temporarily store the primary root window in
    599     // |primary_root_window_for_replace_| when replacing the display.
    600     if (window_tree_hosts_.size() == 0) {
    601       primary_display_id = gfx::Display::kInvalidDisplayID;
    602       primary_tree_host_for_replace_ = host_to_delete;
    603       return;
    604     }
    605     DCHECK_EQ(1U, window_tree_hosts_.size());
    606     primary_display_id = ScreenUtil::GetSecondaryDisplay().id();
    607     AshWindowTreeHost* primary_host = host_to_delete;
    608 
    609     // Delete the other host instead.
    610     host_to_delete = window_tree_hosts_[primary_display_id];
    611     GetRootWindowSettings(GetWindow(host_to_delete))->display_id = display.id();
    612 
    613     // Setup primary root.
    614     window_tree_hosts_[primary_display_id] = primary_host;
    615     GetRootWindowSettings(GetWindow(primary_host))->display_id =
    616         primary_display_id;
    617 
    618     OnDisplayMetricsChanged(
    619         GetDisplayManager()->GetDisplayForId(primary_display_id),
    620         DISPLAY_METRIC_BOUNDS);
    621   }
    622   RootWindowController* controller =
    623       GetRootWindowController(GetWindow(host_to_delete));
    624   DCHECK(controller);
    625   controller->MoveWindowsTo(GetPrimaryRootWindow());
    626   // Delete most of root window related objects, but don't delete
    627   // root window itself yet because the stack may be using it.
    628   controller->Shutdown();
    629   base::MessageLoop::current()->DeleteSoon(FROM_HERE, controller);
    630 }
    631 
    632 void DisplayController::OnDisplayMetricsChanged(const gfx::Display& display,
    633                                                 uint32_t metrics) {
    634   if (!(metrics & (DISPLAY_METRIC_BOUNDS | DISPLAY_METRIC_ROTATION |
    635                    DISPLAY_METRIC_DEVICE_SCALE_FACTOR)))
    636     return;
    637   const DisplayInfo& display_info =
    638       GetDisplayManager()->GetDisplayInfo(display.id());
    639   DCHECK(!display_info.bounds_in_native().IsEmpty());
    640   AshWindowTreeHost* ash_host = window_tree_hosts_[display.id()];
    641   ash_host->AsWindowTreeHost()->SetBounds(display_info.bounds_in_native());
    642   SetDisplayPropertiesOnHost(ash_host, display);
    643 }
    644 
    645 void DisplayController::OnHostResized(const aura::WindowTreeHost* host) {
    646   gfx::Display display = Shell::GetScreen()->GetDisplayNearestWindow(
    647       const_cast<aura::Window*>(host->window()));
    648 
    649   DisplayManager* display_manager = GetDisplayManager();
    650   if (display_manager->UpdateDisplayBounds(display.id(), host->GetBounds())) {
    651     mirror_window_controller_->UpdateWindow();
    652     cursor_window_controller_->UpdateContainer();
    653   }
    654 }
    655 
    656 void DisplayController::CreateOrUpdateNonDesktopDisplay(
    657     const DisplayInfo& info) {
    658   switch (GetDisplayManager()->second_display_mode()) {
    659     case DisplayManager::MIRRORING:
    660       mirror_window_controller_->UpdateWindow(info);
    661       cursor_window_controller_->UpdateContainer();
    662       break;
    663     case DisplayManager::EXTENDED:
    664       NOTREACHED();
    665   }
    666 }
    667 
    668 void DisplayController::CloseNonDesktopDisplay() {
    669   mirror_window_controller_->Close();
    670   // If cursor_compositing is enabled for large cursor, the cursor window is
    671   // always on the desktop display (the visible cursor on the non-desktop
    672   // display is drawn through compositor mirroring). Therefore, it's unnecessary
    673   // to handle the cursor_window at all. See: http://crbug.com/412910
    674   if (!cursor_window_controller_->is_cursor_compositing_enabled())
    675     cursor_window_controller_->UpdateContainer();
    676 }
    677 
    678 void DisplayController::PreDisplayConfigurationChange(bool clear_focus) {
    679   FOR_EACH_OBSERVER(Observer, observers_, OnDisplayConfigurationChanging());
    680   focus_activation_store_->Store(clear_focus);
    681   gfx::Screen* screen = Shell::GetScreen();
    682   gfx::Point point_in_screen = screen->GetCursorScreenPoint();
    683   gfx::Display display = screen->GetDisplayNearestPoint(point_in_screen);
    684   aura::Window* root_window = GetRootWindowForDisplayId(display.id());
    685 
    686   aura::client::ScreenPositionClient* client =
    687       aura::client::GetScreenPositionClient(root_window);
    688   client->ConvertPointFromScreen(root_window, &point_in_screen);
    689   root_window->GetHost()->ConvertPointToNativeScreen(&point_in_screen);
    690   cursor_location_in_native_coords_for_restore_ = point_in_screen;
    691 }
    692 
    693 void DisplayController::PostDisplayConfigurationChange() {
    694   if (limiter_)
    695     limiter_->SetThrottleTimeout(kAfterDisplayChangeThrottleTimeoutMs);
    696 
    697   focus_activation_store_->Restore();
    698 
    699   DisplayManager* display_manager = GetDisplayManager();
    700   DisplayLayoutStore* layout_store = display_manager->layout_store();
    701   if (display_manager->num_connected_displays() > 1) {
    702     DisplayIdPair pair = display_manager->GetCurrentDisplayIdPair();
    703     layout_store->UpdateMirrorStatus(pair, display_manager->IsMirrored());
    704     DisplayLayout layout = layout_store->GetRegisteredDisplayLayout(pair);
    705 
    706     if (Shell::GetScreen()->GetNumDisplays() > 1 ) {
    707       int64 primary_id = layout.primary_id;
    708       SetPrimaryDisplayId(
    709           primary_id == gfx::Display::kInvalidDisplayID ?
    710           pair.first : primary_id);
    711       // Update the primary_id in case the above call is
    712       // ignored. Happens when a) default layout's primary id
    713       // doesn't exist, or b) the primary_id has already been
    714       // set to the same and didn't update it.
    715       layout_store->UpdatePrimaryDisplayId(
    716           pair, Shell::GetScreen()->GetPrimaryDisplay().id());
    717     }
    718   }
    719   FOR_EACH_OBSERVER(Observer, observers_, OnDisplayConfigurationChanged());
    720   UpdateHostWindowNames();
    721   EnsurePointerInDisplays();
    722 }
    723 
    724 AshWindowTreeHost* DisplayController::AddWindowTreeHostForDisplay(
    725     const gfx::Display& display,
    726     const AshWindowTreeHostInitParams& init_params) {
    727   static int host_count = 0;
    728   const DisplayInfo& display_info =
    729       GetDisplayManager()->GetDisplayInfo(display.id());
    730   AshWindowTreeHostInitParams params_with_bounds(init_params);
    731   params_with_bounds.initial_bounds = display_info.bounds_in_native();
    732   AshWindowTreeHost* ash_host = AshWindowTreeHost::Create(params_with_bounds);
    733   aura::WindowTreeHost* host = ash_host->AsWindowTreeHost();
    734 
    735   host->window()->SetName(base::StringPrintf("RootWindow-%d", host_count++));
    736   host->window()->SetTitle(base::UTF8ToUTF16(display_info.name()));
    737   host->compositor()->SetBackgroundColor(SK_ColorBLACK);
    738   // No need to remove our observer observer because the DisplayController
    739   // outlives the host.
    740   host->AddObserver(this);
    741   InitRootWindowSettings(host->window())->display_id = display.id();
    742   host->InitHost();
    743 
    744   window_tree_hosts_[display.id()] = ash_host;
    745   SetDisplayPropertiesOnHost(ash_host, display);
    746 
    747 #if defined(OS_CHROMEOS)
    748   static bool force_constrain_pointer_to_root =
    749       CommandLine::ForCurrentProcess()->HasSwitch(
    750           switches::kAshConstrainPointerToRoot);
    751   if (base::SysInfo::IsRunningOnChromeOS() || force_constrain_pointer_to_root)
    752     ash_host->ConfineCursorToRootWindow();
    753 #endif
    754   return ash_host;
    755 }
    756 
    757 void DisplayController::OnFadeOutForSwapDisplayFinished() {
    758 #if defined(OS_CHROMEOS)
    759   SetPrimaryDisplay(ScreenUtil::GetSecondaryDisplay());
    760   Shell::GetInstance()->display_configurator_animation()
    761       ->StartFadeInAnimation();
    762 #endif
    763 }
    764 
    765 void DisplayController::SetMirrorModeAfterAnimation(bool mirror) {
    766   GetDisplayManager()->SetMirrorMode(mirror);
    767 }
    768 
    769 void DisplayController::UpdateHostWindowNames() {
    770 #if defined(USE_X11)
    771   // crbug.com/120229 - set the window title for the primary dislpay
    772   // to "aura_root_0" so gtalk can find the primary root window to broadcast.
    773   // TODO(jhorwich) Remove this once Chrome supports window-based broadcasting.
    774   aura::Window* primary = Shell::GetPrimaryRootWindow();
    775   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
    776   for (size_t i = 0; i < root_windows.size(); ++i) {
    777     std::string name =
    778         root_windows[i] == primary ? "aura_root_0" : "aura_root_x";
    779     gfx::AcceleratedWidget xwindow =
    780         root_windows[i]->GetHost()->GetAcceleratedWidget();
    781     XStoreName(gfx::GetXDisplay(), xwindow, name.c_str());
    782   }
    783 #endif
    784 }
    785 
    786 }  // namespace ash
    787