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/capture_client.h"
28 #include "ui/aura/client/focus_client.h"
29 #include "ui/aura/client/screen_position_client.h"
30 #include "ui/aura/root_window_transformer.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/compositor/compositor.h"
36 #include "ui/compositor/compositor_vsync_manager.h"
37 #include "ui/gfx/display.h"
38 #include "ui/gfx/screen.h"
39 #include "ui/wm/public/activation_client.h"
41 #if defined(OS_CHROMEOS)
42 #include "ash/display/output_configurator_animation.h"
43 #include "base/sys_info.h"
44 #include "base/time/time.h"
46 #include "ui/base/x/x11_util.h"
47 #include "ui/gfx/x/x11_types.h"
49 // Including this at the bottom to avoid other
50 // potential conflict with chrome headers.
51 #include <X11/extensions/Xrandr.h>
53 #endif // defined(USE_X11)
54 #endif // defined(OS_CHROMEOS)
59 // Primary display stored in global object as it can be
60 // accessed after Shell is deleted. A separate display instance is created
61 // during the shutdown instead of always keeping two display instances
62 // (one here and another one in display_manager) in sync, which is error prone.
63 int64 primary_display_id
= gfx::Display::kInvalidDisplayID
;
65 // Specifies how long the display change should have been disabled
66 // after each display change operations.
67 // |kCycleDisplayThrottleTimeoutMs| is set to be longer to avoid
68 // changing the settings while the system is still configurating
69 // displays. It will be overriden by |kAfterDisplayChangeThrottleTimeoutMs|
70 // when the display change happens, so the actual timeout is much shorter.
71 const int64 kAfterDisplayChangeThrottleTimeoutMs
= 500;
72 const int64 kCycleDisplayThrottleTimeoutMs
= 4000;
73 const int64 kSwapDisplayThrottleTimeoutMs
= 500;
75 DisplayManager
* GetDisplayManager() {
76 return Shell::GetInstance()->display_manager();
79 void SetDisplayPropertiesOnHost(aura::WindowTreeHost
* host
,
80 const gfx::Display
& display
) {
81 DisplayInfo info
= GetDisplayManager()->GetDisplayInfo(display
.id());
82 #if defined(OS_CHROMEOS) && defined(USE_X11)
83 // Native window property (Atom in X11) that specifies the display's
84 // rotation, scale factor and if it's internal display. They are
85 // read and used by touchpad/mouse driver directly on X (contact
86 // adlr@ for more details on touchpad/mouse driver side). The value
87 // of the rotation is one of 0 (normal), 1 (90 degrees clockwise), 2
88 // (180 degree) or 3 (270 degrees clockwise). The value of the
89 // scale factor is in percent (100, 140, 200 etc).
90 const char kRotationProp
[] = "_CHROME_DISPLAY_ROTATION";
91 const char kScaleFactorProp
[] = "_CHROME_DISPLAY_SCALE_FACTOR";
92 const char kInternalProp
[] = "_CHROME_DISPLAY_INTERNAL";
93 const char kCARDINAL
[] = "CARDINAL";
94 int xrandr_rotation
= RR_Rotate_0
;
95 switch (info
.rotation()) {
96 case gfx::Display::ROTATE_0
:
97 xrandr_rotation
= RR_Rotate_0
;
99 case gfx::Display::ROTATE_90
:
100 xrandr_rotation
= RR_Rotate_90
;
102 case gfx::Display::ROTATE_180
:
103 xrandr_rotation
= RR_Rotate_180
;
105 case gfx::Display::ROTATE_270
:
106 xrandr_rotation
= RR_Rotate_270
;
110 int internal
= display
.IsInternal() ? 1 : 0;
111 gfx::AcceleratedWidget xwindow
= host
->GetAcceleratedWidget();
112 ui::SetIntProperty(xwindow
, kInternalProp
, kCARDINAL
, internal
);
113 ui::SetIntProperty(xwindow
, kRotationProp
, kCARDINAL
, xrandr_rotation
);
114 ui::SetIntProperty(xwindow
,
117 100 * display
.device_scale_factor());
119 scoped_ptr
<aura::RootWindowTransformer
> transformer(
120 CreateRootWindowTransformerForDisplay(host
->window(), display
));
121 host
->SetRootWindowTransformer(transformer
.Pass());
124 if (GetDisplayManager()->GetSelectedModeForDisplayId(display
.id(), &mode
) &&
125 mode
.refresh_rate
> 0.0f
) {
126 host
->compositor()->vsync_manager()->SetAuthoritativeVSyncInterval(
127 base::TimeDelta::FromMicroseconds(
128 base::Time::kMicrosecondsPerSecond
/ mode
.refresh_rate
));
134 // A utility class to store/restore focused/active window
135 // when the display configuration has changed.
136 class FocusActivationStore
{
138 FocusActivationStore()
139 : activation_client_(NULL
),
140 capture_client_(NULL
),
146 void Store(bool clear_focus
) {
147 if (!activation_client_
) {
148 aura::Window
* root
= Shell::GetPrimaryRootWindow();
149 activation_client_
= aura::client::GetActivationClient(root
);
150 capture_client_
= aura::client::GetCaptureClient(root
);
151 focus_client_
= aura::client::GetFocusClient(root
);
153 focused_
= focus_client_
->GetFocusedWindow();
155 tracker_
.Add(focused_
);
156 active_
= activation_client_
->GetActiveWindow();
157 if (active_
&& focused_
!= active_
)
158 tracker_
.Add(active_
);
160 // Deactivate the window to close menu / bubble windows.
162 activation_client_
->DeactivateWindow(active_
);
164 // Release capture if any.
165 capture_client_
->SetCapture(NULL
);
166 // Clear the focused window if any. This is necessary because a
167 // window may be deleted when losing focus (fullscreen flash for
168 // example). If the focused window is still alive after move, it'll
169 // be re-focused below.
171 focus_client_
->FocusWindow(NULL
);
175 // Restore focused or active window if it's still alive.
176 if (focused_
&& tracker_
.Contains(focused_
)) {
177 focus_client_
->FocusWindow(focused_
);
178 } else if (active_
&& tracker_
.Contains(active_
)) {
179 activation_client_
->ActivateWindow(active_
);
182 tracker_
.Remove(focused_
);
184 tracker_
.Remove(active_
);
190 aura::client::ActivationClient
* activation_client_
;
191 aura::client::CaptureClient
* capture_client_
;
192 aura::client::FocusClient
* focus_client_
;
193 aura::WindowTracker tracker_
;
194 aura::Window
* focused_
;
195 aura::Window
* active_
;
197 DISALLOW_COPY_AND_ASSIGN(FocusActivationStore
);
200 ////////////////////////////////////////////////////////////////////////////////
201 // DisplayChangeLimiter
203 DisplayController::DisplayChangeLimiter::DisplayChangeLimiter()
204 : throttle_timeout_(base::Time::Now()) {
207 void DisplayController::DisplayChangeLimiter::SetThrottleTimeout(
210 base::Time::Now() + base::TimeDelta::FromMilliseconds(throttle_ms
);
213 bool DisplayController::DisplayChangeLimiter::IsThrottled() const {
214 return base::Time::Now() < throttle_timeout_
;
217 ////////////////////////////////////////////////////////////////////////////////
220 DisplayController::DisplayController()
221 : primary_root_window_for_replace_(NULL
),
222 focus_activation_store_(new FocusActivationStore()),
223 cursor_window_controller_(new CursorWindowController()),
224 mirror_window_controller_(new MirrorWindowController()) {
225 #if defined(OS_CHROMEOS)
226 if (base::SysInfo::IsRunningOnChromeOS())
227 limiter_
.reset(new DisplayChangeLimiter
);
229 // Reset primary display to make sure that tests don't use
230 // stale display info from previous tests.
231 primary_display_id
= gfx::Display::kInvalidDisplayID
;
234 DisplayController::~DisplayController() {
237 void DisplayController::Start() {
238 // Created here so that Shell has finished being created. Adds itself
239 // as a ShellObserver.
240 virtual_keyboard_window_controller_
.reset(
241 new VirtualKeyboardWindowController
);
242 Shell::GetScreen()->AddObserver(this);
243 Shell::GetInstance()->display_manager()->set_delegate(this);
245 FOR_EACH_OBSERVER(Observer
, observers_
, OnDisplaysInitialized());
248 void DisplayController::Shutdown() {
249 // Unset the display manager's delegate here because
250 // DisplayManager outlives DisplayController.
251 Shell::GetInstance()->display_manager()->set_delegate(NULL
);
253 cursor_window_controller_
.reset();
254 mirror_window_controller_
.reset();
255 virtual_keyboard_window_controller_
.reset();
257 Shell::GetScreen()->RemoveObserver(this);
258 // Delete all root window controllers, which deletes root window
259 // from the last so that the primary root window gets deleted last.
260 for (std::map
<int64
, aura::Window
*>::const_reverse_iterator it
=
261 root_windows_
.rbegin(); it
!= root_windows_
.rend(); ++it
) {
262 RootWindowController
* controller
= GetRootWindowController(it
->second
);
268 void DisplayController::InitPrimaryDisplay() {
269 const gfx::Display
& primary_candidate
=
270 GetDisplayManager()->GetPrimaryDisplayCandidate();
271 primary_display_id
= primary_candidate
.id();
272 AddWindowTreeHostForDisplay(primary_candidate
);
275 void DisplayController::InitSecondaryDisplays() {
276 DisplayManager
* display_manager
= GetDisplayManager();
277 for (size_t i
= 0; i
< display_manager
->GetNumDisplays(); ++i
) {
278 const gfx::Display
& display
= display_manager
->GetDisplayAt(i
);
279 if (primary_display_id
!= display
.id()) {
280 aura::WindowTreeHost
* host
= AddWindowTreeHostForDisplay(display
);
281 RootWindowController::CreateForSecondaryDisplay(host
);
284 UpdateHostWindowNames();
287 void DisplayController::AddObserver(Observer
* observer
) {
288 observers_
.AddObserver(observer
);
291 void DisplayController::RemoveObserver(Observer
* observer
) {
292 observers_
.RemoveObserver(observer
);
296 int64
DisplayController::GetPrimaryDisplayId() {
297 return primary_display_id
;
300 aura::Window
* DisplayController::GetPrimaryRootWindow() {
301 DCHECK(!root_windows_
.empty());
302 return root_windows_
[primary_display_id
];
305 aura::Window
* DisplayController::GetRootWindowForDisplayId(int64 id
) {
306 return root_windows_
[id
];
309 void DisplayController::CloseChildWindows() {
310 for (std::map
<int64
, aura::Window
*>::const_iterator it
=
311 root_windows_
.begin(); it
!= root_windows_
.end(); ++it
) {
312 aura::Window
* root_window
= it
->second
;
313 RootWindowController
* controller
= GetRootWindowController(root_window
);
315 controller
->CloseChildWindows();
317 while (!root_window
->children().empty()) {
318 aura::Window
* child
= root_window
->children()[0];
325 aura::Window::Windows
DisplayController::GetAllRootWindows() {
326 aura::Window::Windows windows
;
327 for (std::map
<int64
, aura::Window
*>::const_iterator it
=
328 root_windows_
.begin(); it
!= root_windows_
.end(); ++it
) {
330 if (GetRootWindowController(it
->second
))
331 windows
.push_back(it
->second
);
336 gfx::Insets
DisplayController::GetOverscanInsets(int64 display_id
) const {
337 return GetDisplayManager()->GetOverscanInsets(display_id
);
340 void DisplayController::SetOverscanInsets(int64 display_id
,
341 const gfx::Insets
& insets_in_dip
) {
342 GetDisplayManager()->SetOverscanInsets(display_id
, insets_in_dip
);
345 std::vector
<RootWindowController
*>
346 DisplayController::GetAllRootWindowControllers() {
347 std::vector
<RootWindowController
*> controllers
;
348 for (std::map
<int64
, aura::Window
*>::const_iterator it
=
349 root_windows_
.begin(); it
!= root_windows_
.end(); ++it
) {
350 RootWindowController
* controller
= GetRootWindowController(it
->second
);
352 controllers
.push_back(controller
);
357 void DisplayController::ToggleMirrorMode() {
358 DisplayManager
* display_manager
= GetDisplayManager();
359 if (display_manager
->num_connected_displays() <= 1)
363 if (limiter_
->IsThrottled())
365 limiter_
->SetThrottleTimeout(kCycleDisplayThrottleTimeoutMs
);
367 #if defined(OS_CHROMEOS)
368 Shell
* shell
= Shell::GetInstance();
369 OutputConfiguratorAnimation
* animation
=
370 shell
->output_configurator_animation();
371 animation
->StartFadeOutAnimation(
372 base::Bind(base::IgnoreResult(&DisplayManager::SetMirrorMode
),
373 base::Unretained(display_manager
),
374 !display_manager
->IsMirrored()));
378 void DisplayController::SwapPrimaryDisplay() {
380 if (limiter_
->IsThrottled())
382 limiter_
->SetThrottleTimeout(kSwapDisplayThrottleTimeoutMs
);
385 if (Shell::GetScreen()->GetNumDisplays() > 1) {
386 #if defined(OS_CHROMEOS)
387 OutputConfiguratorAnimation
* animation
=
388 Shell::GetInstance()->output_configurator_animation();
390 animation
->StartFadeOutAnimation(base::Bind(
391 &DisplayController::OnFadeOutForSwapDisplayFinished
,
392 base::Unretained(this)));
394 SetPrimaryDisplay(ScreenUtil::GetSecondaryDisplay());
397 SetPrimaryDisplay(ScreenUtil::GetSecondaryDisplay());
402 void DisplayController::SetPrimaryDisplayId(int64 id
) {
403 DCHECK_NE(gfx::Display::kInvalidDisplayID
, id
);
404 if (id
== gfx::Display::kInvalidDisplayID
|| primary_display_id
== id
)
407 const gfx::Display
& display
= GetDisplayManager()->GetDisplayForId(id
);
408 if (display
.is_valid())
409 SetPrimaryDisplay(display
);
412 void DisplayController::SetPrimaryDisplay(
413 const gfx::Display
& new_primary_display
) {
414 DisplayManager
* display_manager
= GetDisplayManager();
415 DCHECK(new_primary_display
.is_valid());
416 DCHECK(display_manager
->IsActiveDisplay(new_primary_display
));
418 if (!new_primary_display
.is_valid() ||
419 !display_manager
->IsActiveDisplay(new_primary_display
)) {
420 LOG(ERROR
) << "Invalid or non-existent display is requested:"
421 << new_primary_display
.ToString();
425 if (primary_display_id
== new_primary_display
.id() ||
426 root_windows_
.size() < 2) {
430 aura::Window
* non_primary_root
= root_windows_
[new_primary_display
.id()];
431 LOG_IF(ERROR
, !non_primary_root
)
432 << "Unknown display is requested in SetPrimaryDisplay: id="
433 << new_primary_display
.id();
434 if (!non_primary_root
)
437 gfx::Display old_primary_display
= Shell::GetScreen()->GetPrimaryDisplay();
439 // Swap root windows between current and new primary display.
440 aura::Window
* primary_root
= root_windows_
[primary_display_id
];
441 DCHECK(primary_root
);
442 DCHECK_NE(primary_root
, non_primary_root
);
444 root_windows_
[new_primary_display
.id()] = primary_root
;
445 GetRootWindowSettings(primary_root
)->display_id
= new_primary_display
.id();
447 root_windows_
[old_primary_display
.id()] = non_primary_root
;
448 GetRootWindowSettings(non_primary_root
)->display_id
=
449 old_primary_display
.id();
451 primary_display_id
= new_primary_display
.id();
452 GetDisplayManager()->layout_store()->UpdatePrimaryDisplayId(
453 display_manager
->GetCurrentDisplayIdPair(), primary_display_id
);
455 UpdateWorkAreaOfDisplayNearestWindow(
456 primary_root
, old_primary_display
.GetWorkAreaInsets());
457 UpdateWorkAreaOfDisplayNearestWindow(
458 non_primary_root
, new_primary_display
.GetWorkAreaInsets());
460 // Update the dispay manager with new display info.
461 std::vector
<DisplayInfo
> display_info_list
;
462 display_info_list
.push_back(display_manager
->GetDisplayInfo(
463 primary_display_id
));
464 display_info_list
.push_back(display_manager
->GetDisplayInfo(
465 ScreenUtil::GetSecondaryDisplay().id()));
466 GetDisplayManager()->set_force_bounds_changed(true);
467 GetDisplayManager()->UpdateDisplays(display_info_list
);
468 GetDisplayManager()->set_force_bounds_changed(false);
471 void DisplayController::EnsurePointerInDisplays() {
472 // If the mouse is currently on a display in native location,
473 // use the same native location. Otherwise find the display closest
474 // to the current cursor location in screen coordinates.
476 gfx::Point point_in_screen
= Shell::GetScreen()->GetCursorScreenPoint();
477 gfx::Point target_location_in_native
;
478 int64 closest_distance_squared
= -1;
479 DisplayManager
* display_manager
= GetDisplayManager();
481 aura::Window
* dst_root_window
= NULL
;
482 for (size_t i
= 0; i
< display_manager
->GetNumDisplays(); ++i
) {
483 const gfx::Display
& display
= display_manager
->GetDisplayAt(i
);
484 const DisplayInfo display_info
=
485 display_manager
->GetDisplayInfo(display
.id());
486 aura::Window
* root_window
= GetRootWindowForDisplayId(display
.id());
487 if (display_info
.bounds_in_native().Contains(
488 cursor_location_in_native_coords_for_restore_
)) {
489 dst_root_window
= root_window
;
490 target_location_in_native
= cursor_location_in_native_coords_for_restore_
;
493 gfx::Point center
= display
.bounds().CenterPoint();
494 // Use the distance squared from the center of the dislay. This is not
495 // exactly "closest" display, but good enough to pick one
496 // appropriate (and there are at most two displays).
497 // We don't care about actual distance, only relative to other displays, so
498 // using the LengthSquared() is cheaper than Length().
500 int64 distance_squared
= (center
- point_in_screen
).LengthSquared();
501 if (closest_distance_squared
< 0 ||
502 closest_distance_squared
> distance_squared
) {
503 aura::Window
* root_window
= GetRootWindowForDisplayId(display
.id());
504 aura::client::ScreenPositionClient
* client
=
505 aura::client::GetScreenPositionClient(root_window
);
506 client
->ConvertPointFromScreen(root_window
, ¢er
);
507 root_window
->GetHost()->ConvertPointToNativeScreen(¢er
);
508 dst_root_window
= root_window
;
509 target_location_in_native
= center
;
510 closest_distance_squared
= distance_squared
;
513 dst_root_window
->GetHost()->ConvertPointFromNativeScreen(
514 &target_location_in_native
);
515 dst_root_window
->MoveCursorTo(target_location_in_native
);
518 bool DisplayController::UpdateWorkAreaOfDisplayNearestWindow(
519 const aura::Window
* window
,
520 const gfx::Insets
& insets
) {
521 const aura::Window
* root_window
= window
->GetRootWindow();
522 int64 id
= GetRootWindowSettings(root_window
)->display_id
;
523 // if id is |kInvaildDisplayID|, it's being deleted.
524 DCHECK(id
!= gfx::Display::kInvalidDisplayID
);
525 return GetDisplayManager()->UpdateWorkAreaOfDisplay(id
, insets
);
528 void DisplayController::OnDisplayBoundsChanged(const gfx::Display
& display
) {
529 const DisplayInfo
& display_info
=
530 GetDisplayManager()->GetDisplayInfo(display
.id());
531 DCHECK(!display_info
.bounds_in_native().IsEmpty());
532 aura::WindowTreeHost
* host
= root_windows_
[display
.id()]->GetHost();
533 host
->SetBounds(display_info
.bounds_in_native());
534 SetDisplayPropertiesOnHost(host
, display
);
537 void DisplayController::OnDisplayAdded(const gfx::Display
& display
) {
538 if (primary_root_window_for_replace_
) {
539 DCHECK(root_windows_
.empty());
540 primary_display_id
= display
.id();
541 root_windows_
[display
.id()] = primary_root_window_for_replace_
;
542 GetRootWindowSettings(primary_root_window_for_replace_
)->display_id
=
544 primary_root_window_for_replace_
= NULL
;
545 const DisplayInfo
& display_info
=
546 GetDisplayManager()->GetDisplayInfo(display
.id());
547 aura::WindowTreeHost
* host
= root_windows_
[display
.id()]->GetHost();
548 host
->SetBounds(display_info
.bounds_in_native());
549 SetDisplayPropertiesOnHost(host
, display
);
551 if (primary_display_id
== gfx::Display::kInvalidDisplayID
)
552 primary_display_id
= display
.id();
553 DCHECK(!root_windows_
.empty());
554 aura::WindowTreeHost
* host
= AddWindowTreeHostForDisplay(display
);
555 RootWindowController::CreateForSecondaryDisplay(host
);
559 void DisplayController::OnDisplayRemoved(const gfx::Display
& display
) {
560 aura::Window
* root_to_delete
= root_windows_
[display
.id()];
561 DCHECK(root_to_delete
) << display
.ToString();
563 // Display for root window will be deleted when the Primary RootWindow
564 // is deleted by the Shell.
565 root_windows_
.erase(display
.id());
567 // When the primary root window's display is removed, move the primary
568 // root to the other display.
569 if (primary_display_id
== display
.id()) {
570 // Temporarily store the primary root window in
571 // |primary_root_window_for_replace_| when replacing the display.
572 if (root_windows_
.size() == 0) {
573 primary_display_id
= gfx::Display::kInvalidDisplayID
;
574 primary_root_window_for_replace_
= root_to_delete
;
577 DCHECK_EQ(1U, root_windows_
.size());
578 primary_display_id
= ScreenUtil::GetSecondaryDisplay().id();
579 aura::Window
* primary_root
= root_to_delete
;
581 // Delete the other root instead.
582 root_to_delete
= root_windows_
[primary_display_id
];
583 GetRootWindowSettings(root_to_delete
)->display_id
= display
.id();
585 // Setup primary root.
586 root_windows_
[primary_display_id
] = primary_root
;
587 GetRootWindowSettings(primary_root
)->display_id
= primary_display_id
;
589 OnDisplayBoundsChanged(
590 GetDisplayManager()->GetDisplayForId(primary_display_id
));
592 RootWindowController
* controller
= GetRootWindowController(root_to_delete
);
594 controller
->MoveWindowsTo(GetPrimaryRootWindow());
595 // Delete most of root window related objects, but don't delete
596 // root window itself yet because the stack may be using it.
597 controller
->Shutdown();
598 base::MessageLoop::current()->DeleteSoon(FROM_HERE
, controller
);
601 void DisplayController::OnHostResized(const aura::WindowTreeHost
* host
) {
602 gfx::Display display
= Shell::GetScreen()->GetDisplayNearestWindow(
603 const_cast<aura::Window
*>(host
->window()));
605 DisplayManager
* display_manager
= GetDisplayManager();
606 if (display_manager
->UpdateDisplayBounds(display
.id(), host
->GetBounds())) {
607 mirror_window_controller_
->UpdateWindow();
608 cursor_window_controller_
->UpdateContainer();
612 void DisplayController::CreateOrUpdateNonDesktopDisplay(
613 const DisplayInfo
& info
) {
614 switch (GetDisplayManager()->second_display_mode()) {
615 case DisplayManager::MIRRORING
:
616 mirror_window_controller_
->UpdateWindow(info
);
617 cursor_window_controller_
->UpdateContainer();
618 virtual_keyboard_window_controller_
->Close();
620 case DisplayManager::VIRTUAL_KEYBOARD
:
621 mirror_window_controller_
->Close();
622 cursor_window_controller_
->UpdateContainer();
623 virtual_keyboard_window_controller_
->UpdateWindow(info
);
625 case DisplayManager::EXTENDED
:
630 void DisplayController::CloseNonDesktopDisplay() {
631 mirror_window_controller_
->Close();
632 cursor_window_controller_
->UpdateContainer();
633 virtual_keyboard_window_controller_
->Close();
636 void DisplayController::PreDisplayConfigurationChange(bool clear_focus
) {
637 FOR_EACH_OBSERVER(Observer
, observers_
, OnDisplayConfigurationChanging());
638 focus_activation_store_
->Store(clear_focus
);
639 gfx::Screen
* screen
= Shell::GetScreen();
640 gfx::Point point_in_screen
= screen
->GetCursorScreenPoint();
641 gfx::Display display
= screen
->GetDisplayNearestPoint(point_in_screen
);
642 aura::Window
* root_window
= GetRootWindowForDisplayId(display
.id());
644 aura::client::ScreenPositionClient
* client
=
645 aura::client::GetScreenPositionClient(root_window
);
646 client
->ConvertPointFromScreen(root_window
, &point_in_screen
);
647 root_window
->GetHost()->ConvertPointToNativeScreen(&point_in_screen
);
648 cursor_location_in_native_coords_for_restore_
= point_in_screen
;
651 void DisplayController::PostDisplayConfigurationChange() {
653 limiter_
->SetThrottleTimeout(kAfterDisplayChangeThrottleTimeoutMs
);
655 focus_activation_store_
->Restore();
657 DisplayManager
* display_manager
= GetDisplayManager();
658 DisplayLayoutStore
* layout_store
= display_manager
->layout_store();
659 if (display_manager
->num_connected_displays() > 1) {
660 DisplayIdPair pair
= display_manager
->GetCurrentDisplayIdPair();
661 layout_store
->UpdateMirrorStatus(pair
, display_manager
->IsMirrored());
662 DisplayLayout layout
= layout_store
->GetRegisteredDisplayLayout(pair
);
664 if (Shell::GetScreen()->GetNumDisplays() > 1 ) {
665 int64 primary_id
= layout
.primary_id
;
667 primary_id
== gfx::Display::kInvalidDisplayID
?
668 pair
.first
: primary_id
);
669 // Update the primary_id in case the above call is
670 // ignored. Happens when a) default layout's primary id
671 // doesn't exist, or b) the primary_id has already been
672 // set to the same and didn't update it.
673 layout_store
->UpdatePrimaryDisplayId(
674 pair
, Shell::GetScreen()->GetPrimaryDisplay().id());
677 FOR_EACH_OBSERVER(Observer
, observers_
, OnDisplayConfigurationChanged());
678 UpdateHostWindowNames();
679 EnsurePointerInDisplays();
682 aura::WindowTreeHost
* DisplayController::AddWindowTreeHostForDisplay(
683 const gfx::Display
& display
) {
684 static int host_count
= 0;
685 const DisplayInfo
& display_info
=
686 GetDisplayManager()->GetDisplayInfo(display
.id());
687 const gfx::Rect
& bounds_in_native
= display_info
.bounds_in_native();
688 aura::WindowTreeHost
* host
=
689 Shell::GetInstance()->window_tree_host_factory()->CreateWindowTreeHost(
691 host
->window()->SetName(base::StringPrintf("RootWindow-%d", host_count
++));
692 host
->compositor()->SetBackgroundColor(SK_ColorBLACK
);
693 // No need to remove our observer observer because the DisplayController
694 // outlives the host.
695 host
->AddObserver(this);
696 InitRootWindowSettings(host
->window())->display_id
= display
.id();
699 root_windows_
[display
.id()] = host
->window();
700 SetDisplayPropertiesOnHost(host
, display
);
702 #if defined(OS_CHROMEOS)
703 static bool force_constrain_pointer_to_root
=
704 CommandLine::ForCurrentProcess()->HasSwitch(
705 switches::kAshConstrainPointerToRoot
);
706 if (base::SysInfo::IsRunningOnChromeOS() || force_constrain_pointer_to_root
)
707 host
->ConfineCursorToRootWindow();
712 void DisplayController::OnFadeOutForSwapDisplayFinished() {
713 #if defined(OS_CHROMEOS)
714 SetPrimaryDisplay(ScreenUtil::GetSecondaryDisplay());
715 Shell::GetInstance()->output_configurator_animation()->StartFadeInAnimation();
719 void DisplayController::UpdateHostWindowNames() {
721 // crbug.com/120229 - set the window title for the primary dislpay
722 // to "aura_root_0" so gtalk can find the primary root window to broadcast.
723 // TODO(jhorwich) Remove this once Chrome supports window-based broadcasting.
724 aura::Window
* primary
= Shell::GetPrimaryRootWindow();
725 aura::Window::Windows root_windows
= Shell::GetAllRootWindows();
726 for (size_t i
= 0; i
< root_windows
.size(); ++i
) {
728 root_windows
[i
] == primary
? "aura_root_0" : "aura_root_x";
729 gfx::AcceleratedWidget xwindow
=
730 root_windows
[i
]->GetHost()->GetAcceleratedWidget();
731 XStoreName(gfx::GetXDisplay(), xwindow
, name
.c_str());