Separate projection mode from rest of touch HUD
[chromium-blink-merge.git] / ash / display / display_controller.cc
blobe8186db924d7683419601f82f80d81d7789a6ed9
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"
7 #include <algorithm>
8 #include <cmath>
9 #include <map>
11 #include "ash/ash_switches.h"
12 #include "ash/display/display_manager.h"
13 #include "ash/display/root_window_transformers.h"
14 #include "ash/host/root_window_host_factory.h"
15 #include "ash/root_window_controller.h"
16 #include "ash/screen_ash.h"
17 #include "ash/shell.h"
18 #include "ash/wm/coordinate_conversion.h"
19 #include "ash/wm/property_util.h"
20 #include "ash/wm/window_util.h"
21 #include "base/command_line.h"
22 #include "base/strings/stringprintf.h"
23 #include "third_party/skia/include/utils/SkMatrix44.h"
24 #include "ui/aura/client/activation_client.h"
25 #include "ui/aura/client/capture_client.h"
26 #include "ui/aura/client/cursor_client.h"
27 #include "ui/aura/client/focus_client.h"
28 #include "ui/aura/client/screen_position_client.h"
29 #include "ui/aura/root_window.h"
30 #include "ui/aura/root_window_transformer.h"
31 #include "ui/aura/window.h"
32 #include "ui/aura/window_property.h"
33 #include "ui/aura/window_tracker.h"
34 #include "ui/compositor/compositor.h"
35 #include "ui/compositor/dip_util.h"
36 #include "ui/gfx/display.h"
37 #include "ui/gfx/screen.h"
39 #if defined(OS_CHROMEOS)
40 #include "base/chromeos/chromeos_version.h"
41 #include "base/time/time.h"
42 #if defined(USE_X11)
43 #include "ash/display/output_configurator_animation.h"
44 #include "chromeos/display/output_configurator.h"
45 #include "ui/base/x/x11_util.h"
47 // Including this at the bottom to avoid other
48 // potential conflict with chrome headers.
49 #include <X11/extensions/Xrandr.h>
50 #undef RootWindow
51 #endif // defined(USE_X11)
52 #endif // defined(OS_CHROMEOS)
54 namespace ash {
55 namespace {
57 // Primary display stored in global object as it can be
58 // accessed after Shell is deleted. A separate display instance is created
59 // during the shutdown instead of always keeping two display instances
60 // (one here and another one in display_manager) in sync, which is error prone.
61 int64 primary_display_id = gfx::Display::kInvalidDisplayID;
62 gfx::Display* primary_display_for_shutdown = NULL;
63 // Keeps the number of displays during the shutdown after
64 // ash::Shell:: is deleted.
65 int num_displays_for_shutdown = -1;
67 // Specifies how long the display change should have been disabled
68 // after each display change operations.
69 // |kCycleDisplayThrottleTimeoutMs| is set to be longer to avoid
70 // changing the settings while the system is still configurating
71 // displays. It will be overriden by |kAfterDisplayChangeThrottleTimeoutMs|
72 // when the display change happens, so the actual timeout is much shorter.
73 const int64 kAfterDisplayChangeThrottleTimeoutMs = 500;
74 const int64 kCycleDisplayThrottleTimeoutMs = 4000;
75 const int64 kSwapDisplayThrottleTimeoutMs = 500;
77 internal::DisplayManager* GetDisplayManager() {
78 return Shell::GetInstance()->display_manager();
81 void SetDisplayPropertiesOnHostWindow(aura::RootWindow* root,
82 const gfx::Display& display) {
83 internal::DisplayInfo info =
84 GetDisplayManager()->GetDisplayInfo(display.id());
85 #if defined(OS_CHROMEOS) && defined(USE_X11)
86 // Native window property (Atom in X11) that specifies the display's
87 // rotation, scale factor and if it's internal display. They are
88 // read and used by touchpad/mouse driver directly on X (contact
89 // adlr@ for more details on touchpad/mouse driver side). The value
90 // of the rotation is one of 0 (normal), 1 (90 degrees clockwise), 2
91 // (180 degree) or 3 (270 degrees clockwise). The value of the
92 // scale factor is in percent (100, 140, 200 etc).
93 const char kRotationProp[] = "_CHROME_DISPLAY_ROTATION";
94 const char kScaleFactorProp[] = "_CHROME_DISPLAY_SCALE_FACTOR";
95 const char kInternalProp[] = "_CHROME_DISPLAY_INTERNAL";
96 const char kCARDINAL[] = "CARDINAL";
97 int xrandr_rotation = RR_Rotate_0;
98 switch (info.rotation()) {
99 case gfx::Display::ROTATE_0:
100 xrandr_rotation = RR_Rotate_0;
101 break;
102 case gfx::Display::ROTATE_90:
103 xrandr_rotation = RR_Rotate_90;
104 break;
105 case gfx::Display::ROTATE_180:
106 xrandr_rotation = RR_Rotate_180;
107 break;
108 case gfx::Display::ROTATE_270:
109 xrandr_rotation = RR_Rotate_270;
110 break;
113 int internal = display.IsInternal() ? 1 : 0;
114 gfx::AcceleratedWidget xwindow = root->GetAcceleratedWidget();
115 ui::SetIntProperty(xwindow, kInternalProp, kCARDINAL, internal);
116 ui::SetIntProperty(xwindow, kRotationProp, kCARDINAL, xrandr_rotation);
117 ui::SetIntProperty(xwindow,
118 kScaleFactorProp,
119 kCARDINAL,
120 100 * display.device_scale_factor());
121 #endif
122 scoped_ptr<aura::RootWindowTransformer> transformer(
123 internal::CreateRootWindowTransformerForDisplay(root, display));
124 root->SetRootWindowTransformer(transformer.Pass());
127 } // namespace
129 namespace internal {
131 // A utility class to store/restore focused/active window
132 // when the display configuration has changed.
133 class FocusActivationStore {
134 public:
135 FocusActivationStore()
136 : activation_client_(NULL),
137 capture_client_(NULL),
138 focus_client_(NULL),
139 focused_(NULL),
140 active_(NULL) {
143 void Store() {
144 if (!activation_client_) {
145 aura::RootWindow* root = Shell::GetPrimaryRootWindow();
146 activation_client_ = aura::client::GetActivationClient(root);
147 capture_client_ = aura::client::GetCaptureClient(root);
148 focus_client_ = aura::client::GetFocusClient(root);
150 focused_ = focus_client_->GetFocusedWindow();
151 if (focused_)
152 tracker_.Add(focused_);
153 active_ = activation_client_->GetActiveWindow();
154 if (active_ && focused_ != active_)
155 tracker_.Add(active_);
157 // Deactivate the window to close menu / bubble windows.
158 activation_client_->DeactivateWindow(active_);
159 // Release capture if any.
160 capture_client_->SetCapture(NULL);
161 // Clear the focused window if any. This is necessary because a
162 // window may be deleted when losing focus (fullscreen flash for
163 // example). If the focused window is still alive after move, it'll
164 // be re-focused below.
165 focus_client_->FocusWindow(NULL);
168 void Restore() {
169 // Restore focused or active window if it's still alive.
170 if (focused_ && tracker_.Contains(focused_)) {
171 focus_client_->FocusWindow(focused_);
172 } else if (active_ && tracker_.Contains(active_)) {
173 activation_client_->ActivateWindow(active_);
175 if (focused_)
176 tracker_.Remove(focused_);
177 if (active_)
178 tracker_.Remove(active_);
179 focused_ = NULL;
180 active_ = NULL;
183 private:
184 aura::client::ActivationClient* activation_client_;
185 aura::client::CaptureClient* capture_client_;
186 aura::client::FocusClient* focus_client_;
187 aura::WindowTracker tracker_;
188 aura::Window* focused_;
189 aura::Window* active_;
191 DISALLOW_COPY_AND_ASSIGN(FocusActivationStore);
194 } // namespace internal
196 ////////////////////////////////////////////////////////////////////////////////
197 // DisplayChangeLimiter
199 DisplayController::DisplayChangeLimiter::DisplayChangeLimiter()
200 : throttle_timeout_(base::Time::Now()) {
203 void DisplayController::DisplayChangeLimiter::SetThrottleTimeout(
204 int64 throttle_ms) {
205 throttle_timeout_ =
206 base::Time::Now() + base::TimeDelta::FromMilliseconds(throttle_ms);
209 bool DisplayController::DisplayChangeLimiter::IsThrottled() const {
210 return base::Time::Now() < throttle_timeout_;
213 ////////////////////////////////////////////////////////////////////////////////
214 // DisplayController
216 DisplayController::DisplayController()
217 : primary_root_window_for_replace_(NULL),
218 in_bootstrap_(true),
219 focus_activation_store_(new internal::FocusActivationStore()) {
220 CommandLine* command_line = CommandLine::ForCurrentProcess();
221 #if defined(OS_CHROMEOS)
222 if (!command_line->HasSwitch(switches::kAshDisableDisplayChangeLimiter) &&
223 base::chromeos::IsRunningOnChromeOS())
224 limiter_.reset(new DisplayChangeLimiter);
225 #endif
226 if (command_line->HasSwitch(switches::kAshSecondaryDisplayLayout)) {
227 std::string value = command_line->GetSwitchValueASCII(
228 switches::kAshSecondaryDisplayLayout);
229 char layout;
230 int offset = 0;
231 if (sscanf(value.c_str(), "%c,%d", &layout, &offset) == 2) {
232 if (layout == 't')
233 default_display_layout_.position = DisplayLayout::TOP;
234 else if (layout == 'b')
235 default_display_layout_.position = DisplayLayout::BOTTOM;
236 else if (layout == 'r')
237 default_display_layout_.position = DisplayLayout::RIGHT;
238 else if (layout == 'l')
239 default_display_layout_.position = DisplayLayout::LEFT;
240 default_display_layout_.offset = offset;
243 // Reset primary display to make sure that tests don't use
244 // stale display info from previous tests.
245 primary_display_id = gfx::Display::kInvalidDisplayID;
246 delete primary_display_for_shutdown;
247 primary_display_for_shutdown = NULL;
248 num_displays_for_shutdown = -1;
251 DisplayController::~DisplayController() {
252 DCHECK(primary_display_for_shutdown);
255 void DisplayController::Start() {
256 Shell::GetScreen()->AddObserver(this);
257 in_bootstrap_ = false;
260 void DisplayController::Shutdown() {
261 DCHECK(!primary_display_for_shutdown);
262 primary_display_for_shutdown = new gfx::Display(
263 GetDisplayManager()->GetDisplayForId(primary_display_id));
264 num_displays_for_shutdown = GetDisplayManager()->GetNumDisplays();
266 Shell::GetScreen()->RemoveObserver(this);
267 // Delete all root window controllers, which deletes root window
268 // from the last so that the primary root window gets deleted last.
269 for (std::map<int64, aura::RootWindow*>::const_reverse_iterator it =
270 root_windows_.rbegin(); it != root_windows_.rend(); ++it) {
271 internal::RootWindowController* controller =
272 GetRootWindowController(it->second);
273 DCHECK(controller);
274 delete controller;
278 // static
279 const gfx::Display& DisplayController::GetPrimaryDisplay() {
280 DCHECK_NE(primary_display_id, gfx::Display::kInvalidDisplayID);
281 if (primary_display_for_shutdown)
282 return *primary_display_for_shutdown;
283 return GetDisplayManager()->GetDisplayForId(primary_display_id);
286 // static
287 int DisplayController::GetNumDisplays() {
288 if (num_displays_for_shutdown >= 0)
289 return num_displays_for_shutdown;
290 return GetDisplayManager()->GetNumDisplays();
293 // static
294 bool DisplayController::HasPrimaryDisplay() {
295 return primary_display_id != gfx::Display::kInvalidDisplayID;
298 void DisplayController::InitPrimaryDisplay() {
299 const gfx::Display* primary_candidate =
300 GetDisplayManager()->GetPrimaryDisplayCandidate();
301 primary_display_id = primary_candidate->id();
302 AddRootWindowForDisplay(*primary_candidate);
305 void DisplayController::InitSecondaryDisplays() {
306 internal::DisplayManager* display_manager = GetDisplayManager();
307 UpdateDisplayBoundsForLayout();
308 for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) {
309 const gfx::Display* display = display_manager->GetDisplayAt(i);
310 if (primary_display_id != display->id()) {
311 aura::RootWindow* root = AddRootWindowForDisplay(*display);
312 Shell::GetInstance()->InitRootWindowForSecondaryDisplay(root);
315 if (display_manager->GetNumDisplays() > 1) {
316 DisplayIdPair pair = GetCurrentDisplayIdPair();
317 DisplayLayout layout = GetCurrentDisplayLayout();
318 SetPrimaryDisplayId(
319 layout.primary_id == gfx::Display::kInvalidDisplayID ?
320 pair.first : layout.primary_id);
322 UpdateHostWindowNames();
325 void DisplayController::AddObserver(Observer* observer) {
326 observers_.AddObserver(observer);
329 void DisplayController::RemoveObserver(Observer* observer) {
330 observers_.RemoveObserver(observer);
333 aura::RootWindow* DisplayController::GetPrimaryRootWindow() {
334 DCHECK(!root_windows_.empty());
335 return root_windows_[primary_display_id];
338 aura::RootWindow* DisplayController::GetRootWindowForDisplayId(int64 id) {
339 return root_windows_[id];
342 void DisplayController::CloseChildWindows() {
343 for (std::map<int64, aura::RootWindow*>::const_iterator it =
344 root_windows_.begin(); it != root_windows_.end(); ++it) {
345 aura::RootWindow* root_window = it->second;
346 internal::RootWindowController* controller =
347 GetRootWindowController(root_window);
348 if (controller) {
349 controller->CloseChildWindows();
350 } else {
351 while (!root_window->children().empty()) {
352 aura::Window* child = root_window->children()[0];
353 delete child;
359 std::vector<aura::RootWindow*> DisplayController::GetAllRootWindows() {
360 std::vector<aura::RootWindow*> windows;
361 for (std::map<int64, aura::RootWindow*>::const_iterator it =
362 root_windows_.begin(); it != root_windows_.end(); ++it) {
363 DCHECK(it->second);
364 if (GetRootWindowController(it->second))
365 windows.push_back(it->second);
367 return windows;
370 gfx::Insets DisplayController::GetOverscanInsets(int64 display_id) const {
371 return GetDisplayManager()->GetOverscanInsets(display_id);
374 void DisplayController::SetOverscanInsets(int64 display_id,
375 const gfx::Insets& insets_in_dip) {
376 GetDisplayManager()->SetOverscanInsets(display_id, insets_in_dip);
379 std::vector<internal::RootWindowController*>
380 DisplayController::GetAllRootWindowControllers() {
381 std::vector<internal::RootWindowController*> controllers;
382 for (std::map<int64, aura::RootWindow*>::const_iterator it =
383 root_windows_.begin(); it != root_windows_.end(); ++it) {
384 internal::RootWindowController* controller =
385 GetRootWindowController(it->second);
386 if (controller)
387 controllers.push_back(controller);
389 return controllers;
392 void DisplayController::SetDefaultDisplayLayout(const DisplayLayout& layout) {
393 CommandLine* command_line = CommandLine::ForCurrentProcess();
394 if (!command_line->HasSwitch(switches::kAshSecondaryDisplayLayout))
395 default_display_layout_ = layout;
398 void DisplayController::RegisterLayoutForDisplayIdPair(
399 int64 id1,
400 int64 id2,
401 const DisplayLayout& layout) {
402 RegisterLayoutForDisplayIdPairInternal(id1, id2, layout, true);
405 void DisplayController::SetLayoutForCurrentDisplays(
406 const DisplayLayout& layout_relative_to_primary) {
407 DCHECK_EQ(2U, GetDisplayManager()->GetNumDisplays());
408 if (GetDisplayManager()->GetNumDisplays() < 2)
409 return;
410 const gfx::Display& primary = GetPrimaryDisplay();
411 const DisplayIdPair pair = GetCurrentDisplayIdPair();
412 // Invert if the primary was swapped.
413 DisplayLayout to_set = pair.first == primary.id() ?
414 layout_relative_to_primary : layout_relative_to_primary.Invert();
416 const DisplayLayout& current_layout = paired_layouts_[pair];
417 if (to_set.position != current_layout.position ||
418 to_set.offset != current_layout.offset) {
419 to_set.primary_id = primary.id();
420 paired_layouts_[pair] = to_set;
421 NotifyDisplayConfigurationChanging();
422 // TODO(oshima): Call UpdateDisplays instead.
423 UpdateDisplayBoundsForLayout();
424 NotifyDisplayConfigurationChanged();
428 DisplayLayout DisplayController::GetCurrentDisplayLayout() {
429 DCHECK_EQ(2U, GetDisplayManager()->num_connected_displays());
430 // Invert if the primary was swapped.
431 if (GetDisplayManager()->num_connected_displays() > 1) {
432 DisplayIdPair pair = GetCurrentDisplayIdPair();
433 return ComputeDisplayLayoutForDisplayIdPair(pair);
435 // On release build, just fallback to default instead of blowing up.
436 DisplayLayout layout = default_display_layout_;
437 layout.primary_id = primary_display_id;
438 return layout;
441 DisplayIdPair DisplayController::GetCurrentDisplayIdPair() const {
442 internal::DisplayManager* display_manager = GetDisplayManager();
443 const gfx::Display& primary = GetPrimaryDisplay();
444 if (display_manager->IsMirrored()) {
445 return std::make_pair(primary.id(),
446 display_manager->mirrored_display().id());
449 const gfx::Display& secondary = ScreenAsh::GetSecondaryDisplay();
450 if (primary.IsInternal() ||
451 GetDisplayManager()->first_display_id() == primary.id()) {
452 return std::make_pair(primary.id(), secondary.id());
453 } else {
454 // Display has been Swapped.
455 return std::make_pair(secondary.id(), primary.id());
459 DisplayLayout DisplayController::GetRegisteredDisplayLayout(
460 const DisplayIdPair& pair) {
461 std::map<DisplayIdPair, DisplayLayout>::const_iterator iter =
462 paired_layouts_.find(pair);
463 return
464 iter != paired_layouts_.end() ? iter->second : CreateDisplayLayout(pair);
467 void DisplayController::ToggleMirrorMode() {
468 internal::DisplayManager* display_manager = GetDisplayManager();
469 if (display_manager->num_connected_displays() <= 1)
470 return;
472 if (limiter_) {
473 if (limiter_->IsThrottled())
474 return;
475 limiter_->SetThrottleTimeout(kCycleDisplayThrottleTimeoutMs);
477 #if defined(OS_CHROMEOS) && defined(USE_X11)
478 Shell* shell = Shell::GetInstance();
479 internal::OutputConfiguratorAnimation* animation =
480 shell->output_configurator_animation();
481 animation->StartFadeOutAnimation(base::Bind(
482 base::IgnoreResult(&internal::DisplayManager::SetMirrorMode),
483 base::Unretained(display_manager),
484 !display_manager->IsMirrored()));
485 #endif
488 void DisplayController::SwapPrimaryDisplay() {
489 if (limiter_) {
490 if (limiter_->IsThrottled())
491 return;
492 limiter_->SetThrottleTimeout(kSwapDisplayThrottleTimeoutMs);
495 if (Shell::GetScreen()->GetNumDisplays() > 1) {
496 #if defined(OS_CHROMEOS) && defined(USE_X11)
497 internal::OutputConfiguratorAnimation* animation =
498 Shell::GetInstance()->output_configurator_animation();
499 if (animation) {
500 animation->StartFadeOutAnimation(base::Bind(
501 &DisplayController::OnFadeOutForSwapDisplayFinished,
502 base::Unretained(this)));
503 } else {
504 SetPrimaryDisplay(ScreenAsh::GetSecondaryDisplay());
506 #else
507 SetPrimaryDisplay(ScreenAsh::GetSecondaryDisplay());
508 #endif
512 void DisplayController::SetPrimaryDisplayId(int64 id) {
513 DCHECK_NE(gfx::Display::kInvalidDisplayID, id);
514 if (id == gfx::Display::kInvalidDisplayID || primary_display_id == id)
515 return;
517 const gfx::Display& display = GetDisplayManager()->GetDisplayForId(id);
518 if (display.is_valid())
519 SetPrimaryDisplay(display);
522 void DisplayController::SetPrimaryDisplay(
523 const gfx::Display& new_primary_display) {
524 internal::DisplayManager* display_manager = GetDisplayManager();
525 DCHECK(new_primary_display.is_valid());
526 DCHECK(display_manager->IsActiveDisplay(new_primary_display));
528 if (!new_primary_display.is_valid() ||
529 !display_manager->IsActiveDisplay(new_primary_display)) {
530 LOG(ERROR) << "Invalid or non-existent display is requested:"
531 << new_primary_display.ToString();
532 return;
535 if (primary_display_id == new_primary_display.id() ||
536 root_windows_.size() < 2) {
537 return;
540 aura::RootWindow* non_primary_root = root_windows_[new_primary_display.id()];
541 LOG_IF(ERROR, !non_primary_root)
542 << "Unknown display is requested in SetPrimaryDisplay: id="
543 << new_primary_display.id();
544 if (!non_primary_root)
545 return;
547 gfx::Display old_primary_display = GetPrimaryDisplay();
549 // Swap root windows between current and new primary display.
550 aura::RootWindow* primary_root = root_windows_[primary_display_id];
551 DCHECK(primary_root);
552 DCHECK_NE(primary_root, non_primary_root);
554 root_windows_[new_primary_display.id()] = primary_root;
555 primary_root->SetProperty(internal::kDisplayIdKey, new_primary_display.id());
557 root_windows_[old_primary_display.id()] = non_primary_root;
558 non_primary_root->SetProperty(internal::kDisplayIdKey,
559 old_primary_display.id());
561 primary_display_id = new_primary_display.id();
562 paired_layouts_[GetCurrentDisplayIdPair()].primary_id = primary_display_id;
564 display_manager->UpdateWorkAreaOfDisplayNearestWindow(
565 primary_root, old_primary_display.GetWorkAreaInsets());
566 display_manager->UpdateWorkAreaOfDisplayNearestWindow(
567 non_primary_root, new_primary_display.GetWorkAreaInsets());
569 // Update the dispay manager with new display info.
570 std::vector<internal::DisplayInfo> display_info_list;
571 display_info_list.push_back(display_manager->GetDisplayInfo(
572 primary_display_id));
573 display_info_list.push_back(display_manager->GetDisplayInfo(
574 GetSecondaryDisplay()->id()));
575 GetDisplayManager()->set_force_bounds_changed(true);
576 GetDisplayManager()->UpdateDisplays(display_info_list);
577 GetDisplayManager()->set_force_bounds_changed(false);
580 gfx::Display* DisplayController::GetSecondaryDisplay() {
581 internal::DisplayManager* display_manager = GetDisplayManager();
582 CHECK_EQ(2U, display_manager->GetNumDisplays());
583 return display_manager->GetDisplayAt(0)->id() == primary_display_id ?
584 display_manager->GetDisplayAt(1) : display_manager->GetDisplayAt(0);
587 void DisplayController::EnsurePointerInDisplays() {
588 // Don't try to move the pointer during the boot/startup.
589 if (!HasPrimaryDisplay())
590 return;
591 gfx::Point location_in_screen = Shell::GetScreen()->GetCursorScreenPoint();
592 gfx::Point target_location;
593 int64 closest_distance_squared = -1;
594 internal::DisplayManager* display_manager = GetDisplayManager();
596 aura::RootWindow* dst_root_window = NULL;
597 for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) {
598 const gfx::Display* display = display_manager->GetDisplayAt(i);
599 aura::RootWindow* root_window = GetRootWindowForDisplayId(display->id());
600 if (display->bounds().Contains(location_in_screen)) {
601 dst_root_window = root_window;
602 target_location = location_in_screen;
603 break;
605 gfx::Point center = display->bounds().CenterPoint();
606 // Use the distance squared from the center of the dislay. This is not
607 // exactly "closest" display, but good enough to pick one
608 // appropriate (and there are at most two displays).
609 // We don't care about actual distance, only relative to other displays, so
610 // using the LengthSquared() is cheaper than Length().
612 int64 distance_squared = (center - location_in_screen).LengthSquared();
613 if (closest_distance_squared < 0 ||
614 closest_distance_squared > distance_squared) {
615 dst_root_window = root_window;
616 target_location = center;
617 closest_distance_squared = distance_squared;
620 DCHECK(dst_root_window);
621 aura::client::ScreenPositionClient* client =
622 aura::client::GetScreenPositionClient(dst_root_window);
623 client->ConvertPointFromScreen(dst_root_window, &target_location);
624 dst_root_window->MoveCursorTo(target_location);
627 gfx::Point DisplayController::GetNativeMouseCursorLocation() const {
628 if (in_bootstrap())
629 return gfx::Point();
631 gfx::Point location = Shell::GetScreen()->GetCursorScreenPoint();
632 const gfx::Display& display =
633 Shell::GetScreen()->GetDisplayNearestPoint(location);
634 const aura::RootWindow* root_window =
635 root_windows_.find(display.id())->second;
636 aura::client::ScreenPositionClient* client =
637 aura::client::GetScreenPositionClient(root_window);
638 client->ConvertPointFromScreen(root_window, &location);
639 root_window->ConvertPointToNativeScreen(&location);
640 return location;
643 void DisplayController::UpdateMouseCursor(const gfx::Point& point_in_native) {
644 if (in_bootstrap())
645 return;
647 std::vector<aura::RootWindow*> root_windows = GetAllRootWindows();
648 for (std::vector<aura::RootWindow*>::iterator iter = root_windows.begin();
649 iter != root_windows.end();
650 ++iter) {
651 aura::RootWindow* root_window = *iter;
652 gfx::Rect bounds_in_native(root_window->GetHostOrigin(),
653 root_window->GetHostSize());
654 if (bounds_in_native.Contains(point_in_native)) {
655 gfx::Point point(point_in_native);
656 root_window->ConvertPointFromNativeScreen(&point);
657 root_window->MoveCursorTo(point);
658 break;
663 void DisplayController::OnDisplayBoundsChanged(const gfx::Display& display) {
664 const internal::DisplayInfo& display_info =
665 GetDisplayManager()->GetDisplayInfo(display.id());
666 DCHECK(!display_info.bounds_in_pixel().IsEmpty());
667 aura::RootWindow* root = root_windows_[display.id()];
668 root->SetHostBounds(display_info.bounds_in_pixel());
669 SetDisplayPropertiesOnHostWindow(root, display);
672 void DisplayController::OnDisplayAdded(const gfx::Display& display) {
673 if (primary_root_window_for_replace_) {
674 DCHECK(root_windows_.empty());
675 primary_display_id = display.id();
676 root_windows_[display.id()] = primary_root_window_for_replace_;
677 primary_root_window_for_replace_->SetProperty(
678 internal::kDisplayIdKey, display.id());
679 primary_root_window_for_replace_ = NULL;
680 const internal::DisplayInfo& display_info =
681 GetDisplayManager()->GetDisplayInfo(display.id());
682 root_windows_[display.id()]->SetHostBounds(
683 display_info.bounds_in_pixel());
684 } else {
685 if (primary_display_id == gfx::Display::kInvalidDisplayID)
686 primary_display_id = display.id();
687 DCHECK(!root_windows_.empty());
688 aura::RootWindow* root = AddRootWindowForDisplay(display);
689 Shell::GetInstance()->InitRootWindowForSecondaryDisplay(root);
693 void DisplayController::OnDisplayRemoved(const gfx::Display& display) {
694 aura::RootWindow* root_to_delete = root_windows_[display.id()];
695 DCHECK(root_to_delete) << display.ToString();
697 // Display for root window will be deleted when the Primary RootWindow
698 // is deleted by the Shell.
699 root_windows_.erase(display.id());
701 // When the primary root window's display is removed, move the primary
702 // root to the other display.
703 if (primary_display_id == display.id()) {
704 // Temporarily store the primary root window in
705 // |primary_root_window_for_replace_| when replacing the display.
706 if (root_windows_.size() == 0) {
707 primary_display_id = gfx::Display::kInvalidDisplayID;
708 primary_root_window_for_replace_ = root_to_delete;
709 return;
711 DCHECK_EQ(1U, root_windows_.size());
712 primary_display_id = GetSecondaryDisplay()->id();
713 aura::RootWindow* primary_root = root_to_delete;
715 // Delete the other root instead.
716 root_to_delete = root_windows_[primary_display_id];
717 root_to_delete->SetProperty(internal::kDisplayIdKey, display.id());
719 // Setup primary root.
720 root_windows_[primary_display_id] = primary_root;
721 primary_root->SetProperty(internal::kDisplayIdKey, primary_display_id);
723 OnDisplayBoundsChanged(
724 GetDisplayManager()->GetDisplayForId(primary_display_id));
726 internal::RootWindowController* controller =
727 GetRootWindowController(root_to_delete);
728 DCHECK(controller);
729 controller->MoveWindowsTo(GetPrimaryRootWindow());
730 // Delete most of root window related objects, but don't delete
731 // root window itself yet because the stack may be using it.
732 controller->Shutdown();
733 base::MessageLoop::current()->DeleteSoon(FROM_HERE, controller);
736 aura::RootWindow* DisplayController::AddRootWindowForDisplay(
737 const gfx::Display& display) {
738 static int root_window_count = 0;
739 const internal::DisplayInfo& display_info =
740 GetDisplayManager()->GetDisplayInfo(display.id());
741 const gfx::Rect& bounds_in_pixel = display_info.bounds_in_pixel();
742 aura::RootWindow::CreateParams params(bounds_in_pixel);
743 params.host = Shell::GetInstance()->root_window_host_factory()->
744 CreateRootWindowHost(bounds_in_pixel);
745 aura::RootWindow* root_window = new aura::RootWindow(params);
746 root_window->SetName(
747 base::StringPrintf("RootWindow-%d", root_window_count++));
748 root_window->compositor()->SetBackgroundColor(SK_ColorBLACK);
749 // No need to remove RootWindowObserver because
750 // the DisplayManager object outlives RootWindow objects.
751 root_window->AddRootWindowObserver(GetDisplayManager());
752 root_window->SetProperty(internal::kDisplayIdKey, display.id());
753 root_window->Init();
755 root_windows_[display.id()] = root_window;
756 SetDisplayPropertiesOnHostWindow(root_window, display);
758 #if defined(OS_CHROMEOS)
759 static bool force_constrain_pointer_to_root =
760 CommandLine::ForCurrentProcess()->HasSwitch(
761 switches::kAshConstrainPointerToRoot);
762 if (base::chromeos::IsRunningOnChromeOS() || force_constrain_pointer_to_root)
763 root_window->ConfineCursorToWindow();
764 #endif
765 return root_window;
768 void DisplayController::UpdateDisplayBoundsForLayout() {
769 if (Shell::GetScreen()->GetNumDisplays() < 2 ||
770 GetDisplayManager()->num_connected_displays() < 2) {
771 return;
773 DCHECK_EQ(2, Shell::GetScreen()->GetNumDisplays());
775 const DisplayLayout layout = GetCurrentDisplayLayout();
776 Shell::GetInstance()->display_manager()->UpdateDisplayBoundsForLayout(
777 layout, GetPrimaryDisplay(), GetSecondaryDisplay());
780 void DisplayController::NotifyDisplayConfigurationChanging() {
781 if (in_bootstrap())
782 return;
783 FOR_EACH_OBSERVER(Observer, observers_, OnDisplayConfigurationChanging());
784 focus_activation_store_->Store();
787 void DisplayController::NotifyDisplayConfigurationChanged() {
788 if (in_bootstrap())
789 return;
791 if (limiter_)
792 limiter_->SetThrottleTimeout(kAfterDisplayChangeThrottleTimeoutMs);
794 focus_activation_store_->Restore();
796 internal::DisplayManager* display_manager = GetDisplayManager();
797 if (display_manager->num_connected_displays() > 1) {
798 DisplayIdPair pair = GetCurrentDisplayIdPair();
799 if (paired_layouts_.find(pair) == paired_layouts_.end())
800 CreateDisplayLayout(pair);
801 paired_layouts_[pair].mirrored = display_manager->IsMirrored();
802 if (Shell::GetScreen()->GetNumDisplays() > 1 ) {
803 int64 primary_id = paired_layouts_[pair].primary_id;
804 SetPrimaryDisplayId(
805 primary_id == gfx::Display::kInvalidDisplayID ?
806 pair.first : primary_id);
807 // Update the primary_id in case the above call is
808 // ignored. Happens when a) default layout's primary id
809 // doesn't exist, or b) the primary_id has already been
810 // set to the same and didn't update it.
811 paired_layouts_[pair].primary_id = GetPrimaryDisplay().id();
814 FOR_EACH_OBSERVER(Observer, observers_, OnDisplayConfigurationChanged());
815 UpdateHostWindowNames();
818 void DisplayController::RegisterLayoutForDisplayIdPairInternal(
819 int64 id1,
820 int64 id2,
821 const DisplayLayout& layout,
822 bool override) {
823 DisplayIdPair pair = std::make_pair(id1, id2);
824 if (override || paired_layouts_.find(pair) == paired_layouts_.end())
825 paired_layouts_[pair] = layout;
828 void DisplayController::OnFadeOutForSwapDisplayFinished() {
829 #if defined(OS_CHROMEOS) && defined(USE_X11)
830 SetPrimaryDisplay(ScreenAsh::GetSecondaryDisplay());
831 Shell::GetInstance()->output_configurator_animation()->StartFadeInAnimation();
832 #endif
835 DisplayLayout DisplayController::ComputeDisplayLayoutForDisplayIdPair(
836 const DisplayIdPair& pair) {
837 DisplayLayout layout = GetRegisteredDisplayLayout(pair);
838 int64 primary_id = layout.primary_id;
839 // TODO(oshima): replace this with DCHECK.
840 if (primary_id == gfx::Display::kInvalidDisplayID)
841 primary_id = GetPrimaryDisplay().id();
842 // Invert if the primary was swapped. If mirrored, first is always
843 // primary.
844 return pair.first == primary_id ? layout : layout.Invert();
847 void DisplayController::UpdateHostWindowNames() {
848 #if defined(USE_X11)
849 // crbug.com/120229 - set the window title for the primary dislpay
850 // to "aura_root_0" so gtalk can find the primary root window to broadcast.
851 // TODO(jhorwich) Remove this once Chrome supports window-based broadcasting.
852 aura::RootWindow* primary = Shell::GetPrimaryRootWindow();
853 Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
854 for (size_t i = 0; i < root_windows.size(); ++i) {
855 std::string name =
856 root_windows[i] == primary ? "aura_root_0" : "aura_root_x";
857 gfx::AcceleratedWidget xwindow = root_windows[i]->GetAcceleratedWidget();
858 XStoreName(ui::GetXDisplay(), xwindow, name.c_str());
860 #endif
863 DisplayLayout DisplayController::CreateDisplayLayout(
864 const DisplayIdPair& pair) {
865 DisplayLayout layout = default_display_layout_;
866 layout.primary_id = pair.first;
867 paired_layouts_[pair] = layout;
868 return layout;
871 } // namespace ash