#include "ash/display/display_manager.h"
+#include <algorithm>
#include <cmath>
#include <set>
#include <string>
#include "ash/ash_switches.h"
#include "ash/display/display_layout_store.h"
-#include "ash/screen_ash.h"
+#include "ash/display/screen_ash.h"
+#include "ash/screen_util.h"
#include "ash/shell.h"
#include "base/auto_reset.h"
#include "base/command_line.h"
#include "base/logging.h"
+#include "base/metrics/histogram.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h"
#include "grit/ash_strings.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/display.h"
+#include "ui/gfx/display_observer.h"
+#include "ui/gfx/font_render_params.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/screen.h"
#include "ui/gfx/size_conversions.h"
#endif
#if defined(OS_CHROMEOS)
-#include "ash/display/output_configurator_animation.h"
+#include "ash/display/display_configurator_animation.h"
#include "base/sys_info.h"
-#include "chromeos/display/output_configurator.h"
#endif
#if defined(OS_WIN)
#endif
namespace ash {
-namespace internal {
typedef std::vector<gfx::Display> DisplayList;
typedef std::vector<DisplayInfo> DisplayInfoList;
namespace {
+// We need to keep this in order for unittests to tell if
+// the object in gfx::Screen::GetScreenByType is for shutdown.
+gfx::Screen* screen_for_shutdown = NULL;
+
// The number of pixels to overlap between the primary and secondary displays,
// in case that the offset value is too large.
const int kMinimumOverlapForInvalidOffset = 100;
// 800, 1024, 1280, 1440, 1600 and 1920 pixel width respectively on
// 2560 pixel width 2x density display. Please see crbug.com/233375
// for the full list of resolutions.
-const float kUIScalesFor2x[] = {0.5f, 0.625f, 0.8f, 1.0f, 1.125f, 1.25f, 1.5f};
+const float kUIScalesFor2x[] =
+ {0.5f, 0.625f, 0.8f, 1.0f, 1.125f, 1.25f, 1.5f, 2.0f};
+const float kUIScalesFor1_25x[] = {0.5f, 0.625f, 0.8f, 1.0f, 1.25f };
const float kUIScalesFor1280[] = {0.5f, 0.625f, 0.8f, 1.0f, 1.125f };
const float kUIScalesFor1366[] = {0.5f, 0.6f, 0.75f, 1.0f, 1.125f };
}
};
-struct ResolutionMatcher {
- ResolutionMatcher(const gfx::Size& size) : size(size) {}
- bool operator()(const Resolution& resolution) {
- return resolution.size == size;
+struct DisplayModeMatcher {
+ DisplayModeMatcher(const DisplayMode& target_mode)
+ : target_mode(target_mode) {}
+ bool operator()(const DisplayMode& mode) {
+ return target_mode.IsEquivalent(mode);
}
- gfx::Size size;
+ DisplayMode target_mode;
};
struct ScaleComparator {
- ScaleComparator(float s) : scale(s) {}
+ explicit ScaleComparator(float s) : scale(s) {}
bool operator()(float s) const {
const float kEpsilon = 0.0001f;
DisplayManager::DisplayManager()
: delegate_(NULL),
+ screen_ash_(new ScreenAsh),
+ screen_(screen_ash_.get()),
layout_store_(new DisplayLayoutStore),
first_display_id_(gfx::Display::kInvalidDisplayID),
num_connected_displays_(0),
force_bounds_changed_(false),
change_display_upon_host_resize_(false),
second_display_mode_(EXTENDED),
- mirrored_display_id_(gfx::Display::kInvalidDisplayID) {
+ mirrored_display_id_(gfx::Display::kInvalidDisplayID),
+ registered_internal_display_rotation_lock_(false),
+ registered_internal_display_rotation_(gfx::Display::ROTATE_0) {
+
#if defined(OS_CHROMEOS)
+ // Enable only on the device so that DisplayManagerFontTest passes.
+ if (base::SysInfo::IsRunningOnChromeOS())
+ DisplayInfo::SetUse125DSFForUIScaling(true);
+
change_display_upon_host_resize_ = !base::SysInfo::IsRunningOnChromeOS();
#endif
+ gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_ALTERNATE,
+ screen_ash_.get());
+ gfx::Screen* current_native =
+ gfx::Screen::GetScreenByType(gfx::SCREEN_TYPE_NATIVE);
+ // If there is no native, or the native was for shutdown,
+ // use ash's screen.
+ if (!current_native ||
+ current_native == screen_for_shutdown) {
+ gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE,
+ screen_ash_.get());
+ }
}
DisplayManager::~DisplayManager() {
+#if defined(OS_CHROMEOS)
+ // Reset the font params.
+ gfx::SetFontRenderParamsDeviceScaleFactor(1.0f);
+#endif
}
// static
std::vector<float> DisplayManager::GetScalesForDisplay(
const DisplayInfo& info) {
+
+#define ASSIGN_ARRAY(v, a) v.assign(a, a + arraysize(a))
+
std::vector<float> ret;
if (info.device_scale_factor() == 2.0f) {
- ret.assign(kUIScalesFor2x, kUIScalesFor2x + arraysize(kUIScalesFor2x));
+ ASSIGN_ARRAY(ret, kUIScalesFor2x);
+ return ret;
+ } else if (info.device_scale_factor() == 1.25f) {
+ ASSIGN_ARRAY(ret, kUIScalesFor1_25x);
return ret;
}
switch (info.bounds_in_native().width()) {
case 1280:
- ret.assign(kUIScalesFor1280,
- kUIScalesFor1280 + arraysize(kUIScalesFor1280));
+ ASSIGN_ARRAY(ret, kUIScalesFor1280);
break;
case 1366:
- ret.assign(kUIScalesFor1366,
- kUIScalesFor1366 + arraysize(kUIScalesFor1366));
+ ASSIGN_ARRAY(ret, kUIScalesFor1366);
break;
default:
- ret.assign(kUIScalesFor1280,
- kUIScalesFor1280 + arraysize(kUIScalesFor1280));
+ ASSIGN_ARRAY(ret, kUIScalesFor1280);
#if defined(OS_CHROMEOS)
if (base::SysInfo::IsRunningOnChromeOS())
NOTREACHED() << "Unknown resolution:" << info.ToString();
// static
float DisplayManager::GetNextUIScale(const DisplayInfo& info, bool up) {
- float scale = info.ui_scale();
+ float scale = info.configured_ui_scale();
std::vector<float> scales = GetScalesForDisplay(info);
for (size_t i = 0; i < scales.size(); ++i) {
if (ScaleComparator(scales[i])(scale)) {
for (vector<string>::const_iterator iter = parts.begin();
iter != parts.end(); ++iter) {
info_list.push_back(DisplayInfo::CreateFromSpec(*iter));
+ info_list.back().set_native(true);
}
MaybeInitInternalDisplay(info_list[0].id());
if (info_list.size() > 1 &&
void DisplayManager::InitDefaultDisplay() {
DisplayInfoList info_list;
info_list.push_back(DisplayInfo::CreateFromSpec(std::string()));
+ info_list.back().set_native(true);
MaybeInitInternalDisplay(info_list[0].id());
OnNativeDisplaysChanged(info_list);
}
+void DisplayManager::InitFontParams() {
+#if defined(OS_CHROMEOS)
+ if (!HasInternalDisplay())
+ return;
+ const DisplayInfo& display_info =
+ GetDisplayInfo(gfx::Display::InternalDisplayId());
+ gfx::SetFontRenderParamsDeviceScaleFactor(
+ display_info.GetEffectiveDeviceScaleFactor());
+#endif // OS_CHROMEOS
+}
+
// static
void DisplayManager::UpdateDisplayBoundsForLayoutById(
const DisplayLayout& layout,
DisplayIdPair DisplayManager::GetCurrentDisplayIdPair() const {
if (IsMirrored()) {
- DCHECK_LE(2u, num_connected_displays());
+ if (software_mirroring_enabled()) {
+ CHECK_EQ(2u, num_connected_displays());
+ // This comment is to make it easy to distinguish the crash
+ // between two checks.
+ CHECK_EQ(1u, displays_.size());
+ }
return std::make_pair(displays_[0].id(), mirrored_display_id_);
} else {
CHECK_GE(2u, displays_.size());
DCHECK_EQ(2U, GetNumDisplays());
if (GetNumDisplays() < 2)
return;
- const gfx::Display& primary = Shell::GetScreen()->GetPrimaryDisplay();
+ const gfx::Display& primary = screen_->GetPrimaryDisplay();
const DisplayIdPair pair = GetCurrentDisplayIdPair();
// Invert if the primary was swapped.
DisplayLayout to_set = pair.first == primary.id() ?
const DisplayLayout layout = GetCurrentDisplayLayout();
UpdateDisplayBoundsForLayoutById(
layout, primary,
- ScreenAsh::GetSecondaryDisplay().id());
+ ScreenUtil::GetSecondaryDisplay().id());
- //UpdateCurrentDisplayBoundsForLayout();
// Primary's bounds stay the same. Just notify bounds change
// on the secondary.
- Shell::GetInstance()->screen()->NotifyBoundsChanged(
- ScreenAsh::GetSecondaryDisplay());
+ screen_ash_->NotifyMetricsChanged(
+ ScreenUtil::GetSecondaryDisplay(),
+ gfx::DisplayObserver::DISPLAY_METRIC_BOUNDS |
+ gfx::DisplayObserver::DISPLAY_METRIC_WORK_AREA);
if (delegate_)
delegate_->PostDisplayConfigurationChange();
}
return;
}
+ // TODO(mukai): merge this implementation into SetDisplayMode().
DisplayInfoList display_info_list;
for (DisplayList::const_iterator iter = displays_.begin();
iter != displays_.end(); ++iter) {
DisplayInfo info = GetDisplayInfo(iter->id());
if (info.id() == display_id) {
- if (info.ui_scale() == ui_scale)
+ if (info.configured_ui_scale() == ui_scale)
return;
std::vector<float> scales = GetScalesForDisplay(info);
ScaleComparator comparator(ui_scale);
scales.end()) {
return;
}
- info.set_ui_scale(ui_scale);
+ info.set_configured_ui_scale(ui_scale);
}
display_info_list.push_back(info);
}
if (gfx::Display::InternalDisplayId() == display_id)
return;
const DisplayInfo& display_info = GetDisplayInfo(display_id);
- const std::vector<Resolution>& resolutions = display_info.resolutions();
- DCHECK_NE(0u, resolutions.size());
- std::vector<Resolution>::const_iterator iter =
- std::find_if(resolutions.begin(),
- resolutions.end(),
- ResolutionMatcher(resolution));
- if (iter == resolutions.end()) {
+ const std::vector<DisplayMode>& modes = display_info.display_modes();
+ DCHECK_NE(0u, modes.size());
+ DisplayMode target_mode;
+ target_mode.size = resolution;
+ std::vector<DisplayMode>::const_iterator iter =
+ std::find_if(modes.begin(), modes.end(), DisplayModeMatcher(target_mode));
+ if (iter == modes.end()) {
LOG(WARNING) << "Unsupported resolution was requested:"
<< resolution.ToString();
return;
- } else if (iter == resolutions.begin()) {
- // The best resolution was set, so forget it.
- resolutions_.erase(display_id);
- } else {
- resolutions_[display_id] = resolution;
}
-#if defined(OS_CHROMEOS) && defined(USE_X11)
+ display_modes_[display_id] = *iter;
+#if defined(OS_CHROMEOS)
if (base::SysInfo::IsRunningOnChromeOS())
- Shell::GetInstance()->output_configurator()->ScheduleConfigureOutputs();
+ Shell::GetInstance()->display_configurator()->OnConfigurationChanged();
+#endif
+}
+
+bool DisplayManager::SetDisplayMode(int64 display_id,
+ const DisplayMode& display_mode) {
+ if (IsInternalDisplayId(display_id)) {
+ SetDisplayUIScale(display_id, display_mode.ui_scale);
+ return false;
+ }
+
+ DisplayInfoList display_info_list;
+ bool display_property_changed = false;
+ bool resolution_changed = false;
+ for (DisplayList::const_iterator iter = displays_.begin();
+ iter != displays_.end(); ++iter) {
+ DisplayInfo info = GetDisplayInfo(iter->id());
+ if (info.id() == display_id) {
+ const std::vector<DisplayMode>& modes = info.display_modes();
+ std::vector<DisplayMode>::const_iterator iter =
+ std::find_if(modes.begin(),
+ modes.end(),
+ DisplayModeMatcher(display_mode));
+ if (iter == modes.end()) {
+ LOG(WARNING) << "Unsupported resolution was requested:"
+ << display_mode.size.ToString();
+ return false;
+ }
+ display_modes_[display_id] = *iter;
+ if (info.bounds_in_native().size() != display_mode.size)
+ resolution_changed = true;
+ if (info.device_scale_factor() != display_mode.device_scale_factor) {
+ info.set_device_scale_factor(display_mode.device_scale_factor);
+ display_property_changed = true;
+ }
+ }
+ display_info_list.push_back(info);
+ }
+ if (display_property_changed) {
+ AddMirrorDisplayInfoIfAny(&display_info_list);
+ UpdateDisplays(display_info_list);
+ }
+#if defined(OS_CHROMEOS)
+ if (resolution_changed && base::SysInfo::IsRunningOnChromeOS())
+ Shell::GetInstance()->display_configurator()->OnConfigurationChanged();
#endif
+ return resolution_changed;
}
void DisplayManager::RegisterDisplayProperty(
gfx::Display::Rotation rotation,
float ui_scale,
const gfx::Insets* overscan_insets,
- const gfx::Size& resolution_in_pixels) {
- if (display_info_.find(display_id) == display_info_.end()) {
- display_info_[display_id] =
- DisplayInfo(display_id, std::string(""), false);
- }
+ const gfx::Size& resolution_in_pixels,
+ float device_scale_factor,
+ ui::ColorCalibrationProfile color_profile) {
+ if (display_info_.find(display_id) == display_info_.end())
+ display_info_[display_id] = DisplayInfo(display_id, std::string(), false);
display_info_[display_id].set_rotation(rotation);
+ display_info_[display_id].SetColorProfile(color_profile);
// Just in case the preference file was corrupted.
+ // TODO(mukai): register |display_modes_| here as well, so the lookup for the
+ // default mode in GetActiveModeForDisplayId() gets much simpler.
if (0.5f <= ui_scale && ui_scale <= 2.0f)
- display_info_[display_id].set_ui_scale(ui_scale);
+ display_info_[display_id].set_configured_ui_scale(ui_scale);
if (overscan_insets)
display_info_[display_id].SetOverscanInsets(*overscan_insets);
- if (!resolution_in_pixels.IsEmpty())
- resolutions_[display_id] = resolution_in_pixels;
+ if (!resolution_in_pixels.IsEmpty()) {
+ DCHECK(!IsInternalDisplayId(display_id));
+ // Default refresh rate, until OnNativeDisplaysChanged() updates us with the
+ // actual display info, is 60 Hz.
+ DisplayMode mode(resolution_in_pixels, 60.0f, false, false);
+ mode.device_scale_factor = device_scale_factor;
+ display_modes_[display_id] = mode;
+ }
+}
+
+DisplayMode DisplayManager::GetActiveModeForDisplayId(int64 display_id) const {
+ DisplayMode selected_mode;
+ if (GetSelectedModeForDisplayId(display_id, &selected_mode))
+ return selected_mode;
+
+ // If 'selected' mode is empty, it should return the default mode. This means
+ // the native mode for the external display. Unfortunately this is not true
+ // for the internal display because restoring UI-scale doesn't register the
+ // restored mode to |display_mode_|, so it needs to look up the mode whose
+ // UI-scale value matches. See the TODO in RegisterDisplayProperty().
+ const DisplayInfo& info = GetDisplayInfo(display_id);
+ const std::vector<DisplayMode>& display_modes = info.display_modes();
+
+ if (IsInternalDisplayId(display_id)) {
+ for (size_t i = 0; i < display_modes.size(); ++i) {
+ if (info.configured_ui_scale() == display_modes[i].ui_scale)
+ return display_modes[i];
+ }
+ } else {
+ for (size_t i = 0; i < display_modes.size(); ++i) {
+ if (display_modes[i].native)
+ return display_modes[i];
+ }
+ }
+ return selected_mode;
+}
+
+void DisplayManager::RegisterDisplayRotationProperties(bool rotation_lock,
+ gfx::Display::Rotation rotation) {
+ if (delegate_)
+ delegate_->PreDisplayConfigurationChange(false);
+ registered_internal_display_rotation_lock_ = rotation_lock;
+ registered_internal_display_rotation_ = rotation;
+ if (delegate_)
+ delegate_->PostDisplayConfigurationChange();
}
-bool DisplayManager::GetSelectedResolutionForDisplayId(
- int64 id,
- gfx::Size* resolution_out) const {
- std::map<int64, gfx::Size>::const_iterator iter =
- resolutions_.find(id);
- if (iter == resolutions_.end())
+bool DisplayManager::GetSelectedModeForDisplayId(int64 id,
+ DisplayMode* mode_out) const {
+ std::map<int64, DisplayMode>::const_iterator iter = display_modes_.find(id);
+ if (iter == display_modes_.end())
return false;
- *resolution_out = iter->second;
+ *mode_out = iter->second;
return true;
}
it->second.overscan_insets_in_dip() : gfx::Insets();
}
+void DisplayManager::SetColorCalibrationProfile(
+ int64 display_id,
+ ui::ColorCalibrationProfile profile) {
+#if defined(OS_CHROMEOS)
+ if (!display_info_[display_id].IsColorProfileAvailable(profile))
+ return;
+
+ if (delegate_)
+ delegate_->PreDisplayConfigurationChange(false);
+ // Just sets color profile if it's not running on ChromeOS (like tests).
+ if (!base::SysInfo::IsRunningOnChromeOS() ||
+ Shell::GetInstance()->display_configurator()->SetColorCalibrationProfile(
+ display_id, profile)) {
+ display_info_[display_id].SetColorProfile(profile);
+ UMA_HISTOGRAM_ENUMERATION(
+ "ChromeOS.Display.ColorProfile", profile, ui::NUM_COLOR_PROFILES);
+ }
+ if (delegate_)
+ delegate_->PostDisplayConfigurationChange();
+#endif
+}
+
void DisplayManager::OnNativeDisplaysChanged(
const std::vector<DisplayInfo>& updated_displays) {
if (updated_displays.empty()) {
+ VLOG(1) << "OnNativeDisplaysChanged(0): # of current displays="
+ << displays_.size();
// If the device is booted without display, or chrome is started
// without --ash-host-window-bounds on linux desktop, use the
// default display.
origins.insert(origin);
new_display_info_list.push_back(*iter);
}
+
+ DisplayMode new_mode;
+ new_mode.size = iter->bounds_in_native().size();
+ new_mode.device_scale_factor = iter->device_scale_factor();
+ new_mode.ui_scale = iter->configured_ui_scale();
+ const std::vector<DisplayMode>& display_modes = iter->display_modes();
+ // This is empty the displays are initialized from InitFromCommandLine.
+ if (!display_modes.size())
+ continue;
+ std::vector<DisplayMode>::const_iterator display_modes_iter =
+ std::find_if(display_modes.begin(),
+ display_modes.end(),
+ DisplayModeMatcher(new_mode));
+ // Update the actual resolution selected as the resolution request may fail.
+ if (display_modes_iter == display_modes.end())
+ display_modes_.erase(iter->id());
+ else if (display_modes_.find(iter->id()) != display_modes_.end())
+ display_modes_[iter->id()] = *display_modes_iter;
}
if (HasInternalDisplay() &&
!internal_display_connected &&
void DisplayManager::UpdateDisplays(
const std::vector<DisplayInfo>& updated_display_info_list) {
#if defined(OS_WIN)
- if (base::win::GetVersion() >= base::win::VERSION_WIN8) {
- DCHECK_EQ(1u, updated_display_info_list.size()) <<
- "Multiple display test does not work on Win8 bots. Please "
- "skip (don't disable) the test using SupportsMultipleDisplays()";
- }
+ DCHECK_EQ(1u, updated_display_info_list.size()) <<
+ ": Multiple display test does not work on Windows bots. Please "
+ "skip (don't disable) the test using SupportsMultipleDisplays()";
#endif
DisplayInfoList new_display_info_list = updated_display_info_list;
new_display_info_list.end(),
DisplayInfoSortFunctor());
DisplayList removed_displays;
- std::vector<size_t> changed_display_indices;
+ std::map<size_t, uint32_t> display_changes;
std::vector<size_t> added_display_indices;
DisplayList::iterator curr_iter = displays_.begin();
non_desktop_display_ =
CreateDisplayFromDisplayInfoById(non_desktop_display_id);
++new_info_iter;
- // Remove existing external dispaly if it is going to be used as
+ // Remove existing external display if it is going to be used as
// non desktop.
if (curr_iter != displays_.end() &&
curr_iter->id() == non_desktop_display_id) {
CreateDisplayFromDisplayInfoById(new_info_iter->id());
const DisplayInfo& new_display_info = GetDisplayInfo(new_display.id());
- bool host_window_bounds_changed =
- current_display_info.bounds_in_native() !=
- new_display_info.bounds_in_native();
+ uint32_t metrics = gfx::DisplayObserver::DISPLAY_METRIC_NONE;
- if (force_bounds_changed_ ||
- host_window_bounds_changed ||
- (current_display.device_scale_factor() !=
- new_display.device_scale_factor()) ||
+ // At that point the new Display objects we have are not entirely updated,
+ // they are missing the translation related to the Display disposition in
+ // the layout.
+ // Using display.bounds() and display.work_area() would fail most of the
+ // time.
+ if (force_bounds_changed_ || (current_display_info.bounds_in_native() !=
+ new_display_info.bounds_in_native()) ||
(current_display_info.size_in_pixel() !=
- new_display.GetSizeInPixel()) ||
- (current_display.rotation() != new_display.rotation())) {
+ new_display.GetSizeInPixel())) {
+ metrics |= gfx::DisplayObserver::DISPLAY_METRIC_BOUNDS |
+ gfx::DisplayObserver::DISPLAY_METRIC_WORK_AREA;
+ }
+
+ if (current_display.device_scale_factor() !=
+ new_display.device_scale_factor()) {
+ metrics |= gfx::DisplayObserver::DISPLAY_METRIC_DEVICE_SCALE_FACTOR;
+ }
+
+ if (current_display.rotation() != new_display.rotation())
+ metrics |= gfx::DisplayObserver::DISPLAY_METRIC_ROTATION;
- changed_display_indices.push_back(new_displays.size());
+ if (metrics != gfx::DisplayObserver::DISPLAY_METRIC_NONE) {
+ display_changes.insert(
+ std::pair<size_t, uint32_t>(new_displays.size(), metrics));
}
new_display.UpdateWorkAreaFromInsets(current_display.GetWorkAreaInsets());
scoped_ptr<NonDesktopDisplayUpdater> non_desktop_display_updater(
new NonDesktopDisplayUpdater(this, delegate_));
+ // Clear focus if the display has been removed, but don't clear focus if
+ // the destkop has been moved from one display to another
+ // (mirror -> docked, docked -> single internal).
+ bool clear_focus =
+ !removed_displays.empty() &&
+ !(removed_displays.size() == 1 && added_display_indices.size() == 1);
+ if (delegate_)
+ delegate_->PreDisplayConfigurationChange(clear_focus);
+
// Do not update |displays_| if there's nothing to be updated. Without this,
// it will not update the display layout, which causes the bug
// http://crbug.com/155948.
- if (changed_display_indices.empty() && added_display_indices.empty() &&
+ if (display_changes.empty() && added_display_indices.empty() &&
removed_displays.empty()) {
+ // When changing from software mirroring mode to sinlge display mode, it
+ // is possible there is no need to update |displays_| and we early out
+ // here. But we still want to run the PostDisplayConfigurationChange()
+ // cause there are some clients need to act on this, e.g.
+ // TouchTransformerController needs to adjust the TouchTransformer when
+ // switching from dual displays to single display.
+ if (delegate_)
+ delegate_->PostDisplayConfigurationChange();
return;
}
- if (delegate_)
- delegate_->PreDisplayConfigurationChange(!removed_displays.empty());
size_t updated_index;
if (UpdateSecondaryDisplayBoundsForLayout(&new_displays, &updated_index) &&
std::find(added_display_indices.begin(),
added_display_indices.end(),
- updated_index) == added_display_indices.end() &&
- std::find(changed_display_indices.begin(),
- changed_display_indices.end(),
- updated_index) == changed_display_indices.end()) {
- changed_display_indices.push_back(updated_index);
+ updated_index) == added_display_indices.end()) {
+ uint32_t metrics = gfx::DisplayObserver::DISPLAY_METRIC_BOUNDS |
+ gfx::DisplayObserver::DISPLAY_METRIC_WORK_AREA;
+ if (display_changes.find(updated_index) != display_changes.end())
+ metrics |= display_changes[updated_index];
+
+ display_changes[updated_index] = metrics;
}
displays_ = new_displays;
for (DisplayList::const_reverse_iterator iter = removed_displays.rbegin();
iter != removed_displays.rend(); ++iter) {
- Shell::GetInstance()->screen()->NotifyDisplayRemoved(displays_.back());
+ screen_ash_->NotifyDisplayRemoved(displays_.back());
displays_.pop_back();
}
// Close the non desktop window here to avoid creating two compositor on
non_desktop_display_updater.reset();
for (std::vector<size_t>::iterator iter = added_display_indices.begin();
iter != added_display_indices.end(); ++iter) {
- Shell::GetInstance()->screen()->NotifyDisplayAdded(displays_[*iter]);
+ screen_ash_->NotifyDisplayAdded(displays_[*iter]);
}
// Create the non destkop window after all displays are added so that
// it can mirror the display newly added. This can happen when switching
// from dock mode to software mirror mode.
non_desktop_display_updater.reset();
- for (std::vector<size_t>::iterator iter = changed_display_indices.begin();
- iter != changed_display_indices.end(); ++iter) {
- Shell::GetInstance()->screen()->NotifyBoundsChanged(displays_[*iter]);
+ for (std::map<size_t, uint32_t>::iterator iter = display_changes.begin();
+ iter != display_changes.end();
+ ++iter) {
+ screen_ash_->NotifyMetricsChanged(displays_[iter->first], iter->second);
}
if (delegate_)
delegate_->PostDisplayConfigurationChange();
#if defined(USE_X11) && defined(OS_CHROMEOS)
- if (!changed_display_indices.empty() && base::SysInfo::IsRunningOnChromeOS())
+ if (!display_changes.empty() && base::SysInfo::IsRunningOnChromeOS())
ui::ClearX11DefaultRootWindow();
#endif
}
}
const DisplayInfo& DisplayManager::GetDisplayInfo(int64 display_id) const {
+ DCHECK_NE(gfx::Display::kInvalidDisplayID, display_id);
+
std::map<int64, DisplayInfo>::const_iterator iter =
display_info_.find(display_id);
CHECK(iter != display_info_.end()) << display_id;
#if defined(OS_CHROMEOS)
if (base::SysInfo::IsRunningOnChromeOS()) {
- chromeos::OutputState new_state = mirrored ?
- chromeos::STATE_DUAL_MIRROR : chromeos::STATE_DUAL_EXTENDED;
- Shell::GetInstance()->output_configurator()->SetDisplayMode(new_state);
+ ui::MultipleDisplayState new_state =
+ mirrored ? ui::MULTIPLE_DISPLAY_STATE_DUAL_MIRROR :
+ ui::MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED;
+ Shell::GetInstance()->display_configurator()->SetDisplayMode(new_state);
return;
}
#endif
}
UpdateDisplays(display_info_list);
#if defined(OS_CHROMEOS)
- if (Shell::GetInstance()->output_configurator_animation()) {
- Shell::GetInstance()->output_configurator_animation()->
+ if (Shell::GetInstance()->display_configurator_animation()) {
+ Shell::GetInstance()->display_configurator_animation()->
StartFadeInAnimation();
}
#endif
}
num_connected_displays_ = new_display_info_list.size();
mirrored_display_id_ = gfx::Display::kInvalidDisplayID;
+ non_desktop_display_ = gfx::Display();
UpdateDisplays(new_display_info_list);
}
#if defined(OS_CHROMEOS)
void DisplayManager::SetSoftwareMirroring(bool enabled) {
- // TODO(oshima|bshe): Support external display on the system
- // that has virtual keyboard display.
- if (second_display_mode_ == VIRTUAL_KEYBOARD)
- return;
SetSecondDisplayMode(enabled ? MIRRORING : EXTENDED);
}
+
+bool DisplayManager::SoftwareMirroringEnabled() const {
+ return software_mirroring_enabled();
+}
#endif
void DisplayManager::SetSecondDisplayMode(SecondDisplayMode mode) {
return false;
gfx::Display* display = FindDisplayForId(display_id);
display->SetSize(display_info_[display_id].size_in_pixel());
- Shell::GetInstance()->screen()->NotifyBoundsChanged(*display);
+ screen_ash_->NotifyMetricsChanged(
+ *display, gfx::DisplayObserver::DISPLAY_METRIC_BOUNDS);
return true;
}
return false;
NonDesktopDisplayUpdater updater(this, delegate_);
}
+void DisplayManager::CreateScreenForShutdown() const {
+ bool native_is_ash =
+ gfx::Screen::GetScreenByType(gfx::SCREEN_TYPE_NATIVE) ==
+ screen_ash_.get();
+ delete screen_for_shutdown;
+ screen_for_shutdown = screen_ash_->CloneForShutdown();
+ gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_ALTERNATE,
+ screen_for_shutdown);
+ if (native_is_ash) {
+ gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE,
+ screen_for_shutdown);
+ }
+}
+
gfx::Display* DisplayManager::FindDisplayForId(int64 id) {
for (DisplayList::iterator iter = displays_.begin();
iter != displays_.end(); ++iter) {
void DisplayManager::InsertAndUpdateDisplayInfo(const DisplayInfo& new_info) {
std::map<int64, DisplayInfo>::iterator info =
display_info_.find(new_info.id());
- if (info != display_info_.end())
+ if (info != display_info_.end()) {
info->second.Copy(new_info);
- else {
+ } else {
display_info_[new_info.id()] = new_info;
display_info_[new_info.id()].set_native(false);
}
display_info_[new_info.id()].UpdateDisplaySize();
+
+ OnDisplayInfoUpdated(display_info_[new_info.id()]);
+}
+
+void DisplayManager::OnDisplayInfoUpdated(const DisplayInfo& display_info) {
+#if defined(OS_CHROMEOS)
+ ui::ColorCalibrationProfile color_profile = display_info.color_profile();
+ if (color_profile != ui::COLOR_PROFILE_STANDARD) {
+ Shell::GetInstance()->display_configurator()->SetColorCalibrationProfile(
+ display_info.id(), color_profile);
+ }
+#endif
}
gfx::Display DisplayManager::CreateDisplayFromDisplayInfoById(int64 id) {
gfx::Display new_display(display_info.id());
gfx::Rect bounds_in_native(display_info.size_in_pixel());
+ float device_scale_factor = display_info.GetEffectiveDeviceScaleFactor();
// Simply set the origin to (0,0). The primary display's origin is
// always (0,0) and the secondary display's bounds will be updated
// in |UpdateSecondaryDisplayBoundsForLayout| called in |UpdateDisplay|.
new_display.SetScaleAndBounds(
- display_info.device_scale_factor(), gfx::Rect(bounds_in_native.size()));
+ device_scale_factor, gfx::Rect(bounds_in_native.size()));
new_display.set_rotation(display_info.rotation());
new_display.set_touch_support(display_info.touch_support());
return new_display;
(id_at_zero == first_display_id_ ||
id_at_zero == gfx::Display::InternalDisplayId()) ?
std::make_pair(id_at_zero, displays->at(1).id()) :
- std::make_pair(displays->at(1).id(), id_at_zero) ;
+ std::make_pair(displays->at(1).id(), id_at_zero);
DisplayLayout layout =
layout_store_->ComputeDisplayLayoutForDisplayIdPair(pair);
secondary_display->UpdateWorkAreaFromInsets(insets);
}
-} // namespace internal
} // namespace ash