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

Side by Side Diff: ash/wm/workspace/workspace_window_resizer.cc

Issue 14273008: Add ash-enable-sticky-edges for 'sticky' instead of 'snap' behavior. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ash/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
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
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
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
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
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
OLDNEW
« no previous file with comments | « ash/wm/workspace/workspace_window_resizer.h ('k') | ash/wm/workspace/workspace_window_resizer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698