Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(314)

Side by Side Diff: ash/display/display_manager.cc

Issue 1845723002: Allow unified desktop for 3+ displays (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | ash/display/display_manager_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 1062 matching lines...) Expand 10 before | Expand all | Expand 10 after
1073 DisplayInfo* info = &display_info_[gfx::Display::InternalDisplayId()]; 1073 DisplayInfo* info = &display_info_[gfx::Display::InternalDisplayId()];
1074 SetInternalDisplayModeList(info); 1074 SetInternalDisplayModeList(info);
1075 } 1075 }
1076 1076
1077 void DisplayManager::CreateSoftwareMirroringDisplayInfo( 1077 void DisplayManager::CreateSoftwareMirroringDisplayInfo(
1078 DisplayInfoList* display_info_list) { 1078 DisplayInfoList* display_info_list) {
1079 // Use the internal display or 1st as the mirror source, then scale 1079 // Use the internal display or 1st as the mirror source, then scale
1080 // the root window so that it matches the external display's 1080 // the root window so that it matches the external display's
1081 // resolution. This is necessary in order for scaling to work while 1081 // resolution. This is necessary in order for scaling to work while
1082 // mirrored. 1082 // mirrored.
1083 if (display_info_list->size() == 2) { 1083 switch (multi_display_mode_) {
1084 switch (multi_display_mode_) { 1084 case MIRRORING: {
1085 case MIRRORING: { 1085 if (display_info_list->size() != 2)
1086 bool zero_is_source = 1086 return;
1087 first_display_id_ == (*display_info_list)[0].id() || 1087 bool zero_is_source =
1088 gfx::Display::IsInternalDisplayId((*display_info_list)[0].id()); 1088 first_display_id_ == (*display_info_list)[0].id() ||
1089 DCHECK_EQ(MIRRORING, multi_display_mode_); 1089 gfx::Display::IsInternalDisplayId((*display_info_list)[0].id());
1090 mirroring_display_id_ = 1090 DCHECK_EQ(MIRRORING, multi_display_mode_);
1091 (*display_info_list)[zero_is_source ? 1 : 0].id(); 1091 mirroring_display_id_ = (*display_info_list)[zero_is_source ? 1 : 0].id();
1092 1092
1093 int64_t display_id = mirroring_display_id_; 1093 int64_t display_id = mirroring_display_id_;
1094 auto iter = 1094 auto iter =
1095 std::find_if(display_info_list->begin(), display_info_list->end(), 1095 std::find_if(display_info_list->begin(), display_info_list->end(),
1096 [display_id](const DisplayInfo& info) { 1096 [display_id](const DisplayInfo& info) {
1097 return info.id() == display_id; 1097 return info.id() == display_id;
1098 }); 1098 });
1099 DCHECK(iter != display_info_list->end()); 1099 DCHECK(iter != display_info_list->end());
1100 1100
1101 DisplayInfo info = *iter; 1101 DisplayInfo info = *iter;
1102 info.SetOverscanInsets(gfx::Insets()); 1102 info.SetOverscanInsets(gfx::Insets());
1103 InsertAndUpdateDisplayInfo(info);
1104 software_mirroring_display_list_.push_back(
1105 CreateMirroringDisplayFromDisplayInfoById(mirroring_display_id_,
1106 gfx::Point(), 1.0f));
1107 display_info_list->erase(iter);
1108 break;
1109 }
1110 case UNIFIED: {
1111 if (display_info_list->size() == 1)
1112 return;
1113 // TODO(oshima): Currently, all displays are laid out horizontally,
1114 // from left to right. Allow more flexible layouts, such as
1115 // right to left, or vertical layouts.
1116 gfx::Rect unified_bounds;
1117 software_mirroring_display_list_.clear();
1118 // 1st Pass. Find the max size.
1119 int max_height = std::numeric_limits<int>::min();
1120
1121 int default_height = 0;
1122 float default_device_scale_factor = 1.0f;
1123 for (auto& info : *display_info_list) {
1124 max_height = std::max(max_height, info.size_in_pixel().height());
1125 if (!default_height || gfx::Display::IsInternalDisplayId(info.id())) {
1126 default_height = info.size_in_pixel().height();
1127 default_device_scale_factor = info.device_scale_factor();
1128 }
1129 }
1130
1131 std::vector<DisplayMode> display_mode_list;
1132 std::set<std::pair<float, float>> dsf_scale_list;
1133
1134 // 2nd Pass. Compute the unified display size.
1135 for (auto& info : *display_info_list) {
1103 InsertAndUpdateDisplayInfo(info); 1136 InsertAndUpdateDisplayInfo(info);
1104 software_mirroring_display_list_.push_back( 1137 gfx::Point origin(unified_bounds.right(), 0);
1105 CreateMirroringDisplayFromDisplayInfoById(mirroring_display_id_, 1138 float scale =
1106 gfx::Point(), 1.0f)); 1139 info.size_in_pixel().height() / static_cast<float>(max_height);
1107 display_info_list->erase(iter); 1140 // The display is scaled to fit the unified desktop size.
1108 break; 1141 gfx::Display display = CreateMirroringDisplayFromDisplayInfoById(
1142 info.id(), origin, 1.0f / scale);
1143 unified_bounds.Union(display.bounds());
1144
1145 dsf_scale_list.insert(
1146 std::make_pair(info.device_scale_factor(), scale));
1109 } 1147 }
1110 case UNIFIED: {
1111 // TODO(oshima): Currently, all displays are laid out horizontally,
1112 // from left to right. Allow more flexible layouts, such as
1113 // right to left, or vertical layouts.
1114 gfx::Rect unified_bounds;
1115 software_mirroring_display_list_.clear();
1116 1148
1117 // 1st Pass. Find the max size. 1149 DisplayInfo info(kUnifiedDisplayId, "Unified Desktop", false);
1118 int max_height = std::numeric_limits<int>::min();
1119 1150
1120 int default_height = 0; 1151 DisplayMode native_mode(unified_bounds.size(), 60.0f, false, true);
1121 float default_device_scale_factor = 1.0f; 1152 std::vector<DisplayMode> modes =
1122 for (auto& info : *display_info_list) { 1153 CreateUnifiedDisplayModeList(native_mode, dsf_scale_list);
1123 max_height = std::max(max_height, info.size_in_pixel().height());
1124 if (!default_height || gfx::Display::IsInternalDisplayId(info.id())) {
1125 default_height = info.size_in_pixel().height();
1126 default_device_scale_factor = info.device_scale_factor();
1127 }
1128 }
1129 1154
1130 std::vector<DisplayMode> display_mode_list; 1155 // Find the default mode.
1131 std::set<std::pair<float, float>> dsf_scale_list; 1156 auto iter = std::find_if(
1157 modes.begin(), modes.end(),
1158 [default_height,
1159 default_device_scale_factor](const DisplayMode& mode) {
1160 return mode.size.height() == default_height &&
1161 mode.device_scale_factor == default_device_scale_factor;
1162 });
1163 iter->native = true;
1164 info.SetDisplayModes(modes);
1165 info.set_device_scale_factor(iter->device_scale_factor);
1166 info.SetBounds(gfx::Rect(iter->size));
1132 1167
1133 // 2nd Pass. Compute the unified display size. 1168 // Forget the configured resolution if the original unified
1134 for (auto& info : *display_info_list) { 1169 // desktop resolution has changed.
1135 InsertAndUpdateDisplayInfo(info); 1170 if (display_info_.count(kUnifiedDisplayId) != 0 &&
1136 gfx::Point origin(unified_bounds.right(), 0); 1171 GetMaxNativeSize(display_info_[kUnifiedDisplayId]) !=
1137 float scale = 1172 unified_bounds.size()) {
1138 info.size_in_pixel().height() / static_cast<float>(max_height); 1173 display_modes_.erase(kUnifiedDisplayId);
1139 // The display is scaled to fit the unified desktop size. 1174 }
1140 gfx::Display display = CreateMirroringDisplayFromDisplayInfoById(
1141 info.id(), origin, 1.0f / scale);
1142 unified_bounds.Union(display.bounds());
1143 1175
1144 dsf_scale_list.insert( 1176 // 3rd Pass. Set the selected mode, then recompute the mirroring
1145 std::make_pair(info.device_scale_factor(), scale)); 1177 // display size.
1146 } 1178 DisplayMode mode;
1179 if (GetSelectedModeForDisplayId(kUnifiedDisplayId, &mode) &&
1180 FindDisplayMode(info, mode) != info.display_modes().end()) {
1181 info.set_device_scale_factor(mode.device_scale_factor);
1182 info.SetBounds(gfx::Rect(mode.size));
1183 } else {
1184 display_modes_.erase(kUnifiedDisplayId);
1185 }
1147 1186
1148 DisplayInfo info(kUnifiedDisplayId, "Unified Desktop", false); 1187 int unified_display_height = info.size_in_pixel().height();
1188 gfx::Point origin;
1189 for (auto& info : *display_info_list) {
1190 float display_scale = info.size_in_pixel().height() /
1191 static_cast<float>(unified_display_height);
1192 gfx::Display display = CreateMirroringDisplayFromDisplayInfoById(
1193 info.id(), origin, 1.0f / display_scale);
1194 origin.Offset(display.size().width(), 0);
1195 display.UpdateWorkAreaFromInsets(gfx::Insets());
1196 software_mirroring_display_list_.push_back(display);
1197 }
1149 1198
1150 DisplayMode native_mode(unified_bounds.size(), 60.0f, false, true); 1199 display_info_list->clear();
1151 std::vector<DisplayMode> modes = 1200 display_info_list->push_back(info);
1152 CreateUnifiedDisplayModeList(native_mode, dsf_scale_list); 1201 InsertAndUpdateDisplayInfo(info);
1153 1202 break;
1154 // Find the default mode.
1155 auto iter = std::find_if(
1156 modes.begin(), modes.end(),
1157 [default_height,
1158 default_device_scale_factor](const DisplayMode& mode) {
1159 return mode.size.height() == default_height &&
1160 mode.device_scale_factor == default_device_scale_factor;
1161 });
1162 iter->native = true;
1163 info.SetDisplayModes(modes);
1164 info.set_device_scale_factor(iter->device_scale_factor);
1165 info.SetBounds(gfx::Rect(iter->size));
1166
1167 // Forget the configured resolution if the original unified
1168 // desktop resolution has changed.
1169 if (display_info_.count(kUnifiedDisplayId) != 0 &&
1170 GetMaxNativeSize(display_info_[kUnifiedDisplayId]) !=
1171 unified_bounds.size()) {
1172 display_modes_.erase(kUnifiedDisplayId);
1173 }
1174
1175 // 3rd Pass. Set the selected mode, then recompute the mirroring
1176 // display size.
1177 DisplayMode mode;
1178 if (GetSelectedModeForDisplayId(kUnifiedDisplayId, &mode) &&
1179 FindDisplayMode(info, mode) != info.display_modes().end()) {
1180 info.set_device_scale_factor(mode.device_scale_factor);
1181 info.SetBounds(gfx::Rect(mode.size));
1182 } else {
1183 display_modes_.erase(kUnifiedDisplayId);
1184 }
1185
1186 int unified_display_height = info.size_in_pixel().height();
1187 gfx::Point origin;
1188 for (auto& info : *display_info_list) {
1189 float display_scale = info.size_in_pixel().height() /
1190 static_cast<float>(unified_display_height);
1191 gfx::Display display = CreateMirroringDisplayFromDisplayInfoById(
1192 info.id(), origin, 1.0f / display_scale);
1193 origin.Offset(display.size().width(), 0);
1194 display.UpdateWorkAreaFromInsets(gfx::Insets());
1195 software_mirroring_display_list_.push_back(display);
1196 }
1197
1198 display_info_list->clear();
1199 display_info_list->push_back(info);
1200 InsertAndUpdateDisplayInfo(info);
1201 break;
1202 }
1203 case EXTENDED:
1204 break;
1205 } 1203 }
1204 case EXTENDED:
1205 break;
1206 } 1206 }
1207 } 1207 }
1208 1208
1209 gfx::Display* DisplayManager::FindDisplayForId(int64_t id) { 1209 gfx::Display* DisplayManager::FindDisplayForId(int64_t id) {
1210 auto iter = std::find_if( 1210 auto iter = std::find_if(
1211 active_display_list_.begin(), active_display_list_.end(), 1211 active_display_list_.begin(), active_display_list_.end(),
1212 [id](const gfx::Display& display) { return display.id() == id; }); 1212 [id](const gfx::Display& display) { return display.id() == id; });
1213 if (iter != active_display_list_.end()) 1213 if (iter != active_display_list_.end())
1214 return &(*iter); 1214 return &(*iter);
1215 // TODO(oshima): This happens when a windows in unified desktop have 1215 // TODO(oshima): This happens when a windows in unified desktop have
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
1395 1395
1396 return old_bounds != target_display->bounds(); 1396 return old_bounds != target_display->bounds();
1397 } 1397 }
1398 1398
1399 void DisplayManager::RunPendingTasksForTest() { 1399 void DisplayManager::RunPendingTasksForTest() {
1400 if (!software_mirroring_display_list_.empty()) 1400 if (!software_mirroring_display_list_.empty())
1401 base::RunLoop().RunUntilIdle(); 1401 base::RunLoop().RunUntilIdle();
1402 } 1402 }
1403 1403
1404 } // namespace ash 1404 } // namespace ash
OLDNEW
« no previous file with comments | « no previous file | ash/display/display_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698