| 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 if (item_view->bounds().IsEmpty()) { |
| 376 if (!item_bounds.IsEmpty()) { | 381 // The bounds of item could be still empty if it does not have a visible |
| 377 int x_offset = item_bounds.x() + item_bounds.width() / 2; | 382 // tray view. In that case, use the default (minimum) offset. |
| 378 return base::i18n::IsRTL() ? x_offset : tray_container_->width() - x_offset; | 383 return TrayBubbleView::InitParams::kArrowDefaultOffset; |
| 379 } | 384 } |
| 380 | 385 |
| 381 // The bounds of item could be still empty. It could happen in the case that | 386 gfx::Point point(item_view->width() / 2, 0); |
| 382 // the view appears for the first time in the current session, because the | 387 ConvertPointToWidget(item_view, &point); |
| 383 // bounds is not calculated yet. In that case, we want to guess the offset | 388 return point.x(); |
| 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 } | 389 } |
| 399 | 390 |
| 400 void SystemTray::ShowDefaultViewWithOffset(BubbleCreationType creation_type, | 391 void SystemTray::ShowDefaultViewWithOffset(BubbleCreationType creation_type, |
| 401 int arrow_offset) { | 392 int arrow_offset) { |
| 402 ShowItems(items_.get(), false, true, creation_type, arrow_offset); | 393 ShowItems(items_.get(), false, true, creation_type, arrow_offset); |
| 403 } | 394 } |
| 404 | 395 |
| 405 void SystemTray::ShowItems(const std::vector<SystemTrayItem*>& items, | 396 void SystemTray::ShowItems(const std::vector<SystemTrayItem*>& items, |
| 406 bool detailed, | 397 bool detailed, |
| 407 bool can_activate, | 398 bool can_activate, |
| 408 BubbleCreationType creation_type, | 399 BubbleCreationType creation_type, |
| 409 int arrow_offset) { | 400 int arrow_offset) { |
| 410 // Destroy any existing bubble and create a new one. | 401 // Destroy any existing bubble and create a new one. |
| 411 SystemTrayBubble::BubbleType bubble_type = detailed ? | 402 SystemTrayBubble::BubbleType bubble_type = detailed ? |
| 412 SystemTrayBubble::BUBBLE_TYPE_DETAILED : | 403 SystemTrayBubble::BUBBLE_TYPE_DETAILED : |
| 413 SystemTrayBubble::BUBBLE_TYPE_DEFAULT; | 404 SystemTrayBubble::BUBBLE_TYPE_DEFAULT; |
| 414 | 405 |
| 415 // Destroy the notification bubble here so that it doesn't get rebuilt | 406 // 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). | 407 // while we add items to the main bubble_ (e.g. in HideNotificationView). |
| 417 notification_bubble_.reset(); | 408 notification_bubble_.reset(); |
| 418 | 409 |
| 419 if (bubble_.get() && creation_type == BUBBLE_USE_EXISTING) { | 410 if (bubble_.get() && creation_type == BUBBLE_USE_EXISTING) { |
| 420 bubble_->UpdateView(items, bubble_type); | 411 bubble_->UpdateView(items, bubble_type); |
| 421 } else { | 412 } else { |
| 422 bubble_.reset(new SystemTrayBubble(this, items, bubble_type)); | 413 bubble_.reset(new SystemTrayBubble(this, items, bubble_type)); |
| 423 ash::SystemTrayDelegate* delegate = | 414 ash::SystemTrayDelegate* delegate = |
| 424 ash::Shell::GetInstance()->tray_delegate(); | 415 ash::Shell::GetInstance()->tray_delegate(); |
| 425 views::View* anchor = tray_container_; | 416 views::View* anchor = tray_container_; |
| 426 SystemTrayBubble::InitParams init_params( | 417 TrayBubbleView::InitParams init_params(TrayBubbleView::ANCHOR_TYPE_TRAY, |
| 427 SystemTrayBubble::ANCHOR_TYPE_TRAY, | 418 shelf_alignment()); |
| 428 shelf_alignment()); | |
| 429 init_params.anchor = anchor; | |
| 430 init_params.can_activate = can_activate; | 419 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) | 420 if (detailed) |
| 435 init_params.max_height = default_bubble_height_; | 421 init_params.max_height = default_bubble_height_; |
| 436 bubble_->InitView(init_params); | 422 init_params.arrow_offset = arrow_offset; |
| 423 bubble_->InitView(anchor, init_params, delegate->GetUserLoginStatus()); |
| 437 } | 424 } |
| 438 // Save height of default view for creating detailed views directly. | 425 // Save height of default view for creating detailed views directly. |
| 439 if (!detailed) | 426 if (!detailed) |
| 440 default_bubble_height_ = bubble_->bubble_view()->height(); | 427 default_bubble_height_ = bubble_->bubble_view()->height(); |
| 441 | 428 |
| 442 if (detailed && items.size() > 0) | 429 if (detailed && items.size() > 0) |
| 443 detailed_item_ = items[0]; | 430 detailed_item_ = items[0]; |
| 444 else | 431 else |
| 445 detailed_item_ = NULL; | 432 detailed_item_ = NULL; |
| 446 | 433 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 472 items.push_back(*iter); | 459 items.push_back(*iter); |
| 473 } | 460 } |
| 474 notification_bubble_.reset(new SystemTrayBubble( | 461 notification_bubble_.reset(new SystemTrayBubble( |
| 475 this, items, SystemTrayBubble::BUBBLE_TYPE_NOTIFICATION)); | 462 this, items, SystemTrayBubble::BUBBLE_TYPE_NOTIFICATION)); |
| 476 } else { | 463 } else { |
| 477 // Show all notifications. | 464 // Show all notifications. |
| 478 notification_bubble_.reset(new SystemTrayBubble( | 465 notification_bubble_.reset(new SystemTrayBubble( |
| 479 this, notification_items_, SystemTrayBubble::BUBBLE_TYPE_NOTIFICATION)); | 466 this, notification_items_, SystemTrayBubble::BUBBLE_TYPE_NOTIFICATION)); |
| 480 } | 467 } |
| 481 views::View* anchor; | 468 views::View* anchor; |
| 482 SystemTrayBubble::AnchorType anchor_type; | 469 TrayBubbleView::AnchorType anchor_type; |
| 483 if (bubble_.get()) { | 470 if (bubble_.get()) { |
| 484 anchor = bubble_->bubble_view(); | 471 anchor = bubble_->bubble_view(); |
| 485 anchor_type = SystemTrayBubble::ANCHOR_TYPE_BUBBLE; | 472 anchor_type = TrayBubbleView::ANCHOR_TYPE_BUBBLE; |
| 486 } else { | 473 } else { |
| 487 anchor = tray_container_; | 474 anchor = tray_container_; |
| 488 anchor_type = SystemTrayBubble::ANCHOR_TYPE_TRAY; | 475 anchor_type = TrayBubbleView::ANCHOR_TYPE_TRAY; |
| 489 } | 476 } |
| 490 SystemTrayBubble::InitParams init_params(anchor_type, shelf_alignment()); | 477 TrayBubbleView::InitParams init_params(anchor_type, shelf_alignment()); |
| 491 init_params.anchor = anchor; | 478 init_params.arrow_offset = GetTrayXOffset(notification_items_[0]); |
| 492 init_params.login_status = | 479 init_params.arrow_color = kBackgroundColor; |
| 493 ash::Shell::GetInstance()->tray_delegate()->GetUserLoginStatus(); | 480 user::LoginStatus login_status = |
| 494 int arrow_offset = GetTrayXOffset(notification_items_[0]); | 481 Shell::GetInstance()->tray_delegate()->GetUserLoginStatus(); |
| 495 if (arrow_offset >= 0) | 482 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_) | 483 if (hide_notifications_) |
| 499 notification_bubble_->SetVisible(false); | 484 notification_bubble_->SetVisible(false); |
| 500 } | 485 } |
| 501 | 486 |
| 502 void SystemTray::UpdateNotificationAnchor() { | 487 void SystemTray::UpdateNotificationAnchor() { |
| 503 if (!notification_bubble_.get()) | 488 if (!notification_bubble_.get()) |
| 504 return; | 489 return; |
| 505 notification_bubble_->bubble_view()->UpdateBubble(); | 490 notification_bubble_->bubble_view()->UpdateBubble(); |
| 506 // Ensure that the notification buble is above the launcher/status area. | 491 // Ensure that the notification buble is above the launcher/status area. |
| 507 notification_bubble_->bubble_view()->GetWidget()->StackAtTop(); | 492 notification_bubble_->bubble_view()->GetWidget()->StackAtTop(); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 526 } | 511 } |
| 527 } | 512 } |
| 528 | 513 |
| 529 void SystemTray::SetShelfAlignment(ShelfAlignment alignment) { | 514 void SystemTray::SetShelfAlignment(ShelfAlignment alignment) { |
| 530 if (alignment == shelf_alignment()) | 515 if (alignment == shelf_alignment()) |
| 531 return; | 516 return; |
| 532 internal::TrayBackgroundView::SetShelfAlignment(alignment); | 517 internal::TrayBackgroundView::SetShelfAlignment(alignment); |
| 533 UpdateAfterShelfAlignmentChange(alignment); | 518 UpdateAfterShelfAlignmentChange(alignment); |
| 534 SetBorder(); | 519 SetBorder(); |
| 535 tray_container_->UpdateLayout(alignment); | 520 tray_container_->UpdateLayout(alignment); |
| 536 // Destroy an existing bubble so that it is rebuilt correctly. | 521 // Destroy any existing bubble so that it is rebuilt correctly. |
| 537 bubble_.reset(); | 522 bubble_.reset(); |
| 538 // Rebuild any notification bubble. | 523 // Rebuild any notification bubble. |
| 539 if (notification_bubble_.get()) { | 524 if (notification_bubble_.get()) { |
| 540 notification_bubble_.reset(); | 525 notification_bubble_.reset(); |
| 541 UpdateNotificationBubble(); | 526 UpdateNotificationBubble(); |
| 542 } | 527 } |
| 543 } | 528 } |
| 544 | 529 |
| 545 bool SystemTray::PerformAction(const views::Event& event) { | 530 bool SystemTray::PerformAction(const views::Event& event) { |
| 546 // If we're already showing the default view, hide it; otherwise, show it | 531 // If we're already showing the default view, hide it; otherwise, show it |
| 547 // (and hide any popup that's currently shown). | 532 // (and hide any popup that's currently shown). |
| 548 if (bubble_.get() && | 533 if (bubble_.get() && |
| 549 bubble_->bubble_type() == SystemTrayBubble::BUBBLE_TYPE_DEFAULT) { | 534 bubble_->bubble_type() == SystemTrayBubble::BUBBLE_TYPE_DEFAULT) { |
| 550 bubble_->Close(); | 535 bubble_->Close(); |
| 551 } else { | 536 } else { |
| 552 int arrow_offset = -1; | 537 int arrow_offset = TrayBubbleView::InitParams::kArrowDefaultOffset; |
| 553 if (event.IsMouseEvent() || event.type() == ui::ET_GESTURE_TAP) { | 538 if (event.IsMouseEvent() || event.type() == ui::ET_GESTURE_TAP) { |
| 554 const views::LocatedEvent& located_event = | 539 const views::LocatedEvent& located_event = |
| 555 static_cast<const views::LocatedEvent&>(event); | 540 static_cast<const views::LocatedEvent&>(event); |
| 556 if (shelf_alignment() == SHELF_ALIGNMENT_BOTTOM) | 541 if (shelf_alignment() == SHELF_ALIGNMENT_BOTTOM) { |
| 557 arrow_offset = base::i18n::IsRTL() ? | 542 gfx::Point point(located_event.x(), 0); |
| 558 located_event.x() : tray_container_->width() - located_event.x(); | 543 ConvertPointToWidget(this, &point); |
| 544 arrow_offset = point.x(); |
| 545 } |
| 559 } | 546 } |
| 560 ShowDefaultViewWithOffset(BUBBLE_CREATE_NEW, arrow_offset); | 547 ShowDefaultViewWithOffset(BUBBLE_CREATE_NEW, arrow_offset); |
| 561 } | 548 } |
| 562 return true; | 549 return true; |
| 563 } | 550 } |
| 564 | 551 |
| 565 void SystemTray::OnMouseEntered(const views::MouseEvent& event) { | 552 void SystemTray::OnMouseEntered(const views::MouseEvent& event) { |
| 566 TrayBackgroundView::OnMouseEntered(event); | 553 TrayBackgroundView::OnMouseEntered(event); |
| 567 should_show_launcher_ = true; | 554 should_show_launcher_ = true; |
| 568 } | 555 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 588 | 575 |
| 589 void SystemTray::OnPaintFocusBorder(gfx::Canvas* canvas) { | 576 void SystemTray::OnPaintFocusBorder(gfx::Canvas* canvas) { |
| 590 // The tray itself expands to the right and bottom edge of the screen to make | 577 // The tray itself expands to the right and bottom edge of the screen to make |
| 591 // sure clicking on the edges brings up the popup. However, the focus border | 578 // sure clicking on the edges brings up the popup. However, the focus border |
| 592 // should be only around the container. | 579 // should be only around the container. |
| 593 if (GetWidget() && GetWidget()->IsActive()) | 580 if (GetWidget() && GetWidget()->IsActive()) |
| 594 DrawBorder(canvas, GetContentsBounds()); | 581 DrawBorder(canvas, GetContentsBounds()); |
| 595 } | 582 } |
| 596 | 583 |
| 597 } // namespace ash | 584 } // namespace ash |
| OLD | NEW |