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 |