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 // We want to to stack the panels like a deck of cards: | |
sky
2012/04/26 04:30:31
Be warned, we're going to make the launcher suppor
dcheng
2012/04/26 06:30:59
Doh. Thanks for the heads up. We're definitely goi
| |
231 // ,--,--,--,-------.--.--. | |
232 // | | | | | | | | |
233 // | | | | | | | | |
234 // | |
235 // Since there's no way of extracting a panel ordering from the launcher, | |
236 // we build an ordering based on the x-coordinate of the panel bounds... | |
237 // It's a little hacky... | |
sky
2012/04/26 04:30:31
You can actually get this information from the Lau
dcheng
2012/04/26 06:30:59
I've updated this comment to better reflect the cu
| |
238 std::map<int, aura::Window*> window_ordering; | |
239 | |
240 for (PanelList::const_iterator it = panel_windows_.begin(); | |
241 it != panel_windows_.end(); ++it) { | |
242 window_ordering.insert(std::make_pair((*it)->bounds().x(), *it)); | |
243 } | |
244 | |
245 if (!active_panel) { | |
sky
2012/04/26 04:30:31
Since this can early return, make it first.
dcheng
2012/04/26 06:30:59
Done.
| |
246 if (!last_active_panel_) | |
247 return; | |
248 active_panel = last_active_panel_; | |
sky
2012/04/26 04:30:31
Should you return if last_active_panel_ is NULL?
dcheng
2012/04/26 06:30:59
No, this can happen if this is the first time a pa
sky
2012/04/26 16:05:10
Can't it also happen if last_active_panel_ is clos
dcheng
2012/04/26 18:10:25
Good point--it didn't occur to me since there's no
sky
2012/04/26 19:06:59
Of course. You're right.
| |
249 } | |
250 | |
251 aura::Window* previous_panel = NULL; | |
252 for (std::map<int, aura::Window*>::const_iterator it = | |
253 window_ordering.begin(); | |
254 it != window_ordering.end() && it->second != active_panel; ++it) { | |
255 if (previous_panel) | |
256 panel_container_->StackChildAbove(it->second, previous_panel); | |
257 previous_panel = it->second; | |
258 } | |
259 | |
260 previous_panel = NULL; | |
261 for (std::map<int, aura::Window*>::const_reverse_iterator it = | |
262 window_ordering.rbegin(); | |
263 it != window_ordering.rend() && it->second != active_panel; ++it) { | |
264 if (previous_panel) | |
265 panel_container_->StackChildAbove(it->second, previous_panel); | |
266 previous_panel = it->second; | |
267 } | |
268 | |
269 panel_container_->StackChildAtTop(active_panel); | |
270 last_active_panel_ = active_panel; | |
200 } | 271 } |
201 | 272 |
202 } // namespace internal | 273 } // namespace internal |
203 } // namespace ash | 274 } // namespace ash |
OLD | NEW |