Disable TabDragController tests that fail with a real compositor.
[chromium-blink-merge.git] / ash / wm / panels / panel_window_resizer.cc
blobb1db4a543baac725bad9a51914c4a906b7ac0980
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/coordinate_conversion.h"
15 #include "ash/wm/panels/panel_layout_manager.h"
16 #include "ash/wm/window_state.h"
17 #include "ash/wm/window_util.h"
18 #include "base/memory/weak_ptr.h"
19 #include "ui/aura/client/aura_constants.h"
20 #include "ui/aura/client/window_tree_client.h"
21 #include "ui/aura/env.h"
22 #include "ui/aura/root_window.h"
23 #include "ui/aura/window.h"
24 #include "ui/aura/window_delegate.h"
25 #include "ui/base/hit_test.h"
26 #include "ui/base/ui_base_types.h"
27 #include "ui/gfx/screen.h"
28 #include "ui/views/widget/widget.h"
30 namespace ash {
32 namespace {
33 const int kPanelSnapToLauncherDistance = 30;
35 internal::PanelLayoutManager* GetPanelLayoutManager(
36 aura::Window* panel_container) {
37 DCHECK(panel_container->id() == internal::kShellWindowId_PanelContainer);
38 return static_cast<internal::PanelLayoutManager*>(
39 panel_container->layout_manager());
42 } // namespace
44 PanelWindowResizer::~PanelWindowResizer() {
47 // static
48 PanelWindowResizer*
49 PanelWindowResizer::Create(WindowResizer* next_window_resizer,
50 wm::WindowState* window_state) {
51 return new PanelWindowResizer(next_window_resizer, window_state);
54 void PanelWindowResizer::Drag(const gfx::Point& location, int event_flags) {
55 last_location_ = location;
56 wm::ConvertPointToScreen(GetTarget()->parent(), &last_location_);
57 if (!did_move_or_resize_) {
58 did_move_or_resize_ = true;
59 StartedDragging();
62 // Check if the destination has changed displays.
63 gfx::Screen* screen = Shell::GetScreen();
64 const gfx::Display dst_display =
65 screen->GetDisplayNearestPoint(last_location_);
66 if (dst_display.id() !=
67 screen->GetDisplayNearestWindow(panel_container_->GetRootWindow()).id()) {
68 // The panel is being dragged to a new display. If the previous container is
69 // the current parent of the panel it will be informed of the end of drag
70 // when the panel is reparented, otherwise let the previous container know
71 // the drag is complete. If we told the panel's parent that the drag was
72 // complete it would begin positioning the panel.
73 if (GetTarget()->parent() != panel_container_)
74 GetPanelLayoutManager(panel_container_)->FinishDragging();
75 aura::Window* dst_root = Shell::GetInstance()->display_controller()->
76 GetRootWindowForDisplayId(dst_display.id());
77 panel_container_ = Shell::GetContainer(
78 dst_root, internal::kShellWindowId_PanelContainer);
80 // The panel's parent already knows that the drag is in progress for this
81 // panel.
82 if (panel_container_ && GetTarget()->parent() != panel_container_)
83 GetPanelLayoutManager(panel_container_)->StartDragging(GetTarget());
85 gfx::Point offset;
86 gfx::Rect bounds(CalculateBoundsForDrag(location));
87 if (!(details().bounds_change & WindowResizer::kBoundsChange_Resizes)) {
88 window_state_->drag_details()->should_attach_to_shelf =
89 AttachToLauncher(bounds, &offset);
91 gfx::Point modified_location(location.x() + offset.x(),
92 location.y() + offset.y());
94 base::WeakPtr<PanelWindowResizer> resizer(weak_ptr_factory_.GetWeakPtr());
95 next_window_resizer_->Drag(modified_location, event_flags);
96 if (!resizer)
97 return;
99 if (details().should_attach_to_shelf &&
100 !(details().bounds_change & WindowResizer::kBoundsChange_Resizes)) {
101 UpdateLauncherPosition();
105 void PanelWindowResizer::CompleteDrag() {
106 // The root window can change when dragging into a different screen.
107 next_window_resizer_->CompleteDrag();
108 FinishDragging();
111 void PanelWindowResizer::RevertDrag() {
112 next_window_resizer_->RevertDrag();
113 window_state_->drag_details()->should_attach_to_shelf = was_attached_;
114 FinishDragging();
117 PanelWindowResizer::PanelWindowResizer(WindowResizer* next_window_resizer,
118 wm::WindowState* window_state)
119 : WindowResizer(window_state),
120 next_window_resizer_(next_window_resizer),
121 panel_container_(NULL),
122 initial_panel_container_(NULL),
123 did_move_or_resize_(false),
124 was_attached_(window_state->panel_attached()),
125 weak_ptr_factory_(this) {
126 DCHECK(details().is_resizable);
127 panel_container_ = Shell::GetContainer(
128 GetTarget()->GetRootWindow(),
129 internal::kShellWindowId_PanelContainer);
130 initial_panel_container_ = panel_container_;
133 bool PanelWindowResizer::AttachToLauncher(const gfx::Rect& bounds,
134 gfx::Point* offset) {
135 bool should_attach = false;
136 if (panel_container_) {
137 internal::PanelLayoutManager* panel_layout_manager =
138 GetPanelLayoutManager(panel_container_);
139 gfx::Rect launcher_bounds = ScreenUtil::ConvertRectFromScreen(
140 GetTarget()->parent(),
141 panel_layout_manager->shelf()->
142 shelf_widget()->GetWindowBoundsInScreen());
143 switch (panel_layout_manager->shelf()->alignment()) {
144 case SHELF_ALIGNMENT_BOTTOM:
145 if (bounds.bottom() >= (launcher_bounds.y() -
146 kPanelSnapToLauncherDistance)) {
147 should_attach = true;
148 offset->set_y(launcher_bounds.y() - bounds.height() - bounds.y());
150 break;
151 case SHELF_ALIGNMENT_LEFT:
152 if (bounds.x() <= (launcher_bounds.right() +
153 kPanelSnapToLauncherDistance)) {
154 should_attach = true;
155 offset->set_x(launcher_bounds.right() - bounds.x());
157 break;
158 case SHELF_ALIGNMENT_RIGHT:
159 if (bounds.right() >= (launcher_bounds.x() -
160 kPanelSnapToLauncherDistance)) {
161 should_attach = true;
162 offset->set_x(launcher_bounds.x() - bounds.width() - bounds.x());
164 break;
165 case SHELF_ALIGNMENT_TOP:
166 if (bounds.y() <= (launcher_bounds.bottom() +
167 kPanelSnapToLauncherDistance)) {
168 should_attach = true;
169 offset->set_y(launcher_bounds.bottom() - bounds.y());
171 break;
174 return should_attach;
177 void PanelWindowResizer::StartedDragging() {
178 // Tell the panel layout manager that we are dragging this panel before
179 // attaching it so that it does not get repositioned.
180 if (panel_container_)
181 GetPanelLayoutManager(panel_container_)->StartDragging(GetTarget());
182 if (!was_attached_) {
183 // Attach the panel while dragging placing it in front of other panels.
184 window_state_->set_continue_drag_after_reparent(true);
185 window_state_->set_panel_attached(true);
186 // We use root window coordinates to ensure that during the drag the panel
187 // is reparented to a container in the root window that has that window.
188 aura::Window* target = GetTarget();
189 aura::Window* target_root = target->GetRootWindow();
190 aura::Window* old_parent = target->parent();
191 aura::client::ParentWindowWithContext(
192 target, target_root, target_root->GetBoundsInScreen());
193 wm::ReparentTransientChildrenOfChild(target, old_parent, target->parent());
197 void PanelWindowResizer::FinishDragging() {
198 if (!did_move_or_resize_)
199 return;
200 if (window_state_->panel_attached() != details().should_attach_to_shelf) {
201 window_state_->set_panel_attached(details().should_attach_to_shelf);
202 // We use last known location to ensure that after the drag the panel
203 // is reparented to a container in the root window that has that location.
204 aura::Window* target = GetTarget();
205 aura::Window* target_root = target->GetRootWindow();
206 aura::Window* old_parent = target->parent();
207 aura::client::ParentWindowWithContext(
208 target, target_root, gfx::Rect(last_location_, gfx::Size()));
209 wm::ReparentTransientChildrenOfChild(target, old_parent, target->parent());
212 // If we started the drag in one root window and moved into another root
213 // but then canceled the drag we may need to inform the original layout
214 // manager that the drag is finished.
215 if (initial_panel_container_ != panel_container_)
216 GetPanelLayoutManager(initial_panel_container_)->FinishDragging();
217 if (panel_container_)
218 GetPanelLayoutManager(panel_container_)->FinishDragging();
221 void PanelWindowResizer::UpdateLauncherPosition() {
222 if (panel_container_) {
223 GetPanelLayoutManager(panel_container_)->shelf()->
224 UpdateIconPositionForWindow(GetTarget());
228 } // namespace aura