OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ash/display/display_controller.h" | 5 #include "ash/display/display_controller.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "ash/ash_switches.h" | 9 #include "ash/ash_switches.h" |
10 #include "ash/display/multi_display_manager.h" | 10 #include "ash/display/multi_display_manager.h" |
(...skipping 17 matching lines...) Expand all Loading... |
28 | 28 |
29 #if defined(OS_CHROMEOS) | 29 #if defined(OS_CHROMEOS) |
30 #include "base/chromeos/chromeos_version.h" | 30 #include "base/chromeos/chromeos_version.h" |
31 #endif | 31 #endif |
32 | 32 |
33 namespace ash { | 33 namespace ash { |
34 namespace { | 34 namespace { |
35 | 35 |
36 // Primary display stored in global object as it can be | 36 // Primary display stored in global object as it can be |
37 // accessed after Shell is deleted. | 37 // accessed after Shell is deleted. |
38 gfx::Display* primary_display = NULL; | 38 int64 primary_display_id = gfx::Display::kInvalidDisplayID; |
39 | 39 |
40 // The maximum value for 'offset' in DisplayLayout in case of outliers. Need | 40 // The maximum value for 'offset' in DisplayLayout in case of outliers. Need |
41 // to change this value in case to support even larger displays. | 41 // to change this value in case to support even larger displays. |
42 const int kMaxValidOffset = 10000; | 42 const int kMaxValidOffset = 10000; |
43 | 43 |
44 // The number of pixels to overlap between the primary and secondary displays, | 44 // The number of pixels to overlap between the primary and secondary displays, |
45 // in case that the offset value is too large. | 45 // in case that the offset value is too large. |
46 const int kMinimumOverlapForInvalidOffset = 50; | 46 const int kMinimumOverlapForInvalidOffset = 50; |
47 | 47 |
48 bool GetPositionFromString(const base::StringPiece& position, | 48 bool GetPositionFromString(const base::StringPiece& position, |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
149 | 149 |
150 // static | 150 // static |
151 void DisplayLayout::RegisterJSONConverter( | 151 void DisplayLayout::RegisterJSONConverter( |
152 base::JSONValueConverter<DisplayLayout>* converter) { | 152 base::JSONValueConverter<DisplayLayout>* converter) { |
153 converter->RegisterCustomField<Position>( | 153 converter->RegisterCustomField<Position>( |
154 "position", &DisplayLayout::position, &GetPositionFromString); | 154 "position", &DisplayLayout::position, &GetPositionFromString); |
155 converter->RegisterIntField("offset", &DisplayLayout::offset); | 155 converter->RegisterIntField("offset", &DisplayLayout::offset); |
156 } | 156 } |
157 | 157 |
158 DisplayController::DisplayController() { | 158 DisplayController::DisplayController() { |
159 // Reinstantiate display to make sure that tests don't use | 159 // Reset primary display to make sure that tests don't use |
160 // stale display info from previous tests. | 160 // stale display info from previous tests. |
161 delete primary_display; | 161 primary_display_id = gfx::Display::kInvalidDisplayID; |
162 primary_display = new gfx::Display(); | |
163 | 162 |
164 GetDisplayManager()->AddObserver(this); | 163 GetDisplayManager()->AddObserver(this); |
165 } | 164 } |
166 | 165 |
167 DisplayController::~DisplayController() { | 166 DisplayController::~DisplayController() { |
168 GetDisplayManager()->RemoveObserver(this); | 167 GetDisplayManager()->RemoveObserver(this); |
169 // Delete all root window controllers, which deletes root window | 168 // Delete all root window controllers, which deletes root window |
170 // from the last so that the primary root window gets deleted last. | 169 // from the last so that the primary root window gets deleted last. |
171 for (std::map<int64, aura::RootWindow*>::const_reverse_iterator it = | 170 for (std::map<int64, aura::RootWindow*>::const_reverse_iterator it = |
172 root_windows_.rbegin(); it != root_windows_.rend(); ++it) { | 171 root_windows_.rbegin(); it != root_windows_.rend(); ++it) { |
173 internal::RootWindowController* controller = | 172 internal::RootWindowController* controller = |
174 GetRootWindowController(it->second); | 173 GetRootWindowController(it->second); |
175 DCHECK(controller); | 174 DCHECK(controller); |
176 delete controller; | 175 delete controller; |
177 } | 176 } |
178 } | 177 } |
179 // static | 178 // static |
180 gfx::Display DisplayController::GetPrimaryDisplay() { | 179 const gfx::Display& DisplayController::GetPrimaryDisplay() { |
181 DCHECK(primary_display); | 180 DCHECK_NE(primary_display_id, gfx::Display::kInvalidDisplayID); |
182 return *primary_display; | 181 return GetDisplayManager()->GetDisplayForId(primary_display_id); |
183 } | 182 } |
184 | 183 |
185 void DisplayController::InitPrimaryDisplay() { | 184 void DisplayController::InitPrimaryDisplay() { |
186 const gfx::Display* primary_candidate = GetDisplayManager()->GetDisplayAt(0); | 185 const gfx::Display* primary_candidate = GetDisplayManager()->GetDisplayAt(0); |
187 #if defined(OS_CHROMEOS) | 186 #if defined(OS_CHROMEOS) |
188 if (base::chromeos::IsRunningOnChromeOS()) { | 187 if (base::chromeos::IsRunningOnChromeOS()) { |
189 internal::MultiDisplayManager* display_manager = GetDisplayManager(); | 188 internal::MultiDisplayManager* display_manager = GetDisplayManager(); |
190 // On ChromeOS device, root windows are stacked vertically, and | 189 // On ChromeOS device, root windows are stacked vertically, and |
191 // default primary is the one on top. | 190 // default primary is the one on top. |
192 int count = display_manager->GetNumDisplays(); | 191 int count = display_manager->GetNumDisplays(); |
193 int y = primary_candidate->bounds_in_pixel().y(); | 192 int y = primary_candidate->bounds_in_pixel().y(); |
194 for (int i = 1; i < count; ++i) { | 193 for (int i = 1; i < count; ++i) { |
195 const gfx::Display* display = display_manager->GetDisplayAt(i); | 194 const gfx::Display* display = display_manager->GetDisplayAt(i); |
196 if (display_manager->IsInternalDisplayId(display->id())) { | 195 if (display_manager->IsInternalDisplayId(display->id())) { |
197 primary_candidate = display; | 196 primary_candidate = display; |
198 break; | 197 break; |
199 } else if (display->bounds_in_pixel().y() < y) { | 198 } else if (display->bounds_in_pixel().y() < y) { |
200 primary_candidate = display; | 199 primary_candidate = display; |
201 y = display->bounds_in_pixel().y(); | 200 y = display->bounds_in_pixel().y(); |
202 } | 201 } |
203 } | 202 } |
204 } | 203 } |
205 #endif | 204 #endif |
206 *primary_display = *primary_candidate; | 205 primary_display_id = primary_candidate->id(); |
207 aura::RootWindow* root = AddRootWindowForDisplay(*primary_display); | 206 aura::RootWindow* root = AddRootWindowForDisplay(*primary_candidate); |
208 root->SetHostBounds(primary_display->bounds_in_pixel()); | 207 root->SetHostBounds(primary_candidate->bounds_in_pixel()); |
209 UpdateDisplayBoundsForLayout(); | 208 UpdateDisplayBoundsForLayout(); |
210 } | 209 } |
211 | 210 |
212 void DisplayController::InitSecondaryDisplays() { | 211 void DisplayController::InitSecondaryDisplays() { |
213 internal::MultiDisplayManager* display_manager = GetDisplayManager(); | 212 internal::MultiDisplayManager* display_manager = GetDisplayManager(); |
214 for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) { | 213 for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) { |
215 const gfx::Display* display = display_manager->GetDisplayAt(i); | 214 const gfx::Display* display = display_manager->GetDisplayAt(i); |
216 if (primary_display->id() != display->id()) { | 215 if (primary_display_id != display->id()) { |
217 aura::RootWindow* root = AddRootWindowForDisplay(*display); | 216 aura::RootWindow* root = AddRootWindowForDisplay(*display); |
218 Shell::GetInstance()->InitRootWindowForSecondaryDisplay(root); | 217 Shell::GetInstance()->InitRootWindowForSecondaryDisplay(root); |
219 } | 218 } |
220 } | 219 } |
221 CommandLine* command_line = CommandLine::ForCurrentProcess(); | 220 CommandLine* command_line = CommandLine::ForCurrentProcess(); |
222 if (command_line->HasSwitch(switches::kAshSecondaryDisplayLayout)) { | 221 if (command_line->HasSwitch(switches::kAshSecondaryDisplayLayout)) { |
223 std::string value = command_line->GetSwitchValueASCII( | 222 std::string value = command_line->GetSwitchValueASCII( |
224 switches::kAshSecondaryDisplayLayout); | 223 switches::kAshSecondaryDisplayLayout); |
225 char layout; | 224 char layout; |
226 int offset; | 225 int offset; |
(...skipping 15 matching lines...) Expand all Loading... |
242 void DisplayController::AddObserver(Observer* observer) { | 241 void DisplayController::AddObserver(Observer* observer) { |
243 observers_.AddObserver(observer); | 242 observers_.AddObserver(observer); |
244 } | 243 } |
245 | 244 |
246 void DisplayController::RemoveObserver(Observer* observer) { | 245 void DisplayController::RemoveObserver(Observer* observer) { |
247 observers_.RemoveObserver(observer); | 246 observers_.RemoveObserver(observer); |
248 } | 247 } |
249 | 248 |
250 aura::RootWindow* DisplayController::GetPrimaryRootWindow() { | 249 aura::RootWindow* DisplayController::GetPrimaryRootWindow() { |
251 DCHECK(!root_windows_.empty()); | 250 DCHECK(!root_windows_.empty()); |
252 return root_windows_[primary_display->id()]; | 251 return root_windows_[primary_display_id]; |
253 } | 252 } |
254 | 253 |
255 aura::RootWindow* DisplayController::GetRootWindowForDisplayId(int64 id) { | 254 aura::RootWindow* DisplayController::GetRootWindowForDisplayId(int64 id) { |
256 return root_windows_[id]; | 255 return root_windows_[id]; |
257 } | 256 } |
258 | 257 |
259 void DisplayController::CloseChildWindows() { | 258 void DisplayController::CloseChildWindows() { |
260 for (std::map<int64, aura::RootWindow*>::const_iterator it = | 259 for (std::map<int64, aura::RootWindow*>::const_iterator it = |
261 root_windows_.begin(); it != root_windows_.end(); ++it) { | 260 root_windows_.begin(); it != root_windows_.end(); ++it) { |
262 aura::RootWindow* root_window = it->second; | 261 aura::RootWindow* root_window = it->second; |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
344 DCHECK(new_primary_display.is_valid()); | 343 DCHECK(new_primary_display.is_valid()); |
345 DCHECK(display_manager->IsActiveDisplay(new_primary_display)); | 344 DCHECK(display_manager->IsActiveDisplay(new_primary_display)); |
346 | 345 |
347 if (!new_primary_display.is_valid() || | 346 if (!new_primary_display.is_valid() || |
348 !display_manager->IsActiveDisplay(new_primary_display)) { | 347 !display_manager->IsActiveDisplay(new_primary_display)) { |
349 LOG(ERROR) << "Invalid or non-existent display is requested:" | 348 LOG(ERROR) << "Invalid or non-existent display is requested:" |
350 << new_primary_display.ToString(); | 349 << new_primary_display.ToString(); |
351 return; | 350 return; |
352 } | 351 } |
353 | 352 |
354 if (primary_display->id() == new_primary_display.id() || | 353 if (primary_display_id == new_primary_display.id() || |
355 root_windows_.size() < 2) { | 354 root_windows_.size() < 2) { |
356 return; | 355 return; |
357 } | 356 } |
358 | 357 |
359 aura::RootWindow* non_primary_root = root_windows_[new_primary_display.id()]; | 358 aura::RootWindow* non_primary_root = root_windows_[new_primary_display.id()]; |
360 LOG_IF(ERROR, !non_primary_root) | 359 LOG_IF(ERROR, !non_primary_root) |
361 << "Unknown display is requested in SetPrimaryDisplay: id=" | 360 << "Unknown display is requested in SetPrimaryDisplay: id=" |
362 << new_primary_display.id(); | 361 << new_primary_display.id(); |
363 if (!non_primary_root) | 362 if (!non_primary_root) |
364 return; | 363 return; |
365 | 364 |
366 gfx::Display old_primary_display = *primary_display; | 365 gfx::Display old_primary_display = GetPrimaryDisplay(); |
367 | 366 |
368 // Swap root windows between current and new primary display. | 367 // Swap root windows between current and new primary display. |
369 aura::RootWindow* primary_root = root_windows_[primary_display->id()]; | 368 aura::RootWindow* primary_root = root_windows_[primary_display_id]; |
370 DCHECK(primary_root); | 369 DCHECK(primary_root); |
371 DCHECK_NE(primary_root, non_primary_root); | 370 DCHECK_NE(primary_root, non_primary_root); |
372 | 371 |
373 root_windows_[new_primary_display.id()] = primary_root; | 372 root_windows_[new_primary_display.id()] = primary_root; |
374 primary_root->SetProperty(internal::kDisplayIdKey, new_primary_display.id()); | 373 primary_root->SetProperty(internal::kDisplayIdKey, new_primary_display.id()); |
375 | 374 |
376 root_windows_[old_primary_display.id()] = non_primary_root; | 375 root_windows_[old_primary_display.id()] = non_primary_root; |
377 non_primary_root->SetProperty(internal::kDisplayIdKey, | 376 non_primary_root->SetProperty(internal::kDisplayIdKey, |
378 old_primary_display.id()); | 377 old_primary_display.id()); |
379 | 378 |
380 *primary_display = new_primary_display; | 379 primary_display_id = new_primary_display.id(); |
381 | 380 |
382 // Update the layout. | 381 // Update the layout. |
383 SetLayoutForDisplayName( | 382 SetLayoutForDisplayName( |
384 display_manager->GetDisplayNameFor(old_primary_display), | 383 display_manager->GetDisplayNameFor(old_primary_display), |
385 GetLayoutForDisplay(new_primary_display).Invert()); | 384 GetLayoutForDisplay(new_primary_display).Invert()); |
386 | 385 |
387 // Update the dispay manager with new display info. | 386 // Update the dispay manager with new display info. |
388 std::vector<gfx::Display> displays; | 387 std::vector<gfx::Display> displays; |
389 displays.push_back(*primary_display); | 388 displays.push_back(GetDisplayManager()->GetDisplayForId(primary_display_id)); |
390 displays.push_back(*GetSecondaryDisplay()); | 389 displays.push_back(*GetSecondaryDisplay()); |
391 GetDisplayManager()->set_force_bounds_changed(true); | 390 GetDisplayManager()->set_force_bounds_changed(true); |
392 GetDisplayManager()->OnNativeDisplaysChanged(displays); | 391 GetDisplayManager()->OnNativeDisplaysChanged(displays); |
393 GetDisplayManager()->set_force_bounds_changed(false); | 392 GetDisplayManager()->set_force_bounds_changed(false); |
394 } | 393 } |
395 | 394 |
396 gfx::Display* DisplayController::GetSecondaryDisplay() { | 395 gfx::Display* DisplayController::GetSecondaryDisplay() { |
397 internal::MultiDisplayManager* display_manager = GetDisplayManager(); | 396 internal::MultiDisplayManager* display_manager = GetDisplayManager(); |
398 CHECK_EQ(2U, display_manager->GetNumDisplays()); | 397 CHECK_EQ(2U, display_manager->GetNumDisplays()); |
399 return display_manager->GetDisplayAt(0)->id() == primary_display->id() ? | 398 return display_manager->GetDisplayAt(0)->id() == primary_display_id ? |
400 display_manager->GetDisplayAt(1) : display_manager->GetDisplayAt(0); | 399 display_manager->GetDisplayAt(1) : display_manager->GetDisplayAt(0); |
401 } | 400 } |
402 | 401 |
403 void DisplayController::OnDisplayBoundsChanged(const gfx::Display& display) { | 402 void DisplayController::OnDisplayBoundsChanged(const gfx::Display& display) { |
404 if (display.id() == primary_display->id()) | |
405 *primary_display = display; | |
406 NotifyDisplayConfigurationChanging(); | 403 NotifyDisplayConfigurationChanging(); |
407 UpdateDisplayBoundsForLayout(); | 404 UpdateDisplayBoundsForLayout(); |
408 root_windows_[display.id()]->SetHostBounds(display.bounds_in_pixel()); | 405 root_windows_[display.id()]->SetHostBounds(display.bounds_in_pixel()); |
409 } | 406 } |
410 | 407 |
411 void DisplayController::OnDisplayAdded(const gfx::Display& display) { | 408 void DisplayController::OnDisplayAdded(const gfx::Display& display) { |
412 DCHECK(!root_windows_.empty()); | 409 DCHECK(!root_windows_.empty()); |
413 NotifyDisplayConfigurationChanging(); | 410 NotifyDisplayConfigurationChanging(); |
414 aura::RootWindow* root = AddRootWindowForDisplay(display); | 411 aura::RootWindow* root = AddRootWindowForDisplay(display); |
415 Shell::GetInstance()->InitRootWindowForSecondaryDisplay(root); | 412 Shell::GetInstance()->InitRootWindowForSecondaryDisplay(root); |
416 UpdateDisplayBoundsForLayout(); | 413 UpdateDisplayBoundsForLayout(); |
417 } | 414 } |
418 | 415 |
419 void DisplayController::OnDisplayRemoved(const gfx::Display& display) { | 416 void DisplayController::OnDisplayRemoved(const gfx::Display& display) { |
420 aura::RootWindow* root_to_delete = root_windows_[display.id()]; | 417 aura::RootWindow* root_to_delete = root_windows_[display.id()]; |
421 DCHECK(root_to_delete) << display.ToString(); | 418 DCHECK(root_to_delete) << display.ToString(); |
422 NotifyDisplayConfigurationChanging(); | 419 NotifyDisplayConfigurationChanging(); |
423 | 420 |
424 // Display for root window will be deleted when the Primary RootWindow | 421 // Display for root window will be deleted when the Primary RootWindow |
425 // is deleted by the Shell. | 422 // is deleted by the Shell. |
426 root_windows_.erase(display.id()); | 423 root_windows_.erase(display.id()); |
427 | 424 |
428 // When the primary root window's display is removed, move the primary | 425 // When the primary root window's display is removed, move the primary |
429 // root to the other display. | 426 // root to the other display. |
430 if (primary_display->id() == display.id()) { | 427 if (primary_display_id == display.id()) { |
431 DCHECK_EQ(1U, root_windows_.size()); | 428 DCHECK_EQ(1U, root_windows_.size()); |
432 *primary_display = *GetSecondaryDisplay(); | 429 primary_display_id = GetSecondaryDisplay()->id(); |
433 aura::RootWindow* primary_root = root_to_delete; | 430 aura::RootWindow* primary_root = root_to_delete; |
434 | 431 |
435 // Delete the other root instead. | 432 // Delete the other root instead. |
436 root_to_delete = root_windows_[primary_display->id()]; | 433 root_to_delete = root_windows_[primary_display_id]; |
437 root_to_delete->SetProperty(internal::kDisplayIdKey, display.id()); | 434 root_to_delete->SetProperty(internal::kDisplayIdKey, display.id()); |
438 | 435 |
439 // Setup primary root. | 436 // Setup primary root. |
440 root_windows_[primary_display->id()] = primary_root; | 437 root_windows_[primary_display_id] = primary_root; |
441 primary_root->SetProperty(internal::kDisplayIdKey, primary_display->id()); | 438 primary_root->SetProperty(internal::kDisplayIdKey, primary_display_id); |
442 | 439 |
443 OnDisplayBoundsChanged(*primary_display); | 440 OnDisplayBoundsChanged( |
| 441 GetDisplayManager()->GetDisplayForId(primary_display_id)); |
444 } | 442 } |
445 internal::RootWindowController* controller = | 443 internal::RootWindowController* controller = |
446 GetRootWindowController(root_to_delete); | 444 GetRootWindowController(root_to_delete); |
447 DCHECK(controller); | 445 DCHECK(controller); |
448 controller->MoveWindowsTo(GetPrimaryRootWindow()); | 446 controller->MoveWindowsTo(GetPrimaryRootWindow()); |
449 // Delete most of root window related objects, but don't delete | 447 // Delete most of root window related objects, but don't delete |
450 // root window itself yet because the stak may be using it. | 448 // root window itself yet because the stak may be using it. |
451 controller->Shutdown(); | 449 controller->Shutdown(); |
452 MessageLoop::current()->DeleteSoon(FROM_HERE, controller); | 450 MessageLoop::current()->DeleteSoon(FROM_HERE, controller); |
453 } | 451 } |
(...skipping 12 matching lines...) Expand all Loading... |
466 root->ConfineCursorToWindow(); | 464 root->ConfineCursorToWindow(); |
467 #endif | 465 #endif |
468 return root; | 466 return root; |
469 } | 467 } |
470 | 468 |
471 void DisplayController::UpdateDisplayBoundsForLayout() { | 469 void DisplayController::UpdateDisplayBoundsForLayout() { |
472 if (gfx::Screen::GetNumDisplays() <= 1) | 470 if (gfx::Screen::GetNumDisplays() <= 1) |
473 return; | 471 return; |
474 | 472 |
475 DCHECK_EQ(2, gfx::Screen::GetNumDisplays()); | 473 DCHECK_EQ(2, gfx::Screen::GetNumDisplays()); |
476 const gfx::Rect& primary_bounds = primary_display->bounds(); | 474 const gfx::Rect& primary_bounds = GetPrimaryDisplay().bounds(); |
477 | 475 |
478 gfx::Display* secondary_display = GetSecondaryDisplay(); | 476 gfx::Display* secondary_display = GetSecondaryDisplay(); |
479 const gfx::Rect& secondary_bounds = secondary_display->bounds(); | 477 const gfx::Rect& secondary_bounds = secondary_display->bounds(); |
480 gfx::Point new_secondary_origin = primary_bounds.origin(); | 478 gfx::Point new_secondary_origin = primary_bounds.origin(); |
481 | 479 |
482 const DisplayLayout& layout = GetLayoutForDisplay(*secondary_display); | 480 const DisplayLayout& layout = GetLayoutForDisplay(*secondary_display); |
483 DisplayLayout::Position position = layout.position; | 481 DisplayLayout::Position position = layout.position; |
484 | 482 |
485 // Ignore the offset in case the secondary display doesn't share edges with | 483 // Ignore the offset in case the secondary display doesn't share edges with |
486 // the primary display. | 484 // the primary display. |
(...skipping 27 matching lines...) Expand all Loading... |
514 secondary_display->set_bounds( | 512 secondary_display->set_bounds( |
515 gfx::Rect(new_secondary_origin, secondary_bounds.size())); | 513 gfx::Rect(new_secondary_origin, secondary_bounds.size())); |
516 secondary_display->UpdateWorkAreaFromInsets(insets); | 514 secondary_display->UpdateWorkAreaFromInsets(insets); |
517 } | 515 } |
518 | 516 |
519 void DisplayController::NotifyDisplayConfigurationChanging() { | 517 void DisplayController::NotifyDisplayConfigurationChanging() { |
520 FOR_EACH_OBSERVER(Observer, observers_, OnDisplayConfigurationChanging()); | 518 FOR_EACH_OBSERVER(Observer, observers_, OnDisplayConfigurationChanging()); |
521 } | 519 } |
522 | 520 |
523 } // namespace ash | 521 } // namespace ash |
OLD | NEW |