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