Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / ash / wm / panels / panel_window_resizer.cc
bloba57ac596ba9e565426648c7d8975d4844dcc8ee7
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
3 // found in the LICENSE file.
5 #include "ash/wm/panels/panel_window_resizer.h"
7 #include "ash/display/display_controller.h"
8 #include "ash/screen_util.h"
9 #include "ash/shelf/shelf.h"
10 #include "ash/shelf/shelf_types.h"
11 #include "ash/shelf/shelf_widget.h"
12 #include "ash/shell.h"
13 #include "ash/shell_window_ids.h"
14 #include "ash/wm/panels/panel_layout_manager.h"
15 #include "ash/wm/window_state.h"
16 #include "ash/wm/window_util.h"
17 #include "base/memory/weak_ptr.h"
18 #include "ui/aura/client/aura_constants.h"
19 #include "ui/aura/client/window_tree_client.h"
20 #include "ui/aura/env.h"
21 #include "ui/aura/window.h"
22 #include "ui/aura/window_delegate.h"
23 #include "ui/aura/window_event_dispatcher.h"
24 #include "ui/base/hit_test.h"
25 #include "ui/base/ui_base_types.h"
26 #include "ui/gfx/screen.h"
27 #include "ui/views/widget/widget.h"
28 #include "ui/wm/core/coordinate_conversion.h"
30 namespace ash {
32 namespace {
33 const int kPanelSnapToLauncherDistance = 30;
35 PanelLayoutManager* GetPanelLayoutManager(aura::Window* panel_container) {
36 DCHECK(panel_container->id() == kShellWindowId_PanelContainer);
37 return static_cast<PanelLayoutManager*>(panel_container->layout_manager());
40 } // namespace
42 PanelWindowResizer::~PanelWindowResizer() {
45 // static
46 PanelWindowResizer*
47 PanelWindowResizer::Create(WindowResizer* next_window_resizer,
48 wm::WindowState* window_state) {
49 return new PanelWindowResizer(next_window_resizer, window_state);
52 void PanelWindowResizer::Drag(const gfx::Point& location, int event_flags) {
53 last_location_ = location;
54 ::wm::ConvertPointToScreen(GetTarget()->parent(), &last_location_);
55 if (!did_move_or_resize_) {
56 did_move_or_resize_ = true;
57 StartedDragging();
60 // Check if the destination has changed displays.
61 gfx::Screen* screen = Shell::GetScreen();
62 const gfx::Display dst_display =
63 screen->GetDisplayNearestPoint(last_location_);
64 if (dst_display.id() !=
65 screen->GetDisplayNearestWindow(panel_container_->GetRootWindow()).id()) {
66 // The panel is being dragged to a new display. If the previous container is
67 // the current parent of the panel it will be informed of the end of drag
68 // when the panel is reparented, otherwise let the previous container know
69 // the drag is complete. If we told the panel's parent that the drag was
70 // complete it would begin positioning the panel.
71 if (GetTarget()->parent() != panel_container_)
72 GetPanelLayoutManager(panel_container_)->FinishDragging();
73 aura::Window* dst_root = Shell::GetInstance()->display_controller()->
74 GetRootWindowForDisplayId(dst_display.id());
75 panel_container_ =
76 Shell::GetContainer(dst_root, kShellWindowId_PanelContainer);
78 // The panel's parent already knows that the drag is in progress for this
79 // panel.
80 if (panel_container_ && GetTarget()->parent() != panel_container_)
81 GetPanelLayoutManager(panel_container_)->StartDragging(GetTarget());
83 gfx::Point offset;
84 gfx::Rect bounds(CalculateBoundsForDrag(location));
85 if (!(details().bounds_change & WindowResizer::kBoundsChange_Resizes)) {
86 window_state_->drag_details()->should_attach_to_shelf =
87 AttachToLauncher(bounds, &offset);
89 gfx::Point modified_location(location.x() + offset.x(),
90 location.y() + offset.y());
92 base::WeakPtr<PanelWindowResizer> resizer(weak_ptr_factory_.GetWeakPtr());
93 next_window_resizer_->Drag(modified_location, event_flags);
94 if (!resizer)
95 return;
97 if (details().should_attach_to_shelf &&
98 !(details().bounds_change & WindowResizer::kBoundsChange_Resizes)) {
99 UpdateLauncherPosition();
103 void PanelWindowResizer::CompleteDrag() {
104 // The root window can change when dragging into a different screen.
105 next_window_resizer_->CompleteDrag();
106 FinishDragging();
109 void PanelWindowResizer::RevertDrag() {
110 next_window_resizer_->RevertDrag();
111 window_state_->drag_details()->should_attach_to_shelf = was_attached_;
112 FinishDragging();
115 PanelWindowResizer::PanelWindowResizer(WindowResizer* next_window_resizer,
116 wm::WindowState* window_state)
117 : WindowResizer(window_state),
118 next_window_resizer_(next_window_resizer),
119 panel_container_(NULL),
120 initial_panel_container_(NULL),
121 did_move_or_resize_(false),
122 was_attached_(window_state->panel_attached()),
123 weak_ptr_factory_(this) {
124 DCHECK(details().is_resizable);
125 panel_container_ = Shell::GetContainer(GetTarget()->GetRootWindow(),
126 kShellWindowId_PanelContainer);
127 initial_panel_container_ = panel_container_;
130 bool PanelWindowResizer::AttachToLauncher(const gfx::Rect& bounds,
131 gfx::Point* offset) {
132 bool should_attach = false;
133 if (panel_container_) {
134 PanelLayoutManager* panel_layout_manager =
135 GetPanelLayoutManager(panel_container_);
136 gfx::Rect launcher_bounds = ScreenUtil::ConvertRectFromScreen(
137 GetTarget()->parent(),
138 panel_layout_manager->shelf()->
139 shelf_widget()->GetWindowBoundsInScreen());
140 switch (panel_layout_manager->shelf()->alignment()) {
141 case SHELF_ALIGNMENT_BOTTOM:
142 if (bounds.bottom() >= (launcher_bounds.y() -
143 kPanelSnapToLauncherDistance)) {
144 should_attach = true;
145 offset->set_y(launcher_bounds.y() - bounds.height() - bounds.y());
147 break;
148 case SHELF_ALIGNMENT_LEFT:
149 if (bounds.x() <= (launcher_bounds.right() +
150 kPanelSnapToLauncherDistance)) {
151 should_attach = true;
152 offset->set_x(launcher_bounds.right() - bounds.x());
154 break;
155 case SHELF_ALIGNMENT_RIGHT:
156 if (bounds.right() >= (launcher_bounds.x() -
157 kPanelSnapToLauncherDistance)) {
158 should_attach = true;
159 offset->set_x(launcher_bounds.x() - bounds.width() - bounds.x());
161 break;
162 case SHELF_ALIGNMENT_TOP:
163 if (bounds.y() <= (launcher_bounds.bottom() +
164 kPanelSnapToLauncherDistance)) {
165 should_attach = true;
166 offset->set_y(launcher_bounds.bottom() - bounds.y());
168 break;
171 return should_attach;
174 void PanelWindowResizer::StartedDragging() {
175 // Tell the panel layout manager that we are dragging this panel before
176 // attaching it so that it does not get repositioned.
177 if (panel_container_)
178 GetPanelLayoutManager(panel_container_)->StartDragging(GetTarget());
179 if (!was_attached_) {
180 // Attach the panel while dragging placing it in front of other panels.
181 window_state_->set_panel_attached(true);
182 // We use root window coordinates to ensure that during the drag the panel
183 // is reparented to a container in the root window that has that window.
184 aura::Window* target = GetTarget();
185 aura::Window* target_root = target->GetRootWindow();
186 aura::Window* old_parent = target->parent();
187 aura::client::ParentWindowWithContext(
188 target, target_root, target_root->GetBoundsInScreen());
189 wm::ReparentTransientChildrenOfChild(target, old_parent, target->parent());
193 void PanelWindowResizer::FinishDragging() {
194 if (!did_move_or_resize_)
195 return;
196 if (window_state_->panel_attached() != details().should_attach_to_shelf) {
197 window_state_->set_panel_attached(details().should_attach_to_shelf);
198 // We use last known location to ensure that after the drag the panel
199 // is reparented to a container in the root window that has that location.
200 aura::Window* target = GetTarget();
201 aura::Window* target_root = target->GetRootWindow();
202 aura::Window* old_parent = target->parent();
203 aura::client::ParentWindowWithContext(
204 target, target_root, gfx::Rect(last_location_, gfx::Size()));
205 wm::ReparentTransientChildrenOfChild(target, old_parent, target->parent());
208 // If we started the drag in one root window and moved into another root
209 // but then canceled the drag we may need to inform the original layout
210 // manager that the drag is finished.
211 if (initial_panel_container_ != panel_container_)
212 GetPanelLayoutManager(initial_panel_container_)->FinishDragging();
213 if (panel_container_)
214 GetPanelLayoutManager(panel_container_)->FinishDragging();
217 void PanelWindowResizer::UpdateLauncherPosition() {
218 if (panel_container_) {
219 GetPanelLayoutManager(panel_container_)->shelf()->
220 UpdateIconPositionForWindow(GetTarget());
224 } // namespace aura