17d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 27d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 37d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// found in the LICENSE file. 47d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 57d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "ash/wm/dock/docked_window_resizer.h" 67d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 7d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ash/display/display_controller.h" 87d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "ash/root_window_controller.h" 95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/screen_util.h" 105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/shelf/shelf.h" 117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "ash/shelf/shelf_types.h" 127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "ash/shelf/shelf_widget.h" 137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "ash/shell.h" 147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "ash/shell_window_ids.h" 157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "ash/wm/dock/docked_window_layout_manager.h" 1668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ash/wm/window_state.h" 174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "ash/wm/window_util.h" 183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "ash/wm/workspace/magnetism_matcher.h" 193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "ash/wm/workspace/workspace_window_resizer.h" 207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/command_line.h" 2158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/memory/weak_ptr.h" 227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "ui/aura/client/aura_constants.h" 231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "ui/aura/client/window_tree_client.h" 247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "ui/aura/env.h" 257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "ui/aura/window.h" 267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "ui/aura/window_delegate.h" 27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/aura/window_event_dispatcher.h" 287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "ui/base/hit_test.h" 297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "ui/base/ui_base_types.h" 307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "ui/gfx/screen.h" 317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "ui/views/widget/widget.h" 326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "ui/wm/core/coordinate_conversion.h" 337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)namespace ash { 357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)namespace { 367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)DockedWindowLayoutManager* GetDockedLayoutManagerAtPoint( 383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const gfx::Point& point) { 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) gfx::Display display = ScreenUtil::FindDisplayContainingPoint(point); 40d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!display.is_valid()) 41d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return NULL; 421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) aura::Window* root = Shell::GetInstance()->display_controller()-> 43d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) GetRootWindowForDisplayId(display.id()); 443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) aura::Window* dock_container = Shell::GetContainer( 45d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) root, kShellWindowId_DockedContainer); 463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return static_cast<DockedWindowLayoutManager*>( 473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) dock_container->layout_manager()); 483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} // namespace 517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)DockedWindowResizer::~DockedWindowResizer() { 537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// static 567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)DockedWindowResizer* 577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)DockedWindowResizer::Create(WindowResizer* next_window_resizer, 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) wm::WindowState* window_state) { 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return new DockedWindowResizer(next_window_resizer, window_state); 607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void DockedWindowResizer::Drag(const gfx::Point& location, int event_flags) { 637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) last_location_ = location; 646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ::wm::ConvertPointToScreen(GetTarget()->parent(), &last_location_); 657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!did_move_or_resize_) { 667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) did_move_or_resize_ = true; 677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) StartedDragging(); 687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) gfx::Point offset; 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) gfx::Rect bounds(CalculateBoundsForDrag(location)); 71a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) MaybeSnapToEdge(bounds, &offset); 72a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) gfx::Point modified_location(location); 73a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) modified_location.Offset(offset.x(), offset.y()); 74ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 7558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::WeakPtr<DockedWindowResizer> resizer(weak_ptr_factory_.GetWeakPtr()); 7658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) next_window_resizer_->Drag(modified_location, event_flags); 7758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!resizer) 78ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return; 793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DockedWindowLayoutManager* new_dock_layout = 813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) GetDockedLayoutManagerAtPoint(last_location_); 82d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (new_dock_layout && new_dock_layout != dock_layout_) { 833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // The window is being dragged to a new display. If the previous 843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // container is the current parent of the window it will be informed of 853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // the end of drag when the window is reparented, otherwise let the 863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // previous container know the drag is complete. If we told the 873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // window's parent that the drag was complete it would begin 883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // positioning the window. 89d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (is_docked_ && dock_layout_->is_dragged_window_docked()) 903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) dock_layout_->UndockDraggedWindow(); 913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (dock_layout_ != initial_dock_layout_) 92f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) dock_layout_->FinishDragging( 93f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DOCKED_ACTION_NONE, 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) details().source == aura::client::WINDOW_MOVE_SOURCE_MOUSE ? 95f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DOCKED_ACTION_SOURCE_MOUSE : DOCKED_ACTION_SOURCE_TOUCH); 963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) is_docked_ = false; 973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) dock_layout_ = new_dock_layout; 983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // The window's initial layout manager already knows that the drag is 993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // in progress for this window. 1003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (new_dock_layout != initial_dock_layout_) 1013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) new_dock_layout->StartDragging(GetTarget()); 1023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 103d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Window could get docked by the WorkspaceWindowResizer, update the state. 104d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) is_docked_ = dock_layout_->is_dragged_window_docked(); 105f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Whenever a window is dragged out of the dock it will be auto-sized 106f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // in the dock if it gets docked again. 107f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!is_docked_) 108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) was_bounds_changed_by_user_ = false; 1097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 1107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void DockedWindowResizer::CompleteDrag() { 1127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // The root window can change when dragging into a different screen. 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) next_window_resizer_->CompleteDrag(); 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FinishedDragging(aura::client::MOVE_SUCCESSFUL); 1157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 1167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 1177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void DockedWindowResizer::RevertDrag() { 1187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) next_window_resizer_->RevertDrag(); 119d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Restore docked state to what it was before the drag if necessary. 120f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (is_docked_ != was_docked_) { 121d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) is_docked_ = was_docked_; 122f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (is_docked_) 123f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) dock_layout_->DockDraggedWindow(GetTarget()); 124f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) else 125f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) dock_layout_->UndockDraggedWindow(); 126d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FinishedDragging(aura::client::MOVE_CANCELED); 1287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 1297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 1307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)DockedWindowResizer::DockedWindowResizer(WindowResizer* next_window_resizer, 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) wm::WindowState* window_state) 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : WindowResizer(window_state), 1337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) next_window_resizer_(next_window_resizer), 1347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) dock_layout_(NULL), 1353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) initial_dock_layout_(NULL), 136ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch did_move_or_resize_(false), 137ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch was_docked_(false), 1383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) is_docked_(false), 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) was_bounds_changed_by_user_(window_state->bounds_changed_by_user()), 14058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) weak_ptr_factory_(this) { 1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(details().is_resizable); 1427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) aura::Window* dock_container = Shell::GetContainer( 1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GetTarget()->GetRootWindow(), 1443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) kShellWindowId_DockedContainer); 1453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) dock_layout_ = static_cast<DockedWindowLayoutManager*>( 1467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) dock_container->layout_manager()); 1473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) initial_dock_layout_ = dock_layout_; 1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) was_docked_ = GetTarget()->parent() == dock_container; 1493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) is_docked_ = was_docked_; 1503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 1513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 152a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void DockedWindowResizer::MaybeSnapToEdge(const gfx::Rect& bounds, 1537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) gfx::Point* offset) { 154d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Windows only snap magnetically when they were previously docked. 155d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!was_docked_) 156a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return; 157d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DockedAlignment dock_alignment = dock_layout_->CalculateAlignment(); 1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) gfx::Rect dock_bounds = ScreenUtil::ConvertRectFromScreen( 159d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) GetTarget()->parent(), 160d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) dock_layout_->dock_container()->GetBoundsInScreen()); 161ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Short-range magnetism when retaining docked state. Same constant as in 1633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // MagnetismMatcher is used for consistency. 1643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const int kSnapToDockDistance = MagnetismMatcher::kMagneticDistance; 1653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (dock_alignment == DOCKED_ALIGNMENT_LEFT || 167d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) dock_alignment == DOCKED_ALIGNMENT_NONE) { 168ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch const int distance = bounds.x() - dock_bounds.x(); 16968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (distance < kSnapToDockDistance && distance > 0) { 170558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch offset->set_x(-distance); 171a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return; 172ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 173ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 1743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (dock_alignment == DOCKED_ALIGNMENT_RIGHT || 175d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) dock_alignment == DOCKED_ALIGNMENT_NONE) { 176ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch const int distance = dock_bounds.right() - bounds.right(); 177a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (distance < kSnapToDockDistance && distance > 0) 178558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch offset->set_x(distance); 1797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 1807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 1817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 1827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void DockedWindowResizer::StartedDragging() { 183f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // During resizing the window width is preserved by DockedwindowLayoutManager. 184f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (is_docked_ && 1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (details().bounds_change & WindowResizer::kBoundsChange_Resizes)) { 1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) window_state_->set_bounds_changed_by_user(true); 187f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 188f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 1897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Tell the dock layout manager that we are dragging this window. 1903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // At this point we are not yet animating the window as it may not be 1913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // inside the docked area. 1927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) dock_layout_->StartDragging(GetTarget()); 1933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Reparent workspace windows during the drag to elevate them above workspace. 1943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Other windows for which the DockedWindowResizer is instantiated include 1953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // panels and windows that are already docked. Those do not need reparenting. 1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (GetTarget()->type() != ui::wm::WINDOW_TYPE_PANEL && 1973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) GetTarget()->parent()->id() == kShellWindowId_DefaultContainer) { 1983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Reparent the window into the docked windows container in order to get it 1993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // on top of other docked windows. 2003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) aura::Window* docked_container = Shell::GetContainer( 2013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) GetTarget()->GetRootWindow(), 2023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) kShellWindowId_DockedContainer); 203a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) wm::ReparentChildWithTransientChildren(GetTarget(), 204a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) GetTarget()->parent(), 205a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) docked_container); 2063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 2073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (is_docked_) 2083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) dock_layout_->DockDraggedWindow(GetTarget()); 2097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 2107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void DockedWindowResizer::FinishedDragging( 2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) aura::client::WindowMoveResult move_result) { 2137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!did_move_or_resize_) 2147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return; 2154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) did_move_or_resize_ = false; 2167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) aura::Window* window = GetTarget(); 2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const bool is_attached_panel = window->type() == ui::wm::WINDOW_TYPE_PANEL && 2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) window_state_->panel_attached(); 219d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const bool is_resized = 2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (details().bounds_change & WindowResizer::kBoundsChange_Resizes) != 0; 2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 222a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Undock the window if it is not in the normal or minimized state type. This 2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // happens if a user snaps or maximizes a window using a keyboard shortcut 2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // while it is being dragged. 225a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!window_state_->IsMinimized() && !window_state_->IsNormalStateType()) 2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) is_docked_ = false; 22768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 22868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // When drag is completed the dragged docked window is resized to the bounds 22968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // calculated by the layout manager that conform to other docked windows. 230f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!is_attached_panel && is_docked_ && !is_resized) { 2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) gfx::Rect bounds = ScreenUtil::ConvertRectFromScreen( 23268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) window->parent(), dock_layout_->dragged_bounds()); 23368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (!bounds.IsEmpty() && bounds.width() != window->bounds().width()) { 23468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) window->SetBounds(bounds); 23568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 23668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 237f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // If a window has restore bounds, update the restore origin and width but not 238f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // the height (since the height is auto-calculated for the docked windows). 2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (is_resized && is_docked_ && window_state_->HasRestoreBounds()) { 240f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) gfx::Rect restore_bounds = window->GetBoundsInScreen(); 241f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) restore_bounds.set_height( 2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) window_state_->GetRestoreBoundsInScreen().height()); 2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) window_state_->SetRestoreBoundsInScreen(restore_bounds); 244f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 245f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 246f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Check if the window needs to be docked or returned to workspace. 247f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DockedAction action = MaybeReparentWindowOnDragCompletion(is_resized, 248f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) is_attached_panel); 249f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) dock_layout_->FinishDragging( 2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) move_result == aura::client::MOVE_CANCELED ? DOCKED_ACTION_NONE : action, 2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) details().source == aura::client::WINDOW_MOVE_SOURCE_MOUSE ? 252f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DOCKED_ACTION_SOURCE_MOUSE : DOCKED_ACTION_SOURCE_TOUCH); 253f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 254f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // If we started the drag in one root window and moved into another root 255f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // but then canceled the drag we may need to inform the original layout 256f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // manager that the drag is finished. 257f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (initial_dock_layout_ != dock_layout_) 258f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) initial_dock_layout_->FinishDragging( 259f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DOCKED_ACTION_NONE, 2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) details().source == aura::client::WINDOW_MOVE_SOURCE_MOUSE ? 261f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DOCKED_ACTION_SOURCE_MOUSE : DOCKED_ACTION_SOURCE_TOUCH); 262f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) is_docked_ = false; 263f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 264f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 265f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)DockedAction DockedWindowResizer::MaybeReparentWindowOnDragCompletion( 266f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) bool is_resized, bool is_attached_panel) { 267f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) aura::Window* window = GetTarget(); 2687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 2693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Check if the window needs to be docked or returned to workspace. 270f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DockedAction action = DOCKED_ACTION_NONE; 2713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) aura::Window* dock_container = Shell::GetContainer( 2723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) window->GetRootWindow(), 2733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) kShellWindowId_DockedContainer); 274f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if ((is_resized || !is_attached_panel) && 275d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) is_docked_ != (window->parent() == dock_container)) { 276d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (is_docked_) { 277a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) wm::ReparentChildWithTransientChildren(window, 278a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) window->parent(), 279a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) dock_container); 280f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) action = DOCKED_ACTION_DOCK; 2813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } else if (window->parent()->id() == kShellWindowId_DockedContainer) { 2827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Reparent the window back to workspace. 2831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // We need to be careful to give ParentWindowWithContext a location in 2847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // the right root window (matching the logic in DragWindowResizer) based 2857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // on which root window a mouse pointer is in. We want to undock into the 2867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // right screen near the edge of a multiscreen setup (based on where the 2877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // mouse is). 2887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) gfx::Rect near_last_location(last_location_, gfx::Size()); 2897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Reparenting will cause Relayout and possible dock shrinking. 2904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) aura::Window* previous_parent = window->parent(); 2911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) aura::client::ParentWindowWithContext(window, window, near_last_location); 292a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (window->parent() != previous_parent) { 293a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) wm::ReparentTransientChildrenOfChild(window, 294a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) previous_parent, 295a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) window->parent()); 296a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 297f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) action = was_docked_ ? DOCKED_ACTION_UNDOCK : DOCKED_ACTION_NONE; 2987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 299f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } else { 300f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Docked state was not changed but still need to record a UMA action. 301f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (is_resized && is_docked_ && was_docked_) 302f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) action = DOCKED_ACTION_RESIZE; 303f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) else if (is_docked_ && was_docked_) 304f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) action = DOCKED_ACTION_REORDER; 305f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) else if (is_docked_ && !was_docked_) 306f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) action = DOCKED_ACTION_DOCK; 307f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) else 308f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) action = DOCKED_ACTION_NONE; 3097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 310f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // When a window is newly docked it is auto-sized by docked layout adjusting 311f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // to other windows. If it is just dragged (but not resized) while being 312f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // docked it is auto-sized unless it has been resized while being docked 313f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // before. 314f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (is_docked_) { 315f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) wm::GetWindowState(window)->set_bounds_changed_by_user( 316f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) was_docked_ && (is_resized || was_bounds_changed_by_user_)); 317f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 318f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return action; 3193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 3203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 3213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} // namespace ash 322