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/system/tray/system_tray.h" | 5 #include "ash/system/tray/system_tray.h" |
6 | 6 |
7 #include "ash/shell.h" | 7 #include "ash/shell.h" |
8 #include "ash/shell/panel_window.h" | 8 #include "ash/shell/panel_window.h" |
9 #include "ash/shell_window_ids.h" | 9 #include "ash/shell_window_ids.h" |
10 #include "ash/system/audio/tray_volume.h" | 10 #include "ash/system/audio/tray_volume.h" |
(...skipping 12 matching lines...) Expand all Loading... | |
23 #include "ash/system/tray/system_tray_bubble.h" | 23 #include "ash/system/tray/system_tray_bubble.h" |
24 #include "ash/system/tray/system_tray_delegate.h" | 24 #include "ash/system/tray/system_tray_delegate.h" |
25 #include "ash/system/tray/system_tray_item.h" | 25 #include "ash/system/tray/system_tray_item.h" |
26 #include "ash/system/tray/tray_constants.h" | 26 #include "ash/system/tray/tray_constants.h" |
27 #include "ash/system/tray_accessibility.h" | 27 #include "ash/system/tray_accessibility.h" |
28 #include "ash/system/tray_caps_lock.h" | 28 #include "ash/system/tray_caps_lock.h" |
29 #include "ash/system/tray_update.h" | 29 #include "ash/system/tray_update.h" |
30 #include "ash/system/user/login_status.h" | 30 #include "ash/system/user/login_status.h" |
31 #include "ash/system/user/tray_user.h" | 31 #include "ash/system/user/tray_user.h" |
32 #include "ash/wm/shelf_layout_manager.h" | 32 #include "ash/wm/shelf_layout_manager.h" |
33 #include "base/i18n/rtl.h" | |
34 #include "base/logging.h" | 33 #include "base/logging.h" |
35 #include "base/timer.h" | 34 #include "base/timer.h" |
36 #include "base/utf_string_conversions.h" | 35 #include "base/utf_string_conversions.h" |
37 #include "grit/ash_strings.h" | 36 #include "grit/ash_strings.h" |
38 #include "ui/aura/root_window.h" | 37 #include "ui/aura/root_window.h" |
39 #include "ui/base/accessibility/accessible_view_state.h" | 38 #include "ui/base/accessibility/accessible_view_state.h" |
40 #include "ui/base/events.h" | 39 #include "ui/base/events.h" |
41 #include "ui/base/l10n/l10n_util.h" | 40 #include "ui/base/l10n/l10n_util.h" |
42 #include "ui/compositor/layer.h" | 41 #include "ui/compositor/layer.h" |
43 #include "ui/gfx/canvas.h" | 42 #include "ui/gfx/canvas.h" |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
137 | 136 |
138 DISALLOW_COPY_AND_ASSIGN(SystemTrayLayerAnimationObserver); | 137 DISALLOW_COPY_AND_ASSIGN(SystemTrayLayerAnimationObserver); |
139 }; | 138 }; |
140 | 139 |
141 } // namespace internal | 140 } // namespace internal |
142 | 141 |
143 // SystemTray | 142 // SystemTray |
144 | 143 |
145 using internal::SystemTrayBubble; | 144 using internal::SystemTrayBubble; |
146 using internal::SystemTrayLayerAnimationObserver; | 145 using internal::SystemTrayLayerAnimationObserver; |
146 using internal::TrayBubbleView; | |
147 | 147 |
148 SystemTray::SystemTray() | 148 SystemTray::SystemTray() |
149 : items_(), | 149 : items_(), |
150 accessibility_observer_(NULL), | 150 accessibility_observer_(NULL), |
151 audio_observer_(NULL), | 151 audio_observer_(NULL), |
152 bluetooth_observer_(NULL), | 152 bluetooth_observer_(NULL), |
153 brightness_observer_(NULL), | 153 brightness_observer_(NULL), |
154 caps_lock_observer_(NULL), | 154 caps_lock_observer_(NULL), |
155 clock_observer_(NULL), | 155 clock_observer_(NULL), |
156 drive_observer_(NULL), | 156 drive_observer_(NULL), |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
249 PreferredSizeChanged(); | 249 PreferredSizeChanged(); |
250 tray_item_map_[item] = tray_item; | 250 tray_item_map_[item] = tray_item; |
251 } | 251 } |
252 } | 252 } |
253 | 253 |
254 void SystemTray::RemoveTrayItem(SystemTrayItem* item) { | 254 void SystemTray::RemoveTrayItem(SystemTrayItem* item) { |
255 NOTIMPLEMENTED(); | 255 NOTIMPLEMENTED(); |
256 } | 256 } |
257 | 257 |
258 void SystemTray::ShowDefaultView(BubbleCreationType creation_type) { | 258 void SystemTray::ShowDefaultView(BubbleCreationType creation_type) { |
259 ShowDefaultViewWithOffset(creation_type, -1); | 259 ShowDefaultViewWithOffset(creation_type, |
260 TrayBubbleView::InitParams::kArrowDefaultOffset); | |
260 } | 261 } |
261 | 262 |
262 void SystemTray::ShowDetailedView(SystemTrayItem* item, | 263 void SystemTray::ShowDetailedView(SystemTrayItem* item, |
263 int close_delay, | 264 int close_delay, |
264 bool activate, | 265 bool activate, |
265 BubbleCreationType creation_type) { | 266 BubbleCreationType creation_type) { |
266 std::vector<SystemTrayItem*> items; | 267 std::vector<SystemTrayItem*> items; |
267 items.push_back(item); | 268 items.push_back(item); |
268 ShowItems(items, true, activate, creation_type, GetTrayXOffset(item)); | 269 ShowItems(items, true, activate, creation_type, GetTrayXOffset(item)); |
269 bubble_->StartAutoCloseTimer(close_delay); | 270 bubble_->StartAutoCloseTimer(close_delay); |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
359 Shell::GetInstance()->shelf()->UpdateAutoHideState(); | 360 Shell::GetInstance()->shelf()->UpdateAutoHideState(); |
360 } | 361 } |
361 } else if (bubble == notification_bubble_) { | 362 } else if (bubble == notification_bubble_) { |
362 notification_bubble_.reset(); | 363 notification_bubble_.reset(); |
363 } else { | 364 } else { |
364 NOTREACHED(); | 365 NOTREACHED(); |
365 } | 366 } |
366 } | 367 } |
367 | 368 |
368 int SystemTray::GetTrayXOffset(SystemTrayItem* item) const { | 369 int SystemTray::GetTrayXOffset(SystemTrayItem* item) const { |
370 // Don't attempt to align the arrow if the shelf is on the left or right. | |
371 if (shelf_alignment() != SHELF_ALIGNMENT_BOTTOM) | |
372 return TrayBubbleView::InitParams::kArrowDefaultOffset; | |
373 | |
369 std::map<SystemTrayItem*, views::View*>::const_iterator it = | 374 std::map<SystemTrayItem*, views::View*>::const_iterator it = |
370 tray_item_map_.find(item); | 375 tray_item_map_.find(item); |
371 if (it == tray_item_map_.end()) | 376 if (it == tray_item_map_.end()) |
372 return -1; | 377 return TrayBubbleView::InitParams::kArrowDefaultOffset; |
373 | 378 |
374 const views::View* item_view = it->second; | 379 const views::View* item_view = it->second; |
375 gfx::Rect item_bounds = item_view->bounds(); | 380 gfx::Rect rect(item_view->width() / 2, 0, 0, 0); |
msw
2012/07/27 20:32:04
nit: use a Point and ConvertPointToWidget; assign
stevenjb
2012/07/30 20:09:03
Done.
| |
376 if (!item_bounds.IsEmpty()) { | 381 gfx::Rect item_bounds = item_view->ConvertRectToWidget(rect); |
377 int x_offset = item_bounds.x() + item_bounds.width() / 2; | 382 if (!item_view->bounds().IsEmpty()) |
msw
2012/07/27 20:32:04
Invert the check and make this an early return of
stevenjb
2012/07/30 20:09:03
Good call, done.
| |
378 return base::i18n::IsRTL() ? x_offset : tray_container_->width() - x_offset; | 383 return item_bounds.x(); |
379 } | |
380 | 384 |
381 // The bounds of item could be still empty. It could happen in the case that | 385 // The bounds of item could be still empty if it does not have a visible |
382 // the view appears for the first time in the current session, because the | 386 // tray view. In that case, use the default (minimum) offset. |
383 // bounds is not calculated yet. In that case, we want to guess the offset | 387 return TrayBubbleView::InitParams::kArrowDefaultOffset; |
384 // from the position of its parent. | |
385 int x_offset = 0; | |
386 for (int i = 0; i < tray_container_->child_count(); ++i) { | |
387 const views::View* child = tray_container_->child_at(i); | |
388 if (child == item_view) | |
389 return base::i18n::IsRTL() ? | |
390 x_offset : tray_container_->width() - x_offset; | |
391 | |
392 if (!child->visible()) | |
393 continue; | |
394 x_offset = child->bounds().right(); | |
395 } | |
396 | |
397 return -1; | |
398 } | 388 } |
399 | 389 |
400 void SystemTray::ShowDefaultViewWithOffset(BubbleCreationType creation_type, | 390 void SystemTray::ShowDefaultViewWithOffset(BubbleCreationType creation_type, |
401 int arrow_offset) { | 391 int arrow_offset) { |
402 ShowItems(items_.get(), false, true, creation_type, arrow_offset); | 392 ShowItems(items_.get(), false, true, creation_type, arrow_offset); |
403 } | 393 } |
404 | 394 |
405 void SystemTray::ShowItems(const std::vector<SystemTrayItem*>& items, | 395 void SystemTray::ShowItems(const std::vector<SystemTrayItem*>& items, |
406 bool detailed, | 396 bool detailed, |
407 bool can_activate, | 397 bool can_activate, |
408 BubbleCreationType creation_type, | 398 BubbleCreationType creation_type, |
409 int arrow_offset) { | 399 int arrow_offset) { |
410 // Destroy any existing bubble and create a new one. | 400 // Destroy any existing bubble and create a new one. |
411 SystemTrayBubble::BubbleType bubble_type = detailed ? | 401 SystemTrayBubble::BubbleType bubble_type = detailed ? |
412 SystemTrayBubble::BUBBLE_TYPE_DETAILED : | 402 SystemTrayBubble::BUBBLE_TYPE_DETAILED : |
413 SystemTrayBubble::BUBBLE_TYPE_DEFAULT; | 403 SystemTrayBubble::BUBBLE_TYPE_DEFAULT; |
414 | 404 |
415 // Destroy the notification bubble here so that it doesn't get rebuilt | 405 // Destroy the notification bubble here so that it doesn't get rebuilt |
416 // while we add items to the main bubble_ (e.g. in HideNotificationView). | 406 // while we add items to the main bubble_ (e.g. in HideNotificationView). |
417 notification_bubble_.reset(); | 407 notification_bubble_.reset(); |
418 | 408 |
419 if (bubble_.get() && creation_type == BUBBLE_USE_EXISTING) { | 409 if (bubble_.get() && creation_type == BUBBLE_USE_EXISTING) { |
420 bubble_->UpdateView(items, bubble_type); | 410 bubble_->UpdateView(items, bubble_type); |
421 } else { | 411 } else { |
422 bubble_.reset(new SystemTrayBubble(this, items, bubble_type)); | 412 bubble_.reset(new SystemTrayBubble(this, items, bubble_type)); |
423 ash::SystemTrayDelegate* delegate = | 413 ash::SystemTrayDelegate* delegate = |
424 ash::Shell::GetInstance()->tray_delegate(); | 414 ash::Shell::GetInstance()->tray_delegate(); |
425 views::View* anchor = tray_container_; | 415 views::View* anchor = tray_container_; |
426 SystemTrayBubble::InitParams init_params( | 416 TrayBubbleView::InitParams init_params(TrayBubbleView::ANCHOR_TYPE_TRAY, |
427 SystemTrayBubble::ANCHOR_TYPE_TRAY, | 417 shelf_alignment()); |
428 shelf_alignment()); | |
429 init_params.anchor = anchor; | |
430 init_params.can_activate = can_activate; | 418 init_params.can_activate = can_activate; |
431 init_params.login_status = delegate->GetUserLoginStatus(); | |
432 if (arrow_offset >= 0) | |
433 init_params.arrow_offset = arrow_offset; | |
434 if (detailed) | 419 if (detailed) |
435 init_params.max_height = default_bubble_height_; | 420 init_params.max_height = default_bubble_height_; |
436 bubble_->InitView(init_params); | 421 init_params.arrow_offset = arrow_offset; |
422 bubble_->InitView(anchor, init_params, delegate->GetUserLoginStatus()); | |
437 } | 423 } |
438 // Save height of default view for creating detailed views directly. | 424 // Save height of default view for creating detailed views directly. |
439 if (!detailed) | 425 if (!detailed) |
440 default_bubble_height_ = bubble_->bubble_view()->height(); | 426 default_bubble_height_ = bubble_->bubble_view()->height(); |
441 | 427 |
442 if (detailed && items.size() > 0) | 428 if (detailed && items.size() > 0) |
443 detailed_item_ = items[0]; | 429 detailed_item_ = items[0]; |
444 else | 430 else |
445 detailed_item_ = NULL; | 431 detailed_item_ = NULL; |
446 | 432 |
(...skipping 25 matching lines...) Expand all Loading... | |
472 items.push_back(*iter); | 458 items.push_back(*iter); |
473 } | 459 } |
474 notification_bubble_.reset(new SystemTrayBubble( | 460 notification_bubble_.reset(new SystemTrayBubble( |
475 this, items, SystemTrayBubble::BUBBLE_TYPE_NOTIFICATION)); | 461 this, items, SystemTrayBubble::BUBBLE_TYPE_NOTIFICATION)); |
476 } else { | 462 } else { |
477 // Show all notifications. | 463 // Show all notifications. |
478 notification_bubble_.reset(new SystemTrayBubble( | 464 notification_bubble_.reset(new SystemTrayBubble( |
479 this, notification_items_, SystemTrayBubble::BUBBLE_TYPE_NOTIFICATION)); | 465 this, notification_items_, SystemTrayBubble::BUBBLE_TYPE_NOTIFICATION)); |
480 } | 466 } |
481 views::View* anchor; | 467 views::View* anchor; |
482 SystemTrayBubble::AnchorType anchor_type; | 468 TrayBubbleView::AnchorType anchor_type; |
483 if (bubble_.get()) { | 469 if (bubble_.get()) { |
484 anchor = bubble_->bubble_view(); | 470 anchor = bubble_->bubble_view(); |
485 anchor_type = SystemTrayBubble::ANCHOR_TYPE_BUBBLE; | 471 anchor_type = TrayBubbleView::ANCHOR_TYPE_BUBBLE; |
486 } else { | 472 } else { |
487 anchor = tray_container_; | 473 anchor = tray_container_; |
488 anchor_type = SystemTrayBubble::ANCHOR_TYPE_TRAY; | 474 anchor_type = TrayBubbleView::ANCHOR_TYPE_TRAY; |
489 } | 475 } |
490 SystemTrayBubble::InitParams init_params(anchor_type, shelf_alignment()); | 476 TrayBubbleView::InitParams init_params(anchor_type, shelf_alignment()); |
491 init_params.anchor = anchor; | 477 init_params.arrow_offset = GetTrayXOffset(notification_items_[0]); |
492 init_params.login_status = | 478 init_params.arrow_color = kBackgroundColor; |
493 ash::Shell::GetInstance()->tray_delegate()->GetUserLoginStatus(); | 479 user::LoginStatus login_status = |
494 int arrow_offset = GetTrayXOffset(notification_items_[0]); | 480 Shell::GetInstance()->tray_delegate()->GetUserLoginStatus(); |
495 if (arrow_offset >= 0) | 481 notification_bubble_->InitView(anchor, init_params, login_status); |
496 init_params.arrow_offset = arrow_offset; | |
497 notification_bubble_->InitView(init_params); | |
498 if (hide_notifications_) | 482 if (hide_notifications_) |
499 notification_bubble_->SetVisible(false); | 483 notification_bubble_->SetVisible(false); |
500 } | 484 } |
501 | 485 |
502 void SystemTray::UpdateNotificationAnchor() { | 486 void SystemTray::UpdateNotificationAnchor() { |
503 if (!notification_bubble_.get()) | 487 if (!notification_bubble_.get()) |
504 return; | 488 return; |
505 notification_bubble_->bubble_view()->UpdateAnchor(); | 489 notification_bubble_->bubble_view()->UpdateBubble(); |
506 // Ensure that the notification buble is above the launcher/status area. | 490 // Ensure that the notification buble is above the launcher/status area. |
507 notification_bubble_->bubble_view()->GetWidget()->StackAtTop(); | 491 notification_bubble_->bubble_view()->GetWidget()->StackAtTop(); |
508 } | 492 } |
509 | 493 |
510 void SystemTray::SetBorder() { | 494 void SystemTray::SetBorder() { |
511 // Change the border padding for different shelf alignment. | 495 // Change the border padding for different shelf alignment. |
512 if (shelf_alignment() == SHELF_ALIGNMENT_BOTTOM) { | 496 if (shelf_alignment() == SHELF_ALIGNMENT_BOTTOM) { |
513 set_border(views::Border::CreateEmptyBorder(0, 0, | 497 set_border(views::Border::CreateEmptyBorder(0, 0, |
514 kPaddingFromBottomOfScreenBottomAlignment, | 498 kPaddingFromBottomOfScreenBottomAlignment, |
515 kPaddingFromRightEdgeOfScreenBottomAlignment)); | 499 kPaddingFromRightEdgeOfScreenBottomAlignment)); |
(...skipping 10 matching lines...) Expand all Loading... | |
526 } | 510 } |
527 } | 511 } |
528 | 512 |
529 void SystemTray::SetShelfAlignment(ShelfAlignment alignment) { | 513 void SystemTray::SetShelfAlignment(ShelfAlignment alignment) { |
530 if (alignment == shelf_alignment()) | 514 if (alignment == shelf_alignment()) |
531 return; | 515 return; |
532 internal::TrayBackgroundView::SetShelfAlignment(alignment); | 516 internal::TrayBackgroundView::SetShelfAlignment(alignment); |
533 UpdateAfterShelfAlignmentChange(alignment); | 517 UpdateAfterShelfAlignmentChange(alignment); |
534 SetBorder(); | 518 SetBorder(); |
535 tray_container_->UpdateLayout(alignment); | 519 tray_container_->UpdateLayout(alignment); |
520 // Destroy an existing bubble so that it is rebuilt correctly. | |
msw
2012/07/27 20:32:04
nit: not sure if you meant to write "any".
stevenjb
2012/07/30 20:09:03
Done.
| |
521 bubble_.reset(); | |
522 // Rebuild any notification bubble. | |
523 if (notification_bubble_.get()) { | |
524 notification_bubble_.reset(); | |
525 UpdateNotificationBubble(); | |
526 } | |
536 } | 527 } |
537 | 528 |
538 bool SystemTray::PerformAction(const views::Event& event) { | 529 bool SystemTray::PerformAction(const views::Event& event) { |
539 // If we're already showing the default view, hide it; otherwise, show it | 530 // If we're already showing the default view, hide it; otherwise, show it |
540 // (and hide any popup that's currently shown). | 531 // (and hide any popup that's currently shown). |
541 if (bubble_.get() && | 532 if (bubble_.get() && |
542 bubble_->bubble_type() == SystemTrayBubble::BUBBLE_TYPE_DEFAULT) { | 533 bubble_->bubble_type() == SystemTrayBubble::BUBBLE_TYPE_DEFAULT) { |
543 bubble_->Close(); | 534 bubble_->Close(); |
544 } else { | 535 } else { |
545 int arrow_offset = -1; | 536 int arrow_offset = TrayBubbleView::InitParams::kArrowDefaultOffset; |
546 if (event.IsMouseEvent() || event.type() == ui::ET_GESTURE_TAP) { | 537 if (event.IsMouseEvent() || event.type() == ui::ET_GESTURE_TAP) { |
547 const views::LocatedEvent& located_event = | 538 const views::LocatedEvent& located_event = |
548 static_cast<const views::LocatedEvent&>(event); | 539 static_cast<const views::LocatedEvent&>(event); |
549 if (shelf_alignment() == SHELF_ALIGNMENT_BOTTOM) | 540 if (shelf_alignment() == SHELF_ALIGNMENT_BOTTOM) { |
550 arrow_offset = base::i18n::IsRTL() ? | 541 gfx::Rect bounds(located_event.x(), 0, 0, 0); |
msw
2012/07/27 20:32:04
nit: use a Point and ConvertPointToWidget.
stevenjb
2012/07/30 20:09:03
Done.
| |
551 located_event.x() : tray_container_->width() - located_event.x(); | 542 bounds = ConvertRectToWidget(bounds); |
543 arrow_offset = bounds.x(); | |
544 } | |
552 } | 545 } |
553 ShowDefaultViewWithOffset(BUBBLE_CREATE_NEW, arrow_offset); | 546 ShowDefaultViewWithOffset(BUBBLE_CREATE_NEW, arrow_offset); |
554 } | 547 } |
555 return true; | 548 return true; |
556 } | 549 } |
557 | 550 |
558 void SystemTray::OnMouseEntered(const views::MouseEvent& event) { | 551 void SystemTray::OnMouseEntered(const views::MouseEvent& event) { |
559 TrayBackgroundView::OnMouseEntered(event); | 552 TrayBackgroundView::OnMouseEntered(event); |
560 should_show_launcher_ = true; | 553 should_show_launcher_ = true; |
561 } | 554 } |
(...skipping 19 matching lines...) Expand all Loading... | |
581 | 574 |
582 void SystemTray::OnPaintFocusBorder(gfx::Canvas* canvas) { | 575 void SystemTray::OnPaintFocusBorder(gfx::Canvas* canvas) { |
583 // The tray itself expands to the right and bottom edge of the screen to make | 576 // The tray itself expands to the right and bottom edge of the screen to make |
584 // sure clicking on the edges brings up the popup. However, the focus border | 577 // sure clicking on the edges brings up the popup. However, the focus border |
585 // should be only around the container. | 578 // should be only around the container. |
586 if (GetWidget() && GetWidget()->IsActive()) | 579 if (GetWidget() && GetWidget()->IsActive()) |
587 DrawBorder(canvas, GetContentsBounds()); | 580 DrawBorder(canvas, GetContentsBounds()); |
588 } | 581 } |
589 | 582 |
590 } // namespace ash | 583 } // namespace ash |
OLD | NEW |