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/frame_painter.h" |
11 #include "ash/wm/property_util.h" | 12 #include "ash/wm/property_util.h" |
12 #include "base/auto_reset.h" | 13 #include "base/auto_reset.h" |
| 14 #include "base/bind.h" |
| 15 #include "base/bind_helpers.h" |
| 16 #include "third_party/skia/include/core/SkColor.h" |
| 17 #include "third_party/skia/include/core/SkPaint.h" |
| 18 #include "third_party/skia/include/core/SkPath.h" |
13 #include "ui/aura/client/activation_client.h" | 19 #include "ui/aura/client/activation_client.h" |
14 #include "ui/aura/client/aura_constants.h" | 20 #include "ui/aura/client/aura_constants.h" |
15 #include "ui/aura/root_window.h" | 21 #include "ui/aura/root_window.h" |
16 #include "ui/aura/window.h" | 22 #include "ui/aura/window.h" |
| 23 #include "ui/gfx/canvas.h" |
17 #include "ui/gfx/rect.h" | 24 #include "ui/gfx/rect.h" |
18 #include "ui/gfx/size.h" | 25 #include "ui/views/background.h" |
19 #include "ui/views/widget/widget.h" | 26 #include "ui/views/widget/widget.h" |
20 | 27 |
| 28 namespace ash { |
| 29 namespace internal { |
| 30 |
21 namespace { | 31 namespace { |
22 const int kPanelMarginEdge = 4; | 32 const int kPanelMarginEdge = 4; |
23 const int kPanelMarginMiddle = 8; | 33 const int kPanelMarginMiddle = 8; |
24 | 34 |
25 const int kMinimizedHeight = 24; | 35 const int kMinimizedHeight = 24; |
26 | 36 |
27 const float kMaxHeightFactor = .80f; | 37 const float kMaxHeightFactor = .80f; |
28 const float kMaxWidthFactor = .50f; | 38 const float kMaxWidthFactor = .50f; |
29 } | |
30 | 39 |
31 namespace ash { | 40 // Callout arrow dimensions. |
32 namespace internal { | 41 const int kArrowWidth = 20; |
| 42 const int kArrowHeight = 10; |
| 43 |
| 44 class CalloutWidgetBackground : public views::Background { |
| 45 public: |
| 46 CalloutWidgetBackground() {} |
| 47 virtual void Paint(gfx::Canvas* canvas, views::View* view) const OVERRIDE { |
| 48 SkPath path; |
| 49 // TODO(dcheng): Verify if this results in off by one errors. |
| 50 path.moveTo(SkIntToScalar(0), SkIntToScalar(0)); |
| 51 path.lineTo(SkIntToScalar(kArrowWidth / 2), SkIntToScalar(kArrowHeight)); |
| 52 path.lineTo(SkIntToScalar(kArrowWidth), SkIntToScalar(0)); |
| 53 |
| 54 // Use the same opacity and colors as the header for now. |
| 55 SkPaint paint; |
| 56 paint.setStyle(SkPaint::kFill_Style); |
| 57 paint.setColor( |
| 58 SkColorSetARGB(FramePainter::kActiveWindowOpacity, 189, 189, 189)); |
| 59 canvas->DrawPath(path, paint); |
| 60 } |
| 61 |
| 62 private: |
| 63 DISALLOW_COPY_AND_ASSIGN(CalloutWidgetBackground); |
| 64 }; |
| 65 |
| 66 } // namespace |
33 | 67 |
34 //////////////////////////////////////////////////////////////////////////////// | 68 //////////////////////////////////////////////////////////////////////////////// |
35 // PanelLayoutManager public implementation: | 69 // PanelLayoutManager public implementation: |
36 PanelLayoutManager::PanelLayoutManager(aura::Window* panel_container) | 70 PanelLayoutManager::PanelLayoutManager(aura::Window* panel_container) |
37 : panel_container_(panel_container), | 71 : panel_container_(panel_container), |
38 in_layout_(false), | 72 in_layout_(false), |
39 dragged_panel_(NULL), | 73 dragged_panel_(NULL), |
40 launcher_(NULL), | 74 launcher_(NULL), |
41 last_active_panel_(NULL) { | 75 last_active_panel_(NULL), |
| 76 callout_widget_(new views::Widget), |
| 77 weak_factory_(this) { |
42 DCHECK(panel_container); | 78 DCHECK(panel_container); |
| 79 views::Widget::InitParams params; |
| 80 params.type = views::Widget::InitParams::TYPE_POPUP; |
| 81 params.transparent = true; |
| 82 params.can_activate = false; |
| 83 params.keep_on_top = true; |
| 84 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
| 85 params.parent = panel_container_; |
| 86 params.bounds.set_width(kArrowWidth); |
| 87 params.bounds.set_height(kArrowHeight); |
| 88 // Why do we need this and can_activate = false? |
| 89 callout_widget_->set_focus_on_creation(false); |
| 90 callout_widget_->Init(params); |
| 91 views::View* content_view = new views::View; |
| 92 content_view->set_background(new CalloutWidgetBackground); |
| 93 callout_widget_->SetContentsView(content_view); |
43 Shell::GetRootWindow()->AddObserver(this); | 94 Shell::GetRootWindow()->AddObserver(this); |
44 } | 95 } |
45 | 96 |
46 PanelLayoutManager::~PanelLayoutManager() { | 97 PanelLayoutManager::~PanelLayoutManager() { |
47 if (launcher_) | 98 if (launcher_) |
48 launcher_->RemoveIconObserver(this); | 99 launcher_->RemoveIconObserver(this); |
49 Shell::GetRootWindow()->RemoveObserver(this); | 100 Shell::GetRootWindow()->RemoveObserver(this); |
50 } | 101 } |
51 | 102 |
52 void PanelLayoutManager::StartDragging(aura::Window* panel) { | 103 void PanelLayoutManager::StartDragging(aura::Window* panel) { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
94 Relayout(); | 145 Relayout(); |
95 } | 146 } |
96 | 147 |
97 //////////////////////////////////////////////////////////////////////////////// | 148 //////////////////////////////////////////////////////////////////////////////// |
98 // PanelLayoutManager, aura::LayoutManager implementation: | 149 // PanelLayoutManager, aura::LayoutManager implementation: |
99 void PanelLayoutManager::OnWindowResized() { | 150 void PanelLayoutManager::OnWindowResized() { |
100 Relayout(); | 151 Relayout(); |
101 } | 152 } |
102 | 153 |
103 void PanelLayoutManager::OnWindowAddedToLayout(aura::Window* child) { | 154 void PanelLayoutManager::OnWindowAddedToLayout(aura::Window* child) { |
| 155 if (child == callout_widget_->GetNativeWindow()) |
| 156 return; |
104 panel_windows_.push_back(child); | 157 panel_windows_.push_back(child); |
105 Relayout(); | 158 Relayout(); |
106 } | 159 } |
107 | 160 |
108 void PanelLayoutManager::OnWillRemoveWindowFromLayout(aura::Window* child) { | 161 void PanelLayoutManager::OnWillRemoveWindowFromLayout(aura::Window* child) { |
109 PanelList::iterator found = | 162 PanelList::iterator found = |
110 std::find(panel_windows_.begin(), panel_windows_.end(), child); | 163 std::find(panel_windows_.begin(), panel_windows_.end(), child); |
111 if (found != panel_windows_.end()) | 164 if (found != panel_windows_.end()) |
112 panel_windows_.erase(found); | 165 panel_windows_.erase(found); |
113 | 166 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
168 } | 221 } |
169 | 222 |
170 //////////////////////////////////////////////////////////////////////////////// | 223 //////////////////////////////////////////////////////////////////////////////// |
171 // PanelLayoutManager, aura::WindowObserver implementation: | 224 // PanelLayoutManager, aura::WindowObserver implementation: |
172 void PanelLayoutManager::OnWindowPropertyChanged(aura::Window* window, | 225 void PanelLayoutManager::OnWindowPropertyChanged(aura::Window* window, |
173 const void* key, | 226 const void* key, |
174 intptr_t old) { | 227 intptr_t old) { |
175 if (key == aura::client::kRootWindowActiveWindowKey) { | 228 if (key == aura::client::kRootWindowActiveWindowKey) { |
176 aura::Window* active = window->GetProperty( | 229 aura::Window* active = window->GetProperty( |
177 aura::client::kRootWindowActiveWindowKey); | 230 aura::client::kRootWindowActiveWindowKey); |
178 if (active && active->type() == aura::client::WINDOW_TYPE_PANEL) | 231 if (active && active->type() == aura::client::WINDOW_TYPE_PANEL) { |
179 UpdateStacking(active); | 232 UpdateStacking(active); |
| 233 UpdateCallout(active); |
| 234 } else { |
| 235 UpdateCallout(NULL); |
| 236 } |
180 } | 237 } |
181 } | 238 } |
182 | 239 |
183 | 240 |
184 //////////////////////////////////////////////////////////////////////////////// | 241 //////////////////////////////////////////////////////////////////////////////// |
185 // PanelLayoutManager private implementation: | 242 // PanelLayoutManager private implementation: |
186 void PanelLayoutManager::Relayout() { | 243 void PanelLayoutManager::Relayout() { |
187 if (in_layout_) | 244 if (in_layout_) |
188 return; | 245 return; |
189 AutoReset<bool> auto_reset_in_layout(&in_layout_, true); | 246 AutoReset<bool> auto_reset_in_layout(&in_layout_, true); |
190 | 247 |
| 248 int launcher_top = launcher_->widget()->GetWindowScreenBounds().y(); |
191 aura::Window* active_panel = NULL; | 249 aura::Window* active_panel = NULL; |
192 for (PanelList::iterator iter = panel_windows_.begin(); | 250 for (PanelList::iterator iter = panel_windows_.begin(); |
193 iter != panel_windows_.end(); ++iter) { | 251 iter != panel_windows_.end(); ++iter) { |
194 aura::Window* panel = *iter; | 252 aura::Window* panel = *iter; |
195 if (!panel->IsVisible() || panel == dragged_panel_) | 253 if (!panel->IsVisible() || panel == dragged_panel_) |
196 continue; | 254 continue; |
197 | 255 |
198 gfx::Rect icon_bounds = | 256 gfx::Rect icon_bounds = |
199 launcher_->GetScreenBoundsOfItemIconForWindow(panel); | 257 launcher_->GetScreenBoundsOfItemIconForWindow(panel); |
200 | 258 |
(...skipping 10 matching lines...) Expand all Loading... |
211 } | 269 } |
212 | 270 |
213 gfx::Point icon_origin = icon_bounds.origin(); | 271 gfx::Point icon_origin = icon_bounds.origin(); |
214 aura::Window::ConvertPointToWindow(panel_container_->GetRootWindow(), | 272 aura::Window::ConvertPointToWindow(panel_container_->GetRootWindow(), |
215 panel_container_, &icon_origin); | 273 panel_container_, &icon_origin); |
216 | 274 |
217 // TODO(dcheng): Need to clamp to screen edges. | 275 // TODO(dcheng): Need to clamp to screen edges. |
218 gfx::Rect bounds = panel->bounds(); | 276 gfx::Rect bounds = panel->bounds(); |
219 bounds.set_x( | 277 bounds.set_x( |
220 icon_origin.x() + icon_bounds.width() / 2 - bounds.width() / 2); | 278 icon_origin.x() + icon_bounds.width() / 2 - bounds.width() / 2); |
221 bounds.set_y(icon_origin.y() - bounds.height()); | 279 bounds.set_y(launcher_top - bounds.height()); |
222 SetChildBoundsDirect(panel, bounds); | 280 SetChildBoundsDirect(panel, bounds); |
223 } | 281 } |
224 | 282 |
225 UpdateStacking(active_panel); | 283 UpdateStacking(active_panel); |
| 284 UpdateCallout(active_panel); |
226 } | 285 } |
227 | 286 |
228 void PanelLayoutManager::UpdateStacking(aura::Window* active_panel) { | 287 void PanelLayoutManager::UpdateStacking(aura::Window* active_panel) { |
229 if (!active_panel) { | 288 if (!active_panel) { |
230 if (!last_active_panel_) | 289 if (!last_active_panel_) |
231 return; | 290 return; |
232 active_panel = last_active_panel_; | 291 active_panel = last_active_panel_; |
233 } | 292 } |
234 | 293 |
235 // We want to to stack the panels like a deck of cards: | 294 // We want to to stack the panels like a deck of cards: |
(...skipping 28 matching lines...) Expand all Loading... |
264 it != window_ordering.rend() && it->second != active_panel; ++it) { | 323 it != window_ordering.rend() && it->second != active_panel; ++it) { |
265 if (previous_panel) | 324 if (previous_panel) |
266 panel_container_->StackChildAbove(it->second, previous_panel); | 325 panel_container_->StackChildAbove(it->second, previous_panel); |
267 previous_panel = it->second; | 326 previous_panel = it->second; |
268 } | 327 } |
269 | 328 |
270 panel_container_->StackChildAtTop(active_panel); | 329 panel_container_->StackChildAtTop(active_panel); |
271 last_active_panel_ = active_panel; | 330 last_active_panel_ = active_panel; |
272 } | 331 } |
273 | 332 |
| 333 void PanelLayoutManager::UpdateCallout(aura::Window* active_panel) { |
| 334 weak_factory_.InvalidateWeakPtrs(); |
| 335 // TODO(dcheng): This doesn't account for panels in overflow. They should have |
| 336 // a callout as well. |
| 337 if (!active_panel || |
| 338 launcher_->GetScreenBoundsOfItemIconForWindow(active_panel).IsEmpty()) { |
| 339 callout_widget_->Hide(); |
| 340 return; |
| 341 } |
| 342 MessageLoop::current()->PostTask( |
| 343 FROM_HERE, |
| 344 base::Bind(&PanelLayoutManager::ShowCalloutHelper, |
| 345 weak_factory_.GetWeakPtr(), |
| 346 active_panel)); |
| 347 } |
| 348 |
| 349 void PanelLayoutManager::ShowCalloutHelper(aura::Window* active_panel) { |
| 350 DCHECK(active_panel); |
| 351 gfx::Rect bounds = active_panel->GetBoundsInRootWindow(); |
| 352 gfx::Rect callout_bounds = callout_widget_->GetWindowScreenBounds(); |
| 353 callout_bounds.set_x( |
| 354 bounds.x() + (bounds.width() - callout_bounds.width()) / 2); |
| 355 callout_bounds.set_y(bounds.bottom()); |
| 356 SetChildBoundsDirect(callout_widget_->GetNativeWindow(), callout_bounds); |
| 357 panel_container_->StackChildAtTop(callout_widget_->GetNativeWindow()); |
| 358 callout_widget_->Show(); |
| 359 } |
| 360 |
274 } // namespace internal | 361 } // namespace internal |
275 } // namespace ash | 362 } // namespace ash |
OLD | NEW |