Chromium Code Reviews| 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 |