Chromium Code Reviews| Index: ash/wm/workspace/workspace_window_resizer.cc |
| diff --git a/ash/wm/workspace/workspace_window_resizer.cc b/ash/wm/workspace/workspace_window_resizer.cc |
| index 000260c0399eb55341aeaffe356806ce55e4603e..0f642d32b6e829afafdfa57803a5094b709b6646 100644 |
| --- a/ash/wm/workspace/workspace_window_resizer.cc |
| +++ b/ash/wm/workspace/workspace_window_resizer.cc |
| @@ -41,6 +41,23 @@ bool ShouldSnapToEdge(int distance_from_edge, int grid_size) { |
| distance_from_edge > -grid_size * 2; |
| } |
| +// Returns true if Ash has more than one root window. |
| +bool HasSecondaryRootWindow() { |
| + return Shell::GetAllRootWindows().size() > 1; |
| +} |
| + |
| +// When there are two root windows, returns one of the root windows which is not |
| +// |root_window|. Returns NULL if only one root window exists. |
| +aura::RootWindow* GetAnotherRootWindow(aura::RootWindow* root_window) { |
| + Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); |
| + if (root_windows.size() < 2) |
| + return NULL; |
| + DCHECK_EQ(2U, root_windows.size()); |
|
sky
2012/08/07 03:28:05
Is there a limitation that we only ever support at
Yusuke Sato
2012/08/07 16:38:30
According to oshima, yes. Actually DisplayControll
oshima
2012/08/08 01:40:31
We only support to up 2 displays for now (in terms
|
| + if (root_windows[0] == root_window) |
| + return root_windows[1]; |
| + return root_windows[0]; |
| +} |
| + |
| } // namespace |
| // static |
| @@ -69,15 +86,23 @@ WorkspaceWindowResizer* WorkspaceWindowResizer::Create( |
| void WorkspaceWindowResizer::Drag(const gfx::Point& location, int event_flags) { |
| std::pair<aura::RootWindow*, gfx::Point> actual_location = |
| wm::GetRootWindowRelativeToWindow(window()->parent(), location); |
| - |
| - // TODO(yusukes): Implement dragging a window from one display to another. |
| aura::RootWindow* current_root = actual_location.first; |
| - if (current_root != window()->GetRootWindow()) |
| - return; |
| + gfx::Point location_in_original_root = actual_location.second; |
| + aura::Window::ConvertPointToWindow(current_root, |
| + window()->GetRootWindow(), |
| + &location_in_original_root); |
| + |
| + // Do not use |location| below this point, use |location_in_original_root| |
| + // instead. When the pointer is on |window()->GetRootWindow()|, |location| and |
| + // |location_in_original_root| have the same value and both of them are in |
| + // |window()->GetRootWindow()|'s coordinates, but once the pointer enters the |
| + // other root window, you will see an unexpected value on the former. See |
| + // comments in wm::GetRootWindowRelativeToWindow() for details. |
| int grid_size = event_flags & ui::EF_CONTROL_DOWN ? |
| 0 : ash::Shell::GetInstance()->GetGridSize(); |
| - gfx::Rect bounds = CalculateBoundsForDrag(details_, location, grid_size); |
| + gfx::Rect bounds = // in |window()->GetRootWindow()|'s coordinates. |
| + CalculateBoundsForDrag(details_, location_in_original_root, grid_size); |
|
sky
2012/08/07 03:28:05
I'm confused, CalculateBoundsForDrag should take c
Yusuke Sato
2012/08/07 16:38:30
The variable name and the comment were wrong. Sorr
|
| if (wm::IsWindowNormal(details_.window)) |
| AdjustBoundsForMainWindow(&bounds, grid_size); |
| @@ -86,7 +111,20 @@ void WorkspaceWindowResizer::Drag(const gfx::Point& location, int event_flags) { |
| RestackWindows(); |
| did_move_or_resize_ = true; |
| } |
| - UpdatePhantomWindow(location, bounds, grid_size); |
| + |
| + const bool in_original_root = (window()->GetRootWindow() == current_root); |
| + // Hide a phantom window for snapping if the cursor is in another root window. |
| + if (in_original_root) |
| + UpdatePhantomWindow(location_in_original_root, bounds, grid_size); |
| + else |
| + phantom_window_controller_.reset(); |
| + |
| + // Show a phantom window for dragging in another root window. |
| + if (HasSecondaryRootWindow()) |
| + UpdateDragPhantomWindow(bounds); |
| + else |
| + drag_phantom_window_controller_.reset(); |
| + |
| if (!attached_windows_.empty()) |
| LayoutAttachedWindows(bounds, grid_size); |
| if (bounds != details_.window->bounds()) |
| @@ -95,6 +133,7 @@ void WorkspaceWindowResizer::Drag(const gfx::Point& location, int event_flags) { |
| } |
| void WorkspaceWindowResizer::CompleteDrag(int event_flags) { |
| + drag_phantom_window_controller_.reset(); |
| phantom_window_controller_.reset(); |
| if (!did_move_or_resize_ || details_.window_component != HTCAPTION) |
| return; |
| @@ -140,6 +179,7 @@ void WorkspaceWindowResizer::CompleteDrag(int event_flags) { |
| } |
| void WorkspaceWindowResizer::RevertDrag() { |
| + drag_phantom_window_controller_.reset(); |
| phantom_window_controller_.reset(); |
| if (!did_move_or_resize_) |
| @@ -312,17 +352,23 @@ void WorkspaceWindowResizer::CalculateAttachedSizes( |
| void WorkspaceWindowResizer::AdjustBoundsForMainWindow( |
| gfx::Rect* bounds, int grid_size) const { |
| - // Always keep kMinOnscreenHeight on the bottom. |
| + // Always keep kMinOnscreenHeight on the bottom except when an extended |
| + // display is available and a window is being dragged. |
|
sky
2012/08/07 03:28:05
Doesn't that only make sense if the extended displ
Yusuke Sato
2012/08/07 16:38:30
Yes.
|
| gfx::Rect work_area( |
| ScreenAsh::GetDisplayWorkAreaBoundsInParent(details_.window)); |
| int max_y = AlignToGridRoundUp(work_area.bottom() - kMinOnscreenHeight, |
| grid_size); |
| - if (bounds->y() > max_y) |
| + if ((details_.window_component != HTCAPTION || !HasSecondaryRootWindow()) && |
| + bounds->y() > max_y) { |
| bounds->set_y(max_y); |
| + } |
| - // Don't allow dragging above the top of the display. |
| - if (bounds->y() <= work_area.y()) |
| + // Don't allow dragging above the top of the display except when an extended |
| + // display is available and a window is being dragged. |
| + if ((details_.window_component != HTCAPTION || !HasSecondaryRootWindow()) && |
| + bounds->y() <= work_area.y()) { |
| bounds->set_y(work_area.y()); |
| + } |
| if (grid_size >= 0 && details_.window_component == HTCAPTION) |
| SnapToWorkAreaEdges(work_area, bounds, grid_size); |
| @@ -391,6 +437,33 @@ int WorkspaceWindowResizer::PrimaryAxisCoordinate(int x, int y) const { |
| return 0; |
| } |
| +void WorkspaceWindowResizer::UpdateDragPhantomWindow(const gfx::Rect& bounds) { |
| + if (!did_move_or_resize_ || details_.window_component != HTCAPTION || |
| + !ShouldAllowMouseWarp()) { |
| + return; |
| + } |
| + |
| + // It's available. Show a phantom window on the display if needed. |
| + aura::RootWindow* another_root = |
| + GetAnotherRootWindow(window()->GetRootWindow()); |
| + const gfx::Rect root_bounds_in_screen(another_root->GetBoundsInScreen()); |
| + const gfx::Rect bounds_in_screen = |
| + ScreenAsh::ConvertRectToScreen(window()->GetRootWindow(), bounds); |
| + const gfx::Rect phantom(root_bounds_in_screen.Intersect(bounds_in_screen)); |
| + |
| + if (!phantom.IsEmpty()) { |
| + if (!drag_phantom_window_controller_.get()) { |
| + drag_phantom_window_controller_.reset( |
| + new PhantomWindowController(window())); |
| + drag_phantom_window_controller_->Show(phantom); |
| + } else { |
| + drag_phantom_window_controller_->SetBounds(phantom); // no animation |
| + } |
| + } else { |
| + drag_phantom_window_controller_.reset(); |
| + } |
| +} |
| + |
| void WorkspaceWindowResizer::UpdatePhantomWindow(const gfx::Point& location, |
| const gfx::Rect& bounds, |
| int grid_size) { |