Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / ash / display / display_util.cc
blob12373e84e3857fc64bd4cc137a00d59980f0b481
1 // Copyright 2014 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.
5 #include "ash/display/display_util.h"
7 #include <algorithm>
9 #include "ash/display/display_info.h"
10 #include "ash/display/display_manager.h"
11 #include "ash/host/ash_window_tree_host.h"
12 #include "ash/shell.h"
13 #include "ui/aura/env.h"
14 #include "ui/aura/window_tree_host.h"
15 #include "ui/gfx/geometry/point.h"
16 #include "ui/gfx/geometry/rect.h"
17 #include "ui/wm/core/coordinate_conversion.h"
19 #if defined(OS_CHROMEOS)
20 #include "base/sys_info.h"
21 #endif
23 namespace ash {
24 namespace {
26 // List of value UI Scale values. Scales for 2x are equivalent to 640,
27 // 800, 1024, 1280, 1440, 1600 and 1920 pixel width respectively on
28 // 2560 pixel width 2x density display. Please see crbug.com/233375
29 // for the full list of resolutions.
30 const float kUIScalesFor2x[] =
31 {0.5f, 0.625f, 0.8f, 1.0f, 1.125f, 1.25f, 1.5f, 2.0f};
32 const float kUIScalesFor1_25x[] = {0.5f, 0.625f, 0.8f, 1.0f, 1.25f };
33 const float kUIScalesFor1280[] = {0.5f, 0.625f, 0.8f, 1.0f, 1.125f };
34 const float kUIScalesFor1366[] = {0.5f, 0.6f, 0.75f, 1.0f, 1.125f };
36 std::vector<float> GetScalesForDisplay(const DisplayMode& native_mode) {
37 #define ASSIGN_ARRAY(v, a) v.assign(a, a + arraysize(a))
39 std::vector<float> ret;
40 if (native_mode.device_scale_factor == 2.0f) {
41 ASSIGN_ARRAY(ret, kUIScalesFor2x);
42 return ret;
43 } else if (native_mode.device_scale_factor == 1.25f) {
44 ASSIGN_ARRAY(ret, kUIScalesFor1_25x);
45 return ret;
47 switch (native_mode.size.width()) {
48 case 1280:
49 ASSIGN_ARRAY(ret, kUIScalesFor1280);
50 break;
51 case 1366:
52 ASSIGN_ARRAY(ret, kUIScalesFor1366);
53 break;
54 default:
55 ASSIGN_ARRAY(ret, kUIScalesFor1280);
56 #if defined(OS_CHROMEOS)
57 if (base::SysInfo::IsRunningOnChromeOS())
58 NOTREACHED() << "Unknown resolution:" << native_mode.size.ToString();
59 #endif
61 return ret;
64 struct ScaleComparator {
65 explicit ScaleComparator(float s) : scale(s) {}
67 bool operator()(const DisplayMode& mode) const {
68 const float kEpsilon = 0.0001f;
69 return std::abs(scale - mode.ui_scale) < kEpsilon;
71 float scale;
74 void ConvertPointFromScreenToNative(aura::WindowTreeHost* host,
75 gfx::Point* point) {
76 ::wm::ConvertPointFromScreen(host->window(), point);
77 host->ConvertPointToNativeScreen(point);
80 } // namespace
82 std::vector<DisplayMode> CreateInternalDisplayModeList(
83 const DisplayMode& native_mode) {
84 std::vector<DisplayMode> display_mode_list;
86 float native_ui_scale = (native_mode.device_scale_factor == 1.25f)
87 ? 1.0f
88 : native_mode.device_scale_factor;
89 for (float ui_scale : GetScalesForDisplay(native_mode)) {
90 DisplayMode mode = native_mode;
91 mode.ui_scale = ui_scale;
92 mode.native = (ui_scale == native_ui_scale);
93 display_mode_list.push_back(mode);
95 return display_mode_list;
98 std::vector<DisplayMode> CreateUnifiedDisplayModeList(
99 const DisplayMode& native_mode,
100 const std::set<float>& scales) {
101 std::vector<DisplayMode> display_mode_list;
103 float native_ui_scale = native_mode.device_scale_factor;
104 for (float ui_scale : scales) {
105 DisplayMode mode = native_mode;
106 mode.ui_scale = ui_scale;
107 mode.native = (ui_scale == native_ui_scale);
108 display_mode_list.push_back(mode);
110 return display_mode_list;
113 // static
114 float GetNextUIScale(const DisplayInfo& info, bool up) {
115 ScaleComparator comparator(info.configured_ui_scale());
116 const std::vector<DisplayMode>& modes = info.display_modes();
117 for (auto iter = modes.begin(); iter != modes.end(); ++iter) {
118 if (comparator(*iter)) {
119 if (up && (iter + 1) != modes.end())
120 return (iter + 1)->ui_scale;
121 if (!up && iter != modes.begin())
122 return (iter - 1)->ui_scale;
123 return info.configured_ui_scale();
126 // Fallback to 1.0f if the |scale| wasn't in the list.
127 return 1.0f;
130 bool HasDisplayModeForUIScale(const DisplayInfo& info, float ui_scale) {
131 ScaleComparator comparator(ui_scale);
132 const std::vector<DisplayMode>& modes = info.display_modes();
133 return std::find_if(modes.begin(), modes.end(), comparator) != modes.end();
136 void ComputeBoundary(const gfx::Display& primary_display,
137 const gfx::Display& secondary_display,
138 DisplayLayout::Position position,
139 gfx::Rect* primary_edge_in_screen,
140 gfx::Rect* secondary_edge_in_screen) {
141 const gfx::Rect& primary = primary_display.bounds();
142 const gfx::Rect& secondary = secondary_display.bounds();
143 switch (position) {
144 case DisplayLayout::TOP:
145 case DisplayLayout::BOTTOM: {
146 int left = std::max(primary.x(), secondary.x());
147 int right = std::min(primary.right(), secondary.right());
148 if (position == DisplayLayout::TOP) {
149 primary_edge_in_screen->SetRect(left, primary.y(), right - left, 1);
150 secondary_edge_in_screen->SetRect(left, secondary.bottom() - 1,
151 right - left, 1);
152 } else {
153 primary_edge_in_screen->SetRect(left, primary.bottom() - 1,
154 right - left, 1);
155 secondary_edge_in_screen->SetRect(left, secondary.y(), right - left, 1);
157 break;
159 case DisplayLayout::LEFT:
160 case DisplayLayout::RIGHT: {
161 int top = std::max(primary.y(), secondary.y());
162 int bottom = std::min(primary.bottom(), secondary.bottom());
163 if (position == DisplayLayout::LEFT) {
164 primary_edge_in_screen->SetRect(primary.x(), top, 1, bottom - top);
165 secondary_edge_in_screen->SetRect(secondary.right() - 1, top, 1,
166 bottom - top);
167 } else {
168 primary_edge_in_screen->SetRect(primary.right() - 1, top, 1,
169 bottom - top);
170 secondary_edge_in_screen->SetRect(secondary.y(), top, 1, bottom - top);
172 break;
177 gfx::Rect GetNativeEdgeBounds(AshWindowTreeHost* ash_host,
178 const gfx::Rect& bounds_in_screen) {
179 aura::WindowTreeHost* host = ash_host->AsWindowTreeHost();
180 gfx::Rect native_bounds = host->GetBounds();
181 native_bounds.Inset(ash_host->GetHostInsets());
182 gfx::Point start_in_native = bounds_in_screen.origin();
183 gfx::Point end_in_native = bounds_in_screen.bottom_right();
185 ConvertPointFromScreenToNative(host, &start_in_native);
186 ConvertPointFromScreenToNative(host, &end_in_native);
188 if (std::abs(start_in_native.x() - end_in_native.x()) <
189 std::abs(start_in_native.y() - end_in_native.y())) {
190 // vertical in native
191 int x = std::abs(native_bounds.x() - start_in_native.x()) <
192 std::abs(native_bounds.right() - start_in_native.x())
193 ? native_bounds.x()
194 : native_bounds.right() - 1;
195 return gfx::Rect(x, std::min(start_in_native.y(), end_in_native.y()), 1,
196 std::abs(end_in_native.y() - start_in_native.y()));
197 } else {
198 // horizontal in native
199 int y = std::abs(native_bounds.y() - start_in_native.y()) <
200 std::abs(native_bounds.bottom() - start_in_native.y())
201 ? native_bounds.y()
202 : native_bounds.bottom() - 1;
203 return gfx::Rect(std::min(start_in_native.x(), end_in_native.x()), y,
204 std::abs(end_in_native.x() - start_in_native.x()), 1);
208 // Moves the cursor to the point inside the root that is closest to
209 // the point_in_screen, which is outside of the root window.
210 void MoveCursorTo(AshWindowTreeHost* ash_host,
211 const gfx::Point& point_in_screen,
212 bool update_last_location_now) {
213 aura::WindowTreeHost* host = ash_host->AsWindowTreeHost();
214 gfx::Point point_in_native = point_in_screen;
215 ::wm::ConvertPointFromScreen(host->window(), &point_in_native);
216 host->ConvertPointToNativeScreen(&point_in_native);
218 // now fit the point inside the native bounds.
219 gfx::Rect native_bounds = host->GetBounds();
220 gfx::Point native_origin = native_bounds.origin();
221 native_bounds.Inset(ash_host->GetHostInsets());
222 // Shrink further so that the mouse doesn't warp on the
223 // edge. The right/bottom needs to be shrink by 2 to subtract
224 // the 1 px from width/height value.
225 native_bounds.Inset(1, 1, 2, 2);
227 // Ensure that |point_in_native| is inside the |native_bounds|.
228 point_in_native.SetToMax(native_bounds.origin());
229 point_in_native.SetToMin(native_bounds.bottom_right());
231 gfx::Point point_in_host = point_in_native;
233 point_in_host.Offset(-native_origin.x(), -native_origin.y());
234 host->MoveCursorToHostLocation(point_in_host);
236 if (update_last_location_now) {
237 gfx::Point new_point_in_screen = point_in_native;
238 if (Shell::GetInstance()->display_manager()->IsInUnifiedMode()) {
239 // TODO(oshima): Do not use ConvertPointFromNativeScreen because
240 // the mirroring display has a transform that should not be applied here.
241 gfx::Point origin = host->GetBounds().origin();
242 new_point_in_screen.Offset(-origin.x(), -origin.y());
243 } else {
244 host->ConvertPointFromNativeScreen(&new_point_in_screen);
246 ::wm::ConvertPointToScreen(host->window(), &new_point_in_screen);
247 aura::Env::GetInstance()->set_last_mouse_location(new_point_in_screen);
251 int FindDisplayIndexContainingPoint(const std::vector<gfx::Display>& displays,
252 const gfx::Point& point_in_screen) {
253 auto iter = std::find_if(displays.begin(), displays.end(),
254 [point_in_screen](const gfx::Display& display) {
255 return display.bounds().Contains(point_in_screen);
257 return iter == displays.end() ? -1 : (iter - displays.begin());
260 } // namespace ash