| // Copyright 2016 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "ui/display/display_list.h" |
| |
| #include "base/memory/ptr_util.h" |
| #include "ui/display/display_observer.h" |
| |
| namespace display { |
| |
| DisplayListObserverLock::~DisplayListObserverLock() { |
| display_list_->DecrementObserverSuspendLockCount(); |
| } |
| |
| DisplayListObserverLock::DisplayListObserverLock(DisplayList* display_list) |
| : display_list_(display_list) { |
| display_list_->IncrementObserverSuspendLockCount(); |
| } |
| |
| DisplayList::DisplayList() {} |
| |
| DisplayList::~DisplayList() { |
| DCHECK_EQ(0, observer_suspend_lock_count_); |
| } |
| |
| void DisplayList::AddObserver(DisplayObserver* observer) { |
| observers_.AddObserver(observer); |
| } |
| |
| void DisplayList::RemoveObserver(DisplayObserver* observer) { |
| observers_.RemoveObserver(observer); |
| } |
| |
| DisplayList::Displays::const_iterator DisplayList::FindDisplayById( |
| int64_t id) const { |
| for (auto iter = displays_.begin(); iter != displays_.end(); ++iter) { |
| if (iter->id() == id) |
| return iter; |
| } |
| return displays_.end(); |
| } |
| |
| DisplayList::Displays::const_iterator DisplayList::GetPrimaryDisplayIterator() |
| const { |
| return primary_display_index_ == -1 |
| ? displays_.end() |
| : displays_.begin() + primary_display_index_; |
| } |
| |
| std::unique_ptr<DisplayListObserverLock> DisplayList::SuspendObserverUpdates() { |
| return base::WrapUnique(new DisplayListObserverLock(this)); |
| } |
| |
| void DisplayList::AddOrUpdateDisplay(const Display& display, Type type) { |
| if (FindDisplayById(display.id()) == displays_.end()) |
| AddDisplay(display, type); |
| else |
| UpdateDisplay(display, type); |
| } |
| |
| uint32_t DisplayList::UpdateDisplay(const Display& display) { |
| return UpdateDisplay(display, GetTypeByDisplayId(display.id())); |
| } |
| |
| uint32_t DisplayList::UpdateDisplay(const Display& display, Type type) { |
| auto iter = FindDisplayByIdInternal(display.id()); |
| DCHECK(iter != displays_.end()); |
| |
| Display* local_display = &(*iter); |
| uint32_t changed_values = 0; |
| if (type == Type::PRIMARY && |
| static_cast<int>(iter - displays_.begin()) != |
| static_cast<int>(GetPrimaryDisplayIterator() - displays_.begin())) { |
| primary_display_index_ = static_cast<int>(iter - displays_.begin()); |
| // ash::DisplayManager only notifies for the Display gaining primary, not |
| // the one losing it. |
| changed_values |= DisplayObserver::DISPLAY_METRIC_PRIMARY; |
| } |
| if (local_display->bounds() != display.bounds()) { |
| local_display->set_bounds(display.bounds()); |
| changed_values |= DisplayObserver::DISPLAY_METRIC_BOUNDS; |
| } |
| if (local_display->work_area() != display.work_area()) { |
| local_display->set_work_area(display.work_area()); |
| changed_values |= DisplayObserver::DISPLAY_METRIC_WORK_AREA; |
| } |
| if (local_display->rotation() != display.rotation()) { |
| local_display->set_rotation(display.rotation()); |
| changed_values |= DisplayObserver::DISPLAY_METRIC_ROTATION; |
| } |
| if (local_display->device_scale_factor() != display.device_scale_factor()) { |
| local_display->set_device_scale_factor(display.device_scale_factor()); |
| changed_values |= DisplayObserver::DISPLAY_METRIC_DEVICE_SCALE_FACTOR; |
| } |
| if (local_display->color_space() != display.color_space()) { |
| local_display->set_color_space(display.color_space()); |
| changed_values |= DisplayObserver::DISPLAY_METRIC_COLOR_SPACE; |
| } |
| if (should_notify_observers()) { |
| for (DisplayObserver& observer : observers_) |
| observer.OnDisplayMetricsChanged(*local_display, changed_values); |
| } |
| return changed_values; |
| } |
| |
| void DisplayList::AddDisplay(const Display& display, Type type) { |
| DCHECK(displays_.end() == FindDisplayByIdInternal(display.id())); |
| displays_.push_back(display); |
| if (type == Type::PRIMARY) |
| primary_display_index_ = static_cast<int>(displays_.size()) - 1; |
| if (should_notify_observers()) { |
| for (DisplayObserver& observer : observers_) |
| observer.OnDisplayAdded(display); |
| } |
| } |
| |
| void DisplayList::RemoveDisplay(int64_t id) { |
| auto iter = FindDisplayByIdInternal(id); |
| DCHECK(displays_.end() != iter); |
| if (primary_display_index_ == static_cast<int>(iter - displays_.begin())) { |
| // The primary display can only be removed if it is the last display. |
| // Users must choose a new primary before removing an old primary display. |
| DCHECK_EQ(1u, displays_.size()); |
| primary_display_index_ = -1; |
| } else if (primary_display_index_ > |
| static_cast<int>(iter - displays_.begin())) { |
| primary_display_index_--; |
| } |
| const Display display = *iter; |
| displays_.erase(iter); |
| if (should_notify_observers()) { |
| for (DisplayObserver& observer : observers_) |
| observer.OnDisplayRemoved(display); |
| } |
| } |
| |
| void DisplayList::IncrementObserverSuspendLockCount() { |
| observer_suspend_lock_count_++; |
| } |
| |
| void DisplayList::DecrementObserverSuspendLockCount() { |
| DCHECK_GT(observer_suspend_lock_count_, 0); |
| observer_suspend_lock_count_--; |
| } |
| |
| DisplayList::Type DisplayList::GetTypeByDisplayId(int64_t display_id) const { |
| if (primary_display_index_ == -1) |
| return Type::NOT_PRIMARY; |
| return (displays_[primary_display_index_].id() == display_id |
| ? Type::PRIMARY |
| : Type::NOT_PRIMARY); |
| } |
| |
| DisplayList::Displays::iterator DisplayList::FindDisplayByIdInternal( |
| int64_t id) { |
| for (auto iter = displays_.begin(); iter != displays_.end(); ++iter) { |
| if (iter->id() == id) |
| return iter; |
| } |
| return displays_.end(); |
| } |
| |
| } // namespace display |