Index: ash/wm/workspace/snap_sizer.cc |
diff --git a/ash/wm/workspace/snap_sizer.cc b/ash/wm/workspace/snap_sizer.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..d2641b08d4886e0b2faa561fe5b3f12db3a8d52c |
--- /dev/null |
+++ b/ash/wm/workspace/snap_sizer.cc |
@@ -0,0 +1,120 @@ |
+// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "ash/wm/workspace/snap_sizer.h" |
+ |
+#include <cmath> |
+ |
+#include "ash/wm/window_resizer.h" |
+#include "ui/aura/window.h" |
+#include "ui/gfx/screen.h" |
+ |
+namespace ash { |
+namespace internal { |
+ |
+namespace { |
+ |
+// Percent of the screen (width) to give the window. |
+const float kPercents[] = { .5f, 2.0f / 3.0f, .8f }; |
+ |
+// Windows are initially snapped to the percent at index 0. The index into |
+// |kPercents| is changed if any of the following happen: |
+// . The user stops moving the mouse for |kDelayBeforeIncreaseMS| and then moves |
+// the mouse again. |
+// . The mouse moves |kPixelsBeforeAdjust| horizontal pixels. |
+// . The mouse is against the edge of the screen and the mouse is moved |
+// |kMovesBeforeAdjust| times. |
+const int kDelayBeforeIncreaseMS = 500; |
+const int kMovesBeforeAdjust = 50; |
+const int kPixelsBeforeAdjust = 200; |
+ |
+} // namespace |
+ |
+SnapSizer::SnapSizer(aura::Window* window, |
+ const gfx::Point& start, |
+ Edge edge, |
+ int grid_size) |
+ : window_(window), |
+ edge_(edge), |
+ grid_size_(grid_size), |
+ time_last_update_(base::TimeTicks::Now()), |
+ percent_index_(0), |
+ num_moves_since_adjust_(0), |
+ last_adjust_x_(start.x()), |
+ last_update_x_(start.x()) { |
+ target_bounds_ = GetTargetBounds(); |
+} |
+ |
+void SnapSizer::Update(const gfx::Point& location) { |
+ // See description above for details on this behavior. |
+ num_moves_since_adjust_++; |
+ if ((base::TimeTicks::Now() - time_last_update_).InMilliseconds() > |
+ kDelayBeforeIncreaseMS) { |
+ ChangeBounds(location.x(), |
+ CalculateIncrement(location.x(), last_update_x_)); |
+ } else { |
+ bool along_edge = AlongEdge(location.x()); |
+ if (std::abs(location.x() - last_adjust_x_) >= kPixelsBeforeAdjust || |
+ (along_edge && num_moves_since_adjust_ >= kMovesBeforeAdjust)) { |
+ ChangeBounds(location.x(), |
+ CalculateIncrement(location.x(), last_adjust_x_)); |
+ } |
+ } |
+ last_update_x_ = location.x(); |
+ time_last_update_ = base::TimeTicks::Now(); |
+} |
+ |
+int SnapSizer::CalculateIncrement(int x, int reference_x) const { |
+ if (AlongEdge(x)) |
+ return 1; |
+ if (x == reference_x) |
+ return 0; |
+ if (edge_ == LEFT_EDGE) { |
+ if (x < reference_x) |
+ return 1; |
+ return -1; |
+ } |
+ // edge_ == RIGHT_EDGE. |
+ if (x > reference_x) |
+ return 1; |
+ return -1; |
+} |
+ |
+void SnapSizer::ChangeBounds(int x, int delta) { |
+ int index = std::min(static_cast<int>(arraysize(kPercents)) - 1, |
+ std::max(percent_index_ + delta, 0)); |
+ if (index != percent_index_) { |
+ percent_index_ = index; |
+ target_bounds_ = GetTargetBounds(); |
+ } |
+ num_moves_since_adjust_ = 0; |
+ last_adjust_x_ = x; |
+} |
+ |
+gfx::Rect SnapSizer::GetTargetBounds() const { |
+ gfx::Rect work_area(gfx::Screen::GetMonitorWorkAreaNearestWindow(window_)); |
+ int y = WindowResizer::AlignToGridRoundUp(work_area.y(), grid_size_); |
+ int max_y = |
+ WindowResizer::AlignToGridRoundDown(work_area.bottom(), grid_size_); |
+ int width = static_cast<float>(work_area.width()) * kPercents[percent_index_]; |
+ if (edge_ == LEFT_EDGE) { |
+ int x = WindowResizer::AlignToGridRoundUp(work_area.x(), grid_size_); |
+ int mid_x = WindowResizer::AlignToGridRoundUp( |
+ work_area.x() + width, grid_size_); |
+ return gfx::Rect(x, y, mid_x - x, max_y - y); |
+ } |
+ int max_x = |
+ WindowResizer::AlignToGridRoundDown(work_area.right(), grid_size_); |
+ int x = WindowResizer::AlignToGridRoundUp(max_x - width, grid_size_); |
+ return gfx::Rect(x , y, max_x - x, max_y - y); |
+} |
+ |
+bool SnapSizer::AlongEdge(int x) const { |
+ // TODO: need to support multi-monitor. |
+ gfx::Rect area(gfx::Screen::GetMonitorAreaNearestWindow(window_)); |
+ return (x <= area.x()) || (x >= area.right() - 1); |
+} |
+ |
+} // namespace internal |
+} // namespace ash |