OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ash/display/display_manager.h" | 5 #include "ash/display/display_manager.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <cmath> | 8 #include <cmath> |
9 #include <set> | 9 #include <set> |
10 #include <string> | 10 #include <string> |
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
271 | 271 |
272 bool DisplayManager::HasInternalDisplay() const { | 272 bool DisplayManager::HasInternalDisplay() const { |
273 return gfx::Display::InternalDisplayId() != gfx::Display::kInvalidDisplayID; | 273 return gfx::Display::InternalDisplayId() != gfx::Display::kInvalidDisplayID; |
274 } | 274 } |
275 | 275 |
276 bool DisplayManager::IsInternalDisplayId(int64 id) const { | 276 bool DisplayManager::IsInternalDisplayId(int64 id) const { |
277 return gfx::Display::InternalDisplayId() == id; | 277 return gfx::Display::InternalDisplayId() == id; |
278 } | 278 } |
279 | 279 |
280 DisplayLayout DisplayManager::GetCurrentDisplayLayout() { | 280 DisplayLayout DisplayManager::GetCurrentDisplayLayout() { |
281 DCHECK_EQ(2U, num_connected_displays()); | 281 DCHECK_LE(2U, num_connected_displays()); |
282 // Invert if the primary was swapped. | 282 // Invert if the primary was swapped. |
283 if (num_connected_displays() > 1) { | 283 if (num_connected_displays() == 2) { |
284 DisplayIdPair pair = GetCurrentDisplayIdPair(); | 284 DisplayIdPair pair = GetCurrentDisplayIdPair(); |
285 return layout_store_->ComputeDisplayLayoutForDisplayIdPair(pair); | 285 return layout_store_->ComputeDisplayLayoutForDisplayIdPair(pair); |
| 286 } else if (num_connected_displays() > 2) { |
| 287 // Return fixed horizontal layout for >= 3 displays. |
| 288 DisplayLayout layout(DisplayLayout::RIGHT, 0); |
| 289 return layout; |
286 } | 290 } |
287 NOTREACHED() << "DisplayLayout is requested for single display"; | 291 NOTREACHED() << "DisplayLayout is requested for single display"; |
288 // On release build, just fallback to default instead of blowing up. | 292 // On release build, just fallback to default instead of blowing up. |
289 DisplayLayout layout = | 293 DisplayLayout layout = |
290 layout_store_->default_display_layout(); | 294 layout_store_->default_display_layout(); |
291 layout.primary_id = displays_[0].id(); | 295 layout.primary_id = displays_[0].id(); |
292 return layout; | 296 return layout; |
293 } | 297 } |
294 | 298 |
295 DisplayIdPair DisplayManager::GetCurrentDisplayIdPair() const { | 299 DisplayIdPair DisplayManager::GetCurrentDisplayIdPair() const { |
296 if (IsMirrored()) { | 300 if (IsMirrored()) { |
297 if (software_mirroring_enabled()) { | 301 if (software_mirroring_enabled()) { |
298 CHECK_EQ(2u, num_connected_displays()); | 302 CHECK_EQ(2u, num_connected_displays()); |
299 // This comment is to make it easy to distinguish the crash | 303 // This comment is to make it easy to distinguish the crash |
300 // between two checks. | 304 // between two checks. |
301 CHECK_EQ(1u, displays_.size()); | 305 CHECK_EQ(1u, displays_.size()); |
302 } | 306 } |
303 return std::make_pair(displays_[0].id(), mirrored_display_id_); | 307 return std::make_pair(displays_[0].id(), mirrored_display_id_); |
304 } else { | 308 } else { |
305 CHECK_GE(2u, displays_.size()); | 309 CHECK_LE(2u, displays_.size()); |
306 int64 id_at_zero = displays_[0].id(); | 310 int64 id_at_zero = displays_[0].id(); |
307 if (id_at_zero == gfx::Display::InternalDisplayId() || | 311 if (id_at_zero == gfx::Display::InternalDisplayId() || |
308 id_at_zero == first_display_id()) { | 312 id_at_zero == first_display_id()) { |
309 return std::make_pair(id_at_zero, displays_[1].id()); | 313 return std::make_pair(id_at_zero, displays_[1].id()); |
310 } else { | 314 } else { |
311 return std::make_pair(displays_[1].id(), id_at_zero); | 315 return std::make_pair(displays_[1].id(), id_at_zero); |
312 } | 316 } |
313 } | 317 } |
314 } | 318 } |
315 | 319 |
316 void DisplayManager::SetLayoutForCurrentDisplays( | 320 void DisplayManager::SetLayoutForCurrentDisplays( |
317 const DisplayLayout& layout_relative_to_primary) { | 321 const DisplayLayout& layout_relative_to_primary) { |
318 DCHECK_EQ(2U, GetNumDisplays()); | 322 if (GetNumDisplays() != 2) |
319 if (GetNumDisplays() < 2) | |
320 return; | 323 return; |
321 const gfx::Display& primary = screen_->GetPrimaryDisplay(); | 324 const gfx::Display& primary = screen_->GetPrimaryDisplay(); |
322 const DisplayIdPair pair = GetCurrentDisplayIdPair(); | 325 const DisplayIdPair pair = GetCurrentDisplayIdPair(); |
323 // Invert if the primary was swapped. | 326 // Invert if the primary was swapped. |
324 DisplayLayout to_set = pair.first == primary.id() ? | 327 DisplayLayout to_set = pair.first == primary.id() ? |
325 layout_relative_to_primary : layout_relative_to_primary.Invert(); | 328 layout_relative_to_primary : layout_relative_to_primary.Invert(); |
326 | 329 |
327 DisplayLayout current_layout = | 330 DisplayLayout current_layout = |
328 layout_store_->GetRegisteredDisplayLayout(pair); | 331 layout_store_->GetRegisteredDisplayLayout(pair); |
329 if (to_set.position != current_layout.position || | 332 if (to_set.position != current_layout.position || |
(...skipping 530 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
860 // is possible there is no need to update |displays_| and we early out | 863 // is possible there is no need to update |displays_| and we early out |
861 // here. But we still want to run the PostDisplayConfigurationChange() | 864 // here. But we still want to run the PostDisplayConfigurationChange() |
862 // cause there are some clients need to act on this, e.g. | 865 // cause there are some clients need to act on this, e.g. |
863 // TouchTransformerController needs to adjust the TouchTransformer when | 866 // TouchTransformerController needs to adjust the TouchTransformer when |
864 // switching from dual displays to single display. | 867 // switching from dual displays to single display. |
865 if (delegate_) | 868 if (delegate_) |
866 delegate_->PostDisplayConfigurationChange(); | 869 delegate_->PostDisplayConfigurationChange(); |
867 return; | 870 return; |
868 } | 871 } |
869 | 872 |
870 size_t updated_index; | 873 std::vector<size_t> updated_indices; |
871 if (UpdateSecondaryDisplayBoundsForLayout(&new_displays, &updated_index) && | 874 if (UpdateNonPrimaryDisplayBoundsForLayout(&new_displays, &updated_indices)) { |
872 std::find(added_display_indices.begin(), | 875 for (std::vector<size_t>::iterator it = updated_indices.begin(); |
873 added_display_indices.end(), | 876 it != updated_indices.end(); ++it) { |
874 updated_index) == added_display_indices.end()) { | 877 size_t updated_index = *it; |
875 uint32_t metrics = gfx::DisplayObserver::DISPLAY_METRIC_BOUNDS | | 878 if (std::find(added_display_indices.begin(), |
876 gfx::DisplayObserver::DISPLAY_METRIC_WORK_AREA; | 879 added_display_indices.end(), |
877 if (display_changes.find(updated_index) != display_changes.end()) | 880 updated_index) == added_display_indices.end()) { |
878 metrics |= display_changes[updated_index]; | 881 uint32_t metrics = gfx::DisplayObserver::DISPLAY_METRIC_BOUNDS | |
| 882 gfx::DisplayObserver::DISPLAY_METRIC_WORK_AREA; |
| 883 if (display_changes.find(updated_index) != display_changes.end()) |
| 884 metrics |= display_changes[updated_index]; |
879 | 885 |
880 display_changes[updated_index] = metrics; | 886 display_changes[updated_index] = metrics; |
| 887 } |
| 888 } |
881 } | 889 } |
882 | 890 |
883 displays_ = new_displays; | 891 displays_ = new_displays; |
884 | 892 |
885 base::AutoReset<bool> resetter(&change_display_upon_host_resize_, false); | 893 base::AutoReset<bool> resetter(&change_display_upon_host_resize_, false); |
886 | 894 |
887 // Temporarily add displays to be removed because display object | 895 // Temporarily add displays to be removed because display object |
888 // being removed are accessed during shutting down the root. | 896 // being removed are accessed during shutting down the root. |
889 displays_.insert(displays_.end(), removed_displays.begin(), | 897 displays_.insert(displays_.end(), removed_displays.begin(), |
890 removed_displays.end()); | 898 removed_displays.end()); |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
954 if (has_mirroring_display && delegate_) | 962 if (has_mirroring_display && delegate_) |
955 CreateMirrorWindowAsyncIfAny(); | 963 CreateMirrorWindowAsyncIfAny(); |
956 } | 964 } |
957 | 965 |
958 const gfx::Display& DisplayManager::GetDisplayAt(size_t index) const { | 966 const gfx::Display& DisplayManager::GetDisplayAt(size_t index) const { |
959 DCHECK_LT(index, displays_.size()); | 967 DCHECK_LT(index, displays_.size()); |
960 return displays_[index]; | 968 return displays_[index]; |
961 } | 969 } |
962 | 970 |
963 const gfx::Display& DisplayManager::GetPrimaryDisplayCandidate() const { | 971 const gfx::Display& DisplayManager::GetPrimaryDisplayCandidate() const { |
964 if (GetNumDisplays() == 1) | 972 if (GetNumDisplays() != 2) |
965 return displays_[0]; | 973 return displays_[0]; |
966 DisplayLayout layout = layout_store_->GetRegisteredDisplayLayout( | 974 DisplayLayout layout = layout_store_->GetRegisteredDisplayLayout( |
967 GetCurrentDisplayIdPair()); | 975 GetCurrentDisplayIdPair()); |
968 return GetDisplayForId(layout.primary_id); | 976 return GetDisplayForId(layout.primary_id); |
969 } | 977 } |
970 | 978 |
971 size_t DisplayManager::GetNumDisplays() const { | 979 size_t DisplayManager::GetNumDisplays() const { |
972 return displays_.size(); | 980 return displays_.size(); |
973 } | 981 } |
974 | 982 |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1164 | 1172 |
1165 gfx::Display DisplayManager::CreateDisplayFromDisplayInfoById(int64 id) { | 1173 gfx::Display DisplayManager::CreateDisplayFromDisplayInfoById(int64 id) { |
1166 DCHECK(display_info_.find(id) != display_info_.end()); | 1174 DCHECK(display_info_.find(id) != display_info_.end()); |
1167 const DisplayInfo& display_info = display_info_[id]; | 1175 const DisplayInfo& display_info = display_info_[id]; |
1168 | 1176 |
1169 gfx::Display new_display(display_info.id()); | 1177 gfx::Display new_display(display_info.id()); |
1170 gfx::Rect bounds_in_native(display_info.size_in_pixel()); | 1178 gfx::Rect bounds_in_native(display_info.size_in_pixel()); |
1171 float device_scale_factor = display_info.GetEffectiveDeviceScaleFactor(); | 1179 float device_scale_factor = display_info.GetEffectiveDeviceScaleFactor(); |
1172 | 1180 |
1173 // Simply set the origin to (0,0). The primary display's origin is | 1181 // Simply set the origin to (0,0). The primary display's origin is |
1174 // always (0,0) and the secondary display's bounds will be updated | 1182 // always (0,0) and the bounds of non-primary display(s) will be updated |
1175 // in |UpdateSecondaryDisplayBoundsForLayout| called in |UpdateDisplay|. | 1183 // in |UpdateNonPrimaryDisplayBoundsForLayout| called in |UpdateDisplay|. |
1176 new_display.SetScaleAndBounds( | 1184 new_display.SetScaleAndBounds( |
1177 device_scale_factor, gfx::Rect(bounds_in_native.size())); | 1185 device_scale_factor, gfx::Rect(bounds_in_native.size())); |
1178 new_display.set_rotation(display_info.rotation()); | 1186 new_display.set_rotation(display_info.rotation()); |
1179 new_display.set_touch_support(display_info.touch_support()); | 1187 new_display.set_touch_support(display_info.touch_support()); |
1180 return new_display; | 1188 return new_display; |
1181 } | 1189 } |
1182 | 1190 |
1183 bool DisplayManager::UpdateSecondaryDisplayBoundsForLayout( | 1191 bool DisplayManager::UpdateNonPrimaryDisplayBoundsForLayout( |
1184 DisplayList* displays, | 1192 DisplayList* displays, |
1185 size_t* updated_index) const { | 1193 std::vector<size_t>* updated_indices) const { |
1186 if (displays->size() != 2U) | 1194 |
| 1195 if (displays->size() < 2U) |
1187 return false; | 1196 return false; |
1188 | 1197 |
| 1198 if (displays->size() > 2U) { |
| 1199 // For more than 2 displays, always use horizontal layout. |
| 1200 int x_offset = displays->at(0).bounds().width(); |
| 1201 for (size_t i = 1; i < displays->size(); ++i) { |
| 1202 gfx::Display& display = displays->at(i); |
| 1203 const gfx::Rect& bounds = display.bounds(); |
| 1204 gfx::Point origin = gfx::Point(x_offset, 0); |
| 1205 gfx::Insets insets = display.GetWorkAreaInsets(); |
| 1206 display.set_bounds(gfx::Rect(origin, bounds.size())); |
| 1207 display.UpdateWorkAreaFromInsets(insets); |
| 1208 x_offset += bounds.width(); |
| 1209 updated_indices->push_back(i); |
| 1210 } |
| 1211 return true; |
| 1212 } |
| 1213 |
1189 int64 id_at_zero = displays->at(0).id(); | 1214 int64 id_at_zero = displays->at(0).id(); |
1190 DisplayIdPair pair = | 1215 DisplayIdPair pair = |
1191 (id_at_zero == first_display_id_ || | 1216 (id_at_zero == first_display_id_ || |
1192 id_at_zero == gfx::Display::InternalDisplayId()) ? | 1217 id_at_zero == gfx::Display::InternalDisplayId()) ? |
1193 std::make_pair(id_at_zero, displays->at(1).id()) : | 1218 std::make_pair(id_at_zero, displays->at(1).id()) : |
1194 std::make_pair(displays->at(1).id(), id_at_zero); | 1219 std::make_pair(displays->at(1).id(), id_at_zero); |
1195 DisplayLayout layout = | 1220 DisplayLayout layout = |
1196 layout_store_->ComputeDisplayLayoutForDisplayIdPair(pair); | 1221 layout_store_->ComputeDisplayLayoutForDisplayIdPair(pair); |
1197 | 1222 |
1198 // Ignore if a user has a old format (should be extremely rare) | 1223 // Ignore if a user has a old format (should be extremely rare) |
1199 // and this will be replaced with DCHECK. | 1224 // and this will be replaced with DCHECK. |
1200 if (layout.primary_id != gfx::Display::kInvalidDisplayID) { | 1225 if (layout.primary_id != gfx::Display::kInvalidDisplayID) { |
1201 size_t primary_index, secondary_index; | 1226 size_t primary_index, secondary_index; |
1202 if (displays->at(0).id() == layout.primary_id) { | 1227 if (displays->at(0).id() == layout.primary_id) { |
1203 primary_index = 0; | 1228 primary_index = 0; |
1204 secondary_index = 1; | 1229 secondary_index = 1; |
1205 } else { | 1230 } else { |
1206 primary_index = 1; | 1231 primary_index = 1; |
1207 secondary_index = 0; | 1232 secondary_index = 0; |
1208 } | 1233 } |
1209 // This function may be called before the secondary display is | 1234 // This function may be called before the secondary display is |
1210 // registered. The bounds is empty in that case and will | 1235 // registered. The bounds is empty in that case and will |
1211 // return true. | 1236 // return true. |
1212 gfx::Rect bounds = | 1237 gfx::Rect bounds = |
1213 GetDisplayForId(displays->at(secondary_index).id()).bounds(); | 1238 GetDisplayForId(displays->at(secondary_index).id()).bounds(); |
1214 UpdateDisplayBoundsForLayout( | 1239 UpdateDisplayBoundsForLayout( |
1215 layout, displays->at(primary_index), &displays->at(secondary_index)); | 1240 layout, displays->at(primary_index), &displays->at(secondary_index)); |
1216 *updated_index = secondary_index; | 1241 updated_indices->push_back(secondary_index); |
1217 return bounds != displays->at(secondary_index).bounds(); | 1242 return bounds != displays->at(secondary_index).bounds(); |
1218 } | 1243 } |
1219 return false; | 1244 return false; |
1220 } | 1245 } |
1221 | 1246 |
1222 void DisplayManager::CreateMirrorWindowIfAny() { | 1247 void DisplayManager::CreateMirrorWindowIfAny() { |
1223 if (HasSoftwareMirroringDisplay() && delegate_) { | 1248 if (HasSoftwareMirroringDisplay() && delegate_) { |
1224 DisplayInfo display_info = GetDisplayInfo(mirroring_display_.id()); | 1249 DisplayInfo display_info = GetDisplayInfo(mirroring_display_.id()); |
1225 delegate_->CreateOrUpdateMirroringDisplay(display_info); | 1250 delegate_->CreateOrUpdateMirroringDisplay(display_info); |
1226 } | 1251 } |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1272 new_secondary_origin.Offset(-secondary_bounds.width(), offset); | 1297 new_secondary_origin.Offset(-secondary_bounds.width(), offset); |
1273 break; | 1298 break; |
1274 } | 1299 } |
1275 gfx::Insets insets = secondary_display->GetWorkAreaInsets(); | 1300 gfx::Insets insets = secondary_display->GetWorkAreaInsets(); |
1276 secondary_display->set_bounds( | 1301 secondary_display->set_bounds( |
1277 gfx::Rect(new_secondary_origin, secondary_bounds.size())); | 1302 gfx::Rect(new_secondary_origin, secondary_bounds.size())); |
1278 secondary_display->UpdateWorkAreaFromInsets(insets); | 1303 secondary_display->UpdateWorkAreaFromInsets(insets); |
1279 } | 1304 } |
1280 | 1305 |
1281 } // namespace ash | 1306 } // namespace ash |
OLD | NEW |