| 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/common/system/tray/system_tray.h" | 5 #include "ash/common/system/tray/system_tray.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <map> | 8 #include <map> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| 11 #include "ash/common/key_event_watcher.h" | 11 #include "ash/common/key_event_watcher.h" |
| 12 #include "ash/common/login_status.h" | 12 #include "ash/common/login_status.h" |
| 13 #include "ash/common/material_design/material_design_controller.h" | 13 #include "ash/common/material_design/material_design_controller.h" |
| 14 #include "ash/common/session/session_state_delegate.h" | 14 #include "ash/common/session/session_state_delegate.h" |
| 15 #include "ash/common/shelf/wm_shelf.h" | 15 #include "ash/common/shelf/wm_shelf.h" |
| 16 #include "ash/common/shelf/wm_shelf_util.h" | 16 #include "ash/common/shelf/wm_shelf_util.h" |
| 17 #include "ash/common/system/chromeos/audio/tray_audio.h" | 17 #include "ash/common/system/chromeos/audio/tray_audio.h" |
| 18 #include "ash/common/system/chromeos/bluetooth/tray_bluetooth.h" | 18 #include "ash/common/system/chromeos/bluetooth/tray_bluetooth.h" |
| 19 #include "ash/common/system/chromeos/brightness/tray_brightness.h" | 19 #include "ash/common/system/chromeos/brightness/tray_brightness.h" |
| 20 #include "ash/common/system/chromeos/cast/tray_cast.h" | 20 #include "ash/common/system/chromeos/cast/tray_cast.h" |
| 21 #include "ash/common/system/chromeos/enterprise/tray_enterprise.h" | 21 #include "ash/common/system/chromeos/enterprise/tray_enterprise.h" |
| 22 #include "ash/common/system/chromeos/media_security/multi_profile_media_tray_ite
m.h" | 22 #include "ash/common/system/chromeos/media_security/multi_profile_media_tray_ite
m.h" |
| 23 #include "ash/common/system/chromeos/network/tray_network.h" | 23 #include "ash/common/system/chromeos/network/tray_network.h" |
| 24 #include "ash/common/system/chromeos/network/tray_sms.h" | |
| 25 #include "ash/common/system/chromeos/network/tray_vpn.h" | 24 #include "ash/common/system/chromeos/network/tray_vpn.h" |
| 26 #include "ash/common/system/chromeos/power/power_status.h" | 25 #include "ash/common/system/chromeos/power/power_status.h" |
| 27 #include "ash/common/system/chromeos/power/tray_power.h" | 26 #include "ash/common/system/chromeos/power/tray_power.h" |
| 28 #include "ash/common/system/chromeos/screen_security/screen_capture_tray_item.h" | 27 #include "ash/common/system/chromeos/screen_security/screen_capture_tray_item.h" |
| 29 #include "ash/common/system/chromeos/screen_security/screen_share_tray_item.h" | 28 #include "ash/common/system/chromeos/screen_security/screen_share_tray_item.h" |
| 30 #include "ash/common/system/chromeos/session/tray_session_length_limit.h" | 29 #include "ash/common/system/chromeos/session/tray_session_length_limit.h" |
| 31 #include "ash/common/system/chromeos/settings/tray_settings.h" | 30 #include "ash/common/system/chromeos/settings/tray_settings.h" |
| 32 #include "ash/common/system/chromeos/supervised/tray_supervised_user.h" | 31 #include "ash/common/system/chromeos/supervised/tray_supervised_user.h" |
| 33 #include "ash/common/system/chromeos/tray_caps_lock.h" | 32 #include "ash/common/system/chromeos/tray_caps_lock.h" |
| 34 #include "ash/common/system/chromeos/tray_tracing.h" | 33 #include "ash/common/system/chromeos/tray_tracing.h" |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 200 DISALLOW_COPY_AND_ASSIGN(ActivationObserver); | 199 DISALLOW_COPY_AND_ASSIGN(ActivationObserver); |
| 201 }; | 200 }; |
| 202 | 201 |
| 203 // SystemTray | 202 // SystemTray |
| 204 | 203 |
| 205 SystemTray::SystemTray(WmShelf* wm_shelf) | 204 SystemTray::SystemTray(WmShelf* wm_shelf) |
| 206 : TrayBackgroundView(wm_shelf), | 205 : TrayBackgroundView(wm_shelf), |
| 207 web_notification_tray_(nullptr), | 206 web_notification_tray_(nullptr), |
| 208 detailed_item_(nullptr), | 207 detailed_item_(nullptr), |
| 209 default_bubble_height_(0), | 208 default_bubble_height_(0), |
| 210 hide_notifications_(false), | |
| 211 full_system_tray_menu_(false), | 209 full_system_tray_menu_(false), |
| 212 tray_accessibility_(nullptr), | 210 tray_accessibility_(nullptr), |
| 213 tray_audio_(nullptr), | 211 tray_audio_(nullptr), |
| 214 tray_cast_(nullptr), | 212 tray_cast_(nullptr), |
| 215 tray_date_(nullptr), | 213 tray_date_(nullptr), |
| 216 tray_network_(nullptr), | 214 tray_network_(nullptr), |
| 217 tray_tiles_(nullptr), | 215 tray_tiles_(nullptr), |
| 218 tray_system_info_(nullptr), | 216 tray_system_info_(nullptr), |
| 219 tray_update_(nullptr), | 217 tray_update_(nullptr), |
| 220 screen_capture_tray_item_(nullptr), | 218 screen_capture_tray_item_(nullptr), |
| 221 screen_share_tray_item_(nullptr) { | 219 screen_share_tray_item_(nullptr) { |
| 222 if (MaterialDesignController::IsShelfMaterial()) { | 220 if (MaterialDesignController::IsShelfMaterial()) { |
| 223 SetInkDropMode(InkDropMode::ON); | 221 SetInkDropMode(InkDropMode::ON); |
| 224 SetContentsBackground(false); | 222 SetContentsBackground(false); |
| 225 | 223 |
| 226 // Since |system_tray| locates on the right most position, no separator is | 224 // Since |system_tray| locates on the right most position, no separator is |
| 227 // required on its right side. | 225 // required on its right side. |
| 228 set_separator_visibility(false); | 226 set_separator_visibility(false); |
| 229 } else { | 227 } else { |
| 230 SetContentsBackground(true); | 228 SetContentsBackground(true); |
| 231 } | 229 } |
| 232 } | 230 } |
| 233 | 231 |
| 234 SystemTray::~SystemTray() { | 232 SystemTray::~SystemTray() { |
| 235 // Destroy any child views that might have back pointers before ~View(). | 233 // Destroy any child views that might have back pointers before ~View(). |
| 236 activation_observer_.reset(); | 234 activation_observer_.reset(); |
| 237 key_event_watcher_.reset(); | 235 key_event_watcher_.reset(); |
| 238 system_bubble_.reset(); | 236 system_bubble_.reset(); |
| 239 notification_bubble_.reset(); | |
| 240 for (const auto& item : items_) | 237 for (const auto& item : items_) |
| 241 item->DestroyTrayView(); | 238 item->DestroyTrayView(); |
| 242 } | 239 } |
| 243 | 240 |
| 244 void SystemTray::InitializeTrayItems( | 241 void SystemTray::InitializeTrayItems( |
| 245 SystemTrayDelegate* delegate, | 242 SystemTrayDelegate* delegate, |
| 246 WebNotificationTray* web_notification_tray) { | 243 WebNotificationTray* web_notification_tray) { |
| 247 DCHECK(web_notification_tray); | 244 DCHECK(web_notification_tray); |
| 248 web_notification_tray_ = web_notification_tray; | 245 web_notification_tray_ = web_notification_tray; |
| 249 TrayBackgroundView::Initialize(); | 246 TrayBackgroundView::Initialize(); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 285 AddTrayItem(base::MakeUnique<TrayEnterprise>(this)); | 282 AddTrayItem(base::MakeUnique<TrayEnterprise>(this)); |
| 286 AddTrayItem(base::MakeUnique<TraySupervisedUser>(this)); | 283 AddTrayItem(base::MakeUnique<TraySupervisedUser>(this)); |
| 287 AddTrayItem(base::MakeUnique<TrayIME>(this)); | 284 AddTrayItem(base::MakeUnique<TrayIME>(this)); |
| 288 AddTrayItem(base::WrapUnique(tray_accessibility_)); | 285 AddTrayItem(base::WrapUnique(tray_accessibility_)); |
| 289 AddTrayItem(base::MakeUnique<TrayTracing>(this)); | 286 AddTrayItem(base::MakeUnique<TrayTracing>(this)); |
| 290 AddTrayItem( | 287 AddTrayItem( |
| 291 base::MakeUnique<TrayPower>(this, message_center::MessageCenter::Get())); | 288 base::MakeUnique<TrayPower>(this, message_center::MessageCenter::Get())); |
| 292 tray_network_ = new TrayNetwork(this); | 289 tray_network_ = new TrayNetwork(this); |
| 293 AddTrayItem(base::WrapUnique(tray_network_)); | 290 AddTrayItem(base::WrapUnique(tray_network_)); |
| 294 AddTrayItem(base::MakeUnique<TrayVPN>(this)); | 291 AddTrayItem(base::MakeUnique<TrayVPN>(this)); |
| 295 AddTrayItem(base::MakeUnique<TraySms>(this)); | |
| 296 AddTrayItem(base::MakeUnique<TrayBluetooth>(this)); | 292 AddTrayItem(base::MakeUnique<TrayBluetooth>(this)); |
| 297 tray_cast_ = new TrayCast(this); | 293 tray_cast_ = new TrayCast(this); |
| 298 AddTrayItem(base::WrapUnique(tray_cast_)); | 294 AddTrayItem(base::WrapUnique(tray_cast_)); |
| 299 screen_capture_tray_item_ = new ScreenCaptureTrayItem(this); | 295 screen_capture_tray_item_ = new ScreenCaptureTrayItem(this); |
| 300 AddTrayItem(base::WrapUnique(screen_capture_tray_item_)); | 296 AddTrayItem(base::WrapUnique(screen_capture_tray_item_)); |
| 301 screen_share_tray_item_ = new ScreenShareTrayItem(this); | 297 screen_share_tray_item_ = new ScreenShareTrayItem(this); |
| 302 AddTrayItem(base::WrapUnique(screen_share_tray_item_)); | 298 AddTrayItem(base::WrapUnique(screen_share_tray_item_)); |
| 303 AddTrayItem(base::MakeUnique<MultiProfileMediaTrayItem>(this)); | 299 AddTrayItem(base::MakeUnique<MultiProfileMediaTrayItem>(this)); |
| 304 tray_audio_ = new TrayAudio(this); | 300 tray_audio_ = new TrayAudio(this); |
| 305 AddTrayItem(base::WrapUnique(tray_audio_)); | 301 AddTrayItem(base::WrapUnique(tray_audio_)); |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 389 if (GetSystemBubble()) { | 385 if (GetSystemBubble()) { |
| 390 GetSystemBubble() | 386 GetSystemBubble() |
| 391 ->bubble_view() | 387 ->bubble_view() |
| 392 ->GetWidget() | 388 ->GetWidget() |
| 393 ->SetVisibilityAnimationTransition( | 389 ->SetVisibilityAnimationTransition( |
| 394 views::Widget::VisibilityTransition::ANIMATE_NONE); | 390 views::Widget::VisibilityTransition::ANIMATE_NONE); |
| 395 } | 391 } |
| 396 } | 392 } |
| 397 | 393 |
| 398 DestroySystemBubble(); | 394 DestroySystemBubble(); |
| 399 UpdateNotificationBubble(); | |
| 400 } | |
| 401 | |
| 402 void SystemTray::ShowNotificationView(SystemTrayItem* item) { | |
| 403 if (std::find(notification_items_.begin(), notification_items_.end(), item) != | |
| 404 notification_items_.end()) | |
| 405 return; | |
| 406 notification_items_.push_back(item); | |
| 407 UpdateNotificationBubble(); | |
| 408 } | |
| 409 | |
| 410 void SystemTray::HideNotificationView(SystemTrayItem* item) { | |
| 411 auto found_iter = | |
| 412 std::find(notification_items_.begin(), notification_items_.end(), item); | |
| 413 if (found_iter == notification_items_.end()) | |
| 414 return; | |
| 415 notification_items_.erase(found_iter); | |
| 416 // Only update the notification bubble if visible (i.e. don't create one). | |
| 417 if (notification_bubble_) | |
| 418 UpdateNotificationBubble(); | |
| 419 } | 395 } |
| 420 | 396 |
| 421 void SystemTray::UpdateAfterLoginStatusChange(LoginStatus login_status) { | 397 void SystemTray::UpdateAfterLoginStatusChange(LoginStatus login_status) { |
| 422 DestroySystemBubble(); | 398 DestroySystemBubble(); |
| 423 UpdateNotificationBubble(); | |
| 424 | 399 |
| 425 for (const auto& item : items_) | 400 for (const auto& item : items_) |
| 426 item->UpdateAfterLoginStatusChange(login_status); | 401 item->UpdateAfterLoginStatusChange(login_status); |
| 427 | 402 |
| 428 // Items default to SHELF_ALIGNMENT_BOTTOM. Update them if the initial | 403 // Items default to SHELF_ALIGNMENT_BOTTOM. Update them if the initial |
| 429 // position of the shelf differs. | 404 // position of the shelf differs. |
| 430 if (!IsHorizontalAlignment(shelf_alignment())) | 405 if (!IsHorizontalAlignment(shelf_alignment())) |
| 431 UpdateAfterShelfAlignmentChange(shelf_alignment()); | 406 UpdateAfterShelfAlignmentChange(shelf_alignment()); |
| 432 | 407 |
| 433 SetVisible(true); | 408 SetVisible(true); |
| 434 PreferredSizeChanged(); | 409 PreferredSizeChanged(); |
| 435 } | 410 } |
| 436 | 411 |
| 437 void SystemTray::UpdateAfterShelfAlignmentChange(ShelfAlignment alignment) { | 412 void SystemTray::UpdateAfterShelfAlignmentChange(ShelfAlignment alignment) { |
| 438 for (const auto& item : items_) | 413 for (const auto& item : items_) |
| 439 item->UpdateAfterShelfAlignmentChange(alignment); | 414 item->UpdateAfterShelfAlignmentChange(alignment); |
| 440 } | 415 } |
| 441 | 416 |
| 442 void SystemTray::SetHideNotifications(bool hide_notifications) { | |
| 443 if (notification_bubble_) | |
| 444 notification_bubble_->bubble()->SetVisible(!hide_notifications); | |
| 445 hide_notifications_ = hide_notifications; | |
| 446 } | |
| 447 | |
| 448 bool SystemTray::ShouldShowShelf() const { | 417 bool SystemTray::ShouldShowShelf() const { |
| 449 return system_bubble_.get() && system_bubble_->bubble()->ShouldShowShelf(); | 418 return system_bubble_.get() && system_bubble_->bubble()->ShouldShowShelf(); |
| 450 } | 419 } |
| 451 | 420 |
| 452 bool SystemTray::HasSystemBubble() const { | 421 bool SystemTray::HasSystemBubble() const { |
| 453 return system_bubble_.get() != NULL; | 422 return system_bubble_.get() != NULL; |
| 454 } | 423 } |
| 455 | 424 |
| 456 bool SystemTray::HasNotificationBubble() const { | |
| 457 return notification_bubble_.get() != NULL; | |
| 458 } | |
| 459 | |
| 460 SystemTrayBubble* SystemTray::GetSystemBubble() { | 425 SystemTrayBubble* SystemTray::GetSystemBubble() { |
| 461 if (!system_bubble_) | 426 if (!system_bubble_) |
| 462 return NULL; | 427 return NULL; |
| 463 return system_bubble_->bubble(); | 428 return system_bubble_->bubble(); |
| 464 } | 429 } |
| 465 | 430 |
| 466 bool SystemTray::IsAnyBubbleVisible() const { | 431 bool SystemTray::IsSystemBubbleVisible() const { |
| 467 return ((system_bubble_.get() && system_bubble_->bubble()->IsVisible()) || | 432 return HasSystemBubble() && system_bubble_->bubble()->IsVisible(); |
| 468 (notification_bubble_.get() && | |
| 469 notification_bubble_->bubble()->IsVisible())); | |
| 470 } | |
| 471 | |
| 472 bool SystemTray::IsMouseInNotificationBubble() const { | |
| 473 if (!notification_bubble_) | |
| 474 return false; | |
| 475 return notification_bubble_->bubble_view()->GetBoundsInScreen().Contains( | |
| 476 display::Screen::GetScreen()->GetCursorScreenPoint()); | |
| 477 } | 433 } |
| 478 | 434 |
| 479 bool SystemTray::CloseSystemBubble() const { | 435 bool SystemTray::CloseSystemBubble() const { |
| 480 if (!system_bubble_) | 436 if (!system_bubble_) |
| 481 return false; | 437 return false; |
| 482 CHECK(!activating_); | 438 CHECK(!activating_); |
| 483 system_bubble_->bubble()->Close(); | 439 system_bubble_->bubble()->Close(); |
| 484 return true; | 440 return true; |
| 485 } | 441 } |
| 486 | 442 |
| 487 views::View* SystemTray::GetHelpButtonView() const { | 443 views::View* SystemTray::GetHelpButtonView() const { |
| 488 if (MaterialDesignController::IsSystemTrayMenuMaterial()) | 444 if (MaterialDesignController::IsSystemTrayMenuMaterial()) |
| 489 return tray_tiles_->GetHelpButtonView(); | 445 return tray_tiles_->GetHelpButtonView(); |
| 490 return tray_date_->GetHelpButtonView(); | 446 return tray_date_->GetHelpButtonView(); |
| 491 } | 447 } |
| 492 | 448 |
| 493 TrayAudio* SystemTray::GetTrayAudio() const { | 449 TrayAudio* SystemTray::GetTrayAudio() const { |
| 494 return tray_audio_; | 450 return tray_audio_; |
| 495 } | 451 } |
| 496 | 452 |
| 497 // Private methods. | 453 // Private methods. |
| 498 | 454 |
| 499 bool SystemTray::HasSystemBubbleType(SystemTrayBubble::BubbleType type) { | 455 bool SystemTray::HasSystemBubbleType(SystemTrayBubble::BubbleType type) { |
| 500 DCHECK(type != SystemTrayBubble::BUBBLE_TYPE_NOTIFICATION); | |
| 501 return system_bubble_.get() && system_bubble_->bubble_type() == type; | 456 return system_bubble_.get() && system_bubble_->bubble_type() == type; |
| 502 } | 457 } |
| 503 | 458 |
| 504 void SystemTray::DestroySystemBubble() { | 459 void SystemTray::DestroySystemBubble() { |
| 505 CloseSystemBubbleAndDeactivateSystemTray(); | 460 CloseSystemBubbleAndDeactivateSystemTray(); |
| 506 detailed_item_ = NULL; | 461 detailed_item_ = NULL; |
| 507 UpdateWebNotifications(); | 462 UpdateWebNotifications(); |
| 508 } | 463 } |
| 509 | 464 |
| 510 void SystemTray::DestroyNotificationBubble() { | |
| 511 if (notification_bubble_) { | |
| 512 notification_bubble_.reset(); | |
| 513 UpdateWebNotifications(); | |
| 514 } | |
| 515 } | |
| 516 | |
| 517 base::string16 SystemTray::GetAccessibleNameForTray() { | 465 base::string16 SystemTray::GetAccessibleNameForTray() { |
| 518 base::string16 time = GetAccessibleTimeString(base::Time::Now()); | 466 base::string16 time = GetAccessibleTimeString(base::Time::Now()); |
| 519 base::string16 battery = PowerStatus::Get()->GetAccessibleNameString(false); | 467 base::string16 battery = PowerStatus::Get()->GetAccessibleNameString(false); |
| 520 return l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_ACCESSIBLE_DESCRIPTION, | 468 return l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_ACCESSIBLE_DESCRIPTION, |
| 521 time, battery); | 469 time, battery); |
| 522 } | 470 } |
| 523 | 471 |
| 524 void SystemTray::ShowItems(const std::vector<SystemTrayItem*>& items, | 472 void SystemTray::ShowItems(const std::vector<SystemTrayItem*>& items, |
| 525 bool detailed, | 473 bool detailed, |
| 526 bool can_activate, | 474 bool can_activate, |
| 527 BubbleCreationType creation_type, | 475 BubbleCreationType creation_type, |
| 528 bool persistent) { | 476 bool persistent) { |
| 529 // No system tray bubbles in kiosk mode. | 477 // No system tray bubbles in kiosk mode. |
| 530 SystemTrayDelegate* system_tray_delegate = | 478 SystemTrayDelegate* system_tray_delegate = |
| 531 WmShell::Get()->system_tray_delegate(); | 479 WmShell::Get()->system_tray_delegate(); |
| 532 if (system_tray_delegate->GetUserLoginStatus() == LoginStatus::KIOSK_APP || | 480 if (system_tray_delegate->GetUserLoginStatus() == LoginStatus::KIOSK_APP || |
| 533 system_tray_delegate->GetUserLoginStatus() == | 481 system_tray_delegate->GetUserLoginStatus() == |
| 534 LoginStatus::ARC_KIOSK_APP) { | 482 LoginStatus::ARC_KIOSK_APP) { |
| 535 return; | 483 return; |
| 536 } | 484 } |
| 537 | 485 |
| 538 // Destroy any existing bubble and create a new one. | 486 // Destroy any existing bubble and create a new one. |
| 539 SystemTrayBubble::BubbleType bubble_type = | 487 SystemTrayBubble::BubbleType bubble_type = |
| 540 detailed ? SystemTrayBubble::BUBBLE_TYPE_DETAILED | 488 detailed ? SystemTrayBubble::BUBBLE_TYPE_DETAILED |
| 541 : SystemTrayBubble::BUBBLE_TYPE_DEFAULT; | 489 : SystemTrayBubble::BUBBLE_TYPE_DEFAULT; |
| 542 | 490 |
| 543 // Destroy the notification bubble here so that it doesn't get rebuilt | |
| 544 // while we add items to the main bubble_ (e.g. in HideNotificationView). | |
| 545 notification_bubble_.reset(); | |
| 546 if (system_bubble_.get() && creation_type == BUBBLE_USE_EXISTING) { | 491 if (system_bubble_.get() && creation_type == BUBBLE_USE_EXISTING) { |
| 547 system_bubble_->bubble()->UpdateView(items, bubble_type); | 492 system_bubble_->bubble()->UpdateView(items, bubble_type); |
| 548 // If ChromeVox is enabled, focus the default item if no item is focused. | 493 // If ChromeVox is enabled, focus the default item if no item is focused. |
| 549 if (WmShell::Get()->accessibility_delegate()->IsSpokenFeedbackEnabled()) | 494 if (WmShell::Get()->accessibility_delegate()->IsSpokenFeedbackEnabled()) |
| 550 system_bubble_->bubble()->FocusDefaultIfNeeded(); | 495 system_bubble_->bubble()->FocusDefaultIfNeeded(); |
| 551 } else { | 496 } else { |
| 552 // Cleanup the existing bubble before showing a new one. Otherwise, it's | 497 // Cleanup the existing bubble before showing a new one. Otherwise, it's |
| 553 // possible to confuse the new system bubble with the old one during | 498 // possible to confuse the new system bubble with the old one during |
| 554 // destruction, leading to subtle errors/crashes such as crbug.com/545166. | 499 // destruction, leading to subtle errors/crashes such as crbug.com/545166. |
| 555 DestroySystemBubble(); | 500 DestroySystemBubble(); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 603 | 548 |
| 604 key_event_watcher_.reset(); | 549 key_event_watcher_.reset(); |
| 605 if (can_activate) | 550 if (can_activate) |
| 606 CreateKeyEventWatcher(); | 551 CreateKeyEventWatcher(); |
| 607 | 552 |
| 608 if (detailed && items.size() > 0) | 553 if (detailed && items.size() > 0) |
| 609 detailed_item_ = items[0]; | 554 detailed_item_ = items[0]; |
| 610 else | 555 else |
| 611 detailed_item_ = NULL; | 556 detailed_item_ = NULL; |
| 612 | 557 |
| 613 UpdateNotificationBubble(); // State changed, re-create notifications. | 558 UpdateWebNotifications(); |
| 614 if (!notification_bubble_) | |
| 615 UpdateWebNotifications(); | |
| 616 shelf()->UpdateAutoHideState(); | 559 shelf()->UpdateAutoHideState(); |
| 617 | 560 |
| 618 // When we show the system menu in our alternate shelf layout, we need to | 561 // When we show the system menu in our alternate shelf layout, we need to |
| 619 // tint the background. | 562 // tint the background. |
| 620 if (full_system_tray_menu_) | 563 if (full_system_tray_menu_) |
| 621 SetIsActive(true); | 564 SetIsActive(true); |
| 622 } | 565 } |
| 623 | 566 |
| 624 // TODO(estade): there's only one thing that triggers a notification bubble, | |
| 625 // and that's TraySms. We could delete a lot of code in SystemTray if that | |
| 626 // used the message center notifications instead. See crbug.com/630641 | |
| 627 void SystemTray::UpdateNotificationBubble() { | |
| 628 // Only show the notification bubble if we have notifications. | |
| 629 if (notification_items_.empty()) { | |
| 630 DestroyNotificationBubble(); | |
| 631 return; | |
| 632 } | |
| 633 // Destroy the existing bubble before constructing a new one. | |
| 634 notification_bubble_.reset(); | |
| 635 SystemTrayBubble* notification_bubble; | |
| 636 notification_bubble = new SystemTrayBubble( | |
| 637 this, notification_items_, SystemTrayBubble::BUBBLE_TYPE_NOTIFICATION); | |
| 638 // Tray items might want to show notifications while we are creating and | |
| 639 // initializing the |system_bubble_| - but it might not be fully initialized | |
| 640 // when coming here - this would produce a crashed like crbug.com/247416. | |
| 641 // As such we check the existence of the widget here. | |
| 642 TrayBubbleView::InitParams init_params( | |
| 643 GetAnchorAlignment(), kTrayPopupMinWidth, kTrayPopupMaxWidth); | |
| 644 views::View* anchor = GetBubbleAnchor(); | |
| 645 gfx::Insets anchor_insets = GetBubbleAnchorInsets(); | |
| 646 // If there's already a system menu bubble, stack this one on top. | |
| 647 if (system_bubble_.get() && system_bubble_->bubble_view() && | |
| 648 system_bubble_->bubble_view()->GetWidget()) { | |
| 649 anchor = system_bubble_->bubble_view(); | |
| 650 anchor_insets.Set(-message_center::kMarginBetweenItems, 0, 0, 0); | |
| 651 init_params.anchor_alignment = TrayBubbleView::ANCHOR_ALIGNMENT_BOTTOM; | |
| 652 } | |
| 653 init_params.bg_color = kBackgroundColor; | |
| 654 notification_bubble_.reset(new SystemBubbleWrapper(notification_bubble)); | |
| 655 notification_bubble_->InitView(this, anchor, anchor_insets, &init_params, | |
| 656 false); | |
| 657 | |
| 658 if (notification_bubble->bubble_view()->child_count() == 0) { | |
| 659 // It is possible that none of the items generated actual notifications. | |
| 660 DestroyNotificationBubble(); | |
| 661 return; | |
| 662 } | |
| 663 if (hide_notifications_) | |
| 664 notification_bubble->SetVisible(false); | |
| 665 else | |
| 666 UpdateWebNotifications(); | |
| 667 } | |
| 668 | |
| 669 void SystemTray::UpdateWebNotifications() { | 567 void SystemTray::UpdateWebNotifications() { |
| 670 TrayBubbleView* bubble_view = NULL; | 568 TrayBubbleView* bubble_view = NULL; |
| 671 if (notification_bubble_) | 569 if (system_bubble_) |
| 672 bubble_view = notification_bubble_->bubble_view(); | |
| 673 else if (system_bubble_) | |
| 674 bubble_view = system_bubble_->bubble_view(); | 570 bubble_view = system_bubble_->bubble_view(); |
| 675 | 571 |
| 676 int height = 0; | 572 int height = 0; |
| 677 if (bubble_view) { | 573 if (bubble_view) { |
| 678 gfx::Rect work_area = | 574 gfx::Rect work_area = |
| 679 display::Screen::GetScreen() | 575 display::Screen::GetScreen() |
| 680 ->GetDisplayNearestWindow(bubble_view->GetWidget()->GetNativeView()) | 576 ->GetDisplayNearestWindow(bubble_view->GetWidget()->GetNativeView()) |
| 681 .work_area(); | 577 .work_area(); |
| 682 height = | 578 height = |
| 683 std::max(0, work_area.bottom() - bubble_view->GetBoundsInScreen().y()); | 579 std::max(0, work_area.bottom() - bubble_view->GetBoundsInScreen().y()); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 695 } | 591 } |
| 696 | 592 |
| 697 void SystemTray::SetShelfAlignment(ShelfAlignment alignment) { | 593 void SystemTray::SetShelfAlignment(ShelfAlignment alignment) { |
| 698 if (alignment == shelf_alignment()) | 594 if (alignment == shelf_alignment()) |
| 699 return; | 595 return; |
| 700 TrayBackgroundView::SetShelfAlignment(alignment); | 596 TrayBackgroundView::SetShelfAlignment(alignment); |
| 701 UpdateAfterShelfAlignmentChange(alignment); | 597 UpdateAfterShelfAlignmentChange(alignment); |
| 702 // Destroy any existing bubble so that it is rebuilt correctly. | 598 // Destroy any existing bubble so that it is rebuilt correctly. |
| 703 CloseSystemBubbleAndDeactivateSystemTray(); | 599 CloseSystemBubbleAndDeactivateSystemTray(); |
| 704 // Rebuild any notification bubble. | 600 // Rebuild any notification bubble. |
| 705 if (notification_bubble_) { | 601 UpdateWebNotifications(); |
| 706 notification_bubble_.reset(); | |
| 707 UpdateNotificationBubble(); | |
| 708 // UpdateWebNotifications() should be called in UpdateNotificationBubble(). | |
| 709 } else if (!hide_notifications_) { | |
| 710 UpdateWebNotifications(); | |
| 711 } | |
| 712 } | 602 } |
| 713 | 603 |
| 714 void SystemTray::AnchorUpdated() { | 604 void SystemTray::AnchorUpdated() { |
| 715 if (notification_bubble_) { | |
| 716 notification_bubble_->bubble_view()->UpdateBubble(); | |
| 717 // Ensure that the notification buble is above the shelf/status area. | |
| 718 notification_bubble_->bubble_view()->GetWidget()->StackAtTop(); | |
| 719 UpdateBubbleViewArrow(notification_bubble_->bubble_view()); | |
| 720 } | |
| 721 if (system_bubble_) { | 605 if (system_bubble_) { |
| 722 system_bubble_->bubble_view()->UpdateBubble(); | 606 system_bubble_->bubble_view()->UpdateBubble(); |
| 723 UpdateBubbleViewArrow(system_bubble_->bubble_view()); | 607 UpdateBubbleViewArrow(system_bubble_->bubble_view()); |
| 724 } | 608 } |
| 725 } | 609 } |
| 726 | 610 |
| 727 void SystemTray::BubbleResized(const TrayBubbleView* bubble_view) { | 611 void SystemTray::BubbleResized(const TrayBubbleView* bubble_view) { |
| 728 UpdateWebNotifications(); | 612 UpdateWebNotifications(); |
| 729 } | 613 } |
| 730 | 614 |
| 731 void SystemTray::HideBubbleWithView(const TrayBubbleView* bubble_view) { | 615 void SystemTray::HideBubbleWithView(const TrayBubbleView* bubble_view) { |
| 732 if (system_bubble_.get() && bubble_view == system_bubble_->bubble_view()) { | 616 if (system_bubble_.get() && bubble_view == system_bubble_->bubble_view()) { |
| 733 DestroySystemBubble(); | 617 DestroySystemBubble(); |
| 734 UpdateNotificationBubble(); // State changed, re-create notifications. | |
| 735 shelf()->UpdateAutoHideState(); | 618 shelf()->UpdateAutoHideState(); |
| 736 } else if (notification_bubble_.get() && | |
| 737 bubble_view == notification_bubble_->bubble_view()) { | |
| 738 DestroyNotificationBubble(); | |
| 739 } | 619 } |
| 740 } | 620 } |
| 741 | 621 |
| 742 void SystemTray::ClickedOutsideBubble() { | 622 void SystemTray::ClickedOutsideBubble() { |
| 743 if (!system_bubble_ || system_bubble_->is_persistent()) | 623 if (!system_bubble_ || system_bubble_->is_persistent()) |
| 744 return; | 624 return; |
| 745 HideBubbleWithView(system_bubble_->bubble_view()); | 625 HideBubbleWithView(system_bubble_->bubble_view()); |
| 746 } | 626 } |
| 747 | 627 |
| 748 void SystemTray::BubbleViewDestroyed() { | 628 void SystemTray::BubbleViewDestroyed() { |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 897 .work_area() | 777 .work_area() |
| 898 .height(); | 778 .height(); |
| 899 if (work_area_height > 0) { | 779 if (work_area_height > 0) { |
| 900 UMA_HISTOGRAM_CUSTOM_COUNTS( | 780 UMA_HISTOGRAM_CUSTOM_COUNTS( |
| 901 "Ash.SystemMenu.PercentageOfWorkAreaHeightCoveredByMenu", | 781 "Ash.SystemMenu.PercentageOfWorkAreaHeightCoveredByMenu", |
| 902 100 * bubble_view->height() / work_area_height, 1, 300, 100); | 782 100 * bubble_view->height() / work_area_height, 1, 300, 100); |
| 903 } | 783 } |
| 904 } | 784 } |
| 905 | 785 |
| 906 } // namespace ash | 786 } // namespace ash |
| OLD | NEW |