system_tray.cc revision 868fa2fe829687343ffae624259930155e16dbd8
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/system/tray/system_tray.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/ash_switches.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ash/shelf/shelf_layout_manager.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/shell.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/shell/panel_window.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/shell_window_ids.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/system/bluetooth/tray_bluetooth.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/system/brightness/tray_brightness.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/system/date/tray_date.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/system/drive/tray_drive.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/system/ime/tray_ime.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/system/locale/tray_locale.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/system/logout_button/tray_logout_button.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/system/monitor/tray_monitor.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ash/system/session_length_limit/tray_session_length_limit.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/system/status_area_widget.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/system/tray/system_tray_delegate.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/system/tray/system_tray_item.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/system/tray/tray_bubble_wrapper.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/system/tray/tray_constants.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/system/tray_accessibility.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/system/tray_caps_lock.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/system/tray_update.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/system/user/login_status.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/system/user/tray_user.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
33868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/timer.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/ash_strings.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/root_window.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/events/event_constants.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/compositor/layer.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/canvas.h"
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/screen.h"
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/skia_util.h"
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/border.h"
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/label.h"
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/layout/box_layout.h"
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/layout/fill_layout.h"
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/view.h"
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS)
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ash/system/chromeos/audio/tray_audio.h"
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ash/system/chromeos/enterprise/tray_enterprise.h"
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ash/system/chromeos/managed/tray_locally_managed_user.h"
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/system/chromeos/network/tray_network.h"
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/system/chromeos/network/tray_sms.h"
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/system/chromeos/network/tray_vpn.h"
5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ash/system/chromeos/power/tray_power.h"
57868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ash/system/chromeos/screen_security/screen_capture_tray_item.h"
58868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ash/system/chromeos/screen_security/screen_share_tray_item.h"
5990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ash/system/chromeos/settings/tray_settings.h"
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ash/system/chromeos/tray_display.h"
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using views::TrayBubbleView;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ash {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The minimum width of the system tray menu width.
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kMinimumSystemTrayMenuWidth = 300;
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace internal {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Class to initialize and manage the SystemTrayBubble and TrayBubbleWrapper
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// instances for a bubble.
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SystemBubbleWrapper {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Takes ownership of |bubble|.
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit SystemBubbleWrapper(internal::SystemTrayBubble* bubble)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : bubble_(bubble) {
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initializes the bubble view and creates |bubble_wrapper_|.
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void InitView(TrayBackgroundView* tray,
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                views::View* anchor,
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                TrayBubbleView::InitParams* init_params) {
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(anchor);
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user::LoginStatus login_status =
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        Shell::GetInstance()->system_tray_delegate()->GetUserLoginStatus();
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bubble_->InitView(anchor, login_status, init_params);
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bubble_wrapper_.reset(
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new internal::TrayBubbleWrapper(tray, bubble_->bubble_view()));
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Convenience accessors:
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SystemTrayBubble* bubble() const { return bubble_.get(); }
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SystemTrayBubble::BubbleType bubble_type() const {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return bubble_->bubble_type();
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TrayBubbleView* bubble_view() const { return bubble_->bubble_view(); }
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<internal::SystemTrayBubble> bubble_;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<internal::TrayBubbleWrapper> bubble_wrapper_;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SystemBubbleWrapper);
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace internal
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SystemTray
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using internal::SystemTrayBubble;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SystemTray::SystemTray(internal::StatusAreaWidget* status_area_widget)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : internal::TrayBackgroundView(status_area_widget),
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      items_(),
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default_bubble_height_(0),
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      hide_notifications_(false) {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetContentsBackground();
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SystemTray::~SystemTray() {
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Destroy any child views that might have back pointers before ~View().
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  system_bubble_.reset();
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notification_bubble_.reset();
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::vector<SystemTrayItem*>::iterator it = items_.begin();
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != items_.end();
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++it) {
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*it)->DestroyTrayView();
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SystemTray::InitializeTrayItems(SystemTrayDelegate* delegate) {
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  internal::TrayBackgroundView::Initialize();
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateItems(delegate);
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SystemTray::CreateItems(SystemTrayDelegate* delegate) {
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if !defined(OS_WIN)
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddTrayItem(new internal::TraySessionLengthLimit(this));
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddTrayItem(new internal::TrayLogoutButton(this));
14290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // In multi-profile user mode we can have multiple user tiles.
14390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ash::Shell* shell = ash::Shell::GetInstance();
14490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int maximum_user_profiles =
14590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      shell->delegate()->IsMultiProfilesEnabled() ?
14690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          shell->session_state_delegate()->GetMaximumNumberOfLoggedInUsers() :
14790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          0;
14890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Note: We purposely use one more item then logged in users to account for
14990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // the additional separator.
15090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for (int i = 0; i <= maximum_user_profiles; i++)
15190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    AddTrayItem(new internal::TrayUser(this, i));
15290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS)
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddTrayItem(new internal::TrayEnterprise(this));
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  AddTrayItem(new internal::TrayLocallyManagedUser(this));
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddTrayItem(new internal::TrayIME(this));
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  tray_accessibility_ = new internal::TrayAccessibility(this);
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddTrayItem(tray_accessibility_);
16190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#if defined(OS_CHROMEOS)
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddTrayItem(new internal::TrayPower(this));
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS)
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddTrayItem(new internal::TrayNetwork(this));
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddTrayItem(new internal::TrayVPN(this));
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddTrayItem(new internal::TraySms(this));
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if !defined(OS_WIN)
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddTrayItem(new internal::TrayBluetooth(this));
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddTrayItem(new internal::TrayDrive(this));
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddTrayItem(new internal::TrayLocale(this));
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS)
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddTrayItem(new internal::TrayDisplay(this));
176868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddTrayItem(new internal::ScreenCaptureTrayItem(this));
177868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddTrayItem(new internal::ScreenShareTrayItem(this));
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  AddTrayItem(new internal::TrayAudio(this));
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if !defined(OS_WIN)
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddTrayItem(new internal::TrayBrightness(this));
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddTrayItem(new internal::TrayCapsLock(this));
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif
18490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#if defined(OS_CHROMEOS)
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddTrayItem(new internal::TraySettings(this));
18690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddTrayItem(new internal::TrayUpdate(this));
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddTrayItem(new internal::TrayDate(this));
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_LINUX)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add memory monitor if enabled.
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CommandLine* cmd = CommandLine::ForCurrentProcess();
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cmd->HasSwitch(ash::switches::kAshEnableMemoryMonitor))
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AddTrayItem(new internal::TrayMonitor(this));
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetVisible(ash::Shell::GetInstance()->system_tray_delegate()->
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetTrayVisibilityOnStartup());
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SystemTray::AddTrayItem(SystemTrayItem* item) {
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  items_.push_back(item);
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SystemTrayDelegate* delegate = Shell::GetInstance()->system_tray_delegate();
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  views::View* tray_item = item->CreateTrayView(delegate->GetUserLoginStatus());
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  item->UpdateAfterShelfAlignmentChange(shelf_alignment());
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (tray_item) {
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tray_container()->AddChildViewAt(tray_item, 0);
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PreferredSizeChanged();
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tray_item_map_[item] = tray_item;
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SystemTray::RemoveTrayItem(SystemTrayItem* item) {
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTIMPLEMENTED();
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SystemTray::ShowDefaultView(BubbleCreationType creation_type) {
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ShowDefaultViewWithOffset(creation_type,
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            TrayBubbleView::InitParams::kArrowDefaultOffset);
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SystemTray::ShowDetailedView(SystemTrayItem* item,
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  int close_delay,
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  bool activate,
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  BubbleCreationType creation_type) {
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<SystemTrayItem*> items;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  items.push_back(item);
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ShowItems(items, true, activate, creation_type, GetTrayXOffset(item));
231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (system_bubble_)
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    system_bubble_->bubble()->StartAutoCloseTimer(close_delay);
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SystemTray::SetDetailedViewCloseDelay(int close_delay) {
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (HasSystemBubbleType(SystemTrayBubble::BUBBLE_TYPE_DETAILED))
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    system_bubble_->bubble()->StartAutoCloseTimer(close_delay);
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SystemTray::HideDetailedView(SystemTrayItem* item) {
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (item != detailed_item_)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DestroySystemBubble();
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdateNotificationBubble();
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SystemTray::ShowNotificationView(SystemTrayItem* item) {
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (std::find(notification_items_.begin(), notification_items_.end(), item)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      != notification_items_.end())
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notification_items_.push_back(item);
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdateNotificationBubble();
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SystemTray::HideNotificationView(SystemTrayItem* item) {
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<SystemTrayItem*>::iterator found_iter =
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::find(notification_items_.begin(), notification_items_.end(), item);
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (found_iter == notification_items_.end())
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notification_items_.erase(found_iter);
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Only update the notification bubble if visible (i.e. don't create one).
262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (notification_bubble_)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UpdateNotificationBubble();
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SystemTray::UpdateAfterLoginStatusChange(user::LoginStatus login_status) {
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DestroySystemBubble();
268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  UpdateNotificationBubble();
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::vector<SystemTrayItem*>::iterator it = items_.begin();
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      it != items_.end();
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++it) {
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*it)->UpdateAfterLoginStatusChange(login_status);
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetVisible(true);
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PreferredSizeChanged();
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SystemTray::UpdateAfterShelfAlignmentChange(ShelfAlignment alignment) {
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::vector<SystemTrayItem*>::iterator it = items_.begin();
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      it != items_.end();
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++it) {
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*it)->UpdateAfterShelfAlignmentChange(alignment);
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SystemTray::SetHideNotifications(bool hide_notifications) {
289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (notification_bubble_)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    notification_bubble_->bubble()->SetVisible(!hide_notifications);
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hide_notifications_ = hide_notifications;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SystemTray::ShouldShowLauncher() const {
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return system_bubble_.get() && system_bubble_->bubble()->ShouldShowLauncher();
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SystemTray::HasSystemBubble() const {
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return system_bubble_.get() != NULL;
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SystemTray::HasNotificationBubble() const {
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return notification_bubble_.get() != NULL;
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)internal::SystemTrayBubble* SystemTray::GetSystemBubble() {
307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!system_bubble_)
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return system_bubble_->bubble();
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SystemTray::IsAnyBubbleVisible() const {
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ((system_bubble_.get() &&
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           system_bubble_->bubble()->IsVisible()) ||
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (notification_bubble_.get() &&
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           notification_bubble_->bubble()->IsVisible()));
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SystemTray::IsMouseInNotificationBubble() const {
320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!notification_bubble_)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return notification_bubble_->bubble_view()->GetBoundsInScreen().Contains(
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Shell::GetScreen()->GetCursorScreenPoint());
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
326868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool SystemTray::CloseSystemBubble() const {
327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!system_bubble_)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  system_bubble_->bubble()->Close();
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SystemTray::CloseNotificationBubbleForTest() const {
334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!notification_bubble_)
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  notification_bubble_->bubble()->Close();
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Private methods.
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SystemTray::HasSystemBubbleType(SystemTrayBubble::BubbleType type) {
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(type != SystemTrayBubble::BUBBLE_TYPE_NOTIFICATION);
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return system_bubble_.get() && system_bubble_->bubble_type() == type;
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SystemTray::DestroySystemBubble() {
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  system_bubble_.reset();
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  detailed_item_ = NULL;
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SystemTray::DestroyNotificationBubble() {
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notification_bubble_.reset();
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  status_area_widget()->SetHideWebNotifications(false);
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SystemTray::GetTrayXOffset(SystemTrayItem* item) const {
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't attempt to align the arrow if the shelf is on the left or right.
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (shelf_alignment() != SHELF_ALIGNMENT_BOTTOM &&
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      shelf_alignment() != SHELF_ALIGNMENT_TOP)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TrayBubbleView::InitParams::kArrowDefaultOffset;
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::map<SystemTrayItem*, views::View*>::const_iterator it =
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tray_item_map_.find(item);
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it == tray_item_map_.end())
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TrayBubbleView::InitParams::kArrowDefaultOffset;
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const views::View* item_view = it->second;
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (item_view->bounds().IsEmpty()) {
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The bounds of item could be still empty if it does not have a visible
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // tray view. In that case, use the default (minimum) offset.
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TrayBubbleView::InitParams::kArrowDefaultOffset;
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Point point(item_view->width() / 2, 0);
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ConvertPointToWidget(item_view, &point);
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return point.x();
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SystemTray::ShowDefaultViewWithOffset(BubbleCreationType creation_type,
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           int arrow_offset) {
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ShowItems(items_.get(), false, true, creation_type, arrow_offset);
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SystemTray::ShowItems(const std::vector<SystemTrayItem*>& items,
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           bool detailed,
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           bool can_activate,
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           BubbleCreationType creation_type,
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           int arrow_offset) {
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Destroy any existing bubble and create a new one.
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SystemTrayBubble::BubbleType bubble_type = detailed ?
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SystemTrayBubble::BUBBLE_TYPE_DETAILED :
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SystemTrayBubble::BUBBLE_TYPE_DEFAULT;
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Destroy the notification bubble here so that it doesn't get rebuilt
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // while we add items to the main bubble_ (e.g. in HideNotificationView).
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notification_bubble_.reset();
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (system_bubble_.get() && creation_type == BUBBLE_USE_EXISTING) {
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    system_bubble_->bubble()->UpdateView(items, bubble_type);
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // The menu width is fixed, and it is a per language setting.
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int menu_width = std::max(kMinimumSystemTrayMenuWidth,
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        Shell::GetInstance()->system_tray_delegate()->GetSystemTrayMenuWidth());
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TrayBubbleView::InitParams init_params(TrayBubbleView::ANCHOR_TYPE_TRAY,
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           GetAnchorAlignment(),
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           menu_width,
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           kTrayPopupMaxWidth);
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    init_params.can_activate = can_activate;
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (detailed) {
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // This is the case where a volume control or brightness control bubble
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // is created.
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      init_params.max_height = default_bubble_height_;
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      init_params.arrow_color = kBackgroundColor;
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      init_params.arrow_color = kHeaderBackgroundColor;
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    init_params.arrow_offset = arrow_offset;
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // For Volume and Brightness we don't want to show an arrow when
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // they are shown in a bubble by themselves.
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    init_params.arrow_paint_type = views::BubbleBorder::PAINT_NORMAL;
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (items.size() == 1 && items[0]->ShouldHideArrow())
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      init_params.arrow_paint_type = views::BubbleBorder::PAINT_TRANSPARENT;
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SystemTrayBubble* bubble = new SystemTrayBubble(this, items, bubble_type);
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    system_bubble_.reset(new internal::SystemBubbleWrapper(bubble));
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    system_bubble_->InitView(this, tray_container(), &init_params);
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Save height of default view for creating detailed views directly.
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!detailed)
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default_bubble_height_ = system_bubble_->bubble_view()->height();
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (detailed && items.size() > 0)
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    detailed_item_ = items[0];
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    detailed_item_ = NULL;
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdateNotificationBubble();  // State changed, re-create notifications.
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  status_area_widget()->SetHideWebNotifications(true);
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetShelfLayoutManager()->UpdateAutoHideState();
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SystemTray::UpdateNotificationBubble() {
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Only show the notification buble if we have notifications.
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (notification_items_.empty()) {
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DestroyNotificationBubble();
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Destroy the existing bubble before constructing a new one.
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notification_bubble_.reset();
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SystemTrayBubble* notification_bubble;
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  notification_bubble = new SystemTrayBubble(
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      this, notification_items_, SystemTrayBubble::BUBBLE_TYPE_NOTIFICATION);
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  views::View* anchor;
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TrayBubbleView::AnchorType anchor_type;
456868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Tray items might want to show notifications while we are creating and
457868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // initializing the |system_bubble_| - but it might not be fully initialized
458868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // when coming here - this would produce a crashed like crbug.com/247416.
459868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // As such we check the existence of the widget here.
460868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (system_bubble_.get() &&
461868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      system_bubble_->bubble_view() &&
462868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      system_bubble_->bubble_view()->GetWidget()) {
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    anchor = system_bubble_->bubble_view();
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    anchor_type = TrayBubbleView::ANCHOR_TYPE_BUBBLE;
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    anchor = tray_container();
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    anchor_type = TrayBubbleView::ANCHOR_TYPE_TRAY;
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TrayBubbleView::InitParams init_params(anchor_type,
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         GetAnchorAlignment(),
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         kTrayPopupMinWidth,
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         kTrayPopupMaxWidth);
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  init_params.arrow_color = kBackgroundColor;
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  init_params.arrow_offset = GetTrayXOffset(notification_items_[0]);
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notification_bubble_.reset(
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new internal::SystemBubbleWrapper(notification_bubble));
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notification_bubble_->InitView(this, anchor, &init_params);
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (notification_bubble->bubble_view()->child_count() == 0) {
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // It is possible that none of the items generated actual notifications.
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DestroyNotificationBubble();
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (hide_notifications_)
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    notification_bubble->SetVisible(false);
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    status_area_widget()->SetHideWebNotifications(true);
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SystemTray::SetShelfAlignment(ShelfAlignment alignment) {
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (alignment == shelf_alignment())
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  internal::TrayBackgroundView::SetShelfAlignment(alignment);
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdateAfterShelfAlignmentChange(alignment);
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Destroy any existing bubble so that it is rebuilt correctly.
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  system_bubble_.reset();
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Rebuild any notification bubble.
498c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (notification_bubble_) {
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    notification_bubble_.reset();
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UpdateNotificationBubble();
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SystemTray::AnchorUpdated() {
505c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (notification_bubble_) {
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    notification_bubble_->bubble_view()->UpdateBubble();
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Ensure that the notification buble is above the launcher/status area.
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    notification_bubble_->bubble_view()->GetWidget()->StackAtTop();
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UpdateBubbleViewArrow(notification_bubble_->bubble_view());
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
511c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (system_bubble_) {
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    system_bubble_->bubble_view()->UpdateBubble();
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UpdateBubbleViewArrow(system_bubble_->bubble_view());
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
517c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)base::string16 SystemTray::GetAccessibleNameForTray() {
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_ACCESSIBLE_NAME);
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SystemTray::HideBubbleWithView(const TrayBubbleView* bubble_view) {
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (system_bubble_.get() && bubble_view == system_bubble_->bubble_view()) {
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DestroySystemBubble();
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UpdateNotificationBubble();  // State changed, re-create notifications.
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GetShelfLayoutManager()->UpdateAutoHideState();
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (notification_bubble_.get() &&
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             bubble_view == notification_bubble_->bubble_view()) {
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DestroyNotificationBubble();
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SystemTray::ClickedOutsideBubble() {
533c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!system_bubble_)
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HideBubbleWithView(system_bubble_->bubble_view());
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SystemTray::BubbleViewDestroyed() {
540c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (system_bubble_) {
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    system_bubble_->bubble()->DestroyItemViews();
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    system_bubble_->bubble()->BubbleViewDestroyed();
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SystemTray::OnMouseEnteredView() {
547c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (system_bubble_)
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    system_bubble_->bubble()->StopAutoCloseTimer();
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SystemTray::OnMouseExitedView() {
552c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (system_bubble_)
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    system_bubble_->bubble()->RestartAutoCloseTimer();
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
556c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)base::string16 SystemTray::GetAccessibleNameForBubble() {
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetAccessibleNameForTray();
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Rect SystemTray::GetAnchorRect(
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    views::Widget* anchor_widget,
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TrayBubbleView::AnchorType anchor_type,
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TrayBubbleView::AnchorAlignment anchor_alignment) {
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetBubbleAnchorRect(anchor_widget, anchor_type, anchor_alignment);
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SystemTray::HideBubble(const TrayBubbleView* bubble_view) {
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HideBubbleWithView(bubble_view);
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SystemTray::PerformAction(const ui::Event& event) {
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we're already showing the default view, hide it; otherwise, show it
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (and hide any popup that's currently shown).
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (HasSystemBubbleType(SystemTrayBubble::BUBBLE_TYPE_DEFAULT)) {
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    system_bubble_->bubble()->Close();
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int arrow_offset = TrayBubbleView::InitParams::kArrowDefaultOffset;
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (event.IsMouseEvent() || event.type() == ui::ET_GESTURE_TAP) {
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const ui::LocatedEvent& located_event =
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          static_cast<const ui::LocatedEvent&>(event);
5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (shelf_alignment() == SHELF_ALIGNMENT_BOTTOM ||
5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          shelf_alignment() == SHELF_ALIGNMENT_TOP) {
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        gfx::Point point(located_event.x(), 0);
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ConvertPointToWidget(this, &point);
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        arrow_offset = point.x();
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ShowDefaultViewWithOffset(BUBBLE_CREATE_NEW, arrow_offset);
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace ash
594