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
3// found in the LICENSE file.
4
5#include "ash/system/status_area_widget.h"
6
7#include "ash/root_window_controller.h"
8#include "ash/shelf/shelf_layout_manager.h"
9#include "ash/shelf/shelf_widget.h"
10#include "ash/shell.h"
11#include "ash/shell_delegate.h"
12#include "ash/shell_window_ids.h"
13#include "ash/system/bluetooth/bluetooth_observer.h"
14#include "ash/system/overview/overview_button_tray.h"
15#include "ash/system/status_area_widget_delegate.h"
16#include "ash/system/tray/system_tray.h"
17#include "ash/system/tray/system_tray_delegate.h"
18#include "ash/system/web_notification/web_notification_tray.h"
19#include "ash/wm/window_properties.h"
20#include "base/i18n/time_formatting.h"
21#include "ui/aura/window.h"
22#include "ui/gfx/screen.h"
23
24#if defined(OS_CHROMEOS)
25#include "ash/system/chromeos/session/logout_button_tray.h"
26#include "ash/system/chromeos/virtual_keyboard/virtual_keyboard_tray.h"
27#endif
28
29namespace ash {
30
31const char StatusAreaWidget::kNativeViewName[] = "StatusAreaWidget";
32
33StatusAreaWidget::StatusAreaWidget(aura::Window* status_container)
34    : status_area_widget_delegate_(new StatusAreaWidgetDelegate),
35      overview_button_tray_(NULL),
36      system_tray_(NULL),
37      web_notification_tray_(NULL),
38#if defined(OS_CHROMEOS)
39      logout_button_tray_(NULL),
40      virtual_keyboard_tray_(NULL),
41#endif
42      login_status_(user::LOGGED_IN_NONE) {
43  views::Widget::InitParams params(
44      views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
45  params.delegate = status_area_widget_delegate_;
46  params.parent = status_container;
47  params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
48  Init(params);
49  set_focus_on_creation(false);
50  SetContentsView(status_area_widget_delegate_);
51  GetNativeView()->SetName(kNativeViewName);
52}
53
54StatusAreaWidget::~StatusAreaWidget() {
55}
56
57void StatusAreaWidget::CreateTrayViews() {
58  AddOverviewButtonTray();
59  AddSystemTray();
60  AddWebNotificationTray();
61#if defined(OS_CHROMEOS)
62  AddLogoutButtonTray();
63  AddVirtualKeyboardTray();
64#endif
65
66  SystemTrayDelegate* delegate =
67      ash::Shell::GetInstance()->system_tray_delegate();
68  DCHECK(delegate);
69  // Initialize after all trays have been created.
70  system_tray_->InitializeTrayItems(delegate);
71  web_notification_tray_->Initialize();
72#if defined(OS_CHROMEOS)
73  logout_button_tray_->Initialize();
74  virtual_keyboard_tray_->Initialize();
75#endif
76  overview_button_tray_->Initialize();
77  UpdateAfterLoginStatusChange(delegate->GetUserLoginStatus());
78}
79
80void StatusAreaWidget::Shutdown() {
81  // Destroy the trays early, causing them to be removed from the view
82  // hierarchy. Do not used scoped pointers since we don't want to destroy them
83  // in the destructor if Shutdown() is not called (e.g. in tests).
84  delete web_notification_tray_;
85  web_notification_tray_ = NULL;
86  delete system_tray_;
87  system_tray_ = NULL;
88#if defined(OS_CHROMEOS)
89  delete virtual_keyboard_tray_;
90  virtual_keyboard_tray_ = NULL;
91  delete logout_button_tray_;
92  logout_button_tray_ = NULL;
93#endif
94  delete overview_button_tray_;
95  overview_button_tray_ = NULL;
96}
97
98bool StatusAreaWidget::ShouldShowShelf() const {
99  if ((system_tray_ && system_tray_->ShouldShowShelf()) ||
100      (web_notification_tray_ &&
101       web_notification_tray_->ShouldBlockShelfAutoHide()))
102    return true;
103
104  if (!RootWindowController::ForShelf(GetNativeView())->shelf()->IsVisible())
105    return false;
106
107  // If the shelf is currently visible, don't hide the shelf if the mouse
108  // is in any of the notification bubbles.
109  return (system_tray_ && system_tray_->IsMouseInNotificationBubble()) ||
110         (web_notification_tray_ &&
111          web_notification_tray_->IsMouseInNotificationBubble());
112}
113
114bool StatusAreaWidget::IsMessageBubbleShown() const {
115  return ((system_tray_ && system_tray_->IsAnyBubbleVisible()) ||
116          (web_notification_tray_ &&
117           web_notification_tray_->IsMessageCenterBubbleVisible()));
118}
119
120void StatusAreaWidget::SchedulePaint() {
121  status_area_widget_delegate_->SchedulePaint();
122  web_notification_tray_->SchedulePaint();
123  system_tray_->SchedulePaint();
124#if defined(OS_CHROMEOS)
125  virtual_keyboard_tray_->SchedulePaint();
126  logout_button_tray_->SchedulePaint();
127#endif
128  overview_button_tray_->SchedulePaint();
129}
130
131void StatusAreaWidget::OnNativeWidgetActivationChanged(bool active) {
132  Widget::OnNativeWidgetActivationChanged(active);
133  if (active)
134    status_area_widget_delegate_->SetPaneFocusAndFocusDefault();
135}
136
137void StatusAreaWidget::AddSystemTray() {
138  system_tray_ = new SystemTray(this);
139  status_area_widget_delegate_->AddTray(system_tray_);
140}
141
142void StatusAreaWidget::AddWebNotificationTray() {
143  web_notification_tray_ = new WebNotificationTray(this);
144  status_area_widget_delegate_->AddTray(web_notification_tray_);
145}
146
147#if defined(OS_CHROMEOS)
148void StatusAreaWidget::AddLogoutButtonTray() {
149  logout_button_tray_ = new LogoutButtonTray(this);
150  status_area_widget_delegate_->AddTray(logout_button_tray_);
151}
152
153void StatusAreaWidget::AddVirtualKeyboardTray() {
154  virtual_keyboard_tray_ = new VirtualKeyboardTray(this);
155  status_area_widget_delegate_->AddTray(virtual_keyboard_tray_);
156}
157#endif
158
159void StatusAreaWidget::AddOverviewButtonTray() {
160  overview_button_tray_ = new OverviewButtonTray(this);
161  status_area_widget_delegate_->AddTray(overview_button_tray_);
162}
163
164void StatusAreaWidget::SetShelfAlignment(ShelfAlignment alignment) {
165  status_area_widget_delegate_->set_alignment(alignment);
166  if (system_tray_)
167    system_tray_->SetShelfAlignment(alignment);
168  if (web_notification_tray_)
169    web_notification_tray_->SetShelfAlignment(alignment);
170#if defined(OS_CHROMEOS)
171  if (logout_button_tray_)
172    logout_button_tray_->SetShelfAlignment(alignment);
173  if (virtual_keyboard_tray_)
174    virtual_keyboard_tray_->SetShelfAlignment(alignment);
175#endif
176  if (overview_button_tray_)
177    overview_button_tray_->SetShelfAlignment(alignment);
178  status_area_widget_delegate_->UpdateLayout();
179}
180
181void StatusAreaWidget::SetHideSystemNotifications(bool hide) {
182  if (system_tray_)
183    system_tray_->SetHideNotifications(hide);
184}
185
186void StatusAreaWidget::UpdateAfterLoginStatusChange(
187    user::LoginStatus login_status) {
188  if (login_status_ == login_status)
189    return;
190  login_status_ = login_status;
191  if (system_tray_)
192    system_tray_->UpdateAfterLoginStatusChange(login_status);
193  if (web_notification_tray_)
194    web_notification_tray_->UpdateAfterLoginStatusChange(login_status);
195#if defined(OS_CHROMEOS)
196  if (logout_button_tray_)
197    logout_button_tray_->UpdateAfterLoginStatusChange(login_status);
198#endif
199  if (overview_button_tray_)
200    overview_button_tray_->UpdateAfterLoginStatusChange(login_status);
201}
202
203}  // namespace ash
204