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/window_tree_host_factory.h"
19 #include "ash/root_window_controller.h"
20 #include "ash/root_window_settings.h"
21 #include "ash/screen_util.h"
22 #include "ash/shell.h"
23 #include "ash/shell_delegate.h"
24 #include "ash/wm/coordinate_conversion.h"
25 #include "base/command_line.h"
26 #include "base/strings/stringprintf.h"
27 #include "ui/aura/client/activation_client.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/root_window.h"
32 #include "ui/aura/root_window_transformer.h"
33 #include "ui/aura/window.h"
34 #include "ui/aura/window_property.h"
35 #include "ui/aura/window_tracker.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"
41 #if defined(OS_CHROMEOS)
42 #include "base/sys_info.h"
43 #include "base/time/time.h"
45 #include "ash/display/output_configurator_animation.h"
46 #include "chromeos/display/output_configurator.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 internal::DisplayManager* GetDisplayManager() {
77 return Shell::GetInstance()->display_manager();
80 void SetDisplayPropertiesOnHostWindow(aura::RootWindow* root,
81 const gfx::Display& display) {
82 internal::DisplayInfo info =
83 GetDisplayManager()->GetDisplayInfo(display.id());
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 = root->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<aura::RootWindowTransformer> transformer(
122 internal::CreateRootWindowTransformerForDisplay(root->window(), display));
123 root->host()->SetRootWindowTransformer(transformer.Pass());
125 internal::DisplayMode mode;
126 if (GetDisplayManager()->GetSelectedModeForDisplayId(display.id(), &mode) &&
127 mode.refresh_rate > 0.0f) {
128 root->host()->compositor()->vsync_manager()->SetAuthoritativeVSyncInterval(
129 base::TimeDelta::FromMicroseconds(base::Time::kMicrosecondsPerSecond /
138 // A utility class to store/restore focused/active window
139 // when the display configuration has changed.
140 class FocusActivationStore {
142 FocusActivationStore()
143 : activation_client_(NULL),
144 capture_client_(NULL),
150 void Store(bool clear_focus) {
151 if (!activation_client_) {
152 aura::Window* root = Shell::GetPrimaryRootWindow();
153 activation_client_ = aura::client::GetActivationClient(root);
154 capture_client_ = aura::client::GetCaptureClient(root);
155 focus_client_ = aura::client::GetFocusClient(root);
157 focused_ = focus_client_->GetFocusedWindow();
159 tracker_.Add(focused_);
160 active_ = activation_client_->GetActiveWindow();
161 if (active_ && focused_ != active_)
162 tracker_.Add(active_);
164 // Deactivate the window to close menu / bubble windows.
166 activation_client_->DeactivateWindow(active_);
168 // Release capture if any.
169 capture_client_->SetCapture(NULL);
170 // Clear the focused window if any. This is necessary because a
171 // window may be deleted when losing focus (fullscreen flash for
172 // example). If the focused window is still alive after move, it'll
173 // be re-focused below.
175 focus_client_->FocusWindow(NULL);
179 // Restore focused or active window if it's still alive.
180 if (focused_ && tracker_.Contains(focused_)) {
181 focus_client_->FocusWindow(focused_);
182 } else if (active_ && tracker_.Contains(active_)) {
183 activation_client_->ActivateWindow(active_);
186 tracker_.Remove(focused_);
188 tracker_.Remove(active_);
194 aura::client::ActivationClient* activation_client_;
195 aura::client::CaptureClient* capture_client_;
196 aura::client::FocusClient* focus_client_;
197 aura::WindowTracker tracker_;
198 aura::Window* focused_;
199 aura::Window* active_;
201 DISALLOW_COPY_AND_ASSIGN(FocusActivationStore);
204 } // namespace internal
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_root_window_for_replace_(NULL),
228 focus_activation_store_(new internal::FocusActivationStore()),
229 cursor_window_controller_(new internal::CursorWindowController()),
230 mirror_window_controller_(new internal::MirrorWindowController()),
231 virtual_keyboard_window_controller_(
232 new internal::VirtualKeyboardWindowController) {
233 #if defined(OS_CHROMEOS)
234 CommandLine* command_line = CommandLine::ForCurrentProcess();
235 if (!command_line->HasSwitch(switches::kAshDisableDisplayChangeLimiter) &&
236 base::SysInfo::IsRunningOnChromeOS())
237 limiter_.reset(new DisplayChangeLimiter);
239 // Reset primary display to make sure that tests don't use
240 // stale display info from previous tests.
241 primary_display_id = gfx::Display::kInvalidDisplayID;
244 DisplayController::~DisplayController() {
247 void DisplayController::Start() {
248 Shell::GetScreen()->AddObserver(this);
249 Shell::GetInstance()->display_manager()->set_delegate(this);
251 if (Shell::GetInstance()->delegate()->IsFirstRunAfterBoot()) {
252 // Update the display pref with the initial power state.
253 FOR_EACH_OBSERVER(Observer, observers_, OnDisplayConfigurationChanging());
254 FOR_EACH_OBSERVER(Observer, observers_, OnDisplayConfigurationChanged());
258 void DisplayController::Shutdown() {
259 // Unset the display manager's delegate here because
260 // DisplayManager outlives DisplayController.
261 Shell::GetInstance()->display_manager()->set_delegate(NULL);
263 cursor_window_controller_.reset();
264 mirror_window_controller_.reset();
265 virtual_keyboard_window_controller_.reset();
267 Shell::GetScreen()->RemoveObserver(this);
268 // Delete all root window controllers, which deletes root window
269 // from the last so that the primary root window gets deleted last.
270 for (std::map<int64, aura::Window*>::const_reverse_iterator it =
271 root_windows_.rbegin(); it != root_windows_.rend(); ++it) {
272 internal::RootWindowController* controller =
273 internal::GetRootWindowController(it->second);
279 void DisplayController::InitPrimaryDisplay() {
280 const gfx::Display& primary_candidate =
281 GetDisplayManager()->GetPrimaryDisplayCandidate();
282 primary_display_id = primary_candidate.id();
283 AddRootWindowForDisplay(primary_candidate);
286 void DisplayController::InitSecondaryDisplays() {
287 internal::DisplayManager* display_manager = GetDisplayManager();
288 for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) {
289 const gfx::Display& display = display_manager->GetDisplayAt(i);
290 if (primary_display_id != display.id()) {
291 aura::RootWindow* root = AddRootWindowForDisplay(display);
292 internal::RootWindowController::CreateForSecondaryDisplay(root);
295 UpdateHostWindowNames();
298 void DisplayController::AddObserver(Observer* observer) {
299 observers_.AddObserver(observer);
302 void DisplayController::RemoveObserver(Observer* observer) {
303 observers_.RemoveObserver(observer);
307 int64 DisplayController::GetPrimaryDisplayId() {
308 return primary_display_id;
311 aura::Window* DisplayController::GetPrimaryRootWindow() {
312 DCHECK(!root_windows_.empty());
313 return root_windows_[primary_display_id];
316 aura::Window* DisplayController::GetRootWindowForDisplayId(int64 id) {
317 return root_windows_[id];
320 void DisplayController::CloseChildWindows() {
321 for (std::map<int64, aura::Window*>::const_iterator it =
322 root_windows_.begin(); it != root_windows_.end(); ++it) {
323 aura::Window* root_window = it->second;
324 internal::RootWindowController* controller =
325 internal::GetRootWindowController(root_window);
327 controller->CloseChildWindows();
329 while (!root_window->children().empty()) {
330 aura::Window* child = root_window->children()[0];
337 aura::Window::Windows DisplayController::GetAllRootWindows() {
338 aura::Window::Windows windows;
339 for (std::map<int64, aura::Window*>::const_iterator it =
340 root_windows_.begin(); it != root_windows_.end(); ++it) {
342 if (internal::GetRootWindowController(it->second))
343 windows.push_back(it->second);
348 gfx::Insets DisplayController::GetOverscanInsets(int64 display_id) const {
349 return GetDisplayManager()->GetOverscanInsets(display_id);
352 void DisplayController::SetOverscanInsets(int64 display_id,
353 const gfx::Insets& insets_in_dip) {
354 GetDisplayManager()->SetOverscanInsets(display_id, insets_in_dip);
357 std::vector<internal::RootWindowController*>
358 DisplayController::GetAllRootWindowControllers() {
359 std::vector<internal::RootWindowController*> controllers;
360 for (std::map<int64, aura::Window*>::const_iterator it =
361 root_windows_.begin(); it != root_windows_.end(); ++it) {
362 internal::RootWindowController* controller =
363 internal::GetRootWindowController(it->second);
365 controllers.push_back(controller);
370 void DisplayController::ToggleMirrorMode() {
371 internal::DisplayManager* display_manager = GetDisplayManager();
372 if (display_manager->num_connected_displays() <= 1)
376 if (limiter_->IsThrottled())
378 limiter_->SetThrottleTimeout(kCycleDisplayThrottleTimeoutMs);
380 #if defined(OS_CHROMEOS) && defined(USE_X11)
381 Shell* shell = Shell::GetInstance();
382 internal::OutputConfiguratorAnimation* animation =
383 shell->output_configurator_animation();
384 animation->StartFadeOutAnimation(base::Bind(
385 base::IgnoreResult(&internal::DisplayManager::SetMirrorMode),
386 base::Unretained(display_manager),
387 !display_manager->IsMirrored()));
391 void DisplayController::SwapPrimaryDisplay() {
393 if (limiter_->IsThrottled())
395 limiter_->SetThrottleTimeout(kSwapDisplayThrottleTimeoutMs);
398 if (Shell::GetScreen()->GetNumDisplays() > 1) {
399 #if defined(OS_CHROMEOS) && defined(USE_X11)
400 internal::OutputConfiguratorAnimation* animation =
401 Shell::GetInstance()->output_configurator_animation();
403 animation->StartFadeOutAnimation(base::Bind(
404 &DisplayController::OnFadeOutForSwapDisplayFinished,
405 base::Unretained(this)));
407 SetPrimaryDisplay(ScreenUtil::GetSecondaryDisplay());
410 SetPrimaryDisplay(ScreenUtil::GetSecondaryDisplay());
415 void DisplayController::SetPrimaryDisplayId(int64 id) {
416 DCHECK_NE(gfx::Display::kInvalidDisplayID, id);
417 if (id == gfx::Display::kInvalidDisplayID || primary_display_id == id)
420 const gfx::Display& display = GetDisplayManager()->GetDisplayForId(id);
421 if (display.is_valid())
422 SetPrimaryDisplay(display);
425 void DisplayController::SetPrimaryDisplay(
426 const gfx::Display& new_primary_display) {
427 internal::DisplayManager* display_manager = GetDisplayManager();
428 DCHECK(new_primary_display.is_valid());
429 DCHECK(display_manager->IsActiveDisplay(new_primary_display));
431 if (!new_primary_display.is_valid() ||
432 !display_manager->IsActiveDisplay(new_primary_display)) {
433 LOG(ERROR) << "Invalid or non-existent display is requested:"
434 << new_primary_display.ToString();
438 if (primary_display_id == new_primary_display.id() ||
439 root_windows_.size() < 2) {
443 aura::Window* non_primary_root = root_windows_[new_primary_display.id()];
444 LOG_IF(ERROR, !non_primary_root)
445 << "Unknown display is requested in SetPrimaryDisplay: id="
446 << new_primary_display.id();
447 if (!non_primary_root)
450 gfx::Display old_primary_display = Shell::GetScreen()->GetPrimaryDisplay();
452 // Swap root windows between current and new primary display.
453 aura::Window* primary_root = root_windows_[primary_display_id];
454 DCHECK(primary_root);
455 DCHECK_NE(primary_root, non_primary_root);
457 root_windows_[new_primary_display.id()] = primary_root;
458 internal::GetRootWindowSettings(primary_root)->display_id =
459 new_primary_display.id();
461 root_windows_[old_primary_display.id()] = non_primary_root;
462 internal::GetRootWindowSettings(non_primary_root)->display_id =
463 old_primary_display.id();
465 primary_display_id = new_primary_display.id();
466 GetDisplayManager()->layout_store()->UpdatePrimaryDisplayId(
467 display_manager->GetCurrentDisplayIdPair(), primary_display_id);
469 UpdateWorkAreaOfDisplayNearestWindow(
470 primary_root, old_primary_display.GetWorkAreaInsets());
471 UpdateWorkAreaOfDisplayNearestWindow(
472 non_primary_root, new_primary_display.GetWorkAreaInsets());
474 // Update the dispay manager with new display info.
475 std::vector<internal::DisplayInfo> display_info_list;
476 display_info_list.push_back(display_manager->GetDisplayInfo(
477 primary_display_id));
478 display_info_list.push_back(display_manager->GetDisplayInfo(
479 ScreenUtil::GetSecondaryDisplay().id()));
480 GetDisplayManager()->set_force_bounds_changed(true);
481 GetDisplayManager()->UpdateDisplays(display_info_list);
482 GetDisplayManager()->set_force_bounds_changed(false);
485 void DisplayController::EnsurePointerInDisplays() {
486 // If the mouse is currently on a display in native location,
487 // use the same native location. Otherwise find the display closest
488 // to the current cursor location in screen coordinates.
490 gfx::Point point_in_screen = Shell::GetScreen()->GetCursorScreenPoint();
491 gfx::Point target_location_in_native;
492 int64 closest_distance_squared = -1;
493 internal::DisplayManager* display_manager = GetDisplayManager();
495 aura::Window* dst_root_window = NULL;
496 for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) {
497 const gfx::Display& display = display_manager->GetDisplayAt(i);
498 const internal::DisplayInfo display_info =
499 display_manager->GetDisplayInfo(display.id());
500 aura::Window* root_window = GetRootWindowForDisplayId(display.id());
501 if (display_info.bounds_in_native().Contains(
502 cursor_location_in_native_coords_for_restore_)) {
503 dst_root_window = root_window;
504 target_location_in_native = cursor_location_in_native_coords_for_restore_;
507 gfx::Point center = display.bounds().CenterPoint();
508 // Use the distance squared from the center of the dislay. This is not
509 // exactly "closest" display, but good enough to pick one
510 // appropriate (and there are at most two displays).
511 // We don't care about actual distance, only relative to other displays, so
512 // using the LengthSquared() is cheaper than Length().
514 int64 distance_squared = (center - point_in_screen).LengthSquared();
515 if (closest_distance_squared < 0 ||
516 closest_distance_squared > distance_squared) {
517 aura::Window* root_window = GetRootWindowForDisplayId(display.id());
518 aura::client::ScreenPositionClient* client =
519 aura::client::GetScreenPositionClient(root_window);
520 client->ConvertPointFromScreen(root_window, ¢er);
521 root_window->GetDispatcher()->host()->ConvertPointToNativeScreen(¢er);
522 dst_root_window = root_window;
523 target_location_in_native = center;
524 closest_distance_squared = distance_squared;
527 dst_root_window->GetDispatcher()->host()->ConvertPointFromNativeScreen(
528 &target_location_in_native);
529 dst_root_window->MoveCursorTo(target_location_in_native);
532 bool DisplayController::UpdateWorkAreaOfDisplayNearestWindow(
533 const aura::Window* window,
534 const gfx::Insets& insets) {
535 const aura::Window* root_window = window->GetRootWindow();
536 int64 id = internal::GetRootWindowSettings(root_window)->display_id;
537 // if id is |kInvaildDisplayID|, it's being deleted.
538 DCHECK(id != gfx::Display::kInvalidDisplayID);
539 return GetDisplayManager()->UpdateWorkAreaOfDisplay(id, insets);
542 void DisplayController::OnDisplayBoundsChanged(const gfx::Display& display) {
543 const internal::DisplayInfo& display_info =
544 GetDisplayManager()->GetDisplayInfo(display.id());
545 DCHECK(!display_info.bounds_in_native().IsEmpty());
546 aura::WindowEventDispatcher* dispatcher =
547 root_windows_[display.id()]->GetDispatcher();
548 dispatcher->host()->SetBounds(display_info.bounds_in_native());
549 SetDisplayPropertiesOnHostWindow(dispatcher, display);
552 void DisplayController::OnDisplayAdded(const gfx::Display& display) {
553 if (primary_root_window_for_replace_) {
554 DCHECK(root_windows_.empty());
555 primary_display_id = display.id();
556 root_windows_[display.id()] = primary_root_window_for_replace_;
557 internal::GetRootWindowSettings(primary_root_window_for_replace_)->
558 display_id = display.id();
559 primary_root_window_for_replace_ = NULL;
560 const internal::DisplayInfo& display_info =
561 GetDisplayManager()->GetDisplayInfo(display.id());
562 aura::WindowEventDispatcher* dispatcher =
563 root_windows_[display.id()]->GetDispatcher();
564 dispatcher->host()->SetBounds(display_info.bounds_in_native());
565 SetDisplayPropertiesOnHostWindow(dispatcher, display);
567 if (primary_display_id == gfx::Display::kInvalidDisplayID)
568 primary_display_id = display.id();
569 DCHECK(!root_windows_.empty());
570 aura::RootWindow* root = AddRootWindowForDisplay(display);
571 internal::RootWindowController::CreateForSecondaryDisplay(root);
575 void DisplayController::OnDisplayRemoved(const gfx::Display& display) {
576 aura::Window* root_to_delete = root_windows_[display.id()];
577 DCHECK(root_to_delete) << display.ToString();
579 // Display for root window will be deleted when the Primary RootWindow
580 // is deleted by the Shell.
581 root_windows_.erase(display.id());
583 // When the primary root window's display is removed, move the primary
584 // root to the other display.
585 if (primary_display_id == display.id()) {
586 // Temporarily store the primary root window in
587 // |primary_root_window_for_replace_| when replacing the display.
588 if (root_windows_.size() == 0) {
589 primary_display_id = gfx::Display::kInvalidDisplayID;
590 primary_root_window_for_replace_ = root_to_delete;
593 DCHECK_EQ(1U, root_windows_.size());
594 primary_display_id = ScreenUtil::GetSecondaryDisplay().id();
595 aura::Window* primary_root = root_to_delete;
597 // Delete the other root instead.
598 root_to_delete = root_windows_[primary_display_id];
599 internal::GetRootWindowSettings(root_to_delete)->display_id = display.id();
601 // Setup primary root.
602 root_windows_[primary_display_id] = primary_root;
603 internal::GetRootWindowSettings(primary_root)->display_id =
606 OnDisplayBoundsChanged(
607 GetDisplayManager()->GetDisplayForId(primary_display_id));
609 internal::RootWindowController* controller =
610 internal::GetRootWindowController(root_to_delete);
612 controller->MoveWindowsTo(GetPrimaryRootWindow());
613 // Delete most of root window related objects, but don't delete
614 // root window itself yet because the stack may be using it.
615 controller->Shutdown();
616 base::MessageLoop::current()->DeleteSoon(FROM_HERE, controller);
619 void DisplayController::OnWindowTreeHostResized(const aura::RootWindow* root) {
620 gfx::Display display = Shell::GetScreen()->GetDisplayNearestWindow(
621 const_cast<aura::Window*>(root->window()));
623 internal::DisplayManager* display_manager = GetDisplayManager();
624 if (display_manager->UpdateDisplayBounds(
626 root->host()->GetBounds())) {
627 mirror_window_controller_->UpdateWindow();
628 cursor_window_controller_->UpdateContainer();
632 void DisplayController::CreateOrUpdateNonDesktopDisplay(
633 const internal::DisplayInfo& info) {
634 switch (GetDisplayManager()->second_display_mode()) {
635 case internal::DisplayManager::MIRRORING:
636 mirror_window_controller_->UpdateWindow(info);
637 cursor_window_controller_->UpdateContainer();
638 virtual_keyboard_window_controller_->Close();
640 case internal::DisplayManager::VIRTUAL_KEYBOARD:
641 mirror_window_controller_->Close();
642 cursor_window_controller_->UpdateContainer();
643 virtual_keyboard_window_controller_->UpdateWindow(info);
645 case internal::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->GetDispatcher()->host()->ConvertPointToNativeScreen(
669 cursor_location_in_native_coords_for_restore_ = point_in_screen;
672 void DisplayController::PostDisplayConfigurationChange() {
674 limiter_->SetThrottleTimeout(kAfterDisplayChangeThrottleTimeoutMs);
676 focus_activation_store_->Restore();
678 internal::DisplayManager* display_manager = GetDisplayManager();
679 internal::DisplayLayoutStore* layout_store = display_manager->layout_store();
680 if (display_manager->num_connected_displays() > 1) {
681 DisplayIdPair pair = display_manager->GetCurrentDisplayIdPair();
682 layout_store->UpdateMirrorStatus(pair, display_manager->IsMirrored());
683 DisplayLayout layout = layout_store->GetRegisteredDisplayLayout(pair);
685 if (Shell::GetScreen()->GetNumDisplays() > 1 ) {
686 int64 primary_id = layout.primary_id;
688 primary_id == gfx::Display::kInvalidDisplayID ?
689 pair.first : primary_id);
690 // Update the primary_id in case the above call is
691 // ignored. Happens when a) default layout's primary id
692 // doesn't exist, or b) the primary_id has already been
693 // set to the same and didn't update it.
694 layout_store->UpdatePrimaryDisplayId(
695 pair, Shell::GetScreen()->GetPrimaryDisplay().id());
698 FOR_EACH_OBSERVER(Observer, observers_, OnDisplayConfigurationChanged());
699 UpdateHostWindowNames();
700 EnsurePointerInDisplays();
703 aura::RootWindow* DisplayController::AddRootWindowForDisplay(
704 const gfx::Display& display) {
705 static int root_window_count = 0;
706 const internal::DisplayInfo& display_info =
707 GetDisplayManager()->GetDisplayInfo(display.id());
708 const gfx::Rect& bounds_in_native = display_info.bounds_in_native();
709 aura::RootWindow::CreateParams params(bounds_in_native);
710 params.host = Shell::GetInstance()->window_tree_host_factory()->
711 CreateWindowTreeHost(bounds_in_native);
712 aura::RootWindow* root_window = new aura::RootWindow(params);
713 root_window->window()->SetName(
714 base::StringPrintf("RootWindow-%d", root_window_count++));
715 root_window->host()->compositor()->SetBackgroundColor(SK_ColorBLACK);
716 // No need to remove RootWindowObserver because
717 // the DisplayController object outlives RootWindow objects.
718 root_window->AddRootWindowObserver(this);
719 internal::InitRootWindowSettings(root_window->window())->display_id =
721 root_window->host()->InitHost();
723 root_windows_[display.id()] = root_window->window();
724 SetDisplayPropertiesOnHostWindow(root_window, display);
726 #if defined(OS_CHROMEOS)
727 static bool force_constrain_pointer_to_root =
728 CommandLine::ForCurrentProcess()->HasSwitch(
729 switches::kAshConstrainPointerToRoot);
730 if (base::SysInfo::IsRunningOnChromeOS() || force_constrain_pointer_to_root)
731 root_window->host()->ConfineCursorToRootWindow();
736 void DisplayController::OnFadeOutForSwapDisplayFinished() {
737 #if defined(OS_CHROMEOS) && defined(USE_X11)
738 SetPrimaryDisplay(ScreenUtil::GetSecondaryDisplay());
739 Shell::GetInstance()->output_configurator_animation()->StartFadeInAnimation();
743 void DisplayController::UpdateHostWindowNames() {
745 // crbug.com/120229 - set the window title for the primary dislpay
746 // to "aura_root_0" so gtalk can find the primary root window to broadcast.
747 // TODO(jhorwich) Remove this once Chrome supports window-based broadcasting.
748 aura::Window* primary = Shell::GetPrimaryRootWindow();
749 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
750 for (size_t i = 0; i < root_windows.size(); ++i) {
752 root_windows[i] == primary ? "aura_root_0" : "aura_root_x";
753 gfx::AcceleratedWidget xwindow =
754 root_windows[i]->GetDispatcher()->host()->GetAcceleratedWidget();
755 XStoreName(gfx::GetXDisplay(), xwindow, name.c_str());