Index: ash/wm/workspace/snap_sizer.cc |
diff --git a/ash/wm/workspace/snap_sizer.cc b/ash/wm/workspace/snap_sizer.cc |
index 11b59470fcd87d5be27e934cc992feac57b7c90a..fcf9cc0906acc4aa1d13883bf2f11e9baae5e371 100644 |
--- a/ash/wm/workspace/snap_sizer.cc |
+++ b/ash/wm/workspace/snap_sizer.cc |
@@ -6,10 +6,17 @@ |
#include <cmath> |
+#include "ash/ash_switches.h" |
+#include "ash/launcher/launcher.h" |
#include "ash/screen_ash.h" |
+#include "ash/shell.h" |
+#include "ash/shell_window_ids.h" |
+#include "ash/wm/dock/docked_window_layout_manager.h" |
#include "ash/wm/property_util.h" |
+#include "ash/wm/window_properties.h" |
#include "ash/wm/window_resizer.h" |
#include "ash/wm/window_util.h" |
+#include "base/command_line.h" |
#include "ui/aura/window.h" |
#include "ui/gfx/screen.h" |
@@ -38,28 +45,37 @@ const int kPixelsBeforeAdjust = 100; |
const int kMinimumScreenPercent = 90; |
// Create the list of possible width for the current screen configuration: |
-// Fill the |usable_width_| list with items from |kIdealWidth| which fit on |
-// the screen and supplement it with the 'half of screen' size. Furthermore, |
-// add an entry for 90% of the screen size if it is smaller then the biggest |
-// value in the |kIdealWidth| list (to get a step between the values). |
-std::vector<int> BuildIdealWidthList(aura::Window* window) { |
+// Returns a list that for windows that can be snapped (|allow_snap| set) |
+// includes items from |kIdealWidth| which fit on the screen and supplement it |
+// with the 'half of screen' size. Furthermore, add an entry for 90% of the |
+// screen size if it is smaller then the biggest value in the |kIdealWidth| |
+// list (to get a step between the values). |
+// When a window can be docked (|allow_dock| set) a zero-width is added as the |
+// last value to facilitate showing a docking guide. |
+std::vector<int> BuildIdealWidthList(aura::Window* window, |
+ bool allow_snap, |
+ bool allow_dock) { |
std::vector<int> ideal_width_list; |
- gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(window)); |
- int half_size = work_area.width() / 2; |
- int maximum_width = (kMinimumScreenPercent * work_area.width()) / 100; |
- for (size_t i = 0; i < arraysize(kIdealWidth); i++) { |
- if (maximum_width >= kIdealWidth[i]) { |
- if (i && !ideal_width_list.size() && maximum_width != kIdealWidth[i]) |
- ideal_width_list.push_back(maximum_width); |
- if (half_size > kIdealWidth[i]) |
- ideal_width_list.push_back(half_size); |
- if (half_size >= kIdealWidth[i]) |
- half_size = 0; |
- ideal_width_list.push_back(kIdealWidth[i]); |
+ if (allow_snap) { |
+ gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(window)); |
+ int half_size = work_area.width() / 2; |
+ int maximum_width = (kMinimumScreenPercent * work_area.width()) / 100; |
+ for (size_t i = 0; i < arraysize(kIdealWidth); i++) { |
+ if (maximum_width >= kIdealWidth[i]) { |
+ if (i && !ideal_width_list.size() && maximum_width != kIdealWidth[i]) |
+ ideal_width_list.push_back(maximum_width); |
+ if (half_size > kIdealWidth[i]) |
+ ideal_width_list.push_back(half_size); |
+ if (half_size >= kIdealWidth[i]) |
+ half_size = 0; |
+ ideal_width_list.push_back(kIdealWidth[i]); |
+ } |
} |
+ if (half_size) |
+ ideal_width_list.push_back(half_size); |
} |
- if (half_size) |
- ideal_width_list.push_back(half_size); |
+ if (allow_dock) |
+ ideal_width_list.push_back(0); |
return ideal_width_list; |
} |
@@ -79,13 +95,28 @@ SnapSizer::SnapSizer(aura::Window* window, |
last_adjust_x_(start.x()), |
last_update_x_(start.x()), |
start_x_(start.x()), |
- input_type_(input_type), |
- usable_width_(BuildIdealWidthList(window)) { |
+ input_type_(input_type) { |
+ aura::Window* dock_container = Shell::GetContainer( |
+ window_->GetRootWindow(), kShellWindowId_DockedContainer); |
+ dock_layout_ = static_cast<DockedWindowLayoutManager*>( |
+ dock_container->layout_manager()); |
+ bool allow_dock = |
+ input_type_ == internal::SnapSizer::WORKSPACE_DRAG_INPUT && |
+ CanDockWindow(window_, edge_); |
+ bool allow_snap = !allow_dock || |
+ (wm::CanSnapWindow(window_) && |
+ !dock_layout_->is_dragged_window_docked() && |
+ window->bounds().width() > DockedWindowLayoutManager::kMaxDockWidth && |
+ (window_->type() != aura::client::WINDOW_TYPE_PANEL)); |
flackr
2013/09/10 17:59:44
This seems like it's redundant with the panel chec
varkha
2013/09/10 21:49:35
Done.
|
+ usable_width_ = BuildIdealWidthList(window, allow_snap, allow_dock); |
DCHECK(!usable_width_.empty()); |
+ UpdateDockedState(); |
target_bounds_ = GetTargetBounds(); |
} |
SnapSizer::~SnapSizer() { |
+ if (dock_layout_->is_dragged_window_docked()) |
+ dock_layout_->UndockDraggedWindow(); |
flackr
2013/09/10 17:59:44
How does the window stay docked when dropped in th
varkha
2013/09/10 21:49:35
DockedWindowResizer::CompleteDrag is called while
flackr
2013/09/11 18:08:50
Understood, maybe a short comment that on completi
varkha
2013/09/11 18:22:56
Done.
|
} |
void SnapSizer::SnapWindow(aura::Window* window, SnapSizer::Edge edge) { |
@@ -136,6 +167,7 @@ void SnapSizer::Update(const gfx::Point& location) { |
CalculateIncrement(location.x(), last_adjust_x_)); |
} |
} |
+ UpdateDockedState(); |
last_update_x_ = location.x(); |
time_last_update_ = base::TimeTicks::Now(); |
} |
@@ -157,6 +189,7 @@ gfx::Rect SnapSizer::GetSnapBounds(const gfx::Rect& bounds) { |
void SnapSizer::SelectDefaultSizeAndDisableResize() { |
resize_disabled_ = true; |
size_index_ = 0; |
+ UpdateDockedState(); |
target_bounds_ = GetTargetBounds(); |
} |
@@ -177,6 +210,11 @@ gfx::Rect SnapSizer::GetTargetBoundsForSize(size_t size_index) const { |
width = usable_width_[size_index]; |
} |
+ if (width == 0) { |
+ return ScreenAsh::ConvertRectFromScreen(window_->parent(), |
+ dock_layout_->dragged_bounds()); |
+ } |
+ |
if (edge_ == LEFT_EDGE) { |
int x = work_area.x(); |
int mid_x = x + width; |
@@ -187,6 +225,37 @@ gfx::Rect SnapSizer::GetTargetBoundsForSize(size_t size_index) const { |
return gfx::Rect(x , y, max_x - x, max_y - y); |
} |
+bool SnapSizer::ShouldDockWindow() const { |
+ // TODO(varkha): use dedicated state. |
+ return (usable_width_[size_index_] == 0); |
+} |
+ |
+// static |
+bool SnapSizer::CanDockWindow(aura::Window* window, SnapSizer::Edge edge) { |
+ if (!CommandLine::ForCurrentProcess()->HasSwitch( |
+ switches::kAshEnableDockedWindows)) { |
+ return false; |
+ } |
+ // Cannot dock on the other size from an existing dock. |
+ aura::Window* dock_container = Shell::GetContainer( |
+ window->GetRootWindow(), kShellWindowId_DockedContainer); |
+ DockedWindowLayoutManager* dock_layout = |
+ static_cast<DockedWindowLayoutManager*>(dock_container->layout_manager()); |
+ const DockedAlignment alignment = dock_layout->CalculateAlignment(); |
+ if ((edge == LEFT_EDGE && alignment == DOCKED_ALIGNMENT_RIGHT) || |
+ (edge == RIGHT_EDGE && alignment == DOCKED_ALIGNMENT_LEFT)) { |
+ return false; |
+ } |
+ |
+ // Do not allow docking on the same side as launcher shelf. |
+ Launcher* launcher = Launcher::ForWindow(window); |
+ if (!launcher) |
+ return true; |
flackr
2013/09/10 17:59:44
nit: This early return is a little dangerous in th
varkha
2013/09/10 21:49:35
Done.
|
+ return (edge == LEFT_EDGE && launcher->alignment() != SHELF_ALIGNMENT_LEFT) || |
+ (edge == RIGHT_EDGE && launcher->alignment() != SHELF_ALIGNMENT_RIGHT); |
+ |
+} |
+ |
int SnapSizer::CalculateIncrement(int x, int reference_x) const { |
if (AlongEdge(x)) |
return 1; |
@@ -219,9 +288,21 @@ gfx::Rect SnapSizer::GetTargetBounds() const { |
} |
bool SnapSizer::AlongEdge(int x) const { |
- gfx::Rect area(ScreenAsh::GetDisplayBoundsInParent(window_)); |
+ gfx::Rect area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(window_)); |
return (x <= area.x()) || (x >= area.right() - 1); |
} |
+void SnapSizer::UpdateDockedState() { |
+ if (ShouldDockWindow() && |
+ dock_layout_->GetAlignmentOfWindow(window_) != DOCKED_ALIGNMENT_NONE) { |
+ if (!dock_layout_->is_dragged_window_docked()) |
+ dock_layout_->DockDraggedWindow(window_); |
+ target_bounds_ = GetTargetBounds(); |
+ } else { |
+ if (dock_layout_->is_dragged_window_docked()) |
+ dock_layout_->UndockDraggedWindow(); |
+ } |
+} |
+ |
} // namespace internal |
} // namespace ash |