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

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: 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>
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
67 window_resizer = PanelWindowResizer::Create( 67 window_resizer = PanelWindowResizer::Create(
68 window_resizer, window, point_in_parent, window_component); 68 window_resizer, window, point_in_parent, window_component);
69 } 69 }
70 return make_scoped_ptr<WindowResizer>(window_resizer); 70 return make_scoped_ptr<WindowResizer>(window_resizer);
71 } 71 }
72 72
73 namespace internal { 73 namespace internal {
74 74
75 namespace { 75 namespace {
76 76
77 // Duration of the animation when snapping the window into place. 77 // Returns the coordinate along the secondary axis to stick to.
78 const int kSnapDurationMS = 100;
79
80 // Returns true if should snap to the edge.
81 bool ShouldSnapToEdge(int distance_from_edge, int grid_size) {
82 return distance_from_edge < grid_size &&
83 distance_from_edge > -grid_size * 2;
84 }
85
86 // Returns the coordinate along the secondary axis to snap to.
87 int CoordinateAlongSecondaryAxis(SecondaryMagnetismEdge edge, 78 int CoordinateAlongSecondaryAxis(SecondaryMagnetismEdge edge,
88 int leading, 79 int leading,
89 int trailing, 80 int trailing,
90 int none) { 81 int none) {
91 switch (edge) { 82 switch (edge) {
92 case SECONDARY_MAGNETISM_EDGE_LEADING: 83 case SECONDARY_MAGNETISM_EDGE_LEADING:
93 return leading; 84 return leading;
94 case SECONDARY_MAGNETISM_EDGE_TRAILING: 85 case SECONDARY_MAGNETISM_EDGE_TRAILING:
95 return trailing; 86 return trailing;
96 case SECONDARY_MAGNETISM_EDGE_NONE: 87 case SECONDARY_MAGNETISM_EDGE_NONE:
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 x = attach_origin.x(); 171 x = attach_origin.x();
181 w = src.right() - x; 172 w = src.right() - x;
182 } else if (edge.secondary_edge == SECONDARY_MAGNETISM_EDGE_TRAILING) { 173 } else if (edge.secondary_edge == SECONDARY_MAGNETISM_EDGE_TRAILING) {
183 w += attach_origin.x() - src.x(); 174 w += attach_origin.x() - src.x();
184 } 175 }
185 break; 176 break;
186 } 177 }
187 return gfx::Rect(x, y, w, h); 178 return gfx::Rect(x, y, w, h);
188 } 179 }
189 180
190 // Converts a window comopnent edge to the magnetic edge to snap to. 181 // Converts a window comopnent edge to the magnetic edge to stick to.
flackr 2013/04/16 00:32:14 nit: s/comopnent/component
stevenjb 2013/04/16 20:08:20 Done.
191 uint32 WindowComponentToMagneticEdge(int window_component) { 182 uint32 WindowComponentToMagneticEdge(int window_component) {
192 switch (window_component) { 183 switch (window_component) {
193 case HTTOPLEFT: 184 case HTTOPLEFT:
194 return MAGNETISM_EDGE_LEFT | MAGNETISM_EDGE_TOP; 185 return MAGNETISM_EDGE_LEFT | MAGNETISM_EDGE_TOP;
195 case HTTOPRIGHT: 186 case HTTOPRIGHT:
196 return MAGNETISM_EDGE_TOP | MAGNETISM_EDGE_RIGHT; 187 return MAGNETISM_EDGE_TOP | MAGNETISM_EDGE_RIGHT;
197 case HTBOTTOMLEFT: 188 case HTBOTTOMLEFT:
198 return MAGNETISM_EDGE_LEFT | MAGNETISM_EDGE_BOTTOM; 189 return MAGNETISM_EDGE_LEFT | MAGNETISM_EDGE_BOTTOM;
199 case HTBOTTOMRIGHT: 190 case HTBOTTOMRIGHT:
200 return MAGNETISM_EDGE_RIGHT | MAGNETISM_EDGE_BOTTOM; 191 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) { 296 const std::vector<aura::Window*>& attached_windows) {
306 Details details(window, location_in_parent, window_component); 297 Details details(window, location_in_parent, window_component);
307 return details.is_resizable ? 298 return details.is_resizable ?
308 new WorkspaceWindowResizer(details, attached_windows) : NULL; 299 new WorkspaceWindowResizer(details, attached_windows) : NULL;
309 } 300 }
310 301
311 void WorkspaceWindowResizer::Drag(const gfx::Point& location_in_parent, 302 void WorkspaceWindowResizer::Drag(const gfx::Point& location_in_parent,
312 int event_flags) { 303 int event_flags) {
313 last_mouse_location_ = location_in_parent; 304 last_mouse_location_ = location_in_parent;
314 305
315 const int snap_size = 306 const bool is_sticky = !(event_flags & ui::EF_CONTROL_DOWN);
316 event_flags & ui::EF_CONTROL_DOWN ? 0 : kScreenEdgeInset; 307
317 // |bounds| is in |window()->parent()|'s coordinates. 308 // |bounds| is in |window()->parent()|'s coordinates.
318 gfx::Rect bounds = CalculateBoundsForDrag(details_, location_in_parent); 309 gfx::Rect bounds = CalculateBoundsForDrag(details_, location_in_parent);
319 310
320 if (wm::IsWindowNormal(window())) 311 if (wm::IsWindowNormal(window()))
321 AdjustBoundsForMainWindow(snap_size, &bounds); 312 AdjustBoundsForMainWindow(is_sticky, &bounds);
322 313
323 if (bounds != window()->bounds()) { 314 if (bounds != window()->bounds()) {
324 if (!did_move_or_resize_) { 315 if (!did_move_or_resize_) {
325 if (!details_.restore_bounds.IsEmpty()) 316 if (!details_.restore_bounds.IsEmpty())
326 ClearRestoreBounds(window()); 317 ClearRestoreBounds(window());
327 RestackWindows(); 318 RestackWindows();
328 } 319 }
329 did_move_or_resize_ = true; 320 did_move_or_resize_ = true;
330 } 321 }
331 322
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after
589 for (size_t i = 0; i < attached_windows_.size(); i++) { 580 for (size_t i = 0; i < attached_windows_.size(); i++) {
590 int initial_size = initial_size_[i]; 581 int initial_size = initial_size_[i];
591 aura::WindowDelegate* delegate = attached_windows_[i]->delegate(); 582 aura::WindowDelegate* delegate = attached_windows_[i]->delegate();
592 int min = PrimaryAxisSize(delegate->GetMinimumSize()); 583 int min = PrimaryAxisSize(delegate->GetMinimumSize());
593 int max = PrimaryAxisSize(delegate->GetMaximumSize()); 584 int max = PrimaryAxisSize(delegate->GetMaximumSize());
594 585
595 sizes->push_back(WindowSize(initial_size, min, max)); 586 sizes->push_back(WindowSize(initial_size, min, max));
596 } 587 }
597 } 588 }
598 589
599 void WorkspaceWindowResizer::MagneticallySnapToOtherWindows(gfx::Rect* bounds) { 590 void WorkspaceWindowResizer::MagneticallyStickToOtherWindows(
591 gfx::Rect* bounds) {
600 if (UpdateMagnetismWindow(*bounds, kAllMagnetismEdges)) { 592 if (UpdateMagnetismWindow(*bounds, kAllMagnetismEdges)) {
601 bounds->set_origin( 593 bounds->set_origin(
602 OriginForMagneticAttach(*bounds, magnetism_window_->bounds(), 594 OriginForMagneticAttach(*bounds, magnetism_window_->bounds(),
603 magnetism_edge_)); 595 magnetism_edge_));
604 } 596 }
605 } 597 }
606 598
607 void WorkspaceWindowResizer::MagneticallySnapResizeToOtherWindows( 599 void WorkspaceWindowResizer::MagneticallyStickResizeToOtherWindows(
608 gfx::Rect* bounds) { 600 gfx::Rect* bounds) {
609 const uint32 edges = WindowComponentToMagneticEdge(details_.window_component); 601 const uint32 edges = WindowComponentToMagneticEdge(details_.window_component);
610 if (UpdateMagnetismWindow(*bounds, edges)) { 602 if (UpdateMagnetismWindow(*bounds, edges)) {
611 *bounds = BoundsForMagneticResizeAttach( 603 *bounds = BoundsForMagneticResizeAttach(
612 *bounds, magnetism_window_->bounds(), magnetism_edge_); 604 *bounds, magnetism_window_->bounds(), magnetism_edge_);
613 } 605 }
614 } 606 }
615 607
616 bool WorkspaceWindowResizer::UpdateMagnetismWindow(const gfx::Rect& bounds, 608 bool WorkspaceWindowResizer::UpdateMagnetismWindow(const gfx::Rect& bounds,
617 uint32 edges) { 609 uint32 edges) {
618 MagnetismMatcher matcher(bounds, edges); 610 MagnetismMatcher matcher(bounds, edges);
619 611
620 // If we snapped to a window then check it first. That way we don't bounce 612 // If we stuck to a window then check it first. That way we don't bounce
621 // around when close to multiple edges. 613 // around when close to multiple edges.
622 if (magnetism_window_) { 614 if (magnetism_window_) {
623 if (window_tracker_.Contains(magnetism_window_) && 615 if (window_tracker_.Contains(magnetism_window_) &&
624 matcher.ShouldAttach(magnetism_window_->bounds(), &magnetism_edge_)) { 616 matcher.ShouldAttach(magnetism_window_->bounds(), &magnetism_edge_)) {
625 return true; 617 return true;
626 } 618 }
627 window_tracker_.Remove(magnetism_window_); 619 window_tracker_.Remove(magnetism_window_);
628 magnetism_window_ = NULL; 620 magnetism_window_ = NULL;
629 } 621 }
630 622
631 aura::Window* parent = window()->parent(); 623 aura::Window* parent = window()->parent();
632 const aura::Window::Windows& windows(parent->children()); 624 const aura::Window::Windows& windows(parent->children());
633 for (aura::Window::Windows::const_reverse_iterator i = windows.rbegin(); 625 for (aura::Window::Windows::const_reverse_iterator i = windows.rbegin();
634 i != windows.rend() && !matcher.AreEdgesObscured(); ++i) { 626 i != windows.rend() && !matcher.AreEdgesObscured(); ++i) {
635 aura::Window* other = *i; 627 aura::Window* other = *i;
636 if (other == window() || !other->IsVisible()) 628 if (other == window() || !other->IsVisible())
637 continue; 629 continue;
638 if (matcher.ShouldAttach(other->bounds(), &magnetism_edge_)) { 630 if (matcher.ShouldAttach(other->bounds(), &magnetism_edge_)) {
639 magnetism_window_ = other; 631 magnetism_window_ = other;
640 window_tracker_.Add(magnetism_window_); 632 window_tracker_.Add(magnetism_window_);
641 return true; 633 return true;
642 } 634 }
643 } 635 }
644 return false; 636 return false;
645 } 637 }
646 638
647 void WorkspaceWindowResizer::AdjustBoundsForMainWindow( 639 void WorkspaceWindowResizer::AdjustBoundsForMainWindow(bool is_sticky,
648 int snap_size, 640 gfx::Rect* bounds) {
649 gfx::Rect* bounds) {
650 gfx::Point last_mouse_location_in_screen = last_mouse_location_; 641 gfx::Point last_mouse_location_in_screen = last_mouse_location_;
651 wm::ConvertPointToScreen(window()->parent(), &last_mouse_location_in_screen); 642 wm::ConvertPointToScreen(window()->parent(), &last_mouse_location_in_screen);
652 gfx::Display display = Shell::GetScreen()->GetDisplayNearestPoint( 643 gfx::Display display = Shell::GetScreen()->GetDisplayNearestPoint(
653 last_mouse_location_in_screen); 644 last_mouse_location_in_screen);
654 gfx::Rect work_area = 645 gfx::Rect work_area =
655 ScreenAsh::ConvertRectFromScreen(window()->parent(), display.work_area()); 646 ScreenAsh::ConvertRectFromScreen(window()->parent(), display.work_area());
656 if (details_.window_component == HTCAPTION) { 647 if (details_.window_component == HTCAPTION) {
657 // Adjust the bounds to the work area where the mouse cursor is located. 648 // Adjust the bounds to the work area where the mouse cursor is located.
658 // Always keep kMinOnscreenHeight on the bottom. 649 // Always keep kMinOnscreenHeight on the bottom.
659 int max_y = work_area.bottom() - kMinOnscreenHeight; 650 int max_y = work_area.bottom() - kMinOnscreenHeight;
660 if (bounds->y() > max_y) { 651 if (bounds->y() > max_y) {
661 bounds->set_y(max_y); 652 bounds->set_y(max_y);
662 } else if (bounds->y() <= work_area.y()) { 653 } else if (bounds->y() <= work_area.y()) {
663 // Don't allow dragging above the top of the display until the mouse 654 // Don't allow dragging above the top of the display until the mouse
664 // cursor reaches the work area above if any. 655 // cursor reaches the work area above if any.
665 bounds->set_y(work_area.y()); 656 bounds->set_y(work_area.y());
666 } 657 }
667 658
668 if (snap_size > 0) { 659 if (is_sticky) {
669 SnapToWorkAreaEdges(work_area, snap_size, bounds); 660 StickToWorkAreaEdges(work_area, bounds);
670 MagneticallySnapToOtherWindows(bounds); 661 MagneticallyStickToOtherWindows(bounds);
671 } 662 }
672 } else if (snap_size > 0) { 663 } else if (is_sticky) {
673 MagneticallySnapResizeToOtherWindows(bounds); 664 MagneticallyStickResizeToOtherWindows(bounds);
674 if (!magnetism_window_ && snap_size > 0) 665 if (!magnetism_window_)
675 SnapResizeToWorkAreaBounds(work_area, snap_size, bounds); 666 StickyResizeToWorkAreaBounds(work_area, bounds);
676 } 667 }
677 668
678 if (attached_windows_.empty()) 669 if (attached_windows_.empty())
679 return; 670 return;
680 671
681 if (details_.window_component == HTRIGHT) { 672 if (details_.window_component == HTRIGHT) {
682 bounds->set_width(std::min(bounds->width(), 673 bounds->set_width(std::min(bounds->width(),
683 work_area.right() - total_min_ - bounds->x())); 674 work_area.right() - total_min_ - bounds->x()));
684 } else { 675 } else {
685 DCHECK_EQ(HTBOTTOM, details_.window_component); 676 DCHECK_EQ(HTBOTTOM, details_.window_component);
686 bounds->set_height(std::min(bounds->height(), 677 bounds->set_height(std::min(bounds->height(),
687 work_area.bottom() - total_min_ - bounds->y())); 678 work_area.bottom() - total_min_ - bounds->y()));
688 } 679 }
689 } 680 }
690 681
691 void WorkspaceWindowResizer::SnapToWorkAreaEdges( 682 void WorkspaceWindowResizer::StickToWorkAreaEdges(
692 const gfx::Rect& work_area, 683 const gfx::Rect& work_area,
693 int snap_size,
694 gfx::Rect* bounds) const { 684 gfx::Rect* bounds) const {
695 const int left_edge = work_area.x(); 685 const int left_edge = work_area.x();
696 const int right_edge = work_area.right(); 686 const int right_edge = work_area.right();
697 const int top_edge = work_area.y(); 687 const int top_edge = work_area.y();
698 const int bottom_edge = work_area.bottom(); 688 const int bottom_edge = work_area.bottom();
699 if (ShouldSnapToEdge(bounds->x() - left_edge, snap_size)) { 689 if (wm::ShouldStickToEdge(bounds->x() - left_edge)) {
700 bounds->set_x(left_edge); 690 bounds->set_x(left_edge);
701 } else if (ShouldSnapToEdge(right_edge - bounds->right(), 691 } else if (wm::ShouldStickToEdge(right_edge - bounds->right())) {
702 snap_size)) {
703 bounds->set_x(right_edge - bounds->width()); 692 bounds->set_x(right_edge - bounds->width());
704 } 693 }
705 if (ShouldSnapToEdge(bounds->y() - top_edge, snap_size)) { 694 if (wm::ShouldStickToEdge(bounds->y() - top_edge)) {
706 bounds->set_y(top_edge); 695 bounds->set_y(top_edge);
707 } else if (ShouldSnapToEdge(bottom_edge - bounds->bottom(), snap_size) && 696 } else if (wm::ShouldStickToEdge(bottom_edge - bounds->bottom()) &&
708 bounds->height() < (bottom_edge - top_edge)) { 697 bounds->height() < (bottom_edge - top_edge)) {
709 // Only snap to the bottom if the window is smaller than the work area. 698 // 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 699 // Doing otherwise can lead to window snapping in weird ways as it bounces
711 // between snapping to top then bottom. 700 // between snapping to top then bottom.
712 bounds->set_y(bottom_edge - bounds->height()); 701 bounds->set_y(bottom_edge - bounds->height());
713 } 702 }
714 } 703 }
715 704
716 void WorkspaceWindowResizer::SnapResizeToWorkAreaBounds( 705 void WorkspaceWindowResizer::StickyResizeToWorkAreaBounds(
717 const gfx::Rect& work_area, 706 const gfx::Rect& work_area,
718 int snap_size,
719 gfx::Rect* bounds) const { 707 gfx::Rect* bounds) const {
720 const uint32 edges = WindowComponentToMagneticEdge(details_.window_component); 708 const uint32 edges = WindowComponentToMagneticEdge(details_.window_component);
721 const int left_edge = work_area.x(); 709 const int left_edge = work_area.x();
722 const int right_edge = work_area.right(); 710 const int right_edge = work_area.right();
723 const int top_edge = work_area.y(); 711 const int top_edge = work_area.y();
724 const int bottom_edge = work_area.bottom(); 712 const int bottom_edge = work_area.bottom();
725 if (edges & MAGNETISM_EDGE_TOP && 713 if (edges & MAGNETISM_EDGE_TOP &&
726 ShouldSnapToEdge(bounds->y() - top_edge, snap_size)) { 714 wm::ShouldStickToEdge(bounds->y() - top_edge)) {
727 bounds->set_height(bounds->bottom() - top_edge); 715 bounds->set_height(bounds->bottom() - top_edge);
728 bounds->set_y(top_edge); 716 bounds->set_y(top_edge);
729 } 717 }
730 if (edges & MAGNETISM_EDGE_LEFT && 718 if (edges & MAGNETISM_EDGE_LEFT &&
731 ShouldSnapToEdge(bounds->x() - left_edge, snap_size)) { 719 wm::ShouldStickToEdge(bounds->x() - left_edge)) {
732 bounds->set_width(bounds->right() - left_edge); 720 bounds->set_width(bounds->right() - left_edge);
733 bounds->set_x(left_edge); 721 bounds->set_x(left_edge);
734 } 722 }
735 if (edges & MAGNETISM_EDGE_BOTTOM && 723 if (edges & MAGNETISM_EDGE_BOTTOM &&
736 ShouldSnapToEdge(bottom_edge - bounds->bottom(), snap_size)) { 724 wm::ShouldStickToEdge(bottom_edge - bounds->bottom())) {
737 bounds->set_height(bottom_edge - bounds->y()); 725 bounds->set_height(bottom_edge - bounds->y());
738 } 726 }
739 if (edges & MAGNETISM_EDGE_RIGHT && 727 if (edges & MAGNETISM_EDGE_RIGHT &&
740 ShouldSnapToEdge(right_edge - bounds->right(), snap_size)) { 728 wm::ShouldStickToEdge(right_edge - bounds->right())) {
741 bounds->set_width(right_edge - bounds->x()); 729 bounds->set_width(right_edge - bounds->x());
742 } 730 }
743 } 731 }
744 732
745 int WorkspaceWindowResizer::PrimaryAxisSize(const gfx::Size& size) const { 733 int WorkspaceWindowResizer::PrimaryAxisSize(const gfx::Size& size) const {
746 return PrimaryAxisCoordinate(size.width(), size.height()); 734 return PrimaryAxisCoordinate(size.width(), size.height());
747 } 735 }
748 736
749 int WorkspaceWindowResizer::PrimaryAxisCoordinate(int x, int y) const { 737 int WorkspaceWindowResizer::PrimaryAxisCoordinate(int x, int y) const {
750 switch (details_.window_component) { 738 switch (details_.window_component) {
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
830 gfx::Rect area(ScreenAsh::GetDisplayBoundsInParent(window())); 818 gfx::Rect area(ScreenAsh::GetDisplayBoundsInParent(window()));
831 if (location.x() <= area.x()) 819 if (location.x() <= area.x())
832 return SNAP_LEFT_EDGE; 820 return SNAP_LEFT_EDGE;
833 if (location.x() >= area.right() - 1) 821 if (location.x() >= area.right() - 1)
834 return SNAP_RIGHT_EDGE; 822 return SNAP_RIGHT_EDGE;
835 return SNAP_NONE; 823 return SNAP_NONE;
836 } 824 }
837 825
838 } // namespace internal 826 } // namespace internal
839 } // namespace ash 827 } // namespace ash
OLDNEW
« ash/wm/workspace/workspace_window_resizer.h ('K') | « ash/wm/workspace/workspace_window_resizer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698