OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/overview/window_selector_item.h" | 5 #include "ash/wm/overview/window_selector_item.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "ash/screen_util.h" | 10 #include "ash/screen_util.h" |
11 #include "ash/shell.h" | 11 #include "ash/shell.h" |
12 #include "ash/shell_window_ids.h" | 12 #include "ash/shell_window_ids.h" |
13 #include "ash/wm/overview/overview_animation_type.h" | 13 #include "ash/wm/overview/overview_animation_type.h" |
14 #include "ash/wm/overview/scoped_overview_animation_settings.h" | 14 #include "ash/wm/overview/scoped_overview_animation_settings.h" |
15 #include "ash/wm/overview/scoped_transform_overview_window.h" | 15 #include "ash/wm/overview/scoped_transform_overview_window.h" |
16 #include "ash/wm/overview/window_selector_controller.h" | 16 #include "ash/wm/overview/window_selector_controller.h" |
17 #include "ash/wm/window_state.h" | 17 #include "ash/wm/window_state.h" |
18 #include "base/auto_reset.h" | 18 #include "base/auto_reset.h" |
19 #include "base/strings/string_util.h" | 19 #include "base/strings/string_util.h" |
20 #include "base/strings/utf_string_conversions.h" | 20 #include "base/strings/utf_string_conversions.h" |
21 #include "base/time/time.h" | 21 #include "base/time/time.h" |
22 #include "grit/ash_resources.h" | 22 #include "grit/ash_resources.h" |
23 #include "grit/ash_strings.h" | 23 #include "grit/ash_strings.h" |
24 #include "ui/aura/window.h" | 24 #include "ui/aura/window.h" |
25 #include "ui/base/l10n/l10n_util.h" | 25 #include "ui/base/l10n/l10n_util.h" |
26 #include "ui/base/resource/resource_bundle.h" | 26 #include "ui/base/resource/resource_bundle.h" |
27 #include "ui/gfx/geometry/vector2d.h" | 27 #include "ui/gfx/geometry/vector2d.h" |
28 #include "ui/gfx/text_constants.h" | |
28 #include "ui/gfx/transform_util.h" | 29 #include "ui/gfx/transform_util.h" |
29 #include "ui/strings/grit/ui_strings.h" | 30 #include "ui/strings/grit/ui_strings.h" |
31 #include "ui/views/border.h" | |
30 #include "ui/views/controls/button/image_button.h" | 32 #include "ui/views/controls/button/image_button.h" |
31 #include "ui/views/controls/label.h" | 33 #include "ui/views/controls/button/label_button.h" |
32 #include "ui/views/layout/box_layout.h" | 34 #include "ui/views/layout/box_layout.h" |
33 #include "ui/views/widget/widget.h" | 35 #include "ui/views/widget/widget.h" |
34 #include "ui/wm/core/window_util.h" | 36 #include "ui/wm/core/window_util.h" |
35 | 37 |
36 namespace ash { | 38 namespace ash { |
37 | 39 |
38 namespace { | 40 namespace { |
39 | 41 |
40 // In the conceptual overview table, the window margin is the space reserved | 42 // In the conceptual overview table, the window margin is the space reserved |
41 // around the window within the cell. This margin does not overlap so the | 43 // around the window within the cell. This margin does not overlap so the |
42 // closest distance between adjacent windows will be twice this amount. | 44 // closest distance between adjacent windows will be twice this amount. |
43 static const int kWindowMargin = 30; | 45 static const int kWindowMargin = 30; |
44 | 46 |
45 // Foreground label color. | 47 // Foreground label color. |
46 static const SkColor kLabelColor = SK_ColorWHITE; | 48 static const SkColor kLabelColor = SK_ColorWHITE; |
47 | 49 |
48 // Background label color. | |
49 static const SkColor kLabelBackground = SK_ColorTRANSPARENT; | |
50 | |
51 // Label shadow color. | 50 // Label shadow color. |
52 static const SkColor kLabelShadow = 0xB0000000; | 51 static const SkColor kLabelShadow = 0xB0000000; |
53 | 52 |
54 // Vertical padding for the label, both over and beneath it. | 53 // Vertical padding for the label, both over and beneath it. |
55 static const int kVerticalLabelPadding = 20; | 54 static const int kVerticalLabelPadding = 20; |
56 | 55 |
57 // Solid shadow length from the label | 56 // Solid shadow length from the label |
58 static const int kVerticalShadowOffset = 1; | 57 static const int kVerticalShadowOffset = 1; |
59 | 58 |
60 // Amount of blur applied to the label shadow | 59 // Amount of blur applied to the label shadow |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
110 | 109 |
111 OverviewCloseButton::~OverviewCloseButton() { | 110 OverviewCloseButton::~OverviewCloseButton() { |
112 } | 111 } |
113 | 112 |
114 } // namespace | 113 } // namespace |
115 | 114 |
116 WindowSelectorItem::WindowSelectorItem(aura::Window* root_window) | 115 WindowSelectorItem::WindowSelectorItem(aura::Window* root_window) |
117 : dimmed_(false), | 116 : dimmed_(false), |
118 root_window_(root_window), | 117 root_window_(root_window), |
119 in_bounds_update_(false), | 118 in_bounds_update_(false), |
120 window_label_view_(nullptr), | 119 window_label_button_view_(nullptr), |
121 close_button_(new OverviewCloseButton(this)), | 120 close_button_(new OverviewCloseButton(this)) { |
122 selector_item_activate_window_button_( | |
123 new TransparentActivateWindowButton(root_window, this)) { | |
124 views::Widget::InitParams params; | 121 views::Widget::InitParams params; |
125 params.type = views::Widget::InitParams::TYPE_POPUP; | 122 params.type = views::Widget::InitParams::TYPE_POPUP; |
126 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | 123 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
127 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; | 124 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; |
128 params.parent = Shell::GetContainer(root_window, | 125 params.parent = Shell::GetContainer(root_window, |
129 kShellWindowId_OverlayContainer); | 126 kShellWindowId_OverlayContainer); |
130 close_button_widget_.set_focus_on_creation(false); | 127 close_button_widget_.set_focus_on_creation(false); |
131 close_button_widget_.Init(params); | 128 close_button_widget_.Init(params); |
132 close_button_->SetVisible(false); | 129 close_button_->SetVisible(false); |
133 close_button_widget_.SetContentsView(close_button_); | 130 close_button_widget_.SetContentsView(close_button_); |
(...skipping 14 matching lines...) Expand all Loading... | |
148 transform_window->window()->RemoveObserver(this); | 145 transform_window->window()->RemoveObserver(this); |
149 } | 146 } |
150 } | 147 } |
151 | 148 |
152 void WindowSelectorItem::AddWindow(aura::Window* window) { | 149 void WindowSelectorItem::AddWindow(aura::Window* window) { |
153 DCHECK(window->GetRootWindow() == root_window_); | 150 DCHECK(window->GetRootWindow() == root_window_); |
154 window->AddObserver(this); | 151 window->AddObserver(this); |
155 ScopedTransformOverviewWindow* transform_window = | 152 ScopedTransformOverviewWindow* transform_window = |
156 new ScopedTransformOverviewWindow(window); | 153 new ScopedTransformOverviewWindow(window); |
157 transform_windows_.push_back(transform_window); | 154 transform_windows_.push_back(transform_window); |
158 // The transparent overlays are added at the front of the z-order when | |
159 // created so make sure the selector item's transparent overlay is behind the | |
160 // overlay for the window that was just added. | |
161 transform_window->activate_button()->StackAbove( | |
162 selector_item_activate_window_button_.get()); | |
163 | 155 |
164 UpdateSelectorButtons(); | |
165 UpdateCloseButtonAccessibilityName(); | 156 UpdateCloseButtonAccessibilityName(); |
166 } | 157 } |
167 | 158 |
168 bool WindowSelectorItem::HasSelectableWindow(const aura::Window* window) const { | 159 bool WindowSelectorItem::HasSelectableWindow(const aura::Window* window) const { |
169 for (auto* transform_window : transform_windows_) { | 160 for (auto* transform_window : transform_windows_) { |
170 if (transform_window->window() == window) | 161 if (transform_window->window() == window) |
171 return true; | 162 return true; |
172 } | 163 } |
173 return false; | 164 return false; |
174 } | 165 } |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
216 // If empty WindowSelectorItem will be destroyed immediately after this by | 207 // If empty WindowSelectorItem will be destroyed immediately after this by |
217 // its owner. | 208 // its owner. |
218 if (empty()) | 209 if (empty()) |
219 return; | 210 return; |
220 | 211 |
221 UpdateCloseButtonAccessibilityName(); | 212 UpdateCloseButtonAccessibilityName(); |
222 window_label_.reset(); | 213 window_label_.reset(); |
223 UpdateWindowLabels(target_bounds_, | 214 UpdateWindowLabels(target_bounds_, |
224 OverviewAnimationType::OVERVIEW_ANIMATION_NONE); | 215 OverviewAnimationType::OVERVIEW_ANIMATION_NONE); |
225 UpdateCloseButtonLayout(OverviewAnimationType::OVERVIEW_ANIMATION_NONE); | 216 UpdateCloseButtonLayout(OverviewAnimationType::OVERVIEW_ANIMATION_NONE); |
226 UpdateSelectorButtons(); | |
227 } | 217 } |
228 | 218 |
229 bool WindowSelectorItem::empty() const { | 219 bool WindowSelectorItem::empty() const { |
230 return transform_windows_.empty(); | 220 return transform_windows_.empty(); |
231 } | 221 } |
232 | 222 |
233 void WindowSelectorItem::PrepareForOverview() { | 223 void WindowSelectorItem::PrepareForOverview() { |
234 for (auto* transform_window : transform_windows_) | 224 for (auto* transform_window : transform_windows_) |
235 transform_window->PrepareForOverview(); | 225 transform_window->PrepareForOverview(); |
236 } | 226 } |
237 | 227 |
238 void WindowSelectorItem::SetBounds(aura::Window* root_window, | 228 void WindowSelectorItem::SetBounds(aura::Window* root_window, |
239 const gfx::Rect& target_bounds, | 229 const gfx::Rect& target_bounds, |
240 OverviewAnimationType animation_type) { | 230 OverviewAnimationType animation_type) { |
241 if (in_bounds_update_) | 231 if (in_bounds_update_) |
242 return; | 232 return; |
243 base::AutoReset<bool> auto_reset_in_bounds_update(&in_bounds_update_, true); | 233 base::AutoReset<bool> auto_reset_in_bounds_update(&in_bounds_update_, true); |
244 target_bounds_ = target_bounds; | 234 target_bounds_ = target_bounds; |
245 | 235 |
246 UpdateWindowLabels(target_bounds, animation_type); | 236 UpdateWindowLabels(target_bounds, animation_type); |
247 | 237 |
248 gfx::Rect inset_bounds(target_bounds); | 238 gfx::Rect inset_bounds(target_bounds); |
249 inset_bounds.Inset(kWindowMargin, kWindowMargin); | 239 inset_bounds.Inset(kWindowMargin, kWindowMargin); |
250 SetItemBounds(root_window, inset_bounds, animation_type); | 240 SetItemBounds(root_window, inset_bounds, animation_type); |
251 | 241 |
252 // SetItemBounds is called before UpdateCloseButtonLayout so the close button | 242 // SetItemBounds is called before UpdateCloseButtonLayout so the close button |
253 // can properly use the updated windows bounds. | 243 // can properly use the updated windows bounds. |
254 UpdateCloseButtonLayout(animation_type); | 244 UpdateCloseButtonLayout(animation_type); |
255 UpdateSelectorButtons(); | |
256 } | 245 } |
257 | 246 |
258 void WindowSelectorItem::RecomputeWindowTransforms() { | 247 void WindowSelectorItem::RecomputeWindowTransforms() { |
259 if (in_bounds_update_ || target_bounds_.IsEmpty()) | 248 if (in_bounds_update_ || target_bounds_.IsEmpty()) |
260 return; | 249 return; |
261 DCHECK(root_window_); | 250 DCHECK(root_window_); |
262 base::AutoReset<bool> auto_reset_in_bounds_update(&in_bounds_update_, true); | 251 base::AutoReset<bool> auto_reset_in_bounds_update(&in_bounds_update_, true); |
263 gfx::Rect inset_bounds(target_bounds_); | 252 gfx::Rect inset_bounds(target_bounds_); |
264 inset_bounds.Inset(kWindowMargin, kWindowMargin); | 253 inset_bounds.Inset(kWindowMargin, kWindowMargin); |
265 SetItemBounds(root_window_, inset_bounds, | 254 SetItemBounds(root_window_, inset_bounds, |
266 OverviewAnimationType::OVERVIEW_ANIMATION_NONE); | 255 OverviewAnimationType::OVERVIEW_ANIMATION_NONE); |
267 | 256 |
268 UpdateCloseButtonLayout(OverviewAnimationType::OVERVIEW_ANIMATION_NONE); | 257 UpdateCloseButtonLayout(OverviewAnimationType::OVERVIEW_ANIMATION_NONE); |
269 UpdateSelectorButtons(); | |
270 } | 258 } |
271 | 259 |
272 void WindowSelectorItem::SendFocusAlert() const { | 260 void WindowSelectorItem::SendFocusAlert() const { |
273 selector_item_activate_window_button_->SendFocusAlert(); | 261 window_label_button_view_->NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, |
262 true); | |
274 } | 263 } |
275 | 264 |
276 void WindowSelectorItem::SetDimmed(bool dimmed) { | 265 void WindowSelectorItem::SetDimmed(bool dimmed) { |
277 dimmed_ = dimmed; | 266 dimmed_ = dimmed; |
278 SetOpacity(dimmed ? kDimmedItemOpacity : 1.0f); | 267 SetOpacity(dimmed ? kDimmedItemOpacity : 1.0f); |
279 } | 268 } |
280 | 269 |
281 void WindowSelectorItem::ButtonPressed(views::Button* sender, | 270 void WindowSelectorItem::ButtonPressed(views::Button* sender, |
282 const ui::Event& event) { | 271 const ui::Event& event) { |
283 CHECK(!transform_windows_.empty()); | 272 if (sender == close_button_) { |
284 SelectionTransformWindow()->Close(); | 273 CHECK(!transform_windows_.empty()); |
274 SelectionTransformWindow()->Close(); | |
275 return; | |
276 } | |
277 wm::GetWindowState(SelectionWindow())->Activate(); | |
bruthig
2015/01/09 17:04:33
I'm assuming this is handling the clicks on the La
Nina
2015/01/21 16:24:16
I don't think we want to add a redundant if clause
| |
285 } | 278 } |
286 | 279 |
287 void WindowSelectorItem::OnWindowTitleChanged(aura::Window* window) { | 280 void WindowSelectorItem::OnWindowTitleChanged(aura::Window* window) { |
288 // TODO(flackr): Maybe add the new title to a vector of titles so that we can | 281 // TODO(flackr): Maybe add the new title to a vector of titles so that we can |
289 // filter any of the titles the window had while in the overview session. | 282 // filter any of the titles the window had while in the overview session. |
290 if (window == SelectionWindow()) { | 283 if (window == SelectionWindow()) { |
291 window_label_view_->SetText(window->title()); | 284 window_label_button_view_->SetText(window->title()); |
292 UpdateCloseButtonAccessibilityName(); | 285 UpdateCloseButtonAccessibilityName(); |
293 } | 286 } |
294 UpdateCloseButtonLayout(OverviewAnimationType::OVERVIEW_ANIMATION_NONE); | 287 UpdateCloseButtonLayout(OverviewAnimationType::OVERVIEW_ANIMATION_NONE); |
295 UpdateSelectorButtons(); | |
296 } | |
297 | |
298 void WindowSelectorItem::Select() { | |
299 aura::Window* selection_window = SelectionWindow(); | |
300 if (selection_window) | |
301 wm::GetWindowState(selection_window)->Activate(); | |
302 } | 288 } |
303 | 289 |
304 void WindowSelectorItem::SetItemBounds(aura::Window* root_window, | 290 void WindowSelectorItem::SetItemBounds(aura::Window* root_window, |
305 const gfx::Rect& target_bounds, | 291 const gfx::Rect& target_bounds, |
306 OverviewAnimationType animation_type) { | 292 OverviewAnimationType animation_type) { |
307 gfx::Rect bounding_rect; | 293 gfx::Rect bounding_rect; |
308 for (auto* transform_window : transform_windows_) { | 294 for (auto* transform_window : transform_windows_) { |
309 bounding_rect.Union( | 295 bounding_rect.Union( |
310 transform_window->GetTargetBoundsInScreen()); | 296 transform_window->GetTargetBoundsInScreen()); |
311 } | 297 } |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
370 } | 356 } |
371 | 357 |
372 void WindowSelectorItem::CreateWindowLabel(const base::string16& title) { | 358 void WindowSelectorItem::CreateWindowLabel(const base::string16& title) { |
373 window_label_.reset(new views::Widget); | 359 window_label_.reset(new views::Widget); |
374 views::Widget::InitParams params; | 360 views::Widget::InitParams params; |
375 params.type = views::Widget::InitParams::TYPE_POPUP; | 361 params.type = views::Widget::InitParams::TYPE_POPUP; |
376 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | 362 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
377 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; | 363 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; |
378 params.parent = Shell::GetContainer(root_window_, | 364 params.parent = Shell::GetContainer(root_window_, |
379 kShellWindowId_OverlayContainer); | 365 kShellWindowId_OverlayContainer); |
380 params.accept_events = false; | |
381 params.visible_on_all_workspaces = true; | 366 params.visible_on_all_workspaces = true; |
382 window_label_->set_focus_on_creation(false); | 367 window_label_->set_focus_on_creation(false); |
383 window_label_->Init(params); | 368 window_label_->Init(params); |
384 window_label_view_ = new views::Label; | 369 window_label_button_view_ = new views::LabelButton(this, title); |
385 window_label_view_->SetEnabledColor(kLabelColor); | 370 window_label_button_view_->SetTextColor(views::LabelButton::STATE_NORMAL, |
386 window_label_view_->SetBackgroundColor(kLabelBackground); | 371 kLabelColor); |
387 window_label_view_->SetShadows(gfx::ShadowValues( | 372 window_label_button_view_->SetTextColor(views::LabelButton::STATE_HOVERED, |
373 kLabelColor); | |
374 window_label_button_view_->SetTextColor(views::LabelButton::STATE_PRESSED, | |
375 kLabelColor); | |
376 window_label_button_view_->set_animate_on_state_change(false); | |
377 window_label_button_view_->SetHorizontalAlignment(gfx::ALIGN_CENTER); | |
378 window_label_button_view_->SetBorder(views::Border::NullBorder()); | |
379 window_label_button_view_->SetTextShadows(gfx::ShadowValues( | |
388 1, | 380 1, |
389 gfx::ShadowValue( | 381 gfx::ShadowValue( |
390 gfx::Point(0, kVerticalShadowOffset), kShadowBlur, kLabelShadow))); | 382 gfx::Point(0, kVerticalShadowOffset), kShadowBlur, kLabelShadow))); |
391 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); | 383 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); |
392 window_label_view_->SetFontList( | 384 window_label_button_view_->SetFontList( |
393 bundle.GetFontList(ui::ResourceBundle::BoldFont)); | 385 bundle.GetFontList(ui::ResourceBundle::BoldFont)); |
394 window_label_view_->SetText(title); | |
395 views::BoxLayout* layout = new views::BoxLayout(views::BoxLayout::kVertical, | 386 views::BoxLayout* layout = new views::BoxLayout(views::BoxLayout::kVertical, |
396 0, | 387 0, |
397 kVerticalLabelPadding, | 388 kVerticalLabelPadding, |
398 0); | 389 0); |
399 window_label_view_->SetLayoutManager(layout); | 390 window_label_button_view_->SetLayoutManager(layout); |
400 window_label_->SetContentsView(window_label_view_); | 391 window_label_->SetContentsView(window_label_button_view_); |
401 window_label_->Show(); | 392 window_label_->Show(); |
402 } | 393 } |
403 | 394 |
404 void WindowSelectorItem::UpdateSelectorButtons() { | |
405 CHECK(!transform_windows_.empty()); | |
406 | |
407 selector_item_activate_window_button_->SetBounds(target_bounds()); | |
408 selector_item_activate_window_button_->SetAccessibleName( | |
409 transform_windows_.front()->window()->title()); | |
410 | |
411 for (auto* transform_window : transform_windows_) { | |
412 TransparentActivateWindowButton* activate_button = | |
413 transform_window->activate_button(); | |
414 | |
415 // If there is only one window in this, then expand the transparent overlay | |
416 // so that touch exploration in ChromVox only provides spoken feedback once | |
417 // within |this| selector item's bounds. | |
418 gfx::Rect bounds = transform_windows_.size() == 1 | |
419 ? target_bounds() : GetTransformedBounds(transform_window->window()); | |
420 activate_button->SetBounds(bounds); | |
421 activate_button->SetAccessibleName(transform_window->window()->title()); | |
422 } | |
423 } | |
424 | |
425 void WindowSelectorItem::UpdateCloseButtonLayout( | 395 void WindowSelectorItem::UpdateCloseButtonLayout( |
426 OverviewAnimationType animation_type) { | 396 OverviewAnimationType animation_type) { |
427 if (!close_button_->visible()) { | 397 if (!close_button_->visible()) { |
428 close_button_->SetVisible(true); | 398 close_button_->SetVisible(true); |
429 SetupFadeInAfterLayout(close_button_widget_.GetNativeWindow()); | 399 SetupFadeInAfterLayout(close_button_widget_.GetNativeWindow()); |
430 } | 400 } |
431 ScopedOverviewAnimationSettings animation_settings(animation_type, | 401 ScopedOverviewAnimationSettings animation_settings(animation_type, |
432 close_button_widget_.GetNativeWindow()); | 402 close_button_widget_.GetNativeWindow()); |
433 | 403 |
434 gfx::Rect transformed_window_bounds = ScreenUtil::ConvertRectFromScreen( | 404 gfx::Rect transformed_window_bounds = ScreenUtil::ConvertRectFromScreen( |
(...skipping 13 matching lines...) Expand all Loading... | |
448 SelectionWindow()->title())); | 418 SelectionWindow()->title())); |
449 } | 419 } |
450 | 420 |
451 ScopedTransformOverviewWindow* | 421 ScopedTransformOverviewWindow* |
452 WindowSelectorItem::SelectionTransformWindow() const { | 422 WindowSelectorItem::SelectionTransformWindow() const { |
453 CHECK(!transform_windows_.empty()); | 423 CHECK(!transform_windows_.empty()); |
454 return transform_windows_.front(); | 424 return transform_windows_.front(); |
455 } | 425 } |
456 | 426 |
457 } // namespace ash | 427 } // namespace ash |
OLD | NEW |