Tim Song | f7f00b0 | 2020-09-03 20:57:00 | [diff] [blame] | 1 | // Copyright 2020 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/phonehub/phone_hub_tray.h" |
| 6 | |
| 7 | #include "ash/accessibility/accessibility_controller_impl.h" |
Meilin Wang | a35e0ef | 2020-10-13 23:04:55 | [diff] [blame] | 8 | #include "ash/focus_cycler.h" |
Tim Song | c935ade | 2020-10-27 18:26:51 | [diff] [blame] | 9 | #include "ash/public/cpp/system_tray_client.h" |
Tim Song | f7f00b0 | 2020-09-03 20:57:00 | [diff] [blame] | 10 | #include "ash/resources/vector_icons/vector_icons.h" |
| 11 | #include "ash/shelf/shelf.h" |
| 12 | #include "ash/shell.h" |
| 13 | #include "ash/strings/grit/ash_strings.h" |
| 14 | #include "ash/style/ash_color_provider.h" |
Tim Song | c935ade | 2020-10-27 18:26:51 | [diff] [blame] | 15 | #include "ash/system/model/system_tray_model.h" |
Meilin Wang | d626fde | 2020-10-23 17:53:36 | [diff] [blame] | 16 | #include "ash/system/phonehub/phone_hub_content_view.h" |
Tim Song | 947932a | 2020-10-31 00:38:45 | [diff] [blame] | 17 | #include "ash/system/phonehub/phone_hub_metrics.h" |
Andre Le | d52e467 | 2020-09-09 19:24:38 | [diff] [blame] | 18 | #include "ash/system/phonehub/quick_actions_view.h" |
Andre Le | ed1afef | 2020-09-11 01:06:55 | [diff] [blame] | 19 | #include "ash/system/phonehub/task_continuation_view.h" |
Meilin Wang | c14a36f | 2020-10-31 00:17:51 | [diff] [blame] | 20 | #include "ash/system/phonehub/ui_constants.h" |
Tim Song | f7f00b0 | 2020-09-03 20:57:00 | [diff] [blame] | 21 | #include "ash/system/tray/system_menu_button.h" |
| 22 | #include "ash/system/tray/tray_bubble_wrapper.h" |
| 23 | #include "ash/system/tray/tray_constants.h" |
| 24 | #include "ash/system/tray/tray_container.h" |
Tim Song | f7f00b0 | 2020-09-03 20:57:00 | [diff] [blame] | 25 | #include "ash/system/tray/tray_popup_utils.h" |
| 26 | #include "ash/system/tray/tray_utils.h" |
| 27 | #include "base/bind.h" |
Tim Song | b32e781 | 2020-09-11 22:42:19 | [diff] [blame] | 28 | #include "chromeos/components/phonehub/phone_hub_manager.h" |
Andre Le | 6619bb72 | 2020-09-17 17:49:11 | [diff] [blame] | 29 | #include "chromeos/components/phonehub/phone_model.h" |
Tim Song | f7f00b0 | 2020-09-03 20:57:00 | [diff] [blame] | 30 | #include "ui/base/l10n/l10n_util.h" |
| 31 | #include "ui/base/resource/resource_bundle.h" |
| 32 | #include "ui/gfx/geometry/insets.h" |
| 33 | #include "ui/gfx/paint_vector_icon.h" |
| 34 | #include "ui/views/controls/image_view.h" |
Tim Song | f7f00b0 | 2020-09-03 20:57:00 | [diff] [blame] | 35 | |
| 36 | namespace ash { |
| 37 | |
| 38 | namespace { |
| 39 | |
| 40 | // Padding for tray icon (dp; the button that shows the phone_hub menu). |
Jiaming Cheng | e9eeb03 | 2021-03-04 20:21:10 | [diff] [blame] | 41 | constexpr int kTrayIconMainAxisInset = 6; |
Tim Song | f7f00b0 | 2020-09-03 20:57:00 | [diff] [blame] | 42 | constexpr int kTrayIconCrossAxisInset = 0; |
| 43 | |
Meilin Wang | c14a36f | 2020-10-31 00:17:51 | [diff] [blame] | 44 | constexpr gfx::Insets kBubblePadding(0, 0, kBubbleBottomPaddingDip, 0); |
Andre Le | 4fb5e91 | 2020-09-09 16:30:03 | [diff] [blame] | 45 | |
Tim Song | f7f00b0 | 2020-09-03 20:57:00 | [diff] [blame] | 46 | } // namespace |
| 47 | |
Tim Song | 3049a95 | 2020-09-29 06:49:56 | [diff] [blame] | 48 | PhoneHubTray::PhoneHubTray(Shelf* shelf) |
| 49 | : TrayBackgroundView(shelf), ui_controller_(new PhoneHubUiController()) { |
Sigurdur Asgeirsson | e592c48 | 2021-01-28 16:17:29 | [diff] [blame] | 50 | observed_phone_hub_ui_controller_.Observe(ui_controller_.get()); |
Tim Song | 3049a95 | 2020-09-29 06:49:56 | [diff] [blame] | 51 | |
Tim Song | f7f00b0 | 2020-09-03 20:57:00 | [diff] [blame] | 52 | auto icon = std::make_unique<views::ImageView>(); |
Allen Bauer | d9daac11 | 2020-09-15 21:54:04 | [diff] [blame] | 53 | icon->SetTooltipText( |
Tim Song | f7f00b0 | 2020-09-03 20:57:00 | [diff] [blame] | 54 | l10n_util::GetStringUTF16(IDS_ASH_PHONE_HUB_TRAY_ACCESSIBLE_NAME)); |
| 55 | icon->SetImage(CreateVectorIcon( |
Andre Le | b2a5ccb | 2020-10-26 17:50:16 | [diff] [blame] | 56 | kPhoneHubPhoneIcon, |
Tim Song | f7f00b0 | 2020-09-03 20:57:00 | [diff] [blame] | 57 | AshColorProvider::Get()->GetContentLayerColor( |
minch | 5847c6f | 2020-09-08 01:13:17 | [diff] [blame] | 58 | AshColorProvider::ContentLayerType::kIconColorPrimary))); |
Tim Song | f7f00b0 | 2020-09-03 20:57:00 | [diff] [blame] | 59 | |
| 60 | tray_container()->SetMargin(kTrayIconMainAxisInset, kTrayIconCrossAxisInset); |
| 61 | icon_ = tray_container()->AddChildView(std::move(icon)); |
| 62 | } |
| 63 | |
| 64 | PhoneHubTray::~PhoneHubTray() { |
| 65 | if (bubble_) |
| 66 | bubble_->bubble_view()->ResetDelegate(); |
Tim Song | b32e781 | 2020-09-11 22:42:19 | [diff] [blame] | 67 | } |
| 68 | |
| 69 | void PhoneHubTray::SetPhoneHubManager( |
| 70 | chromeos::phonehub::PhoneHubManager* phone_hub_manager) { |
Tim Song | 3049a95 | 2020-09-29 06:49:56 | [diff] [blame] | 71 | ui_controller_->SetPhoneHubManager(phone_hub_manager); |
Tim Song | f7f00b0 | 2020-09-03 20:57:00 | [diff] [blame] | 72 | } |
| 73 | |
| 74 | void PhoneHubTray::ClickedOutsideBubble() { |
| 75 | CloseBubble(); |
| 76 | } |
| 77 | |
Jan Wilken Dörrie | 85285b0 | 2021-03-11 23:38:47 | [diff] [blame^] | 78 | std::u16string PhoneHubTray::GetAccessibleNameForTray() { |
Tim Song | f7f00b0 | 2020-09-03 20:57:00 | [diff] [blame] | 79 | return l10n_util::GetStringUTF16(IDS_ASH_PHONE_HUB_TRAY_ACCESSIBLE_NAME); |
| 80 | } |
| 81 | |
| 82 | void PhoneHubTray::HandleLocaleChange() { |
Allen Bauer | d9daac11 | 2020-09-15 21:54:04 | [diff] [blame] | 83 | icon_->SetTooltipText( |
Tim Song | f7f00b0 | 2020-09-03 20:57:00 | [diff] [blame] | 84 | l10n_util::GetStringUTF16(IDS_ASH_PHONE_HUB_TRAY_ACCESSIBLE_NAME)); |
| 85 | } |
| 86 | |
| 87 | void PhoneHubTray::HideBubbleWithView(const TrayBubbleView* bubble_view) { |
| 88 | if (bubble_->bubble_view() == bubble_view) |
| 89 | CloseBubble(); |
| 90 | } |
| 91 | |
Jan Wilken Dörrie | 85285b0 | 2021-03-11 23:38:47 | [diff] [blame^] | 92 | std::u16string PhoneHubTray::GetAccessibleNameForBubble() { |
Tim Song | f7f00b0 | 2020-09-03 20:57:00 | [diff] [blame] | 93 | return GetAccessibleNameForTray(); |
| 94 | } |
| 95 | |
| 96 | bool PhoneHubTray::ShouldEnableExtraKeyboardAccessibility() { |
Anatoliy Potapchuk | e368758 | 2020-09-08 22:50:32 | [diff] [blame] | 97 | return Shell::Get()->accessibility_controller()->spoken_feedback().enabled(); |
Tim Song | f7f00b0 | 2020-09-03 20:57:00 | [diff] [blame] | 98 | } |
| 99 | |
| 100 | void PhoneHubTray::HideBubble(const TrayBubbleView* bubble_view) { |
| 101 | HideBubbleWithView(bubble_view); |
| 102 | } |
| 103 | |
Tim Song | 3049a95 | 2020-09-29 06:49:56 | [diff] [blame] | 104 | void PhoneHubTray::OnPhoneHubUiStateChanged() { |
| 105 | UpdateVisibility(); |
| 106 | |
| 107 | if (!bubble_) |
| 108 | return; |
| 109 | TrayBubbleView* bubble_view = bubble_->bubble_view(); |
| 110 | |
| 111 | DCHECK(ui_controller_.get()); |
Meilin Wang | d626fde | 2020-10-23 17:53:36 | [diff] [blame] | 112 | std::unique_ptr<PhoneHubContentView> content_view = |
Meilin Wang | 6531973 | 2020-11-06 20:03:18 | [diff] [blame] | 113 | ui_controller_->CreateContentView(this); |
Tim Song | 3049a95 | 2020-09-29 06:49:56 | [diff] [blame] | 114 | if (!content_view.get()) { |
| 115 | CloseBubble(); |
| 116 | return; |
| 117 | } |
| 118 | |
Juliet Levesque | 0300e11e9b | 2021-03-09 15:50:54 | [diff] [blame] | 119 | if (content_view_) { |
Juliet Levesque | 92bc5b2 | 2021-03-11 20:54:26 | [diff] [blame] | 120 | // If we are already showing the same content_view, no need to remove and |
| 121 | // update the tray. |
| 122 | // TODO(crbug.com/1185316) : Find way to update views without work around |
| 123 | // when same view is removed and added. |
| 124 | if (content_view->GetID() == content_view_->GetID()) |
| 125 | return; |
| 126 | |
Tim Song | 3049a95 | 2020-09-29 06:49:56 | [diff] [blame] | 127 | bubble_view->RemoveChildView(content_view_); |
Juliet Levesque | 0300e11e9b | 2021-03-09 15:50:54 | [diff] [blame] | 128 | delete content_view_; |
| 129 | } |
Juliet Levesque | 92bc5b2 | 2021-03-11 20:54:26 | [diff] [blame] | 130 | content_view_ = bubble_view->AddChildView(std::move(content_view)); |
Meilin Wang | 4f25086 | 2020-10-02 23:40:19 | [diff] [blame] | 131 | |
| 132 | // Updates bubble to handle possible size change with a different child view. |
| 133 | bubble_view->UpdateBubble(); |
Tim Song | 3049a95 | 2020-09-29 06:49:56 | [diff] [blame] | 134 | } |
| 135 | |
Tim Song | f7f00b0 | 2020-09-03 20:57:00 | [diff] [blame] | 136 | void PhoneHubTray::AnchorUpdated() { |
| 137 | if (bubble_) |
| 138 | bubble_->bubble_view()->UpdateBubble(); |
| 139 | } |
| 140 | |
| 141 | void PhoneHubTray::Initialize() { |
| 142 | TrayBackgroundView::Initialize(); |
| 143 | UpdateVisibility(); |
| 144 | } |
| 145 | |
Ahmed Mehfooz | 15cebdd | 2021-03-03 01:07:07 | [diff] [blame] | 146 | void PhoneHubTray::ShowBubble() { |
Tim Song | f7f00b0 | 2020-09-03 20:57:00 | [diff] [blame] | 147 | if (bubble_) |
| 148 | return; |
| 149 | |
Kyle Horimoto | ae02ab3 | 2020-12-11 00:35:47 | [diff] [blame] | 150 | ui_controller_->HandleBubbleOpened(); |
Andre Le | b8d8ec5 | 2020-11-02 23:11:46 | [diff] [blame] | 151 | |
Tim Song | f7f00b0 | 2020-09-03 20:57:00 | [diff] [blame] | 152 | TrayBubbleView::InitParams init_params; |
| 153 | init_params.delegate = this; |
| 154 | init_params.parent_window = GetBubbleWindowContainer(); |
Regan Hsu | a5e2427 | 2020-12-22 20:38:28 | [diff] [blame] | 155 | init_params.anchor_mode = TrayBubbleView::AnchorMode::kRect; |
| 156 | init_params.anchor_rect = shelf()->GetSystemTrayAnchorRect(); |
| 157 | init_params.insets = GetTrayBubbleInsets(); |
Tim Song | f7f00b0 | 2020-09-03 20:57:00 | [diff] [blame] | 158 | init_params.shelf_alignment = shelf()->alignment(); |
Meilin Wang | c14a36f | 2020-10-31 00:17:51 | [diff] [blame] | 159 | init_params.preferred_width = kTrayMenuWidth; |
Tim Song | f7f00b0 | 2020-09-03 20:57:00 | [diff] [blame] | 160 | init_params.close_on_deactivate = true; |
| 161 | init_params.has_shadow = false; |
| 162 | init_params.translucent = true; |
Ahmed Mehfooz | 15cebdd | 2021-03-03 01:07:07 | [diff] [blame] | 163 | init_params.reroute_event_handler = true; |
Tim Song | f7f00b0 | 2020-09-03 20:57:00 | [diff] [blame] | 164 | init_params.corner_radius = kTrayItemCornerRadius; |
Tim Song | f7f00b0 | 2020-09-03 20:57:00 | [diff] [blame] | 165 | |
| 166 | TrayBubbleView* bubble_view = new TrayBubbleView(init_params); |
Andre Le | 4fb5e91 | 2020-09-09 16:30:03 | [diff] [blame] | 167 | bubble_view->SetBorder(views::CreateEmptyBorder(kBubblePadding)); |
Tim Song | f7f00b0 | 2020-09-03 20:57:00 | [diff] [blame] | 168 | |
Meilin Wang | 6531973 | 2020-11-06 20:03:18 | [diff] [blame] | 169 | // Creates header view on top for displaying phone status and settings icon. |
| 170 | auto phone_status = ui_controller_->CreateStatusHeaderView(this); |
| 171 | phone_status_view_ = phone_status.get(); |
| 172 | DCHECK(phone_status_view_); |
| 173 | bubble_view->AddChildView(std::move(phone_status)); |
Meilin Wang | 50d8a729 | 2020-09-25 23:52:33 | [diff] [blame] | 174 | |
| 175 | // Other contents, i.e. the connected view and the interstitial views, |
| 176 | // will be positioned underneath the phone status view and updated based |
| 177 | // on the current mode. |
Meilin Wang | 6531973 | 2020-11-06 20:03:18 | [diff] [blame] | 178 | auto content_view = ui_controller_->CreateContentView(this); |
Tim Song | 3049a95 | 2020-09-29 06:49:56 | [diff] [blame] | 179 | content_view_ = content_view.get(); |
Tim Song | 947932a | 2020-10-31 00:38:45 | [diff] [blame] | 180 | DCHECK(content_view_); |
| 181 | bubble_view->AddChildView(std::move(content_view)); |
Tim Song | f7f00b0 | 2020-09-03 20:57:00 | [diff] [blame] | 182 | |
| 183 | bubble_ = std::make_unique<TrayBubbleWrapper>(this, bubble_view, |
| 184 | false /* is_persistent */); |
Tim Song | 3049a95 | 2020-09-29 06:49:56 | [diff] [blame] | 185 | |
Tim Song | f7f00b0 | 2020-09-03 20:57:00 | [diff] [blame] | 186 | SetIsActive(true); |
Meilin Wang | a35e0ef | 2020-10-13 23:04:55 | [diff] [blame] | 187 | |
Tim Song | 947932a | 2020-10-31 00:38:45 | [diff] [blame] | 188 | phone_hub_metrics::LogScreenOnBubbleOpen( |
| 189 | content_view_->GetScreenForMetrics()); |
Tim Song | f7f00b0 | 2020-09-03 20:57:00 | [diff] [blame] | 190 | } |
| 191 | |
| 192 | TrayBubbleView* PhoneHubTray::GetBubbleView() { |
| 193 | return bubble_ ? bubble_->bubble_view() : nullptr; |
| 194 | } |
| 195 | |
Ahmed Mehfooz | 15cebdd | 2021-03-03 01:07:07 | [diff] [blame] | 196 | views::Widget* PhoneHubTray::GetBubbleWidget() const { |
| 197 | return bubble_ ? bubble_->GetBubbleWidget() : nullptr; |
| 198 | } |
| 199 | |
Tim Song | f7f00b0 | 2020-09-03 20:57:00 | [diff] [blame] | 200 | const char* PhoneHubTray::GetClassName() const { |
| 201 | return "PhoneHubTray"; |
| 202 | } |
| 203 | |
Tim Song | c935ade | 2020-10-27 18:26:51 | [diff] [blame] | 204 | bool PhoneHubTray::CanOpenConnectedDeviceSettings() { |
| 205 | return TrayPopupUtils::CanOpenWebUISettings(); |
| 206 | } |
| 207 | |
| 208 | void PhoneHubTray::OpenConnectedDevicesSettings() { |
Tim Song | 947932a | 2020-10-31 00:38:45 | [diff] [blame] | 209 | DCHECK(content_view_); |
| 210 | phone_hub_metrics::LogScreenOnSettingsButtonClicked( |
| 211 | content_view_->GetScreenForMetrics()); |
| 212 | |
Tim Song | c935ade | 2020-10-27 18:26:51 | [diff] [blame] | 213 | DCHECK(CanOpenConnectedDeviceSettings()); |
| 214 | Shell::Get()->system_tray_model()->client()->ShowConnectedDevicesSettings(); |
| 215 | } |
| 216 | |
Meilin Wang | 6531973 | 2020-11-06 20:03:18 | [diff] [blame] | 217 | void PhoneHubTray::HideStatusHeaderView() { |
| 218 | if (!phone_status_view_) |
| 219 | return; |
| 220 | |
| 221 | phone_status_view_->SetVisible(false); |
| 222 | bubble_->bubble_view()->UpdateBubble(); |
| 223 | } |
| 224 | |
Tim Song | f7f00b0 | 2020-09-03 20:57:00 | [diff] [blame] | 225 | void PhoneHubTray::CloseBubble() { |
Tim Song | 947932a | 2020-10-31 00:38:45 | [diff] [blame] | 226 | if (!bubble_) |
| 227 | return; |
| 228 | |
| 229 | DCHECK(content_view_); |
| 230 | phone_hub_metrics::LogScreenOnBubbleClose( |
| 231 | content_view_->GetScreenForMetrics()); |
| 232 | |
| 233 | content_view_->OnBubbleClose(); |
Tim Song | 3049a95 | 2020-09-29 06:49:56 | [diff] [blame] | 234 | content_view_ = nullptr; |
Tim Song | f7f00b0 | 2020-09-03 20:57:00 | [diff] [blame] | 235 | bubble_.reset(); |
| 236 | SetIsActive(false); |
| 237 | shelf()->UpdateAutoHideState(); |
| 238 | } |
| 239 | |
| 240 | void PhoneHubTray::UpdateVisibility() { |
Tim Song | 3049a95 | 2020-09-29 06:49:56 | [diff] [blame] | 241 | DCHECK(ui_controller_.get()); |
| 242 | auto ui_state = ui_controller_->ui_state(); |
| 243 | SetVisiblePreferred(ui_state != PhoneHubUiController::UiState::kHidden); |
Tim Song | f7f00b0 | 2020-09-03 20:57:00 | [diff] [blame] | 244 | } |
| 245 | |
| 246 | } // namespace ash |