Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / ash / display / display_change_observer_chromeos.cc
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
27 namespace ash {
28
29 using ui::DisplayConfigurator;
30
31 namespace {
32
33 // Display mode list is sorted by (in descending priority):
34 //  * the area in pixels.
35 //  * refresh rate.
36 struct 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
47 std::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
84 DisplayChangeObserver::DisplayChangeObserver() {
85   Shell::GetInstance()->AddShellObserver(this);
86 }
87
88 DisplayChangeObserver::~DisplayChangeObserver() {
89   Shell::GetInstance()->RemoveShellObserver(this);
90 }
91
92 ui::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
102 bool 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
113 void 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
165 void 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