display_controller.cc revision c5cede9ae108bb15f6b7a8aea21c7e1fefa2834c
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. 4 5#include "ash/display/display_controller.h" 6 7#include <algorithm> 8#include <cmath> 9#include <map> 10 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" 40 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" 45#if defined(USE_X11) 46#include "ui/base/x/x11_util.h" 47#include "ui/gfx/x/x11_types.h" 48 49// Including this at the bottom to avoid other 50// potential conflict with chrome headers. 51#include <X11/extensions/Xrandr.h> 52#undef RootWindow 53#endif // defined(USE_X11) 54#endif // defined(OS_CHROMEOS) 55 56namespace ash { 57namespace { 58 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. 63int64 primary_display_id = gfx::Display::kInvalidDisplayID; 64 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. 71const int64 kAfterDisplayChangeThrottleTimeoutMs = 500; 72const int64 kCycleDisplayThrottleTimeoutMs = 4000; 73const int64 kSwapDisplayThrottleTimeoutMs = 500; 74 75DisplayManager* GetDisplayManager() { 76 return Shell::GetInstance()->display_manager(); 77} 78 79void 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; 98 break; 99 case gfx::Display::ROTATE_90: 100 xrandr_rotation = RR_Rotate_90; 101 break; 102 case gfx::Display::ROTATE_180: 103 xrandr_rotation = RR_Rotate_180; 104 break; 105 case gfx::Display::ROTATE_270: 106 xrandr_rotation = RR_Rotate_270; 107 break; 108 } 109 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, 115 kScaleFactorProp, 116 kCARDINAL, 117 100 * display.device_scale_factor()); 118#endif 119 scoped_ptr<aura::RootWindowTransformer> transformer( 120 CreateRootWindowTransformerForDisplay(host->window(), display)); 121 host->SetRootWindowTransformer(transformer.Pass()); 122 123 DisplayMode mode; 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)); 129 } 130} 131 132} // namespace 133 134// A utility class to store/restore focused/active window 135// when the display configuration has changed. 136class FocusActivationStore { 137 public: 138 FocusActivationStore() 139 : activation_client_(NULL), 140 capture_client_(NULL), 141 focus_client_(NULL), 142 focused_(NULL), 143 active_(NULL) { 144 } 145 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); 152 } 153 focused_ = focus_client_->GetFocusedWindow(); 154 if (focused_) 155 tracker_.Add(focused_); 156 active_ = activation_client_->GetActiveWindow(); 157 if (active_ && focused_ != active_) 158 tracker_.Add(active_); 159 160 // Deactivate the window to close menu / bubble windows. 161 if (clear_focus) 162 activation_client_->DeactivateWindow(active_); 163 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. 170 if (clear_focus) 171 focus_client_->FocusWindow(NULL); 172 } 173 174 void Restore() { 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_); 180 } 181 if (focused_) 182 tracker_.Remove(focused_); 183 if (active_) 184 tracker_.Remove(active_); 185 focused_ = NULL; 186 active_ = NULL; 187 } 188 189 private: 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_; 196 197 DISALLOW_COPY_AND_ASSIGN(FocusActivationStore); 198}; 199 200//////////////////////////////////////////////////////////////////////////////// 201// DisplayChangeLimiter 202 203DisplayController::DisplayChangeLimiter::DisplayChangeLimiter() 204 : throttle_timeout_(base::Time::Now()) { 205} 206 207void DisplayController::DisplayChangeLimiter::SetThrottleTimeout( 208 int64 throttle_ms) { 209 throttle_timeout_ = 210 base::Time::Now() + base::TimeDelta::FromMilliseconds(throttle_ms); 211} 212 213bool DisplayController::DisplayChangeLimiter::IsThrottled() const { 214 return base::Time::Now() < throttle_timeout_; 215} 216 217//////////////////////////////////////////////////////////////////////////////// 218// DisplayController 219 220DisplayController::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); 228#endif 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; 232} 233 234DisplayController::~DisplayController() { 235} 236 237void 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); 244 245 FOR_EACH_OBSERVER(Observer, observers_, OnDisplaysInitialized()); 246} 247 248void DisplayController::Shutdown() { 249 // Unset the display manager's delegate here because 250 // DisplayManager outlives DisplayController. 251 Shell::GetInstance()->display_manager()->set_delegate(NULL); 252 253 cursor_window_controller_.reset(); 254 mirror_window_controller_.reset(); 255 virtual_keyboard_window_controller_.reset(); 256 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); 263 DCHECK(controller); 264 delete controller; 265 } 266} 267 268void DisplayController::InitPrimaryDisplay() { 269 const gfx::Display& primary_candidate = 270 GetDisplayManager()->GetPrimaryDisplayCandidate(); 271 primary_display_id = primary_candidate.id(); 272 AddWindowTreeHostForDisplay(primary_candidate); 273} 274 275void 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); 282 } 283 } 284 UpdateHostWindowNames(); 285} 286 287void DisplayController::AddObserver(Observer* observer) { 288 observers_.AddObserver(observer); 289} 290 291void DisplayController::RemoveObserver(Observer* observer) { 292 observers_.RemoveObserver(observer); 293} 294 295// static 296int64 DisplayController::GetPrimaryDisplayId() { 297 return primary_display_id; 298} 299 300aura::Window* DisplayController::GetPrimaryRootWindow() { 301 DCHECK(!root_windows_.empty()); 302 return root_windows_[primary_display_id]; 303} 304 305aura::Window* DisplayController::GetRootWindowForDisplayId(int64 id) { 306 return root_windows_[id]; 307} 308 309void 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); 314 if (controller) { 315 controller->CloseChildWindows(); 316 } else { 317 while (!root_window->children().empty()) { 318 aura::Window* child = root_window->children()[0]; 319 delete child; 320 } 321 } 322 } 323} 324 325aura::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) { 329 DCHECK(it->second); 330 if (GetRootWindowController(it->second)) 331 windows.push_back(it->second); 332 } 333 return windows; 334} 335 336gfx::Insets DisplayController::GetOverscanInsets(int64 display_id) const { 337 return GetDisplayManager()->GetOverscanInsets(display_id); 338} 339 340void DisplayController::SetOverscanInsets(int64 display_id, 341 const gfx::Insets& insets_in_dip) { 342 GetDisplayManager()->SetOverscanInsets(display_id, insets_in_dip); 343} 344 345std::vector<RootWindowController*> 346DisplayController::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); 351 if (controller) 352 controllers.push_back(controller); 353 } 354 return controllers; 355} 356 357void DisplayController::ToggleMirrorMode() { 358 DisplayManager* display_manager = GetDisplayManager(); 359 if (display_manager->num_connected_displays() <= 1) 360 return; 361 362 if (limiter_) { 363 if (limiter_->IsThrottled()) 364 return; 365 limiter_->SetThrottleTimeout(kCycleDisplayThrottleTimeoutMs); 366 } 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())); 375#endif 376} 377 378void DisplayController::SwapPrimaryDisplay() { 379 if (limiter_) { 380 if (limiter_->IsThrottled()) 381 return; 382 limiter_->SetThrottleTimeout(kSwapDisplayThrottleTimeoutMs); 383 } 384 385 if (Shell::GetScreen()->GetNumDisplays() > 1) { 386#if defined(OS_CHROMEOS) 387 OutputConfiguratorAnimation* animation = 388 Shell::GetInstance()->output_configurator_animation(); 389 if (animation) { 390 animation->StartFadeOutAnimation(base::Bind( 391 &DisplayController::OnFadeOutForSwapDisplayFinished, 392 base::Unretained(this))); 393 } else { 394 SetPrimaryDisplay(ScreenUtil::GetSecondaryDisplay()); 395 } 396#else 397 SetPrimaryDisplay(ScreenUtil::GetSecondaryDisplay()); 398#endif 399 } 400} 401 402void DisplayController::SetPrimaryDisplayId(int64 id) { 403 DCHECK_NE(gfx::Display::kInvalidDisplayID, id); 404 if (id == gfx::Display::kInvalidDisplayID || primary_display_id == id) 405 return; 406 407 const gfx::Display& display = GetDisplayManager()->GetDisplayForId(id); 408 if (display.is_valid()) 409 SetPrimaryDisplay(display); 410} 411 412void 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)); 417 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(); 422 return; 423 } 424 425 if (primary_display_id == new_primary_display.id() || 426 root_windows_.size() < 2) { 427 return; 428 } 429 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) 435 return; 436 437 gfx::Display old_primary_display = Shell::GetScreen()->GetPrimaryDisplay(); 438 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); 443 444 root_windows_[new_primary_display.id()] = primary_root; 445 GetRootWindowSettings(primary_root)->display_id = new_primary_display.id(); 446 447 root_windows_[old_primary_display.id()] = non_primary_root; 448 GetRootWindowSettings(non_primary_root)->display_id = 449 old_primary_display.id(); 450 451 primary_display_id = new_primary_display.id(); 452 GetDisplayManager()->layout_store()->UpdatePrimaryDisplayId( 453 display_manager->GetCurrentDisplayIdPair(), primary_display_id); 454 455 UpdateWorkAreaOfDisplayNearestWindow( 456 primary_root, old_primary_display.GetWorkAreaInsets()); 457 UpdateWorkAreaOfDisplayNearestWindow( 458 non_primary_root, new_primary_display.GetWorkAreaInsets()); 459 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); 469} 470 471void 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. 475 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(); 480 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_; 491 break; 492 } 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(). 499 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; 511 } 512 } 513 dst_root_window->GetHost()->ConvertPointFromNativeScreen( 514 &target_location_in_native); 515 dst_root_window->MoveCursorTo(target_location_in_native); 516} 517 518bool 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); 526} 527 528void 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); 535} 536 537void 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 = 543 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); 550 } else { 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); 556 } 557} 558 559void DisplayController::OnDisplayRemoved(const gfx::Display& display) { 560 aura::Window* root_to_delete = root_windows_[display.id()]; 561 DCHECK(root_to_delete) << display.ToString(); 562 563 // Display for root window will be deleted when the Primary RootWindow 564 // is deleted by the Shell. 565 root_windows_.erase(display.id()); 566 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; 575 return; 576 } 577 DCHECK_EQ(1U, root_windows_.size()); 578 primary_display_id = ScreenUtil::GetSecondaryDisplay().id(); 579 aura::Window* primary_root = root_to_delete; 580 581 // Delete the other root instead. 582 root_to_delete = root_windows_[primary_display_id]; 583 GetRootWindowSettings(root_to_delete)->display_id = display.id(); 584 585 // Setup primary root. 586 root_windows_[primary_display_id] = primary_root; 587 GetRootWindowSettings(primary_root)->display_id = primary_display_id; 588 589 OnDisplayBoundsChanged( 590 GetDisplayManager()->GetDisplayForId(primary_display_id)); 591 } 592 RootWindowController* controller = GetRootWindowController(root_to_delete); 593 DCHECK(controller); 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); 599} 600 601void DisplayController::OnHostResized(const aura::WindowTreeHost* host) { 602 gfx::Display display = Shell::GetScreen()->GetDisplayNearestWindow( 603 const_cast<aura::Window*>(host->window())); 604 605 DisplayManager* display_manager = GetDisplayManager(); 606 if (display_manager->UpdateDisplayBounds(display.id(), host->GetBounds())) { 607 mirror_window_controller_->UpdateWindow(); 608 cursor_window_controller_->UpdateContainer(); 609 } 610} 611 612void 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(); 619 break; 620 case DisplayManager::VIRTUAL_KEYBOARD: 621 mirror_window_controller_->Close(); 622 cursor_window_controller_->UpdateContainer(); 623 virtual_keyboard_window_controller_->UpdateWindow(info); 624 break; 625 case DisplayManager::EXTENDED: 626 NOTREACHED(); 627 } 628} 629 630void DisplayController::CloseNonDesktopDisplay() { 631 mirror_window_controller_->Close(); 632 cursor_window_controller_->UpdateContainer(); 633 virtual_keyboard_window_controller_->Close(); 634} 635 636void 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()); 643 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; 649} 650 651void DisplayController::PostDisplayConfigurationChange() { 652 if (limiter_) 653 limiter_->SetThrottleTimeout(kAfterDisplayChangeThrottleTimeoutMs); 654 655 focus_activation_store_->Restore(); 656 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); 663 664 if (Shell::GetScreen()->GetNumDisplays() > 1 ) { 665 int64 primary_id = layout.primary_id; 666 SetPrimaryDisplayId( 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()); 675 } 676 } 677 FOR_EACH_OBSERVER(Observer, observers_, OnDisplayConfigurationChanged()); 678 UpdateHostWindowNames(); 679 EnsurePointerInDisplays(); 680} 681 682aura::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( 690 bounds_in_native); 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(); 697 host->InitHost(); 698 699 root_windows_[display.id()] = host->window(); 700 SetDisplayPropertiesOnHost(host, display); 701 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(); 708#endif 709 return host; 710} 711 712void DisplayController::OnFadeOutForSwapDisplayFinished() { 713#if defined(OS_CHROMEOS) 714 SetPrimaryDisplay(ScreenUtil::GetSecondaryDisplay()); 715 Shell::GetInstance()->output_configurator_animation()->StartFadeInAnimation(); 716#endif 717} 718 719void DisplayController::UpdateHostWindowNames() { 720#if defined(USE_X11) 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) { 727 std::string name = 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()); 732 } 733#endif 734} 735 736} // namespace ash 737