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/display_layout_store.h"
     13 #include "ash/display/display_manager.h"
     14 #include "ash/display/mirror_window_controller.h"
     15 #include "ash/display/root_window_transformers.h"
     16 #include "ash/host/root_window_host_factory.h"
     17 #include "ash/root_window_controller.h"
     18 #include "ash/screen_ash.h"
     19 #include "ash/shell.h"
     20 #include "ash/wm/coordinate_conversion.h"
     21 #include "ash/wm/property_util.h"
     22 #include "ash/wm/window_properties.h"
     23 #include "ash/wm/window_util.h"
     24 #include "base/command_line.h"
     25 #include "base/strings/stringprintf.h"
     26 #include "third_party/skia/include/utils/SkMatrix44.h"
     27 #include "ui/aura/client/activation_client.h"
     28 #include "ui/aura/client/capture_client.h"
     29 #include "ui/aura/client/cursor_client.h"
     30 #include "ui/aura/client/focus_client.h"
     31 #include "ui/aura/client/screen_position_client.h"
     32 #include "ui/aura/root_window.h"
     33 #include "ui/aura/root_window_transformer.h"
     34 #include "ui/aura/window.h"
     35 #include "ui/aura/window_property.h"
     36 #include "ui/aura/window_tracker.h"
     37 #include "ui/compositor/compositor.h"
     38 #include "ui/compositor/dip_util.h"
     39 #include "ui/gfx/display.h"
     40 #include "ui/gfx/screen.h"
     41 
     42 #if defined(OS_CHROMEOS)
     43 #include "base/chromeos/chromeos_version.h"
     44 #include "base/time/time.h"
     45 #if defined(USE_X11)
     46 #include "ash/display/output_configurator_animation.h"
     47 #include "chromeos/display/output_configurator.h"
     48 #include "ui/base/x/x11_util.h"
     49 
     50 // Including this at the bottom to avoid other
     51 // potential conflict with chrome headers.
     52 #include <X11/extensions/Xrandr.h>
     53 #undef RootWindow
     54 #endif  // defined(USE_X11)
     55 #endif  // defined(OS_CHROMEOS)
     56 
     57 DECLARE_WINDOW_PROPERTY_TYPE(int64);
     58 
     59 namespace ash {
     60 namespace {
     61 
     62 // Primary display stored in global object as it can be
     63 // accessed after Shell is deleted. A separate display instance is created
     64 // during the shutdown instead of always keeping two display instances
     65 // (one here and another one in display_manager) in sync, which is error prone.
     66 int64 primary_display_id = gfx::Display::kInvalidDisplayID;
     67 gfx::Display* primary_display_for_shutdown = NULL;
     68 // Keeps the number of displays during the shutdown after
     69 // ash::Shell:: is deleted.
     70 int num_displays_for_shutdown = -1;
     71 
     72 // Specifies how long the display change should have been disabled
     73 // after each display change operations.
     74 // |kCycleDisplayThrottleTimeoutMs| is set to be longer to avoid
     75 // changing the settings while the system is still configurating
     76 // displays. It will be overriden by |kAfterDisplayChangeThrottleTimeoutMs|
     77 // when the display change happens, so the actual timeout is much shorter.
     78 const int64 kAfterDisplayChangeThrottleTimeoutMs = 500;
     79 const int64 kCycleDisplayThrottleTimeoutMs = 4000;
     80 const int64 kSwapDisplayThrottleTimeoutMs = 500;
     81 
     82 internal::DisplayManager* GetDisplayManager() {
     83   return Shell::GetInstance()->display_manager();
     84 }
     85 
     86 void SetDisplayPropertiesOnHostWindow(aura::RootWindow* root,
     87                                       const gfx::Display& display) {
     88   internal::DisplayInfo info =
     89       GetDisplayManager()->GetDisplayInfo(display.id());
     90 #if defined(OS_CHROMEOS) && defined(USE_X11)
     91   // Native window property (Atom in X11) that specifies the display's
     92   // rotation, scale factor and if it's internal display.  They are
     93   // read and used by touchpad/mouse driver directly on X (contact
     94   // adlr@ for more details on touchpad/mouse driver side). The value
     95   // of the rotation is one of 0 (normal), 1 (90 degrees clockwise), 2
     96   // (180 degree) or 3 (270 degrees clockwise).  The value of the
     97   // scale factor is in percent (100, 140, 200 etc).
     98   const char kRotationProp[] = "_CHROME_DISPLAY_ROTATION";
     99   const char kScaleFactorProp[] = "_CHROME_DISPLAY_SCALE_FACTOR";
    100   const char kInternalProp[] = "_CHROME_DISPLAY_INTERNAL";
    101   const char kCARDINAL[] = "CARDINAL";
    102   int xrandr_rotation = RR_Rotate_0;
    103   switch (info.rotation()) {
    104     case gfx::Display::ROTATE_0:
    105       xrandr_rotation = RR_Rotate_0;
    106       break;
    107     case gfx::Display::ROTATE_90:
    108       xrandr_rotation = RR_Rotate_90;
    109       break;
    110     case gfx::Display::ROTATE_180:
    111       xrandr_rotation = RR_Rotate_180;
    112       break;
    113     case gfx::Display::ROTATE_270:
    114       xrandr_rotation = RR_Rotate_270;
    115       break;
    116   }
    117 
    118   int internal = display.IsInternal() ? 1 : 0;
    119   gfx::AcceleratedWidget xwindow = root->GetAcceleratedWidget();
    120   ui::SetIntProperty(xwindow, kInternalProp, kCARDINAL, internal);
    121   ui::SetIntProperty(xwindow, kRotationProp, kCARDINAL, xrandr_rotation);
    122   ui::SetIntProperty(xwindow,
    123                      kScaleFactorProp,
    124                      kCARDINAL,
    125                      100 * display.device_scale_factor());
    126 #endif
    127   scoped_ptr<aura::RootWindowTransformer> transformer(
    128       internal::CreateRootWindowTransformerForDisplay(root, display));
    129   root->SetRootWindowTransformer(transformer.Pass());
    130 }
    131 
    132 }  // namespace
    133 
    134 namespace internal {
    135 
    136 DEFINE_WINDOW_PROPERTY_KEY(int64, kDisplayIdKey,
    137                            gfx::Display::kInvalidDisplayID);
    138 
    139 // A utility class to store/restore focused/active window
    140 // when the display configuration has changed.
    141 class FocusActivationStore {
    142  public:
    143   FocusActivationStore()
    144       : activation_client_(NULL),
    145         capture_client_(NULL),
    146         focus_client_(NULL),
    147         focused_(NULL),
    148         active_(NULL) {
    149   }
    150 
    151   void Store() {
    152     if (!activation_client_) {
    153       aura::RootWindow* root = Shell::GetPrimaryRootWindow();
    154       activation_client_ = aura::client::GetActivationClient(root);
    155       capture_client_ = aura::client::GetCaptureClient(root);
    156       focus_client_ = aura::client::GetFocusClient(root);
    157     }
    158     focused_ = focus_client_->GetFocusedWindow();
    159     if (focused_)
    160       tracker_.Add(focused_);
    161     active_ = activation_client_->GetActiveWindow();
    162     if (active_ && focused_ != active_)
    163       tracker_.Add(active_);
    164 
    165     // Deactivate the window to close menu / bubble windows.
    166     activation_client_->DeactivateWindow(active_);
    167     // Release capture if any.
    168     capture_client_->SetCapture(NULL);
    169     // Clear the focused window if any. This is necessary because a
    170     // window may be deleted when losing focus (fullscreen flash for
    171     // example).  If the focused window is still alive after move, it'll
    172     // be re-focused below.
    173     focus_client_->FocusWindow(NULL);
    174   }
    175 
    176   void Restore() {
    177     // Restore focused or active window if it's still alive.
    178     if (focused_ && tracker_.Contains(focused_)) {
    179       focus_client_->FocusWindow(focused_);
    180     } else if (active_ && tracker_.Contains(active_)) {
    181       activation_client_->ActivateWindow(active_);
    182     }
    183     if (focused_)
    184       tracker_.Remove(focused_);
    185     if (active_)
    186       tracker_.Remove(active_);
    187     focused_ = NULL;
    188     active_ = NULL;
    189   }
    190 
    191  private:
    192   aura::client::ActivationClient* activation_client_;
    193   aura::client::CaptureClient* capture_client_;
    194   aura::client::FocusClient* focus_client_;
    195   aura::WindowTracker tracker_;
    196   aura::Window* focused_;
    197   aura::Window* active_;
    198 
    199   DISALLOW_COPY_AND_ASSIGN(FocusActivationStore);
    200 };
    201 
    202 }  // namespace internal
    203 
    204 ////////////////////////////////////////////////////////////////////////////////
    205 // DisplayChangeLimiter
    206 
    207 DisplayController::DisplayChangeLimiter::DisplayChangeLimiter()
    208     : throttle_timeout_(base::Time::Now()) {
    209 }
    210 
    211 void DisplayController::DisplayChangeLimiter::SetThrottleTimeout(
    212     int64 throttle_ms) {
    213   throttle_timeout_ =
    214       base::Time::Now() + base::TimeDelta::FromMilliseconds(throttle_ms);
    215 }
    216 
    217 bool DisplayController::DisplayChangeLimiter::IsThrottled() const {
    218   return base::Time::Now() < throttle_timeout_;
    219 }
    220 
    221 ////////////////////////////////////////////////////////////////////////////////
    222 // DisplayController
    223 
    224 DisplayController::DisplayController()
    225     : primary_root_window_for_replace_(NULL),
    226       focus_activation_store_(new internal::FocusActivationStore()),
    227       mirror_window_controller_(new internal::MirrorWindowController) {
    228   CommandLine* command_line = CommandLine::ForCurrentProcess();
    229 #if defined(OS_CHROMEOS)
    230   if (!command_line->HasSwitch(switches::kAshDisableDisplayChangeLimiter) &&
    231       base::chromeos::IsRunningOnChromeOS())
    232     limiter_.reset(new DisplayChangeLimiter);
    233 #endif
    234   // Reset primary display to make sure that tests don't use
    235   // stale display info from previous tests.
    236   primary_display_id = gfx::Display::kInvalidDisplayID;
    237   delete primary_display_for_shutdown;
    238   primary_display_for_shutdown = NULL;
    239   num_displays_for_shutdown = -1;
    240 }
    241 
    242 DisplayController::~DisplayController() {
    243   DCHECK(primary_display_for_shutdown);
    244 }
    245 
    246 void DisplayController::Start() {
    247   Shell::GetScreen()->AddObserver(this);
    248   Shell::GetInstance()->display_manager()->set_delegate(this);
    249 }
    250 
    251 void DisplayController::Shutdown() {
    252   // Unset the display manager's delegate here because
    253   // DisplayManager outlives DisplayController.
    254   Shell::GetInstance()->display_manager()->set_delegate(NULL);
    255 
    256   mirror_window_controller_.reset();
    257 
    258   DCHECK(!primary_display_for_shutdown);
    259   primary_display_for_shutdown = new gfx::Display(
    260       GetDisplayManager()->GetDisplayForId(primary_display_id));
    261   num_displays_for_shutdown = GetDisplayManager()->GetNumDisplays();
    262 
    263   Shell::GetScreen()->RemoveObserver(this);
    264   // Delete all root window controllers, which deletes root window
    265   // from the last so that the primary root window gets deleted last.
    266   for (std::map<int64, aura::RootWindow*>::const_reverse_iterator it =
    267            root_windows_.rbegin(); it != root_windows_.rend(); ++it) {
    268     internal::RootWindowController* controller =
    269         GetRootWindowController(it->second);
    270     DCHECK(controller);
    271     delete controller;
    272   }
    273 }
    274 
    275 // static
    276 const gfx::Display& DisplayController::GetPrimaryDisplay() {
    277   DCHECK_NE(primary_display_id, gfx::Display::kInvalidDisplayID);
    278   if (primary_display_for_shutdown)
    279     return *primary_display_for_shutdown;
    280   return GetDisplayManager()->GetDisplayForId(primary_display_id);
    281 }
    282 
    283 // static
    284 int DisplayController::GetNumDisplays() {
    285   if (num_displays_for_shutdown >= 0)
    286     return num_displays_for_shutdown;
    287   return GetDisplayManager()->GetNumDisplays();
    288 }
    289 
    290 void DisplayController::InitPrimaryDisplay() {
    291   const gfx::Display* primary_candidate =
    292       GetDisplayManager()->GetPrimaryDisplayCandidate();
    293   primary_display_id = primary_candidate->id();
    294   AddRootWindowForDisplay(*primary_candidate);
    295 }
    296 
    297 void DisplayController::InitSecondaryDisplays() {
    298   internal::DisplayManager* display_manager = GetDisplayManager();
    299   UpdateDisplayBoundsForLayout();
    300   for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) {
    301     const gfx::Display& display = display_manager->GetDisplayAt(i);
    302     if (primary_display_id != display.id()) {
    303       aura::RootWindow* root = AddRootWindowForDisplay(display);
    304       Shell::GetInstance()->InitRootWindowForSecondaryDisplay(root);
    305     }
    306   }
    307   if (display_manager->GetNumDisplays() > 1) {
    308     DisplayIdPair pair = GetCurrentDisplayIdPair();
    309     DisplayLayout layout = GetCurrentDisplayLayout();
    310     SetPrimaryDisplayId(
    311         layout.primary_id == gfx::Display::kInvalidDisplayID ?
    312         pair.first : layout.primary_id);
    313   }
    314   UpdateHostWindowNames();
    315 }
    316 
    317 void DisplayController::AddObserver(Observer* observer) {
    318   observers_.AddObserver(observer);
    319 }
    320 
    321 void DisplayController::RemoveObserver(Observer* observer) {
    322   observers_.RemoveObserver(observer);
    323 }
    324 
    325 aura::RootWindow* DisplayController::GetPrimaryRootWindow() {
    326   DCHECK(!root_windows_.empty());
    327   return root_windows_[primary_display_id];
    328 }
    329 
    330 aura::RootWindow* DisplayController::GetRootWindowForDisplayId(int64 id) {
    331   return root_windows_[id];
    332 }
    333 
    334 void DisplayController::CloseChildWindows() {
    335   for (std::map<int64, aura::RootWindow*>::const_iterator it =
    336            root_windows_.begin(); it != root_windows_.end(); ++it) {
    337     aura::RootWindow* root_window = it->second;
    338     internal::RootWindowController* controller =
    339         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 std::vector<aura::RootWindow*> DisplayController::GetAllRootWindows() {
    352   std::vector<aura::RootWindow*> windows;
    353   for (std::map<int64, aura::RootWindow*>::const_iterator it =
    354            root_windows_.begin(); it != root_windows_.end(); ++it) {
    355     DCHECK(it->second);
    356     if (GetRootWindowController(it->second))
    357       windows.push_back(it->second);
    358   }
    359   return windows;
    360 }
    361 
    362 gfx::Insets DisplayController::GetOverscanInsets(int64 display_id) const {
    363   return GetDisplayManager()->GetOverscanInsets(display_id);
    364 }
    365 
    366 void DisplayController::SetOverscanInsets(int64 display_id,
    367                                           const gfx::Insets& insets_in_dip) {
    368   GetDisplayManager()->SetOverscanInsets(display_id, insets_in_dip);
    369 }
    370 
    371 std::vector<internal::RootWindowController*>
    372 DisplayController::GetAllRootWindowControllers() {
    373   std::vector<internal::RootWindowController*> controllers;
    374   for (std::map<int64, aura::RootWindow*>::const_iterator it =
    375            root_windows_.begin(); it != root_windows_.end(); ++it) {
    376     internal::RootWindowController* controller =
    377         GetRootWindowController(it->second);
    378     if (controller)
    379       controllers.push_back(controller);
    380   }
    381   return controllers;
    382 }
    383 
    384 void DisplayController::SetLayoutForCurrentDisplays(
    385     const DisplayLayout& layout_relative_to_primary) {
    386   DCHECK_EQ(2U, GetDisplayManager()->GetNumDisplays());
    387   if (GetDisplayManager()->GetNumDisplays() < 2)
    388     return;
    389   const gfx::Display& primary = GetPrimaryDisplay();
    390   const DisplayIdPair pair = GetCurrentDisplayIdPair();
    391   // Invert if the primary was swapped.
    392   DisplayLayout to_set = pair.first == primary.id() ?
    393       layout_relative_to_primary : layout_relative_to_primary.Invert();
    394 
    395   internal::DisplayLayoutStore* layout_store =
    396       GetDisplayManager()->layout_store();
    397   DisplayLayout current_layout =
    398       layout_store->GetRegisteredDisplayLayout(pair);
    399   if (to_set.position != current_layout.position ||
    400       to_set.offset != current_layout.offset) {
    401     to_set.primary_id = primary.id();
    402     layout_store->RegisterLayoutForDisplayIdPair(
    403         pair.first, pair.second, to_set);
    404     PreDisplayConfigurationChange();
    405     // TODO(oshima): Call UpdateDisplays instead.
    406     UpdateDisplayBoundsForLayout();
    407     // Primary's bounds stay the same. Just notify bounds change
    408     // on the secondary.
    409     Shell::GetInstance()->screen()->NotifyBoundsChanged(
    410         ScreenAsh::GetSecondaryDisplay());
    411     PostDisplayConfigurationChange();
    412   }
    413 }
    414 
    415 DisplayLayout DisplayController::GetCurrentDisplayLayout() {
    416   DCHECK_EQ(2U, GetDisplayManager()->num_connected_displays());
    417   // Invert if the primary was swapped.
    418   if (GetDisplayManager()->num_connected_displays() > 1) {
    419     DisplayIdPair pair = GetCurrentDisplayIdPair();
    420     return GetDisplayManager()->layout_store()->
    421         ComputeDisplayLayoutForDisplayIdPair(pair);
    422   }
    423   NOTREACHED() << "DisplayLayout is requested for single display";
    424   // On release build, just fallback to default instead of blowing up.
    425   DisplayLayout layout =
    426       GetDisplayManager()->layout_store()->default_display_layout();
    427   layout.primary_id = primary_display_id;
    428   return layout;
    429 }
    430 
    431 DisplayIdPair DisplayController::GetCurrentDisplayIdPair() const {
    432   internal::DisplayManager* display_manager = GetDisplayManager();
    433   const gfx::Display& primary = GetPrimaryDisplay();
    434   if (display_manager->IsMirrored()) {
    435     return std::make_pair(primary.id(),
    436                           display_manager->mirrored_display().id());
    437   }
    438 
    439   const gfx::Display& secondary = ScreenAsh::GetSecondaryDisplay();
    440   if (primary.IsInternal() ||
    441       GetDisplayManager()->first_display_id() == primary.id()) {
    442     return std::make_pair(primary.id(), secondary.id());
    443   } else {
    444     // Display has been Swapped.
    445     return std::make_pair(secondary.id(), primary.id());
    446   }
    447 }
    448 
    449 void DisplayController::ToggleMirrorMode() {
    450   internal::DisplayManager* display_manager = GetDisplayManager();
    451   if (display_manager->num_connected_displays() <= 1)
    452     return;
    453 
    454   if (limiter_) {
    455     if  (limiter_->IsThrottled())
    456       return;
    457     limiter_->SetThrottleTimeout(kCycleDisplayThrottleTimeoutMs);
    458   }
    459 #if defined(OS_CHROMEOS) && defined(USE_X11)
    460   Shell* shell = Shell::GetInstance();
    461   internal::OutputConfiguratorAnimation* animation =
    462       shell->output_configurator_animation();
    463   animation->StartFadeOutAnimation(base::Bind(
    464       base::IgnoreResult(&internal::DisplayManager::SetMirrorMode),
    465       base::Unretained(display_manager),
    466       !display_manager->IsMirrored()));
    467 #endif
    468 }
    469 
    470 void DisplayController::SwapPrimaryDisplay() {
    471   if (limiter_) {
    472     if  (limiter_->IsThrottled())
    473       return;
    474     limiter_->SetThrottleTimeout(kSwapDisplayThrottleTimeoutMs);
    475   }
    476 
    477   if (Shell::GetScreen()->GetNumDisplays() > 1) {
    478 #if defined(OS_CHROMEOS) && defined(USE_X11)
    479     internal::OutputConfiguratorAnimation* animation =
    480         Shell::GetInstance()->output_configurator_animation();
    481     if (animation) {
    482       animation->StartFadeOutAnimation(base::Bind(
    483           &DisplayController::OnFadeOutForSwapDisplayFinished,
    484           base::Unretained(this)));
    485     } else {
    486       SetPrimaryDisplay(ScreenAsh::GetSecondaryDisplay());
    487     }
    488 #else
    489     SetPrimaryDisplay(ScreenAsh::GetSecondaryDisplay());
    490 #endif
    491   }
    492 }
    493 
    494 void DisplayController::SetPrimaryDisplayId(int64 id) {
    495   DCHECK_NE(gfx::Display::kInvalidDisplayID, id);
    496   if (id == gfx::Display::kInvalidDisplayID || primary_display_id == id)
    497     return;
    498 
    499   const gfx::Display& display = GetDisplayManager()->GetDisplayForId(id);
    500   if (display.is_valid())
    501     SetPrimaryDisplay(display);
    502 }
    503 
    504 void DisplayController::SetPrimaryDisplay(
    505     const gfx::Display& new_primary_display) {
    506   internal::DisplayManager* display_manager = GetDisplayManager();
    507   DCHECK(new_primary_display.is_valid());
    508   DCHECK(display_manager->IsActiveDisplay(new_primary_display));
    509 
    510   if (!new_primary_display.is_valid() ||
    511       !display_manager->IsActiveDisplay(new_primary_display)) {
    512     LOG(ERROR) << "Invalid or non-existent display is requested:"
    513                << new_primary_display.ToString();
    514     return;
    515   }
    516 
    517   if (primary_display_id == new_primary_display.id() ||
    518       root_windows_.size() < 2) {
    519     return;
    520   }
    521 
    522   aura::RootWindow* non_primary_root = root_windows_[new_primary_display.id()];
    523   LOG_IF(ERROR, !non_primary_root)
    524       << "Unknown display is requested in SetPrimaryDisplay: id="
    525       << new_primary_display.id();
    526   if (!non_primary_root)
    527     return;
    528 
    529   gfx::Display old_primary_display = GetPrimaryDisplay();
    530 
    531   // Swap root windows between current and new primary display.
    532   aura::RootWindow* primary_root = root_windows_[primary_display_id];
    533   DCHECK(primary_root);
    534   DCHECK_NE(primary_root, non_primary_root);
    535 
    536   root_windows_[new_primary_display.id()] = primary_root;
    537   primary_root->SetProperty(internal::kDisplayIdKey, new_primary_display.id());
    538 
    539   root_windows_[old_primary_display.id()] = non_primary_root;
    540   non_primary_root->SetProperty(internal::kDisplayIdKey,
    541                                 old_primary_display.id());
    542 
    543   primary_display_id = new_primary_display.id();
    544   GetDisplayManager()->layout_store()->UpdatePrimaryDisplayId(
    545       GetCurrentDisplayIdPair(), primary_display_id);
    546 
    547   UpdateWorkAreaOfDisplayNearestWindow(
    548       primary_root, old_primary_display.GetWorkAreaInsets());
    549   UpdateWorkAreaOfDisplayNearestWindow(
    550       non_primary_root, new_primary_display.GetWorkAreaInsets());
    551 
    552   // Update the dispay manager with new display info.
    553   std::vector<internal::DisplayInfo> display_info_list;
    554   display_info_list.push_back(display_manager->GetDisplayInfo(
    555       primary_display_id));
    556   display_info_list.push_back(display_manager->GetDisplayInfo(
    557       ScreenAsh::GetSecondaryDisplay().id()));
    558   GetDisplayManager()->set_force_bounds_changed(true);
    559   GetDisplayManager()->UpdateDisplays(display_info_list);
    560   GetDisplayManager()->set_force_bounds_changed(false);
    561 }
    562 
    563 void DisplayController::EnsurePointerInDisplays() {
    564   // If the mouse is currently on a display in native location,
    565   // use the same native location. Otherwise find the display closest
    566   // to the current cursor location in screen coordinates.
    567 
    568   gfx::Point point_in_screen = Shell::GetScreen()->GetCursorScreenPoint();
    569   gfx::Point target_location_in_native;
    570   int64 closest_distance_squared = -1;
    571   internal::DisplayManager* display_manager = GetDisplayManager();
    572 
    573   aura::RootWindow* dst_root_window = NULL;
    574   for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) {
    575     const gfx::Display& display = display_manager->GetDisplayAt(i);
    576     const internal::DisplayInfo display_info =
    577         display_manager->GetDisplayInfo(display.id());
    578     aura::RootWindow* root_window = GetRootWindowForDisplayId(display.id());
    579     if (display_info.bounds_in_pixel().Contains(
    580             cursor_location_in_native_coords_for_restore_)) {
    581       dst_root_window = root_window;
    582       target_location_in_native = cursor_location_in_native_coords_for_restore_;
    583       break;
    584     }
    585     gfx::Point center = display.bounds().CenterPoint();
    586     // Use the distance squared from the center of the dislay. This is not
    587     // exactly "closest" display, but good enough to pick one
    588     // appropriate (and there are at most two displays).
    589     // We don't care about actual distance, only relative to other displays, so
    590     // using the LengthSquared() is cheaper than Length().
    591 
    592     int64 distance_squared = (center - point_in_screen).LengthSquared();
    593     if (closest_distance_squared < 0 ||
    594         closest_distance_squared > distance_squared) {
    595       aura::RootWindow* root_window = GetRootWindowForDisplayId(display.id());
    596       aura::client::ScreenPositionClient* client =
    597           aura::client::GetScreenPositionClient(root_window);
    598       client->ConvertPointFromScreen(root_window, &center);
    599       root_window->ConvertPointToNativeScreen(&center);
    600       dst_root_window = root_window;
    601       target_location_in_native = center;
    602       closest_distance_squared = distance_squared;
    603     }
    604   }
    605   dst_root_window->ConvertPointFromNativeScreen(&target_location_in_native);
    606   dst_root_window->MoveCursorTo(target_location_in_native);
    607 }
    608 
    609 bool DisplayController::UpdateWorkAreaOfDisplayNearestWindow(
    610     const aura::Window* window,
    611     const gfx::Insets& insets) {
    612   const aura::RootWindow* root_window = window->GetRootWindow();
    613   int64 id = root_window->GetProperty(internal::kDisplayIdKey);
    614   // if id is |kInvaildDisplayID|, it's being deleted.
    615   DCHECK(id != gfx::Display::kInvalidDisplayID);
    616   return GetDisplayManager()->UpdateWorkAreaOfDisplay(id, insets);
    617 }
    618 
    619 const gfx::Display& DisplayController::GetDisplayNearestWindow(
    620     const aura::Window* window) const {
    621   if (!window)
    622     return GetPrimaryDisplay();
    623   const aura::RootWindow* root_window = window->GetRootWindow();
    624   if (!root_window)
    625     return GetPrimaryDisplay();
    626   int64 id = root_window->GetProperty(internal::kDisplayIdKey);
    627   // if id is |kInvaildDisplayID|, it's being deleted.
    628   DCHECK(id != gfx::Display::kInvalidDisplayID);
    629 
    630   internal::DisplayManager* display_manager = GetDisplayManager();
    631   // RootWindow needs Display to determine its device scale factor.
    632   // TODO(oshima): We don't need full display info for mirror
    633   // window. Refactor so that RootWindow doesn't use it.
    634   if (display_manager->mirrored_display().id() == id)
    635     return display_manager->mirrored_display();
    636 
    637   return display_manager->GetDisplayForId(id);
    638 }
    639 
    640 const gfx::Display& DisplayController::GetDisplayNearestPoint(
    641     const gfx::Point& point) const {
    642   // Fallback to the primary display if there is no root display containing
    643   // the |point|.
    644   const gfx::Display& display =
    645       GetDisplayManager()->FindDisplayContainingPoint(point);
    646   return display.is_valid() ? display : GetPrimaryDisplay();
    647 }
    648 
    649 const gfx::Display& DisplayController::GetDisplayMatching(
    650     const gfx::Rect& rect) const {
    651   if (rect.IsEmpty())
    652     return GetDisplayNearestPoint(rect.origin());
    653 
    654   int max_area = 0;
    655   const gfx::Display* matching = NULL;
    656   for (size_t i = 0; i < GetDisplayManager()->GetNumDisplays(); ++i) {
    657     const gfx::Display& display = GetDisplayManager()->GetDisplayAt(i);
    658     gfx::Rect intersect = gfx::IntersectRects(display.bounds(), rect);
    659     int area = intersect.width() * intersect.height();
    660     if (area > max_area) {
    661       max_area = area;
    662       matching = &display;
    663     }
    664   }
    665   // Fallback to the primary display if there is no matching display.
    666   return matching ? *matching : GetPrimaryDisplay();
    667 }
    668 
    669 void DisplayController::OnDisplayBoundsChanged(const gfx::Display& display) {
    670   const internal::DisplayInfo& display_info =
    671       GetDisplayManager()->GetDisplayInfo(display.id());
    672   DCHECK(!display_info.bounds_in_pixel().IsEmpty());
    673   aura::RootWindow* root = root_windows_[display.id()];
    674   root->SetHostBounds(display_info.bounds_in_pixel());
    675   SetDisplayPropertiesOnHostWindow(root, display);
    676 }
    677 
    678 void DisplayController::OnDisplayAdded(const gfx::Display& display) {
    679   if (primary_root_window_for_replace_) {
    680     DCHECK(root_windows_.empty());
    681     primary_display_id = display.id();
    682     root_windows_[display.id()] = primary_root_window_for_replace_;
    683     primary_root_window_for_replace_->SetProperty(
    684         internal::kDisplayIdKey, display.id());
    685     primary_root_window_for_replace_ = NULL;
    686     const internal::DisplayInfo& display_info =
    687         GetDisplayManager()->GetDisplayInfo(display.id());
    688     root_windows_[display.id()]->SetHostBounds(
    689         display_info.bounds_in_pixel());
    690   } else {
    691     if (primary_display_id == gfx::Display::kInvalidDisplayID)
    692       primary_display_id = display.id();
    693     DCHECK(!root_windows_.empty());
    694     aura::RootWindow* root = AddRootWindowForDisplay(display);
    695     Shell::GetInstance()->InitRootWindowForSecondaryDisplay(root);
    696   }
    697 }
    698 
    699 void DisplayController::OnDisplayRemoved(const gfx::Display& display) {
    700   aura::RootWindow* root_to_delete = root_windows_[display.id()];
    701   DCHECK(root_to_delete) << display.ToString();
    702 
    703   // Display for root window will be deleted when the Primary RootWindow
    704   // is deleted by the Shell.
    705   root_windows_.erase(display.id());
    706 
    707   // When the primary root window's display is removed, move the primary
    708   // root to the other display.
    709   if (primary_display_id == display.id()) {
    710     // Temporarily store the primary root window in
    711     // |primary_root_window_for_replace_| when replacing the display.
    712     if (root_windows_.size() == 0) {
    713       primary_display_id = gfx::Display::kInvalidDisplayID;
    714       primary_root_window_for_replace_ = root_to_delete;
    715       return;
    716     }
    717     DCHECK_EQ(1U, root_windows_.size());
    718     primary_display_id = ScreenAsh::GetSecondaryDisplay().id();
    719     aura::RootWindow* primary_root = root_to_delete;
    720 
    721     // Delete the other root instead.
    722     root_to_delete = root_windows_[primary_display_id];
    723     root_to_delete->SetProperty(internal::kDisplayIdKey, display.id());
    724 
    725     // Setup primary root.
    726     root_windows_[primary_display_id] = primary_root;
    727     primary_root->SetProperty(internal::kDisplayIdKey, primary_display_id);
    728 
    729     OnDisplayBoundsChanged(
    730         GetDisplayManager()->GetDisplayForId(primary_display_id));
    731   }
    732   internal::RootWindowController* controller =
    733       GetRootWindowController(root_to_delete);
    734   DCHECK(controller);
    735   controller->MoveWindowsTo(GetPrimaryRootWindow());
    736   // Delete most of root window related objects, but don't delete
    737   // root window itself yet because the stack may be using it.
    738   controller->Shutdown();
    739   base::MessageLoop::current()->DeleteSoon(FROM_HERE, controller);
    740 }
    741 
    742 void DisplayController::OnRootWindowHostResized(const aura::RootWindow* root) {
    743   internal::DisplayManager* display_manager = GetDisplayManager();
    744   gfx::Display display = GetDisplayNearestWindow(root);
    745   if (display_manager->UpdateDisplayBounds(
    746           display.id(),
    747           gfx::Rect(root->GetHostOrigin(), root->GetHostSize()))) {
    748     mirror_window_controller_->UpdateWindow();
    749   }
    750 }
    751 
    752 void DisplayController::CreateOrUpdateMirrorWindow(
    753     const internal::DisplayInfo& info) {
    754   mirror_window_controller_->UpdateWindow(info);
    755 }
    756 
    757 void DisplayController::CloseMirrorWindow() {
    758   mirror_window_controller_->Close();
    759 }
    760 
    761 void DisplayController::PreDisplayConfigurationChange() {
    762   FOR_EACH_OBSERVER(Observer, observers_, OnDisplayConfigurationChanging());
    763   focus_activation_store_->Store();
    764 
    765   gfx::Point point_in_screen = Shell::GetScreen()->GetCursorScreenPoint();
    766   gfx::Display display =
    767       Shell::GetScreen()->GetDisplayNearestPoint(point_in_screen);
    768   aura::RootWindow* root_window = GetRootWindowForDisplayId(display.id());
    769 
    770   aura::client::ScreenPositionClient* client =
    771       aura::client::GetScreenPositionClient(root_window);
    772   client->ConvertPointFromScreen(root_window, &point_in_screen);
    773   root_window->ConvertPointToNativeScreen(&point_in_screen);
    774   cursor_location_in_native_coords_for_restore_ = point_in_screen;
    775 }
    776 
    777 void DisplayController::PostDisplayConfigurationChange() {
    778   if (limiter_)
    779     limiter_->SetThrottleTimeout(kAfterDisplayChangeThrottleTimeoutMs);
    780 
    781   focus_activation_store_->Restore();
    782 
    783   internal::DisplayManager* display_manager = GetDisplayManager();
    784   internal::DisplayLayoutStore* layout_store = display_manager->layout_store();
    785   if (display_manager->num_connected_displays() > 1) {
    786     DisplayIdPair pair = GetCurrentDisplayIdPair();
    787     layout_store->UpdateMirrorStatus(pair, display_manager->IsMirrored());
    788     DisplayLayout layout = layout_store->GetRegisteredDisplayLayout(pair);
    789 
    790     if (Shell::GetScreen()->GetNumDisplays() > 1 ) {
    791       int64 primary_id = layout.primary_id;
    792       SetPrimaryDisplayId(
    793           primary_id == gfx::Display::kInvalidDisplayID ?
    794           pair.first : primary_id);
    795       // Update the primary_id in case the above call is
    796       // ignored. Happens when a) default layout's primary id
    797       // doesn't exist, or b) the primary_id has already been
    798       // set to the same and didn't update it.
    799       layout_store->UpdatePrimaryDisplayId(pair, GetPrimaryDisplay().id());
    800     }
    801   }
    802   FOR_EACH_OBSERVER(Observer, observers_, OnDisplayConfigurationChanged());
    803   UpdateHostWindowNames();
    804   EnsurePointerInDisplays();
    805 }
    806 
    807 aura::RootWindow* DisplayController::AddRootWindowForDisplay(
    808     const gfx::Display& display) {
    809   static int root_window_count = 0;
    810   const internal::DisplayInfo& display_info =
    811       GetDisplayManager()->GetDisplayInfo(display.id());
    812   const gfx::Rect& bounds_in_pixel = display_info.bounds_in_pixel();
    813   aura::RootWindow::CreateParams params(bounds_in_pixel);
    814   params.host = Shell::GetInstance()->root_window_host_factory()->
    815       CreateRootWindowHost(bounds_in_pixel);
    816   aura::RootWindow* root_window = new aura::RootWindow(params);
    817   root_window->SetName(
    818       base::StringPrintf("RootWindow-%d", root_window_count++));
    819   root_window->compositor()->SetBackgroundColor(SK_ColorBLACK);
    820   // No need to remove RootWindowObserver because
    821   // the DisplayController object outlives RootWindow objects.
    822   root_window->AddRootWindowObserver(this);
    823   root_window->SetProperty(internal::kDisplayIdKey, display.id());
    824   root_window->Init();
    825 
    826   root_windows_[display.id()] = root_window;
    827   SetDisplayPropertiesOnHostWindow(root_window, display);
    828 
    829 #if defined(OS_CHROMEOS)
    830   static bool force_constrain_pointer_to_root =
    831       CommandLine::ForCurrentProcess()->HasSwitch(
    832           switches::kAshConstrainPointerToRoot);
    833   if (base::chromeos::IsRunningOnChromeOS() || force_constrain_pointer_to_root)
    834     root_window->ConfineCursorToWindow();
    835 #endif
    836   return root_window;
    837 }
    838 
    839 void DisplayController::UpdateDisplayBoundsForLayout() {
    840   if (Shell::GetScreen()->GetNumDisplays() < 2 ||
    841       GetDisplayManager()->num_connected_displays() < 2) {
    842     return;
    843   }
    844   DCHECK_EQ(2, Shell::GetScreen()->GetNumDisplays());
    845 
    846   const DisplayLayout layout = GetCurrentDisplayLayout();
    847   Shell::GetInstance()->display_manager()->UpdateDisplayBoundsForLayoutById(
    848       layout, GetPrimaryDisplay(),
    849       ScreenAsh::GetSecondaryDisplay().id());
    850 }
    851 
    852 void DisplayController::OnFadeOutForSwapDisplayFinished() {
    853 #if defined(OS_CHROMEOS) && defined(USE_X11)
    854   SetPrimaryDisplay(ScreenAsh::GetSecondaryDisplay());
    855   Shell::GetInstance()->output_configurator_animation()->StartFadeInAnimation();
    856 #endif
    857 }
    858 
    859 void DisplayController::UpdateHostWindowNames() {
    860 #if defined(USE_X11)
    861   // crbug.com/120229 - set the window title for the primary dislpay
    862   // to "aura_root_0" so gtalk can find the primary root window to broadcast.
    863   // TODO(jhorwich) Remove this once Chrome supports window-based broadcasting.
    864   aura::RootWindow* primary = Shell::GetPrimaryRootWindow();
    865   Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
    866   for (size_t i = 0; i < root_windows.size(); ++i) {
    867     std::string name =
    868         root_windows[i] == primary ? "aura_root_0" : "aura_root_x";
    869     gfx::AcceleratedWidget xwindow = root_windows[i]->GetAcceleratedWidget();
    870     XStoreName(ui::GetXDisplay(), xwindow, name.c_str());
    871   }
    872 #endif
    873 }
    874 
    875 }  // namespace ash
    876