OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ash/wm/panel_layout_manager.h" | 5 #include "ash/wm/panel_layout_manager.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "ash/launcher/launcher.h" | 9 #include "ash/launcher/launcher.h" |
10 #include "ash/shell.h" | 10 #include "ash/shell.h" |
11 #include "ash/wm/property_util.h" | 11 #include "ash/wm/property_util.h" |
12 #include "base/auto_reset.h" | 12 #include "base/auto_reset.h" |
| 13 #include "ui/aura/client/activation_client.h" |
13 #include "ui/aura/client/aura_constants.h" | 14 #include "ui/aura/client/aura_constants.h" |
14 #include "ui/aura/root_window.h" | 15 #include "ui/aura/root_window.h" |
15 #include "ui/aura/window.h" | 16 #include "ui/aura/window.h" |
16 #include "ui/gfx/rect.h" | 17 #include "ui/gfx/rect.h" |
17 #include "ui/gfx/size.h" | 18 #include "ui/gfx/size.h" |
18 #include "ui/views/widget/widget.h" | 19 #include "ui/views/widget/widget.h" |
19 | 20 |
20 namespace { | 21 namespace { |
21 const int kPanelMarginEdge = 4; | 22 const int kPanelMarginEdge = 4; |
22 const int kPanelMarginMiddle = 8; | 23 const int kPanelMarginMiddle = 8; |
23 | 24 |
24 const int kMinimizedHeight = 24; | 25 const int kMinimizedHeight = 24; |
25 | 26 |
26 const float kMaxHeightFactor = .80f; | 27 const float kMaxHeightFactor = .80f; |
27 const float kMaxWidthFactor = .50f; | 28 const float kMaxWidthFactor = .50f; |
28 } | 29 } |
29 | 30 |
30 namespace ash { | 31 namespace ash { |
31 namespace internal { | 32 namespace internal { |
32 | 33 |
33 //////////////////////////////////////////////////////////////////////////////// | 34 //////////////////////////////////////////////////////////////////////////////// |
34 // PanelLayoutManager public implementation: | 35 // PanelLayoutManager public implementation: |
35 | |
36 PanelLayoutManager::PanelLayoutManager(aura::Window* panel_container) | 36 PanelLayoutManager::PanelLayoutManager(aura::Window* panel_container) |
37 : panel_container_(panel_container), | 37 : panel_container_(panel_container), |
38 in_layout_(false), | 38 in_layout_(false), |
39 dragged_panel_(NULL), | 39 dragged_panel_(NULL), |
40 launcher_(NULL) { | 40 launcher_(NULL), |
| 41 last_active_panel_(NULL) { |
41 DCHECK(panel_container); | 42 DCHECK(panel_container); |
| 43 Shell::GetRootWindow()->AddObserver(this); |
42 } | 44 } |
43 | 45 |
44 PanelLayoutManager::~PanelLayoutManager() { | 46 PanelLayoutManager::~PanelLayoutManager() { |
45 if (launcher_) | 47 if (launcher_) |
46 launcher_->RemoveIconObserver(this); | 48 launcher_->RemoveIconObserver(this); |
| 49 Shell::GetRootWindow()->RemoveObserver(this); |
47 } | 50 } |
48 | 51 |
49 void PanelLayoutManager::StartDragging(aura::Window* panel) { | 52 void PanelLayoutManager::StartDragging(aura::Window* panel) { |
50 DCHECK(!dragged_panel_); | 53 DCHECK(!dragged_panel_); |
51 DCHECK(panel->parent() == panel_container_); | 54 DCHECK(panel->parent() == panel_container_); |
52 dragged_panel_ = panel; | 55 dragged_panel_ = panel; |
53 } | 56 } |
54 | 57 |
55 void PanelLayoutManager::FinishDragging() { | 58 void PanelLayoutManager::FinishDragging() { |
56 DCHECK(dragged_panel_); | 59 DCHECK(dragged_panel_); |
(...skipping 28 matching lines...) Expand all Loading... |
85 gfx::Rect(old_bounds.x(), | 88 gfx::Rect(old_bounds.x(), |
86 old_bounds.bottom() - kMinimizedHeight, | 89 old_bounds.bottom() - kMinimizedHeight, |
87 old_bounds.width(), | 90 old_bounds.width(), |
88 kMinimizedHeight)); | 91 kMinimizedHeight)); |
89 } | 92 } |
90 Relayout(); | 93 Relayout(); |
91 } | 94 } |
92 | 95 |
93 //////////////////////////////////////////////////////////////////////////////// | 96 //////////////////////////////////////////////////////////////////////////////// |
94 // PanelLayoutManager, aura::LayoutManager implementation: | 97 // PanelLayoutManager, aura::LayoutManager implementation: |
95 | |
96 void PanelLayoutManager::OnWindowResized() { | 98 void PanelLayoutManager::OnWindowResized() { |
97 Relayout(); | 99 Relayout(); |
98 } | 100 } |
99 | 101 |
100 void PanelLayoutManager::OnWindowAddedToLayout(aura::Window* child) { | 102 void PanelLayoutManager::OnWindowAddedToLayout(aura::Window* child) { |
101 panel_windows_.push_back(child); | 103 panel_windows_.push_back(child); |
102 Relayout(); | 104 Relayout(); |
103 } | 105 } |
104 | 106 |
105 void PanelLayoutManager::OnWillRemoveWindowFromLayout(aura::Window* child) { | 107 void PanelLayoutManager::OnWillRemoveWindowFromLayout(aura::Window* child) { |
106 PanelList::iterator found = | 108 PanelList::iterator found = |
107 std::find(panel_windows_.begin(), panel_windows_.end(), child); | 109 std::find(panel_windows_.begin(), panel_windows_.end(), child); |
108 if (found != panel_windows_.end()) | 110 if (found != panel_windows_.end()) |
109 panel_windows_.erase(found); | 111 panel_windows_.erase(found); |
110 | 112 |
111 if (dragged_panel_ == child) | 113 if (dragged_panel_ == child) |
112 dragged_panel_ = NULL; | 114 dragged_panel_ = NULL; |
113 | 115 |
| 116 if (last_active_panel_ == child) |
| 117 last_active_panel_ = NULL; |
| 118 |
114 Relayout(); | 119 Relayout(); |
115 } | 120 } |
116 | 121 |
117 void PanelLayoutManager::OnWindowRemovedFromLayout(aura::Window* child) { | 122 void PanelLayoutManager::OnWindowRemovedFromLayout(aura::Window* child) { |
118 } | 123 } |
119 | 124 |
120 void PanelLayoutManager::OnChildWindowVisibilityChanged(aura::Window* child, | 125 void PanelLayoutManager::OnChildWindowVisibilityChanged(aura::Window* child, |
121 bool visible) { | 126 bool visible) { |
122 Relayout(); | 127 Relayout(); |
123 } | 128 } |
(...skipping 25 matching lines...) Expand all Loading... |
149 panel_windows_.erase(dragged_panel_iter); | 154 panel_windows_.erase(dragged_panel_iter); |
150 panel_windows_.insert(new_position, dragged_panel_); | 155 panel_windows_.insert(new_position, dragged_panel_); |
151 } | 156 } |
152 } | 157 } |
153 | 158 |
154 SetChildBoundsDirect(child, bounds); | 159 SetChildBoundsDirect(child, bounds); |
155 Relayout(); | 160 Relayout(); |
156 } | 161 } |
157 | 162 |
158 //////////////////////////////////////////////////////////////////////////////// | 163 //////////////////////////////////////////////////////////////////////////////// |
159 // PanelLayoutManager, aura::LauncherIconObserver implementation: | 164 // PanelLayoutManager, ash::LauncherIconObserver implementation: |
160 | |
161 void PanelLayoutManager::OnLauncherIconPositionsChanged() { | 165 void PanelLayoutManager::OnLauncherIconPositionsChanged() { |
162 Relayout(); | 166 Relayout(); |
163 } | 167 } |
164 | 168 |
165 //////////////////////////////////////////////////////////////////////////////// | 169 //////////////////////////////////////////////////////////////////////////////// |
| 170 // PanelLayoutManager, aura::WindowObserver implementation: |
| 171 void PanelLayoutManager::OnWindowPropertyChanged(aura::Window* window, |
| 172 const void* key, |
| 173 intptr_t old) { |
| 174 if (key == aura::client::kRootWindowActiveWindowKey) { |
| 175 aura::Window* active = window->GetProperty( |
| 176 aura::client::kRootWindowActiveWindowKey); |
| 177 if (active && active->type() == aura::client::WINDOW_TYPE_PANEL) |
| 178 UpdateStacking(active); |
| 179 } |
| 180 } |
| 181 |
| 182 |
| 183 //////////////////////////////////////////////////////////////////////////////// |
166 // PanelLayoutManager private implementation: | 184 // PanelLayoutManager private implementation: |
167 | |
168 void PanelLayoutManager::Relayout() { | 185 void PanelLayoutManager::Relayout() { |
169 if (in_layout_) | 186 if (in_layout_) |
170 return; | 187 return; |
171 AutoReset<bool> auto_reset_in_layout(&in_layout_, true); | 188 AutoReset<bool> auto_reset_in_layout(&in_layout_, true); |
172 | 189 |
173 ash::Shell* shell = ash::Shell::GetInstance(); | 190 ash::Shell* shell = ash::Shell::GetInstance(); |
174 | 191 |
| 192 aura::Window* active_panel = NULL; |
175 for (PanelList::iterator iter = panel_windows_.begin(); | 193 for (PanelList::iterator iter = panel_windows_.begin(); |
176 iter != panel_windows_.end(); ++iter) { | 194 iter != panel_windows_.end(); ++iter) { |
177 aura::Window* panel_win = *iter; | 195 aura::Window* panel = *iter; |
178 if (!panel_win->IsVisible() || panel_win == dragged_panel_) | 196 if (!panel->IsVisible() || panel == dragged_panel_) |
179 continue; | 197 continue; |
180 | 198 |
181 gfx::Rect icon_bounds = | 199 gfx::Rect icon_bounds = |
182 shell->launcher()->GetScreenBoundsOfItemIconForWindow(panel_win); | 200 shell->launcher()->GetScreenBoundsOfItemIconForWindow(panel); |
183 | 201 |
184 // An empty rect indicates that there is no icon for the panel in the | 202 // An empty rect indicates that there is no icon for the panel in the |
185 // launcher. Just use the current bounds, as there's no icon to draw the | 203 // launcher. Just use the current bounds, as there's no icon to draw the |
186 // panel above. | 204 // panel above. |
| 205 // TODO(dcheng): Need to anchor to overflow icon. |
187 if (icon_bounds.IsEmpty()) | 206 if (icon_bounds.IsEmpty()) |
188 continue; | 207 continue; |
189 | 208 |
| 209 if (panel->HasFocus()) { |
| 210 DCHECK(!active_panel); |
| 211 active_panel = panel; |
| 212 } |
| 213 |
190 gfx::Point icon_origin = icon_bounds.origin(); | 214 gfx::Point icon_origin = icon_bounds.origin(); |
191 aura::Window::ConvertPointToWindow(panel_container_->GetRootWindow(), | 215 aura::Window::ConvertPointToWindow(panel_container_->GetRootWindow(), |
192 panel_container_, &icon_origin); | 216 panel_container_, &icon_origin); |
193 | 217 |
194 gfx::Rect bounds = panel_win->bounds(); | 218 // TODO(dcheng): Need to clamp to screen edges. |
| 219 gfx::Rect bounds = panel->bounds(); |
195 bounds.set_x( | 220 bounds.set_x( |
196 icon_origin.x() + icon_bounds.width() / 2 - bounds.width() / 2); | 221 icon_origin.x() + icon_bounds.width() / 2 - bounds.width() / 2); |
197 bounds.set_y(icon_origin.y() - bounds.height()); | 222 bounds.set_y(icon_origin.y() - bounds.height()); |
198 SetChildBoundsDirect(panel_win, bounds); | 223 SetChildBoundsDirect(panel, bounds); |
199 } | 224 } |
| 225 |
| 226 UpdateStacking(active_panel); |
| 227 } |
| 228 |
| 229 void PanelLayoutManager::UpdateStacking(aura::Window* active_panel) { |
| 230 if (!active_panel) { |
| 231 if (!last_active_panel_) |
| 232 return; |
| 233 active_panel = last_active_panel_; |
| 234 } |
| 235 |
| 236 // We want to to stack the panels like a deck of cards: |
| 237 // ,--,--,--,-------.--.--. |
| 238 // | | | | | | | |
| 239 // | | | | | | | |
| 240 // |
| 241 // We use the middle of each panel to figure out how to stack the panels. This |
| 242 // allows us to update the stacking when a panel is being dragged around by |
| 243 // the titlebar--even though it doesn't update the launcher icon positions, we |
| 244 // still want the visual effect. |
| 245 std::map<int, aura::Window*> window_ordering; |
| 246 for (PanelList::const_iterator it = panel_windows_.begin(); |
| 247 it != panel_windows_.end(); ++it) { |
| 248 gfx::Rect bounds = (*it)->bounds(); |
| 249 window_ordering.insert(std::make_pair(bounds.x() + bounds.width() / 2, |
| 250 *it)); |
| 251 } |
| 252 |
| 253 aura::Window* previous_panel = NULL; |
| 254 for (std::map<int, aura::Window*>::const_iterator it = |
| 255 window_ordering.begin(); |
| 256 it != window_ordering.end() && it->second != active_panel; ++it) { |
| 257 if (previous_panel) |
| 258 panel_container_->StackChildAbove(it->second, previous_panel); |
| 259 previous_panel = it->second; |
| 260 } |
| 261 |
| 262 previous_panel = NULL; |
| 263 for (std::map<int, aura::Window*>::const_reverse_iterator it = |
| 264 window_ordering.rbegin(); |
| 265 it != window_ordering.rend() && it->second != active_panel; ++it) { |
| 266 if (previous_panel) |
| 267 panel_container_->StackChildAbove(it->second, previous_panel); |
| 268 previous_panel = it->second; |
| 269 } |
| 270 |
| 271 panel_container_->StackChildAtTop(active_panel); |
| 272 last_active_panel_ = active_panel; |
200 } | 273 } |
201 | 274 |
202 } // namespace internal | 275 } // namespace internal |
203 } // namespace ash | 276 } // namespace ash |
OLD | NEW |