| 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/wm/workspace/workspace_window_resizer.h" | 5 #include "ash/wm/workspace/workspace_window_resizer.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <cmath> | 8 #include <cmath> |
| 9 #include <utility> | 9 #include <utility> |
| 10 #include <vector> | 10 #include <vector> |
| (...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 360 } else if ((details().bounds_change & kBoundsChange_Resizes) && | 360 } else if ((details().bounds_change & kBoundsChange_Resizes) && |
| 361 details().source == aura::client::WINDOW_MOVE_SOURCE_TOUCH) { | 361 details().source == aura::client::WINDOW_MOVE_SOURCE_TOUCH) { |
| 362 sticky_size = kScreenEdgeInsetForTouchDrag; | 362 sticky_size = kScreenEdgeInsetForTouchDrag; |
| 363 } else { | 363 } else { |
| 364 sticky_size = kScreenEdgeInset; | 364 sticky_size = kScreenEdgeInset; |
| 365 } | 365 } |
| 366 // |bounds| is in |GetTarget()->parent()|'s coordinates. | 366 // |bounds| is in |GetTarget()->parent()|'s coordinates. |
| 367 gfx::Rect bounds = CalculateBoundsForDrag(location_in_parent); | 367 gfx::Rect bounds = CalculateBoundsForDrag(location_in_parent); |
| 368 AdjustBoundsForMainWindow(sticky_size, &bounds); | 368 AdjustBoundsForMainWindow(sticky_size, &bounds); |
| 369 | 369 |
| 370 if (bounds != GetTarget()->bounds()) { | 370 if (bounds != GetAuraTarget()->bounds()) { |
| 371 if (!did_move_or_resize_) { | 371 if (!did_move_or_resize_) { |
| 372 if (!details().restore_bounds.IsEmpty()) | 372 if (!details().restore_bounds.IsEmpty()) |
| 373 window_state()->ClearRestoreBounds(); | 373 window_state()->ClearRestoreBounds(); |
| 374 RestackWindows(); | 374 RestackWindows(); |
| 375 } | 375 } |
| 376 did_move_or_resize_ = true; | 376 did_move_or_resize_ = true; |
| 377 } | 377 } |
| 378 | 378 |
| 379 gfx::Point location_in_screen = location_in_parent; | 379 gfx::Point location_in_screen = location_in_parent; |
| 380 ::wm::ConvertPointToScreen(GetTarget()->parent(), &location_in_screen); | 380 ::wm::ConvertPointToScreen(GetAuraTarget()->parent(), &location_in_screen); |
| 381 | 381 |
| 382 aura::Window* root = NULL; | 382 aura::Window* root = NULL; |
| 383 gfx::Display display = | 383 gfx::Display display = |
| 384 ScreenUtil::FindDisplayContainingPoint(location_in_screen); | 384 ScreenUtil::FindDisplayContainingPoint(location_in_screen); |
| 385 // Track the last screen that the pointer was on to keep the snap phantom | 385 // Track the last screen that the pointer was on to keep the snap phantom |
| 386 // window there. | 386 // window there. |
| 387 if (display.is_valid()) { | 387 if (display.is_valid()) { |
| 388 root = Shell::GetInstance() | 388 root = Shell::GetInstance() |
| 389 ->window_tree_host_manager() | 389 ->window_tree_host_manager() |
| 390 ->GetRootWindowForDisplayId(display.id()); | 390 ->GetRootWindowForDisplayId(display.id()); |
| 391 } | 391 } |
| 392 if (!attached_windows_.empty()) | 392 if (!attached_windows_.empty()) |
| 393 LayoutAttachedWindows(&bounds); | 393 LayoutAttachedWindows(&bounds); |
| 394 if (bounds != GetTarget()->bounds()) { | 394 if (bounds != GetAuraTarget()->bounds()) { |
| 395 // SetBounds needs to be called to update the layout which affects where the | 395 // SetBounds needs to be called to update the layout which affects where the |
| 396 // phantom window is drawn. Keep track if the window was destroyed during | 396 // phantom window is drawn. Keep track if the window was destroyed during |
| 397 // the drag and quit early if so. | 397 // the drag and quit early if so. |
| 398 base::WeakPtr<WorkspaceWindowResizer> resizer( | 398 base::WeakPtr<WorkspaceWindowResizer> resizer( |
| 399 weak_ptr_factory_.GetWeakPtr()); | 399 weak_ptr_factory_.GetWeakPtr()); |
| 400 GetTarget()->SetBounds(bounds); | 400 GetAuraTarget()->SetBounds(bounds); |
| 401 if (!resizer) | 401 if (!resizer) |
| 402 return; | 402 return; |
| 403 } | 403 } |
| 404 const bool in_original_root = !root || root == GetTarget()->GetRootWindow(); | 404 const bool in_original_root = |
| 405 !root || root == GetAuraTarget()->GetRootWindow(); |
| 405 // Hide a phantom window for snapping if the cursor is in another root window. | 406 // Hide a phantom window for snapping if the cursor is in another root window. |
| 406 if (in_original_root) { | 407 if (in_original_root) { |
| 407 UpdateSnapPhantomWindow(location_in_parent, bounds); | 408 UpdateSnapPhantomWindow(location_in_parent, bounds); |
| 408 } else { | 409 } else { |
| 409 snap_type_ = SNAP_NONE; | 410 snap_type_ = SNAP_NONE; |
| 410 snap_phantom_window_controller_.reset(); | 411 snap_phantom_window_controller_.reset(); |
| 411 edge_cycler_.reset(); | 412 edge_cycler_.reset(); |
| 412 SetDraggedWindowDocked(false); | 413 SetDraggedWindowDocked(false); |
| 413 } | 414 } |
| 414 } | 415 } |
| 415 | 416 |
| 416 void WorkspaceWindowResizer::CompleteDrag() { | 417 void WorkspaceWindowResizer::CompleteDrag() { |
| 417 if (!did_move_or_resize_) | 418 if (!did_move_or_resize_) |
| 418 return; | 419 return; |
| 419 | 420 |
| 420 window_state()->set_bounds_changed_by_user(true); | 421 window_state()->set_bounds_changed_by_user(true); |
| 421 snap_phantom_window_controller_.reset(); | 422 snap_phantom_window_controller_.reset(); |
| 422 | 423 |
| 423 // If the window's state type changed over the course of the drag do not snap | 424 // If the window's state type changed over the course of the drag do not snap |
| 424 // the window. This happens when the user minimizes or maximizes the window | 425 // the window. This happens when the user minimizes or maximizes the window |
| 425 // using a keyboard shortcut while dragging it. | 426 // using a keyboard shortcut while dragging it. |
| 426 if (window_state()->GetStateType() != details().initial_state_type) | 427 if (window_state()->GetStateType() != details().initial_state_type) |
| 427 return; | 428 return; |
| 428 | 429 |
| 429 bool snapped = false; | 430 bool snapped = false; |
| 430 if (snap_type_ == SNAP_LEFT || snap_type_ == SNAP_RIGHT) { | 431 if (snap_type_ == SNAP_LEFT || snap_type_ == SNAP_RIGHT) { |
| 431 if (!window_state()->HasRestoreBounds()) { | 432 if (!window_state()->HasRestoreBounds()) { |
| 432 gfx::Rect initial_bounds = ScreenUtil::ConvertRectToScreen( | 433 gfx::Rect initial_bounds = ScreenUtil::ConvertRectToScreen( |
| 433 GetTarget()->parent(), details().initial_bounds_in_parent); | 434 GetAuraTarget()->parent(), details().initial_bounds_in_parent); |
| 434 window_state()->SetRestoreBoundsInScreen( | 435 window_state()->SetRestoreBoundsInScreen( |
| 435 details().restore_bounds.IsEmpty() ? | 436 details().restore_bounds.IsEmpty() ? |
| 436 initial_bounds : | 437 initial_bounds : |
| 437 details().restore_bounds); | 438 details().restore_bounds); |
| 438 } | 439 } |
| 439 if (!dock_layout_->is_dragged_window_docked()) { | 440 if (!dock_layout_->is_dragged_window_docked()) { |
| 440 UserMetricsRecorder* metrics = Shell::GetInstance()->metrics(); | 441 UserMetricsRecorder* metrics = Shell::GetInstance()->metrics(); |
| 441 // TODO(oshima): Add event source type to WMEvent and move | 442 // TODO(oshima): Add event source type to WMEvent and move |
| 442 // metrics recording inside WindowState::OnWMEvent. | 443 // metrics recording inside WindowState::OnWMEvent. |
| 443 const wm::WMEvent event(snap_type_ == SNAP_LEFT ? | 444 const wm::WMEvent event(snap_type_ == SNAP_LEFT ? |
| 444 wm::WM_EVENT_SNAP_LEFT : wm::WM_EVENT_SNAP_RIGHT); | 445 wm::WM_EVENT_SNAP_LEFT : wm::WM_EVENT_SNAP_RIGHT); |
| 445 window_state()->OnWMEvent(&event); | 446 window_state()->OnWMEvent(&event); |
| 446 metrics->RecordUserMetricsAction( | 447 metrics->RecordUserMetricsAction( |
| 447 snap_type_ == SNAP_LEFT ? | 448 snap_type_ == SNAP_LEFT ? |
| 448 UMA_DRAG_MAXIMIZE_LEFT : UMA_DRAG_MAXIMIZE_RIGHT); | 449 UMA_DRAG_MAXIMIZE_LEFT : UMA_DRAG_MAXIMIZE_RIGHT); |
| 449 snapped = true; | 450 snapped = true; |
| 450 } | 451 } |
| 451 } | 452 } |
| 452 | 453 |
| 453 if (!snapped) { | 454 if (!snapped) { |
| 454 if (window_state()->IsSnapped()) { | 455 if (window_state()->IsSnapped()) { |
| 455 // Keep the window snapped if the user resizes the window such that the | 456 // Keep the window snapped if the user resizes the window such that the |
| 456 // window has valid bounds for a snapped window. Always unsnap the window | 457 // window has valid bounds for a snapped window. Always unsnap the window |
| 457 // if the user dragged the window via the caption area because doing this | 458 // if the user dragged the window via the caption area because doing this |
| 458 // is slightly less confusing. | 459 // is slightly less confusing. |
| 459 if (details().window_component == HTCAPTION || | 460 if (details().window_component == HTCAPTION || |
| 460 !AreBoundsValidSnappedBounds(window_state()->GetStateType(), | 461 !AreBoundsValidSnappedBounds(window_state()->GetStateType(), |
| 461 GetTarget()->bounds())) { | 462 GetAuraTarget()->bounds())) { |
| 462 // Set the window to WINDOW_STATE_TYPE_NORMAL but keep the | 463 // Set the window to WINDOW_STATE_TYPE_NORMAL but keep the |
| 463 // window at the bounds that the user has moved/resized the | 464 // window at the bounds that the user has moved/resized the |
| 464 // window to. ClearRestoreBounds() is used instead of | 465 // window to. ClearRestoreBounds() is used instead of |
| 465 // SaveCurrentBoundsForRestore() because most of the restore | 466 // SaveCurrentBoundsForRestore() because most of the restore |
| 466 // logic is skipped because we are still in the middle of a | 467 // logic is skipped because we are still in the middle of a |
| 467 // drag. TODO(pkotwicz): Fix this and use | 468 // drag. TODO(pkotwicz): Fix this and use |
| 468 // SaveCurrentBoundsForRestore(). | 469 // SaveCurrentBoundsForRestore(). |
| 469 window_state()->ClearRestoreBounds(); | 470 window_state()->ClearRestoreBounds(); |
| 470 window_state()->Restore(); | 471 window_state()->Restore(); |
| 471 } | 472 } |
| 472 } else if (!dock_layout_->is_dragged_window_docked()) { | 473 } else if (!dock_layout_->is_dragged_window_docked()) { |
| 473 // The window was not snapped and is not snapped. This is a user | 474 // The window was not snapped and is not snapped. This is a user |
| 474 // resize/drag and so the current bounds should be maintained, clearing | 475 // resize/drag and so the current bounds should be maintained, clearing |
| 475 // any prior restore bounds. When the window is docked the restore bound | 476 // any prior restore bounds. When the window is docked the restore bound |
| 476 // must be kept so the docked state can be reverted properly. | 477 // must be kept so the docked state can be reverted properly. |
| 477 window_state()->ClearRestoreBounds(); | 478 window_state()->ClearRestoreBounds(); |
| 478 } | 479 } |
| 479 } | 480 } |
| 480 } | 481 } |
| 481 | 482 |
| 482 void WorkspaceWindowResizer::RevertDrag() { | 483 void WorkspaceWindowResizer::RevertDrag() { |
| 483 window_state()->set_bounds_changed_by_user(initial_bounds_changed_by_user_); | 484 window_state()->set_bounds_changed_by_user(initial_bounds_changed_by_user_); |
| 484 snap_phantom_window_controller_.reset(); | 485 snap_phantom_window_controller_.reset(); |
| 485 | 486 |
| 486 if (!did_move_or_resize_) | 487 if (!did_move_or_resize_) |
| 487 return; | 488 return; |
| 488 | 489 |
| 489 GetTarget()->SetBounds(details().initial_bounds_in_parent); | 490 GetAuraTarget()->SetBounds(details().initial_bounds_in_parent); |
| 490 if (!details().restore_bounds.IsEmpty()) { | 491 if (!details().restore_bounds.IsEmpty()) { |
| 491 window_state()->SetRestoreBoundsInScreen(details().restore_bounds); | 492 window_state()->SetRestoreBoundsInScreen(details().restore_bounds); |
| 492 } | 493 } |
| 493 | 494 |
| 494 if (details().window_component == HTRIGHT) { | 495 if (details().window_component == HTRIGHT) { |
| 495 int last_x = details().initial_bounds_in_parent.right(); | 496 int last_x = details().initial_bounds_in_parent.right(); |
| 496 for (size_t i = 0; i < attached_windows_.size(); ++i) { | 497 for (size_t i = 0; i < attached_windows_.size(); ++i) { |
| 497 gfx::Rect bounds(attached_windows_[i]->bounds()); | 498 gfx::Rect bounds(attached_windows_[i]->bounds()); |
| 498 bounds.set_x(last_x); | 499 bounds.set_x(last_x); |
| 499 bounds.set_width(initial_size_[i]); | 500 bounds.set_width(initial_size_[i]); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 530 | 531 |
| 531 // A mousemove should still show the cursor even if the window is | 532 // A mousemove should still show the cursor even if the window is |
| 532 // being moved or resized with touch, so do not lock the cursor. | 533 // being moved or resized with touch, so do not lock the cursor. |
| 533 if (details().source != aura::client::WINDOW_MOVE_SOURCE_TOUCH) { | 534 if (details().source != aura::client::WINDOW_MOVE_SOURCE_TOUCH) { |
| 534 Shell* shell = Shell::GetInstance(); | 535 Shell* shell = Shell::GetInstance(); |
| 535 shell->cursor_manager()->LockCursor(); | 536 shell->cursor_manager()->LockCursor(); |
| 536 did_lock_cursor_ = true; | 537 did_lock_cursor_ = true; |
| 537 } | 538 } |
| 538 | 539 |
| 539 aura::Window* dock_container = Shell::GetContainer( | 540 aura::Window* dock_container = Shell::GetContainer( |
| 540 GetTarget()->GetRootWindow(), kShellWindowId_DockedContainer); | 541 GetAuraTarget()->GetRootWindow(), kShellWindowId_DockedContainer); |
| 541 dock_layout_ = static_cast<DockedWindowLayoutManager*>( | 542 dock_layout_ = static_cast<DockedWindowLayoutManager*>( |
| 542 dock_container->layout_manager()); | 543 dock_container->layout_manager()); |
| 543 | 544 |
| 544 // Only support attaching to the right/bottom. | 545 // Only support attaching to the right/bottom. |
| 545 DCHECK(attached_windows_.empty() || | 546 DCHECK(attached_windows_.empty() || |
| 546 (details().window_component == HTRIGHT || | 547 (details().window_component == HTRIGHT || |
| 547 details().window_component == HTBOTTOM)); | 548 details().window_component == HTBOTTOM)); |
| 548 | 549 |
| 549 // TODO: figure out how to deal with window going off the edge. | 550 // TODO: figure out how to deal with window going off the edge. |
| 550 | 551 |
| 551 // Calculate sizes so that we can maintain the ratios if we need to resize. | 552 // Calculate sizes so that we can maintain the ratios if we need to resize. |
| 552 int total_available = 0; | 553 int total_available = 0; |
| 553 for (size_t i = 0; i < attached_windows_.size(); ++i) { | 554 for (size_t i = 0; i < attached_windows_.size(); ++i) { |
| 554 gfx::Size min(attached_windows_[i]->delegate()->GetMinimumSize()); | 555 gfx::Size min(attached_windows_[i]->delegate()->GetMinimumSize()); |
| 555 int initial_size = PrimaryAxisSize(attached_windows_[i]->bounds().size()); | 556 int initial_size = PrimaryAxisSize(attached_windows_[i]->bounds().size()); |
| 556 initial_size_.push_back(initial_size); | 557 initial_size_.push_back(initial_size); |
| 557 // If current size is smaller than the min, use the current size as the min. | 558 // If current size is smaller than the min, use the current size as the min. |
| 558 // This way we don't snap on resize. | 559 // This way we don't snap on resize. |
| 559 int min_size = std::min(initial_size, | 560 int min_size = std::min(initial_size, |
| 560 std::max(PrimaryAxisSize(min), kMinOnscreenSize)); | 561 std::max(PrimaryAxisSize(min), kMinOnscreenSize)); |
| 561 total_min_ += min_size; | 562 total_min_ += min_size; |
| 562 total_initial_size_ += initial_size; | 563 total_initial_size_ += initial_size; |
| 563 total_available += std::max(min_size, initial_size) - min_size; | 564 total_available += std::max(min_size, initial_size) - min_size; |
| 564 } | 565 } |
| 565 instance = this; | 566 instance = this; |
| 566 } | 567 } |
| 567 | 568 |
| 568 void WorkspaceWindowResizer::LayoutAttachedWindows( | 569 void WorkspaceWindowResizer::LayoutAttachedWindows( |
| 569 gfx::Rect* bounds) { | 570 gfx::Rect* bounds) { |
| 570 gfx::Rect work_area(ScreenUtil::GetDisplayWorkAreaBoundsInParent( | 571 gfx::Rect work_area( |
| 571 GetTarget())); | 572 ScreenUtil::GetDisplayWorkAreaBoundsInParent(GetAuraTarget())); |
| 572 int initial_size = PrimaryAxisSize(details().initial_bounds_in_parent.size()); | 573 int initial_size = PrimaryAxisSize(details().initial_bounds_in_parent.size()); |
| 573 int current_size = PrimaryAxisSize(bounds->size()); | 574 int current_size = PrimaryAxisSize(bounds->size()); |
| 574 int start = PrimaryAxisCoordinate(bounds->right(), bounds->bottom()); | 575 int start = PrimaryAxisCoordinate(bounds->right(), bounds->bottom()); |
| 575 int end = PrimaryAxisCoordinate(work_area.right(), work_area.bottom()); | 576 int end = PrimaryAxisCoordinate(work_area.right(), work_area.bottom()); |
| 576 | 577 |
| 577 int delta = current_size - initial_size; | 578 int delta = current_size - initial_size; |
| 578 int available_size = end - start; | 579 int available_size = end - start; |
| 579 std::vector<int> sizes; | 580 std::vector<int> sizes; |
| 580 int leftovers = CalculateAttachedSizes(delta, available_size, &sizes); | 581 int leftovers = CalculateAttachedSizes(delta, available_size, &sizes); |
| 581 | 582 |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 701 int min = PrimaryAxisSize(delegate->GetMinimumSize()); | 702 int min = PrimaryAxisSize(delegate->GetMinimumSize()); |
| 702 int max = PrimaryAxisSize(delegate->GetMaximumSize()); | 703 int max = PrimaryAxisSize(delegate->GetMaximumSize()); |
| 703 | 704 |
| 704 sizes->push_back(WindowSize(initial_size, min, max)); | 705 sizes->push_back(WindowSize(initial_size, min, max)); |
| 705 } | 706 } |
| 706 } | 707 } |
| 707 | 708 |
| 708 void WorkspaceWindowResizer::MagneticallySnapToOtherWindows(gfx::Rect* bounds) { | 709 void WorkspaceWindowResizer::MagneticallySnapToOtherWindows(gfx::Rect* bounds) { |
| 709 if (UpdateMagnetismWindow(*bounds, kAllMagnetismEdges)) { | 710 if (UpdateMagnetismWindow(*bounds, kAllMagnetismEdges)) { |
| 710 gfx::Point point = OriginForMagneticAttach( | 711 gfx::Point point = OriginForMagneticAttach( |
| 711 ScreenUtil::ConvertRectToScreen(GetTarget()->parent(), *bounds), | 712 ScreenUtil::ConvertRectToScreen(GetAuraTarget()->parent(), *bounds), |
| 712 magnetism_window_->GetBoundsInScreen(), | 713 magnetism_window_->GetBoundsInScreen(), magnetism_edge_); |
| 713 magnetism_edge_); | 714 aura::client::GetScreenPositionClient(GetAuraTarget()->GetRootWindow()) |
| 714 aura::client::GetScreenPositionClient(GetTarget()->GetRootWindow())-> | 715 ->ConvertPointFromScreen(GetAuraTarget()->parent(), &point); |
| 715 ConvertPointFromScreen(GetTarget()->parent(), &point); | |
| 716 bounds->set_origin(point); | 716 bounds->set_origin(point); |
| 717 } | 717 } |
| 718 } | 718 } |
| 719 | 719 |
| 720 void WorkspaceWindowResizer::MagneticallySnapResizeToOtherWindows( | 720 void WorkspaceWindowResizer::MagneticallySnapResizeToOtherWindows( |
| 721 gfx::Rect* bounds) { | 721 gfx::Rect* bounds) { |
| 722 const uint32_t edges = | 722 const uint32_t edges = |
| 723 WindowComponentToMagneticEdge(details().window_component); | 723 WindowComponentToMagneticEdge(details().window_component); |
| 724 if (UpdateMagnetismWindow(*bounds, edges)) { | 724 if (UpdateMagnetismWindow(*bounds, edges)) { |
| 725 *bounds = ScreenUtil::ConvertRectFromScreen( | 725 *bounds = ScreenUtil::ConvertRectFromScreen( |
| 726 GetTarget()->parent(), | 726 GetAuraTarget()->parent(), |
| 727 BoundsForMagneticResizeAttach( | 727 BoundsForMagneticResizeAttach( |
| 728 ScreenUtil::ConvertRectToScreen(GetTarget()->parent(), *bounds), | 728 ScreenUtil::ConvertRectToScreen(GetAuraTarget()->parent(), *bounds), |
| 729 magnetism_window_->GetBoundsInScreen(), | 729 magnetism_window_->GetBoundsInScreen(), magnetism_edge_)); |
| 730 magnetism_edge_)); | |
| 731 } | 730 } |
| 732 } | 731 } |
| 733 | 732 |
| 734 bool WorkspaceWindowResizer::UpdateMagnetismWindow(const gfx::Rect& bounds, | 733 bool WorkspaceWindowResizer::UpdateMagnetismWindow(const gfx::Rect& bounds, |
| 735 uint32_t edges) { | 734 uint32_t edges) { |
| 736 // |bounds| are in coordinates of original window's parent. | 735 // |bounds| are in coordinates of original window's parent. |
| 737 gfx::Rect bounds_in_screen = | 736 gfx::Rect bounds_in_screen = |
| 738 ScreenUtil::ConvertRectToScreen(GetTarget()->parent(), bounds); | 737 ScreenUtil::ConvertRectToScreen(GetAuraTarget()->parent(), bounds); |
| 739 MagnetismMatcher matcher(bounds_in_screen, edges); | 738 MagnetismMatcher matcher(bounds_in_screen, edges); |
| 740 | 739 |
| 741 // If we snapped to a window then check it first. That way we don't bounce | 740 // If we snapped to a window then check it first. That way we don't bounce |
| 742 // around when close to multiple edges. | 741 // around when close to multiple edges. |
| 743 if (magnetism_window_) { | 742 if (magnetism_window_) { |
| 744 if (window_tracker_.Contains(magnetism_window_) && | 743 if (window_tracker_.Contains(magnetism_window_) && |
| 745 matcher.ShouldAttach(magnetism_window_->GetBoundsInScreen(), | 744 matcher.ShouldAttach(magnetism_window_->GetBoundsInScreen(), |
| 746 &magnetism_edge_)) { | 745 &magnetism_edge_)) { |
| 747 return true; | 746 return true; |
| 748 } | 747 } |
| 749 window_tracker_.Remove(magnetism_window_); | 748 window_tracker_.Remove(magnetism_window_); |
| 750 magnetism_window_ = NULL; | 749 magnetism_window_ = NULL; |
| 751 } | 750 } |
| 752 | 751 |
| 753 // Avoid magnetically snapping windows that are not resizable. | 752 // Avoid magnetically snapping windows that are not resizable. |
| 754 // TODO(oshima): change this to window.type() == TYPE_NORMAL. | 753 // TODO(oshima): change this to window.type() == TYPE_NORMAL. |
| 755 if (!window_state()->CanResize()) | 754 if (!window_state()->CanResize()) |
| 756 return false; | 755 return false; |
| 757 | 756 |
| 758 aura::Window::Windows root_windows = Shell::GetAllRootWindows(); | 757 aura::Window::Windows root_windows = Shell::GetAllRootWindows(); |
| 759 for (aura::Window::Windows::iterator iter = root_windows.begin(); | 758 for (aura::Window::Windows::iterator iter = root_windows.begin(); |
| 760 iter != root_windows.end(); ++iter) { | 759 iter != root_windows.end(); ++iter) { |
| 761 const aura::Window* root_window = *iter; | 760 const aura::Window* root_window = *iter; |
| 762 // Test all children from the desktop in each root window. | 761 // Test all children from the desktop in each root window. |
| 763 const aura::Window::Windows& children = Shell::GetContainer( | 762 const aura::Window::Windows& children = Shell::GetContainer( |
| 764 root_window, kShellWindowId_DefaultContainer)->children(); | 763 root_window, kShellWindowId_DefaultContainer)->children(); |
| 765 for (aura::Window::Windows::const_reverse_iterator i = children.rbegin(); | 764 for (aura::Window::Windows::const_reverse_iterator i = children.rbegin(); |
| 766 i != children.rend() && !matcher.AreEdgesObscured(); ++i) { | 765 i != children.rend() && !matcher.AreEdgesObscured(); ++i) { |
| 767 wm::WindowState* other_state = wm::GetWindowState(*i); | 766 wm::WindowState* other_state = wm::GetWindowState(*i); |
| 768 if (other_state->aura_window() == GetTarget() || | 767 if (other_state->aura_window() == GetAuraTarget() || |
| 769 !other_state->window()->IsVisible() || | 768 !other_state->window()->IsVisible() || |
| 770 !other_state->IsNormalOrSnapped() || !other_state->CanResize()) { | 769 !other_state->IsNormalOrSnapped() || !other_state->CanResize()) { |
| 771 continue; | 770 continue; |
| 772 } | 771 } |
| 773 if (matcher.ShouldAttach( | 772 if (matcher.ShouldAttach( |
| 774 other_state->window()->GetBoundsInScreen(), &magnetism_edge_)) { | 773 other_state->window()->GetBoundsInScreen(), &magnetism_edge_)) { |
| 775 magnetism_window_ = other_state->aura_window(); | 774 magnetism_window_ = other_state->aura_window(); |
| 776 window_tracker_.Add(magnetism_window_); | 775 window_tracker_.Add(magnetism_window_); |
| 777 return true; | 776 return true; |
| 778 } | 777 } |
| 779 } | 778 } |
| 780 } | 779 } |
| 781 return false; | 780 return false; |
| 782 } | 781 } |
| 783 | 782 |
| 784 void WorkspaceWindowResizer::AdjustBoundsForMainWindow( | 783 void WorkspaceWindowResizer::AdjustBoundsForMainWindow( |
| 785 int sticky_size, | 784 int sticky_size, |
| 786 gfx::Rect* bounds) { | 785 gfx::Rect* bounds) { |
| 787 gfx::Point last_mouse_location_in_screen = last_mouse_location_; | 786 gfx::Point last_mouse_location_in_screen = last_mouse_location_; |
| 788 ::wm::ConvertPointToScreen(GetTarget()->parent(), | 787 ::wm::ConvertPointToScreen(GetAuraTarget()->parent(), |
| 789 &last_mouse_location_in_screen); | 788 &last_mouse_location_in_screen); |
| 790 gfx::Display display = gfx::Screen::GetScreen()->GetDisplayNearestPoint( | 789 gfx::Display display = gfx::Screen::GetScreen()->GetDisplayNearestPoint( |
| 791 last_mouse_location_in_screen); | 790 last_mouse_location_in_screen); |
| 792 gfx::Rect work_area = | 791 gfx::Rect work_area = ScreenUtil::ConvertRectFromScreen( |
| 793 ScreenUtil::ConvertRectFromScreen(GetTarget()->parent(), | 792 GetAuraTarget()->parent(), display.work_area()); |
| 794 display.work_area()); | |
| 795 if (details().window_component == HTCAPTION) { | 793 if (details().window_component == HTCAPTION) { |
| 796 // Adjust the bounds to the work area where the mouse cursor is located. | 794 // Adjust the bounds to the work area where the mouse cursor is located. |
| 797 // Always keep kMinOnscreenHeight or the window height (whichever is less) | 795 // Always keep kMinOnscreenHeight or the window height (whichever is less) |
| 798 // on the bottom. | 796 // on the bottom. |
| 799 int max_y = work_area.bottom() - std::min(kMinOnscreenHeight, | 797 int max_y = work_area.bottom() - std::min(kMinOnscreenHeight, |
| 800 bounds->height()); | 798 bounds->height()); |
| 801 if (bounds->y() > max_y) { | 799 if (bounds->y() > max_y) { |
| 802 bounds->set_y(max_y); | 800 bounds->set_y(max_y); |
| 803 } else if (bounds->y() <= work_area.y()) { | 801 } else if (bounds->y() <= work_area.y()) { |
| 804 // Don't allow dragging above the top of the display until the mouse | 802 // Don't allow dragging above the top of the display until the mouse |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 921 if (snap_type_ == SNAP_NONE) { | 919 if (snap_type_ == SNAP_NONE) { |
| 922 SetDraggedWindowDocked(false); | 920 SetDraggedWindowDocked(false); |
| 923 return; | 921 return; |
| 924 } | 922 } |
| 925 } | 923 } |
| 926 | 924 |
| 927 DCHECK(snap_type_ == SNAP_LEFT || snap_type_ == SNAP_RIGHT); | 925 DCHECK(snap_type_ == SNAP_LEFT || snap_type_ == SNAP_RIGHT); |
| 928 DockedAlignment desired_alignment = (snap_type_ == SNAP_LEFT) ? | 926 DockedAlignment desired_alignment = (snap_type_ == SNAP_LEFT) ? |
| 929 DOCKED_ALIGNMENT_LEFT : DOCKED_ALIGNMENT_RIGHT; | 927 DOCKED_ALIGNMENT_LEFT : DOCKED_ALIGNMENT_RIGHT; |
| 930 const bool can_dock = | 928 const bool can_dock = |
| 931 dock_layout_->CanDockWindow(GetTarget(), desired_alignment) && | 929 dock_layout_->CanDockWindow(GetAuraTarget(), desired_alignment) && |
| 932 dock_layout_->GetAlignmentOfWindow(GetTarget()) != DOCKED_ALIGNMENT_NONE; | 930 dock_layout_->GetAlignmentOfWindow(GetAuraTarget()) != |
| 931 DOCKED_ALIGNMENT_NONE; |
| 933 if (!can_dock) { | 932 if (!can_dock) { |
| 934 // If the window cannot be docked, undock the window. This may change the | 933 // If the window cannot be docked, undock the window. This may change the |
| 935 // workspace bounds and hence |snap_type_|. | 934 // workspace bounds and hence |snap_type_|. |
| 936 SetDraggedWindowDocked(false); | 935 SetDraggedWindowDocked(false); |
| 937 snap_type_ = GetSnapType(location); | 936 snap_type_ = GetSnapType(location); |
| 938 } | 937 } |
| 939 const bool can_snap = snap_type_ != SNAP_NONE && window_state()->CanSnap(); | 938 const bool can_snap = snap_type_ != SNAP_NONE && window_state()->CanSnap(); |
| 940 if (!can_snap && !can_dock) { | 939 if (!can_snap && !can_dock) { |
| 941 snap_type_ = SNAP_NONE; | 940 snap_type_ = SNAP_NONE; |
| 942 snap_phantom_window_controller_.reset(); | 941 snap_phantom_window_controller_.reset(); |
| 943 edge_cycler_.reset(); | 942 edge_cycler_.reset(); |
| 944 return; | 943 return; |
| 945 } | 944 } |
| 946 if (!edge_cycler_) { | 945 if (!edge_cycler_) { |
| 947 edge_cycler_.reset(new TwoStepEdgeCycler( | 946 edge_cycler_.reset(new TwoStepEdgeCycler( |
| 948 location, snap_type_ == SNAP_LEFT | 947 location, snap_type_ == SNAP_LEFT |
| 949 ? TwoStepEdgeCycler::DIRECTION_LEFT | 948 ? TwoStepEdgeCycler::DIRECTION_LEFT |
| 950 : TwoStepEdgeCycler::DIRECTION_RIGHT)); | 949 : TwoStepEdgeCycler::DIRECTION_RIGHT)); |
| 951 } else { | 950 } else { |
| 952 edge_cycler_->OnMove(location); | 951 edge_cycler_->OnMove(location); |
| 953 } | 952 } |
| 954 | 953 |
| 955 // Update phantom window with snapped or docked guide bounds. | 954 // Update phantom window with snapped or docked guide bounds. |
| 956 // Windows that cannot be snapped or are less wide than kMaxDockWidth can get | 955 // Windows that cannot be snapped or are less wide than kMaxDockWidth can get |
| 957 // docked without going through a snapping sequence. | 956 // docked without going through a snapping sequence. |
| 958 gfx::Rect phantom_bounds; | 957 gfx::Rect phantom_bounds; |
| 959 const bool should_dock = can_dock && | 958 const bool should_dock = |
| 960 (!can_snap || | 959 can_dock && (!can_snap || |
| 961 GetTarget()->bounds().width() <= | 960 GetAuraTarget()->bounds().width() <= |
| 962 DockedWindowLayoutManager::kMaxDockWidth || | 961 DockedWindowLayoutManager::kMaxDockWidth || |
| 963 edge_cycler_->use_second_mode() || | 962 edge_cycler_->use_second_mode() || |
| 964 dock_layout_->is_dragged_window_docked()); | 963 dock_layout_->is_dragged_window_docked()); |
| 965 if (should_dock) { | 964 if (should_dock) { |
| 966 SetDraggedWindowDocked(true); | 965 SetDraggedWindowDocked(true); |
| 967 phantom_bounds = ScreenUtil::ConvertRectFromScreen( | 966 phantom_bounds = ScreenUtil::ConvertRectFromScreen( |
| 968 GetTarget()->parent(), dock_layout_->dragged_bounds()); | 967 GetAuraTarget()->parent(), dock_layout_->dragged_bounds()); |
| 969 } else { | 968 } else { |
| 970 phantom_bounds = (snap_type_ == SNAP_LEFT) | 969 phantom_bounds = (snap_type_ == SNAP_LEFT) |
| 971 ? wm::GetDefaultLeftSnappedWindowBoundsInParent( | 970 ? wm::GetDefaultLeftSnappedWindowBoundsInParent( |
| 972 wm::WmWindowAura::Get(GetTarget())) | 971 wm::WmWindowAura::Get(GetAuraTarget())) |
| 973 : wm::GetDefaultRightSnappedWindowBoundsInParent( | 972 : wm::GetDefaultRightSnappedWindowBoundsInParent( |
| 974 wm::WmWindowAura::Get(GetTarget())); | 973 wm::WmWindowAura::Get(GetAuraTarget())); |
| 975 } | 974 } |
| 976 | 975 |
| 977 if (!snap_phantom_window_controller_) { | 976 if (!snap_phantom_window_controller_) { |
| 978 snap_phantom_window_controller_.reset( | 977 snap_phantom_window_controller_.reset( |
| 979 new PhantomWindowController(GetTarget())); | 978 new PhantomWindowController(GetAuraTarget())); |
| 980 } | 979 } |
| 981 snap_phantom_window_controller_->Show(ScreenUtil::ConvertRectToScreen( | 980 snap_phantom_window_controller_->Show(ScreenUtil::ConvertRectToScreen( |
| 982 GetTarget()->parent(), phantom_bounds)); | 981 GetAuraTarget()->parent(), phantom_bounds)); |
| 983 } | 982 } |
| 984 | 983 |
| 985 void WorkspaceWindowResizer::RestackWindows() { | 984 void WorkspaceWindowResizer::RestackWindows() { |
| 986 if (attached_windows_.empty()) | 985 if (attached_windows_.empty()) |
| 987 return; | 986 return; |
| 988 // Build a map from index in children to window, returning if there is a | 987 // Build a map from index in children to window, returning if there is a |
| 989 // window with a different parent. | 988 // window with a different parent. |
| 990 typedef std::map<size_t, aura::Window*> IndexToWindowMap; | 989 typedef std::map<size_t, aura::Window*> IndexToWindowMap; |
| 991 IndexToWindowMap map; | 990 IndexToWindowMap map; |
| 992 aura::Window* parent = GetTarget()->parent(); | 991 aura::Window* parent = GetAuraTarget()->parent(); |
| 993 const aura::Window::Windows& windows(parent->children()); | 992 const aura::Window::Windows& windows(parent->children()); |
| 994 map[std::find(windows.begin(), windows.end(), GetTarget()) - | 993 map[std::find(windows.begin(), windows.end(), GetAuraTarget()) - |
| 995 windows.begin()] = GetTarget(); | 994 windows.begin()] = GetAuraTarget(); |
| 996 for (std::vector<aura::Window*>::const_iterator i = | 995 for (std::vector<aura::Window*>::const_iterator i = |
| 997 attached_windows_.begin(); i != attached_windows_.end(); ++i) { | 996 attached_windows_.begin(); i != attached_windows_.end(); ++i) { |
| 998 if ((*i)->parent() != parent) | 997 if ((*i)->parent() != parent) |
| 999 return; | 998 return; |
| 1000 size_t index = | 999 size_t index = |
| 1001 std::find(windows.begin(), windows.end(), *i) - windows.begin(); | 1000 std::find(windows.begin(), windows.end(), *i) - windows.begin(); |
| 1002 map[index] = *i; | 1001 map[index] = *i; |
| 1003 } | 1002 } |
| 1004 | 1003 |
| 1005 // Reorder the windows starting at the topmost. | 1004 // Reorder the windows starting at the topmost. |
| 1006 parent->StackChildAtTop(map.rbegin()->second); | 1005 parent->StackChildAtTop(map.rbegin()->second); |
| 1007 for (IndexToWindowMap::const_reverse_iterator i = map.rbegin(); | 1006 for (IndexToWindowMap::const_reverse_iterator i = map.rbegin(); |
| 1008 i != map.rend(); ) { | 1007 i != map.rend(); ) { |
| 1009 aura::Window* window = i->second; | 1008 aura::Window* window = i->second; |
| 1010 ++i; | 1009 ++i; |
| 1011 if (i != map.rend()) | 1010 if (i != map.rend()) |
| 1012 parent->StackChildBelow(i->second, window); | 1011 parent->StackChildBelow(i->second, window); |
| 1013 } | 1012 } |
| 1014 } | 1013 } |
| 1015 | 1014 |
| 1016 WorkspaceWindowResizer::SnapType WorkspaceWindowResizer::GetSnapType( | 1015 WorkspaceWindowResizer::SnapType WorkspaceWindowResizer::GetSnapType( |
| 1017 const gfx::Point& location) const { | 1016 const gfx::Point& location) const { |
| 1018 // TODO: this likely only wants total display area, not the area of a single | 1017 // TODO: this likely only wants total display area, not the area of a single |
| 1019 // display. | 1018 // display. |
| 1020 gfx::Rect area(ScreenUtil::GetDisplayWorkAreaBoundsInParent(GetTarget())); | 1019 gfx::Rect area(ScreenUtil::GetDisplayWorkAreaBoundsInParent(GetAuraTarget())); |
| 1021 if (details().source == aura::client::WINDOW_MOVE_SOURCE_TOUCH) { | 1020 if (details().source == aura::client::WINDOW_MOVE_SOURCE_TOUCH) { |
| 1022 // Increase tolerance for touch-snapping near the screen edges. This is only | 1021 // Increase tolerance for touch-snapping near the screen edges. This is only |
| 1023 // necessary when the work area left or right edge is same as screen edge. | 1022 // necessary when the work area left or right edge is same as screen edge. |
| 1024 gfx::Rect display_bounds(ScreenUtil::GetDisplayBoundsInParent(GetTarget())); | 1023 gfx::Rect display_bounds( |
| 1024 ScreenUtil::GetDisplayBoundsInParent(GetAuraTarget())); |
| 1025 int inset_left = 0; | 1025 int inset_left = 0; |
| 1026 if (area.x() == display_bounds.x()) | 1026 if (area.x() == display_bounds.x()) |
| 1027 inset_left = kScreenEdgeInsetForTouchDrag; | 1027 inset_left = kScreenEdgeInsetForTouchDrag; |
| 1028 int inset_right = 0; | 1028 int inset_right = 0; |
| 1029 if (area.right() == display_bounds.right()) | 1029 if (area.right() == display_bounds.right()) |
| 1030 inset_right = kScreenEdgeInsetForTouchDrag; | 1030 inset_right = kScreenEdgeInsetForTouchDrag; |
| 1031 area.Inset(inset_left, 0, inset_right, 0); | 1031 area.Inset(inset_left, 0, inset_right, 0); |
| 1032 } | 1032 } |
| 1033 if (location.x() <= area.x()) | 1033 if (location.x() <= area.x()) |
| 1034 return SNAP_LEFT; | 1034 return SNAP_LEFT; |
| 1035 if (location.x() >= area.right() - 1) | 1035 if (location.x() >= area.right() - 1) |
| 1036 return SNAP_RIGHT; | 1036 return SNAP_RIGHT; |
| 1037 return SNAP_NONE; | 1037 return SNAP_NONE; |
| 1038 } | 1038 } |
| 1039 | 1039 |
| 1040 void WorkspaceWindowResizer::SetDraggedWindowDocked(bool should_dock) { | 1040 void WorkspaceWindowResizer::SetDraggedWindowDocked(bool should_dock) { |
| 1041 if (should_dock) { | 1041 if (should_dock) { |
| 1042 if (!dock_layout_->is_dragged_window_docked()) { | 1042 if (!dock_layout_->is_dragged_window_docked()) { |
| 1043 window_state()->set_bounds_changed_by_user(false); | 1043 window_state()->set_bounds_changed_by_user(false); |
| 1044 dock_layout_->DockDraggedWindow(GetTarget()); | 1044 dock_layout_->DockDraggedWindow(GetAuraTarget()); |
| 1045 } | 1045 } |
| 1046 } else { | 1046 } else { |
| 1047 if (dock_layout_->is_dragged_window_docked()) { | 1047 if (dock_layout_->is_dragged_window_docked()) { |
| 1048 dock_layout_->UndockDraggedWindow(); | 1048 dock_layout_->UndockDraggedWindow(); |
| 1049 window_state()->set_bounds_changed_by_user(true); | 1049 window_state()->set_bounds_changed_by_user(true); |
| 1050 } | 1050 } |
| 1051 } | 1051 } |
| 1052 } | 1052 } |
| 1053 | 1053 |
| 1054 bool WorkspaceWindowResizer::AreBoundsValidSnappedBounds( | 1054 bool WorkspaceWindowResizer::AreBoundsValidSnappedBounds( |
| 1055 wm::WindowStateType snapped_type, | 1055 wm::WindowStateType snapped_type, |
| 1056 const gfx::Rect& bounds_in_parent) const { | 1056 const gfx::Rect& bounds_in_parent) const { |
| 1057 DCHECK(snapped_type == wm::WINDOW_STATE_TYPE_LEFT_SNAPPED || | 1057 DCHECK(snapped_type == wm::WINDOW_STATE_TYPE_LEFT_SNAPPED || |
| 1058 snapped_type == wm::WINDOW_STATE_TYPE_RIGHT_SNAPPED); | 1058 snapped_type == wm::WINDOW_STATE_TYPE_RIGHT_SNAPPED); |
| 1059 gfx::Rect snapped_bounds = ScreenUtil::GetDisplayWorkAreaBoundsInParent( | 1059 gfx::Rect snapped_bounds = |
| 1060 GetTarget()); | 1060 ScreenUtil::GetDisplayWorkAreaBoundsInParent(GetAuraTarget()); |
| 1061 if (snapped_type == wm::WINDOW_STATE_TYPE_RIGHT_SNAPPED) | 1061 if (snapped_type == wm::WINDOW_STATE_TYPE_RIGHT_SNAPPED) |
| 1062 snapped_bounds.set_x(snapped_bounds.right() - bounds_in_parent.width()); | 1062 snapped_bounds.set_x(snapped_bounds.right() - bounds_in_parent.width()); |
| 1063 snapped_bounds.set_width(bounds_in_parent.width()); | 1063 snapped_bounds.set_width(bounds_in_parent.width()); |
| 1064 return bounds_in_parent == snapped_bounds; | 1064 return bounds_in_parent == snapped_bounds; |
| 1065 } | 1065 } |
| 1066 | 1066 |
| 1067 } // namespace ash | 1067 } // namespace ash |
| OLD | NEW |