Upstream version 5.34.104.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 "chromeos/display/output_util.h"
20 #include "grit/ash_strings.h"
21 #include "ui/base/l10n/l10n_util.h"
22 #include "ui/base/x/x11_util.h"
23 #include "ui/compositor/dip_util.h"
24 #include "ui/gfx/display.h"
25
26 namespace ash {
27 namespace internal {
28
29 using chromeos::OutputConfigurator;
30
31 namespace {
32
33 // The DPI threshold to detect high density screen.
34 // Higher DPI than this will use device_scale_factor=2.
35 const unsigned int kHighDensityDPIThreshold = 170;
36
37 // 1 inch in mm.
38 const float kInchInMm = 25.4f;
39
40 // Display mode list is sorted by (in descending priority):
41 //  * the area in pixels.
42 //  * refresh rate.
43 struct 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
54 std::vector<DisplayMode> DisplayChangeObserver::GetDisplayModeList(
55     const OutputConfigurator::OutputSnapshot& output) {
56   typedef std::map<std::pair<int, int>, DisplayMode> DisplayModeMap;
57   DisplayModeMap display_mode_map;
58
59   for (std::map<RRMode, OutputConfigurator::ModeInfo>::const_iterator it =
60        output.mode_infos.begin(); it != output.mode_infos.end(); ++it) {
61     const OutputConfigurator::ModeInfo& mode_info = it->second;
62     const std::pair<int, int> size(mode_info.width, mode_info.height);
63     const DisplayMode display_mode(gfx::Size(mode_info.width, mode_info.height),
64                                    mode_info.refresh_rate,
65                                    mode_info.interlaced,
66                                    output.native_mode == it->first);
67
68     // Add the display mode if it isn't already present and override interlaced
69     // display modes with non-interlaced ones.
70     DisplayModeMap::iterator display_mode_it = display_mode_map.find(size);
71     if (display_mode_it == display_mode_map.end())
72       display_mode_map.insert(std::make_pair(size, display_mode));
73     else if (display_mode_it->second.interlaced && !display_mode.interlaced)
74       display_mode_it->second = display_mode;
75   }
76
77   std::vector<DisplayMode> display_mode_list;
78   for (DisplayModeMap::const_iterator iter = display_mode_map.begin();
79        iter != display_mode_map.end();
80        ++iter) {
81     display_mode_list.push_back(iter->second);
82   }
83   std::sort(
84       display_mode_list.begin(), display_mode_list.end(), DisplayModeSorter());
85   return display_mode_list;
86 }
87
88 DisplayChangeObserver::DisplayChangeObserver() {
89   Shell::GetInstance()->AddShellObserver(this);
90 }
91
92 DisplayChangeObserver::~DisplayChangeObserver() {
93   Shell::GetInstance()->RemoveShellObserver(this);
94 }
95
96 ui::OutputState DisplayChangeObserver::GetStateForDisplayIds(
97     const std::vector<int64>& display_ids) const {
98   if (CommandLine::ForCurrentProcess()->HasSwitch(
99           switches::kAshForceMirrorMode)) {
100     return ui::OUTPUT_STATE_DUAL_MIRROR;
101   }
102
103   CHECK_EQ(2U, display_ids.size());
104   DisplayIdPair pair = std::make_pair(display_ids[0], display_ids[1]);
105   DisplayLayout layout = Shell::GetInstance()->display_manager()->
106       layout_store()->GetRegisteredDisplayLayout(pair);
107   return layout.mirrored ? ui::OUTPUT_STATE_DUAL_MIRROR :
108                            ui::OUTPUT_STATE_DUAL_EXTENDED;
109 }
110
111 bool DisplayChangeObserver::GetResolutionForDisplayId(int64 display_id,
112                                                       int* width,
113                                                       int* height) const {
114   DisplayMode mode;
115   if (!Shell::GetInstance()->display_manager()->GetSelectedModeForDisplayId(
116            display_id, &mode))
117     return false;
118
119   *width = mode.size.width();
120   *height = mode.size.height();
121   return true;
122 }
123
124 void DisplayChangeObserver::OnDisplayModeChanged(
125     const std::vector<OutputConfigurator::OutputSnapshot>& outputs) {
126   std::vector<DisplayInfo> displays;
127   std::set<int64> ids;
128   for (size_t i = 0; i < outputs.size(); ++i) {
129     const OutputConfigurator::OutputSnapshot& output = outputs[i];
130
131     if (output.type == ui::OUTPUT_TYPE_INTERNAL &&
132         gfx::Display::InternalDisplayId() == gfx::Display::kInvalidDisplayID) {
133       // Fall back to output index. crbug.com/180100
134       gfx::Display::SetInternalDisplayId(
135           output.display_id == gfx::Display::kInvalidDisplayID ? output.index :
136           output.display_id);
137     }
138
139     const OutputConfigurator::ModeInfo* mode_info =
140         OutputConfigurator::GetModeInfo(output, output.current_mode);
141     if (!mode_info)
142       continue;
143
144     float device_scale_factor = 1.0f;
145     if (!ui::IsXDisplaySizeBlackListed(output.width_mm, output.height_mm) &&
146         (kInchInMm * mode_info->width / output.width_mm) >
147         kHighDensityDPIThreshold) {
148       device_scale_factor = 2.0f;
149     }
150     gfx::Rect display_bounds(
151         output.x, output.y, mode_info->width, mode_info->height);
152
153     std::vector<DisplayMode> display_modes = GetDisplayModeList(output);
154
155     std::string name =
156         output.type == ui::OUTPUT_TYPE_INTERNAL
157             ? l10n_util::GetStringUTF8(IDS_ASH_INTERNAL_DISPLAY_NAME)
158             : chromeos::GetDisplayName(output.output);
159     if (name.empty())
160       name = l10n_util::GetStringUTF8(IDS_ASH_STATUS_TRAY_UNKNOWN_DISPLAY_NAME);
161
162     bool has_overscan = false;
163     chromeos::GetOutputOverscanFlag(output.output, &has_overscan);
164
165     int64 id = output.display_id;
166     if (id == gfx::Display::kInvalidDisplayID || ids.find(id) != ids.end())
167       id = output.index;
168     ids.insert(id);
169
170     displays.push_back(DisplayInfo(id, name, has_overscan));
171     displays.back().set_device_scale_factor(device_scale_factor);
172     displays.back().SetBounds(display_bounds);
173     displays.back().set_native(true);
174     displays.back().set_display_modes(display_modes);
175     displays.back().set_touch_support(
176         output.touch_device_id == 0 ? gfx::Display::TOUCH_SUPPORT_UNAVAILABLE :
177                                       gfx::Display::TOUCH_SUPPORT_AVAILABLE);
178   }
179
180   // DisplayManager can be null during the boot.
181   Shell::GetInstance()->display_manager()->OnNativeDisplaysChanged(displays);
182 }
183
184 void DisplayChangeObserver::OnAppTerminating() {
185 #if defined(USE_ASH)
186   // Stop handling display configuration events once the shutdown
187   // process starts. crbug.com/177014.
188   Shell::GetInstance()->output_configurator()->Stop();
189 #endif
190 }
191
192 }  // namespace internal
193 }  // namespace ash