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 "third_party/skia/include/core/SkCanvas.h" | |
14 #include "third_party/skia/include/core/SkColor.h" | |
15 #include "third_party/skia/include/core/SkPaint.h" | |
16 #include "third_party/skia/include/core/SkPath.h" | |
13 #include "ui/aura/client/activation_client.h" | 17 #include "ui/aura/client/activation_client.h" |
14 #include "ui/aura/client/aura_constants.h" | 18 #include "ui/aura/client/aura_constants.h" |
15 #include "ui/aura/root_window.h" | 19 #include "ui/aura/root_window.h" |
16 #include "ui/aura/window.h" | 20 #include "ui/aura/window.h" |
21 #include "ui/gfx/canvas.h" | |
17 #include "ui/gfx/rect.h" | 22 #include "ui/gfx/rect.h" |
18 #include "ui/gfx/size.h" | 23 #include "ui/views/background.h" |
19 #include "ui/views/widget/widget.h" | 24 #include "ui/views/widget/widget.h" |
20 | 25 |
26 namespace ash { | |
27 namespace internal { | |
28 | |
21 namespace { | 29 namespace { |
22 const int kPanelMarginEdge = 4; | 30 const int kPanelMarginEdge = 4; |
23 const int kPanelMarginMiddle = 8; | 31 const int kPanelMarginMiddle = 8; |
24 | 32 |
25 const int kMinimizedHeight = 24; | 33 const int kMinimizedHeight = 24; |
26 | 34 |
27 const float kMaxHeightFactor = .80f; | 35 const float kMaxHeightFactor = .80f; |
28 const float kMaxWidthFactor = .50f; | 36 const float kMaxWidthFactor = .50f; |
29 } | |
30 | 37 |
31 namespace ash { | 38 // Callout arrow dimensions. |
32 namespace internal { | 39 const int kArrowWidth = 20; |
40 const int kArrowHeight = 10; | |
41 | |
42 class CalloutWidgetBackground : public views::Background{ | |
sky
2012/04/26 15:41:16
nit: space after Background
dcheng
2012/04/27 01:11:35
Done.
| |
43 public: | |
44 CalloutWidgetBackground() {} | |
45 virtual void Paint(gfx::Canvas* canvas, views::View* view) const OVERRIDE { | |
46 SkPath path; | |
47 // TODO(dcheng): Verify if this results in off by one errors. | |
48 path.moveTo(SkIntToScalar(0), SkIntToScalar(0)); | |
49 path.lineTo(SkIntToScalar(kArrowWidth / 2), SkIntToScalar(kArrowHeight)); | |
50 path.lineTo(SkIntToScalar(kArrowWidth), SkIntToScalar(0)); | |
51 | |
52 // TODO(dcheng): get real colors, and port this over to use gfx::Canvas | |
53 // instead. | |
54 SkPaint paint; | |
55 paint.setStyle(SkPaint::kFill_Style); | |
56 paint.setColor(SK_ColorBLUE); | |
57 canvas->sk_canvas()->drawPath(path, paint); | |
58 | |
59 paint.setStyle(SkPaint::kStroke_Style); | |
60 paint.setColor(SK_ColorRED); | |
61 canvas->sk_canvas()->drawPath(path, paint); | |
62 } | |
63 | |
64 private: | |
65 DISALLOW_COPY_AND_ASSIGN(CalloutWidgetBackground); | |
66 }; | |
67 | |
68 } // namespace | |
33 | 69 |
34 //////////////////////////////////////////////////////////////////////////////// | 70 //////////////////////////////////////////////////////////////////////////////// |
35 // PanelLayoutManager public implementation: | 71 // PanelLayoutManager public implementation: |
36 PanelLayoutManager::PanelLayoutManager(aura::Window* panel_container) | 72 PanelLayoutManager::PanelLayoutManager(aura::Window* panel_container) |
37 : panel_container_(panel_container), | 73 : panel_container_(panel_container), |
38 in_layout_(false), | 74 in_layout_(false), |
39 dragged_panel_(NULL), | 75 dragged_panel_(NULL), |
40 launcher_(NULL), | 76 launcher_(NULL), |
41 last_active_panel_(NULL) { | 77 last_active_panel_(NULL), |
78 callout_widget_(new views::Widget) { | |
42 DCHECK(panel_container); | 79 DCHECK(panel_container); |
80 views::Widget::InitParams params; | |
81 params.type = views::Widget::InitParams::TYPE_POPUP; | |
82 params.transparent = true; | |
83 params.can_activate = false; | |
84 params.keep_on_top = true; | |
85 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | |
86 params.parent = panel_container_; | |
87 params.bounds.set_width(kArrowWidth); | |
88 params.bounds.set_height(kArrowHeight); | |
89 // Why do we need this and can_activate = false? | |
90 callout_widget_->set_focus_on_creation(false); | |
91 callout_widget_->Init(params); | |
92 views::View* content_view = new views::View; | |
93 content_view->set_background(new CalloutWidgetBackground); | |
94 callout_widget_->SetContentsView(content_view); | |
95 callout_widget_->Show(); | |
43 Shell::GetRootWindow()->AddObserver(this); | 96 Shell::GetRootWindow()->AddObserver(this); |
44 } | 97 } |
45 | 98 |
46 PanelLayoutManager::~PanelLayoutManager() { | 99 PanelLayoutManager::~PanelLayoutManager() { |
47 if (launcher_) | 100 if (launcher_) |
48 launcher_->RemoveIconObserver(this); | 101 launcher_->RemoveIconObserver(this); |
49 Shell::GetRootWindow()->RemoveObserver(this); | 102 Shell::GetRootWindow()->RemoveObserver(this); |
50 } | 103 } |
51 | 104 |
52 void PanelLayoutManager::StartDragging(aura::Window* panel) { | 105 void PanelLayoutManager::StartDragging(aura::Window* panel) { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
93 Relayout(); | 146 Relayout(); |
94 } | 147 } |
95 | 148 |
96 //////////////////////////////////////////////////////////////////////////////// | 149 //////////////////////////////////////////////////////////////////////////////// |
97 // PanelLayoutManager, aura::LayoutManager implementation: | 150 // PanelLayoutManager, aura::LayoutManager implementation: |
98 void PanelLayoutManager::OnWindowResized() { | 151 void PanelLayoutManager::OnWindowResized() { |
99 Relayout(); | 152 Relayout(); |
100 } | 153 } |
101 | 154 |
102 void PanelLayoutManager::OnWindowAddedToLayout(aura::Window* child) { | 155 void PanelLayoutManager::OnWindowAddedToLayout(aura::Window* child) { |
156 if (child == callout_widget_->GetNativeWindow()) | |
157 return; | |
103 panel_windows_.push_back(child); | 158 panel_windows_.push_back(child); |
104 Relayout(); | 159 Relayout(); |
105 } | 160 } |
106 | 161 |
107 void PanelLayoutManager::OnWillRemoveWindowFromLayout(aura::Window* child) { | 162 void PanelLayoutManager::OnWillRemoveWindowFromLayout(aura::Window* child) { |
108 PanelList::iterator found = | 163 PanelList::iterator found = |
109 std::find(panel_windows_.begin(), panel_windows_.end(), child); | 164 std::find(panel_windows_.begin(), panel_windows_.end(), child); |
110 if (found != panel_windows_.end()) | 165 if (found != panel_windows_.end()) |
111 panel_windows_.erase(found); | 166 panel_windows_.erase(found); |
112 | 167 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
167 } | 222 } |
168 | 223 |
169 //////////////////////////////////////////////////////////////////////////////// | 224 //////////////////////////////////////////////////////////////////////////////// |
170 // PanelLayoutManager, aura::WindowObserver implementation: | 225 // PanelLayoutManager, aura::WindowObserver implementation: |
171 void PanelLayoutManager::OnWindowPropertyChanged(aura::Window* window, | 226 void PanelLayoutManager::OnWindowPropertyChanged(aura::Window* window, |
172 const void* key, | 227 const void* key, |
173 intptr_t old) { | 228 intptr_t old) { |
174 if (key == aura::client::kRootWindowActiveWindowKey) { | 229 if (key == aura::client::kRootWindowActiveWindowKey) { |
175 aura::Window* active = window->GetProperty( | 230 aura::Window* active = window->GetProperty( |
176 aura::client::kRootWindowActiveWindowKey); | 231 aura::client::kRootWindowActiveWindowKey); |
177 if (active && active->type() == aura::client::WINDOW_TYPE_PANEL) | 232 if (active && active->type() == aura::client::WINDOW_TYPE_PANEL) { |
178 UpdateStacking(active); | 233 UpdateStacking(active); |
234 UpdateCallout(active); | |
235 } | |
179 } | 236 } |
180 } | 237 } |
181 | 238 |
182 | 239 |
183 //////////////////////////////////////////////////////////////////////////////// | 240 //////////////////////////////////////////////////////////////////////////////// |
184 // PanelLayoutManager private implementation: | 241 // PanelLayoutManager private implementation: |
185 void PanelLayoutManager::Relayout() { | 242 void PanelLayoutManager::Relayout() { |
186 if (in_layout_) | 243 if (in_layout_) |
187 return; | 244 return; |
188 AutoReset<bool> auto_reset_in_layout(&in_layout_, true); | 245 AutoReset<bool> auto_reset_in_layout(&in_layout_, true); |
(...skipping 23 matching lines...) Expand all Loading... | |
212 } | 269 } |
213 | 270 |
214 gfx::Point icon_origin = icon_bounds.origin(); | 271 gfx::Point icon_origin = icon_bounds.origin(); |
215 aura::Window::ConvertPointToWindow(panel_container_->GetRootWindow(), | 272 aura::Window::ConvertPointToWindow(panel_container_->GetRootWindow(), |
216 panel_container_, &icon_origin); | 273 panel_container_, &icon_origin); |
217 | 274 |
218 // TODO(dcheng): Need to clamp to screen edges. | 275 // TODO(dcheng): Need to clamp to screen edges. |
219 gfx::Rect bounds = panel->bounds(); | 276 gfx::Rect bounds = panel->bounds(); |
220 bounds.set_x( | 277 bounds.set_x( |
221 icon_origin.x() + icon_bounds.width() / 2 - bounds.width() / 2); | 278 icon_origin.x() + icon_bounds.width() / 2 - bounds.width() / 2); |
222 bounds.set_y(icon_origin.y() - bounds.height()); | 279 // TODO(dcheng): This is just a random constant so panels don't sit right |
280 // on top of the launcher. We should be using the same padding that normal | |
281 // windows use. | |
282 bounds.set_y(icon_origin.y() - bounds.height() - 10); | |
sky
2012/04/26 15:41:16
Normal windows can sit flush to the launcher.
dcheng
2012/04/27 01:11:35
Right now, we're lining things up to the top of th
| |
223 SetChildBoundsDirect(panel, bounds); | 283 SetChildBoundsDirect(panel, bounds); |
224 } | 284 } |
225 | 285 |
226 UpdateStacking(active_panel); | 286 UpdateStacking(active_panel); |
287 UpdateCallout(active_panel); | |
sky
2012/04/26 15:41:16
UpdateStacking might use last_active_panel_, does
dcheng
2012/04/27 01:11:35
No, we only want to decorate a panel with the call
| |
227 } | 288 } |
228 | 289 |
229 void PanelLayoutManager::UpdateStacking(aura::Window* active_panel) { | 290 void PanelLayoutManager::UpdateStacking(aura::Window* active_panel) { |
230 // We want to to stack the panels like a deck of cards: | 291 // We want to to stack the panels like a deck of cards: |
231 // ,--,--,--,-------.--.--. | 292 // ,--,--,--,-------.--.--. |
232 // | | | | | | | | 293 // | | | | | | | |
233 // | | | | | | | | 294 // | | | | | | | |
234 // | 295 // |
235 // Since there's no way of extracting a panel ordering from the launcher, | 296 // 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... | 297 // we build an ordering based on the x-coordinate of the panel bounds... |
(...skipping 26 matching lines...) Expand all Loading... | |
263 it != window_ordering.rend() && it->second != active_panel; ++it) { | 324 it != window_ordering.rend() && it->second != active_panel; ++it) { |
264 if (previous_panel) | 325 if (previous_panel) |
265 panel_container_->StackChildAbove(it->second, previous_panel); | 326 panel_container_->StackChildAbove(it->second, previous_panel); |
266 previous_panel = it->second; | 327 previous_panel = it->second; |
267 } | 328 } |
268 | 329 |
269 panel_container_->StackChildAtTop(active_panel); | 330 panel_container_->StackChildAtTop(active_panel); |
270 last_active_panel_ = active_panel; | 331 last_active_panel_ = active_panel; |
271 } | 332 } |
272 | 333 |
334 void PanelLayoutManager::UpdateCallout(aura::Window* active_panel) { | |
335 if (!active_panel) { | |
336 callout_widget_->Hide(); | |
337 return; | |
338 } | |
339 gfx::Rect bounds = active_panel->GetBoundsInRootWindow(); | |
340 gfx::Rect callout_bounds = callout_widget_->GetWindowScreenBounds(); | |
341 callout_bounds.set_x( | |
342 bounds.x() + (bounds.width() - callout_bounds.width()) / 2); | |
343 callout_bounds.set_y(bounds.bottom()); | |
344 SetChildBoundsDirect(callout_widget_->GetNativeWindow(), callout_bounds); | |
345 callout_widget_->Show(); | |
346 panel_container_->StackChildAtTop(callout_widget_->GetNativeWindow()); | |
sky
2012/04/26 15:41:16
I would stack at top first, then show.
dcheng
2012/04/27 01:11:35
Done.
| |
347 } | |
348 | |
273 } // namespace internal | 349 } // namespace internal |
274 } // namespace ash | 350 } // namespace ash |
OLD | NEW |