| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/user/user_view.h" | 5 #include "ash/common/system/user/user_view.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "ash/common/material_design/material_design_controller.h" | |
| 11 #include "ash/common/multi_profile_uma.h" | 10 #include "ash/common/multi_profile_uma.h" |
| 12 #include "ash/common/popup_message.h" | 11 #include "ash/common/popup_message.h" |
| 13 #include "ash/common/session/session_state_delegate.h" | 12 #include "ash/common/session/session_state_delegate.h" |
| 14 #include "ash/common/shell_delegate.h" | 13 #include "ash/common/shell_delegate.h" |
| 15 #include "ash/common/system/tray/system_tray.h" | 14 #include "ash/common/system/tray/system_tray.h" |
| 16 #include "ash/common/system/tray/system_tray_controller.h" | 15 #include "ash/common/system/tray/system_tray_controller.h" |
| 17 #include "ash/common/system/tray/system_tray_delegate.h" | 16 #include "ash/common/system/tray/system_tray_delegate.h" |
| 18 #include "ash/common/system/tray/tray_constants.h" | 17 #include "ash/common/system/tray/tray_constants.h" |
| 19 #include "ash/common/system/tray/tray_popup_item_style.h" | 18 #include "ash/common/system/tray/tray_popup_item_style.h" |
| 20 #include "ash/common/system/tray/tray_popup_utils.h" | 19 #include "ash/common/system/tray/tray_popup_utils.h" |
| (...skipping 14 matching lines...) Expand all Loading... |
| 35 #include "grit/ash_strings.h" | 34 #include "grit/ash_strings.h" |
| 36 #include "ui/base/l10n/l10n_util.h" | 35 #include "ui/base/l10n/l10n_util.h" |
| 37 #include "ui/base/resource/resource_bundle.h" | 36 #include "ui/base/resource/resource_bundle.h" |
| 38 #include "ui/gfx/canvas.h" | 37 #include "ui/gfx/canvas.h" |
| 39 #include "ui/gfx/geometry/insets.h" | 38 #include "ui/gfx/geometry/insets.h" |
| 40 #include "ui/gfx/paint_vector_icon.h" | 39 #include "ui/gfx/paint_vector_icon.h" |
| 41 #include "ui/views/controls/button/label_button.h" | 40 #include "ui/views/controls/button/label_button.h" |
| 42 #include "ui/views/controls/label.h" | 41 #include "ui/views/controls/label.h" |
| 43 #include "ui/views/controls/separator.h" | 42 #include "ui/views/controls/separator.h" |
| 44 #include "ui/views/layout/fill_layout.h" | 43 #include "ui/views/layout/fill_layout.h" |
| 45 #include "ui/views/mouse_watcher_view_host.h" | |
| 46 #include "ui/views/painter.h" | 44 #include "ui/views/painter.h" |
| 47 | 45 |
| 48 namespace ash { | 46 namespace ash { |
| 49 namespace tray { | 47 namespace tray { |
| 50 | 48 |
| 51 namespace { | 49 namespace { |
| 52 | 50 |
| 53 bool UseMd() { | |
| 54 return MaterialDesignController::IsSystemTrayMenuMaterial(); | |
| 55 } | |
| 56 | |
| 57 // When a hover border is used, it is starting this many pixels before the icon | |
| 58 // position. | |
| 59 const int kTrayUserTileHoverBorderInset = 10; | |
| 60 | |
| 61 // Offsetting the popup message relative to the tray menu. | |
| 62 const int kPopupMessageOffset = 25; | |
| 63 | |
| 64 // Switch to a user with the given |user_index|. | 51 // Switch to a user with the given |user_index|. |
| 65 void SwitchUser(UserIndex user_index) { | 52 void SwitchUser(UserIndex user_index) { |
| 66 // Do not switch users when the log screen is presented. | 53 // Do not switch users when the log screen is presented. |
| 67 SessionStateDelegate* delegate = WmShell::Get()->GetSessionStateDelegate(); | 54 SessionStateDelegate* delegate = WmShell::Get()->GetSessionStateDelegate(); |
| 68 if (delegate->IsUserSessionBlocked()) | 55 if (delegate->IsUserSessionBlocked()) |
| 69 return; | 56 return; |
| 70 | 57 |
| 71 DCHECK(user_index > 0); | 58 DCHECK(user_index > 0); |
| 72 MultiProfileUMA::RecordSwitchActiveUser( | 59 MultiProfileUMA::RecordSwitchActiveUser( |
| 73 MultiProfileUMA::SWITCH_ACTIVE_USER_BY_TRAY); | 60 MultiProfileUMA::SWITCH_ACTIVE_USER_BY_TRAY); |
| 74 delegate->SwitchActiveUser(delegate->GetUserInfo(user_index)->GetAccountId()); | 61 delegate->SwitchActiveUser(delegate->GetUserInfo(user_index)->GetAccountId()); |
| 75 } | 62 } |
| 76 | 63 |
| 77 bool IsMultiProfileSupportedAndUserActive() { | 64 bool IsMultiProfileSupportedAndUserActive() { |
| 78 return WmShell::Get()->delegate()->IsMultiProfilesEnabled() && | 65 return WmShell::Get()->delegate()->IsMultiProfilesEnabled() && |
| 79 !WmShell::Get()->GetSessionStateDelegate()->IsUserSessionBlocked(); | 66 !WmShell::Get()->GetSessionStateDelegate()->IsUserSessionBlocked(); |
| 80 } | 67 } |
| 81 | 68 |
| 82 // Creates the view shown in the user switcher popup ("AddUserMenuOption"). | 69 // Creates the view shown in the user switcher popup ("AddUserMenuOption"). |
| 83 views::View* CreateAddUserView(AddUserSessionPolicy policy, | 70 views::View* CreateAddUserView(AddUserSessionPolicy policy, |
| 84 views::ButtonListener* listener) { | 71 views::ButtonListener* listener) { |
| 85 DCHECK(UseMd()); | |
| 86 auto view = new views::View; | 72 auto view = new views::View; |
| 87 const int icon_padding = (kMenuButtonSize - kMenuIconSize) / 2; | 73 const int icon_padding = (kMenuButtonSize - kMenuIconSize) / 2; |
| 88 auto layout = | 74 auto layout = |
| 89 new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, | 75 new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, |
| 90 kTrayPopupLabelHorizontalPadding + icon_padding); | 76 kTrayPopupLabelHorizontalPadding + icon_padding); |
| 91 layout->set_minimum_cross_axis_size( | 77 layout->set_minimum_cross_axis_size( |
| 92 GetTrayConstant(TRAY_POPUP_ITEM_MIN_HEIGHT)); | 78 GetTrayConstant(TRAY_POPUP_ITEM_MIN_HEIGHT)); |
| 93 view->SetLayoutManager(layout); | 79 view->SetLayoutManager(layout); |
| 94 view->set_background( | 80 view->set_background( |
| 95 views::Background::CreateSolidBackground(kBackgroundColor)); | 81 views::Background::CreateSolidBackground(kBackgroundColor)); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 128 label_style.set_color_style(TrayPopupItemStyle::ColorStyle::INACTIVE); | 114 label_style.set_color_style(TrayPopupItemStyle::ColorStyle::INACTIVE); |
| 129 vertical_padding += kMenuSeparatorVerticalPadding; | 115 vertical_padding += kMenuSeparatorVerticalPadding; |
| 130 } | 116 } |
| 131 label_style.SetupLabel(command_label); | 117 label_style.SetupLabel(command_label); |
| 132 view->AddChildView(command_label); | 118 view->AddChildView(command_label); |
| 133 view->SetBorder(views::CreateEmptyBorder(vertical_padding, icon_padding, | 119 view->SetBorder(views::CreateEmptyBorder(vertical_padding, icon_padding, |
| 134 vertical_padding, | 120 vertical_padding, |
| 135 kTrayPopupLabelHorizontalPadding)); | 121 kTrayPopupLabelHorizontalPadding)); |
| 136 if (policy == AddUserSessionPolicy::ALLOWED) { | 122 if (policy == AddUserSessionPolicy::ALLOWED) { |
| 137 auto button = | 123 auto button = |
| 138 new ButtonFromView(view, listener, TrayPopupInkDropStyle::INSET_BOUNDS, | 124 new ButtonFromView(view, listener, TrayPopupInkDropStyle::INSET_BOUNDS); |
| 139 false, gfx::Insets()); | |
| 140 button->SetAccessibleName( | 125 button->SetAccessibleName( |
| 141 l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_SIGN_IN_ANOTHER_ACCOUNT)); | 126 l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_SIGN_IN_ANOTHER_ACCOUNT)); |
| 142 return button; | 127 return button; |
| 143 } | 128 } |
| 144 | 129 |
| 145 return view; | 130 return view; |
| 146 } | 131 } |
| 147 | 132 |
| 148 class UserViewMouseWatcherHost : public views::MouseWatcherHost { | 133 class UserViewMouseWatcherHost : public views::MouseWatcherHost { |
| 149 public: | 134 public: |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 184 close_widget_.Run(); | 169 close_widget_.Run(); |
| 185 } | 170 } |
| 186 void OnGestureEvent(ui::GestureEvent* event) override { close_widget_.Run(); } | 171 void OnGestureEvent(ui::GestureEvent* event) override { close_widget_.Run(); } |
| 187 | 172 |
| 188 private: | 173 private: |
| 189 base::Closure close_widget_; | 174 base::Closure close_widget_; |
| 190 | 175 |
| 191 DISALLOW_COPY_AND_ASSIGN(AddUserWidgetContents); | 176 DISALLOW_COPY_AND_ASSIGN(AddUserWidgetContents); |
| 192 }; | 177 }; |
| 193 | 178 |
| 194 // The menu item view which gets shown when the user clicks in multi profile | |
| 195 // mode onto the user item. | |
| 196 class AddUserView : public views::View { | |
| 197 public: | |
| 198 // The |owner| is the view for which this view gets created. | |
| 199 AddUserView(ButtonFromView* owner); | |
| 200 ~AddUserView() override; | |
| 201 | |
| 202 // Get the anchor view for a message. | |
| 203 views::View* anchor() { return anchor_; } | |
| 204 | |
| 205 private: | |
| 206 // Overridden from views::View. | |
| 207 gfx::Size GetPreferredSize() const override; | |
| 208 | |
| 209 // Create the additional client content for this item. | |
| 210 void AddContent(); | |
| 211 | |
| 212 // This is the content we create and show. | |
| 213 views::View* add_user_; | |
| 214 | |
| 215 // This is the owner view of this item. | |
| 216 ButtonFromView* owner_; | |
| 217 | |
| 218 // The anchor view for targetted bubble messages. | |
| 219 views::View* anchor_; | |
| 220 | |
| 221 DISALLOW_COPY_AND_ASSIGN(AddUserView); | |
| 222 }; | |
| 223 | |
| 224 AddUserView::AddUserView(ButtonFromView* owner) | |
| 225 : add_user_(nullptr), owner_(owner), anchor_(nullptr) { | |
| 226 DCHECK(!UseMd()); | |
| 227 AddContent(); | |
| 228 owner_->ForceBorderVisible(true); | |
| 229 } | |
| 230 | |
| 231 AddUserView::~AddUserView() { | |
| 232 owner_->ForceBorderVisible(false); | |
| 233 } | |
| 234 | |
| 235 gfx::Size AddUserView::GetPreferredSize() const { | |
| 236 return owner_->bounds().size(); | |
| 237 } | |
| 238 | |
| 239 void AddUserView::AddContent() { | |
| 240 SetLayoutManager(new views::FillLayout()); | |
| 241 set_background(views::Background::CreateSolidBackground(kBackgroundColor)); | |
| 242 | |
| 243 add_user_ = new views::View; | |
| 244 add_user_->SetLayoutManager(new views::BoxLayout( | |
| 245 views::BoxLayout::kHorizontal, 0, 0, kTrayPopupPaddingBetweenItems)); | |
| 246 AddChildViewAt(add_user_, 0); | |
| 247 | |
| 248 // Add the icon which is also the anchor for messages. | |
| 249 add_user_->SetBorder( | |
| 250 views::CreateEmptyBorder(0, kTrayUserTileHoverBorderInset, 0, 0)); | |
| 251 RoundedImageView* icon = new RoundedImageView(kTrayRoundedBorderRadius, true); | |
| 252 anchor_ = icon; | |
| 253 icon->SetImage(*ui::ResourceBundle::GetSharedInstance() | |
| 254 .GetImageNamed(IDR_AURA_UBER_TRAY_ADD_MULTIPROFILE_USER) | |
| 255 .ToImageSkia(), | |
| 256 gfx::Size(kTrayItemSize, kTrayItemSize)); | |
| 257 add_user_->AddChildView(icon); | |
| 258 | |
| 259 // Add the command text. | |
| 260 views::Label* command_label = new views::Label( | |
| 261 l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_SIGN_IN_ANOTHER_ACCOUNT)); | |
| 262 command_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); | |
| 263 add_user_->AddChildView(command_label); | |
| 264 } | |
| 265 | |
| 266 // This border reserves 4dp above and 8dp below and paints a horizontal | 179 // This border reserves 4dp above and 8dp below and paints a horizontal |
| 267 // separator 3dp below the host view. | 180 // separator 3dp below the host view. |
| 268 class ActiveUserBorder : public views::Border { | 181 class ActiveUserBorder : public views::Border { |
| 269 public: | 182 public: |
| 270 ActiveUserBorder() {} | 183 ActiveUserBorder() {} |
| 271 ~ActiveUserBorder() override {} | 184 ~ActiveUserBorder() override {} |
| 272 | 185 |
| 273 // views::Border: | 186 // views::Border: |
| 274 void Paint(const views::View& view, gfx::Canvas* canvas) override { | 187 void Paint(const views::View& view, gfx::Canvas* canvas) override { |
| 275 canvas->FillRect( | 188 canvas->FillRect( |
| (...skipping 19 matching lines...) Expand all Loading... |
| 295 | 208 |
| 296 UserView::UserView(SystemTrayItem* owner, LoginStatus login, UserIndex index) | 209 UserView::UserView(SystemTrayItem* owner, LoginStatus login, UserIndex index) |
| 297 : user_index_(index), | 210 : user_index_(index), |
| 298 user_card_view_(nullptr), | 211 user_card_view_(nullptr), |
| 299 owner_(owner), | 212 owner_(owner), |
| 300 is_user_card_button_(false), | 213 is_user_card_button_(false), |
| 301 logout_button_(nullptr), | 214 logout_button_(nullptr), |
| 302 add_user_enabled_(true), | 215 add_user_enabled_(true), |
| 303 focus_manager_(nullptr) { | 216 focus_manager_(nullptr) { |
| 304 CHECK_NE(LoginStatus::NOT_LOGGED_IN, login); | 217 CHECK_NE(LoginStatus::NOT_LOGGED_IN, login); |
| 305 if (!UseMd() && !index && login == LoginStatus::PUBLIC) { | |
| 306 // Public user gets a yellow bg. | |
| 307 set_background(views::Background::CreateSolidBackground( | |
| 308 kPublicAccountBackgroundColor)); | |
| 309 } | |
| 310 // The logout button must be added before the user card so that the user card | 218 // The logout button must be added before the user card so that the user card |
| 311 // can correctly calculate the remaining available width. | 219 // can correctly calculate the remaining available width. |
| 312 // Note that only the current multiprofile user gets a button. | 220 // Note that only the current multiprofile user gets a button. |
| 313 if (IsActiveUser()) | 221 if (IsActiveUser()) |
| 314 AddLogoutButton(login); | 222 AddLogoutButton(login); |
| 315 AddUserCard(login); | 223 AddUserCard(login); |
| 316 | 224 |
| 317 if (UseMd()) { | 225 auto layout = new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0); |
| 318 auto layout = new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0); | 226 SetLayoutManager(layout); |
| 319 SetLayoutManager(layout); | 227 layout->set_cross_axis_alignment( |
| 320 layout->set_cross_axis_alignment( | 228 views::BoxLayout::CROSS_AXIS_ALIGNMENT_CENTER); |
| 321 views::BoxLayout::CROSS_AXIS_ALIGNMENT_CENTER); | 229 layout->SetFlexForView(user_card_view_, 1); |
| 322 layout->SetFlexForView(user_card_view_, 1); | |
| 323 | 230 |
| 324 if (IsActiveUser()) | 231 if (IsActiveUser()) |
| 325 SetBorder(base::MakeUnique<ActiveUserBorder>()); | 232 SetBorder(base::MakeUnique<ActiveUserBorder>()); |
| 326 } | |
| 327 } | 233 } |
| 328 | 234 |
| 329 UserView::~UserView() { | 235 UserView::~UserView() { |
| 330 RemoveAddUserMenuOption(); | 236 RemoveAddUserMenuOption(); |
| 331 } | 237 } |
| 332 | 238 |
| 333 void UserView::MouseMovedOutOfHost() { | |
| 334 DCHECK(!UseMd()); | |
| 335 RemoveAddUserMenuOption(); | |
| 336 } | |
| 337 | |
| 338 TrayUser::TestState UserView::GetStateForTest() const { | 239 TrayUser::TestState UserView::GetStateForTest() const { |
| 339 if (add_menu_option_.get()) { | 240 if (add_menu_option_.get()) { |
| 340 return add_user_enabled_ ? TrayUser::ACTIVE : TrayUser::ACTIVE_BUT_DISABLED; | 241 return add_user_enabled_ ? TrayUser::ACTIVE : TrayUser::ACTIVE_BUT_DISABLED; |
| 341 } | 242 } |
| 342 | 243 |
| 343 if (!is_user_card_button_) | 244 if (!is_user_card_button_) |
| 344 return TrayUser::SHOWN; | 245 return TrayUser::SHOWN; |
| 345 | 246 |
| 346 return static_cast<ButtonFromView*>(user_card_view_)->is_hovered_for_test() | 247 return static_cast<ButtonFromView*>(user_card_view_)->is_hovered_for_test() |
| 347 ? TrayUser::HOVERED | 248 ? TrayUser::HOVERED |
| 348 : TrayUser::SHOWN; | 249 : TrayUser::SHOWN; |
| 349 } | 250 } |
| 350 | 251 |
| 351 gfx::Rect UserView::GetBoundsInScreenOfUserButtonForTest() { | 252 gfx::Rect UserView::GetBoundsInScreenOfUserButtonForTest() { |
| 352 DCHECK(user_card_view_); | 253 DCHECK(user_card_view_); |
| 353 return user_card_view_->GetBoundsInScreen(); | 254 return user_card_view_->GetBoundsInScreen(); |
| 354 } | 255 } |
| 355 | 256 |
| 356 bool UserView::IsActiveUser() const { | 257 bool UserView::IsActiveUser() const { |
| 357 return user_index_ == 0; | 258 return user_index_ == 0; |
| 358 } | 259 } |
| 359 | 260 |
| 360 gfx::Size UserView::GetPreferredSize() const { | |
| 361 // MD uses a layout manager. | |
| 362 if (UseMd()) | |
| 363 return View::GetPreferredSize(); | |
| 364 | |
| 365 // The width is more or less ignored (set by other rows in the system menu). | |
| 366 gfx::Size size = user_card_view_->GetPreferredSize(); | |
| 367 if (logout_button_) | |
| 368 size.SetToMax(logout_button_->GetPreferredSize()); | |
| 369 // Only the active user panel will be forced to a certain height. | |
| 370 if (IsActiveUser()) { | |
| 371 size.set_height(std::max( | |
| 372 size.height(), | |
| 373 GetTrayConstant(TRAY_POPUP_ITEM_MIN_HEIGHT) + GetInsets().height())); | |
| 374 } | |
| 375 return size; | |
| 376 } | |
| 377 | |
| 378 int UserView::GetHeightForWidth(int width) const { | 261 int UserView::GetHeightForWidth(int width) const { |
| 379 return GetPreferredSize().height(); | 262 return GetPreferredSize().height(); |
| 380 } | 263 } |
| 381 | 264 |
| 382 void UserView::Layout() { | |
| 383 // MD uses a layout manager. | |
| 384 if (UseMd()) | |
| 385 return views::View::Layout(); | |
| 386 | |
| 387 gfx::Rect contents_area(GetContentsBounds()); | |
| 388 if (logout_button_) { | |
| 389 // Give the logout button the space it requests. | |
| 390 gfx::Rect logout_area = contents_area; | |
| 391 logout_area.ClampToCenteredSize(logout_button_->GetPreferredSize()); | |
| 392 logout_area.set_x(contents_area.right() - logout_area.width()); | |
| 393 | |
| 394 // Give the remaining space to the user card. | |
| 395 gfx::Rect user_card_area = contents_area; | |
| 396 int remaining_width = contents_area.width() - logout_area.width(); | |
| 397 if (IsMultiProfileSupportedAndUserActive()) { | |
| 398 // In multiprofile case |user_card_view_| and |logout_button_| have to | |
| 399 // have the same height. | |
| 400 int y = std::min(user_card_area.y(), logout_area.y()); | |
| 401 int height = std::max(user_card_area.height(), logout_area.height()); | |
| 402 logout_area.set_y(y); | |
| 403 logout_area.set_height(height); | |
| 404 user_card_area.set_y(y); | |
| 405 user_card_area.set_height(height); | |
| 406 | |
| 407 // In multiprofile mode we have also to increase the size of the card by | |
| 408 // the size of the border to make it overlap with the logout button. | |
| 409 user_card_area.set_width(std::max(0, remaining_width + 1)); | |
| 410 | |
| 411 // To make the logout button symmetrical with the user card we also make | |
| 412 // the button longer by the same size the hover area in front of the icon | |
| 413 // got inset. | |
| 414 logout_area.set_width(logout_area.width() + | |
| 415 kTrayUserTileHoverBorderInset); | |
| 416 } else { | |
| 417 // In all other modes we have to make sure that there is enough spacing | |
| 418 // between the two. | |
| 419 remaining_width -= kTrayPopupPaddingBetweenItems; | |
| 420 } | |
| 421 user_card_area.set_width(remaining_width); | |
| 422 user_card_view_->SetBoundsRect(user_card_area); | |
| 423 logout_button_->SetBoundsRect(logout_area); | |
| 424 } else { | |
| 425 user_card_view_->SetBoundsRect(contents_area); | |
| 426 } | |
| 427 } | |
| 428 | |
| 429 void UserView::ButtonPressed(views::Button* sender, const ui::Event& event) { | 265 void UserView::ButtonPressed(views::Button* sender, const ui::Event& event) { |
| 430 if (sender == logout_button_) { | 266 if (sender == logout_button_) { |
| 431 WmShell::Get()->RecordUserMetricsAction(UMA_STATUS_AREA_SIGN_OUT); | 267 WmShell::Get()->RecordUserMetricsAction(UMA_STATUS_AREA_SIGN_OUT); |
| 432 RemoveAddUserMenuOption(); | 268 RemoveAddUserMenuOption(); |
| 433 WmShell::Get()->system_tray_controller()->SignOut(); | 269 WmShell::Get()->system_tray_controller()->SignOut(); |
| 434 } else if (sender == user_card_view_ && | 270 } else if (sender == user_card_view_ && |
| 435 IsMultiProfileSupportedAndUserActive()) { | 271 IsMultiProfileSupportedAndUserActive()) { |
| 436 if (IsActiveUser()) { | 272 if (IsActiveUser()) { |
| 437 ToggleAddUserMenuOption(); | 273 ToggleAddUserMenuOption(); |
| 438 } else { | 274 } else { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 464 } | 300 } |
| 465 | 301 |
| 466 void UserView::AddLogoutButton(LoginStatus login) { | 302 void UserView::AddLogoutButton(LoginStatus login) { |
| 467 AddChildView(TrayPopupUtils::CreateVerticalSeparator()); | 303 AddChildView(TrayPopupUtils::CreateVerticalSeparator()); |
| 468 logout_button_ = TrayPopupUtils::CreateTrayPopupBorderlessButton( | 304 logout_button_ = TrayPopupUtils::CreateTrayPopupBorderlessButton( |
| 469 this, user::GetLocalizedSignOutStringForStatus(login, true)); | 305 this, user::GetLocalizedSignOutStringForStatus(login, true)); |
| 470 AddChildView(logout_button_); | 306 AddChildView(logout_button_); |
| 471 } | 307 } |
| 472 | 308 |
| 473 void UserView::AddUserCard(LoginStatus login) { | 309 void UserView::AddUserCard(LoginStatus login) { |
| 474 if (UseMd()) | |
| 475 return AddUserCardMd(login); | |
| 476 | |
| 477 // Add padding around the panel. | |
| 478 const int kSidePadding = kTrayPopupPaddingHorizontal; | |
| 479 SetBorder(views::CreateEmptyBorder( | |
| 480 kTrayPopupUserCardVerticalPadding, kSidePadding, | |
| 481 kTrayPopupUserCardVerticalPadding, kSidePadding)); | |
| 482 | |
| 483 views::TrayBubbleView* bubble_view = | |
| 484 owner_->system_tray()->GetSystemBubble()->bubble_view(); | |
| 485 int max_card_width = bubble_view->GetMaximumSize().width() - | |
| 486 (2 * kSidePadding + kTrayPopupPaddingBetweenItems); | |
| 487 if (logout_button_) | |
| 488 max_card_width -= logout_button_->GetPreferredSize().width(); | |
| 489 user_card_view_ = new UserCardView(login, max_card_width, user_index_); | |
| 490 // The entry is clickable when no system modal dialog is open and the multi | |
| 491 // profile option is active. | |
| 492 bool clickable = !WmShell::Get()->IsSystemModalWindowOpen() && | |
| 493 IsMultiProfileSupportedAndUserActive(); | |
| 494 if (clickable) { | |
| 495 // To allow the border to start before the icon, reduce the size before and | |
| 496 // add an inset to the icon to get the spacing. | |
| 497 if (IsActiveUser()) { | |
| 498 SetBorder(views::CreateEmptyBorder( | |
| 499 kTrayPopupUserCardVerticalPadding, | |
| 500 kSidePadding - kTrayUserTileHoverBorderInset, | |
| 501 kTrayPopupUserCardVerticalPadding, kSidePadding)); | |
| 502 user_card_view_->SetBorder( | |
| 503 views::CreateEmptyBorder(0, kTrayUserTileHoverBorderInset, 0, 0)); | |
| 504 } | |
| 505 gfx::Insets insets = gfx::Insets(1, 1, 1, 1); | |
| 506 views::View* contents_view = user_card_view_; | |
| 507 if (!IsActiveUser()) { | |
| 508 // Since the activation border needs to be drawn around the tile, we | |
| 509 // have to put the tile into another view which fills the menu panel, | |
| 510 // but keeping the offsets of the content. | |
| 511 contents_view = new views::View(); | |
| 512 contents_view->SetBorder(views::CreateEmptyBorder( | |
| 513 kTrayPopupUserCardVerticalPadding, kSidePadding, | |
| 514 kTrayPopupUserCardVerticalPadding, kSidePadding)); | |
| 515 contents_view->SetLayoutManager(new views::FillLayout()); | |
| 516 SetBorder(nullptr); | |
| 517 contents_view->AddChildView(user_card_view_); | |
| 518 insets = gfx::Insets(1, 1, 1, 3); | |
| 519 } | |
| 520 auto* button = new ButtonFromView(contents_view, this, | |
| 521 // This parameter is ignored in non-md. | |
| 522 TrayPopupInkDropStyle::FILL_BOUNDS, | |
| 523 IsActiveUser(), insets); | |
| 524 user_card_view_ = button; | |
| 525 is_user_card_button_ = true; | |
| 526 } | |
| 527 AddChildViewAt(user_card_view_, 0); | |
| 528 // Card for supervised user can consume more space than currently | |
| 529 // available. In that case we should increase system bubble's width. | |
| 530 if (login == LoginStatus::PUBLIC) | |
| 531 bubble_view->SetWidth(GetPreferredSize().width()); | |
| 532 } | |
| 533 | |
| 534 void UserView::AddUserCardMd(LoginStatus login) { | |
| 535 user_card_view_ = new UserCardView(login, -1, user_index_); | 310 user_card_view_ = new UserCardView(login, -1, user_index_); |
| 536 // The entry is clickable when no system modal dialog is open and the multi | 311 // The entry is clickable when no system modal dialog is open and the multi |
| 537 // profile option is active. | 312 // profile option is active. |
| 538 bool clickable = !WmShell::Get()->IsSystemModalWindowOpen() && | 313 bool clickable = !WmShell::Get()->IsSystemModalWindowOpen() && |
| 539 IsMultiProfileSupportedAndUserActive(); | 314 IsMultiProfileSupportedAndUserActive(); |
| 540 if (clickable) { | 315 if (clickable) { |
| 541 views::View* contents_view = user_card_view_; | 316 views::View* contents_view = user_card_view_; |
| 542 auto* button = | 317 auto* button = |
| 543 new ButtonFromView(contents_view, this, | 318 new ButtonFromView(contents_view, this, |
| 544 IsActiveUser() ? TrayPopupInkDropStyle::INSET_BOUNDS | 319 IsActiveUser() ? TrayPopupInkDropStyle::INSET_BOUNDS |
| 545 : TrayPopupInkDropStyle::FILL_BOUNDS, | 320 : TrayPopupInkDropStyle::FILL_BOUNDS); |
| 546 false, gfx::Insets()); | |
| 547 user_card_view_ = button; | 321 user_card_view_ = button; |
| 548 is_user_card_button_ = true; | 322 is_user_card_button_ = true; |
| 549 } | 323 } |
| 550 AddChildViewAt(user_card_view_, 0); | 324 AddChildViewAt(user_card_view_, 0); |
| 551 } | 325 } |
| 552 | 326 |
| 553 void UserView::ToggleAddUserMenuOption() { | 327 void UserView::ToggleAddUserMenuOption() { |
| 554 if (add_menu_option_.get()) { | 328 if (add_menu_option_.get()) { |
| 555 RemoveAddUserMenuOption(); | 329 RemoveAddUserMenuOption(); |
| 556 return; | 330 return; |
| 557 } | 331 } |
| 558 | 332 |
| 559 // Note: We do not need to install a global event handler to delete this | 333 // Note: We do not need to install a global event handler to delete this |
| 560 // item since it will destroyed automatically before the menu / user menu item | 334 // item since it will destroyed automatically before the menu / user menu item |
| 561 // gets destroyed.. | 335 // gets destroyed.. |
| 562 add_menu_option_.reset(new views::Widget); | 336 add_menu_option_.reset(new views::Widget); |
| 563 views::Widget::InitParams params; | 337 views::Widget::InitParams params; |
| 564 params.type = views::Widget::InitParams::TYPE_TOOLTIP; | 338 params.type = views::Widget::InitParams::TYPE_TOOLTIP; |
| 565 params.keep_on_top = true; | 339 params.keep_on_top = true; |
| 566 params.accept_events = true; | 340 params.accept_events = true; |
| 567 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | 341 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
| 568 if (!UseMd()) | |
| 569 params.shadow_type = views::Widget::InitParams::SHADOW_TYPE_NONE; | |
| 570 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; | 342 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; |
| 571 params.name = "AddUserMenuOption"; | 343 params.name = "AddUserMenuOption"; |
| 572 WmLookup::Get() | 344 WmLookup::Get() |
| 573 ->GetWindowForWidget(GetWidget()) | 345 ->GetWindowForWidget(GetWidget()) |
| 574 ->GetRootWindowController() | 346 ->GetRootWindowController() |
| 575 ->ConfigureWidgetInitParamsForContainer( | 347 ->ConfigureWidgetInitParamsForContainer( |
| 576 add_menu_option_.get(), kShellWindowId_DragImageAndTooltipContainer, | 348 add_menu_option_.get(), kShellWindowId_DragImageAndTooltipContainer, |
| 577 ¶ms); | 349 ¶ms); |
| 578 add_menu_option_->Init(params); | 350 add_menu_option_->Init(params); |
| 579 | 351 |
| 580 const SessionStateDelegate* delegate = | 352 const SessionStateDelegate* delegate = |
| 581 WmShell::Get()->GetSessionStateDelegate(); | 353 WmShell::Get()->GetSessionStateDelegate(); |
| 582 const AddUserSessionPolicy add_user_policy = | 354 const AddUserSessionPolicy add_user_policy = |
| 583 delegate->GetAddUserSessionPolicy(); | 355 delegate->GetAddUserSessionPolicy(); |
| 584 add_user_enabled_ = add_user_policy == AddUserSessionPolicy::ALLOWED; | 356 add_user_enabled_ = add_user_policy == AddUserSessionPolicy::ALLOWED; |
| 585 | 357 |
| 586 if (UseMd()) { | 358 // Position the widget on top of the user card view (which is still in the |
| 587 // Position the widget on top of the user card view (which is still in the | 359 // system menu). The top half of the widget will be transparent to allow |
| 588 // system menu). The top half of the widget will be transparent to allow | 360 // the active user to show through. |
| 589 // the active user to show through. | 361 gfx::Rect bounds = user_card_view_->GetBoundsInScreen(); |
| 590 gfx::Rect bounds = user_card_view_->GetBoundsInScreen(); | 362 bounds.set_width(bounds.width() + kSeparatorWidth); |
| 591 bounds.set_width(bounds.width() + kSeparatorWidth); | 363 int row_height = bounds.height(); |
| 592 int row_height = bounds.height(); | |
| 593 | 364 |
| 594 views::View* container = new AddUserWidgetContents( | 365 views::View* container = new AddUserWidgetContents( |
| 595 base::Bind(&UserView::RemoveAddUserMenuOption, base::Unretained(this))); | 366 base::Bind(&UserView::RemoveAddUserMenuOption, base::Unretained(this))); |
| 596 container->SetBorder(views::CreatePaddedBorder( | 367 container->SetBorder(views::CreatePaddedBorder( |
| 597 views::CreateSolidSidedBorder(0, 0, 0, kSeparatorWidth, | 368 views::CreateSolidSidedBorder(0, 0, 0, kSeparatorWidth, kBackgroundColor), |
| 598 kBackgroundColor), | 369 gfx::Insets(row_height, 0, 0, 0))); |
| 599 gfx::Insets(row_height, 0, 0, 0))); | 370 views::View* add_user_padding = new views::View(); |
| 600 views::View* add_user_padding = new views::View(); | 371 add_user_padding->SetBorder(views::CreateSolidSidedBorder( |
| 601 add_user_padding->SetBorder(views::CreateSolidSidedBorder( | 372 kMenuSeparatorVerticalPadding, 0, 0, 0, kBackgroundColor)); |
| 602 kMenuSeparatorVerticalPadding, 0, 0, 0, kBackgroundColor)); | 373 views::View* add_user_view = CreateAddUserView(add_user_policy, this); |
| 603 views::View* add_user_view = CreateAddUserView(add_user_policy, this); | 374 add_user_padding->AddChildView(add_user_view); |
| 604 add_user_padding->AddChildView(add_user_view); | 375 add_user_padding->SetLayoutManager(new views::FillLayout()); |
| 605 add_user_padding->SetLayoutManager(new views::FillLayout()); | 376 container->AddChildView(add_user_padding); |
| 606 container->AddChildView(add_user_padding); | 377 container->SetLayoutManager(new views::FillLayout()); |
| 607 container->SetLayoutManager(new views::FillLayout()); | 378 add_menu_option_->SetContentsView(container); |
| 608 add_menu_option_->SetContentsView(container); | |
| 609 | 379 |
| 610 bounds.set_height(container->GetPreferredSize().height()); | 380 bounds.set_height(container->GetPreferredSize().height()); |
| 611 add_menu_option_->SetBounds(bounds); | 381 add_menu_option_->SetBounds(bounds); |
| 612 | 382 |
| 613 // Show the content. | 383 // Show the content. |
| 614 add_menu_option_->SetAlwaysOnTop(true); | 384 add_menu_option_->SetAlwaysOnTop(true); |
| 615 add_menu_option_->Show(); | 385 add_menu_option_->Show(); |
| 616 | 386 |
| 617 // We activate the entry automatically if invoked with focus. | 387 // We activate the entry automatically if invoked with focus. |
| 618 if (add_user_enabled_ && user_card_view_->HasFocus()) { | 388 if (add_user_enabled_ && user_card_view_->HasFocus()) { |
| 619 add_user_view->GetFocusManager()->SetFocusedView(add_user_view); | 389 add_user_view->GetFocusManager()->SetFocusedView(add_user_view); |
| 620 user_card_view_->GetFocusManager()->SetFocusedView(add_user_view); | 390 user_card_view_->GetFocusManager()->SetFocusedView(add_user_view); |
| 621 } | 391 } |
| 622 } else { | |
| 623 AddUserView* add_user_view = | |
| 624 new AddUserView(static_cast<ButtonFromView*>(user_card_view_)); | |
| 625 ButtonFromView* button = new ButtonFromView( | |
| 626 add_user_view, add_user_enabled_ ? this : nullptr, | |
| 627 // Ignored in non-md. | |
| 628 TrayPopupInkDropStyle::INSET_BOUNDS, add_user_enabled_, gfx::Insets(1)); | |
| 629 button->SetAccessibleName( | |
| 630 l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_SIGN_IN_ANOTHER_ACCOUNT)); | |
| 631 button->ForceBorderVisible(true); | |
| 632 | 392 |
| 633 add_menu_option_->SetOpacity(1.f); | |
| 634 add_menu_option_->SetContentsView(button); | |
| 635 // Position it below our user card. | |
| 636 gfx::Rect bounds = user_card_view_->GetBoundsInScreen(); | |
| 637 bounds.set_y(bounds.y() + bounds.height()); | |
| 638 add_menu_option_->SetBounds(bounds); | |
| 639 | |
| 640 // Show the content. | |
| 641 add_menu_option_->SetAlwaysOnTop(true); | |
| 642 add_menu_option_->Show(); | |
| 643 | |
| 644 if (add_user_enabled_) { | |
| 645 // We activate the entry automatically if invoked with focus. | |
| 646 if (user_card_view_->HasFocus()) { | |
| 647 button->GetFocusManager()->SetFocusedView(button); | |
| 648 user_card_view_->GetFocusManager()->SetFocusedView(button); | |
| 649 } | |
| 650 } else { | |
| 651 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); | |
| 652 int message_id = 0; | |
| 653 switch (add_user_policy) { | |
| 654 case AddUserSessionPolicy::ERROR_NOT_ALLOWED_PRIMARY_USER: | |
| 655 message_id = IDS_ASH_STATUS_TRAY_MESSAGE_NOT_ALLOWED_PRIMARY_USER; | |
| 656 break; | |
| 657 case AddUserSessionPolicy::ERROR_MAXIMUM_USERS_REACHED: | |
| 658 message_id = IDS_ASH_STATUS_TRAY_MESSAGE_CANNOT_ADD_USER; | |
| 659 break; | |
| 660 case AddUserSessionPolicy::ERROR_NO_ELIGIBLE_USERS: | |
| 661 message_id = IDS_ASH_STATUS_TRAY_MESSAGE_OUT_OF_USERS; | |
| 662 break; | |
| 663 default: | |
| 664 NOTREACHED() << "Unknown adding user policy " | |
| 665 << static_cast<int>(add_user_policy); | |
| 666 } | |
| 667 | |
| 668 popup_message_.reset(new PopupMessage( | |
| 669 bundle.GetLocalizedString( | |
| 670 IDS_ASH_STATUS_TRAY_CAPTION_CANNOT_ADD_USER), | |
| 671 bundle.GetLocalizedString(message_id), PopupMessage::ICON_WARNING, | |
| 672 add_user_view->anchor(), views::BubbleBorder::TOP_LEFT, | |
| 673 gfx::Size(parent()->bounds().width() - kPopupMessageOffset, 0), | |
| 674 2 * kPopupMessageOffset)); | |
| 675 } | |
| 676 // Find the screen area which encloses both elements and sets then a mouse | |
| 677 // watcher which will close the "menu". | |
| 678 gfx::Rect area = user_card_view_->GetBoundsInScreen(); | |
| 679 area.set_height(2 * area.height()); | |
| 680 mouse_watcher_.reset( | |
| 681 new views::MouseWatcher(new UserViewMouseWatcherHost(area), this)); | |
| 682 mouse_watcher_->Start(); | |
| 683 } | |
| 684 // Install a listener to focus changes so that we can remove the card when | 393 // Install a listener to focus changes so that we can remove the card when |
| 685 // the focus gets changed. When called through the destruction of the bubble, | 394 // the focus gets changed. When called through the destruction of the bubble, |
| 686 // the FocusManager cannot be determined anymore and we remember it here. | 395 // the FocusManager cannot be determined anymore and we remember it here. |
| 687 focus_manager_ = user_card_view_->GetFocusManager(); | 396 focus_manager_ = user_card_view_->GetFocusManager(); |
| 688 focus_manager_->AddFocusChangeListener(this); | 397 focus_manager_->AddFocusChangeListener(this); |
| 689 } | 398 } |
| 690 | 399 |
| 691 void UserView::RemoveAddUserMenuOption() { | 400 void UserView::RemoveAddUserMenuOption() { |
| 692 if (!add_menu_option_.get()) | 401 if (!add_menu_option_.get()) |
| 693 return; | 402 return; |
| 694 focus_manager_->RemoveFocusChangeListener(this); | 403 focus_manager_->RemoveFocusChangeListener(this); |
| 695 focus_manager_ = nullptr; | 404 focus_manager_ = nullptr; |
| 696 if (user_card_view_->GetFocusManager()) | 405 if (user_card_view_->GetFocusManager()) |
| 697 user_card_view_->GetFocusManager()->ClearFocus(); | 406 user_card_view_->GetFocusManager()->ClearFocus(); |
| 698 popup_message_.reset(); | 407 popup_message_.reset(); |
| 699 mouse_watcher_.reset(); | |
| 700 add_menu_option_.reset(); | 408 add_menu_option_.reset(); |
| 701 } | 409 } |
| 702 | 410 |
| 703 } // namespace tray | 411 } // namespace tray |
| 704 } // namespace ash | 412 } // namespace ash |
| OLD | NEW |