| 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> |
| 11 | 11 |
| 12 #include "ash/ash_switches.h" |
| 12 #include "ash/display/display_controller.h" | 13 #include "ash/display/display_controller.h" |
| 13 #include "ash/screen_ash.h" | 14 #include "ash/screen_ash.h" |
| 14 #include "ash/shell.h" | 15 #include "ash/shell.h" |
| 15 #include "ash/shell_window_ids.h" | 16 #include "ash/shell_window_ids.h" |
| 16 #include "ash/wm/coordinate_conversion.h" | 17 #include "ash/wm/coordinate_conversion.h" |
| 17 #include "ash/wm/default_window_resizer.h" | 18 #include "ash/wm/default_window_resizer.h" |
| 18 #include "ash/wm/drag_window_resizer.h" | 19 #include "ash/wm/drag_window_resizer.h" |
| 19 #include "ash/wm/panels/panel_window_resizer.h" | 20 #include "ash/wm/panels/panel_window_resizer.h" |
| 20 #include "ash/wm/property_util.h" | 21 #include "ash/wm/property_util.h" |
| 21 #include "ash/wm/window_properties.h" | 22 #include "ash/wm/window_properties.h" |
| 22 #include "ash/wm/window_util.h" | 23 #include "ash/wm/window_util.h" |
| 23 #include "ash/wm/workspace/phantom_window_controller.h" | 24 #include "ash/wm/workspace/phantom_window_controller.h" |
| 24 #include "ash/wm/workspace/snap_sizer.h" | 25 #include "ash/wm/workspace/snap_sizer.h" |
| 26 #include "base/command_line.h" |
| 25 #include "ui/aura/client/aura_constants.h" | 27 #include "ui/aura/client/aura_constants.h" |
| 26 #include "ui/aura/client/window_types.h" | 28 #include "ui/aura/client/window_types.h" |
| 27 #include "ui/aura/root_window.h" | 29 #include "ui/aura/root_window.h" |
| 28 #include "ui/aura/window.h" | 30 #include "ui/aura/window.h" |
| 29 #include "ui/aura/window_delegate.h" | 31 #include "ui/aura/window_delegate.h" |
| 30 #include "ui/base/hit_test.h" | 32 #include "ui/base/hit_test.h" |
| 31 #include "ui/compositor/layer.h" | 33 #include "ui/compositor/layer.h" |
| 32 #include "ui/gfx/screen.h" | 34 #include "ui/gfx/screen.h" |
| 33 #include "ui/gfx/transform.h" | 35 #include "ui/gfx/transform.h" |
| 34 | 36 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 67 window_resizer = PanelWindowResizer::Create( | 69 window_resizer = PanelWindowResizer::Create( |
| 68 window_resizer, window, point_in_parent, window_component); | 70 window_resizer, window, point_in_parent, window_component); |
| 69 } | 71 } |
| 70 return make_scoped_ptr<WindowResizer>(window_resizer); | 72 return make_scoped_ptr<WindowResizer>(window_resizer); |
| 71 } | 73 } |
| 72 | 74 |
| 73 namespace internal { | 75 namespace internal { |
| 74 | 76 |
| 75 namespace { | 77 namespace { |
| 76 | 78 |
| 77 // Duration of the animation when snapping the window into place. | 79 // Distance in pixels that the cursor must move past an edge for a window |
| 78 const int kSnapDurationMS = 100; | 80 // to move or resize beyond that edge. |
| 81 const int kStickyDistancePixels = 64; |
| 79 | 82 |
| 80 // Returns true if should snap to the edge. | 83 // Returns true if the window should stick to the edge. |
| 81 bool ShouldSnapToEdge(int distance_from_edge, int grid_size) { | 84 bool ShouldStickToEdge(int distance_from_edge, int sticky_size) { |
| 82 return distance_from_edge < grid_size && | 85 if (CommandLine::ForCurrentProcess()->HasSwitch( |
| 83 distance_from_edge > -grid_size * 2; | 86 switches::kAshEnableStickyEdges)) { |
| 87 return distance_from_edge < 0 && |
| 88 distance_from_edge > -sticky_size; |
| 89 } |
| 90 return distance_from_edge < sticky_size && |
| 91 distance_from_edge > -sticky_size * 2; |
| 84 } | 92 } |
| 85 | 93 |
| 86 // Returns the coordinate along the secondary axis to snap to. | 94 // Returns the coordinate along the secondary axis to snap to. |
| 87 int CoordinateAlongSecondaryAxis(SecondaryMagnetismEdge edge, | 95 int CoordinateAlongSecondaryAxis(SecondaryMagnetismEdge edge, |
| 88 int leading, | 96 int leading, |
| 89 int trailing, | 97 int trailing, |
| 90 int none) { | 98 int none) { |
| 91 switch (edge) { | 99 switch (edge) { |
| 92 case SECONDARY_MAGNETISM_EDGE_LEADING: | 100 case SECONDARY_MAGNETISM_EDGE_LEADING: |
| 93 return leading; | 101 return leading; |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 180 x = attach_origin.x(); | 188 x = attach_origin.x(); |
| 181 w = src.right() - x; | 189 w = src.right() - x; |
| 182 } else if (edge.secondary_edge == SECONDARY_MAGNETISM_EDGE_TRAILING) { | 190 } else if (edge.secondary_edge == SECONDARY_MAGNETISM_EDGE_TRAILING) { |
| 183 w += attach_origin.x() - src.x(); | 191 w += attach_origin.x() - src.x(); |
| 184 } | 192 } |
| 185 break; | 193 break; |
| 186 } | 194 } |
| 187 return gfx::Rect(x, y, w, h); | 195 return gfx::Rect(x, y, w, h); |
| 188 } | 196 } |
| 189 | 197 |
| 190 // Converts a window comopnent edge to the magnetic edge to snap to. | 198 // Converts a window component edge to the magnetic edge to snap to. |
| 191 uint32 WindowComponentToMagneticEdge(int window_component) { | 199 uint32 WindowComponentToMagneticEdge(int window_component) { |
| 192 switch (window_component) { | 200 switch (window_component) { |
| 193 case HTTOPLEFT: | 201 case HTTOPLEFT: |
| 194 return MAGNETISM_EDGE_LEFT | MAGNETISM_EDGE_TOP; | 202 return MAGNETISM_EDGE_LEFT | MAGNETISM_EDGE_TOP; |
| 195 case HTTOPRIGHT: | 203 case HTTOPRIGHT: |
| 196 return MAGNETISM_EDGE_TOP | MAGNETISM_EDGE_RIGHT; | 204 return MAGNETISM_EDGE_TOP | MAGNETISM_EDGE_RIGHT; |
| 197 case HTBOTTOMLEFT: | 205 case HTBOTTOMLEFT: |
| 198 return MAGNETISM_EDGE_LEFT | MAGNETISM_EDGE_BOTTOM; | 206 return MAGNETISM_EDGE_LEFT | MAGNETISM_EDGE_BOTTOM; |
| 199 case HTBOTTOMRIGHT: | 207 case HTBOTTOMRIGHT: |
| 200 return MAGNETISM_EDGE_RIGHT | MAGNETISM_EDGE_BOTTOM; | 208 return MAGNETISM_EDGE_RIGHT | MAGNETISM_EDGE_BOTTOM; |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 305 const std::vector<aura::Window*>& attached_windows) { | 313 const std::vector<aura::Window*>& attached_windows) { |
| 306 Details details(window, location_in_parent, window_component); | 314 Details details(window, location_in_parent, window_component); |
| 307 return details.is_resizable ? | 315 return details.is_resizable ? |
| 308 new WorkspaceWindowResizer(details, attached_windows) : NULL; | 316 new WorkspaceWindowResizer(details, attached_windows) : NULL; |
| 309 } | 317 } |
| 310 | 318 |
| 311 void WorkspaceWindowResizer::Drag(const gfx::Point& location_in_parent, | 319 void WorkspaceWindowResizer::Drag(const gfx::Point& location_in_parent, |
| 312 int event_flags) { | 320 int event_flags) { |
| 313 last_mouse_location_ = location_in_parent; | 321 last_mouse_location_ = location_in_parent; |
| 314 | 322 |
| 315 const int snap_size = | 323 int sticky_size; |
| 316 event_flags & ui::EF_CONTROL_DOWN ? 0 : kScreenEdgeInset; | 324 if (event_flags & ui::EF_CONTROL_DOWN) { |
| 325 sticky_size = 0; |
| 326 } else if (CommandLine::ForCurrentProcess()->HasSwitch( |
| 327 switches::kAshEnableStickyEdges)) { |
| 328 sticky_size = kStickyDistancePixels; |
| 329 } else { |
| 330 sticky_size = kScreenEdgeInset; |
| 331 } |
| 317 // |bounds| is in |window()->parent()|'s coordinates. | 332 // |bounds| is in |window()->parent()|'s coordinates. |
| 318 gfx::Rect bounds = CalculateBoundsForDrag(details_, location_in_parent); | 333 gfx::Rect bounds = CalculateBoundsForDrag(details_, location_in_parent); |
| 319 | 334 |
| 320 if (wm::IsWindowNormal(window())) | 335 if (wm::IsWindowNormal(window())) |
| 321 AdjustBoundsForMainWindow(snap_size, &bounds); | 336 AdjustBoundsForMainWindow(sticky_size, &bounds); |
| 322 | 337 |
| 323 if (bounds != window()->bounds()) { | 338 if (bounds != window()->bounds()) { |
| 324 if (!did_move_or_resize_) { | 339 if (!did_move_or_resize_) { |
| 325 if (!details_.restore_bounds.IsEmpty()) | 340 if (!details_.restore_bounds.IsEmpty()) |
| 326 ClearRestoreBounds(window()); | 341 ClearRestoreBounds(window()); |
| 327 RestackWindows(); | 342 RestackWindows(); |
| 328 } | 343 } |
| 329 did_move_or_resize_ = true; | 344 did_move_or_resize_ = true; |
| 330 } | 345 } |
| 331 | 346 |
| (...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 638 if (matcher.ShouldAttach(other->bounds(), &magnetism_edge_)) { | 653 if (matcher.ShouldAttach(other->bounds(), &magnetism_edge_)) { |
| 639 magnetism_window_ = other; | 654 magnetism_window_ = other; |
| 640 window_tracker_.Add(magnetism_window_); | 655 window_tracker_.Add(magnetism_window_); |
| 641 return true; | 656 return true; |
| 642 } | 657 } |
| 643 } | 658 } |
| 644 return false; | 659 return false; |
| 645 } | 660 } |
| 646 | 661 |
| 647 void WorkspaceWindowResizer::AdjustBoundsForMainWindow( | 662 void WorkspaceWindowResizer::AdjustBoundsForMainWindow( |
| 648 int snap_size, | 663 int sticky_size, |
| 649 gfx::Rect* bounds) { | 664 gfx::Rect* bounds) { |
| 650 gfx::Point last_mouse_location_in_screen = last_mouse_location_; | 665 gfx::Point last_mouse_location_in_screen = last_mouse_location_; |
| 651 wm::ConvertPointToScreen(window()->parent(), &last_mouse_location_in_screen); | 666 wm::ConvertPointToScreen(window()->parent(), &last_mouse_location_in_screen); |
| 652 gfx::Display display = Shell::GetScreen()->GetDisplayNearestPoint( | 667 gfx::Display display = Shell::GetScreen()->GetDisplayNearestPoint( |
| 653 last_mouse_location_in_screen); | 668 last_mouse_location_in_screen); |
| 654 gfx::Rect work_area = | 669 gfx::Rect work_area = |
| 655 ScreenAsh::ConvertRectFromScreen(window()->parent(), display.work_area()); | 670 ScreenAsh::ConvertRectFromScreen(window()->parent(), display.work_area()); |
| 656 if (details_.window_component == HTCAPTION) { | 671 if (details_.window_component == HTCAPTION) { |
| 657 // Adjust the bounds to the work area where the mouse cursor is located. | 672 // Adjust the bounds to the work area where the mouse cursor is located. |
| 658 // Always keep kMinOnscreenHeight on the bottom. | 673 // Always keep kMinOnscreenHeight on the bottom. |
| 659 int max_y = work_area.bottom() - kMinOnscreenHeight; | 674 int max_y = work_area.bottom() - kMinOnscreenHeight; |
| 660 if (bounds->y() > max_y) { | 675 if (bounds->y() > max_y) { |
| 661 bounds->set_y(max_y); | 676 bounds->set_y(max_y); |
| 662 } else if (bounds->y() <= work_area.y()) { | 677 } else if (bounds->y() <= work_area.y()) { |
| 663 // Don't allow dragging above the top of the display until the mouse | 678 // Don't allow dragging above the top of the display until the mouse |
| 664 // cursor reaches the work area above if any. | 679 // cursor reaches the work area above if any. |
| 665 bounds->set_y(work_area.y()); | 680 bounds->set_y(work_area.y()); |
| 666 } | 681 } |
| 667 | 682 |
| 668 if (snap_size > 0) { | 683 if (sticky_size > 0) { |
| 669 SnapToWorkAreaEdges(work_area, snap_size, bounds); | 684 StickToWorkAreaOnMove(work_area, sticky_size, bounds); |
| 670 MagneticallySnapToOtherWindows(bounds); | 685 MagneticallySnapToOtherWindows(bounds); |
| 671 } | 686 } |
| 672 } else if (snap_size > 0) { | 687 } else if (sticky_size > 0) { |
| 673 MagneticallySnapResizeToOtherWindows(bounds); | 688 MagneticallySnapResizeToOtherWindows(bounds); |
| 674 if (!magnetism_window_ && snap_size > 0) | 689 if (!magnetism_window_ && sticky_size > 0) |
| 675 SnapResizeToWorkAreaBounds(work_area, snap_size, bounds); | 690 StickToWorkAreaOnResize(work_area, sticky_size, bounds); |
| 676 } | 691 } |
| 677 | 692 |
| 678 if (attached_windows_.empty()) | 693 if (attached_windows_.empty()) |
| 679 return; | 694 return; |
| 680 | 695 |
| 681 if (details_.window_component == HTRIGHT) { | 696 if (details_.window_component == HTRIGHT) { |
| 682 bounds->set_width(std::min(bounds->width(), | 697 bounds->set_width(std::min(bounds->width(), |
| 683 work_area.right() - total_min_ - bounds->x())); | 698 work_area.right() - total_min_ - bounds->x())); |
| 684 } else { | 699 } else { |
| 685 DCHECK_EQ(HTBOTTOM, details_.window_component); | 700 DCHECK_EQ(HTBOTTOM, details_.window_component); |
| 686 bounds->set_height(std::min(bounds->height(), | 701 bounds->set_height(std::min(bounds->height(), |
| 687 work_area.bottom() - total_min_ - bounds->y())); | 702 work_area.bottom() - total_min_ - bounds->y())); |
| 688 } | 703 } |
| 689 } | 704 } |
| 690 | 705 |
| 691 void WorkspaceWindowResizer::SnapToWorkAreaEdges( | 706 void WorkspaceWindowResizer::StickToWorkAreaOnMove( |
| 692 const gfx::Rect& work_area, | 707 const gfx::Rect& work_area, |
| 693 int snap_size, | 708 int sticky_size, |
| 694 gfx::Rect* bounds) const { | 709 gfx::Rect* bounds) const { |
| 695 const int left_edge = work_area.x(); | 710 const int left_edge = work_area.x(); |
| 696 const int right_edge = work_area.right(); | 711 const int right_edge = work_area.right(); |
| 697 const int top_edge = work_area.y(); | 712 const int top_edge = work_area.y(); |
| 698 const int bottom_edge = work_area.bottom(); | 713 const int bottom_edge = work_area.bottom(); |
| 699 if (ShouldSnapToEdge(bounds->x() - left_edge, snap_size)) { | 714 if (ShouldStickToEdge(bounds->x() - left_edge, sticky_size)) { |
| 700 bounds->set_x(left_edge); | 715 bounds->set_x(left_edge); |
| 701 } else if (ShouldSnapToEdge(right_edge - bounds->right(), | 716 } else if (ShouldStickToEdge(right_edge - bounds->right(), sticky_size)) { |
| 702 snap_size)) { | |
| 703 bounds->set_x(right_edge - bounds->width()); | 717 bounds->set_x(right_edge - bounds->width()); |
| 704 } | 718 } |
| 705 if (ShouldSnapToEdge(bounds->y() - top_edge, snap_size)) { | 719 if (ShouldStickToEdge(bounds->y() - top_edge, sticky_size)) { |
| 706 bounds->set_y(top_edge); | 720 bounds->set_y(top_edge); |
| 707 } else if (ShouldSnapToEdge(bottom_edge - bounds->bottom(), snap_size) && | 721 } else if (ShouldStickToEdge(bottom_edge - bounds->bottom(), sticky_size) && |
| 708 bounds->height() < (bottom_edge - top_edge)) { | 722 bounds->height() < (bottom_edge - top_edge)) { |
| 709 // Only snap to the bottom if the window is smaller than the work area. | 723 // Only snap to the bottom if the window is smaller than the work area. |
| 710 // Doing otherwise can lead to window snapping in weird ways as it bounces | 724 // Doing otherwise can lead to window snapping in weird ways as it bounces |
| 711 // between snapping to top then bottom. | 725 // between snapping to top then bottom. |
| 712 bounds->set_y(bottom_edge - bounds->height()); | 726 bounds->set_y(bottom_edge - bounds->height()); |
| 713 } | 727 } |
| 714 } | 728 } |
| 715 | 729 |
| 716 void WorkspaceWindowResizer::SnapResizeToWorkAreaBounds( | 730 void WorkspaceWindowResizer::StickToWorkAreaOnResize( |
| 717 const gfx::Rect& work_area, | 731 const gfx::Rect& work_area, |
| 718 int snap_size, | 732 int sticky_size, |
| 719 gfx::Rect* bounds) const { | 733 gfx::Rect* bounds) const { |
| 720 const uint32 edges = WindowComponentToMagneticEdge(details_.window_component); | 734 const uint32 edges = WindowComponentToMagneticEdge(details_.window_component); |
| 721 const int left_edge = work_area.x(); | 735 const int left_edge = work_area.x(); |
| 722 const int right_edge = work_area.right(); | 736 const int right_edge = work_area.right(); |
| 723 const int top_edge = work_area.y(); | 737 const int top_edge = work_area.y(); |
| 724 const int bottom_edge = work_area.bottom(); | 738 const int bottom_edge = work_area.bottom(); |
| 725 if (edges & MAGNETISM_EDGE_TOP && | 739 if (edges & MAGNETISM_EDGE_TOP && |
| 726 ShouldSnapToEdge(bounds->y() - top_edge, snap_size)) { | 740 ShouldStickToEdge(bounds->y() - top_edge, sticky_size)) { |
| 727 bounds->set_height(bounds->bottom() - top_edge); | 741 bounds->set_height(bounds->bottom() - top_edge); |
| 728 bounds->set_y(top_edge); | 742 bounds->set_y(top_edge); |
| 729 } | 743 } |
| 730 if (edges & MAGNETISM_EDGE_LEFT && | 744 if (edges & MAGNETISM_EDGE_LEFT && |
| 731 ShouldSnapToEdge(bounds->x() - left_edge, snap_size)) { | 745 ShouldStickToEdge(bounds->x() - left_edge, sticky_size)) { |
| 732 bounds->set_width(bounds->right() - left_edge); | 746 bounds->set_width(bounds->right() - left_edge); |
| 733 bounds->set_x(left_edge); | 747 bounds->set_x(left_edge); |
| 734 } | 748 } |
| 735 if (edges & MAGNETISM_EDGE_BOTTOM && | 749 if (edges & MAGNETISM_EDGE_BOTTOM && |
| 736 ShouldSnapToEdge(bottom_edge - bounds->bottom(), snap_size)) { | 750 ShouldStickToEdge(bottom_edge - bounds->bottom(), sticky_size)) { |
| 737 bounds->set_height(bottom_edge - bounds->y()); | 751 bounds->set_height(bottom_edge - bounds->y()); |
| 738 } | 752 } |
| 739 if (edges & MAGNETISM_EDGE_RIGHT && | 753 if (edges & MAGNETISM_EDGE_RIGHT && |
| 740 ShouldSnapToEdge(right_edge - bounds->right(), snap_size)) { | 754 ShouldStickToEdge(right_edge - bounds->right(), sticky_size)) { |
| 741 bounds->set_width(right_edge - bounds->x()); | 755 bounds->set_width(right_edge - bounds->x()); |
| 742 } | 756 } |
| 743 } | 757 } |
| 744 | 758 |
| 745 int WorkspaceWindowResizer::PrimaryAxisSize(const gfx::Size& size) const { | 759 int WorkspaceWindowResizer::PrimaryAxisSize(const gfx::Size& size) const { |
| 746 return PrimaryAxisCoordinate(size.width(), size.height()); | 760 return PrimaryAxisCoordinate(size.width(), size.height()); |
| 747 } | 761 } |
| 748 | 762 |
| 749 int WorkspaceWindowResizer::PrimaryAxisCoordinate(int x, int y) const { | 763 int WorkspaceWindowResizer::PrimaryAxisCoordinate(int x, int y) const { |
| 750 switch (details_.window_component) { | 764 switch (details_.window_component) { |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 830 gfx::Rect area(ScreenAsh::GetDisplayBoundsInParent(window())); | 844 gfx::Rect area(ScreenAsh::GetDisplayBoundsInParent(window())); |
| 831 if (location.x() <= area.x()) | 845 if (location.x() <= area.x()) |
| 832 return SNAP_LEFT_EDGE; | 846 return SNAP_LEFT_EDGE; |
| 833 if (location.x() >= area.right() - 1) | 847 if (location.x() >= area.right() - 1) |
| 834 return SNAP_RIGHT_EDGE; | 848 return SNAP_RIGHT_EDGE; |
| 835 return SNAP_NONE; | 849 return SNAP_NONE; |
| 836 } | 850 } |
| 837 | 851 |
| 838 } // namespace internal | 852 } // namespace internal |
| 839 } // namespace ash | 853 } // namespace ash |
| OLD | NEW |