Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(92)

Side by Side Diff: ash/display/display_controller.cc

Issue 10952028: Fix crashers in GetPrimaryDisplay (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 15 matching lines...) Expand all
26 #include "ui/gfx/display.h" 26 #include "ui/gfx/display.h"
27 #include "ui/gfx/screen.h" 27 #include "ui/gfx/screen.h"
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
37 // accessed after Shell is deleted.
38 gfx::Display* primary_display = NULL;
39
36 // 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
37 // to change this value in case to support even larger displays. 41 // to change this value in case to support even larger displays.
38 const int kMaxValidOffset = 10000; 42 const int kMaxValidOffset = 10000;
39 43
40 // 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,
41 // in case that the offset value is too large. 45 // in case that the offset value is too large.
42 const int kMinimumOverlapForInvalidOffset = 50; 46 const int kMinimumOverlapForInvalidOffset = 50;
43 47
44 bool GetPositionFromString(const base::StringPiece& position, 48 bool GetPositionFromString(const base::StringPiece& position,
45 DisplayLayout::Position* field) { 49 DisplayLayout::Position* field) {
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
145 149
146 // static 150 // static
147 void DisplayLayout::RegisterJSONConverter( 151 void DisplayLayout::RegisterJSONConverter(
148 base::JSONValueConverter<DisplayLayout>* converter) { 152 base::JSONValueConverter<DisplayLayout>* converter) {
149 converter->RegisterCustomField<Position>( 153 converter->RegisterCustomField<Position>(
150 "position", &DisplayLayout::position, &GetPositionFromString); 154 "position", &DisplayLayout::position, &GetPositionFromString);
151 converter->RegisterIntField("offset", &DisplayLayout::offset); 155 converter->RegisterIntField("offset", &DisplayLayout::offset);
152 } 156 }
153 157
154 DisplayController::DisplayController() { 158 DisplayController::DisplayController() {
159 // Reinstantiate display to make sure that tests don't use
160 // stale display info from previous tests.
161 delete primary_display;
162 primary_display = new gfx::Display();
163
155 GetDisplayManager()->AddObserver(this); 164 GetDisplayManager()->AddObserver(this);
156 } 165 }
157 166
158 DisplayController::~DisplayController() { 167 DisplayController::~DisplayController() {
159 GetDisplayManager()->RemoveObserver(this); 168 GetDisplayManager()->RemoveObserver(this);
160 // Delete all root window controllers, which deletes root window 169 // Delete all root window controllers, which deletes root window
161 // from the last so that the primary root window gets deleted last. 170 // from the last so that the primary root window gets deleted last.
162 for (std::map<int64, aura::RootWindow*>::const_reverse_iterator it = 171 for (std::map<int64, aura::RootWindow*>::const_reverse_iterator it =
163 root_windows_.rbegin(); it != root_windows_.rend(); ++it) { 172 root_windows_.rbegin(); it != root_windows_.rend(); ++it) {
164 internal::RootWindowController* controller = 173 internal::RootWindowController* controller =
165 GetRootWindowController(it->second); 174 GetRootWindowController(it->second);
166 DCHECK(controller); 175 DCHECK(controller);
167 delete controller; 176 delete controller;
168 } 177 }
169 } 178 }
179 // static
180 const gfx::Display& DisplayController::GetPrimaryDisplay() {
181 DCHECK(primary_display);
182 return *primary_display;
183 }
170 184
171 void DisplayController::InitPrimaryDisplay() { 185 void DisplayController::InitPrimaryDisplay() {
172 const gfx::Display* primary_candidate = GetDisplayManager()->GetDisplayAt(0); 186 const gfx::Display* primary_candidate = GetDisplayManager()->GetDisplayAt(0);
173 #if defined(OS_CHROMEOS) 187 #if defined(OS_CHROMEOS)
174 if (base::chromeos::IsRunningOnChromeOS()) { 188 if (base::chromeos::IsRunningOnChromeOS()) {
175 internal::MultiDisplayManager* display_manager = GetDisplayManager(); 189 internal::MultiDisplayManager* display_manager = GetDisplayManager();
176 // On ChromeOS device, root windows are stacked vertically, and 190 // On ChromeOS device, root windows are stacked vertically, and
177 // default primary is the one on top. 191 // default primary is the one on top.
178 int count = display_manager->GetNumDisplays(); 192 int count = display_manager->GetNumDisplays();
179 int y = primary_candidate->bounds_in_pixel().y(); 193 int y = primary_candidate->bounds_in_pixel().y();
180 for (int i = 1; i < count; ++i) { 194 for (int i = 1; i < count; ++i) {
181 const gfx::Display* display = display_manager->GetDisplayAt(i); 195 const gfx::Display* display = display_manager->GetDisplayAt(i);
182 if (display_manager->IsInternalDisplayId(display->id())) { 196 if (display_manager->IsInternalDisplayId(display->id())) {
183 primary_candidate = display; 197 primary_candidate = display;
184 break; 198 break;
185 } else if (display->bounds_in_pixel().y() < y) { 199 } else if (display->bounds_in_pixel().y() < y) {
186 primary_candidate = display; 200 primary_candidate = display;
187 y = display->bounds_in_pixel().y(); 201 y = display->bounds_in_pixel().y();
188 } 202 }
189 } 203 }
190 } 204 }
191 #endif 205 #endif
192 primary_display_ = *primary_candidate; 206 *primary_display = *primary_candidate;
193 aura::RootWindow* root = AddRootWindowForDisplay(primary_display_); 207 aura::RootWindow* root = AddRootWindowForDisplay(*primary_display);
194 root->SetHostBounds(primary_display_.bounds_in_pixel()); 208 root->SetHostBounds(primary_display->bounds_in_pixel());
195 UpdateDisplayBoundsForLayout(); 209 UpdateDisplayBoundsForLayout();
196 } 210 }
197 211
198 void DisplayController::InitSecondaryDisplays() { 212 void DisplayController::InitSecondaryDisplays() {
199 internal::MultiDisplayManager* display_manager = GetDisplayManager(); 213 internal::MultiDisplayManager* display_manager = GetDisplayManager();
200 for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) { 214 for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) {
201 const gfx::Display* display = display_manager->GetDisplayAt(i); 215 const gfx::Display* display = display_manager->GetDisplayAt(i);
202 if (primary_display_.id() != display->id()) { 216 if (primary_display->id() != display->id()) {
203 aura::RootWindow* root = AddRootWindowForDisplay(*display); 217 aura::RootWindow* root = AddRootWindowForDisplay(*display);
204 Shell::GetInstance()->InitRootWindowForSecondaryDisplay(root); 218 Shell::GetInstance()->InitRootWindowForSecondaryDisplay(root);
205 } 219 }
206 } 220 }
207 CommandLine* command_line = CommandLine::ForCurrentProcess(); 221 CommandLine* command_line = CommandLine::ForCurrentProcess();
208 if (command_line->HasSwitch(switches::kAshSecondaryDisplayLayout)) { 222 if (command_line->HasSwitch(switches::kAshSecondaryDisplayLayout)) {
209 std::string value = command_line->GetSwitchValueASCII( 223 std::string value = command_line->GetSwitchValueASCII(
210 switches::kAshSecondaryDisplayLayout); 224 switches::kAshSecondaryDisplayLayout);
211 char layout; 225 char layout;
212 int offset; 226 int offset;
(...skipping 15 matching lines...) Expand all
228 void DisplayController::AddObserver(Observer* observer) { 242 void DisplayController::AddObserver(Observer* observer) {
229 observers_.AddObserver(observer); 243 observers_.AddObserver(observer);
230 } 244 }
231 245
232 void DisplayController::RemoveObserver(Observer* observer) { 246 void DisplayController::RemoveObserver(Observer* observer) {
233 observers_.RemoveObserver(observer); 247 observers_.RemoveObserver(observer);
234 } 248 }
235 249
236 aura::RootWindow* DisplayController::GetPrimaryRootWindow() { 250 aura::RootWindow* DisplayController::GetPrimaryRootWindow() {
237 DCHECK(!root_windows_.empty()); 251 DCHECK(!root_windows_.empty());
238 return root_windows_[primary_display_.id()]; 252 return root_windows_[primary_display->id()];
239 } 253 }
240 254
241 aura::RootWindow* DisplayController::GetRootWindowForDisplayId(int64 id) { 255 aura::RootWindow* DisplayController::GetRootWindowForDisplayId(int64 id) {
242 return root_windows_[id]; 256 return root_windows_[id];
243 } 257 }
244 258
245 void DisplayController::CloseChildWindows() { 259 void DisplayController::CloseChildWindows() {
246 for (std::map<int64, aura::RootWindow*>::const_iterator it = 260 for (std::map<int64, aura::RootWindow*>::const_iterator it =
247 root_windows_.begin(); it != root_windows_.end(); ++it) { 261 root_windows_.begin(); it != root_windows_.end(); ++it) {
248 aura::RootWindow* root_window = it->second; 262 aura::RootWindow* root_window = it->second;
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
330 DCHECK(new_primary_display.is_valid()); 344 DCHECK(new_primary_display.is_valid());
331 DCHECK(display_manager->IsActiveDisplay(new_primary_display)); 345 DCHECK(display_manager->IsActiveDisplay(new_primary_display));
332 346
333 if (!new_primary_display.is_valid() || 347 if (!new_primary_display.is_valid() ||
334 !display_manager->IsActiveDisplay(new_primary_display)) { 348 !display_manager->IsActiveDisplay(new_primary_display)) {
335 LOG(ERROR) << "Invalid or non-existent display is requested:" 349 LOG(ERROR) << "Invalid or non-existent display is requested:"
336 << new_primary_display.ToString(); 350 << new_primary_display.ToString();
337 return; 351 return;
338 } 352 }
339 353
340 if (primary_display_.id() == new_primary_display.id() || 354 if (primary_display->id() == new_primary_display.id() ||
341 root_windows_.size() < 2) { 355 root_windows_.size() < 2) {
342 return; 356 return;
343 } 357 }
344 358
345 aura::RootWindow* non_primary_root = root_windows_[new_primary_display.id()]; 359 aura::RootWindow* non_primary_root = root_windows_[new_primary_display.id()];
346 LOG_IF(ERROR, !non_primary_root) 360 LOG_IF(ERROR, !non_primary_root)
347 << "Unknown display is requested in SetPrimaryDisplay: id=" 361 << "Unknown display is requested in SetPrimaryDisplay: id="
348 << new_primary_display.id(); 362 << new_primary_display.id();
349 if (!non_primary_root) 363 if (!non_primary_root)
350 return; 364 return;
351 365
352 gfx::Display old_primary_display = primary_display_; 366 gfx::Display old_primary_display = *primary_display;
353 367
354 // Swap root windows between current and new primary display. 368 // Swap root windows between current and new primary display.
355 aura::RootWindow* primary_root = root_windows_[primary_display_.id()]; 369 aura::RootWindow* primary_root = root_windows_[primary_display->id()];
356 DCHECK(primary_root); 370 DCHECK(primary_root);
357 DCHECK_NE(primary_root, non_primary_root); 371 DCHECK_NE(primary_root, non_primary_root);
358 372
359 root_windows_[new_primary_display.id()] = primary_root; 373 root_windows_[new_primary_display.id()] = primary_root;
360 primary_root->SetProperty(internal::kDisplayIdKey, new_primary_display.id()); 374 primary_root->SetProperty(internal::kDisplayIdKey, new_primary_display.id());
361 375
362 root_windows_[old_primary_display.id()] = non_primary_root; 376 root_windows_[old_primary_display.id()] = non_primary_root;
363 non_primary_root->SetProperty(internal::kDisplayIdKey, 377 non_primary_root->SetProperty(internal::kDisplayIdKey,
364 old_primary_display.id()); 378 old_primary_display.id());
365 379
366 primary_display_ = new_primary_display; 380 *primary_display = new_primary_display;
367 381
368 // Update the layout. 382 // Update the layout.
369 SetLayoutForDisplayName( 383 SetLayoutForDisplayName(
370 display_manager->GetDisplayNameFor(old_primary_display), 384 display_manager->GetDisplayNameFor(old_primary_display),
371 GetLayoutForDisplay(new_primary_display).Invert()); 385 GetLayoutForDisplay(new_primary_display).Invert());
372 386
373 // Update the dispay manager with new display info. 387 // Update the dispay manager with new display info.
374 std::vector<gfx::Display> displays; 388 std::vector<gfx::Display> displays;
375 displays.push_back(primary_display_); 389 displays.push_back(*primary_display);
376 displays.push_back(*GetSecondaryDisplay()); 390 displays.push_back(*GetSecondaryDisplay());
377 GetDisplayManager()->set_force_bounds_changed(true); 391 GetDisplayManager()->set_force_bounds_changed(true);
378 GetDisplayManager()->OnNativeDisplaysChanged(displays); 392 GetDisplayManager()->OnNativeDisplaysChanged(displays);
379 GetDisplayManager()->set_force_bounds_changed(false); 393 GetDisplayManager()->set_force_bounds_changed(false);
380 } 394 }
381 395
382 gfx::Display* DisplayController::GetSecondaryDisplay() { 396 gfx::Display* DisplayController::GetSecondaryDisplay() {
383 internal::MultiDisplayManager* display_manager = GetDisplayManager(); 397 internal::MultiDisplayManager* display_manager = GetDisplayManager();
384 CHECK_EQ(2U, display_manager->GetNumDisplays()); 398 CHECK_EQ(2U, display_manager->GetNumDisplays());
385 return display_manager->GetDisplayAt(0)->id() == primary_display_.id() ? 399 return display_manager->GetDisplayAt(0)->id() == primary_display->id() ?
386 display_manager->GetDisplayAt(1) : display_manager->GetDisplayAt(0); 400 display_manager->GetDisplayAt(1) : display_manager->GetDisplayAt(0);
387 } 401 }
388 402
389 void DisplayController::OnDisplayBoundsChanged(const gfx::Display& display) { 403 void DisplayController::OnDisplayBoundsChanged(const gfx::Display& display) {
390 if (display.id() == primary_display_.id()) 404 if (display.id() == primary_display->id())
391 primary_display_ = display; 405 *primary_display = display;
392 NotifyDisplayConfigurationChanging(); 406 NotifyDisplayConfigurationChanging();
393 UpdateDisplayBoundsForLayout(); 407 UpdateDisplayBoundsForLayout();
394 root_windows_[display.id()]->SetHostBounds(display.bounds_in_pixel()); 408 root_windows_[display.id()]->SetHostBounds(display.bounds_in_pixel());
395 } 409 }
396 410
397 void DisplayController::OnDisplayAdded(const gfx::Display& display) { 411 void DisplayController::OnDisplayAdded(const gfx::Display& display) {
398 DCHECK(!root_windows_.empty()); 412 DCHECK(!root_windows_.empty());
399 NotifyDisplayConfigurationChanging(); 413 NotifyDisplayConfigurationChanging();
400 aura::RootWindow* root = AddRootWindowForDisplay(display); 414 aura::RootWindow* root = AddRootWindowForDisplay(display);
401 Shell::GetInstance()->InitRootWindowForSecondaryDisplay(root); 415 Shell::GetInstance()->InitRootWindowForSecondaryDisplay(root);
402 UpdateDisplayBoundsForLayout(); 416 UpdateDisplayBoundsForLayout();
403 } 417 }
404 418
405 void DisplayController::OnDisplayRemoved(const gfx::Display& display) { 419 void DisplayController::OnDisplayRemoved(const gfx::Display& display) {
406 aura::RootWindow* root_to_delete = root_windows_[display.id()]; 420 aura::RootWindow* root_to_delete = root_windows_[display.id()];
407 DCHECK(root_to_delete) << display.ToString(); 421 DCHECK(root_to_delete) << display.ToString();
408 NotifyDisplayConfigurationChanging(); 422 NotifyDisplayConfigurationChanging();
409 423
410 // Display for root window will be deleted when the Primary RootWindow 424 // Display for root window will be deleted when the Primary RootWindow
411 // is deleted by the Shell. 425 // is deleted by the Shell.
412 root_windows_.erase(display.id()); 426 root_windows_.erase(display.id());
413 427
414 // When the primary root window's display is removed, move the primary 428 // When the primary root window's display is removed, move the primary
415 // root to the other display. 429 // root to the other display.
416 if (primary_display_.id() == display.id()) { 430 if (primary_display->id() == display.id()) {
417 DCHECK_EQ(1U, root_windows_.size()); 431 DCHECK_EQ(1U, root_windows_.size());
418 primary_display_ = *GetSecondaryDisplay(); 432 *primary_display = *GetSecondaryDisplay();
419 aura::RootWindow* primary_root = root_to_delete; 433 aura::RootWindow* primary_root = root_to_delete;
420 434
421 // Delete the other root instead. 435 // Delete the other root instead.
422 root_to_delete = root_windows_[primary_display_.id()]; 436 root_to_delete = root_windows_[primary_display->id()];
423 root_to_delete->SetProperty(internal::kDisplayIdKey, display.id()); 437 root_to_delete->SetProperty(internal::kDisplayIdKey, display.id());
424 438
425 // Setup primary root. 439 // Setup primary root.
426 root_windows_[primary_display_.id()] = primary_root; 440 root_windows_[primary_display->id()] = primary_root;
427 primary_root->SetProperty(internal::kDisplayIdKey, primary_display_.id()); 441 primary_root->SetProperty(internal::kDisplayIdKey, primary_display->id());
428 442
429 OnDisplayBoundsChanged(primary_display_); 443 OnDisplayBoundsChanged(*primary_display);
430 } 444 }
431 internal::RootWindowController* controller = 445 internal::RootWindowController* controller =
432 GetRootWindowController(root_to_delete); 446 GetRootWindowController(root_to_delete);
433 DCHECK(controller); 447 DCHECK(controller);
434 controller->MoveWindowsTo(GetPrimaryRootWindow()); 448 controller->MoveWindowsTo(GetPrimaryRootWindow());
435 // Delete most of root window related objects, but don't delete 449 // Delete most of root window related objects, but don't delete
436 // root window itself yet because the stak may be using it. 450 // root window itself yet because the stak may be using it.
437 controller->Shutdown(); 451 controller->Shutdown();
438 MessageLoop::current()->DeleteSoon(FROM_HERE, controller); 452 MessageLoop::current()->DeleteSoon(FROM_HERE, controller);
439 } 453 }
(...skipping 12 matching lines...) Expand all
452 root->ConfineCursorToWindow(); 466 root->ConfineCursorToWindow();
453 #endif 467 #endif
454 return root; 468 return root;
455 } 469 }
456 470
457 void DisplayController::UpdateDisplayBoundsForLayout() { 471 void DisplayController::UpdateDisplayBoundsForLayout() {
458 if (gfx::Screen::GetNumDisplays() <= 1) 472 if (gfx::Screen::GetNumDisplays() <= 1)
459 return; 473 return;
460 474
461 DCHECK_EQ(2, gfx::Screen::GetNumDisplays()); 475 DCHECK_EQ(2, gfx::Screen::GetNumDisplays());
462 const gfx::Rect& primary_bounds = primary_display_.bounds(); 476 const gfx::Rect& primary_bounds = primary_display->bounds();
463 477
464 gfx::Display* secondary_display = GetSecondaryDisplay(); 478 gfx::Display* secondary_display = GetSecondaryDisplay();
465 const gfx::Rect& secondary_bounds = secondary_display->bounds(); 479 const gfx::Rect& secondary_bounds = secondary_display->bounds();
466 gfx::Point new_secondary_origin = primary_bounds.origin(); 480 gfx::Point new_secondary_origin = primary_bounds.origin();
467 481
468 const DisplayLayout& layout = GetLayoutForDisplay(*secondary_display); 482 const DisplayLayout& layout = GetLayoutForDisplay(*secondary_display);
469 DisplayLayout::Position position = layout.position; 483 DisplayLayout::Position position = layout.position;
470 484
471 // Ignore the offset in case the secondary display doesn't share edges with 485 // Ignore the offset in case the secondary display doesn't share edges with
472 // the primary display. 486 // the primary display.
(...skipping 27 matching lines...) Expand all
500 secondary_display->set_bounds( 514 secondary_display->set_bounds(
501 gfx::Rect(new_secondary_origin, secondary_bounds.size())); 515 gfx::Rect(new_secondary_origin, secondary_bounds.size()));
502 secondary_display->UpdateWorkAreaFromInsets(insets); 516 secondary_display->UpdateWorkAreaFromInsets(insets);
503 } 517 }
504 518
505 void DisplayController::NotifyDisplayConfigurationChanging() { 519 void DisplayController::NotifyDisplayConfigurationChanging() {
506 FOR_EACH_OBSERVER(Observer, observers_, OnDisplayConfigurationChanging()); 520 FOR_EACH_OBSERVER(Observer, observers_, OnDisplayConfigurationChanging());
507 } 521 }
508 522
509 } // namespace ash 523 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698