15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/display/display_controller.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <cmath>
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <map>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/ash_switches.h"
127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "ash/display/display_layout_store.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ash/display/display_manager.h"
147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "ash/display/mirror_window_controller.h"
15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ash/display/root_window_transformers.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ash/host/root_window_host_factory.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/root_window_controller.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ash/screen_ash.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/shell.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/wm/coordinate_conversion.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/wm/property_util.h"
227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "ash/wm/window_properties.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/wm/window_util.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "third_party/skia/include/utils/SkMatrix44.h"
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/aura/client/activation_client.h"
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/aura/client/capture_client.h"
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/aura/client/cursor_client.h"
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/aura/client/focus_client.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/client/screen_position_client.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/root_window.h"
33868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ui/aura/root_window_transformer.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/window.h"
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/aura/window_property.h"
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/aura/window_tracker.h"
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/compositor/compositor.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/compositor/dip_util.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/display.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/screen.h"
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/chromeos/chromeos_version.h"
44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if defined(USE_X11)
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ash/display/output_configurator_animation.h"
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chromeos/display/output_configurator.h"
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/base/x/x11_util.h"
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Including this at the bottom to avoid other
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// potential conflict with chrome headers.
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <X11/extensions/Xrandr.h>
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#undef RootWindow
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif  // defined(USE_X11)
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif  // defined(OS_CHROMEOS)
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
577dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochDECLARE_WINDOW_PROPERTY_TYPE(int64);
587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ash {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Primary display stored in global object as it can be
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// accessed after Shell is deleted. A separate display instance is created
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// during the shutdown instead of always keeping two display instances
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// (one here and another one in display_manager) in sync, which is error prone.
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int64 primary_display_id = gfx::Display::kInvalidDisplayID;
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)gfx::Display* primary_display_for_shutdown = NULL;
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Keeps the number of displays during the shutdown after
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// ash::Shell:: is deleted.
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int num_displays_for_shutdown = -1;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Specifies how long the display change should have been disabled
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// after each display change operations.
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |kCycleDisplayThrottleTimeoutMs| is set to be longer to avoid
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// changing the settings while the system is still configurating
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// displays. It will be overriden by |kAfterDisplayChangeThrottleTimeoutMs|
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// when the display change happens, so the actual timeout is much shorter.
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int64 kAfterDisplayChangeThrottleTimeoutMs = 500;
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int64 kCycleDisplayThrottleTimeoutMs = 4000;
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int64 kSwapDisplayThrottleTimeoutMs = 500;
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)internal::DisplayManager* GetDisplayManager() {
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return Shell::GetInstance()->display_manager();
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SetDisplayPropertiesOnHostWindow(aura::RootWindow* root,
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      const gfx::Display& display) {
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  internal::DisplayInfo info =
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetDisplayManager()->GetDisplayInfo(display.id());
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if defined(OS_CHROMEOS) && defined(USE_X11)
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Native window property (Atom in X11) that specifies the display's
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // rotation, scale factor and if it's internal display.  They are
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // read and used by touchpad/mouse driver directly on X (contact
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // adlr@ for more details on touchpad/mouse driver side). The value
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // of the rotation is one of 0 (normal), 1 (90 degrees clockwise), 2
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // (180 degree) or 3 (270 degrees clockwise).  The value of the
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // scale factor is in percent (100, 140, 200 etc).
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char kRotationProp[] = "_CHROME_DISPLAY_ROTATION";
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char kScaleFactorProp[] = "_CHROME_DISPLAY_SCALE_FACTOR";
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char kInternalProp[] = "_CHROME_DISPLAY_INTERNAL";
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char kCARDINAL[] = "CARDINAL";
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int xrandr_rotation = RR_Rotate_0;
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (info.rotation()) {
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case gfx::Display::ROTATE_0:
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      xrandr_rotation = RR_Rotate_0;
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case gfx::Display::ROTATE_90:
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      xrandr_rotation = RR_Rotate_90;
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case gfx::Display::ROTATE_180:
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      xrandr_rotation = RR_Rotate_180;
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case gfx::Display::ROTATE_270:
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      xrandr_rotation = RR_Rotate_270;
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int internal = display.IsInternal() ? 1 : 0;
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::AcceleratedWidget xwindow = root->GetAcceleratedWidget();
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ui::SetIntProperty(xwindow, kInternalProp, kCARDINAL, internal);
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ui::SetIntProperty(xwindow, kRotationProp, kCARDINAL, xrandr_rotation);
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ui::SetIntProperty(xwindow,
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     kScaleFactorProp,
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     kCARDINAL,
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     100 * display.device_scale_factor());
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<aura::RootWindowTransformer> transformer(
128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      internal::CreateRootWindowTransformerForDisplay(root, display));
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  root->SetRootWindowTransformer(transformer.Pass());
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace internal {
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1367dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochDEFINE_WINDOW_PROPERTY_KEY(int64, kDisplayIdKey,
1377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                           gfx::Display::kInvalidDisplayID);
1387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// A utility class to store/restore focused/active window
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// when the display configuration has changed.
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class FocusActivationStore {
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  FocusActivationStore()
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      : activation_client_(NULL),
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        capture_client_(NULL),
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        focus_client_(NULL),
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        focused_(NULL),
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        active_(NULL) {
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void Store() {
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!activation_client_) {
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      aura::RootWindow* root = Shell::GetPrimaryRootWindow();
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      activation_client_ = aura::client::GetActivationClient(root);
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      capture_client_ = aura::client::GetCaptureClient(root);
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      focus_client_ = aura::client::GetFocusClient(root);
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    focused_ = focus_client_->GetFocusedWindow();
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (focused_)
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      tracker_.Add(focused_);
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    active_ = activation_client_->GetActiveWindow();
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (active_ && focused_ != active_)
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      tracker_.Add(active_);
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Deactivate the window to close menu / bubble windows.
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    activation_client_->DeactivateWindow(active_);
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Release capture if any.
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    capture_client_->SetCapture(NULL);
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Clear the focused window if any. This is necessary because a
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // window may be deleted when losing focus (fullscreen flash for
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // example).  If the focused window is still alive after move, it'll
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // be re-focused below.
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    focus_client_->FocusWindow(NULL);
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void Restore() {
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Restore focused or active window if it's still alive.
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (focused_ && tracker_.Contains(focused_)) {
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      focus_client_->FocusWindow(focused_);
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    } else if (active_ && tracker_.Contains(active_)) {
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      activation_client_->ActivateWindow(active_);
182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (focused_)
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      tracker_.Remove(focused_);
185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (active_)
186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      tracker_.Remove(active_);
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    focused_ = NULL;
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    active_ = NULL;
189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private:
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  aura::client::ActivationClient* activation_client_;
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  aura::client::CaptureClient* capture_client_;
194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  aura::client::FocusClient* focus_client_;
195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  aura::WindowTracker tracker_;
196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  aura::Window* focused_;
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  aura::Window* active_;
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(FocusActivationStore);
200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace internal
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// DisplayChangeLimiter
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DisplayController::DisplayChangeLimiter::DisplayChangeLimiter()
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : throttle_timeout_(base::Time::Now()) {
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DisplayController::DisplayChangeLimiter::SetThrottleTimeout(
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int64 throttle_ms) {
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  throttle_timeout_ =
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Time::Now() + base::TimeDelta::FromMilliseconds(throttle_ms);
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool DisplayController::DisplayChangeLimiter::IsThrottled() const {
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return base::Time::Now() < throttle_timeout_;
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// DisplayController
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DisplayController::DisplayController()
225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : primary_root_window_for_replace_(NULL),
2267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      focus_activation_store_(new internal::FocusActivationStore()),
2277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      mirror_window_controller_(new internal::MirrorWindowController) {
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CommandLine* command_line = CommandLine::ForCurrentProcess();
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_CHROMEOS)
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!command_line->HasSwitch(switches::kAshDisableDisplayChangeLimiter) &&
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::chromeos::IsRunningOnChromeOS())
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    limiter_.reset(new DisplayChangeLimiter);
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reset primary display to make sure that tests don't use
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // stale display info from previous tests.
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  primary_display_id = gfx::Display::kInvalidDisplayID;
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  delete primary_display_for_shutdown;
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  primary_display_for_shutdown = NULL;
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  num_displays_for_shutdown = -1;
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DisplayController::~DisplayController() {
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(primary_display_for_shutdown);
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DisplayController::Start() {
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Shell::GetScreen()->AddObserver(this);
2487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Shell::GetInstance()->display_manager()->set_delegate(this);
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DisplayController::Shutdown() {
2527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Unset the display manager's delegate here because
2537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // DisplayManager outlives DisplayController.
2547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Shell::GetInstance()->display_manager()->set_delegate(NULL);
2557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  mirror_window_controller_.reset();
2577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!primary_display_for_shutdown);
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  primary_display_for_shutdown = new gfx::Display(
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetDisplayManager()->GetDisplayForId(primary_display_id));
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  num_displays_for_shutdown = GetDisplayManager()->GetNumDisplays();
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Shell::GetScreen()->RemoveObserver(this);
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Delete all root window controllers, which deletes root window
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // from the last so that the primary root window gets deleted last.
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::map<int64, aura::RootWindow*>::const_reverse_iterator it =
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           root_windows_.rbegin(); it != root_windows_.rend(); ++it) {
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    internal::RootWindowController* controller =
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetRootWindowController(it->second);
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(controller);
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete controller;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const gfx::Display& DisplayController::GetPrimaryDisplay() {
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(primary_display_id, gfx::Display::kInvalidDisplayID);
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (primary_display_for_shutdown)
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return *primary_display_for_shutdown;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetDisplayManager()->GetDisplayForId(primary_display_id);
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int DisplayController::GetNumDisplays() {
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (num_displays_for_shutdown >= 0)
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return num_displays_for_shutdown;
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return GetDisplayManager()->GetNumDisplays();
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DisplayController::InitPrimaryDisplay() {
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const gfx::Display* primary_candidate =
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetDisplayManager()->GetPrimaryDisplayCandidate();
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  primary_display_id = primary_candidate->id();
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddRootWindowForDisplay(*primary_candidate);
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DisplayController::InitSecondaryDisplays() {
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  internal::DisplayManager* display_manager = GetDisplayManager();
299eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  UpdateDisplayBoundsForLayout();
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) {
301ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const gfx::Display& display = display_manager->GetDisplayAt(i);
302ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    if (primary_display_id != display.id()) {
303ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      aura::RootWindow* root = AddRootWindowForDisplay(display);
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Shell::GetInstance()->InitRootWindowForSecondaryDisplay(root);
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (display_manager->GetNumDisplays() > 1) {
308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DisplayIdPair pair = GetCurrentDisplayIdPair();
309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DisplayLayout layout = GetCurrentDisplayLayout();
310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SetPrimaryDisplayId(
311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        layout.primary_id == gfx::Display::kInvalidDisplayID ?
312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        pair.first : layout.primary_id);
313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
314eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  UpdateHostWindowNames();
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DisplayController::AddObserver(Observer* observer) {
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observers_.AddObserver(observer);
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DisplayController::RemoveObserver(Observer* observer) {
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observers_.RemoveObserver(observer);
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)aura::RootWindow* DisplayController::GetPrimaryRootWindow() {
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!root_windows_.empty());
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return root_windows_[primary_display_id];
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)aura::RootWindow* DisplayController::GetRootWindowForDisplayId(int64 id) {
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return root_windows_[id];
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DisplayController::CloseChildWindows() {
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::map<int64, aura::RootWindow*>::const_iterator it =
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           root_windows_.begin(); it != root_windows_.end(); ++it) {
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    aura::RootWindow* root_window = it->second;
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    internal::RootWindowController* controller =
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetRootWindowController(root_window);
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (controller) {
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      controller->CloseChildWindows();
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      while (!root_window->children().empty()) {
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        aura::Window* child = root_window->children()[0];
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        delete child;
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::vector<aura::RootWindow*> DisplayController::GetAllRootWindows() {
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<aura::RootWindow*> windows;
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::map<int64, aura::RootWindow*>::const_iterator it =
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           root_windows_.begin(); it != root_windows_.end(); ++it) {
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(it->second);
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (GetRootWindowController(it->second))
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      windows.push_back(it->second);
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return windows;
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Insets DisplayController::GetOverscanInsets(int64 display_id) const {
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetDisplayManager()->GetOverscanInsets(display_id);
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DisplayController::SetOverscanInsets(int64 display_id,
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                          const gfx::Insets& insets_in_dip) {
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GetDisplayManager()->SetOverscanInsets(display_id, insets_in_dip);
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::vector<internal::RootWindowController*>
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DisplayController::GetAllRootWindowControllers() {
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<internal::RootWindowController*> controllers;
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::map<int64, aura::RootWindow*>::const_iterator it =
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           root_windows_.begin(); it != root_windows_.end(); ++it) {
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    internal::RootWindowController* controller =
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetRootWindowController(it->second);
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (controller)
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      controllers.push_back(controller);
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return controllers;
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DisplayController::SetLayoutForCurrentDisplays(
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const DisplayLayout& layout_relative_to_primary) {
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(2U, GetDisplayManager()->GetNumDisplays());
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (GetDisplayManager()->GetNumDisplays() < 2)
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const gfx::Display& primary = GetPrimaryDisplay();
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const DisplayIdPair pair = GetCurrentDisplayIdPair();
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Invert if the primary was swapped.
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DisplayLayout to_set = pair.first == primary.id() ?
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      layout_relative_to_primary : layout_relative_to_primary.Invert();
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  internal::DisplayLayoutStore* layout_store =
3967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      GetDisplayManager()->layout_store();
3977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DisplayLayout current_layout =
3987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      layout_store->GetRegisteredDisplayLayout(pair);
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (to_set.position != current_layout.position ||
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      to_set.offset != current_layout.offset) {
401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    to_set.primary_id = primary.id();
4027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    layout_store->RegisterLayoutForDisplayIdPair(
4037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        pair.first, pair.second, to_set);
4047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    PreDisplayConfigurationChange();
405eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // TODO(oshima): Call UpdateDisplays instead.
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UpdateDisplayBoundsForLayout();
4074311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch    // Primary's bounds stay the same. Just notify bounds change
4084311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch    // on the secondary.
4094311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch    Shell::GetInstance()->screen()->NotifyBoundsChanged(
4104311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch        ScreenAsh::GetSecondaryDisplay());
4117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    PostDisplayConfigurationChange();
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochDisplayLayout DisplayController::GetCurrentDisplayLayout() {
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(2U, GetDisplayManager()->num_connected_displays());
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Invert if the primary was swapped.
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (GetDisplayManager()->num_connected_displays() > 1) {
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DisplayIdPair pair = GetCurrentDisplayIdPair();
4207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return GetDisplayManager()->layout_store()->
4217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        ComputeDisplayLayoutForDisplayIdPair(pair);
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  NOTREACHED() << "DisplayLayout is requested for single display";
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // On release build, just fallback to default instead of blowing up.
4257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DisplayLayout layout =
4267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      GetDisplayManager()->layout_store()->default_display_layout();
427eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  layout.primary_id = primary_display_id;
428eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return layout;
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DisplayIdPair DisplayController::GetCurrentDisplayIdPair() const {
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  internal::DisplayManager* display_manager = GetDisplayManager();
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const gfx::Display& primary = GetPrimaryDisplay();
434868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (display_manager->IsMirrored()) {
435868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return std::make_pair(primary.id(),
436868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                          display_manager->mirrored_display().id());
437868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const gfx::Display& secondary = ScreenAsh::GetSecondaryDisplay();
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (primary.IsInternal() ||
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetDisplayManager()->first_display_id() == primary.id()) {
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return std::make_pair(primary.id(), secondary.id());
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Display has been Swapped.
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return std::make_pair(secondary.id(), primary.id());
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
44990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void DisplayController::ToggleMirrorMode() {
45090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  internal::DisplayManager* display_manager = GetDisplayManager();
45190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (display_manager->num_connected_displays() <= 1)
45290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
45390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
454c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (limiter_) {
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if  (limiter_->IsThrottled())
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    limiter_->SetThrottleTimeout(kCycleDisplayThrottleTimeoutMs);
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
459c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if defined(OS_CHROMEOS) && defined(USE_X11)
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Shell* shell = Shell::GetInstance();
46190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  internal::OutputConfiguratorAnimation* animation =
46290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      shell->output_configurator_animation();
46390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  animation->StartFadeOutAnimation(base::Bind(
46490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::IgnoreResult(&internal::DisplayManager::SetMirrorMode),
46590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::Unretained(display_manager),
46690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      !display_manager->IsMirrored()));
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DisplayController::SwapPrimaryDisplay() {
471c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (limiter_) {
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if  (limiter_->IsThrottled())
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    limiter_->SetThrottleTimeout(kSwapDisplayThrottleTimeoutMs);
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (Shell::GetScreen()->GetNumDisplays() > 1) {
478c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if defined(OS_CHROMEOS) && defined(USE_X11)
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    internal::OutputConfiguratorAnimation* animation =
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        Shell::GetInstance()->output_configurator_animation();
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (animation) {
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      animation->StartFadeOutAnimation(base::Bind(
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          &DisplayController::OnFadeOutForSwapDisplayFinished,
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::Unretained(this)));
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SetPrimaryDisplay(ScreenAsh::GetSecondaryDisplay());
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SetPrimaryDisplay(ScreenAsh::GetSecondaryDisplay());
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DisplayController::SetPrimaryDisplayId(int64 id) {
495c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK_NE(gfx::Display::kInvalidDisplayID, id);
496c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (id == gfx::Display::kInvalidDisplayID || primary_display_id == id)
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
499c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const gfx::Display& display = GetDisplayManager()->GetDisplayForId(id);
500c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (display.is_valid())
501c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SetPrimaryDisplay(display);
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DisplayController::SetPrimaryDisplay(
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Display& new_primary_display) {
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  internal::DisplayManager* display_manager = GetDisplayManager();
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(new_primary_display.is_valid());
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(display_manager->IsActiveDisplay(new_primary_display));
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!new_primary_display.is_valid() ||
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !display_manager->IsActiveDisplay(new_primary_display)) {
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Invalid or non-existent display is requested:"
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << new_primary_display.ToString();
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (primary_display_id == new_primary_display.id() ||
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      root_windows_.size() < 2) {
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aura::RootWindow* non_primary_root = root_windows_[new_primary_display.id()];
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG_IF(ERROR, !non_primary_root)
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      << "Unknown display is requested in SetPrimaryDisplay: id="
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      << new_primary_display.id();
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!non_primary_root)
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Display old_primary_display = GetPrimaryDisplay();
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Swap root windows between current and new primary display.
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aura::RootWindow* primary_root = root_windows_[primary_display_id];
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(primary_root);
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(primary_root, non_primary_root);
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  root_windows_[new_primary_display.id()] = primary_root;
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  primary_root->SetProperty(internal::kDisplayIdKey, new_primary_display.id());
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  root_windows_[old_primary_display.id()] = non_primary_root;
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  non_primary_root->SetProperty(internal::kDisplayIdKey,
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                old_primary_display.id());
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  primary_display_id = new_primary_display.id();
5447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  GetDisplayManager()->layout_store()->UpdatePrimaryDisplayId(
5457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      GetCurrentDisplayIdPair(), primary_display_id);
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  UpdateWorkAreaOfDisplayNearestWindow(
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      primary_root, old_primary_display.GetWorkAreaInsets());
5497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  UpdateWorkAreaOfDisplayNearestWindow(
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      non_primary_root, new_primary_display.GetWorkAreaInsets());
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Update the dispay manager with new display info.
5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<internal::DisplayInfo> display_info_list;
5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  display_info_list.push_back(display_manager->GetDisplayInfo(
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      primary_display_id));
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  display_info_list.push_back(display_manager->GetDisplayInfo(
557ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      ScreenAsh::GetSecondaryDisplay().id()));
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetDisplayManager()->set_force_bounds_changed(true);
5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GetDisplayManager()->UpdateDisplays(display_info_list);
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetDisplayManager()->set_force_bounds_changed(false);
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
563c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void DisplayController::EnsurePointerInDisplays() {
5647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // If the mouse is currently on a display in native location,
5657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // use the same native location. Otherwise find the display closest
5667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // to the current cursor location in screen coordinates.
5677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
5687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  gfx::Point point_in_screen = Shell::GetScreen()->GetCursorScreenPoint();
5697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  gfx::Point target_location_in_native;
570c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int64 closest_distance_squared = -1;
571c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  internal::DisplayManager* display_manager = GetDisplayManager();
572c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
573c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  aura::RootWindow* dst_root_window = NULL;
574c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) {
575ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const gfx::Display& display = display_manager->GetDisplayAt(i);
5767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const internal::DisplayInfo display_info =
577ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        display_manager->GetDisplayInfo(display.id());
578ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    aura::RootWindow* root_window = GetRootWindowForDisplayId(display.id());
5797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (display_info.bounds_in_pixel().Contains(
5807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            cursor_location_in_native_coords_for_restore_)) {
581c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      dst_root_window = root_window;
5827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      target_location_in_native = cursor_location_in_native_coords_for_restore_;
583c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
584c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
585ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    gfx::Point center = display.bounds().CenterPoint();
586c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Use the distance squared from the center of the dislay. This is not
587c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // exactly "closest" display, but good enough to pick one
588c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // appropriate (and there are at most two displays).
589c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // We don't care about actual distance, only relative to other displays, so
590c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // using the LengthSquared() is cheaper than Length().
591c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int64 distance_squared = (center - point_in_screen).LengthSquared();
593c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (closest_distance_squared < 0 ||
594c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        closest_distance_squared > distance_squared) {
595ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      aura::RootWindow* root_window = GetRootWindowForDisplayId(display.id());
5967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      aura::client::ScreenPositionClient* client =
5977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          aura::client::GetScreenPositionClient(root_window);
5987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      client->ConvertPointFromScreen(root_window, &center);
5997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      root_window->ConvertPointToNativeScreen(&center);
600c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      dst_root_window = root_window;
6017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      target_location_in_native = center;
602c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      closest_distance_squared = distance_squared;
603c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
604c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
6057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  dst_root_window->ConvertPointFromNativeScreen(&target_location_in_native);
6067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  dst_root_window->MoveCursorTo(target_location_in_native);
6077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
6087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
6097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool DisplayController::UpdateWorkAreaOfDisplayNearestWindow(
6107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const aura::Window* window,
6117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const gfx::Insets& insets) {
612ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  const aura::RootWindow* root_window = window->GetRootWindow();
613ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  int64 id = root_window->GetProperty(internal::kDisplayIdKey);
614ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // if id is |kInvaildDisplayID|, it's being deleted.
615ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DCHECK(id != gfx::Display::kInvalidDisplayID);
616ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return GetDisplayManager()->UpdateWorkAreaOfDisplay(id, insets);
6177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
6187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
6197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochconst gfx::Display& DisplayController::GetDisplayNearestWindow(
6207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const aura::Window* window) const {
6217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!window)
6227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return GetPrimaryDisplay();
6237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const aura::RootWindow* root_window = window->GetRootWindow();
6247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!root_window)
6257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return GetPrimaryDisplay();
6267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  int64 id = root_window->GetProperty(internal::kDisplayIdKey);
6277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // if id is |kInvaildDisplayID|, it's being deleted.
6287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK(id != gfx::Display::kInvalidDisplayID);
629c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  internal::DisplayManager* display_manager = GetDisplayManager();
6317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // RootWindow needs Display to determine its device scale factor.
6327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // TODO(oshima): We don't need full display info for mirror
6337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // window. Refactor so that RootWindow doesn't use it.
6347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (display_manager->mirrored_display().id() == id)
6357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return display_manager->mirrored_display();
636c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
637ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return display_manager->GetDisplayForId(id);
638c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
639c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochconst gfx::Display& DisplayController::GetDisplayNearestPoint(
6417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const gfx::Point& point) const {
6427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Fallback to the primary display if there is no root display containing
6437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // the |point|.
6447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const gfx::Display& display =
6457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      GetDisplayManager()->FindDisplayContainingPoint(point);
6467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return display.is_valid() ? display : GetPrimaryDisplay();
6477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
6487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
6497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochconst gfx::Display& DisplayController::GetDisplayMatching(
6507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const gfx::Rect& rect) const {
6517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (rect.IsEmpty())
6527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return GetDisplayNearestPoint(rect.origin());
6537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
6547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  int max_area = 0;
6557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const gfx::Display* matching = NULL;
6567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  for (size_t i = 0; i < GetDisplayManager()->GetNumDisplays(); ++i) {
657ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const gfx::Display& display = GetDisplayManager()->GetDisplayAt(i);
658ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    gfx::Rect intersect = gfx::IntersectRects(display.bounds(), rect);
6597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int area = intersect.width() * intersect.height();
6607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (area > max_area) {
6617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      max_area = area;
662ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      matching = &display;
663c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
664c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
6657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Fallback to the primary display if there is no matching display.
6667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return matching ? *matching : GetPrimaryDisplay();
667c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
668c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DisplayController::OnDisplayBoundsChanged(const gfx::Display& display) {
6702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const internal::DisplayInfo& display_info =
6712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetDisplayManager()->GetDisplayInfo(display.id());
6722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!display_info.bounds_in_pixel().IsEmpty());
6732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  aura::RootWindow* root = root_windows_[display.id()];
674c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  root->SetHostBounds(display_info.bounds_in_pixel());
675eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SetDisplayPropertiesOnHostWindow(root, display);
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DisplayController::OnDisplayAdded(const gfx::Display& display) {
6792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (primary_root_window_for_replace_) {
6802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(root_windows_.empty());
6812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    primary_display_id = display.id();
6822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    root_windows_[display.id()] = primary_root_window_for_replace_;
6832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    primary_root_window_for_replace_->SetProperty(
6842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        internal::kDisplayIdKey, display.id());
6852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    primary_root_window_for_replace_ = NULL;
6862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const internal::DisplayInfo& display_info =
6872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        GetDisplayManager()->GetDisplayInfo(display.id());
688c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    root_windows_[display.id()]->SetHostBounds(
689c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        display_info.bounds_in_pixel());
6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
691c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (primary_display_id == gfx::Display::kInvalidDisplayID)
692c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      primary_display_id = display.id();
6932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(!root_windows_.empty());
6942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    aura::RootWindow* root = AddRootWindowForDisplay(display);
6952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Shell::GetInstance()->InitRootWindowForSecondaryDisplay(root);
6962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DisplayController::OnDisplayRemoved(const gfx::Display& display) {
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aura::RootWindow* root_to_delete = root_windows_[display.id()];
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(root_to_delete) << display.ToString();
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Display for root window will be deleted when the Primary RootWindow
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is deleted by the Shell.
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  root_windows_.erase(display.id());
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When the primary root window's display is removed, move the primary
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // root to the other display.
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (primary_display_id == display.id()) {
7102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Temporarily store the primary root window in
7112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // |primary_root_window_for_replace_| when replacing the display.
7122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (root_windows_.size() == 0) {
7132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      primary_display_id = gfx::Display::kInvalidDisplayID;
7142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      primary_root_window_for_replace_ = root_to_delete;
7152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
7162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(1U, root_windows_.size());
718ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    primary_display_id = ScreenAsh::GetSecondaryDisplay().id();
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    aura::RootWindow* primary_root = root_to_delete;
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Delete the other root instead.
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    root_to_delete = root_windows_[primary_display_id];
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    root_to_delete->SetProperty(internal::kDisplayIdKey, display.id());
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Setup primary root.
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    root_windows_[primary_display_id] = primary_root;
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    primary_root->SetProperty(internal::kDisplayIdKey, primary_display_id);
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnDisplayBoundsChanged(
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetDisplayManager()->GetDisplayForId(primary_display_id));
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  internal::RootWindowController* controller =
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetRootWindowController(root_to_delete);
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(controller);
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  controller->MoveWindowsTo(GetPrimaryRootWindow());
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Delete most of root window related objects, but don't delete
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // root window itself yet because the stack may be using it.
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  controller->Shutdown();
739c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::MessageLoop::current()->DeleteSoon(FROM_HERE, controller);
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid DisplayController::OnRootWindowHostResized(const aura::RootWindow* root) {
7437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  internal::DisplayManager* display_manager = GetDisplayManager();
7447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  gfx::Display display = GetDisplayNearestWindow(root);
7457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (display_manager->UpdateDisplayBounds(
7467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          display.id(),
7477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          gfx::Rect(root->GetHostOrigin(), root->GetHostSize()))) {
7487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    mirror_window_controller_->UpdateWindow();
7497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
7507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
7517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
7527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid DisplayController::CreateOrUpdateMirrorWindow(
7537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const internal::DisplayInfo& info) {
7547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  mirror_window_controller_->UpdateWindow(info);
7557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
7567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
7577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid DisplayController::CloseMirrorWindow() {
7587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  mirror_window_controller_->Close();
7597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
7607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
7617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid DisplayController::PreDisplayConfigurationChange() {
7627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  FOR_EACH_OBSERVER(Observer, observers_, OnDisplayConfigurationChanging());
7637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  focus_activation_store_->Store();
7647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
7657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  gfx::Point point_in_screen = Shell::GetScreen()->GetCursorScreenPoint();
7667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  gfx::Display display =
7677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      Shell::GetScreen()->GetDisplayNearestPoint(point_in_screen);
7687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  aura::RootWindow* root_window = GetRootWindowForDisplayId(display.id());
7697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
7707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  aura::client::ScreenPositionClient* client =
7717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      aura::client::GetScreenPositionClient(root_window);
7727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  client->ConvertPointFromScreen(root_window, &point_in_screen);
7737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  root_window->ConvertPointToNativeScreen(&point_in_screen);
7747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  cursor_location_in_native_coords_for_restore_ = point_in_screen;
7757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
7767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
7777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid DisplayController::PostDisplayConfigurationChange() {
7787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (limiter_)
7797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    limiter_->SetThrottleTimeout(kAfterDisplayChangeThrottleTimeoutMs);
7807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
7817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  focus_activation_store_->Restore();
7827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
7837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  internal::DisplayManager* display_manager = GetDisplayManager();
7847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  internal::DisplayLayoutStore* layout_store = display_manager->layout_store();
7857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (display_manager->num_connected_displays() > 1) {
7867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    DisplayIdPair pair = GetCurrentDisplayIdPair();
7877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    layout_store->UpdateMirrorStatus(pair, display_manager->IsMirrored());
7887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    DisplayLayout layout = layout_store->GetRegisteredDisplayLayout(pair);
7897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
7907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (Shell::GetScreen()->GetNumDisplays() > 1 ) {
7917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      int64 primary_id = layout.primary_id;
7927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      SetPrimaryDisplayId(
7937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          primary_id == gfx::Display::kInvalidDisplayID ?
7947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          pair.first : primary_id);
7957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      // Update the primary_id in case the above call is
7967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      // ignored. Happens when a) default layout's primary id
7977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      // doesn't exist, or b) the primary_id has already been
7987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      // set to the same and didn't update it.
7997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      layout_store->UpdatePrimaryDisplayId(pair, GetPrimaryDisplay().id());
8007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
8017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
8027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  FOR_EACH_OBSERVER(Observer, observers_, OnDisplayConfigurationChanged());
8037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  UpdateHostWindowNames();
8047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EnsurePointerInDisplays();
8057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
8067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
80790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)aura::RootWindow* DisplayController::AddRootWindowForDisplay(
8082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const gfx::Display& display) {
8092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static int root_window_count = 0;
8102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const internal::DisplayInfo& display_info =
8112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetDisplayManager()->GetDisplayInfo(display.id());
8122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const gfx::Rect& bounds_in_pixel = display_info.bounds_in_pixel();
8132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  aura::RootWindow::CreateParams params(bounds_in_pixel);
8142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  params.host = Shell::GetInstance()->root_window_host_factory()->
8152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CreateRootWindowHost(bounds_in_pixel);
8162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  aura::RootWindow* root_window = new aura::RootWindow(params);
8172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  root_window->SetName(
8182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::StringPrintf("RootWindow-%d", root_window_count++));
819c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  root_window->compositor()->SetBackgroundColor(SK_ColorBLACK);
8202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // No need to remove RootWindowObserver because
8217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // the DisplayController object outlives RootWindow objects.
8227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  root_window->AddRootWindowObserver(this);
8232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  root_window->SetProperty(internal::kDisplayIdKey, display.id());
8242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  root_window->Init();
8252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
82690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  root_windows_[display.id()] = root_window;
82790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SetDisplayPropertiesOnHostWindow(root_window, display);
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS)
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static bool force_constrain_pointer_to_root =
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CommandLine::ForCurrentProcess()->HasSwitch(
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          switches::kAshConstrainPointerToRoot);
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (base::chromeos::IsRunningOnChromeOS() || force_constrain_pointer_to_root)
83490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    root_window->ConfineCursorToWindow();
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
83690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return root_window;
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DisplayController::UpdateDisplayBoundsForLayout() {
8402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (Shell::GetScreen()->GetNumDisplays() < 2 ||
8412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetDisplayManager()->num_connected_displays() < 2) {
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
8432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(2, Shell::GetScreen()->GetNumDisplays());
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const DisplayLayout layout = GetCurrentDisplayLayout();
847ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  Shell::GetInstance()->display_manager()->UpdateDisplayBoundsForLayoutById(
848ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      layout, GetPrimaryDisplay(),
849ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      ScreenAsh::GetSecondaryDisplay().id());
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DisplayController::OnFadeOutForSwapDisplayFinished() {
853c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if defined(OS_CHROMEOS) && defined(USE_X11)
8542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetPrimaryDisplay(ScreenAsh::GetSecondaryDisplay());
8552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Shell::GetInstance()->output_configurator_animation()->StartFadeInAnimation();
8562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
8572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
859eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid DisplayController::UpdateHostWindowNames() {
860eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(USE_X11)
861eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // crbug.com/120229 - set the window title for the primary dislpay
862eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // to "aura_root_0" so gtalk can find the primary root window to broadcast.
863eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // TODO(jhorwich) Remove this once Chrome supports window-based broadcasting.
864eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  aura::RootWindow* primary = Shell::GetPrimaryRootWindow();
865eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
866eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  for (size_t i = 0; i < root_windows.size(); ++i) {
867eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    std::string name =
868eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        root_windows[i] == primary ? "aura_root_0" : "aura_root_x";
869eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    gfx::AcceleratedWidget xwindow = root_windows[i]->GetAcceleratedWidget();
870eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    XStoreName(ui::GetXDisplay(), xwindow, name.c_str());
871eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
872eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif
873eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
874eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace ash
876