1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ash/display/display_controller.h"
11 #include "ash/ash_switches.h"
12 #include "ash/display/cursor_window_controller.h"
13 #include "ash/display/display_layout_store.h"
14 #include "ash/display/display_manager.h"
15 #include "ash/display/mirror_window_controller.h"
16 #include "ash/display/root_window_transformers.h"
17 #include "ash/display/virtual_keyboard_window_controller.h"
18 #include "ash/host/ash_window_tree_host.h"
19 #include "ash/host/root_window_transformer.h"
20 #include "ash/root_window_controller.h"
21 #include "ash/root_window_settings.h"
22 #include "ash/screen_util.h"
23 #include "ash/shell.h"
24 #include "ash/shell_delegate.h"
25 #include "ash/wm/coordinate_conversion.h"
26 #include "base/command_line.h"
27 #include "base/strings/stringprintf.h"
28 #include "ui/aura/client/capture_client.h"
29 #include "ui/aura/client/focus_client.h"
30 #include "ui/aura/client/screen_position_client.h"
31 #include "ui/aura/window.h"
32 #include "ui/aura/window_event_dispatcher.h"
33 #include "ui/aura/window_property.h"
34 #include "ui/aura/window_tracker.h"
35 #include "ui/aura/window_tree_host.h"
36 #include "ui/compositor/compositor.h"
37 #include "ui/compositor/compositor_vsync_manager.h"
38 #include "ui/gfx/display.h"
39 #include "ui/gfx/screen.h"
40 #include "ui/wm/public/activation_client.h"
42 #if defined(OS_CHROMEOS)
43 #include "ash/display/display_configurator_animation.h"
44 #include "base/sys_info.h"
45 #include "base/time/time.h"
47 #include "ui/base/x/x11_util.h"
48 #include "ui/gfx/x/x11_types.h"
50 // Including this at the bottom to avoid other
51 // potential conflict with chrome headers.
52 #include <X11/extensions/Xrandr.h>
54 #endif // defined(USE_X11)
55 #endif // defined(OS_CHROMEOS)
60 // Primary display stored in global object as it can be
61 // accessed after Shell is deleted. A separate display instance is created
62 // during the shutdown instead of always keeping two display instances
63 // (one here and another one in display_manager) in sync, which is error prone.
64 int64 primary_display_id = gfx::Display::kInvalidDisplayID;
66 // Specifies how long the display change should have been disabled
67 // after each display change operations.
68 // |kCycleDisplayThrottleTimeoutMs| is set to be longer to avoid
69 // changing the settings while the system is still configurating
70 // displays. It will be overriden by |kAfterDisplayChangeThrottleTimeoutMs|
71 // when the display change happens, so the actual timeout is much shorter.
72 const int64 kAfterDisplayChangeThrottleTimeoutMs = 500;
73 const int64 kCycleDisplayThrottleTimeoutMs = 4000;
74 const int64 kSwapDisplayThrottleTimeoutMs = 500;
76 DisplayManager* GetDisplayManager() {
77 return Shell::GetInstance()->display_manager();
80 void SetDisplayPropertiesOnHost(AshWindowTreeHost* ash_host,
81 const gfx::Display& display) {
82 DisplayInfo info = GetDisplayManager()->GetDisplayInfo(display.id());
83 aura::WindowTreeHost* host = ash_host->AsWindowTreeHost();
84 #if defined(OS_CHROMEOS) && defined(USE_X11)
85 // Native window property (Atom in X11) that specifies the display's
86 // rotation, scale factor and if it's internal display. They are
87 // read and used by touchpad/mouse driver directly on X (contact
88 // adlr@ for more details on touchpad/mouse driver side). The value
89 // of the rotation is one of 0 (normal), 1 (90 degrees clockwise), 2
90 // (180 degree) or 3 (270 degrees clockwise). The value of the
91 // scale factor is in percent (100, 140, 200 etc).
92 const char kRotationProp[] = "_CHROME_DISPLAY_ROTATION";
93 const char kScaleFactorProp[] = "_CHROME_DISPLAY_SCALE_FACTOR";
94 const char kInternalProp[] = "_CHROME_DISPLAY_INTERNAL";
95 const char kCARDINAL[] = "CARDINAL";
96 int xrandr_rotation = RR_Rotate_0;
97 switch (info.rotation()) {
98 case gfx::Display::ROTATE_0:
99 xrandr_rotation = RR_Rotate_0;
101 case gfx::Display::ROTATE_90:
102 xrandr_rotation = RR_Rotate_90;
104 case gfx::Display::ROTATE_180:
105 xrandr_rotation = RR_Rotate_180;
107 case gfx::Display::ROTATE_270:
108 xrandr_rotation = RR_Rotate_270;
112 int internal = display.IsInternal() ? 1 : 0;
113 gfx::AcceleratedWidget xwindow = host->GetAcceleratedWidget();
114 ui::SetIntProperty(xwindow, kInternalProp, kCARDINAL, internal);
115 ui::SetIntProperty(xwindow, kRotationProp, kCARDINAL, xrandr_rotation);
116 ui::SetIntProperty(xwindow,
119 100 * display.device_scale_factor());
121 scoped_ptr<RootWindowTransformer> transformer(
122 CreateRootWindowTransformerForDisplay(host->window(), display));
123 ash_host->SetRootWindowTransformer(transformer.Pass());
126 if (GetDisplayManager()->GetSelectedModeForDisplayId(display.id(), &mode) &&
127 mode.refresh_rate > 0.0f) {
128 host->compositor()->vsync_manager()->SetAuthoritativeVSyncInterval(
129 base::TimeDelta::FromMicroseconds(
130 base::Time::kMicrosecondsPerSecond / mode.refresh_rate));
134 aura::Window* GetWindow(AshWindowTreeHost* ash_host) {
135 return ash_host->AsWindowTreeHost()->window();
140 // A utility class to store/restore focused/active window
141 // when the display configuration has changed.
142 class FocusActivationStore {
144 FocusActivationStore()
145 : activation_client_(NULL),
146 capture_client_(NULL),
152 void Store(bool clear_focus) {
153 if (!activation_client_) {
154 aura::Window* root = Shell::GetPrimaryRootWindow();
155 activation_client_ = aura::client::GetActivationClient(root);
156 capture_client_ = aura::client::GetCaptureClient(root);
157 focus_client_ = aura::client::GetFocusClient(root);
159 focused_ = focus_client_->GetFocusedWindow();
161 tracker_.Add(focused_);
162 active_ = activation_client_->GetActiveWindow();
163 if (active_ && focused_ != active_)
164 tracker_.Add(active_);
166 // Deactivate the window to close menu / bubble windows.
168 activation_client_->DeactivateWindow(active_);
170 // Release capture if any.
171 capture_client_->SetCapture(NULL);
172 // Clear the focused window if any. This is necessary because a
173 // window may be deleted when losing focus (fullscreen flash for
174 // example). If the focused window is still alive after move, it'll
175 // be re-focused below.
177 focus_client_->FocusWindow(NULL);
181 // Restore focused or active window if it's still alive.
182 if (focused_ && tracker_.Contains(focused_)) {
183 focus_client_->FocusWindow(focused_);
184 } else if (active_ && tracker_.Contains(active_)) {
185 activation_client_->ActivateWindow(active_);
188 tracker_.Remove(focused_);
190 tracker_.Remove(active_);
196 aura::client::ActivationClient* activation_client_;
197 aura::client::CaptureClient* capture_client_;
198 aura::client::FocusClient* focus_client_;
199 aura::WindowTracker tracker_;
200 aura::Window* focused_;
201 aura::Window* active_;
203 DISALLOW_COPY_AND_ASSIGN(FocusActivationStore);
206 ////////////////////////////////////////////////////////////////////////////////
207 // DisplayChangeLimiter
209 DisplayController::DisplayChangeLimiter::DisplayChangeLimiter()
210 : throttle_timeout_(base::Time::Now()) {
213 void DisplayController::DisplayChangeLimiter::SetThrottleTimeout(
216 base::Time::Now() + base::TimeDelta::FromMilliseconds(throttle_ms);
219 bool DisplayController::DisplayChangeLimiter::IsThrottled() const {
220 return base::Time::Now() < throttle_timeout_;
223 ////////////////////////////////////////////////////////////////////////////////
226 DisplayController::DisplayController()
227 : primary_tree_host_for_replace_(NULL),
228 focus_activation_store_(new FocusActivationStore()),
229 cursor_window_controller_(new CursorWindowController()),
230 mirror_window_controller_(new MirrorWindowController()) {
231 #if defined(OS_CHROMEOS)
232 if (base::SysInfo::IsRunningOnChromeOS())
233 limiter_.reset(new DisplayChangeLimiter);
235 // Reset primary display to make sure that tests don't use
236 // stale display info from previous tests.
237 primary_display_id = gfx::Display::kInvalidDisplayID;
240 DisplayController::~DisplayController() {
243 void DisplayController::Start() {
244 // Created here so that Shell has finished being created. Adds itself
245 // as a ShellObserver.
246 virtual_keyboard_window_controller_.reset(
247 new VirtualKeyboardWindowController);
248 Shell::GetScreen()->AddObserver(this);
249 Shell::GetInstance()->display_manager()->set_delegate(this);
251 FOR_EACH_OBSERVER(Observer, observers_, OnDisplaysInitialized());
254 void DisplayController::Shutdown() {
255 // Unset the display manager's delegate here because
256 // DisplayManager outlives DisplayController.
257 Shell::GetInstance()->display_manager()->set_delegate(NULL);
259 cursor_window_controller_.reset();
260 mirror_window_controller_.reset();
261 virtual_keyboard_window_controller_.reset();
263 Shell::GetScreen()->RemoveObserver(this);
264 // Delete all root window controllers, which deletes root window
265 // from the last so that the primary root window gets deleted last.
266 for (WindowTreeHostMap::const_reverse_iterator it =
267 window_tree_hosts_.rbegin();
268 it != window_tree_hosts_.rend();
270 RootWindowController* controller =
271 GetRootWindowController(GetWindow(it->second));
277 void DisplayController::CreatePrimaryHost() {
278 const gfx::Display& primary_candidate =
279 GetDisplayManager()->GetPrimaryDisplayCandidate();
280 primary_display_id = primary_candidate.id();
281 AddWindowTreeHostForDisplay(primary_candidate);
284 void DisplayController::InitDisplays() {
285 RootWindowController::CreateForPrimaryDisplay(
286 window_tree_hosts_[primary_display_id]);
288 DisplayManager* display_manager = GetDisplayManager();
289 for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) {
290 const gfx::Display& display = display_manager->GetDisplayAt(i);
291 if (primary_display_id != display.id()) {
292 AshWindowTreeHost* ash_host = AddWindowTreeHostForDisplay(display);
293 RootWindowController::CreateForSecondaryDisplay(ash_host);
296 UpdateHostWindowNames();
299 void DisplayController::AddObserver(Observer* observer) {
300 observers_.AddObserver(observer);
303 void DisplayController::RemoveObserver(Observer* observer) {
304 observers_.RemoveObserver(observer);
308 int64 DisplayController::GetPrimaryDisplayId() {
309 return primary_display_id;
312 aura::Window* DisplayController::GetPrimaryRootWindow() {
313 return GetRootWindowForDisplayId(primary_display_id);
316 aura::Window* DisplayController::GetRootWindowForDisplayId(int64 id) {
317 DCHECK_EQ(1u, window_tree_hosts_.count(id));
318 return GetWindow(window_tree_hosts_[id]);
321 void DisplayController::CloseChildWindows() {
322 for (WindowTreeHostMap::const_iterator it = window_tree_hosts_.begin();
323 it != window_tree_hosts_.end();
325 aura::Window* root_window = GetWindow(it->second);
326 RootWindowController* controller = GetRootWindowController(root_window);
328 controller->CloseChildWindows();
330 while (!root_window->children().empty()) {
331 aura::Window* child = root_window->children()[0];
338 aura::Window::Windows DisplayController::GetAllRootWindows() {
339 aura::Window::Windows windows;
340 for (WindowTreeHostMap::const_iterator it = window_tree_hosts_.begin();
341 it != window_tree_hosts_.end();
344 if (GetRootWindowController(GetWindow(it->second)))
345 windows.push_back(GetWindow(it->second));
350 gfx::Insets DisplayController::GetOverscanInsets(int64 display_id) const {
351 return GetDisplayManager()->GetOverscanInsets(display_id);
354 void DisplayController::SetOverscanInsets(int64 display_id,
355 const gfx::Insets& insets_in_dip) {
356 GetDisplayManager()->SetOverscanInsets(display_id, insets_in_dip);
359 std::vector<RootWindowController*>
360 DisplayController::GetAllRootWindowControllers() {
361 std::vector<RootWindowController*> controllers;
362 for (WindowTreeHostMap::const_iterator it = window_tree_hosts_.begin();
363 it != window_tree_hosts_.end();
365 RootWindowController* controller =
366 GetRootWindowController(GetWindow(it->second));
368 controllers.push_back(controller);
373 void DisplayController::ToggleMirrorMode() {
374 DisplayManager* display_manager = GetDisplayManager();
375 if (display_manager->num_connected_displays() <= 1)
379 if (limiter_->IsThrottled())
381 limiter_->SetThrottleTimeout(kCycleDisplayThrottleTimeoutMs);
383 #if defined(OS_CHROMEOS)
384 Shell* shell = Shell::GetInstance();
385 DisplayConfiguratorAnimation* animation =
386 shell->display_configurator_animation();
387 animation->StartFadeOutAnimation(
388 base::Bind(base::IgnoreResult(&DisplayManager::SetMirrorMode),
389 base::Unretained(display_manager),
390 !display_manager->IsMirrored()));
394 void DisplayController::SwapPrimaryDisplay() {
396 if (limiter_->IsThrottled())
398 limiter_->SetThrottleTimeout(kSwapDisplayThrottleTimeoutMs);
401 if (Shell::GetScreen()->GetNumDisplays() > 1) {
402 #if defined(OS_CHROMEOS)
403 DisplayConfiguratorAnimation* animation =
404 Shell::GetInstance()->display_configurator_animation();
406 animation->StartFadeOutAnimation(base::Bind(
407 &DisplayController::OnFadeOutForSwapDisplayFinished,
408 base::Unretained(this)));
410 SetPrimaryDisplay(ScreenUtil::GetSecondaryDisplay());
413 SetPrimaryDisplay(ScreenUtil::GetSecondaryDisplay());
418 void DisplayController::SetPrimaryDisplayId(int64 id) {
419 DCHECK_NE(gfx::Display::kInvalidDisplayID, id);
420 if (id == gfx::Display::kInvalidDisplayID || primary_display_id == id)
423 const gfx::Display& display = GetDisplayManager()->GetDisplayForId(id);
424 if (display.is_valid())
425 SetPrimaryDisplay(display);
428 void DisplayController::SetPrimaryDisplay(
429 const gfx::Display& new_primary_display) {
430 DisplayManager* display_manager = GetDisplayManager();
431 DCHECK(new_primary_display.is_valid());
432 DCHECK(display_manager->IsActiveDisplay(new_primary_display));
434 if (!new_primary_display.is_valid() ||
435 !display_manager->IsActiveDisplay(new_primary_display)) {
436 LOG(ERROR) << "Invalid or non-existent display is requested:"
437 << new_primary_display.ToString();
441 if (primary_display_id == new_primary_display.id() ||
442 window_tree_hosts_.size() < 2) {
446 AshWindowTreeHost* non_primary_host =
447 window_tree_hosts_[new_primary_display.id()];
448 LOG_IF(ERROR, !non_primary_host)
449 << "Unknown display is requested in SetPrimaryDisplay: id="
450 << new_primary_display.id();
451 if (!non_primary_host)
454 gfx::Display old_primary_display = Shell::GetScreen()->GetPrimaryDisplay();
456 // Swap root windows between current and new primary display.
457 AshWindowTreeHost* primary_host = window_tree_hosts_[primary_display_id];
458 DCHECK(primary_host);
459 DCHECK_NE(primary_host, non_primary_host);
461 window_tree_hosts_[new_primary_display.id()] = primary_host;
462 GetRootWindowSettings(GetWindow(primary_host))->display_id =
463 new_primary_display.id();
465 window_tree_hosts_[old_primary_display.id()] = non_primary_host;
466 GetRootWindowSettings(GetWindow(non_primary_host))->display_id =
467 old_primary_display.id();
469 primary_display_id = new_primary_display.id();
470 GetDisplayManager()->layout_store()->UpdatePrimaryDisplayId(
471 display_manager->GetCurrentDisplayIdPair(), primary_display_id);
473 UpdateWorkAreaOfDisplayNearestWindow(GetWindow(primary_host),
474 old_primary_display.GetWorkAreaInsets());
475 UpdateWorkAreaOfDisplayNearestWindow(GetWindow(non_primary_host),
476 new_primary_display.GetWorkAreaInsets());
478 // Update the dispay manager with new display info.
479 std::vector<DisplayInfo> display_info_list;
480 display_info_list.push_back(display_manager->GetDisplayInfo(
481 primary_display_id));
482 display_info_list.push_back(display_manager->GetDisplayInfo(
483 ScreenUtil::GetSecondaryDisplay().id()));
484 GetDisplayManager()->set_force_bounds_changed(true);
485 GetDisplayManager()->UpdateDisplays(display_info_list);
486 GetDisplayManager()->set_force_bounds_changed(false);
489 void DisplayController::EnsurePointerInDisplays() {
490 // If the mouse is currently on a display in native location,
491 // use the same native location. Otherwise find the display closest
492 // to the current cursor location in screen coordinates.
494 gfx::Point point_in_screen = Shell::GetScreen()->GetCursorScreenPoint();
495 gfx::Point target_location_in_native;
496 int64 closest_distance_squared = -1;
497 DisplayManager* display_manager = GetDisplayManager();
499 aura::Window* dst_root_window = NULL;
500 for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) {
501 const gfx::Display& display = display_manager->GetDisplayAt(i);
502 const DisplayInfo display_info =
503 display_manager->GetDisplayInfo(display.id());
504 aura::Window* root_window = GetRootWindowForDisplayId(display.id());
505 if (display_info.bounds_in_native().Contains(
506 cursor_location_in_native_coords_for_restore_)) {
507 dst_root_window = root_window;
508 target_location_in_native = cursor_location_in_native_coords_for_restore_;
511 gfx::Point center = display.bounds().CenterPoint();
512 // Use the distance squared from the center of the dislay. This is not
513 // exactly "closest" display, but good enough to pick one
514 // appropriate (and there are at most two displays).
515 // We don't care about actual distance, only relative to other displays, so
516 // using the LengthSquared() is cheaper than Length().
518 int64 distance_squared = (center - point_in_screen).LengthSquared();
519 if (closest_distance_squared < 0 ||
520 closest_distance_squared > distance_squared) {
521 aura::Window* root_window = GetRootWindowForDisplayId(display.id());
522 aura::client::ScreenPositionClient* client =
523 aura::client::GetScreenPositionClient(root_window);
524 client->ConvertPointFromScreen(root_window, ¢er);
525 root_window->GetHost()->ConvertPointToNativeScreen(¢er);
526 dst_root_window = root_window;
527 target_location_in_native = center;
528 closest_distance_squared = distance_squared;
531 dst_root_window->GetHost()->ConvertPointFromNativeScreen(
532 &target_location_in_native);
533 dst_root_window->MoveCursorTo(target_location_in_native);
536 bool DisplayController::UpdateWorkAreaOfDisplayNearestWindow(
537 const aura::Window* window,
538 const gfx::Insets& insets) {
539 const aura::Window* root_window = window->GetRootWindow();
540 int64 id = GetRootWindowSettings(root_window)->display_id;
541 // if id is |kInvaildDisplayID|, it's being deleted.
542 DCHECK(id != gfx::Display::kInvalidDisplayID);
543 return GetDisplayManager()->UpdateWorkAreaOfDisplay(id, insets);
546 void DisplayController::OnDisplayBoundsChanged(const gfx::Display& display) {
547 const DisplayInfo& display_info =
548 GetDisplayManager()->GetDisplayInfo(display.id());
549 DCHECK(!display_info.bounds_in_native().IsEmpty());
550 AshWindowTreeHost* ash_host = window_tree_hosts_[display.id()];
551 ash_host->AsWindowTreeHost()->SetBounds(display_info.bounds_in_native());
552 SetDisplayPropertiesOnHost(ash_host, display);
555 void DisplayController::OnDisplayAdded(const gfx::Display& display) {
556 if (primary_tree_host_for_replace_) {
557 DCHECK(window_tree_hosts_.empty());
558 primary_display_id = display.id();
559 window_tree_hosts_[display.id()] = primary_tree_host_for_replace_;
560 GetRootWindowSettings(GetWindow(primary_tree_host_for_replace_))
561 ->display_id = display.id();
562 primary_tree_host_for_replace_ = NULL;
563 const DisplayInfo& display_info =
564 GetDisplayManager()->GetDisplayInfo(display.id());
565 AshWindowTreeHost* ash_host = window_tree_hosts_[display.id()];
566 ash_host->AsWindowTreeHost()->SetBounds(display_info.bounds_in_native());
567 SetDisplayPropertiesOnHost(ash_host, display);
569 if (primary_display_id == gfx::Display::kInvalidDisplayID)
570 primary_display_id = display.id();
571 DCHECK(!window_tree_hosts_.empty());
572 AshWindowTreeHost* ash_host = AddWindowTreeHostForDisplay(display);
573 RootWindowController::CreateForSecondaryDisplay(ash_host);
577 void DisplayController::OnDisplayRemoved(const gfx::Display& display) {
578 AshWindowTreeHost* host_to_delete = window_tree_hosts_[display.id()];
579 DCHECK(host_to_delete) << display.ToString();
581 // Display for root window will be deleted when the Primary RootWindow
582 // is deleted by the Shell.
583 window_tree_hosts_.erase(display.id());
585 // When the primary root window's display is removed, move the primary
586 // root to the other display.
587 if (primary_display_id == display.id()) {
588 // Temporarily store the primary root window in
589 // |primary_root_window_for_replace_| when replacing the display.
590 if (window_tree_hosts_.size() == 0) {
591 primary_display_id = gfx::Display::kInvalidDisplayID;
592 primary_tree_host_for_replace_ = host_to_delete;
595 DCHECK_EQ(1U, window_tree_hosts_.size());
596 primary_display_id = ScreenUtil::GetSecondaryDisplay().id();
597 AshWindowTreeHost* primary_host = host_to_delete;
599 // Delete the other host instead.
600 host_to_delete = window_tree_hosts_[primary_display_id];
601 GetRootWindowSettings(GetWindow(host_to_delete))->display_id = display.id();
603 // Setup primary root.
604 window_tree_hosts_[primary_display_id] = primary_host;
605 GetRootWindowSettings(GetWindow(primary_host))->display_id =
608 OnDisplayBoundsChanged(
609 GetDisplayManager()->GetDisplayForId(primary_display_id));
611 RootWindowController* controller =
612 GetRootWindowController(GetWindow(host_to_delete));
614 controller->MoveWindowsTo(GetPrimaryRootWindow());
615 // Delete most of root window related objects, but don't delete
616 // root window itself yet because the stack may be using it.
617 controller->Shutdown();
618 base::MessageLoop::current()->DeleteSoon(FROM_HERE, controller);
621 void DisplayController::OnHostResized(const aura::WindowTreeHost* host) {
622 gfx::Display display = Shell::GetScreen()->GetDisplayNearestWindow(
623 const_cast<aura::Window*>(host->window()));
625 DisplayManager* display_manager = GetDisplayManager();
626 if (display_manager->UpdateDisplayBounds(display.id(), host->GetBounds())) {
627 mirror_window_controller_->UpdateWindow();
628 cursor_window_controller_->UpdateContainer();
632 void DisplayController::CreateOrUpdateNonDesktopDisplay(
633 const DisplayInfo& info) {
634 switch (GetDisplayManager()->second_display_mode()) {
635 case DisplayManager::MIRRORING:
636 mirror_window_controller_->UpdateWindow(info);
637 cursor_window_controller_->UpdateContainer();
638 virtual_keyboard_window_controller_->Close();
640 case DisplayManager::VIRTUAL_KEYBOARD:
641 mirror_window_controller_->Close();
642 cursor_window_controller_->UpdateContainer();
643 virtual_keyboard_window_controller_->UpdateWindow(info);
645 case DisplayManager::EXTENDED:
650 void DisplayController::CloseNonDesktopDisplay() {
651 mirror_window_controller_->Close();
652 cursor_window_controller_->UpdateContainer();
653 virtual_keyboard_window_controller_->Close();
656 void DisplayController::PreDisplayConfigurationChange(bool clear_focus) {
657 FOR_EACH_OBSERVER(Observer, observers_, OnDisplayConfigurationChanging());
658 focus_activation_store_->Store(clear_focus);
659 gfx::Screen* screen = Shell::GetScreen();
660 gfx::Point point_in_screen = screen->GetCursorScreenPoint();
661 gfx::Display display = screen->GetDisplayNearestPoint(point_in_screen);
662 aura::Window* root_window = GetRootWindowForDisplayId(display.id());
664 aura::client::ScreenPositionClient* client =
665 aura::client::GetScreenPositionClient(root_window);
666 client->ConvertPointFromScreen(root_window, &point_in_screen);
667 root_window->GetHost()->ConvertPointToNativeScreen(&point_in_screen);
668 cursor_location_in_native_coords_for_restore_ = point_in_screen;
671 void DisplayController::PostDisplayConfigurationChange() {
673 limiter_->SetThrottleTimeout(kAfterDisplayChangeThrottleTimeoutMs);
675 focus_activation_store_->Restore();
677 DisplayManager* display_manager = GetDisplayManager();
678 DisplayLayoutStore* layout_store = display_manager->layout_store();
679 if (display_manager->num_connected_displays() > 1) {
680 DisplayIdPair pair = display_manager->GetCurrentDisplayIdPair();
681 layout_store->UpdateMirrorStatus(pair, display_manager->IsMirrored());
682 DisplayLayout layout = layout_store->GetRegisteredDisplayLayout(pair);
684 if (Shell::GetScreen()->GetNumDisplays() > 1 ) {
685 int64 primary_id = layout.primary_id;
687 primary_id == gfx::Display::kInvalidDisplayID ?
688 pair.first : primary_id);
689 // Update the primary_id in case the above call is
690 // ignored. Happens when a) default layout's primary id
691 // doesn't exist, or b) the primary_id has already been
692 // set to the same and didn't update it.
693 layout_store->UpdatePrimaryDisplayId(
694 pair, Shell::GetScreen()->GetPrimaryDisplay().id());
697 FOR_EACH_OBSERVER(Observer, observers_, OnDisplayConfigurationChanged());
698 UpdateHostWindowNames();
699 EnsurePointerInDisplays();
702 AshWindowTreeHost* DisplayController::AddWindowTreeHostForDisplay(
703 const gfx::Display& display) {
704 static int host_count = 0;
705 const DisplayInfo& display_info =
706 GetDisplayManager()->GetDisplayInfo(display.id());
707 const gfx::Rect& bounds_in_native = display_info.bounds_in_native();
708 AshWindowTreeHost* ash_host = AshWindowTreeHost::Create(bounds_in_native);
709 aura::WindowTreeHost* host = ash_host->AsWindowTreeHost();
711 host->window()->SetName(base::StringPrintf("RootWindow-%d", host_count++));
712 host->compositor()->SetBackgroundColor(SK_ColorBLACK);
713 // No need to remove our observer observer because the DisplayController
714 // outlives the host.
715 host->AddObserver(this);
716 InitRootWindowSettings(host->window())->display_id = display.id();
719 window_tree_hosts_[display.id()] = ash_host;
720 SetDisplayPropertiesOnHost(ash_host, display);
722 #if defined(OS_CHROMEOS)
723 static bool force_constrain_pointer_to_root =
724 CommandLine::ForCurrentProcess()->HasSwitch(
725 switches::kAshConstrainPointerToRoot);
726 if (base::SysInfo::IsRunningOnChromeOS() || force_constrain_pointer_to_root)
727 ash_host->ConfineCursorToRootWindow();
732 void DisplayController::OnFadeOutForSwapDisplayFinished() {
733 #if defined(OS_CHROMEOS)
734 SetPrimaryDisplay(ScreenUtil::GetSecondaryDisplay());
735 Shell::GetInstance()->display_configurator_animation()
736 ->StartFadeInAnimation();
740 void DisplayController::UpdateHostWindowNames() {
742 // crbug.com/120229 - set the window title for the primary dislpay
743 // to "aura_root_0" so gtalk can find the primary root window to broadcast.
744 // TODO(jhorwich) Remove this once Chrome supports window-based broadcasting.
745 aura::Window* primary = Shell::GetPrimaryRootWindow();
746 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
747 for (size_t i = 0; i < root_windows.size(); ++i) {
749 root_windows[i] == primary ? "aura_root_0" : "aura_root_x";
750 gfx::AcceleratedWidget xwindow =
751 root_windows[i]->GetHost()->GetAcceleratedWidget();
752 XStoreName(gfx::GetXDisplay(), xwindow, name.c_str());