display_change_observer_chromeos.cc revision a02191e04bc25c4935f804f2c080ae28663d096d
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/display_util.h" 23#include "ui/display/types/chromeos/display_mode.h" 24#include "ui/display/types/chromeos/display_snapshot.h" 25#include "ui/gfx/display.h" 26 27namespace ash { 28 29using ui::DisplayConfigurator; 30 31namespace { 32 33// Display mode list is sorted by (in descending priority): 34// * the area in pixels. 35// * refresh rate. 36struct DisplayModeSorter { 37 bool operator()(const DisplayMode& a, const DisplayMode& b) { 38 if (a.size.GetArea() == b.size.GetArea()) 39 return (a.refresh_rate > b.refresh_rate); 40 return (a.size.GetArea() > b.size.GetArea()); 41 } 42}; 43 44} // namespace 45 46// static 47std::vector<DisplayMode> DisplayChangeObserver::GetDisplayModeList( 48 const DisplayConfigurator::DisplayState& output) { 49 typedef std::map<std::pair<int, int>, DisplayMode> DisplayModeMap; 50 DisplayModeMap display_mode_map; 51 52 for (std::vector<const ui::DisplayMode*>::const_iterator it = 53 output.display->modes().begin(); 54 it != output.display->modes().end(); 55 ++it) { 56 const ui::DisplayMode& mode_info = **it; 57 const std::pair<int, int> size(mode_info.size().width(), 58 mode_info.size().height()); 59 const DisplayMode display_mode(mode_info.size(), 60 mode_info.refresh_rate(), 61 mode_info.is_interlaced(), 62 output.display->native_mode() == *it); 63 64 // Add the display mode if it isn't already present and override interlaced 65 // display modes with non-interlaced ones. 66 DisplayModeMap::iterator display_mode_it = display_mode_map.find(size); 67 if (display_mode_it == display_mode_map.end()) 68 display_mode_map.insert(std::make_pair(size, display_mode)); 69 else if (display_mode_it->second.interlaced && !display_mode.interlaced) 70 display_mode_it->second = display_mode; 71 } 72 73 std::vector<DisplayMode> display_mode_list; 74 for (DisplayModeMap::const_iterator iter = display_mode_map.begin(); 75 iter != display_mode_map.end(); 76 ++iter) { 77 display_mode_list.push_back(iter->second); 78 } 79 std::sort( 80 display_mode_list.begin(), display_mode_list.end(), DisplayModeSorter()); 81 return display_mode_list; 82} 83 84DisplayChangeObserver::DisplayChangeObserver() { 85 Shell::GetInstance()->AddShellObserver(this); 86} 87 88DisplayChangeObserver::~DisplayChangeObserver() { 89 Shell::GetInstance()->RemoveShellObserver(this); 90} 91 92ui::MultipleDisplayState DisplayChangeObserver::GetStateForDisplayIds( 93 const std::vector<int64>& display_ids) const { 94 CHECK_EQ(2U, display_ids.size()); 95 DisplayIdPair pair = std::make_pair(display_ids[0], display_ids[1]); 96 DisplayLayout layout = Shell::GetInstance()->display_manager()-> 97 layout_store()->GetRegisteredDisplayLayout(pair); 98 return layout.mirrored ? ui::MULTIPLE_DISPLAY_STATE_DUAL_MIRROR : 99 ui::MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED; 100} 101 102bool DisplayChangeObserver::GetResolutionForDisplayId(int64 display_id, 103 gfx::Size* size) const { 104 DisplayMode mode; 105 if (!Shell::GetInstance()->display_manager()->GetSelectedModeForDisplayId( 106 display_id, &mode)) 107 return false; 108 109 *size = mode.size; 110 return true; 111} 112 113void DisplayChangeObserver::OnDisplayModeChanged( 114 const std::vector<DisplayConfigurator::DisplayState>& display_states) { 115 std::vector<DisplayInfo> displays; 116 std::set<int64> ids; 117 for (size_t i = 0; i < display_states.size(); ++i) { 118 const DisplayConfigurator::DisplayState& state = display_states[i]; 119 120 if (state.display->type() == ui::DISPLAY_CONNECTION_TYPE_INTERNAL && 121 gfx::Display::InternalDisplayId() == gfx::Display::kInvalidDisplayID) { 122 gfx::Display::SetInternalDisplayId(state.display->display_id()); 123 } 124 125 const ui::DisplayMode* mode_info = state.display->current_mode(); 126 if (!mode_info) 127 continue; 128 129 float device_scale_factor = ui::GetScaleFactor( 130 state.display->physical_size(), mode_info->size()); 131 gfx::Rect display_bounds(state.display->origin(), mode_info->size()); 132 133 std::vector<DisplayMode> display_modes = GetDisplayModeList(state); 134 135 std::string name = 136 state.display->type() == ui::DISPLAY_CONNECTION_TYPE_INTERNAL ? 137 l10n_util::GetStringUTF8(IDS_ASH_INTERNAL_DISPLAY_NAME) : 138 state.display->display_name(); 139 if (name.empty()) 140 name = l10n_util::GetStringUTF8(IDS_ASH_STATUS_TRAY_UNKNOWN_DISPLAY_NAME); 141 142 bool has_overscan = state.display->has_overscan(); 143 int64 id = state.display->display_id(); 144 ids.insert(id); 145 146 displays.push_back(DisplayInfo(id, name, has_overscan)); 147 DisplayInfo& new_info = displays.back(); 148 new_info.set_device_scale_factor(device_scale_factor); 149 new_info.SetBounds(display_bounds); 150 new_info.set_native(true); 151 new_info.set_display_modes(display_modes); 152 new_info.set_touch_support(state.touch_device_id == 0 ? 153 gfx::Display::TOUCH_SUPPORT_UNAVAILABLE : 154 gfx::Display::TOUCH_SUPPORT_AVAILABLE); 155 new_info.set_available_color_profiles( 156 Shell::GetInstance() 157 ->display_configurator() 158 ->GetAvailableColorCalibrationProfiles(id)); 159 } 160 161 // DisplayManager can be null during the boot. 162 Shell::GetInstance()->display_manager()->OnNativeDisplaysChanged(displays); 163} 164 165void DisplayChangeObserver::OnAppTerminating() { 166#if defined(USE_ASH) 167 // Stop handling display configuration events once the shutdown 168 // process starts. crbug.com/177014. 169 Shell::GetInstance()->display_configurator()->PrepareForExit(); 170#endif 171} 172 173} // namespace ash 174