Updating XTBs based on .GRDs from branch master
[chromium-blink-merge.git] / ash / wm / panels / panel_window_resizer.cc
blob57a8de5a947a0bc25fbad51473b81b1799320789
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/window_tree_host_manager.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()
74 ->window_tree_host_manager()
75 ->GetRootWindowForDisplayId(dst_display.id());
76 panel_container_ =
77 Shell::GetContainer(dst_root, kShellWindowId_PanelContainer);
79 // The panel's parent already knows that the drag is in progress for this
80 // panel.
81 if (panel_container_ && GetTarget()->parent() != panel_container_)
82 GetPanelLayoutManager(panel_container_)->StartDragging(GetTarget());
84 gfx::Point offset;
85 gfx::Rect bounds(CalculateBoundsForDrag(location));
86 if (!(details().bounds_change & WindowResizer::kBoundsChange_Resizes)) {
87 window_state_->drag_details()->should_attach_to_shelf =
88 AttachToLauncher(bounds, &offset);
90 gfx::Point modified_location(location.x() + offset.x(),
91 location.y() + offset.y());
93 base::WeakPtr<PanelWindowResizer> resizer(weak_ptr_factory_.GetWeakPtr());
94 next_window_resizer_->Drag(modified_location, event_flags);
95 if (!resizer)
96 return;
98 if (details().should_attach_to_shelf &&
99 !(details().bounds_change & WindowResizer::kBoundsChange_Resizes)) {
100 UpdateLauncherPosition();
104 void PanelWindowResizer::CompleteDrag() {
105 // The root window can change when dragging into a different screen.
106 next_window_resizer_->CompleteDrag();
107 FinishDragging();
110 void PanelWindowResizer::RevertDrag() {
111 next_window_resizer_->RevertDrag();
112 window_state_->drag_details()->should_attach_to_shelf = was_attached_;
113 FinishDragging();
116 PanelWindowResizer::PanelWindowResizer(WindowResizer* next_window_resizer,
117 wm::WindowState* window_state)
118 : WindowResizer(window_state),
119 next_window_resizer_(next_window_resizer),
120 panel_container_(NULL),
121 initial_panel_container_(NULL),
122 did_move_or_resize_(false),
123 was_attached_(window_state->panel_attached()),
124 weak_ptr_factory_(this) {
125 DCHECK(details().is_resizable);
126 panel_container_ = Shell::GetContainer(GetTarget()->GetRootWindow(),
127 kShellWindowId_PanelContainer);
128 initial_panel_container_ = panel_container_;
131 bool PanelWindowResizer::AttachToLauncher(const gfx::Rect& bounds,
132 gfx::Point* offset) {
133 bool should_attach = false;
134 if (panel_container_) {
135 PanelLayoutManager* panel_layout_manager =
136 GetPanelLayoutManager(panel_container_);
137 gfx::Rect launcher_bounds = ScreenUtil::ConvertRectFromScreen(
138 GetTarget()->parent(),
139 panel_layout_manager->shelf()->
140 shelf_widget()->GetWindowBoundsInScreen());
141 switch (panel_layout_manager->shelf()->alignment()) {
142 case SHELF_ALIGNMENT_BOTTOM:
143 if (bounds.bottom() >= (launcher_bounds.y() -
144 kPanelSnapToLauncherDistance)) {
145 should_attach = true;
146 offset->set_y(launcher_bounds.y() - bounds.height() - bounds.y());
148 break;
149 case SHELF_ALIGNMENT_LEFT:
150 if (bounds.x() <= (launcher_bounds.right() +
151 kPanelSnapToLauncherDistance)) {
152 should_attach = true;
153 offset->set_x(launcher_bounds.right() - bounds.x());
155 break;
156 case SHELF_ALIGNMENT_RIGHT:
157 if (bounds.right() >= (launcher_bounds.x() -
158 kPanelSnapToLauncherDistance)) {
159 should_attach = true;
160 offset->set_x(launcher_bounds.x() - bounds.width() - bounds.x());
162 break;
163 case SHELF_ALIGNMENT_TOP:
164 if (bounds.y() <= (launcher_bounds.bottom() +
165 kPanelSnapToLauncherDistance)) {
166 should_attach = true;
167 offset->set_y(launcher_bounds.bottom() - bounds.y());
169 break;
172 return should_attach;
175 void PanelWindowResizer::StartedDragging() {
176 // Tell the panel layout manager that we are dragging this panel before
177 // attaching it so that it does not get repositioned.
178 if (panel_container_)
179 GetPanelLayoutManager(panel_container_)->StartDragging(GetTarget());
180 if (!was_attached_) {
181 // Attach the panel while dragging placing it in front of other panels.
182 window_state_->set_panel_attached(true);
183 // We use root window coordinates to ensure that during the drag the panel
184 // is reparented to a container in the root window that has that window.
185 aura::Window* target = GetTarget();
186 aura::Window* target_root = target->GetRootWindow();
187 aura::Window* old_parent = target->parent();
188 aura::client::ParentWindowWithContext(
189 target, target_root, target_root->GetBoundsInScreen());
190 wm::ReparentTransientChildrenOfChild(target, old_parent, target->parent());
194 void PanelWindowResizer::FinishDragging() {
195 if (!did_move_or_resize_)
196 return;
197 if (window_state_->panel_attached() != details().should_attach_to_shelf) {
198 window_state_->set_panel_attached(details().should_attach_to_shelf);
199 // We use last known location to ensure that after the drag the panel
200 // is reparented to a container in the root window that has that location.
201 aura::Window* target = GetTarget();
202 aura::Window* target_root = target->GetRootWindow();
203 aura::Window* old_parent = target->parent();
204 aura::client::ParentWindowWithContext(
205 target, target_root, gfx::Rect(last_location_, gfx::Size()));
206 wm::ReparentTransientChildrenOfChild(target, old_parent, target->parent());
209 // If we started the drag in one root window and moved into another root
210 // but then canceled the drag we may need to inform the original layout
211 // manager that the drag is finished.
212 if (initial_panel_container_ != panel_container_)
213 GetPanelLayoutManager(initial_panel_container_)->FinishDragging();
214 if (panel_container_)
215 GetPanelLayoutManager(panel_container_)->FinishDragging();
218 void PanelWindowResizer::UpdateLauncherPosition() {
219 if (panel_container_) {
220 GetPanelLayoutManager(panel_container_)->shelf()->
221 UpdateIconPositionForWindow(GetTarget());
225 } // namespace aura