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

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

Issue 13466022: Don't move cursor location when rotation /ui scaling has changed (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: add explicit bootstrap flag as display_controller is no longer NULL during bootstrap Created 7 years, 8 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
« no previous file with comments | « ash/display/display_manager.h ('k') | ash/display/display_manager_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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_manager.h" 5 #include "ash/display/display_manager.h"
6 6
7 #include <set> 7 #include <set>
8 #include <string> 8 #include <string>
9 #include <vector> 9 #include <vector>
10 10
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after
351 new_display_info_list.end(), 351 new_display_info_list.end(),
352 DisplayInfoSortFunctor()); 352 DisplayInfoSortFunctor());
353 DisplayList removed_displays; 353 DisplayList removed_displays;
354 std::vector<size_t> changed_display_indices; 354 std::vector<size_t> changed_display_indices;
355 std::vector<size_t> added_display_indices; 355 std::vector<size_t> added_display_indices;
356 356
357 DisplayList::iterator curr_iter = displays_.begin(); 357 DisplayList::iterator curr_iter = displays_.begin();
358 DisplayInfoList::const_iterator new_info_iter = new_display_info_list.begin(); 358 DisplayInfoList::const_iterator new_info_iter = new_display_info_list.begin();
359 359
360 DisplayList new_displays; 360 DisplayList new_displays;
361 bool update_mouse_location = false;
362
361 while (curr_iter != displays_.end() || 363 while (curr_iter != displays_.end() ||
362 new_info_iter != new_display_info_list.end()) { 364 new_info_iter != new_display_info_list.end()) {
363 if (curr_iter == displays_.end()) { 365 if (curr_iter == displays_.end()) {
364 // more displays in new list. 366 // more displays in new list.
365 added_display_indices.push_back(new_displays.size()); 367 added_display_indices.push_back(new_displays.size());
366 InsertAndUpdateDisplayInfo(*new_info_iter); 368 InsertAndUpdateDisplayInfo(*new_info_iter);
367 new_displays.push_back( 369 new_displays.push_back(
368 CreateDisplayFromDisplayInfoById(new_info_iter->id())); 370 CreateDisplayFromDisplayInfoById(new_info_iter->id()));
369 ++new_info_iter; 371 ++new_info_iter;
370 } else if (new_info_iter == new_display_info_list.end()) { 372 } else if (new_info_iter == new_display_info_list.end()) {
371 // more displays in current list. 373 // more displays in current list.
372 removed_displays.push_back(*curr_iter); 374 removed_displays.push_back(*curr_iter);
373 ++curr_iter; 375 ++curr_iter;
376 update_mouse_location = true;
374 } else if (curr_iter->id() == new_info_iter->id()) { 377 } else if (curr_iter->id() == new_info_iter->id()) {
375 const gfx::Display& current_display = *curr_iter; 378 const gfx::Display& current_display = *curr_iter;
376 // Copy the info because |CreateDisplayFromInfo| updates the instance. 379 // Copy the info because |CreateDisplayFromInfo| updates the instance.
377 const DisplayInfo current_display_info = 380 const DisplayInfo current_display_info =
378 GetDisplayInfo(current_display.id()); 381 GetDisplayInfo(current_display.id());
379 InsertAndUpdateDisplayInfo(*new_info_iter); 382 InsertAndUpdateDisplayInfo(*new_info_iter);
380 gfx::Display new_display = 383 gfx::Display new_display =
381 CreateDisplayFromDisplayInfoById(new_info_iter->id()); 384 CreateDisplayFromDisplayInfoById(new_info_iter->id());
382 const DisplayInfo& new_display_info = GetDisplayInfo(new_display.id()); 385 const DisplayInfo& new_display_info = GetDisplayInfo(new_display.id());
386
387 bool host_window_bounds_changed =
388 current_display_info.bounds_in_pixel() !=
389 new_display_info.bounds_in_pixel();
390
383 // TODO(oshima): Rotating square dislay doesn't work as the size 391 // TODO(oshima): Rotating square dislay doesn't work as the size
384 // won't change. This doesn't cause a problem now as there is no 392 // won't change. This doesn't cause a problem now as there is no
385 // such display. This will be fixed by comparing the rotation as 393 // such display. This will be fixed by comparing the rotation as
386 // well when the rotation variable is added to gfx::Display. 394 // well when the rotation variable is added to gfx::Display.
387 if (force_bounds_changed_ || 395 if (force_bounds_changed_ ||
388 (current_display_info.bounds_in_pixel() != 396 host_window_bounds_changed ||
389 new_display_info.bounds_in_pixel()) ||
390 (current_display.device_scale_factor() != 397 (current_display.device_scale_factor() !=
391 new_display.device_scale_factor()) || 398 new_display.device_scale_factor()) ||
392 (current_display_info.size_in_pixel() != 399 (current_display_info.size_in_pixel() !=
393 new_display.GetSizeInPixel())) { 400 new_display.GetSizeInPixel())) {
401
402 // Don't update mouse location if the display size has
403 // changed due to rotation or zooming.
404 if (host_window_bounds_changed)
405 update_mouse_location = true;
406
394 changed_display_indices.push_back(new_displays.size()); 407 changed_display_indices.push_back(new_displays.size());
395 } 408 }
396 409
397 new_display.UpdateWorkAreaFromInsets(current_display.GetWorkAreaInsets()); 410 new_display.UpdateWorkAreaFromInsets(current_display.GetWorkAreaInsets());
398 new_displays.push_back(new_display); 411 new_displays.push_back(new_display);
399 ++curr_iter; 412 ++curr_iter;
400 ++new_info_iter; 413 ++new_info_iter;
401 } else if (curr_iter->id() < new_info_iter->id()) { 414 } else if (curr_iter->id() < new_info_iter->id()) {
402 // more displays in current list between ids, which means it is deleted. 415 // more displays in current list between ids, which means it is deleted.
403 removed_displays.push_back(*curr_iter); 416 removed_displays.push_back(*curr_iter);
404 ++curr_iter; 417 ++curr_iter;
418 update_mouse_location = true;
405 } else { 419 } else {
406 // more displays in new list between ids, which means it is added. 420 // more displays in new list between ids, which means it is added.
407 added_display_indices.push_back(new_displays.size()); 421 added_display_indices.push_back(new_displays.size());
408 InsertAndUpdateDisplayInfo(*new_info_iter); 422 InsertAndUpdateDisplayInfo(*new_info_iter);
409 new_displays.push_back( 423 new_displays.push_back(
410 CreateDisplayFromDisplayInfoById(new_info_iter->id())); 424 CreateDisplayFromDisplayInfoById(new_info_iter->id()));
411 ++new_info_iter; 425 ++new_info_iter;
412 } 426 }
413 } 427 }
414 428
415 // Do not update |displays_| if there's nothing to be updated. Without this, 429 // Do not update |displays_| if there's nothing to be updated. Without this,
416 // it will not update the display layout, which causes the bug 430 // it will not update the display layout, which causes the bug
417 // http://crbug.com/155948. 431 // http://crbug.com/155948.
418 if (changed_display_indices.empty() && added_display_indices.empty() && 432 if (changed_display_indices.empty() && added_display_indices.empty() &&
419 removed_displays.empty()) { 433 removed_displays.empty()) {
420 return; 434 return;
421 } 435 }
422 436
437 DisplayController* display_controller =
438 Shell::GetInstance()->display_controller();
439 gfx::Point mouse_location_in_native;
440 display_controller->NotifyDisplayConfigurationChanging();
441 mouse_location_in_native = display_controller->GetNativeMouseCursorLocation();
442
423 displays_ = new_displays; 443 displays_ = new_displays;
424 444
425 base::AutoReset<bool> resetter(&change_display_upon_host_resize_, false); 445 base::AutoReset<bool> resetter(&change_display_upon_host_resize_, false);
426 446
427 // Temporarily add displays to be removed because display object 447 // Temporarily add displays to be removed because display object
428 // being removed are accessed during shutting down the root. 448 // being removed are accessed during shutting down the root.
429 displays_.insert(displays_.end(), removed_displays.begin(), 449 displays_.insert(displays_.end(), removed_displays.begin(),
430 removed_displays.end()); 450 removed_displays.end());
431 DisplayController* display_controller =
432 Shell::GetInstance()->display_controller();
433 // |display_controller| is NULL during the bootstrap.
434 if (display_controller)
435 display_controller->NotifyDisplayConfigurationChanging();
436 451
437 for (DisplayList::const_reverse_iterator iter = removed_displays.rbegin(); 452 for (DisplayList::const_reverse_iterator iter = removed_displays.rbegin();
438 iter != removed_displays.rend(); ++iter) { 453 iter != removed_displays.rend(); ++iter) {
439 Shell::GetInstance()->screen()->NotifyDisplayRemoved(displays_.back()); 454 Shell::GetInstance()->screen()->NotifyDisplayRemoved(displays_.back());
440 displays_.pop_back(); 455 displays_.pop_back();
441 } 456 }
442 for (std::vector<size_t>::iterator iter = added_display_indices.begin(); 457 for (std::vector<size_t>::iterator iter = added_display_indices.begin();
443 iter != added_display_indices.end(); ++iter) { 458 iter != added_display_indices.end(); ++iter) {
444 Shell::GetInstance()->screen()->NotifyDisplayAdded(displays_[*iter]); 459 Shell::GetInstance()->screen()->NotifyDisplayAdded(displays_[*iter]);
445 } 460 }
446 for (std::vector<size_t>::iterator iter = changed_display_indices.begin(); 461 for (std::vector<size_t>::iterator iter = changed_display_indices.begin();
447 iter != changed_display_indices.end(); ++iter) { 462 iter != changed_display_indices.end(); ++iter) {
448 Shell::GetInstance()->screen()->NotifyBoundsChanged(displays_[*iter]); 463 Shell::GetInstance()->screen()->NotifyBoundsChanged(displays_[*iter]);
449 } 464 }
450 if (display_controller) 465 display_controller->NotifyDisplayConfigurationChanged();
451 display_controller->NotifyDisplayConfigurationChanged(); 466 if (update_mouse_location)
467 display_controller->EnsurePointerInDisplays();
468 else
469 display_controller->UpdateMouseCursor(mouse_location_in_native);
452 470
453 EnsurePointerInDisplays();
454 #if defined(USE_X11) && defined(OS_CHROMEOS) 471 #if defined(USE_X11) && defined(OS_CHROMEOS)
455 if (!changed_display_indices.empty() && base::chromeos::IsRunningOnChromeOS()) 472 if (!changed_display_indices.empty() && base::chromeos::IsRunningOnChromeOS())
456 ui::ClearX11DefaultRootWindow(); 473 ui::ClearX11DefaultRootWindow();
457 #endif 474 #endif
458 } 475 }
459 476
460 gfx::Display* DisplayManager::GetDisplayAt(size_t index) { 477 gfx::Display* DisplayManager::GetDisplayAt(size_t index) {
461 return index < displays_.size() ? &displays_[index] : NULL; 478 return index < displays_.size() ? &displays_[index] : NULL;
462 } 479 }
463 480
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
648 return GetInvalidDisplay(); 665 return GetInvalidDisplay();
649 } 666 }
650 667
651 void DisplayManager::AddDisplayFromSpec(const std::string& spec) { 668 void DisplayManager::AddDisplayFromSpec(const std::string& spec) {
652 DisplayInfo display_info = DisplayInfo::CreateFromSpec(spec); 669 DisplayInfo display_info = DisplayInfo::CreateFromSpec(spec);
653 InsertAndUpdateDisplayInfo(display_info); 670 InsertAndUpdateDisplayInfo(display_info);
654 gfx::Display display = CreateDisplayFromDisplayInfoById(display_info.id()); 671 gfx::Display display = CreateDisplayFromDisplayInfoById(display_info.id());
655 displays_.push_back(display); 672 displays_.push_back(display);
656 } 673 }
657 674
658 void DisplayManager::EnsurePointerInDisplays() {
659 // Don't try to move the pointer during the boot/startup.
660 if (!DisplayController::HasPrimaryDisplay())
661 return;
662 gfx::Point location_in_screen = Shell::GetScreen()->GetCursorScreenPoint();
663 gfx::Point target_location;
664 int64 closest_distance_squared = -1;
665
666 for (DisplayList::const_iterator iter = displays_.begin();
667 iter != displays_.end(); ++iter) {
668 const gfx::Rect& display_bounds = iter->bounds();
669
670 if (display_bounds.Contains(location_in_screen)) {
671 target_location = location_in_screen;
672 break;
673 }
674 gfx::Point center = display_bounds.CenterPoint();
675 // Use the distance squared from the center of the dislay. This is not
676 // exactly "closest" display, but good enough to pick one
677 // appropriate (and there are at most two displays).
678 // We don't care about actual distance, only relative to other displays, so
679 // using the LengthSquared() is cheaper than Length().
680 int64 distance_squared = (center - location_in_screen).LengthSquared();
681 if (closest_distance_squared < 0 ||
682 closest_distance_squared > distance_squared) {
683 target_location = center;
684 closest_distance_squared = distance_squared;
685 }
686 }
687
688 aura::RootWindow* root_window = Shell::GetPrimaryRootWindow();
689 aura::client::ScreenPositionClient* client =
690 aura::client::GetScreenPositionClient(root_window);
691 client->ConvertPointFromScreen(root_window, &target_location);
692
693 root_window->MoveCursorTo(target_location);
694 }
695
696 void DisplayManager::InsertAndUpdateDisplayInfo(const DisplayInfo& new_info) { 675 void DisplayManager::InsertAndUpdateDisplayInfo(const DisplayInfo& new_info) {
697 std::map<int64, DisplayInfo>::iterator info = 676 std::map<int64, DisplayInfo>::iterator info =
698 display_info_.find(new_info.id()); 677 display_info_.find(new_info.id());
699 if (info != display_info_.end()) 678 if (info != display_info_.end())
700 info->second.Copy(new_info); 679 info->second.Copy(new_info);
701 else { 680 else {
702 display_info_[new_info.id()] = new_info; 681 display_info_[new_info.id()] = new_info;
703 display_info_[new_info.id()].set_native(false); 682 display_info_[new_info.id()].set_native(false);
704 } 683 }
705 bool on_chromeos = false; 684 bool on_chromeos = false;
(...skipping 25 matching lines...) Expand all
731 // always (0,0) and the secondary display's bounds will be updated 710 // always (0,0) and the secondary display's bounds will be updated
732 // by |DisplayController::UpdateDisplayBoundsForLayout|. 711 // by |DisplayController::UpdateDisplayBoundsForLayout|.
733 new_display.SetScaleAndBounds( 712 new_display.SetScaleAndBounds(
734 display_info.device_scale_factor(), gfx::Rect(bounds_in_pixel.size())); 713 display_info.device_scale_factor(), gfx::Rect(bounds_in_pixel.size()));
735 new_display.set_rotation(display_info.rotation()); 714 new_display.set_rotation(display_info.rotation());
736 return new_display; 715 return new_display;
737 } 716 }
738 717
739 } // namespace internal 718 } // namespace internal
740 } // namespace ash 719 } // namespace ash
OLDNEW
« no previous file with comments | « ash/display/display_manager.h ('k') | ash/display/display_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698