Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / ash / display / display_info.cc
1 // Copyright (c) 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 <stdio.h>
6 #include <string>
7 #include <vector>
8
9 #include "ash/display/display_info.h"
10 #include "base/logging.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/string_util.h"
13 #include "base/strings/stringprintf.h"
14 #include "ui/gfx/display.h"
15 #include "ui/gfx/size_conversions.h"
16 #include "ui/gfx/size_f.h"
17
18 #if defined(OS_WIN)
19 #include "ui/aura/window_tree_host.h"
20 #include "ui/gfx/win/dpi.h"
21 #endif
22
23 namespace ash {
24 namespace internal {
25
26 DisplayMode::DisplayMode()
27     : refresh_rate(0.0f), interlaced(false), native(false) {}
28
29 DisplayMode::DisplayMode(const gfx::Size& size,
30                          float refresh_rate,
31                          bool interlaced,
32                          bool native)
33     : size(size),
34       refresh_rate(refresh_rate),
35       interlaced(interlaced),
36       native(native) {}
37
38 // satic
39 DisplayInfo DisplayInfo::CreateFromSpec(const std::string& spec) {
40   return CreateFromSpecWithID(spec, gfx::Display::kInvalidDisplayID);
41 }
42
43 // static
44 DisplayInfo DisplayInfo::CreateFromSpecWithID(const std::string& spec,
45                                               int64 id) {
46   // Default bounds for a display.
47   const int kDefaultHostWindowX = 200;
48   const int kDefaultHostWindowY = 200;
49   const int kDefaultHostWindowWidth = 1366;
50   const int kDefaultHostWindowHeight = 768;
51
52   // Use larger than max int to catch overflow early.
53   static int64 synthesized_display_id = 2200000000LL;
54
55 #if defined(OS_WIN)
56   gfx::Rect bounds_in_native(aura::WindowTreeHost::GetNativeScreenSize());
57 #else
58   gfx::Rect bounds_in_native(kDefaultHostWindowX, kDefaultHostWindowY,
59                              kDefaultHostWindowWidth, kDefaultHostWindowHeight);
60 #endif
61   std::string main_spec = spec;
62
63   float ui_scale = 1.0f;
64   std::vector<std::string> parts;
65   if (Tokenize(main_spec, "@", &parts) == 2) {
66     double scale_in_double = 0;
67     if (base::StringToDouble(parts[1], &scale_in_double))
68       ui_scale = scale_in_double;
69     main_spec = parts[0];
70   }
71
72   size_t count = Tokenize(main_spec, "/", &parts);
73   gfx::Display::Rotation rotation(gfx::Display::ROTATE_0);
74   bool has_overscan = false;
75   if (count) {
76     main_spec = parts[0];
77     if (count >= 2) {
78       std::string options = parts[1];
79       for (size_t i = 0; i < options.size(); ++i) {
80         char c = options[i];
81         switch (c) {
82           case 'o':
83             has_overscan = true;
84             break;
85           case 'r':  // rotate 90 degrees to 'right'.
86             rotation = gfx::Display::ROTATE_90;
87             break;
88           case 'u':  // 180 degrees, 'u'pside-down.
89             rotation = gfx::Display::ROTATE_180;
90             break;
91           case 'l':  // rotate 90 degrees to 'left'.
92             rotation = gfx::Display::ROTATE_270;
93             break;
94         }
95       }
96     }
97   }
98
99   int x = 0, y = 0, width, height;
100   float device_scale_factor = 1.0f;
101   if (sscanf(main_spec.c_str(), "%dx%d*%f",
102              &width, &height, &device_scale_factor) >= 2 ||
103       sscanf(main_spec.c_str(), "%d+%d-%dx%d*%f", &x, &y, &width, &height,
104              &device_scale_factor) >= 4) {
105     bounds_in_native.SetRect(x, y, width, height);
106   } else {
107 #if defined(OS_WIN)
108     if (gfx::IsHighDPIEnabled()) {
109       device_scale_factor = gfx::GetModernUIScale();
110     }
111 #endif
112   }
113
114   std::vector<DisplayMode> display_modes;
115   if (Tokenize(main_spec, "#", &parts) == 2) {
116     size_t native_mode = 0;
117     int largest_area = -1;
118     float highest_refresh_rate = -1.0f;
119     main_spec = parts[0];
120     std::string resolution_list = parts[1];
121     count = Tokenize(resolution_list, "|", &parts);
122     for (size_t i = 0; i < count; ++i) {
123       std::string resolution = parts[i];
124       int width, height;
125       float refresh_rate = 0.0f;
126       if (sscanf(resolution.c_str(),
127                  "%dx%d%%%f",
128                  &width,
129                  &height,
130                  &refresh_rate) >= 2) {
131         if (width * height >= largest_area &&
132             refresh_rate > highest_refresh_rate) {
133           // Use mode with largest area and highest refresh rate as native.
134           largest_area = width * height;
135           highest_refresh_rate = refresh_rate;
136           native_mode = i;
137         }
138         display_modes.push_back(
139             DisplayMode(gfx::Size(width, height), refresh_rate, false, false));
140       }
141     }
142     display_modes[native_mode].native = true;
143   }
144
145   if (id == gfx::Display::kInvalidDisplayID)
146     id = synthesized_display_id++;
147   DisplayInfo display_info(
148       id, base::StringPrintf("Display-%d", static_cast<int>(id)), has_overscan);
149   display_info.set_device_scale_factor(device_scale_factor);
150   display_info.set_rotation(rotation);
151   display_info.set_configured_ui_scale(ui_scale);
152   display_info.SetBounds(bounds_in_native);
153   display_info.set_display_modes(display_modes);
154
155   // To test the overscan, it creates the default 5% overscan.
156   if (has_overscan) {
157     int width = bounds_in_native.width() / device_scale_factor / 40;
158     int height = bounds_in_native.height() / device_scale_factor / 40;
159     display_info.SetOverscanInsets(gfx::Insets(height, width, height, width));
160     display_info.UpdateDisplaySize();
161   }
162
163   DVLOG(1) << "DisplayInfoFromSpec info=" << display_info.ToString()
164            << ", spec=" << spec;
165   return display_info;
166 }
167
168 DisplayInfo::DisplayInfo()
169     : id_(gfx::Display::kInvalidDisplayID),
170       has_overscan_(false),
171       rotation_(gfx::Display::ROTATE_0),
172       touch_support_(gfx::Display::TOUCH_SUPPORT_UNKNOWN),
173       device_scale_factor_(1.0f),
174       overscan_insets_in_dip_(0, 0, 0, 0),
175       configured_ui_scale_(1.0f),
176       native_(false) {
177 }
178
179 DisplayInfo::DisplayInfo(int64 id,
180                          const std::string& name,
181                          bool has_overscan)
182     : id_(id),
183       name_(name),
184       has_overscan_(has_overscan),
185       rotation_(gfx::Display::ROTATE_0),
186       touch_support_(gfx::Display::TOUCH_SUPPORT_UNKNOWN),
187       device_scale_factor_(1.0f),
188       overscan_insets_in_dip_(0, 0, 0, 0),
189       configured_ui_scale_(1.0f),
190       native_(false) {
191 }
192
193 DisplayInfo::~DisplayInfo() {
194 }
195
196 void DisplayInfo::Copy(const DisplayInfo& native_info) {
197   DCHECK(id_ == native_info.id_);
198   name_ = native_info.name_;
199   has_overscan_ = native_info.has_overscan_;
200
201   DCHECK(!native_info.bounds_in_native_.IsEmpty());
202   bounds_in_native_ = native_info.bounds_in_native_;
203   size_in_pixel_ = native_info.size_in_pixel_;
204   device_scale_factor_ = native_info.device_scale_factor_;
205   display_modes_ = native_info.display_modes_;
206   touch_support_ = native_info.touch_support_;
207
208   // Copy overscan_insets_in_dip_ if it's not empty. This is for test
209   // cases which use "/o" annotation which sets the overscan inset
210   // to native, and that overscan has to be propagated. This does not
211   // happen on the real environment.
212   if (!native_info.overscan_insets_in_dip_.empty())
213     overscan_insets_in_dip_ = native_info.overscan_insets_in_dip_;
214
215   // Rotation_ and ui_scale_ are given by preference, or unit
216   // tests. Don't copy if this native_info came from
217   // DisplayChangeObserver.
218   if (!native_info.native()) {
219     rotation_ = native_info.rotation_;
220     configured_ui_scale_ = native_info.configured_ui_scale_;
221   }
222   // Don't copy insets as it may be given by preference.  |rotation_|
223   // is treated as a native so that it can be specified in
224   // |CreateFromSpec|.
225 }
226
227 void DisplayInfo::SetBounds(const gfx::Rect& new_bounds_in_native) {
228   bounds_in_native_ = new_bounds_in_native;
229   size_in_pixel_ = new_bounds_in_native.size();
230   UpdateDisplaySize();
231 }
232
233 float DisplayInfo::GetEffectiveUIScale() const {
234   if (device_scale_factor_ == 2.0f && configured_ui_scale_ == 2.0f)
235     return 1.0f;
236   return configured_ui_scale_;
237 }
238
239 void DisplayInfo::UpdateDisplaySize() {
240   size_in_pixel_ = bounds_in_native_.size();
241   if (!overscan_insets_in_dip_.empty()) {
242     gfx::Insets insets_in_pixel =
243         overscan_insets_in_dip_.Scale(device_scale_factor_);
244     size_in_pixel_.Enlarge(-insets_in_pixel.width(), -insets_in_pixel.height());
245   } else {
246     overscan_insets_in_dip_.Set(0, 0, 0, 0);
247   }
248
249   if (rotation_ == gfx::Display::ROTATE_90 ||
250       rotation_ == gfx::Display::ROTATE_270)
251     size_in_pixel_.SetSize(size_in_pixel_.height(), size_in_pixel_.width());
252   gfx::SizeF size_f(size_in_pixel_);
253   size_f.Scale(GetEffectiveUIScale());
254   size_in_pixel_ = gfx::ToFlooredSize(size_f);
255 }
256
257 void DisplayInfo::SetOverscanInsets(const gfx::Insets& insets_in_dip) {
258   overscan_insets_in_dip_ = insets_in_dip;
259 }
260
261 gfx::Insets DisplayInfo::GetOverscanInsetsInPixel() const {
262   return overscan_insets_in_dip_.Scale(device_scale_factor_);
263 }
264
265 std::string DisplayInfo::ToString() const {
266   int rotation_degree = static_cast<int>(rotation_) * 90;
267   return base::StringPrintf(
268       "DisplayInfo[%lld] native bounds=%s, size=%s, scale=%f, "
269       "overscan=%s, rotation=%d, ui-scale=%f, touchscreen=%s",
270       static_cast<long long int>(id_),
271       bounds_in_native_.ToString().c_str(),
272       size_in_pixel_.ToString().c_str(),
273       device_scale_factor_,
274       overscan_insets_in_dip_.ToString().c_str(),
275       rotation_degree,
276       configured_ui_scale_,
277       touch_support_ == gfx::Display::TOUCH_SUPPORT_AVAILABLE
278           ? "yes"
279           : touch_support_ == gfx::Display::TOUCH_SUPPORT_UNAVAILABLE
280                 ? "no"
281                 : "unknown");
282 }
283
284 std::string DisplayInfo::ToFullString() const {
285   std::string display_modes_str;
286   std::vector<DisplayMode>::const_iterator iter = display_modes_.begin();
287   for (; iter != display_modes_.end(); ++iter) {
288     if (!display_modes_str.empty())
289       display_modes_str += ",";
290     base::StringAppendF(&display_modes_str,
291                         "(%dx%d@%f%c%s)",
292                         iter->size.width(),
293                         iter->size.height(),
294                         iter->refresh_rate,
295                         iter->interlaced ? 'I' : 'P',
296                         iter->native ? "(N)" : "");
297   }
298   return ToString() + ", display_modes==" + display_modes_str;
299 }
300
301 }  // namespace internal
302 }  // namespace ash