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"
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/display/cursor_window_controller.h"
137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "ash/display/display_layout_store.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ash/display/display_manager.h"
157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "ash/display/mirror_window_controller.h"
16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ash/display/root_window_transformers.h"
17a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "ash/host/ash_window_tree_host.h"
18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ash/host/ash_window_tree_host_init_params.h"
19a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "ash/host/root_window_transformer.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/root_window_controller.h"
2158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "ash/root_window_settings.h"
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/screen_util.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/shell.h"
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/shell_delegate.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/wm/coordinate_conversion.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/stl_util.h"
28868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
2946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "base/strings/utf_string_conversions.h"
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/aura/client/capture_client.h"
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/aura/client/focus_client.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/client/screen_position_client.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/window.h"
34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/aura/window_event_dispatcher.h"
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/aura/window_property.h"
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/aura/window_tracker.h"
37a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "ui/aura/window_tree_host.h"
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/compositor/compositor.h"
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/compositor/compositor_vsync_manager.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/display.h"
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/screen.h"
42effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "ui/wm/public/activation_client.h"
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS)
455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "ash/display/display_configurator_animation.h"
464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/sys_info.h"
47eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#endif  // defined(OS_CHROMEOS)
49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if defined(USE_X11)
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/base/x/x11_util.h"
5268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ui/gfx/x/x11_types.h"
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Including this at the bottom to avoid other
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// potential conflict with chrome headers.
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <X11/extensions/Xrandr.h>
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#undef RootWindow
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif  // defined(USE_X11)
59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ash {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Primary display stored in global object as it can be
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// accessed after Shell is deleted. A separate display instance is created
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// during the shutdown instead of always keeping two display instances
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// (one here and another one in display_manager) in sync, which is error prone.
68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// This is initialized in the constructor, and then in CreatePrimaryHost().
69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int64 primary_display_id = -1;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Specifies how long the display change should have been disabled
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// after each display change operations.
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |kCycleDisplayThrottleTimeoutMs| is set to be longer to avoid
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// changing the settings while the system is still configurating
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// displays. It will be overriden by |kAfterDisplayChangeThrottleTimeoutMs|
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// when the display change happens, so the actual timeout is much shorter.
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int64 kAfterDisplayChangeThrottleTimeoutMs = 500;
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int64 kCycleDisplayThrottleTimeoutMs = 4000;
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int64 kSwapDisplayThrottleTimeoutMs = 500;
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
81c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochDisplayManager* GetDisplayManager() {
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return Shell::GetInstance()->display_manager();
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
85a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid SetDisplayPropertiesOnHost(AshWindowTreeHost* ash_host,
86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                const gfx::Display& display) {
87c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DisplayInfo info = GetDisplayManager()->GetDisplayInfo(display.id());
88a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  aura::WindowTreeHost* host = ash_host->AsWindowTreeHost();
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if defined(OS_CHROMEOS) && defined(USE_X11)
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Native window property (Atom in X11) that specifies the display's
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // rotation, scale factor and if it's internal display.  They are
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // read and used by touchpad/mouse driver directly on X (contact
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // adlr@ for more details on touchpad/mouse driver side). The value
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // of the rotation is one of 0 (normal), 1 (90 degrees clockwise), 2
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // (180 degree) or 3 (270 degrees clockwise).  The value of the
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // scale factor is in percent (100, 140, 200 etc).
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char kRotationProp[] = "_CHROME_DISPLAY_ROTATION";
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char kScaleFactorProp[] = "_CHROME_DISPLAY_SCALE_FACTOR";
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char kInternalProp[] = "_CHROME_DISPLAY_INTERNAL";
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char kCARDINAL[] = "CARDINAL";
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int xrandr_rotation = RR_Rotate_0;
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (info.rotation()) {
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case gfx::Display::ROTATE_0:
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      xrandr_rotation = RR_Rotate_0;
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case gfx::Display::ROTATE_90:
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      xrandr_rotation = RR_Rotate_90;
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case gfx::Display::ROTATE_180:
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      xrandr_rotation = RR_Rotate_180;
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case gfx::Display::ROTATE_270:
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      xrandr_rotation = RR_Rotate_270;
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int internal = display.IsInternal() ? 1 : 0;
118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  gfx::AcceleratedWidget xwindow = host->GetAcceleratedWidget();
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ui::SetIntProperty(xwindow, kInternalProp, kCARDINAL, internal);
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ui::SetIntProperty(xwindow, kRotationProp, kCARDINAL, xrandr_rotation);
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ui::SetIntProperty(xwindow,
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     kScaleFactorProp,
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     kCARDINAL,
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     100 * display.device_scale_factor());
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
126a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  scoped_ptr<RootWindowTransformer> transformer(
127c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      CreateRootWindowTransformerForDisplay(host->window(), display));
128a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  ash_host->SetRootWindowTransformer(transformer.Pass());
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DisplayMode mode =
1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      GetDisplayManager()->GetActiveModeForDisplayId(display.id());
1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (mode.refresh_rate > 0.0f) {
133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    host->compositor()->vsync_manager()->SetAuthoritativeVSyncInterval(
134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        base::TimeDelta::FromMicroseconds(
135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            base::Time::kMicrosecondsPerSecond / mode.refresh_rate));
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
139a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochaura::Window* GetWindow(AshWindowTreeHost* ash_host) {
140f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK(ash_host->AsWindowTreeHost());
141a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  return ash_host->AsWindowTreeHost()->window();
142a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
143a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// A utility class to store/restore focused/active window
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// when the display configuration has changed.
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class FocusActivationStore {
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  FocusActivationStore()
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      : activation_client_(NULL),
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        capture_client_(NULL),
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        focus_client_(NULL),
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        focused_(NULL),
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        active_(NULL) {
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
158f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  void Store(bool clear_focus) {
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!activation_client_) {
1601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      aura::Window* root = Shell::GetPrimaryRootWindow();
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      activation_client_ = aura::client::GetActivationClient(root);
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      capture_client_ = aura::client::GetCaptureClient(root);
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      focus_client_ = aura::client::GetFocusClient(root);
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    focused_ = focus_client_->GetFocusedWindow();
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (focused_)
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      tracker_.Add(focused_);
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    active_ = activation_client_->GetActiveWindow();
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (active_ && focused_ != active_)
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      tracker_.Add(active_);
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Deactivate the window to close menu / bubble windows.
173f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (clear_focus)
174d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      activation_client_->DeactivateWindow(active_);
175d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Release capture if any.
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    capture_client_->SetCapture(NULL);
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Clear the focused window if any. This is necessary because a
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // window may be deleted when losing focus (fullscreen flash for
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // example).  If the focused window is still alive after move, it'll
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // be re-focused below.
182f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (clear_focus)
183d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      focus_client_->FocusWindow(NULL);
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void Restore() {
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Restore focused or active window if it's still alive.
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (focused_ && tracker_.Contains(focused_)) {
189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      focus_client_->FocusWindow(focused_);
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    } else if (active_ && tracker_.Contains(active_)) {
191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      activation_client_->ActivateWindow(active_);
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (focused_)
194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      tracker_.Remove(focused_);
195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (active_)
196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      tracker_.Remove(active_);
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    focused_ = NULL;
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    active_ = NULL;
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private:
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  aura::client::ActivationClient* activation_client_;
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  aura::client::CaptureClient* capture_client_;
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  aura::client::FocusClient* focus_client_;
205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  aura::WindowTracker tracker_;
206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  aura::Window* focused_;
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  aura::Window* active_;
208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(FocusActivationStore);
210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// DisplayChangeLimiter
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DisplayController::DisplayChangeLimiter::DisplayChangeLimiter()
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : throttle_timeout_(base::Time::Now()) {
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DisplayController::DisplayChangeLimiter::SetThrottleTimeout(
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int64 throttle_ms) {
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  throttle_timeout_ =
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Time::Now() + base::TimeDelta::FromMilliseconds(throttle_ms);
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool DisplayController::DisplayChangeLimiter::IsThrottled() const {
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return base::Time::Now() < throttle_timeout_;
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// DisplayController
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DisplayController::DisplayController()
233a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    : primary_tree_host_for_replace_(NULL),
234c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      focus_activation_store_(new FocusActivationStore()),
235c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      cursor_window_controller_(new CursorWindowController()),
236f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      mirror_window_controller_(new MirrorWindowController()),
237f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      weak_ptr_factory_(this) {
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_CHROMEOS)
239a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (base::SysInfo::IsRunningOnChromeOS())
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    limiter_.reset(new DisplayChangeLimiter);
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reset primary display to make sure that tests don't use
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // stale display info from previous tests.
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  primary_display_id = gfx::Display::kInvalidDisplayID;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DisplayController::~DisplayController() {
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DisplayController::Start() {
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Shell::GetScreen()->AddObserver(this);
2527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Shell::GetInstance()->display_manager()->set_delegate(this);
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DisplayController::Shutdown() {
2567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Unset the display manager's delegate here because
2577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // DisplayManager outlives DisplayController.
2587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Shell::GetInstance()->display_manager()->set_delegate(NULL);
2597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  cursor_window_controller_.reset();
2617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  mirror_window_controller_.reset();
2627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Shell::GetScreen()->RemoveObserver(this);
2641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int64 primary_id = Shell::GetScreen()->GetPrimaryDisplay().id();
2661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Delete non primary root window controllers first, then
2681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // delete the primary root window controller.
2691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  aura::Window::Windows root_windows = DisplayController::GetAllRootWindows();
2701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::vector<RootWindowController*> to_delete;
2711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  RootWindowController* primary_rwc = NULL;
2721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  for (aura::Window::Windows::iterator iter = root_windows.begin();
2731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci       iter != root_windows.end();
2741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci       ++iter) {
2751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    RootWindowController* rwc = GetRootWindowController(*iter);
2761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (GetRootWindowSettings(*iter)->display_id == primary_id)
2771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      primary_rwc = rwc;
2781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    else
2791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      to_delete.push_back(rwc);
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CHECK(primary_rwc);
2821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  STLDeleteElements(&to_delete);
2841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  delete primary_rwc;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
287cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void DisplayController::CreatePrimaryHost(
288cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const AshWindowTreeHostInitParams& init_params) {
2893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const gfx::Display& primary_candidate =
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetDisplayManager()->GetPrimaryDisplayCandidate();
2913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  primary_display_id = primary_candidate.id();
292f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK_NE(gfx::Display::kInvalidDisplayID, primary_display_id);
293cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  AddWindowTreeHostForDisplay(primary_candidate, init_params);
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
296a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid DisplayController::InitDisplays() {
297a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  RootWindowController::CreateForPrimaryDisplay(
298a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      window_tree_hosts_[primary_display_id]);
299a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
300c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DisplayManager* display_manager = GetDisplayManager();
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) {
302ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const gfx::Display& display = display_manager->GetDisplayAt(i);
303ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    if (primary_display_id != display.id()) {
304cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      AshWindowTreeHost* ash_host = AddWindowTreeHostForDisplay(
305cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          display, AshWindowTreeHostInitParams());
306a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      RootWindowController::CreateForSecondaryDisplay(ash_host);
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
309eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  UpdateHostWindowNames();
310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
311cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  FOR_EACH_OBSERVER(Observer, observers_, OnDisplaysInitialized());
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DisplayController::AddObserver(Observer* observer) {
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observers_.AddObserver(observer);
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DisplayController::RemoveObserver(Observer* observer) {
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observers_.RemoveObserver(observer);
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static
3235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)int64 DisplayController::GetPrimaryDisplayId() {
324f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK_NE(gfx::Display::kInvalidDisplayID, primary_display_id);
3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return primary_display_id;
3265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)aura::Window* DisplayController::GetPrimaryRootWindow() {
329a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  return GetRootWindowForDisplayId(primary_display_id);
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)aura::Window* DisplayController::GetRootWindowForDisplayId(int64 id) {
3331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CHECK_EQ(1u, window_tree_hosts_.count(id));
334f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  AshWindowTreeHost* host = window_tree_hosts_[id];
335f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK(host);
336f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return GetWindow(host);
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DisplayController::CloseChildWindows() {
340a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  for (WindowTreeHostMap::const_iterator it = window_tree_hosts_.begin();
341a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch       it != window_tree_hosts_.end();
342a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch       ++it) {
343a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    aura::Window* root_window = GetWindow(it->second);
344c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    RootWindowController* controller = GetRootWindowController(root_window);
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (controller) {
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      controller->CloseChildWindows();
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      while (!root_window->children().empty()) {
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        aura::Window* child = root_window->children()[0];
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        delete child;
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
356f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)aura::Window::Windows DisplayController::GetAllRootWindows() {
357f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  aura::Window::Windows windows;
358a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  for (WindowTreeHostMap::const_iterator it = window_tree_hosts_.begin();
359a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch       it != window_tree_hosts_.end();
360a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch       ++it) {
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(it->second);
362a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    if (GetRootWindowController(GetWindow(it->second)))
363a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      windows.push_back(GetWindow(it->second));
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return windows;
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Insets DisplayController::GetOverscanInsets(int64 display_id) const {
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetDisplayManager()->GetOverscanInsets(display_id);
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DisplayController::SetOverscanInsets(int64 display_id,
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                          const gfx::Insets& insets_in_dip) {
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GetDisplayManager()->SetOverscanInsets(display_id, insets_in_dip);
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
377c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochstd::vector<RootWindowController*>
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DisplayController::GetAllRootWindowControllers() {
379c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  std::vector<RootWindowController*> controllers;
380a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  for (WindowTreeHostMap::const_iterator it = window_tree_hosts_.begin();
381a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch       it != window_tree_hosts_.end();
382a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch       ++it) {
383a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    RootWindowController* controller =
384a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        GetRootWindowController(GetWindow(it->second));
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (controller)
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      controllers.push_back(controller);
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return controllers;
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void DisplayController::ToggleMirrorMode() {
392c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DisplayManager* display_manager = GetDisplayManager();
39390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (display_manager->num_connected_displays() <= 1)
39490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
39590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
396c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (limiter_) {
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if  (limiter_->IsThrottled())
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    limiter_->SetThrottleTimeout(kCycleDisplayThrottleTimeoutMs);
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
401effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#if defined(OS_CHROMEOS)
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Shell* shell = Shell::GetInstance();
4035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DisplayConfiguratorAnimation* animation =
4045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      shell->display_configurator_animation();
405c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  animation->StartFadeOutAnimation(
406f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      base::Bind(&DisplayController::SetMirrorModeAfterAnimation,
407f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr(),
408c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                 !display_manager->IsMirrored()));
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DisplayController::SwapPrimaryDisplay() {
413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (limiter_) {
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if  (limiter_->IsThrottled())
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    limiter_->SetThrottleTimeout(kSwapDisplayThrottleTimeoutMs);
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (Shell::GetScreen()->GetNumDisplays() > 1) {
420effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#if defined(OS_CHROMEOS)
4215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    DisplayConfiguratorAnimation* animation =
4225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        Shell::GetInstance()->display_configurator_animation();
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (animation) {
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      animation->StartFadeOutAnimation(base::Bind(
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          &DisplayController::OnFadeOutForSwapDisplayFinished,
426f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          weak_ptr_factory_.GetWeakPtr()));
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
4285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      SetPrimaryDisplay(ScreenUtil::GetSecondaryDisplay());
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else
4315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    SetPrimaryDisplay(ScreenUtil::GetSecondaryDisplay());
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DisplayController::SetPrimaryDisplayId(int64 id) {
437c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK_NE(gfx::Display::kInvalidDisplayID, id);
438c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (id == gfx::Display::kInvalidDisplayID || primary_display_id == id)
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
441c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const gfx::Display& display = GetDisplayManager()->GetDisplayForId(id);
442c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (display.is_valid())
443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SetPrimaryDisplay(display);
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DisplayController::SetPrimaryDisplay(
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Display& new_primary_display) {
448c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DisplayManager* display_manager = GetDisplayManager();
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(new_primary_display.is_valid());
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(display_manager->IsActiveDisplay(new_primary_display));
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!new_primary_display.is_valid() ||
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !display_manager->IsActiveDisplay(new_primary_display)) {
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Invalid or non-existent display is requested:"
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << new_primary_display.ToString();
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (primary_display_id == new_primary_display.id() ||
460a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      window_tree_hosts_.size() < 2) {
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
464a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  AshWindowTreeHost* non_primary_host =
465a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      window_tree_hosts_[new_primary_display.id()];
466a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  LOG_IF(ERROR, !non_primary_host)
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      << "Unknown display is requested in SetPrimaryDisplay: id="
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      << new_primary_display.id();
469a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (!non_primary_host)
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gfx::Display old_primary_display = Shell::GetScreen()->GetPrimaryDisplay();
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Swap root windows between current and new primary display.
475a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  AshWindowTreeHost* primary_host = window_tree_hosts_[primary_display_id];
476f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK(primary_host);
477f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK_NE(primary_host, non_primary_host);
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
479a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  window_tree_hosts_[new_primary_display.id()] = primary_host;
480a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  GetRootWindowSettings(GetWindow(primary_host))->display_id =
481a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      new_primary_display.id();
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
483a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  window_tree_hosts_[old_primary_display.id()] = non_primary_host;
484a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  GetRootWindowSettings(GetWindow(non_primary_host))->display_id =
48558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      old_primary_display.id();
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  primary_display_id = new_primary_display.id();
4887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  GetDisplayManager()->layout_store()->UpdatePrimaryDisplayId(
4893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      display_manager->GetCurrentDisplayIdPair(), primary_display_id);
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
491a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  UpdateWorkAreaOfDisplayNearestWindow(GetWindow(primary_host),
492a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                       old_primary_display.GetWorkAreaInsets());
493a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  UpdateWorkAreaOfDisplayNearestWindow(GetWindow(non_primary_host),
494a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                       new_primary_display.GetWorkAreaInsets());
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Update the dispay manager with new display info.
497c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  std::vector<DisplayInfo> display_info_list;
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  display_info_list.push_back(display_manager->GetDisplayInfo(
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      primary_display_id));
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  display_info_list.push_back(display_manager->GetDisplayInfo(
5015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ScreenUtil::GetSecondaryDisplay().id()));
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetDisplayManager()->set_force_bounds_changed(true);
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GetDisplayManager()->UpdateDisplays(display_info_list);
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetDisplayManager()->set_force_bounds_changed(false);
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
507c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void DisplayController::EnsurePointerInDisplays() {
5087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // If the mouse is currently on a display in native location,
5097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // use the same native location. Otherwise find the display closest
5107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // to the current cursor location in screen coordinates.
5117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
5127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  gfx::Point point_in_screen = Shell::GetScreen()->GetCursorScreenPoint();
5137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  gfx::Point target_location_in_native;
514c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int64 closest_distance_squared = -1;
515c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DisplayManager* display_manager = GetDisplayManager();
516c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  aura::Window* dst_root_window = NULL;
518c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) {
519ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const gfx::Display& display = display_manager->GetDisplayAt(i);
520c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const DisplayInfo display_info =
521ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        display_manager->GetDisplayInfo(display.id());
5221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    aura::Window* root_window = GetRootWindowForDisplayId(display.id());
52368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (display_info.bounds_in_native().Contains(
5247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            cursor_location_in_native_coords_for_restore_)) {
525c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      dst_root_window = root_window;
5267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      target_location_in_native = cursor_location_in_native_coords_for_restore_;
527c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
528c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
529ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    gfx::Point center = display.bounds().CenterPoint();
530c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Use the distance squared from the center of the dislay. This is not
531c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // exactly "closest" display, but good enough to pick one
532c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // appropriate (and there are at most two displays).
533c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // We don't care about actual distance, only relative to other displays, so
534c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // using the LengthSquared() is cheaper than Length().
535c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int64 distance_squared = (center - point_in_screen).LengthSquared();
537c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (closest_distance_squared < 0 ||
538c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        closest_distance_squared > distance_squared) {
5391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      aura::Window* root_window = GetRootWindowForDisplayId(display.id());
5407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      aura::client::ScreenPositionClient* client =
5417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          aura::client::GetScreenPositionClient(root_window);
5427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      client->ConvertPointFromScreen(root_window, &center);
543a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      root_window->GetHost()->ConvertPointToNativeScreen(&center);
544c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      dst_root_window = root_window;
5457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      target_location_in_native = center;
546c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      closest_distance_squared = distance_squared;
547c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
548c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
549a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  dst_root_window->GetHost()->ConvertPointFromNativeScreen(
5501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      &target_location_in_native);
5517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  dst_root_window->MoveCursorTo(target_location_in_native);
5527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
5537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
5547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool DisplayController::UpdateWorkAreaOfDisplayNearestWindow(
5557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const aura::Window* window,
5567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const gfx::Insets& insets) {
5571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const aura::Window* root_window = window->GetRootWindow();
558c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  int64 id = GetRootWindowSettings(root_window)->display_id;
559ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // if id is |kInvaildDisplayID|, it's being deleted.
560ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DCHECK(id != gfx::Display::kInvalidDisplayID);
561ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return GetDisplayManager()->UpdateWorkAreaOfDisplay(id, insets);
5627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
5637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DisplayController::OnDisplayAdded(const gfx::Display& display) {
565a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (primary_tree_host_for_replace_) {
566a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    DCHECK(window_tree_hosts_.empty());
5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    primary_display_id = display.id();
568a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    window_tree_hosts_[display.id()] = primary_tree_host_for_replace_;
569a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    GetRootWindowSettings(GetWindow(primary_tree_host_for_replace_))
570a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        ->display_id = display.id();
571a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    primary_tree_host_for_replace_ = NULL;
572c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const DisplayInfo& display_info =
5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        GetDisplayManager()->GetDisplayInfo(display.id());
574a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    AshWindowTreeHost* ash_host = window_tree_hosts_[display.id()];
575a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    ash_host->AsWindowTreeHost()->SetBounds(display_info.bounds_in_native());
576a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    SetDisplayPropertiesOnHost(ash_host, display);
5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
578c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (primary_display_id == gfx::Display::kInvalidDisplayID)
579c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      primary_display_id = display.id();
580a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    DCHECK(!window_tree_hosts_.empty());
581cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    AshWindowTreeHost* ash_host = AddWindowTreeHostForDisplay(
582cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        display, AshWindowTreeHostInitParams());
583a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    RootWindowController::CreateForSecondaryDisplay(ash_host);
5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DisplayController::OnDisplayRemoved(const gfx::Display& display) {
588a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  AshWindowTreeHost* host_to_delete = window_tree_hosts_[display.id()];
589f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK(host_to_delete) << display.ToString();
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Display for root window will be deleted when the Primary RootWindow
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is deleted by the Shell.
593a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  window_tree_hosts_.erase(display.id());
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When the primary root window's display is removed, move the primary
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // root to the other display.
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (primary_display_id == display.id()) {
5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Temporarily store the primary root window in
5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // |primary_root_window_for_replace_| when replacing the display.
600a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    if (window_tree_hosts_.size() == 0) {
6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      primary_display_id = gfx::Display::kInvalidDisplayID;
602a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      primary_tree_host_for_replace_ = host_to_delete;
6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
605a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    DCHECK_EQ(1U, window_tree_hosts_.size());
6065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    primary_display_id = ScreenUtil::GetSecondaryDisplay().id();
607a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    AshWindowTreeHost* primary_host = host_to_delete;
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
609a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    // Delete the other host instead.
610a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    host_to_delete = window_tree_hosts_[primary_display_id];
611a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    GetRootWindowSettings(GetWindow(host_to_delete))->display_id = display.id();
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Setup primary root.
614a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    window_tree_hosts_[primary_display_id] = primary_host;
615a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    GetRootWindowSettings(GetWindow(primary_host))->display_id =
616a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        primary_display_id;
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
618cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    OnDisplayMetricsChanged(
619cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        GetDisplayManager()->GetDisplayForId(primary_display_id),
620cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        DISPLAY_METRIC_BOUNDS);
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
622a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  RootWindowController* controller =
623a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      GetRootWindowController(GetWindow(host_to_delete));
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(controller);
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  controller->MoveWindowsTo(GetPrimaryRootWindow());
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Delete most of root window related objects, but don't delete
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // root window itself yet because the stack may be using it.
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  controller->Shutdown();
629c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::MessageLoop::current()->DeleteSoon(FROM_HERE, controller);
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
632cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void DisplayController::OnDisplayMetricsChanged(const gfx::Display& display,
633cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                                uint32_t metrics) {
634cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!(metrics & (DISPLAY_METRIC_BOUNDS | DISPLAY_METRIC_ROTATION |
635cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   DISPLAY_METRIC_DEVICE_SCALE_FACTOR)))
636cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
637cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const DisplayInfo& display_info =
638cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      GetDisplayManager()->GetDisplayInfo(display.id());
639cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(!display_info.bounds_in_native().IsEmpty());
640cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  AshWindowTreeHost* ash_host = window_tree_hosts_[display.id()];
641cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ash_host->AsWindowTreeHost()->SetBounds(display_info.bounds_in_native());
642cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SetDisplayPropertiesOnHost(ash_host, display);
643cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
644cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
645a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void DisplayController::OnHostResized(const aura::WindowTreeHost* host) {
6465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gfx::Display display = Shell::GetScreen()->GetDisplayNearestWindow(
647a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      const_cast<aura::Window*>(host->window()));
6485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
649c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DisplayManager* display_manager = GetDisplayManager();
650a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (display_manager->UpdateDisplayBounds(display.id(), host->GetBounds())) {
6517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    mirror_window_controller_->UpdateWindow();
6525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    cursor_window_controller_->UpdateContainer();
6537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
6547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
6557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
6561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void DisplayController::CreateOrUpdateNonDesktopDisplay(
657c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const DisplayInfo& info) {
6581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  switch (GetDisplayManager()->second_display_mode()) {
659c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case DisplayManager::MIRRORING:
6601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      mirror_window_controller_->UpdateWindow(info);
6615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      cursor_window_controller_->UpdateContainer();
6621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      break;
663c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case DisplayManager::EXTENDED:
6641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      NOTREACHED();
6651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
6667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
6677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
6681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void DisplayController::CloseNonDesktopDisplay() {
6697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  mirror_window_controller_->Close();
6701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // If cursor_compositing is enabled for large cursor, the cursor window is
6711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // always on the desktop display (the visible cursor on the non-desktop
6721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // display is drawn through compositor mirroring). Therefore, it's unnecessary
6731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // to handle the cursor_window at all. See: http://crbug.com/412910
6741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!cursor_window_controller_->is_cursor_compositing_enabled())
6751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    cursor_window_controller_->UpdateContainer();
6767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
6777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
678f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void DisplayController::PreDisplayConfigurationChange(bool clear_focus) {
6797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  FOR_EACH_OBSERVER(Observer, observers_, OnDisplayConfigurationChanging());
680f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  focus_activation_store_->Store(clear_focus);
6815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gfx::Screen* screen = Shell::GetScreen();
6825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gfx::Point point_in_screen = screen->GetCursorScreenPoint();
6835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gfx::Display display = screen->GetDisplayNearestPoint(point_in_screen);
6841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  aura::Window* root_window = GetRootWindowForDisplayId(display.id());
6857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
6867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  aura::client::ScreenPositionClient* client =
6877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      aura::client::GetScreenPositionClient(root_window);
6887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  client->ConvertPointFromScreen(root_window, &point_in_screen);
689a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  root_window->GetHost()->ConvertPointToNativeScreen(&point_in_screen);
6907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  cursor_location_in_native_coords_for_restore_ = point_in_screen;
6917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
6927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
6937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid DisplayController::PostDisplayConfigurationChange() {
6947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (limiter_)
6957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    limiter_->SetThrottleTimeout(kAfterDisplayChangeThrottleTimeoutMs);
6967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
6977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  focus_activation_store_->Restore();
6987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
699c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DisplayManager* display_manager = GetDisplayManager();
700c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DisplayLayoutStore* layout_store = display_manager->layout_store();
7017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (display_manager->num_connected_displays() > 1) {
7023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    DisplayIdPair pair = display_manager->GetCurrentDisplayIdPair();
7037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    layout_store->UpdateMirrorStatus(pair, display_manager->IsMirrored());
7047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    DisplayLayout layout = layout_store->GetRegisteredDisplayLayout(pair);
7057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
7067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (Shell::GetScreen()->GetNumDisplays() > 1 ) {
7077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      int64 primary_id = layout.primary_id;
7087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      SetPrimaryDisplayId(
7097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          primary_id == gfx::Display::kInvalidDisplayID ?
7107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          pair.first : primary_id);
7117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      // Update the primary_id in case the above call is
7127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      // ignored. Happens when a) default layout's primary id
7137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      // doesn't exist, or b) the primary_id has already been
7147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      // set to the same and didn't update it.
7155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      layout_store->UpdatePrimaryDisplayId(
7165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          pair, Shell::GetScreen()->GetPrimaryDisplay().id());
7177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
7187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
7197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  FOR_EACH_OBSERVER(Observer, observers_, OnDisplayConfigurationChanged());
7207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  UpdateHostWindowNames();
7217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EnsurePointerInDisplays();
7227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
7237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
724a02191e04bc25c4935f804f2c080ae28663d096dBen MurdochAshWindowTreeHost* DisplayController::AddWindowTreeHostForDisplay(
725cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const gfx::Display& display,
726cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const AshWindowTreeHostInitParams& init_params) {
727a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  static int host_count = 0;
728c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  const DisplayInfo& display_info =
7292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetDisplayManager()->GetDisplayInfo(display.id());
730cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  AshWindowTreeHostInitParams params_with_bounds(init_params);
731cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  params_with_bounds.initial_bounds = display_info.bounds_in_native();
732cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  AshWindowTreeHost* ash_host = AshWindowTreeHost::Create(params_with_bounds);
733a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  aura::WindowTreeHost* host = ash_host->AsWindowTreeHost();
734a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
735a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  host->window()->SetName(base::StringPrintf("RootWindow-%d", host_count++));
736116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  host->window()->SetTitle(base::UTF8ToUTF16(display_info.name()));
737a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  host->compositor()->SetBackgroundColor(SK_ColorBLACK);
738a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // No need to remove our observer observer because the DisplayController
739a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // outlives the host.
740a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  host->AddObserver(this);
741c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  InitRootWindowSettings(host->window())->display_id = display.id();
742a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  host->InitHost();
743a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
744a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  window_tree_hosts_[display.id()] = ash_host;
745a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  SetDisplayPropertiesOnHost(ash_host, display);
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS)
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static bool force_constrain_pointer_to_root =
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CommandLine::ForCurrentProcess()->HasSwitch(
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          switches::kAshConstrainPointerToRoot);
7514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (base::SysInfo::IsRunningOnChromeOS() || force_constrain_pointer_to_root)
752a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    ash_host->ConfineCursorToRootWindow();
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
754a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  return ash_host;
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DisplayController::OnFadeOutForSwapDisplayFinished() {
758effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#if defined(OS_CHROMEOS)
7595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetPrimaryDisplay(ScreenUtil::GetSecondaryDisplay());
7605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  Shell::GetInstance()->display_configurator_animation()
7615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      ->StartFadeInAnimation();
7622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
7632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
765f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void DisplayController::SetMirrorModeAfterAnimation(bool mirror) {
766f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  GetDisplayManager()->SetMirrorMode(mirror);
767f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
768f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
769eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid DisplayController::UpdateHostWindowNames() {
770eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(USE_X11)
771eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // crbug.com/120229 - set the window title for the primary dislpay
772eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // to "aura_root_0" so gtalk can find the primary root window to broadcast.
773eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // TODO(jhorwich) Remove this once Chrome supports window-based broadcasting.
7741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  aura::Window* primary = Shell::GetPrimaryRootWindow();
775f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  aura::Window::Windows root_windows = Shell::GetAllRootWindows();
776eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  for (size_t i = 0; i < root_windows.size(); ++i) {
777eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    std::string name =
778eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        root_windows[i] == primary ? "aura_root_0" : "aura_root_x";
7791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    gfx::AcceleratedWidget xwindow =
780a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        root_windows[i]->GetHost()->GetAcceleratedWidget();
78168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    XStoreName(gfx::GetXDisplay(), xwindow, name.c_str());
782eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
783eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif
784eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
785eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace ash
787