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); |
| 94 callout_widget_->Show(); |
43 Shell::GetRootWindow()->AddObserver(this); | 95 Shell::GetRootWindow()->AddObserver(this); |
44 } | 96 } |
45 | 97 |
46 PanelLayoutManager::~PanelLayoutManager() { | 98 PanelLayoutManager::~PanelLayoutManager() { |
47 if (launcher_) | 99 if (launcher_) |
48 launcher_->RemoveIconObserver(this); | 100 launcher_->RemoveIconObserver(this); |
49 Shell::GetRootWindow()->RemoveObserver(this); | 101 Shell::GetRootWindow()->RemoveObserver(this); |
50 } | 102 } |
51 | 103 |
52 void PanelLayoutManager::StartDragging(aura::Window* panel) { | 104 void PanelLayoutManager::StartDragging(aura::Window* panel) { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
94 Relayout(); | 146 Relayout(); |
95 } | 147 } |
96 | 148 |
97 //////////////////////////////////////////////////////////////////////////////// | 149 //////////////////////////////////////////////////////////////////////////////// |
98 // PanelLayoutManager, aura::LayoutManager implementation: | 150 // PanelLayoutManager, aura::LayoutManager implementation: |
99 void PanelLayoutManager::OnWindowResized() { | 151 void PanelLayoutManager::OnWindowResized() { |
100 Relayout(); | 152 Relayout(); |
101 } | 153 } |
102 | 154 |
103 void PanelLayoutManager::OnWindowAddedToLayout(aura::Window* child) { | 155 void PanelLayoutManager::OnWindowAddedToLayout(aura::Window* child) { |
| 156 if (child == callout_widget_->GetNativeWindow()) |
| 157 return; |
104 panel_windows_.push_back(child); | 158 panel_windows_.push_back(child); |
105 Relayout(); | 159 Relayout(); |
106 } | 160 } |
107 | 161 |
108 void PanelLayoutManager::OnWillRemoveWindowFromLayout(aura::Window* child) { | 162 void PanelLayoutManager::OnWillRemoveWindowFromLayout(aura::Window* child) { |
109 PanelList::iterator found = | 163 PanelList::iterator found = |
110 std::find(panel_windows_.begin(), panel_windows_.end(), child); | 164 std::find(panel_windows_.begin(), panel_windows_.end(), child); |
111 if (found != panel_windows_.end()) | 165 if (found != panel_windows_.end()) |
112 panel_windows_.erase(found); | 166 panel_windows_.erase(found); |
113 | 167 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
168 } | 222 } |
169 | 223 |
170 //////////////////////////////////////////////////////////////////////////////// | 224 //////////////////////////////////////////////////////////////////////////////// |
171 // PanelLayoutManager, aura::WindowObserver implementation: | 225 // PanelLayoutManager, aura::WindowObserver implementation: |
172 void PanelLayoutManager::OnWindowPropertyChanged(aura::Window* window, | 226 void PanelLayoutManager::OnWindowPropertyChanged(aura::Window* window, |
173 const void* key, | 227 const void* key, |
174 intptr_t old) { | 228 intptr_t old) { |
175 if (key == aura::client::kRootWindowActiveWindowKey) { | 229 if (key == aura::client::kRootWindowActiveWindowKey) { |
176 aura::Window* active = window->GetProperty( | 230 aura::Window* active = window->GetProperty( |
177 aura::client::kRootWindowActiveWindowKey); | 231 aura::client::kRootWindowActiveWindowKey); |
178 if (active && active->type() == aura::client::WINDOW_TYPE_PANEL) | 232 if (active && active->type() == aura::client::WINDOW_TYPE_PANEL) { |
179 UpdateStacking(active); | 233 UpdateStacking(active); |
| 234 UpdateCallout(active); |
| 235 } else { |
| 236 UpdateCallout(NULL); |
| 237 } |
180 } | 238 } |
181 } | 239 } |
182 | 240 |
183 | 241 |
184 //////////////////////////////////////////////////////////////////////////////// | 242 //////////////////////////////////////////////////////////////////////////////// |
185 // PanelLayoutManager private implementation: | 243 // PanelLayoutManager private implementation: |
186 void PanelLayoutManager::Relayout() { | 244 void PanelLayoutManager::Relayout() { |
187 if (in_layout_) | 245 if (in_layout_) |
188 return; | 246 return; |
189 AutoReset<bool> auto_reset_in_layout(&in_layout_, true); | 247 AutoReset<bool> auto_reset_in_layout(&in_layout_, true); |
190 | 248 |
| 249 int launcher_top = launcher_->widget()->GetWindowScreenBounds().y(); |
191 aura::Window* active_panel = NULL; | 250 aura::Window* active_panel = NULL; |
192 for (PanelList::iterator iter = panel_windows_.begin(); | 251 for (PanelList::iterator iter = panel_windows_.begin(); |
193 iter != panel_windows_.end(); ++iter) { | 252 iter != panel_windows_.end(); ++iter) { |
194 aura::Window* panel = *iter; | 253 aura::Window* panel = *iter; |
195 if (!panel->IsVisible() || panel == dragged_panel_) | 254 if (!panel->IsVisible() || panel == dragged_panel_) |
196 continue; | 255 continue; |
197 | 256 |
198 gfx::Rect icon_bounds = | 257 gfx::Rect icon_bounds = |
199 launcher_->GetScreenBoundsOfItemIconForWindow(panel); | 258 launcher_->GetScreenBoundsOfItemIconForWindow(panel); |
200 | 259 |
(...skipping 10 matching lines...) Expand all Loading... |
211 } | 270 } |
212 | 271 |
213 gfx::Point icon_origin = icon_bounds.origin(); | 272 gfx::Point icon_origin = icon_bounds.origin(); |
214 aura::Window::ConvertPointToWindow(panel_container_->GetRootWindow(), | 273 aura::Window::ConvertPointToWindow(panel_container_->GetRootWindow(), |
215 panel_container_, &icon_origin); | 274 panel_container_, &icon_origin); |
216 | 275 |
217 // TODO(dcheng): Need to clamp to screen edges. | 276 // TODO(dcheng): Need to clamp to screen edges. |
218 gfx::Rect bounds = panel->bounds(); | 277 gfx::Rect bounds = panel->bounds(); |
219 bounds.set_x( | 278 bounds.set_x( |
220 icon_origin.x() + icon_bounds.width() / 2 - bounds.width() / 2); | 279 icon_origin.x() + icon_bounds.width() / 2 - bounds.width() / 2); |
221 bounds.set_y(icon_origin.y() - bounds.height()); | 280 bounds.set_y(launcher_top - bounds.height()); |
222 SetChildBoundsDirect(panel, bounds); | 281 SetChildBoundsDirect(panel, bounds); |
223 } | 282 } |
224 | 283 |
225 UpdateStacking(active_panel); | 284 UpdateStacking(active_panel); |
| 285 UpdateCallout(active_panel); |
226 } | 286 } |
227 | 287 |
228 void PanelLayoutManager::UpdateStacking(aura::Window* active_panel) { | 288 void PanelLayoutManager::UpdateStacking(aura::Window* active_panel) { |
229 if (!active_panel) { | 289 if (!active_panel) { |
230 if (!last_active_panel_) | 290 if (!last_active_panel_) |
231 return; | 291 return; |
232 active_panel = last_active_panel_; | 292 active_panel = last_active_panel_; |
233 } | 293 } |
234 | 294 |
235 // We want to to stack the panels like a deck of cards: | 295 // 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) { | 324 it != window_ordering.rend() && it->second != active_panel; ++it) { |
265 if (previous_panel) | 325 if (previous_panel) |
266 panel_container_->StackChildAbove(it->second, previous_panel); | 326 panel_container_->StackChildAbove(it->second, previous_panel); |
267 previous_panel = it->second; | 327 previous_panel = it->second; |
268 } | 328 } |
269 | 329 |
270 panel_container_->StackChildAtTop(active_panel); | 330 panel_container_->StackChildAtTop(active_panel); |
271 last_active_panel_ = active_panel; | 331 last_active_panel_ = active_panel; |
272 } | 332 } |
273 | 333 |
| 334 void PanelLayoutManager::UpdateCallout(aura::Window* active_panel) { |
| 335 weak_factory_.InvalidateWeakPtrs(); |
| 336 // TODO(dcheng): This doesn't account for panels in overflow. They should have |
| 337 // a callout as well. |
| 338 // This also doesn't work well for windows that are TYPE_PANEL but don't get |
| 339 // added to the list of panel_windows_ for whatever reason. |
| 340 if (!active_panel || |
| 341 launcher_->GetScreenBoundsOfItemIconForWindow(active_panel).IsEmpty()) { |
| 342 callout_widget_->Hide(); |
| 343 return; |
| 344 } |
| 345 MessageLoop::current()->PostTask( |
| 346 FROM_HERE, |
| 347 base::Bind(&PanelLayoutManager::ShowCalloutHelper, |
| 348 weak_factory_.GetWeakPtr(), |
| 349 active_panel)); |
| 350 } |
| 351 |
| 352 void PanelLayoutManager::ShowCalloutHelper(aura::Window* active_panel) { |
| 353 DCHECK(active_panel); |
| 354 gfx::Rect bounds = active_panel->GetBoundsInRootWindow(); |
| 355 gfx::Rect callout_bounds = callout_widget_->GetWindowScreenBounds(); |
| 356 callout_bounds.set_x( |
| 357 bounds.x() + (bounds.width() - callout_bounds.width()) / 2); |
| 358 callout_bounds.set_y(bounds.bottom()); |
| 359 SetChildBoundsDirect(callout_widget_->GetNativeWindow(), callout_bounds); |
| 360 panel_container_->StackChildAtTop(callout_widget_->GetNativeWindow()); |
| 361 callout_widget_->Show(); |
| 362 } |
| 363 |
274 } // namespace internal | 364 } // namespace internal |
275 } // namespace ash | 365 } // namespace ash |
OLD | NEW |