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/display/virtual_keyboard_window_controller.h"
     18 #include "ash/host/ash_window_tree_host.h"
     19 #include "ash/host/ash_window_tree_host_init_params.h"
     20 #include "ash/host/root_window_transformer.h"
     21 #include "ash/root_window_controller.h"
     22 #include "ash/root_window_settings.h"
     23 #include "ash/screen_util.h"
     24 #include "ash/shell.h"
     25 #include "ash/shell_delegate.h"
     26 #include "ash/wm/coordinate_conversion.h"
     27 #include "base/command_line.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   if (GetDisplayManager()->GetSelectedModeForDisplayId(display.id(), &mode) &&
    132       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   // Created here so that Shell has finished being created. Adds itself
    252   // as a ShellObserver.
    253   virtual_keyboard_window_controller_.reset(
    254       new VirtualKeyboardWindowController);
    255   Shell::GetScreen()->AddObserver(this);
    256   Shell::GetInstance()->display_manager()->set_delegate(this);
    257 }
    258 
    259 void DisplayController::Shutdown() {
    260   // Unset the display manager's delegate here because
    261   // DisplayManager outlives DisplayController.
    262   Shell::GetInstance()->display_manager()->set_delegate(NULL);
    263 
    264   cursor_window_controller_.reset();
    265   mirror_window_controller_.reset();
    266   virtual_keyboard_window_controller_.reset();
    267 
    268   Shell::GetScreen()->RemoveObserver(this);
    269   // Delete all root window controllers, which deletes root window
    270   // from the last so that the primary root window gets deleted last.
    271   for (WindowTreeHostMap::const_reverse_iterator it =
    272            window_tree_hosts_.rbegin();
    273        it != window_tree_hosts_.rend();
    274        ++it) {
    275     RootWindowController* controller =
    276         GetRootWindowController(GetWindow(it->second));
    277     DCHECK(controller);
    278     delete controller;
    279   }
    280 }
    281 
    282 void DisplayController::CreatePrimaryHost(
    283     const AshWindowTreeHostInitParams& init_params) {
    284   const gfx::Display& primary_candidate =
    285       GetDisplayManager()->GetPrimaryDisplayCandidate();
    286   primary_display_id = primary_candidate.id();
    287   CHECK_NE(gfx::Display::kInvalidDisplayID, primary_display_id);
    288   AddWindowTreeHostForDisplay(primary_candidate, init_params);
    289 }
    290 
    291 void DisplayController::InitDisplays() {
    292   RootWindowController::CreateForPrimaryDisplay(
    293       window_tree_hosts_[primary_display_id]);
    294 
    295   DisplayManager* display_manager = GetDisplayManager();
    296   for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) {
    297     const gfx::Display& display = display_manager->GetDisplayAt(i);
    298     if (primary_display_id != display.id()) {
    299       AshWindowTreeHost* ash_host = AddWindowTreeHostForDisplay(
    300           display, AshWindowTreeHostInitParams());
    301       RootWindowController::CreateForSecondaryDisplay(ash_host);
    302     }
    303   }
    304   UpdateHostWindowNames();
    305 
    306   FOR_EACH_OBSERVER(Observer, observers_, OnDisplaysInitialized());
    307 }
    308 
    309 void DisplayController::AddObserver(Observer* observer) {
    310   observers_.AddObserver(observer);
    311 }
    312 
    313 void DisplayController::RemoveObserver(Observer* observer) {
    314   observers_.RemoveObserver(observer);
    315 }
    316 
    317 // static
    318 int64 DisplayController::GetPrimaryDisplayId() {
    319   CHECK_NE(gfx::Display::kInvalidDisplayID, primary_display_id);
    320   return primary_display_id;
    321 }
    322 
    323 aura::Window* DisplayController::GetPrimaryRootWindow() {
    324   return GetRootWindowForDisplayId(primary_display_id);
    325 }
    326 
    327 aura::Window* DisplayController::GetRootWindowForDisplayId(int64 id) {
    328   DCHECK_EQ(1u, window_tree_hosts_.count(id));
    329   AshWindowTreeHost* host = window_tree_hosts_[id];
    330   CHECK(host);
    331   return GetWindow(host);
    332 }
    333 
    334 void DisplayController::CloseChildWindows() {
    335   for (WindowTreeHostMap::const_iterator it = window_tree_hosts_.begin();
    336        it != window_tree_hosts_.end();
    337        ++it) {
    338     aura::Window* root_window = GetWindow(it->second);
    339     RootWindowController* controller = GetRootWindowController(root_window);
    340     if (controller) {
    341       controller->CloseChildWindows();
    342     } else {
    343       while (!root_window->children().empty()) {
    344         aura::Window* child = root_window->children()[0];
    345         delete child;
    346       }
    347     }
    348   }
    349 }
    350 
    351 aura::Window::Windows DisplayController::GetAllRootWindows() {
    352   aura::Window::Windows windows;
    353   for (WindowTreeHostMap::const_iterator it = window_tree_hosts_.begin();
    354        it != window_tree_hosts_.end();
    355        ++it) {
    356     DCHECK(it->second);
    357     if (GetRootWindowController(GetWindow(it->second)))
    358       windows.push_back(GetWindow(it->second));
    359   }
    360   return windows;
    361 }
    362 
    363 gfx::Insets DisplayController::GetOverscanInsets(int64 display_id) const {
    364   return GetDisplayManager()->GetOverscanInsets(display_id);
    365 }
    366 
    367 void DisplayController::SetOverscanInsets(int64 display_id,
    368                                           const gfx::Insets& insets_in_dip) {
    369   GetDisplayManager()->SetOverscanInsets(display_id, insets_in_dip);
    370 }
    371 
    372 std::vector<RootWindowController*>
    373 DisplayController::GetAllRootWindowControllers() {
    374   std::vector<RootWindowController*> controllers;
    375   for (WindowTreeHostMap::const_iterator it = window_tree_hosts_.begin();
    376        it != window_tree_hosts_.end();
    377        ++it) {
    378     RootWindowController* controller =
    379         GetRootWindowController(GetWindow(it->second));
    380     if (controller)
    381       controllers.push_back(controller);
    382   }
    383   return controllers;
    384 }
    385 
    386 void DisplayController::ToggleMirrorMode() {
    387   DisplayManager* display_manager = GetDisplayManager();
    388   if (display_manager->num_connected_displays() <= 1)
    389     return;
    390 
    391   if (limiter_) {
    392     if  (limiter_->IsThrottled())
    393       return;
    394     limiter_->SetThrottleTimeout(kCycleDisplayThrottleTimeoutMs);
    395   }
    396 #if defined(OS_CHROMEOS)
    397   Shell* shell = Shell::GetInstance();
    398   DisplayConfiguratorAnimation* animation =
    399       shell->display_configurator_animation();
    400   animation->StartFadeOutAnimation(
    401       base::Bind(&DisplayController::SetMirrorModeAfterAnimation,
    402                  weak_ptr_factory_.GetWeakPtr(),
    403                  !display_manager->IsMirrored()));
    404 #endif
    405 }
    406 
    407 void DisplayController::SwapPrimaryDisplay() {
    408   if (limiter_) {
    409     if  (limiter_->IsThrottled())
    410       return;
    411     limiter_->SetThrottleTimeout(kSwapDisplayThrottleTimeoutMs);
    412   }
    413 
    414   if (Shell::GetScreen()->GetNumDisplays() > 1) {
    415 #if defined(OS_CHROMEOS)
    416     DisplayConfiguratorAnimation* animation =
    417         Shell::GetInstance()->display_configurator_animation();
    418     if (animation) {
    419       animation->StartFadeOutAnimation(base::Bind(
    420           &DisplayController::OnFadeOutForSwapDisplayFinished,
    421           weak_ptr_factory_.GetWeakPtr()));
    422     } else {
    423       SetPrimaryDisplay(ScreenUtil::GetSecondaryDisplay());
    424     }
    425 #else
    426     SetPrimaryDisplay(ScreenUtil::GetSecondaryDisplay());
    427 #endif
    428   }
    429 }
    430 
    431 void DisplayController::SetPrimaryDisplayId(int64 id) {
    432   DCHECK_NE(gfx::Display::kInvalidDisplayID, id);
    433   if (id == gfx::Display::kInvalidDisplayID || primary_display_id == id)
    434     return;
    435 
    436   const gfx::Display& display = GetDisplayManager()->GetDisplayForId(id);
    437   if (display.is_valid())
    438     SetPrimaryDisplay(display);
    439 }
    440 
    441 void DisplayController::SetPrimaryDisplay(
    442     const gfx::Display& new_primary_display) {
    443   DisplayManager* display_manager = GetDisplayManager();
    444   DCHECK(new_primary_display.is_valid());
    445   DCHECK(display_manager->IsActiveDisplay(new_primary_display));
    446 
    447   if (!new_primary_display.is_valid() ||
    448       !display_manager->IsActiveDisplay(new_primary_display)) {
    449     LOG(ERROR) << "Invalid or non-existent display is requested:"
    450                << new_primary_display.ToString();
    451     return;
    452   }
    453 
    454   if (primary_display_id == new_primary_display.id() ||
    455       window_tree_hosts_.size() < 2) {
    456     return;
    457   }
    458 
    459   AshWindowTreeHost* non_primary_host =
    460       window_tree_hosts_[new_primary_display.id()];
    461   LOG_IF(ERROR, !non_primary_host)
    462       << "Unknown display is requested in SetPrimaryDisplay: id="
    463       << new_primary_display.id();
    464   if (!non_primary_host)
    465     return;
    466 
    467   gfx::Display old_primary_display = Shell::GetScreen()->GetPrimaryDisplay();
    468 
    469   // Swap root windows between current and new primary display.
    470   AshWindowTreeHost* primary_host = window_tree_hosts_[primary_display_id];
    471   CHECK(primary_host);
    472   CHECK_NE(primary_host, non_primary_host);
    473 
    474   window_tree_hosts_[new_primary_display.id()] = primary_host;
    475   GetRootWindowSettings(GetWindow(primary_host))->display_id =
    476       new_primary_display.id();
    477 
    478   window_tree_hosts_[old_primary_display.id()] = non_primary_host;
    479   GetRootWindowSettings(GetWindow(non_primary_host))->display_id =
    480       old_primary_display.id();
    481 
    482   primary_display_id = new_primary_display.id();
    483   GetDisplayManager()->layout_store()->UpdatePrimaryDisplayId(
    484       display_manager->GetCurrentDisplayIdPair(), primary_display_id);
    485 
    486   UpdateWorkAreaOfDisplayNearestWindow(GetWindow(primary_host),
    487                                        old_primary_display.GetWorkAreaInsets());
    488   UpdateWorkAreaOfDisplayNearestWindow(GetWindow(non_primary_host),
    489                                        new_primary_display.GetWorkAreaInsets());
    490 
    491   // Update the dispay manager with new display info.
    492   std::vector<DisplayInfo> display_info_list;
    493   display_info_list.push_back(display_manager->GetDisplayInfo(
    494       primary_display_id));
    495   display_info_list.push_back(display_manager->GetDisplayInfo(
    496       ScreenUtil::GetSecondaryDisplay().id()));
    497   GetDisplayManager()->set_force_bounds_changed(true);
    498   GetDisplayManager()->UpdateDisplays(display_info_list);
    499   GetDisplayManager()->set_force_bounds_changed(false);
    500 }
    501 
    502 void DisplayController::EnsurePointerInDisplays() {
    503   // If the mouse is currently on a display in native location,
    504   // use the same native location. Otherwise find the display closest
    505   // to the current cursor location in screen coordinates.
    506 
    507   gfx::Point point_in_screen = Shell::GetScreen()->GetCursorScreenPoint();
    508   gfx::Point target_location_in_native;
    509   int64 closest_distance_squared = -1;
    510   DisplayManager* display_manager = GetDisplayManager();
    511 
    512   aura::Window* dst_root_window = NULL;
    513   for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) {
    514     const gfx::Display& display = display_manager->GetDisplayAt(i);
    515     const DisplayInfo display_info =
    516         display_manager->GetDisplayInfo(display.id());
    517     aura::Window* root_window = GetRootWindowForDisplayId(display.id());
    518     if (display_info.bounds_in_native().Contains(
    519             cursor_location_in_native_coords_for_restore_)) {
    520       dst_root_window = root_window;
    521       target_location_in_native = cursor_location_in_native_coords_for_restore_;
    522       break;
    523     }
    524     gfx::Point center = display.bounds().CenterPoint();
    525     // Use the distance squared from the center of the dislay. This is not
    526     // exactly "closest" display, but good enough to pick one
    527     // appropriate (and there are at most two displays).
    528     // We don't care about actual distance, only relative to other displays, so
    529     // using the LengthSquared() is cheaper than Length().
    530 
    531     int64 distance_squared = (center - point_in_screen).LengthSquared();
    532     if (closest_distance_squared < 0 ||
    533         closest_distance_squared > distance_squared) {
    534       aura::Window* root_window = GetRootWindowForDisplayId(display.id());
    535       aura::client::ScreenPositionClient* client =
    536           aura::client::GetScreenPositionClient(root_window);
    537       client->ConvertPointFromScreen(root_window, &center);
    538       root_window->GetHost()->ConvertPointToNativeScreen(&center);
    539       dst_root_window = root_window;
    540       target_location_in_native = center;
    541       closest_distance_squared = distance_squared;
    542     }
    543   }
    544   dst_root_window->GetHost()->ConvertPointFromNativeScreen(
    545       &target_location_in_native);
    546   dst_root_window->MoveCursorTo(target_location_in_native);
    547 }
    548 
    549 bool DisplayController::UpdateWorkAreaOfDisplayNearestWindow(
    550     const aura::Window* window,
    551     const gfx::Insets& insets) {
    552   const aura::Window* root_window = window->GetRootWindow();
    553   int64 id = GetRootWindowSettings(root_window)->display_id;
    554   // if id is |kInvaildDisplayID|, it's being deleted.
    555   DCHECK(id != gfx::Display::kInvalidDisplayID);
    556   return GetDisplayManager()->UpdateWorkAreaOfDisplay(id, insets);
    557 }
    558 
    559 void DisplayController::OnDisplayAdded(const gfx::Display& display) {
    560   if (primary_tree_host_for_replace_) {
    561     DCHECK(window_tree_hosts_.empty());
    562     primary_display_id = display.id();
    563     window_tree_hosts_[display.id()] = primary_tree_host_for_replace_;
    564     GetRootWindowSettings(GetWindow(primary_tree_host_for_replace_))
    565         ->display_id = display.id();
    566     primary_tree_host_for_replace_ = NULL;
    567     const DisplayInfo& display_info =
    568         GetDisplayManager()->GetDisplayInfo(display.id());
    569     AshWindowTreeHost* ash_host = window_tree_hosts_[display.id()];
    570     ash_host->AsWindowTreeHost()->SetBounds(display_info.bounds_in_native());
    571     SetDisplayPropertiesOnHost(ash_host, display);
    572   } else {
    573     if (primary_display_id == gfx::Display::kInvalidDisplayID)
    574       primary_display_id = display.id();
    575     DCHECK(!window_tree_hosts_.empty());
    576     AshWindowTreeHost* ash_host = AddWindowTreeHostForDisplay(
    577         display, AshWindowTreeHostInitParams());
    578     RootWindowController::CreateForSecondaryDisplay(ash_host);
    579   }
    580 }
    581 
    582 void DisplayController::OnDisplayRemoved(const gfx::Display& display) {
    583   AshWindowTreeHost* host_to_delete = window_tree_hosts_[display.id()];
    584   CHECK(host_to_delete) << display.ToString();
    585 
    586   // Display for root window will be deleted when the Primary RootWindow
    587   // is deleted by the Shell.
    588   window_tree_hosts_.erase(display.id());
    589 
    590   // When the primary root window's display is removed, move the primary
    591   // root to the other display.
    592   if (primary_display_id == display.id()) {
    593     // Temporarily store the primary root window in
    594     // |primary_root_window_for_replace_| when replacing the display.
    595     if (window_tree_hosts_.size() == 0) {
    596       primary_display_id = gfx::Display::kInvalidDisplayID;
    597       primary_tree_host_for_replace_ = host_to_delete;
    598       return;
    599     }
    600     DCHECK_EQ(1U, window_tree_hosts_.size());
    601     primary_display_id = ScreenUtil::GetSecondaryDisplay().id();
    602     AshWindowTreeHost* primary_host = host_to_delete;
    603 
    604     // Delete the other host instead.
    605     host_to_delete = window_tree_hosts_[primary_display_id];
    606     GetRootWindowSettings(GetWindow(host_to_delete))->display_id = display.id();
    607 
    608     // Setup primary root.
    609     window_tree_hosts_[primary_display_id] = primary_host;
    610     GetRootWindowSettings(GetWindow(primary_host))->display_id =
    611         primary_display_id;
    612 
    613     OnDisplayMetricsChanged(
    614         GetDisplayManager()->GetDisplayForId(primary_display_id),
    615         DISPLAY_METRIC_BOUNDS);
    616   }
    617   RootWindowController* controller =
    618       GetRootWindowController(GetWindow(host_to_delete));
    619   DCHECK(controller);
    620   controller->MoveWindowsTo(GetPrimaryRootWindow());
    621   // Delete most of root window related objects, but don't delete
    622   // root window itself yet because the stack may be using it.
    623   controller->Shutdown();
    624   base::MessageLoop::current()->DeleteSoon(FROM_HERE, controller);
    625 }
    626 
    627 void DisplayController::OnDisplayMetricsChanged(const gfx::Display& display,
    628                                                 uint32_t metrics) {
    629   if (!(metrics & (DISPLAY_METRIC_BOUNDS | DISPLAY_METRIC_ROTATION |
    630                    DISPLAY_METRIC_DEVICE_SCALE_FACTOR)))
    631     return;
    632 
    633   const DisplayInfo& display_info =
    634       GetDisplayManager()->GetDisplayInfo(display.id());
    635   DCHECK(!display_info.bounds_in_native().IsEmpty());
    636   AshWindowTreeHost* ash_host = window_tree_hosts_[display.id()];
    637   ash_host->AsWindowTreeHost()->SetBounds(display_info.bounds_in_native());
    638   SetDisplayPropertiesOnHost(ash_host, display);
    639 }
    640 
    641 void DisplayController::OnHostResized(const aura::WindowTreeHost* host) {
    642   gfx::Display display = Shell::GetScreen()->GetDisplayNearestWindow(
    643       const_cast<aura::Window*>(host->window()));
    644 
    645   DisplayManager* display_manager = GetDisplayManager();
    646   if (display_manager->UpdateDisplayBounds(display.id(), host->GetBounds())) {
    647     mirror_window_controller_->UpdateWindow();
    648     cursor_window_controller_->UpdateContainer();
    649   }
    650 }
    651 
    652 void DisplayController::CreateOrUpdateNonDesktopDisplay(
    653     const DisplayInfo& info) {
    654   switch (GetDisplayManager()->second_display_mode()) {
    655     case DisplayManager::MIRRORING:
    656       mirror_window_controller_->UpdateWindow(info);
    657       cursor_window_controller_->UpdateContainer();
    658       virtual_keyboard_window_controller_->Close();
    659       break;
    660     case DisplayManager::VIRTUAL_KEYBOARD:
    661       mirror_window_controller_->Close();
    662       cursor_window_controller_->UpdateContainer();
    663       virtual_keyboard_window_controller_->UpdateWindow(info);
    664       break;
    665     case DisplayManager::EXTENDED:
    666       NOTREACHED();
    667   }
    668 }
    669 
    670 void DisplayController::CloseNonDesktopDisplay() {
    671   mirror_window_controller_->Close();
    672   cursor_window_controller_->UpdateContainer();
    673   virtual_keyboard_window_controller_->Close();
    674 }
    675 
    676 void DisplayController::PreDisplayConfigurationChange(bool clear_focus) {
    677   FOR_EACH_OBSERVER(Observer, observers_, OnDisplayConfigurationChanging());
    678   focus_activation_store_->Store(clear_focus);
    679   gfx::Screen* screen = Shell::GetScreen();
    680   gfx::Point point_in_screen = screen->GetCursorScreenPoint();
    681   gfx::Display display = screen->GetDisplayNearestPoint(point_in_screen);
    682   aura::Window* root_window = GetRootWindowForDisplayId(display.id());
    683 
    684   aura::client::ScreenPositionClient* client =
    685       aura::client::GetScreenPositionClient(root_window);
    686   client->ConvertPointFromScreen(root_window, &point_in_screen);
    687   root_window->GetHost()->ConvertPointToNativeScreen(&point_in_screen);
    688   cursor_location_in_native_coords_for_restore_ = point_in_screen;
    689 }
    690 
    691 void DisplayController::PostDisplayConfigurationChange() {
    692   if (limiter_)
    693     limiter_->SetThrottleTimeout(kAfterDisplayChangeThrottleTimeoutMs);
    694 
    695   focus_activation_store_->Restore();
    696 
    697   DisplayManager* display_manager = GetDisplayManager();
    698   DisplayLayoutStore* layout_store = display_manager->layout_store();
    699   if (display_manager->num_connected_displays() > 1) {
    700     DisplayIdPair pair = display_manager->GetCurrentDisplayIdPair();
    701     layout_store->UpdateMirrorStatus(pair, display_manager->IsMirrored());
    702     DisplayLayout layout = layout_store->GetRegisteredDisplayLayout(pair);
    703 
    704     if (Shell::GetScreen()->GetNumDisplays() > 1 ) {
    705       int64 primary_id = layout.primary_id;
    706       SetPrimaryDisplayId(
    707           primary_id == gfx::Display::kInvalidDisplayID ?
    708           pair.first : primary_id);
    709       // Update the primary_id in case the above call is
    710       // ignored. Happens when a) default layout's primary id
    711       // doesn't exist, or b) the primary_id has already been
    712       // set to the same and didn't update it.
    713       layout_store->UpdatePrimaryDisplayId(
    714           pair, Shell::GetScreen()->GetPrimaryDisplay().id());
    715     }
    716   }
    717   FOR_EACH_OBSERVER(Observer, observers_, OnDisplayConfigurationChanged());
    718   UpdateHostWindowNames();
    719   EnsurePointerInDisplays();
    720 }
    721 
    722 AshWindowTreeHost* DisplayController::AddWindowTreeHostForDisplay(
    723     const gfx::Display& display,
    724     const AshWindowTreeHostInitParams& init_params) {
    725   static int host_count = 0;
    726   const DisplayInfo& display_info =
    727       GetDisplayManager()->GetDisplayInfo(display.id());
    728   AshWindowTreeHostInitParams params_with_bounds(init_params);
    729   params_with_bounds.initial_bounds = display_info.bounds_in_native();
    730   AshWindowTreeHost* ash_host = AshWindowTreeHost::Create(params_with_bounds);
    731   aura::WindowTreeHost* host = ash_host->AsWindowTreeHost();
    732 
    733   host->window()->SetName(base::StringPrintf("RootWindow-%d", host_count++));
    734   host->window()->set_title(base::UTF8ToUTF16(display_info.name()));
    735   host->compositor()->SetBackgroundColor(SK_ColorBLACK);
    736   // No need to remove our observer observer because the DisplayController
    737   // outlives the host.
    738   host->AddObserver(this);
    739   InitRootWindowSettings(host->window())->display_id = display.id();
    740   host->InitHost();
    741 
    742   window_tree_hosts_[display.id()] = ash_host;
    743   SetDisplayPropertiesOnHost(ash_host, display);
    744 
    745 #if defined(OS_CHROMEOS)
    746   static bool force_constrain_pointer_to_root =
    747       CommandLine::ForCurrentProcess()->HasSwitch(
    748           switches::kAshConstrainPointerToRoot);
    749   if (base::SysInfo::IsRunningOnChromeOS() || force_constrain_pointer_to_root)
    750     ash_host->ConfineCursorToRootWindow();
    751 #endif
    752   return ash_host;
    753 }
    754 
    755 void DisplayController::OnFadeOutForSwapDisplayFinished() {
    756 #if defined(OS_CHROMEOS)
    757   SetPrimaryDisplay(ScreenUtil::GetSecondaryDisplay());
    758   Shell::GetInstance()->display_configurator_animation()
    759       ->StartFadeInAnimation();
    760 #endif
    761 }
    762 
    763 void DisplayController::SetMirrorModeAfterAnimation(bool mirror) {
    764   GetDisplayManager()->SetMirrorMode(mirror);
    765 }
    766 
    767 void DisplayController::UpdateHostWindowNames() {
    768 #if defined(USE_X11)
    769   // crbug.com/120229 - set the window title for the primary dislpay
    770   // to "aura_root_0" so gtalk can find the primary root window to broadcast.
    771   // TODO(jhorwich) Remove this once Chrome supports window-based broadcasting.
    772   aura::Window* primary = Shell::GetPrimaryRootWindow();
    773   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
    774   for (size_t i = 0; i < root_windows.size(); ++i) {
    775     std::string name =
    776         root_windows[i] == primary ? "aura_root_0" : "aura_root_x";
    777     gfx::AcceleratedWidget xwindow =
    778         root_windows[i]->GetHost()->GetAcceleratedWidget();
    779     XStoreName(gfx::GetXDisplay(), xwindow, name.c_str());
    780   }
    781 #endif
    782 }
    783 
    784 }  // namespace ash
    785