display_change_observer_chromeos.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
1// Copyright 2013 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "ash/display/display_change_observer_chromeos.h" 6 7#include <algorithm> 8#include <map> 9#include <set> 10#include <vector> 11 12#include "ash/ash_switches.h" 13#include "ash/display/display_info.h" 14#include "ash/display/display_layout_store.h" 15#include "ash/display/display_manager.h" 16#include "ash/shell.h" 17#include "base/command_line.h" 18#include "base/logging.h" 19#include "grit/ash_strings.h" 20#include "ui/base/l10n/l10n_util.h" 21#include "ui/compositor/dip_util.h" 22#include "ui/display/types/chromeos/display_mode.h" 23#include "ui/display/types/chromeos/display_snapshot.h" 24#include "ui/display/util/display_util.h" 25#include "ui/gfx/display.h" 26 27namespace ash { 28 29using ui::DisplayConfigurator; 30 31namespace { 32 33// The DPI threshold to detect high density screen. 34// Higher DPI than this will use device_scale_factor=2. 35const unsigned int kHighDensityDPIThreshold = 170; 36 37// 1 inch in mm. 38const float kInchInMm = 25.4f; 39 40// Display mode list is sorted by (in descending priority): 41// * the area in pixels. 42// * refresh rate. 43struct DisplayModeSorter { 44 bool operator()(const DisplayMode& a, const DisplayMode& b) { 45 if (a.size.GetArea() == b.size.GetArea()) 46 return (a.refresh_rate > b.refresh_rate); 47 return (a.size.GetArea() > b.size.GetArea()); 48 } 49}; 50 51} // namespace 52 53// static 54std::vector<DisplayMode> DisplayChangeObserver::GetDisplayModeList( 55 const DisplayConfigurator::DisplayState& output) { 56 typedef std::map<std::pair<int, int>, DisplayMode> DisplayModeMap; 57 DisplayModeMap display_mode_map; 58 59 for (std::vector<const ui::DisplayMode*>::const_iterator it = 60 output.display->modes().begin(); 61 it != output.display->modes().end(); 62 ++it) { 63 const ui::DisplayMode& mode_info = **it; 64 const std::pair<int, int> size(mode_info.size().width(), 65 mode_info.size().height()); 66 const DisplayMode display_mode(mode_info.size(), 67 mode_info.refresh_rate(), 68 mode_info.is_interlaced(), 69 output.display->native_mode() == *it); 70 71 // Add the display mode if it isn't already present and override interlaced 72 // display modes with non-interlaced ones. 73 DisplayModeMap::iterator display_mode_it = display_mode_map.find(size); 74 if (display_mode_it == display_mode_map.end()) 75 display_mode_map.insert(std::make_pair(size, display_mode)); 76 else if (display_mode_it->second.interlaced && !display_mode.interlaced) 77 display_mode_it->second = display_mode; 78 } 79 80 std::vector<DisplayMode> display_mode_list; 81 for (DisplayModeMap::const_iterator iter = display_mode_map.begin(); 82 iter != display_mode_map.end(); 83 ++iter) { 84 display_mode_list.push_back(iter->second); 85 } 86 std::sort( 87 display_mode_list.begin(), display_mode_list.end(), DisplayModeSorter()); 88 return display_mode_list; 89} 90 91DisplayChangeObserver::DisplayChangeObserver() { 92 Shell::GetInstance()->AddShellObserver(this); 93} 94 95DisplayChangeObserver::~DisplayChangeObserver() { 96 Shell::GetInstance()->RemoveShellObserver(this); 97} 98 99ui::MultipleDisplayState DisplayChangeObserver::GetStateForDisplayIds( 100 const std::vector<int64>& display_ids) const { 101 CHECK_EQ(2U, display_ids.size()); 102 DisplayIdPair pair = std::make_pair(display_ids[0], display_ids[1]); 103 DisplayLayout layout = Shell::GetInstance()->display_manager()-> 104 layout_store()->GetRegisteredDisplayLayout(pair); 105 return layout.mirrored ? ui::MULTIPLE_DISPLAY_STATE_DUAL_MIRROR : 106 ui::MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED; 107} 108 109bool DisplayChangeObserver::GetResolutionForDisplayId(int64 display_id, 110 gfx::Size* size) const { 111 DisplayMode mode; 112 if (!Shell::GetInstance()->display_manager()->GetSelectedModeForDisplayId( 113 display_id, &mode)) 114 return false; 115 116 *size = mode.size; 117 return true; 118} 119 120void DisplayChangeObserver::OnDisplayModeChanged( 121 const std::vector<DisplayConfigurator::DisplayState>& display_states) { 122 std::vector<DisplayInfo> displays; 123 std::set<int64> ids; 124 for (size_t i = 0; i < display_states.size(); ++i) { 125 const DisplayConfigurator::DisplayState& state = display_states[i]; 126 127 if (state.display->type() == ui::DISPLAY_CONNECTION_TYPE_INTERNAL && 128 gfx::Display::InternalDisplayId() == gfx::Display::kInvalidDisplayID) { 129 gfx::Display::SetInternalDisplayId(state.display->display_id()); 130 } 131 132 const ui::DisplayMode* mode_info = state.display->current_mode(); 133 if (!mode_info) 134 continue; 135 136 float device_scale_factor = 1.0f; 137 if (!ui::IsDisplaySizeBlackListed(state.display->physical_size()) && 138 (kInchInMm * mode_info->size().width() / 139 state.display->physical_size().width()) > kHighDensityDPIThreshold) { 140 device_scale_factor = 2.0f; 141 } 142 gfx::Rect display_bounds(state.display->origin(), mode_info->size()); 143 144 std::vector<DisplayMode> display_modes = GetDisplayModeList(state); 145 146 std::string name = 147 state.display->type() == ui::DISPLAY_CONNECTION_TYPE_INTERNAL ? 148 l10n_util::GetStringUTF8(IDS_ASH_INTERNAL_DISPLAY_NAME) : 149 state.display->display_name(); 150 if (name.empty()) 151 name = l10n_util::GetStringUTF8(IDS_ASH_STATUS_TRAY_UNKNOWN_DISPLAY_NAME); 152 153 bool has_overscan = state.display->has_overscan(); 154 int64 id = state.display->display_id(); 155 ids.insert(id); 156 157 displays.push_back(DisplayInfo(id, name, has_overscan)); 158 DisplayInfo& new_info = displays.back(); 159 new_info.set_device_scale_factor(device_scale_factor); 160 new_info.SetBounds(display_bounds); 161 new_info.set_native(true); 162 new_info.set_display_modes(display_modes); 163 new_info.set_touch_support(state.touch_device_id == 0 ? 164 gfx::Display::TOUCH_SUPPORT_UNAVAILABLE : 165 gfx::Display::TOUCH_SUPPORT_AVAILABLE); 166 new_info.set_touch_device_id(state.touch_device_id); 167 new_info.set_available_color_profiles( 168 Shell::GetInstance() 169 ->display_configurator() 170 ->GetAvailableColorCalibrationProfiles(id)); 171 } 172 173 // DisplayManager can be null during the boot. 174 Shell::GetInstance()->display_manager()->OnNativeDisplaysChanged(displays); 175} 176 177void DisplayChangeObserver::OnAppTerminating() { 178#if defined(USE_ASH) 179 // Stop handling display configuration events once the shutdown 180 // process starts. crbug.com/177014. 181 Shell::GetInstance()->display_configurator()->PrepareForExit(); 182#endif 183} 184 185} // namespace ash 186