| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 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/wm/dock/docked_window_layout_manager.h" | 5 #include "ash/wm/dock/docked_window_layout_manager.h" |
| 6 | 6 |
| 7 #include "ash/screen_util.h" | 7 #include "ash/screen_util.h" |
| 8 #include "ash/shelf/shelf.h" | 8 #include "ash/shelf/shelf.h" |
| 9 #include "ash/shelf/shelf_constants.h" | 9 #include "ash/shelf/shelf_constants.h" |
| 10 #include "ash/shelf/shelf_layout_manager.h" | 10 #include "ash/shelf/shelf_layout_manager.h" |
| (...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 289 if (delegate->GetMaximumSize().height() != 0) | 289 if (delegate->GetMaximumSize().height() != 0) |
| 290 maximum_height = delegate->GetMaximumSize().height(); | 290 maximum_height = delegate->GetMaximumSize().height(); |
| 291 } | 291 } |
| 292 if (minimum_height) | 292 if (minimum_height) |
| 293 target_height = std::max(target_height, minimum_height); | 293 target_height = std::max(target_height, minimum_height); |
| 294 if (maximum_height) | 294 if (maximum_height) |
| 295 target_height = std::min(target_height, maximum_height); | 295 target_height = std::min(target_height, maximum_height); |
| 296 return target_height; | 296 return target_height; |
| 297 } | 297 } |
| 298 | 298 |
| 299 } // namespace |
| 300 |
| 301 struct DockedWindowLayoutManager::WindowWithHeight { |
| 302 explicit WindowWithHeight(aura::Window* window) |
| 303 : window(window), height(window->bounds().height()) {} |
| 304 aura::Window* window; |
| 305 int height; |
| 306 }; |
| 307 |
| 299 // A functor used to sort the windows in order of their minimum height. | 308 // A functor used to sort the windows in order of their minimum height. |
| 300 struct CompareMinimumHeight { | 309 struct DockedWindowLayoutManager::CompareMinimumHeight { |
| 301 bool operator()(WindowWithHeight win1, WindowWithHeight win2) { | 310 bool operator()(const WindowWithHeight& win1, const WindowWithHeight& win2) { |
| 302 return GetWindowHeightCloseTo(win1.window(), 0) < | 311 return GetWindowHeightCloseTo(win1.window, 0) < |
| 303 GetWindowHeightCloseTo(win2.window(), 0); | 312 GetWindowHeightCloseTo(win2.window, 0); |
| 304 } | 313 } |
| 305 }; | 314 }; |
| 306 | 315 |
| 307 // A functor used to sort the windows in order of their center Y position. | 316 // A functor used to sort the windows in order of their center Y position. |
| 308 // |delta| is a pre-calculated distance from the bottom of one window to the top | 317 // |delta| is a pre-calculated distance from the bottom of one window to the top |
| 309 // of the next. Its value can be positive (gap) or negative (overlap). | 318 // of the next. Its value can be positive (gap) or negative (overlap). |
| 310 // Half of |delta| is used as a transition point at which windows could ideally | 319 // Half of |delta| is used as a transition point at which windows could ideally |
| 311 // swap positions. | 320 // swap positions. |
| 312 struct CompareWindowPos { | 321 struct DockedWindowLayoutManager::CompareWindowPos { |
| 313 CompareWindowPos(aura::Window* dragged_window, | 322 CompareWindowPos(aura::Window* dragged_window, |
| 314 aura::Window* docked_container, | 323 aura::Window* docked_container, |
| 315 float delta) | 324 float delta) |
| 316 : dragged_window_(dragged_window), | 325 : dragged_window_(dragged_window), |
| 317 docked_container_(docked_container), | 326 docked_container_(docked_container), |
| 318 delta_(delta / 2) {} | 327 delta_(delta / 2) {} |
| 319 | 328 |
| 320 bool operator()(WindowWithHeight window_with_height1, | 329 bool operator()(const WindowWithHeight& window_with_height1, |
| 321 WindowWithHeight window_with_height2) { | 330 const WindowWithHeight& window_with_height2) { |
| 322 // Use target coordinates since animations may be active when windows are | 331 // Use target coordinates since animations may be active when windows are |
| 323 // reordered. | 332 // reordered. |
| 324 aura::Window* win1(window_with_height1.window()); | 333 aura::Window* win1(window_with_height1.window); |
| 325 aura::Window* win2(window_with_height2.window()); | 334 aura::Window* win2(window_with_height2.window); |
| 326 gfx::Rect win1_bounds = ScreenUtil::ConvertRectToScreen( | 335 gfx::Rect win1_bounds = ScreenUtil::ConvertRectToScreen( |
| 327 docked_container_, win1->GetTargetBounds()); | 336 docked_container_, win1->GetTargetBounds()); |
| 328 gfx::Rect win2_bounds = ScreenUtil::ConvertRectToScreen( | 337 gfx::Rect win2_bounds = ScreenUtil::ConvertRectToScreen( |
| 329 docked_container_, win2->GetTargetBounds()); | 338 docked_container_, win2->GetTargetBounds()); |
| 330 win1_bounds.set_height(window_with_height1.height_); | 339 win1_bounds.set_height(window_with_height1.height); |
| 331 win2_bounds.set_height(window_with_height2.height_); | 340 win2_bounds.set_height(window_with_height2.height); |
| 332 // If one of the windows is the |dragged_window_| attempt to make an | 341 // If one of the windows is the |dragged_window_| attempt to make an |
| 333 // earlier swap between the windows than just based on their centers. | 342 // earlier swap between the windows than just based on their centers. |
| 334 // This is possible if the dragged window is at least as tall as the other | 343 // This is possible if the dragged window is at least as tall as the other |
| 335 // window. | 344 // window. |
| 336 if (win1 == dragged_window_) | 345 if (win1 == dragged_window_) |
| 337 return compare_two_windows(win1_bounds, win2_bounds); | 346 return compare_two_windows(win1_bounds, win2_bounds); |
| 338 if (win2 == dragged_window_) | 347 if (win2 == dragged_window_) |
| 339 return !compare_two_windows(win2_bounds, win1_bounds); | 348 return !compare_two_windows(win2_bounds, win1_bounds); |
| 340 // Otherwise just compare the centers. | 349 // Otherwise just compare the centers. |
| 341 return win1_bounds.CenterPoint().y() < win2_bounds.CenterPoint().y(); | 350 return win1_bounds.CenterPoint().y() < win2_bounds.CenterPoint().y(); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 363 // In this case just compare the centers. | 372 // In this case just compare the centers. |
| 364 return bounds1.CenterPoint().y() < bounds2.CenterPoint().y(); | 373 return bounds1.CenterPoint().y() < bounds2.CenterPoint().y(); |
| 365 } | 374 } |
| 366 | 375 |
| 367 private: | 376 private: |
| 368 aura::Window* dragged_window_; | 377 aura::Window* dragged_window_; |
| 369 aura::Window* docked_container_; | 378 aura::Window* docked_container_; |
| 370 float delta_; | 379 float delta_; |
| 371 }; | 380 }; |
| 372 | 381 |
| 373 } // namespace | |
| 374 | |
| 375 //////////////////////////////////////////////////////////////////////////////// | 382 //////////////////////////////////////////////////////////////////////////////// |
| 376 // A class that observes shelf for bounds changes. | 383 // A class that observes shelf for bounds changes. |
| 377 class DockedWindowLayoutManager::ShelfWindowObserver : public WindowObserver { | 384 class DockedWindowLayoutManager::ShelfWindowObserver : public WindowObserver { |
| 378 public: | 385 public: |
| 379 explicit ShelfWindowObserver( | 386 explicit ShelfWindowObserver( |
| 380 DockedWindowLayoutManager* docked_layout_manager) | 387 DockedWindowLayoutManager* docked_layout_manager) |
| 381 : docked_layout_manager_(docked_layout_manager) { | 388 : docked_layout_manager_(docked_layout_manager) { |
| 382 DCHECK(docked_layout_manager_->shelf()->shelf_widget()); | 389 DCHECK(docked_layout_manager_->shelf()->shelf_widget()); |
| 383 docked_layout_manager_->shelf()->shelf_widget()->GetNativeView() | 390 docked_layout_manager_->shelf()->shelf_widget()->GetNativeView() |
| 384 ->AddObserver(this); | 391 ->AddObserver(this); |
| (...skipping 755 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1140 std::sort(visible_windows->begin(), visible_windows->end(), | 1147 std::sort(visible_windows->begin(), visible_windows->end(), |
| 1141 CompareMinimumHeight()); | 1148 CompareMinimumHeight()); |
| 1142 // Distribute the free space among the docked windows. Since the windows are | 1149 // Distribute the free space among the docked windows. Since the windows are |
| 1143 // sorted (tall windows first) we can now assume that any window which | 1150 // sorted (tall windows first) we can now assume that any window which |
| 1144 // required more space than the current window will have already been | 1151 // required more space than the current window will have already been |
| 1145 // accounted for previously in this loop, so we can safely give that window | 1152 // accounted for previously in this loop, so we can safely give that window |
| 1146 // its proportional share of the remaining space. | 1153 // its proportional share of the remaining space. |
| 1147 for (std::vector<WindowWithHeight>::reverse_iterator iter = | 1154 for (std::vector<WindowWithHeight>::reverse_iterator iter = |
| 1148 visible_windows->rbegin(); | 1155 visible_windows->rbegin(); |
| 1149 iter != visible_windows->rend(); ++iter) { | 1156 iter != visible_windows->rend(); ++iter) { |
| 1150 iter->height_ = GetWindowHeightCloseTo( | 1157 iter->height = GetWindowHeightCloseTo( |
| 1151 iter->window(), | 1158 iter->window, |
| 1152 (available_room + gap_height) / remaining_windows - gap_height); | 1159 (available_room + gap_height) / remaining_windows - gap_height); |
| 1153 available_room -= (iter->height_ + gap_height); | 1160 available_room -= (iter->height + gap_height); |
| 1154 remaining_windows--; | 1161 remaining_windows--; |
| 1155 } | 1162 } |
| 1156 return available_room + gap_height; | 1163 return available_room + gap_height; |
| 1157 } | 1164 } |
| 1158 | 1165 |
| 1159 int DockedWindowLayoutManager::CalculateIdealWidth( | 1166 int DockedWindowLayoutManager::CalculateIdealWidth( |
| 1160 const std::vector<WindowWithHeight>& visible_windows) { | 1167 const std::vector<WindowWithHeight>& visible_windows) { |
| 1161 int smallest_max_width = kMaxDockWidth; | 1168 int smallest_max_width = kMaxDockWidth; |
| 1162 int largest_min_width = kMinDockWidth; | 1169 int largest_min_width = kMinDockWidth; |
| 1163 // Ideal width of the docked area is as close to kIdealWidth as possible | 1170 // Ideal width of the docked area is as close to kIdealWidth as possible |
| 1164 // while still respecting the minimum and maximum width restrictions on the | 1171 // while still respecting the minimum and maximum width restrictions on the |
| 1165 // individual docked windows as well as the width that was possibly set by a | 1172 // individual docked windows as well as the width that was possibly set by a |
| 1166 // user (which needs to be preserved when dragging and rearranging windows). | 1173 // user (which needs to be preserved when dragging and rearranging windows). |
| 1167 for (std::vector<WindowWithHeight>::const_iterator iter = | 1174 for (std::vector<WindowWithHeight>::const_iterator iter = |
| 1168 visible_windows.begin(); | 1175 visible_windows.begin(); |
| 1169 iter != visible_windows.end(); ++iter) { | 1176 iter != visible_windows.end(); ++iter) { |
| 1170 const aura::Window* window = iter->window(); | 1177 const aura::Window* window = iter->window; |
| 1171 int min_window_width = window->bounds().width(); | 1178 int min_window_width = window->bounds().width(); |
| 1172 int max_window_width = min_window_width; | 1179 int max_window_width = min_window_width; |
| 1173 if (!wm::GetWindowState(window)->bounds_changed_by_user()) { | 1180 if (!wm::GetWindowState(window)->bounds_changed_by_user()) { |
| 1174 min_window_width = GetWindowWidthCloseTo(window, kMinDockWidth); | 1181 min_window_width = GetWindowWidthCloseTo(window, kMinDockWidth); |
| 1175 max_window_width = GetWindowWidthCloseTo(window, kMaxDockWidth); | 1182 max_window_width = GetWindowWidthCloseTo(window, kMaxDockWidth); |
| 1176 } | 1183 } |
| 1177 largest_min_width = std::max(largest_min_width, min_window_width); | 1184 largest_min_width = std::max(largest_min_width, min_window_width); |
| 1178 smallest_max_width = std::min(smallest_max_width, max_window_width); | 1185 smallest_max_width = std::min(smallest_max_width, max_window_width); |
| 1179 } | 1186 } |
| 1180 int ideal_width = std::max(largest_min_width, | 1187 int ideal_width = std::max(largest_min_width, |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1196 const float delta = static_cast<float>(available_room) / | 1203 const float delta = static_cast<float>(available_room) / |
| 1197 ((available_room > 0 || num_windows <= 1) ? | 1204 ((available_room > 0 || num_windows <= 1) ? |
| 1198 num_windows + 1 : num_windows - 1); | 1205 num_windows + 1 : num_windows - 1); |
| 1199 float y_pos = work_area.y() + ((delta > 0) ? delta : 0); | 1206 float y_pos = work_area.y() + ((delta > 0) ? delta : 0); |
| 1200 | 1207 |
| 1201 // Docked area is shown only if there is at least one non-dragged visible | 1208 // Docked area is shown only if there is at least one non-dragged visible |
| 1202 // docked window. | 1209 // docked window. |
| 1203 int new_width = ideal_docked_width; | 1210 int new_width = ideal_docked_width; |
| 1204 if (visible_windows->empty() || | 1211 if (visible_windows->empty() || |
| 1205 (visible_windows->size() == 1 && | 1212 (visible_windows->size() == 1 && |
| 1206 (*visible_windows)[0].window() == dragged_window_)) { | 1213 (*visible_windows)[0].window == dragged_window_)) { |
| 1207 new_width = 0; | 1214 new_width = 0; |
| 1208 } | 1215 } |
| 1209 UpdateDockedWidth(new_width); | 1216 UpdateDockedWidth(new_width); |
| 1210 // Sort windows by their center positions and fan out overlapping | 1217 // Sort windows by their center positions and fan out overlapping |
| 1211 // windows. | 1218 // windows. |
| 1212 std::sort(visible_windows->begin(), visible_windows->end(), | 1219 std::sort(visible_windows->begin(), visible_windows->end(), |
| 1213 CompareWindowPos(is_dragged_from_dock_ ? dragged_window_ : nullptr, | 1220 CompareWindowPos(is_dragged_from_dock_ ? dragged_window_ : nullptr, |
| 1214 dock_container_, delta)); | 1221 dock_container_, delta)); |
| 1215 for (std::vector<WindowWithHeight>::iterator iter = visible_windows->begin(); | 1222 for (std::vector<WindowWithHeight>::iterator iter = visible_windows->begin(); |
| 1216 iter != visible_windows->end(); ++iter) { | 1223 iter != visible_windows->end(); ++iter) { |
| 1217 aura::Window* window = iter->window(); | 1224 aura::Window* window = iter->window; |
| 1218 gfx::Rect bounds = ScreenUtil::ConvertRectToScreen( | 1225 gfx::Rect bounds = ScreenUtil::ConvertRectToScreen( |
| 1219 dock_container_, window->GetTargetBounds()); | 1226 dock_container_, window->GetTargetBounds()); |
| 1220 // A window is extended or shrunk to be as close as possible to the ideal | 1227 // A window is extended or shrunk to be as close as possible to the ideal |
| 1221 // docked area width. Windows that were resized by a user are kept at their | 1228 // docked area width. Windows that were resized by a user are kept at their |
| 1222 // existing size. | 1229 // existing size. |
| 1223 // This also enforces the min / max restrictions on the docked area width. | 1230 // This also enforces the min / max restrictions on the docked area width. |
| 1224 bounds.set_width(GetWindowWidthCloseTo( | 1231 bounds.set_width(GetWindowWidthCloseTo( |
| 1225 window, | 1232 window, |
| 1226 wm::GetWindowState(window)->bounds_changed_by_user() ? | 1233 wm::GetWindowState(window)->bounds_changed_by_user() ? |
| 1227 bounds.width() : ideal_docked_width)); | 1234 bounds.width() : ideal_docked_width)); |
| 1228 DCHECK_LE(bounds.width(), ideal_docked_width); | 1235 DCHECK_LE(bounds.width(), ideal_docked_width); |
| 1229 | 1236 |
| 1230 DockedAlignment alignment = alignment_; | 1237 DockedAlignment alignment = alignment_; |
| 1231 if (alignment == DOCKED_ALIGNMENT_NONE && window == dragged_window_) | 1238 if (alignment == DOCKED_ALIGNMENT_NONE && window == dragged_window_) |
| 1232 alignment = GetEdgeNearestWindow(window); | 1239 alignment = GetEdgeNearestWindow(window); |
| 1233 | 1240 |
| 1234 // Fan out windows evenly distributing the overlap or remaining free space. | 1241 // Fan out windows evenly distributing the overlap or remaining free space. |
| 1235 bounds.set_height(iter->height_); | 1242 bounds.set_height(iter->height); |
| 1236 bounds.set_y(std::max(work_area.y(), | 1243 bounds.set_y(std::max(work_area.y(), |
| 1237 std::min(work_area.bottom() - bounds.height(), | 1244 std::min(work_area.bottom() - bounds.height(), |
| 1238 static_cast<int>(y_pos + 0.5)))); | 1245 static_cast<int>(y_pos + 0.5)))); |
| 1239 y_pos += bounds.height() + delta + kMinDockGap; | 1246 y_pos += bounds.height() + delta + kMinDockGap; |
| 1240 | 1247 |
| 1241 // All docked windows other than the one currently dragged remain stuck | 1248 // All docked windows other than the one currently dragged remain stuck |
| 1242 // to the screen edge (flush with the edge or centered in the dock area). | 1249 // to the screen edge (flush with the edge or centered in the dock area). |
| 1243 switch (alignment) { | 1250 switch (alignment) { |
| 1244 case DOCKED_ALIGNMENT_LEFT: | 1251 case DOCKED_ALIGNMENT_LEFT: |
| 1245 bounds.set_x(dock_bounds.x() + | 1252 bounds.set_x(dock_bounds.x() + |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1365 | 1372 |
| 1366 void DockedWindowLayoutManager::OnKeyboardBoundsChanging( | 1373 void DockedWindowLayoutManager::OnKeyboardBoundsChanging( |
| 1367 const gfx::Rect& keyboard_bounds) { | 1374 const gfx::Rect& keyboard_bounds) { |
| 1368 // This bounds change will have caused a change to the Shelf which does not | 1375 // This bounds change will have caused a change to the Shelf which does not |
| 1369 // propagate automatically to this class, so manually recalculate bounds. | 1376 // propagate automatically to this class, so manually recalculate bounds. |
| 1370 Relayout(); | 1377 Relayout(); |
| 1371 UpdateDockBounds(DockedWindowLayoutManagerObserver::KEYBOARD_BOUNDS_CHANGING); | 1378 UpdateDockBounds(DockedWindowLayoutManagerObserver::KEYBOARD_BOUNDS_CHANGING); |
| 1372 } | 1379 } |
| 1373 | 1380 |
| 1374 } // namespace ash | 1381 } // namespace ash |
| OLD | NEW |