| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 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/window_positioner.h" | 5 #include "ash/wm/common/window_positioner.h" |
| 6 | 6 |
| 7 #include "ash/wm/common/window_positioning_utils.h" | 7 #include "ash/wm/common/window_positioning_utils.h" |
| 8 #include "ash/wm/common/window_state.h" | 8 #include "ash/wm/common/window_state.h" |
| 9 #include "ash/wm/common/wm_globals.h" | 9 #include "ash/wm/common/wm_globals.h" |
| 10 #include "ash/wm/common/wm_screen_util.h" | 10 #include "ash/wm/common/wm_screen_util.h" |
| 11 #include "ash/wm/common/wm_window.h" | 11 #include "ash/wm/common/wm_window.h" |
| 12 #include "ui/compositor/layer.h" | 12 #include "ui/compositor/layer.h" |
| 13 #include "ui/display/screen.h" | 13 #include "ui/display/screen.h" |
| 14 #include "ui/gfx/geometry/insets.h" | 14 #include "ui/gfx/geometry/insets.h" |
| 15 | 15 |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 101 if ((child_bounds.x() <= work_area.x() && | 101 if ((child_bounds.x() <= work_area.x() && |
| 102 new_child_bounds.x() <= work_area.x()) || | 102 new_child_bounds.x() <= work_area.x()) || |
| 103 (child_bounds.right() >= work_area.right() && | 103 (child_bounds.right() >= work_area.right() && |
| 104 new_child_bounds.right() >= work_area.right())) { | 104 new_child_bounds.right() >= work_area.right())) { |
| 105 continue; | 105 continue; |
| 106 } | 106 } |
| 107 if (new_child_bounds.right() > work_area.right()) | 107 if (new_child_bounds.right() > work_area.right()) |
| 108 new_child_bounds.set_x(work_area.right() - bounds.width()); | 108 new_child_bounds.set_x(work_area.right() - bounds.width()); |
| 109 else if (new_child_bounds.x() < work_area.x()) | 109 else if (new_child_bounds.x() < work_area.x()) |
| 110 new_child_bounds.set_x(work_area.x()); | 110 new_child_bounds.set_x(work_area.x()); |
| 111 SetBoundsAndOffsetTransientChildren(transient_child, | 111 SetBoundsAndOffsetTransientChildren(transient_child, new_child_bounds, |
| 112 new_child_bounds, work_area, offset); | 112 work_area, offset); |
| 113 } | 113 } |
| 114 | 114 |
| 115 window->SetBoundsWithTransitionDelay( | 115 window->SetBoundsWithTransitionDelay( |
| 116 bounds, base::TimeDelta::FromMilliseconds(kWindowAutoMoveDurationMS)); | 116 bounds, base::TimeDelta::FromMilliseconds(kWindowAutoMoveDurationMS)); |
| 117 } | 117 } |
| 118 | 118 |
| 119 // Move a |window| to new |bounds|. Animate if desired by user. | 119 // Move a |window| to new |bounds|. Animate if desired by user. |
| 120 // Note: The function will do nothing if the bounds did not change. | 120 // Note: The function will do nothing if the bounds did not change. |
| 121 void SetBoundsAnimated(wm::WmWindow* window, | 121 void SetBoundsAnimated(wm::WmWindow* window, |
| 122 const gfx::Rect& bounds, | 122 const gfx::Rect& bounds, |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 247 *show_state_out = ui::SHOW_STATE_MAXIMIZED; | 247 *show_state_out = ui::SHOW_STATE_MAXIMIZED; |
| 248 } | 248 } |
| 249 return; | 249 return; |
| 250 } | 250 } |
| 251 | 251 |
| 252 wm::WindowState* top_window_state = top_window->GetWindowState(); | 252 wm::WindowState* top_window_state = top_window->GetWindowState(); |
| 253 bool maximized = top_window_state->IsMaximized(); | 253 bool maximized = top_window_state->IsMaximized(); |
| 254 // We ignore the saved show state, but look instead for the top level | 254 // We ignore the saved show state, but look instead for the top level |
| 255 // window's show state. | 255 // window's show state. |
| 256 if (show_state_in == ui::SHOW_STATE_DEFAULT) { | 256 if (show_state_in == ui::SHOW_STATE_DEFAULT) { |
| 257 *show_state_out = maximized ? ui::SHOW_STATE_MAXIMIZED : | 257 *show_state_out = |
| 258 ui::SHOW_STATE_DEFAULT; | 258 maximized ? ui::SHOW_STATE_MAXIMIZED : ui::SHOW_STATE_DEFAULT; |
| 259 } | 259 } |
| 260 | 260 |
| 261 if (maximized || top_window_state->IsFullscreen()) { | 261 if (maximized || top_window_state->IsFullscreen()) { |
| 262 bool has_restore_bounds = top_window_state->HasRestoreBounds(); | 262 bool has_restore_bounds = top_window_state->HasRestoreBounds(); |
| 263 if (has_restore_bounds) { | 263 if (has_restore_bounds) { |
| 264 // For a maximized/fullscreen window ignore the real bounds of | 264 // For a maximized/fullscreen window ignore the real bounds of |
| 265 // the top level window and use its restore bounds | 265 // the top level window and use its restore bounds |
| 266 // instead. Offset the bounds to prevent the windows from | 266 // instead. Offset the bounds to prevent the windows from |
| 267 // overlapping exactly when restored. | 267 // overlapping exactly when restored. |
| 268 *bounds_in_out = top_window_state->GetRestoreBoundsInScreen() + | 268 *bounds_in_out = |
| 269 top_window_state->GetRestoreBoundsInScreen() + |
| 269 gfx::Vector2d(kMinimumWindowOffset, kMinimumWindowOffset); | 270 gfx::Vector2d(kMinimumWindowOffset, kMinimumWindowOffset); |
| 270 } | 271 } |
| 271 if (is_saved_bounds || has_restore_bounds) { | 272 if (is_saved_bounds || has_restore_bounds) { |
| 272 gfx::Rect work_area = target->GetDisplayNearestWindow().work_area(); | 273 gfx::Rect work_area = target->GetDisplayNearestWindow().work_area(); |
| 273 bounds_in_out->AdjustToFit(work_area); | 274 bounds_in_out->AdjustToFit(work_area); |
| 274 // Use adjusted saved bounds or restore bounds, if there is one. | 275 // Use adjusted saved bounds or restore bounds, if there is one. |
| 275 return; | 276 return; |
| 276 } | 277 } |
| 277 } | 278 } |
| 278 | 279 |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 375 | 376 |
| 376 WindowPositioner::WindowPositioner(wm::WmGlobals* globals) | 377 WindowPositioner::WindowPositioner(wm::WmGlobals* globals) |
| 377 : globals_(globals), | 378 : globals_(globals), |
| 378 pop_position_offset_increment_x(0), | 379 pop_position_offset_increment_x(0), |
| 379 pop_position_offset_increment_y(0), | 380 pop_position_offset_increment_y(0), |
| 380 popup_position_offset_from_screen_corner_x(0), | 381 popup_position_offset_from_screen_corner_x(0), |
| 381 popup_position_offset_from_screen_corner_y(0), | 382 popup_position_offset_from_screen_corner_y(0), |
| 382 last_popup_position_x_(0), | 383 last_popup_position_x_(0), |
| 383 last_popup_position_y_(0) {} | 384 last_popup_position_y_(0) {} |
| 384 | 385 |
| 385 WindowPositioner::~WindowPositioner() { | 386 WindowPositioner::~WindowPositioner() {} |
| 386 } | |
| 387 | 387 |
| 388 gfx::Rect WindowPositioner::GetDefaultWindowBounds( | 388 gfx::Rect WindowPositioner::GetDefaultWindowBounds( |
| 389 const display::Display& display) { | 389 const display::Display& display) { |
| 390 const gfx::Rect work_area = display.work_area(); | 390 const gfx::Rect work_area = display.work_area(); |
| 391 // There should be a 'desktop' border around the window at the left and right | 391 // There should be a 'desktop' border around the window at the left and right |
| 392 // side. | 392 // side. |
| 393 int default_width = work_area.width() - 2 * kDesktopBorderSize; | 393 int default_width = work_area.width() - 2 * kDesktopBorderSize; |
| 394 // There should also be a 'desktop' border around the window at the top. | 394 // There should also be a 'desktop' border around the window at the top. |
| 395 // Since the workspace excludes the tray area we only need one border size. | 395 // Since the workspace excludes the tray area we only need one border size. |
| 396 int default_height = work_area.height() - kDesktopBorderSize; | 396 int default_height = work_area.height() - kDesktopBorderSize; |
| 397 int offset_x = kDesktopBorderSize; | 397 int offset_x = kDesktopBorderSize; |
| 398 if (default_width > kMaximumWindowWidth) { | 398 if (default_width > kMaximumWindowWidth) { |
| 399 // The window should get centered on the screen and not follow the grid. | 399 // The window should get centered on the screen and not follow the grid. |
| 400 offset_x = (work_area.width() - kMaximumWindowWidth) / 2; | 400 offset_x = (work_area.width() - kMaximumWindowWidth) / 2; |
| 401 default_width = kMaximumWindowWidth; | 401 default_width = kMaximumWindowWidth; |
| 402 } | 402 } |
| 403 return gfx::Rect(work_area.x() + offset_x, | 403 return gfx::Rect(work_area.x() + offset_x, work_area.y() + kDesktopBorderSize, |
| 404 work_area.y() + kDesktopBorderSize, | 404 default_width, default_height); |
| 405 default_width, | |
| 406 default_height); | |
| 407 } | 405 } |
| 408 | 406 |
| 409 gfx::Rect WindowPositioner::GetPopupPosition(const gfx::Rect& old_pos) { | 407 gfx::Rect WindowPositioner::GetPopupPosition(const gfx::Rect& old_pos) { |
| 410 int grid = kMinimumWindowOffset; | 408 int grid = kMinimumWindowOffset; |
| 411 popup_position_offset_from_screen_corner_x = grid; | 409 popup_position_offset_from_screen_corner_x = grid; |
| 412 popup_position_offset_from_screen_corner_y = grid; | 410 popup_position_offset_from_screen_corner_y = grid; |
| 413 if (!pop_position_offset_increment_x) { | 411 if (!pop_position_offset_increment_x) { |
| 414 // When the popup position increment is 0, the last popup position | 412 // When the popup position increment is 0, the last popup position |
| 415 // was not yet initialized. | 413 // was not yet initialized. |
| 416 last_popup_position_x_ = popup_position_offset_from_screen_corner_x; | 414 last_popup_position_x_ = popup_position_offset_from_screen_corner_x; |
| 417 last_popup_position_y_ = popup_position_offset_from_screen_corner_y; | 415 last_popup_position_y_ = popup_position_offset_from_screen_corner_y; |
| 418 } | 416 } |
| 419 pop_position_offset_increment_x = grid; | 417 pop_position_offset_increment_x = grid; |
| 420 pop_position_offset_increment_y = grid; | 418 pop_position_offset_increment_y = grid; |
| 421 // We handle the Multi monitor support by retrieving the active window's | 419 // We handle the Multi monitor support by retrieving the active window's |
| 422 // work area. | 420 // work area. |
| 423 wm::WmWindow* window = globals_->GetActiveWindow(); | 421 wm::WmWindow* window = globals_->GetActiveWindow(); |
| 424 const gfx::Rect work_area = | 422 const gfx::Rect work_area = |
| 425 window && window->IsVisible() | 423 window && window->IsVisible() |
| 426 ? window->GetDisplayNearestWindow().work_area() | 424 ? window->GetDisplayNearestWindow().work_area() |
| 427 : display::Screen::GetScreen()->GetPrimaryDisplay().work_area(); | 425 : display::Screen::GetScreen()->GetPrimaryDisplay().work_area(); |
| 428 // Only try to reposition the popup when it is not spanning the entire | 426 // Only try to reposition the popup when it is not spanning the entire |
| 429 // screen. | 427 // screen. |
| 430 if ((old_pos.width() + popup_position_offset_from_screen_corner_x >= | 428 if ((old_pos.width() + popup_position_offset_from_screen_corner_x >= |
| 431 work_area.width()) || | 429 work_area.width()) || |
| 432 (old_pos.height() + popup_position_offset_from_screen_corner_y >= | 430 (old_pos.height() + popup_position_offset_from_screen_corner_y >= |
| 433 work_area.height())) | 431 work_area.height())) |
| 434 return AlignPopupPosition(old_pos, work_area, grid); | 432 return AlignPopupPosition(old_pos, work_area, grid); |
| 435 const gfx::Rect result = SmartPopupPosition(old_pos, work_area, grid); | 433 const gfx::Rect result = SmartPopupPosition(old_pos, work_area, grid); |
| 436 if (!result.IsEmpty()) | 434 if (!result.IsEmpty()) |
| 437 return AlignPopupPosition(result, work_area, grid); | 435 return AlignPopupPosition(result, work_area, grid); |
| 438 return NormalPopupPosition(old_pos, work_area); | 436 return NormalPopupPosition(old_pos, work_area); |
| 439 } | 437 } |
| 440 | 438 |
| 441 // static | 439 // static |
| 442 void WindowPositioner::SetMaximizeFirstWindow(bool maximize) { | 440 void WindowPositioner::SetMaximizeFirstWindow(bool maximize) { |
| 443 maximize_first_window = maximize; | 441 maximize_first_window = maximize; |
| 444 } | 442 } |
| 445 | 443 |
| 446 gfx::Rect WindowPositioner::NormalPopupPosition( | 444 gfx::Rect WindowPositioner::NormalPopupPosition(const gfx::Rect& old_pos, |
| 447 const gfx::Rect& old_pos, | 445 const gfx::Rect& work_area) { |
| 448 const gfx::Rect& work_area) { | |
| 449 int w = old_pos.width(); | 446 int w = old_pos.width(); |
| 450 int h = old_pos.height(); | 447 int h = old_pos.height(); |
| 451 // Note: The 'last_popup_position' is checked and kept relative to the | 448 // Note: The 'last_popup_position' is checked and kept relative to the |
| 452 // screen size. The offsetting will be done in the last step when the | 449 // screen size. The offsetting will be done in the last step when the |
| 453 // target rectangle gets returned. | 450 // target rectangle gets returned. |
| 454 bool reset = false; | 451 bool reset = false; |
| 455 if (last_popup_position_y_ + h > work_area.height() || | 452 if (last_popup_position_y_ + h > work_area.height() || |
| 456 last_popup_position_x_ + w > work_area.width()) { | 453 last_popup_position_x_ + w > work_area.width()) { |
| 457 // Popup does not fit on screen. Reset to next diagonal row. | 454 // Popup does not fit on screen. Reset to next diagonal row. |
| 458 last_popup_position_x_ -= last_popup_position_y_ - | 455 last_popup_position_x_ -= last_popup_position_y_ - |
| (...skipping 10 matching lines...) Expand all Loading... |
| 469 } | 466 } |
| 470 int x = last_popup_position_x_; | 467 int x = last_popup_position_x_; |
| 471 int y = last_popup_position_y_; | 468 int y = last_popup_position_y_; |
| 472 if (!reset) { | 469 if (!reset) { |
| 473 last_popup_position_x_ += pop_position_offset_increment_x; | 470 last_popup_position_x_ += pop_position_offset_increment_x; |
| 474 last_popup_position_y_ += pop_position_offset_increment_y; | 471 last_popup_position_y_ += pop_position_offset_increment_y; |
| 475 } | 472 } |
| 476 return gfx::Rect(x + work_area.x(), y + work_area.y(), w, h); | 473 return gfx::Rect(x + work_area.x(), y + work_area.y(), w, h); |
| 477 } | 474 } |
| 478 | 475 |
| 479 gfx::Rect WindowPositioner::SmartPopupPosition( | 476 gfx::Rect WindowPositioner::SmartPopupPosition(const gfx::Rect& old_pos, |
| 480 const gfx::Rect& old_pos, | 477 const gfx::Rect& work_area, |
| 481 const gfx::Rect& work_area, | 478 int grid) { |
| 482 int grid) { | |
| 483 const std::vector<wm::WmWindow*> windows = | 479 const std::vector<wm::WmWindow*> windows = |
| 484 globals_->GetMruWindowListIgnoreModals(); | 480 globals_->GetMruWindowListIgnoreModals(); |
| 485 | 481 |
| 486 std::vector<const gfx::Rect*> regions; | 482 std::vector<const gfx::Rect*> regions; |
| 487 // Process the window list and check if we can bail immediately. | 483 // Process the window list and check if we can bail immediately. |
| 488 for (size_t i = 0; i < windows.size(); i++) { | 484 for (size_t i = 0; i < windows.size(); i++) { |
| 489 // We only include opaque and visible windows. | 485 // We only include opaque and visible windows. |
| 490 if (windows[i] && windows[i]->IsVisible() && windows[i]->GetLayer() && | 486 if (windows[i] && windows[i]->IsVisible() && windows[i]->GetLayer() && |
| 491 (windows[i]->GetLayer()->fills_bounds_opaquely() || | 487 (windows[i]->GetLayer()->fills_bounds_opaquely() || |
| 492 windows[i]->GetLayer()->GetTargetOpacity() == 1.0)) { | 488 windows[i]->GetLayer()->GetTargetOpacity() == 1.0)) { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 509 // We parse for a proper location on the screen. We do this in two runs: | 505 // We parse for a proper location on the screen. We do this in two runs: |
| 510 // The first run will start from the left, parsing down, skipping any | 506 // The first run will start from the left, parsing down, skipping any |
| 511 // overlapping windows it will encounter until the popup's height can not | 507 // overlapping windows it will encounter until the popup's height can not |
| 512 // be served anymore. Then the next grid position to the right will be | 508 // be served anymore. Then the next grid position to the right will be |
| 513 // taken, and the same cycle starts again. This will be repeated until we | 509 // taken, and the same cycle starts again. This will be repeated until we |
| 514 // hit the middle of the screen (or we find a suitable location). | 510 // hit the middle of the screen (or we find a suitable location). |
| 515 // In the second run we parse beginning from the right corner downwards and | 511 // In the second run we parse beginning from the right corner downwards and |
| 516 // then to the left. | 512 // then to the left. |
| 517 // When no location was found, an empty rectangle will be returned. | 513 // When no location was found, an empty rectangle will be returned. |
| 518 for (int run = 0; run < 2; run++) { | 514 for (int run = 0; run < 2; run++) { |
| 519 if (run == 0) { // First run: Start left, parse right till mid screen. | 515 if (run == 0) { // First run: Start left, parse right till mid screen. |
| 520 x = 0; | 516 x = 0; |
| 521 x_increment = pop_position_offset_increment_x; | 517 x_increment = pop_position_offset_increment_x; |
| 522 } else { // Second run: Start right, parse left till mid screen. | 518 } else { // Second run: Start right, parse left till mid screen. |
| 523 x = work_area.width() - w; | 519 x = work_area.width() - w; |
| 524 x_increment = -pop_position_offset_increment_x; | 520 x_increment = -pop_position_offset_increment_x; |
| 525 } | 521 } |
| 526 // Note: The passing (x,y,w,h) window is always relative to the work area's | 522 // Note: The passing (x,y,w,h) window is always relative to the work area's |
| 527 // origin. | 523 // origin. |
| 528 for (; x_increment > 0 ? (x < x_end) : (x > x_end); x += x_increment) { | 524 for (; x_increment > 0 ? (x < x_end) : (x > x_end); x += x_increment) { |
| 529 int y = 0; | 525 int y = 0; |
| 530 while (y + h <= work_area.height()) { | 526 while (y + h <= work_area.height()) { |
| 531 size_t i; | 527 size_t i; |
| 532 for (i = 0; i < regions.size(); i++) { | 528 for (i = 0; i < regions.size(); i++) { |
| 533 if (regions[i]->Intersects(gfx::Rect(x + work_area.x(), | 529 if (regions[i]->Intersects( |
| 534 y + work_area.y(), w, h))) { | 530 gfx::Rect(x + work_area.x(), y + work_area.y(), w, h))) { |
| 535 y = regions[i]->bottom() - work_area.y(); | 531 y = regions[i]->bottom() - work_area.y(); |
| 536 break; | 532 break; |
| 537 } | 533 } |
| 538 } | 534 } |
| 539 if (i >= regions.size()) | 535 if (i >= regions.size()) |
| 540 return gfx::Rect(x + work_area.x(), y + work_area.y(), w, h); | 536 return gfx::Rect(x + work_area.x(), y + work_area.y(), w, h); |
| 541 } | 537 } |
| 542 } | 538 } |
| 543 } | 539 } |
| 544 return gfx::Rect(0, 0, 0, 0); | 540 return gfx::Rect(0, 0, 0, 0); |
| 545 } | 541 } |
| 546 | 542 |
| 547 gfx::Rect WindowPositioner::AlignPopupPosition( | 543 gfx::Rect WindowPositioner::AlignPopupPosition(const gfx::Rect& pos, |
| 548 const gfx::Rect& pos, | 544 const gfx::Rect& work_area, |
| 549 const gfx::Rect& work_area, | 545 int grid) { |
| 550 int grid) { | |
| 551 if (grid <= 1) | 546 if (grid <= 1) |
| 552 return pos; | 547 return pos; |
| 553 | 548 |
| 554 int x = pos.x() - (pos.x() - work_area.x()) % grid; | 549 int x = pos.x() - (pos.x() - work_area.x()) % grid; |
| 555 int y = pos.y() - (pos.y() - work_area.y()) % grid; | 550 int y = pos.y() - (pos.y() - work_area.y()) % grid; |
| 556 int w = pos.width(); | 551 int w = pos.width(); |
| 557 int h = pos.height(); | 552 int h = pos.height(); |
| 558 | 553 |
| 559 // If the alignment was pushing the window out of the screen, we ignore the | 554 // If the alignment was pushing the window out of the screen, we ignore the |
| 560 // alignment for that call. | 555 // alignment for that call. |
| 561 if (abs(pos.right() - work_area.right()) < grid) | 556 if (abs(pos.right() - work_area.right()) < grid) |
| 562 x = work_area.right() - w; | 557 x = work_area.right() - w; |
| 563 if (abs(pos.bottom() - work_area.bottom()) < grid) | 558 if (abs(pos.bottom() - work_area.bottom()) < grid) |
| 564 y = work_area.bottom() - h; | 559 y = work_area.bottom() - h; |
| 565 return gfx::Rect(x, y, w, h); | 560 return gfx::Rect(x, y, w, h); |
| 566 } | 561 } |
| 567 | 562 |
| 568 } // namespace ash | 563 } // namespace ash |
| OLD | NEW |