[QsRevamp Clean Up] remove the use of UnifiedSystemTrayView
Also removed the sub views of it. Bug: b/305075031 Change-Id: I9b47f8205fec0c32e94ff85dfac14ed672271674 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5009234 Reviewed-by: Alex Newcomer <newcomer@chromium.org> Reviewed-by: James Cook <jamescook@chromium.org> Commit-Queue: Jiaming Cheng <jiamingc@chromium.org> Cr-Commit-Position: refs/heads/main@{#1221177}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
883ab6ffe5
commit
2480e206df
ash
BUILD.gnash_prefs.ccash_strings.grd
ash_strings_grd
IDS_ASH_CALENDAR_ENTRY_ACCESSIBLE_DESCRIPTION.png.sha1IDS_ASH_MESSAGE_CENTER_UNLOCK_TO_CHANGE_SETTING.png.sha1IDS_ASH_QUICK_SETTINGS_BUBBLE_ACCESSIBLE_DESCRIPTION.png.sha1
system
accessibility
accessibility_detailed_view_pixeltest.ccautoclick_menu_bubble_controller.ccautoclick_scroll_bubble_controller.cc
select_to_speak
switch_access
bluetooth
channel_indicator
message_center
network
network_detailed_network_view_pixeltest.ccnetwork_feature_pod_controller.ccnetwork_feature_pod_controller_unittest.cc
privacy_screen
time
tray
unified
feature_pod_controller_base.hfeature_pods_container_view.ccfeature_pods_container_view.hfeature_pods_container_view_unittest.ccnotification_hidden_view.ccnotification_hidden_view.hpage_indicator_view.ccpage_indicator_view.hpage_indicator_view_unittest.ccquick_settings_view.ccquick_settings_view.hsystem_tray_test_api.cctop_shortcuts_view.cctop_shortcuts_view.hunified_slider_bubble_controller.ccunified_system_info_view.ccunified_system_info_view.hunified_system_info_view_unittest.ccunified_system_tray.ccunified_system_tray.hunified_system_tray_bubble.ccunified_system_tray_bubble.hunified_system_tray_controller.ccunified_system_tray_controller.hunified_system_tray_controller_unittest.ccunified_system_tray_unittest.ccunified_system_tray_view.ccunified_system_tray_view.huser_chooser_view.cc
chrome/browser/ui/ash
15
ash/BUILD.gn
15
ash/BUILD.gn
@ -2171,8 +2171,6 @@ component("ash") {
|
||||
"system/unified/feature_pod_button.h",
|
||||
"system/unified/feature_pod_controller_base.cc",
|
||||
"system/unified/feature_pod_controller_base.h",
|
||||
"system/unified/feature_pods_container_view.cc",
|
||||
"system/unified/feature_pods_container_view.h",
|
||||
"system/unified/feature_tile.cc",
|
||||
"system/unified/feature_tile.h",
|
||||
"system/unified/feature_tiles_container_view.cc",
|
||||
@ -2189,12 +2187,8 @@ component("ash") {
|
||||
"system/unified/managed_device_tray_item_view.h",
|
||||
"system/unified/notification_counter_view.cc",
|
||||
"system/unified/notification_counter_view.h",
|
||||
"system/unified/notification_hidden_view.cc",
|
||||
"system/unified/notification_hidden_view.h",
|
||||
"system/unified/notification_icons_controller.cc",
|
||||
"system/unified/notification_icons_controller.h",
|
||||
"system/unified/page_indicator_view.cc",
|
||||
"system/unified/page_indicator_view.h",
|
||||
"system/unified/power_button.cc",
|
||||
"system/unified/power_button.h",
|
||||
"system/unified/quick_settings_footer.cc",
|
||||
@ -2215,16 +2209,12 @@ component("ash") {
|
||||
"system/unified/tasks_bubble_view.h",
|
||||
"system/unified/tasks_combobox_model.cc",
|
||||
"system/unified/tasks_combobox_model.h",
|
||||
"system/unified/top_shortcuts_view.cc",
|
||||
"system/unified/top_shortcuts_view.h",
|
||||
"system/unified/unified_notifier_settings_controller.cc",
|
||||
"system/unified/unified_notifier_settings_controller.h",
|
||||
"system/unified/unified_slider_bubble_controller.cc",
|
||||
"system/unified/unified_slider_bubble_controller.h",
|
||||
"system/unified/unified_slider_view.cc",
|
||||
"system/unified/unified_slider_view.h",
|
||||
"system/unified/unified_system_info_view.cc",
|
||||
"system/unified/unified_system_info_view.h",
|
||||
"system/unified/unified_system_tray.cc",
|
||||
"system/unified/unified_system_tray.h",
|
||||
"system/unified/unified_system_tray_bubble.cc",
|
||||
@ -2233,8 +2223,6 @@ component("ash") {
|
||||
"system/unified/unified_system_tray_controller.h",
|
||||
"system/unified/unified_system_tray_model.cc",
|
||||
"system/unified/unified_system_tray_model.h",
|
||||
"system/unified/unified_system_tray_view.cc",
|
||||
"system/unified/unified_system_tray_view.h",
|
||||
"system/unified/user_chooser_detailed_view_controller.cc",
|
||||
"system/unified/user_chooser_detailed_view_controller.h",
|
||||
"system/unified/user_chooser_view.cc",
|
||||
@ -3659,12 +3647,10 @@ test("ash_unittests") {
|
||||
"system/tray/tri_view_unittest.cc",
|
||||
"system/unified/classroom_bubble_view_unittest.cc",
|
||||
"system/unified/date_tray_unittest.cc",
|
||||
"system/unified/feature_pods_container_view_unittest.cc",
|
||||
"system/unified/feature_tile_unittest.cc",
|
||||
"system/unified/feature_tiles_container_view_unittest.cc",
|
||||
"system/unified/notification_counter_view_unittest.cc",
|
||||
"system/unified/notification_icons_controller_unittest.cc",
|
||||
"system/unified/page_indicator_view_unittest.cc",
|
||||
"system/unified/power_button_unittest.cc",
|
||||
"system/unified/quick_settings_footer_unittest.cc",
|
||||
"system/unified/quick_settings_header_unittest.cc",
|
||||
@ -3673,7 +3659,6 @@ test("ash_unittests") {
|
||||
"system/unified/screen_capture_tray_item_view_unittest.cc",
|
||||
"system/unified/tasks_bubble_view_unittest.cc",
|
||||
"system/unified/tasks_combobox_model_unittest.cc",
|
||||
"system/unified/unified_system_info_view_unittest.cc",
|
||||
"system/unified/unified_system_tray_controller_unittest.cc",
|
||||
"system/unified/unified_system_tray_unittest.cc",
|
||||
"system/unified/user_chooser_detailed_view_controller_unittest.cc",
|
||||
|
@ -66,7 +66,6 @@
|
||||
#include "ash/system/session/logout_button_tray.h"
|
||||
#include "ash/system/session/logout_confirmation_controller.h"
|
||||
#include "ash/system/unified/quick_settings_footer.h"
|
||||
#include "ash/system/unified/top_shortcuts_view.h"
|
||||
#include "ash/system/unified/unified_system_tray_controller.h"
|
||||
#include "ash/system/usb_peripheral/usb_peripheral_notification_controller.h"
|
||||
#include "ash/touch/touch_devices_controller.h"
|
||||
@ -200,11 +199,7 @@ void RegisterLocalStatePrefs(PrefRegistrySimple* registry, bool for_test) {
|
||||
LoginExpandedPublicAccountView::RegisterLocalStatePrefs(registry);
|
||||
LockStateController::RegisterPrefs(registry);
|
||||
quick_pair::Mediator::RegisterLocalStatePrefs(registry);
|
||||
if (ash::features::IsQsRevampEnabled()) {
|
||||
QuickSettingsFooter::RegisterLocalStatePrefs(registry);
|
||||
} else {
|
||||
TopShortcutsView::RegisterLocalStatePrefs(registry);
|
||||
}
|
||||
QuickSettingsFooter::RegisterLocalStatePrefs(registry);
|
||||
KeyboardBacklightColorController::RegisterPrefs(registry);
|
||||
BatterySaverController::RegisterLocalStatePrefs(registry);
|
||||
PowerSoundsController::RegisterLocalStatePrefs(registry);
|
||||
|
@ -310,9 +310,6 @@ Style notes:
|
||||
<ph name="network">$2<ex>Connected to Google-A, Median signal</ex></ph>
|
||||
</message>
|
||||
<message name="IDS_ASH_QUICK_SETTINGS_BUBBLE_ACCESSIBLE_DESCRIPTION" desc="The accessible description of the quick settings bubble and the information in it.">
|
||||
Quick Settings, Press search + left to access the notification center.
|
||||
</message>
|
||||
<message name="IDS_ASH_REVAMPED_QUICK_SETTINGS_BUBBLE_ACCESSIBLE_DESCRIPTION" desc="The accessible description of the revamped quick settings bubble and the information in it.">
|
||||
Quick Settings
|
||||
</message>
|
||||
<message name="IDS_ASH_QUICK_SETTINGS_BUBBLE_A11Y_SETTINGS_ACCESSIBLE_DESCRIPTION" desc="The accessible description for accessibility settings accessed through the accessibility feature pod.">
|
||||
@ -1390,9 +1387,6 @@ Style notes:
|
||||
<message name="IDS_ASH_STATUS_TRAY_HELP" desc="The accessible text for the help button.">
|
||||
Help
|
||||
</message>
|
||||
<message name="IDS_ASH_STATUS_TRAY_DATE" desc="The date displayed on ash system bubble, Depending on launguage, please choose the best separator(eg ',') between abbreviated weekday and date">
|
||||
<ph name="short_weekday">$1<ex>Fri</ex></ph>, <ph name="date">$2<ex>Aug 31, 2012</ex></ph>
|
||||
</message>
|
||||
<message name="IDS_ASH_STATUS_TRAY_DATE_TIME" desc="The time displayed on ash system tray, Depending on launguage, please choose the best separator(eg ',') between abbreviated date and time">
|
||||
<ph name="date">$1<ex>Aug 31</ex></ph>, <ph name="time">$2<ex>03:00</ex></ph>
|
||||
</message>
|
||||
@ -5070,15 +5064,6 @@ Some features are limited to increase battery life.
|
||||
<message name="IDS_ASH_MESSAGE_CENTER_FOOTER_LOCKSCREEN" desc="The label in the footer of the message center on lock screen">
|
||||
Unlock device to view your notifications
|
||||
</message>
|
||||
<message name="IDS_ASH_MESSAGE_CENTER_LOCKSCREEN_UNIFIED" desc="The label in the message center area on lock screen.">
|
||||
Notifications are hidden.
|
||||
</message>
|
||||
<message name="IDS_ASH_MESSAGE_CENTER_LOCKSCREEN_CHANGE" desc="The label in the button in the message center area on lock screen. This button is to open the setting of the lock scren notification.">
|
||||
Change
|
||||
</message>
|
||||
<message name="IDS_ASH_MESSAGE_CENTER_LOCKSCREEN_CHANGE_TOOLTIP" desc="The tooltip text for Change button to open the setting of lock screen notification.">
|
||||
Change the lock-screen notification settings
|
||||
</message>
|
||||
<message name="IDS_ASH_MESSAGE_CENTER_NO_MESSAGES" desc="The message displayed in the message center when there are no notifications.">
|
||||
All done
|
||||
</message>
|
||||
@ -5179,10 +5164,6 @@ Some features are limited to increase battery life.
|
||||
Calendar, <ph name="current_month_year">$1<ex>Wednesday, August 17, 2022</ex></ph>
|
||||
</message>
|
||||
|
||||
<message name="IDS_ASH_CALENDAR_ENTRY_ACCESSIBLE_DESCRIPTION" desc="The accessible description of the calendar entry button.">
|
||||
<ph name="current_time">$1<ex>Tuesday, August 31, 2021 at 11:25:12 AM</ex></ph>, Press enter key to open Calendar view
|
||||
</message>
|
||||
|
||||
<message name="IDS_ASH_CALENDAR_TITLE" desc="The label used as the title of the unified system tray calendar view.">
|
||||
Calendar
|
||||
</message>
|
||||
@ -5686,9 +5667,6 @@ Here are some things you can try to get started.
|
||||
<message name="IDS_ASH_MESSAGE_CENTER_UNLOCK_TO_PERFORM_ACTION_WITH_USER_ID" desc="The short message to encourage user to unlock the device so that ChromeOS can perform the notification action selected by user after unlocking.">
|
||||
Unlock device as <ph name="login_id">$1<ex>example@gmail.com</ex></ph> to perform the notification action
|
||||
</message>
|
||||
<message name="IDS_ASH_MESSAGE_CENTER_UNLOCK_TO_CHANGE_SETTING" desc="The short message to encourage user to unlock the device to change the lock screen notification setting, so that ChromeOS can show the setting window after unlocking.">
|
||||
To see notifications on your lock screen, unlock to change the setting
|
||||
</message>
|
||||
|
||||
<!-- Media Notification -->
|
||||
<message name="IDS_ASH_MEDIA_NOTIFICATION_ACTION_PREVIOUS_TRACK" desc="The button to trigger media playback to go to the previous track.">
|
||||
|
@ -1 +0,0 @@
|
||||
f1e17f22d50bbacb0252fb395913043eba44301b
|
@ -1 +0,0 @@
|
||||
e09cf86b689a4c2f1b897737df6f9a229b66944f
|
@ -6,7 +6,6 @@
|
||||
#include "ash/system/unified/unified_system_tray.h"
|
||||
#include "ash/system/unified/unified_system_tray_bubble.h"
|
||||
#include "ash/system/unified/unified_system_tray_controller.h"
|
||||
#include "ash/system/unified/unified_system_tray_view.h"
|
||||
#include "ash/test/ash_test_base.h"
|
||||
#include "ash/test/pixel/ash_pixel_differ.h"
|
||||
#include "ash/test/pixel/ash_pixel_test_init_params.h"
|
||||
|
@ -14,7 +14,6 @@
|
||||
#include "ash/system/tray/tray_background_view.h"
|
||||
#include "ash/system/tray/tray_bubble_view.h"
|
||||
#include "ash/system/tray/tray_constants.h"
|
||||
#include "ash/system/unified/unified_system_tray_view.h"
|
||||
#include "ash/wm/collision_detection/collision_detection_utils.h"
|
||||
#include "ash/wm/work_area_insets.h"
|
||||
#include "ash/wm/workspace/workspace_layout_manager.h"
|
||||
|
@ -11,7 +11,6 @@
|
||||
#include "ash/strings/grit/ash_strings.h"
|
||||
#include "ash/system/tray/tray_background_view.h"
|
||||
#include "ash/system/tray/tray_constants.h"
|
||||
#include "ash/system/unified/unified_system_tray_view.h"
|
||||
#include "ash/wm/collision_detection/collision_detection_utils.h"
|
||||
#include "ash/wm/work_area_insets.h"
|
||||
#include "ash/wm/workspace/workspace_layout_manager.h"
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include "ash/system/accessibility/select_to_speak/select_to_speak_constants.h"
|
||||
#include "ash/system/tray/tray_background_view.h"
|
||||
#include "ash/system/tray/tray_constants.h"
|
||||
#include "ash/system/unified/unified_system_tray_view.h"
|
||||
#include "ui/base/l10n/l10n_util.h"
|
||||
#include "ui/compositor/layer.h"
|
||||
#include "ui/views/border.h"
|
||||
|
@ -15,7 +15,6 @@
|
||||
#include "ash/system/accessibility/select_to_speak/select_to_speak_speed_view.h"
|
||||
#include "ash/system/tray/tray_background_view.h"
|
||||
#include "ash/system/tray/tray_constants.h"
|
||||
#include "ash/system/unified/unified_system_tray_view.h"
|
||||
#include "ui/base/l10n/l10n_util.h"
|
||||
#include "ui/compositor/layer.h"
|
||||
#include "ui/wm/public/activation_client.h"
|
||||
|
@ -11,7 +11,6 @@
|
||||
#include "ash/system/accessibility/switch_access/switch_access_menu_view.h"
|
||||
#include "ash/system/tray/tray_background_view.h"
|
||||
#include "ash/system/tray/tray_constants.h"
|
||||
#include "ash/system/unified/unified_system_tray_view.h"
|
||||
#include "ash/wm/collision_detection/collision_detection_utils.h"
|
||||
#include "ui/accessibility/ax_enums.mojom.h"
|
||||
#include "ui/compositor/layer.h"
|
||||
|
@ -18,7 +18,6 @@
|
||||
#include "ash/system/unified/unified_system_tray.h"
|
||||
#include "ash/system/unified/unified_system_tray_bubble.h"
|
||||
#include "ash/system/unified/unified_system_tray_controller.h"
|
||||
#include "ash/system/unified/unified_system_tray_view.h"
|
||||
#include "ash/test/ash_test_base.h"
|
||||
#include "ash/test/ash_test_helper.h"
|
||||
#include "base/i18n/number_formatting.h"
|
||||
@ -214,10 +213,6 @@ class BluetoothFeaturePodControllerTest : public AshTestBase {
|
||||
->unified_system_tray_controller();
|
||||
}
|
||||
|
||||
UnifiedSystemTrayView* tray_view() {
|
||||
return GetPrimaryUnifiedSystemTray()->bubble()->unified_view();
|
||||
}
|
||||
|
||||
size_t GetTryToShowSurveyCount() {
|
||||
return fake_trigger_impl_->try_to_show_survey_count();
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
namespace ash {
|
||||
|
||||
// ChannelIndicatorQuickSettingsView contains all of the views included in the
|
||||
// channel indicator UI that resides in UnifiedSystemInfoView.
|
||||
// channel indicator UI that resides in `QuickSettingsHeader`.
|
||||
class ASH_EXPORT ChannelIndicatorQuickSettingsView : public views::View {
|
||||
public:
|
||||
METADATA_HEADER(ChannelIndicatorQuickSettingsView);
|
||||
|
@ -44,15 +44,6 @@ class AshMessageCenterLockScreenController
|
||||
bool IsScreenLocked() const override;
|
||||
|
||||
private:
|
||||
FRIEND_TEST_ALL_PREFIXES(UnifiedSystemTrayControllerTest,
|
||||
NotificationHiddenView_ModeShow);
|
||||
FRIEND_TEST_ALL_PREFIXES(UnifiedSystemTrayControllerTest,
|
||||
NotificationHiddenView_ModeHide);
|
||||
FRIEND_TEST_ALL_PREFIXES(UnifiedSystemTrayControllerTest,
|
||||
NotificationHiddenView_ModeHideSensitive);
|
||||
FRIEND_TEST_ALL_PREFIXES(UnifiedSystemTrayControllerTest,
|
||||
NotificationHiddenView_ModeProhibited);
|
||||
|
||||
// Modes of the lock screen notification.
|
||||
enum class Mode { PROHIBITED, HIDE, SHOW, HIDE_SENSITIVE };
|
||||
|
||||
|
@ -107,7 +107,7 @@ TEST_F(NetworkDetailedNetworkViewPixelTest, Basics) {
|
||||
// Show the detailed view.
|
||||
system_tray->bubble()
|
||||
->unified_system_tray_controller()
|
||||
->ShowNetworkDetailedView(/*force=*/true);
|
||||
->ShowNetworkDetailedView();
|
||||
TrayDetailedView* detailed_view =
|
||||
system_tray->bubble()
|
||||
->quick_settings_view()
|
||||
|
@ -208,7 +208,7 @@ void NetworkFeaturePodController::OnIconPressed() {
|
||||
// well as when the network technology cannot be toggled, e.g. ethernet.
|
||||
if (!was_enabled || !can_toggle) {
|
||||
TrackDiveInUMA();
|
||||
tray_controller_->ShowNetworkDetailedView(/*force=*/!can_toggle);
|
||||
tray_controller_->ShowNetworkDetailedView();
|
||||
}
|
||||
}
|
||||
|
||||
@ -216,7 +216,7 @@ void NetworkFeaturePodController::OnLabelPressed() {
|
||||
TrackDiveInUMA();
|
||||
|
||||
SetNetworkTypeEnabled(true);
|
||||
tray_controller_->ShowNetworkDetailedView(/*force=*/true);
|
||||
tray_controller_->ShowNetworkDetailedView();
|
||||
}
|
||||
|
||||
void NetworkFeaturePodController::PropagateThemeChanged() {
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include "ash/system/unified/unified_system_tray_bubble.h"
|
||||
#include "ash/system/unified/unified_system_tray_controller.h"
|
||||
#include "ash/system/unified/unified_system_tray_model.h"
|
||||
#include "ash/system/unified/unified_system_tray_view.h"
|
||||
#include "ash/test/ash_test_base.h"
|
||||
#include "base/strings/stringprintf.h"
|
||||
#include "base/test/metrics/histogram_tester.h"
|
||||
@ -320,10 +319,6 @@ class NetworkFeaturePodControllerTest : public AshTestBase {
|
||||
->unified_system_tray_controller();
|
||||
}
|
||||
|
||||
UnifiedSystemTrayView* unified_view() {
|
||||
return GetPrimaryUnifiedSystemTray()->bubble()->unified_view();
|
||||
}
|
||||
|
||||
QuickSettingsView* quick_settings_view() {
|
||||
return GetPrimaryUnifiedSystemTray()->bubble()->quick_settings_view();
|
||||
}
|
||||
|
@ -15,7 +15,6 @@
|
||||
#include "ash/system/tray/tray_utils.h"
|
||||
#include "ash/system/unified/unified_system_tray.h"
|
||||
#include "ash/system/unified/unified_system_tray_bubble.h"
|
||||
#include "ash/system/unified/unified_system_tray_view.h"
|
||||
#include "base/functional/bind.h"
|
||||
|
||||
namespace ash {
|
||||
|
@ -37,7 +37,7 @@ class UnifiedCalendarViewController : public DetailedViewController {
|
||||
// Unowned, the object that instantiated us.
|
||||
const raw_ptr<UnifiedSystemTrayController, ExperimentalAsh> tray_controller_;
|
||||
|
||||
// Owned by UnifiedSystemTrayView's detailed_view_container_.
|
||||
// Owned by `QuickSettingsView`'s detailed_view_container_.
|
||||
raw_ptr<CalendarView, DanglingUntriaged | ExperimentalAsh> view_ = nullptr;
|
||||
};
|
||||
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include "ash/style/system_shadow.h"
|
||||
#include "ash/system/tray/system_tray_notifier.h"
|
||||
#include "ash/system/tray/tray_constants.h"
|
||||
#include "ash/system/unified/unified_system_tray_view.h"
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "chromeos/constants/chromeos_features.h"
|
||||
#include "third_party/skia/include/core/SkCanvas.h"
|
||||
|
@ -122,11 +122,7 @@ constexpr int kTrayPopupInkDropCornerRadius = 2;
|
||||
// Threshold to ignore update on the slider value.
|
||||
constexpr float kAudioSliderIgnoreUpdateThreshold = 0.01;
|
||||
|
||||
// Duration for the collapse / expand animation in ms.
|
||||
constexpr int kSystemMenuCollapseExpandAnimationDurationMs = 500;
|
||||
|
||||
constexpr auto kUnifiedMenuItemPadding = gfx::Insets::TLBR(0, 16, 16, 16);
|
||||
constexpr auto kUnifiedSystemInfoViewPadding = gfx::Insets::TLBR(0, 16, 16, 16);
|
||||
constexpr int kSliderChildrenViewSpacing = 8;
|
||||
|
||||
// Constants used in the QuickSettingsSlider of the `QuickSettingsView`.
|
||||
@ -223,9 +219,6 @@ constexpr int kFeatureTileMaxRowsWhenMediaViewIsShowing = 3;
|
||||
constexpr int kFeatureTileMinRows = 1;
|
||||
constexpr int kFeatureTileHeight = 64;
|
||||
|
||||
// Height of the page indicator view.
|
||||
constexpr int kPageIndicatorViewMaxHeight = 20;
|
||||
|
||||
// Constants used in system tray page transition animations.
|
||||
constexpr double kCollapseThreshold = 0.3;
|
||||
|
||||
|
@ -401,8 +401,7 @@ TEST_F(TrayEventFilterTest, NotCloseTrayBubbleWhenTranscientChildActivated) {
|
||||
auto* bubble = system_tray->bubble();
|
||||
|
||||
// Show the network detailed view.
|
||||
bubble->unified_system_tray_controller()->ShowNetworkDetailedView(
|
||||
/*force=*/true);
|
||||
bubble->unified_system_tray_controller()->ShowNetworkDetailedView();
|
||||
|
||||
// Click on the info button in the network detailed view so that a transient
|
||||
// bubble is opened.
|
||||
|
@ -16,7 +16,7 @@ class FeatureTile;
|
||||
|
||||
// Base class for controllers of feature pod buttons.
|
||||
// To add a new feature pod button, implement this class, and add to the list in
|
||||
// UnifiedSystemTrayController::InitFeaturePods().
|
||||
// UnifiedSystemTrayController::InitFeatureTiles().
|
||||
class ASH_EXPORT FeaturePodControllerBase {
|
||||
public:
|
||||
virtual ~FeaturePodControllerBase() {}
|
||||
|
@ -1,405 +0,0 @@
|
||||
// Copyright 2018 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "ash/system/unified/feature_pods_container_view.h"
|
||||
|
||||
#include "ash/public/cpp/pagination/pagination_controller.h"
|
||||
#include "ash/public/cpp/pagination/pagination_model.h"
|
||||
#include "ash/system/tray/tray_constants.h"
|
||||
#include "ash/system/unified/feature_pod_button.h"
|
||||
#include "ash/system/unified/unified_system_tray_controller.h"
|
||||
#include "base/ranges/algorithm.h"
|
||||
|
||||
namespace ash {
|
||||
|
||||
FeaturePodsContainerView::FeaturePodsContainerView(
|
||||
UnifiedSystemTrayController* controller,
|
||||
bool initially_expanded)
|
||||
: controller_(controller),
|
||||
pagination_model_(controller->model()->pagination_model()),
|
||||
expanded_amount_(initially_expanded ? 1.0 : 0.0),
|
||||
feature_pod_rows_(kUnifiedFeaturePodMaxRows) {
|
||||
pagination_model_->AddObserver(this);
|
||||
}
|
||||
|
||||
FeaturePodsContainerView::~FeaturePodsContainerView() {
|
||||
DCHECK(pagination_model_);
|
||||
pagination_model_->RemoveObserver(this);
|
||||
}
|
||||
|
||||
void FeaturePodsContainerView::SetExpandedAmount(double expanded_amount) {
|
||||
DCHECK(0.0 <= expanded_amount && expanded_amount <= 1.0);
|
||||
if (expanded_amount_ == expanded_amount)
|
||||
return;
|
||||
expanded_amount_ = expanded_amount;
|
||||
|
||||
int visible_index = 0;
|
||||
for (auto* view : children()) {
|
||||
FeaturePodButton* button = static_cast<FeaturePodButton*>(view);
|
||||
// When collapsing from page 1, buttons below the second row fade out
|
||||
// while the rest move up into a single row for the collapsed state.
|
||||
// When collapsing from page > 1, each row of buttons fades out one by one
|
||||
// and once expanded_amount is less than kCollapseThreshold we begin to
|
||||
// fade in the single row of buttons for the collapsed state.
|
||||
if (expanded_amount_ > 0.0 && expanded_amount_ < kCollapseThreshold &&
|
||||
pagination_model_->selected_page() > 0) {
|
||||
button->SetExpandedAmount(1.0 - expanded_amount,
|
||||
true /* fade_icon_button */);
|
||||
} else if (visible_index > kUnifiedFeaturePodMaxItemsInCollapsed) {
|
||||
int row =
|
||||
(visible_index / kUnifiedFeaturePodItemsInRow) % feature_pod_rows_;
|
||||
double button_expanded_amount =
|
||||
expanded_amount
|
||||
? std::min(1.0, expanded_amount +
|
||||
(0.25 * (feature_pod_rows_ - row - 1)))
|
||||
: expanded_amount;
|
||||
button->SetExpandedAmount(button_expanded_amount,
|
||||
true /* fade_icon_button */);
|
||||
} else {
|
||||
button->SetExpandedAmount(expanded_amount, false /* fade_icon_button */);
|
||||
}
|
||||
if (view->GetVisible())
|
||||
visible_index++;
|
||||
}
|
||||
UpdateChildVisibility();
|
||||
// We have to call Layout() explicitly here.
|
||||
Layout();
|
||||
}
|
||||
|
||||
int FeaturePodsContainerView::GetExpandedHeight() const {
|
||||
const int visible_count = GetVisibleCount();
|
||||
|
||||
// floor(visible_count / kUnifiedFeaturePodItemsInRow)
|
||||
int number_of_lines = (visible_count + kUnifiedFeaturePodItemsInRow - 1) /
|
||||
kUnifiedFeaturePodItemsInRow;
|
||||
|
||||
number_of_lines = std::min(number_of_lines, feature_pod_rows_);
|
||||
|
||||
return kUnifiedFeaturePodBottomPadding +
|
||||
(kUnifiedFeaturePodVerticalPadding + kUnifiedFeaturePodSize.height()) *
|
||||
std::max(0, number_of_lines - 1) +
|
||||
kUnifiedFeaturePodSize.height() + kUnifiedFeaturePodTopPadding;
|
||||
}
|
||||
|
||||
int FeaturePodsContainerView::GetCollapsedHeight() const {
|
||||
return 2 * kUnifiedFeaturePodCollapsedVerticalPadding +
|
||||
kUnifiedFeaturePodCollapsedSize.height();
|
||||
}
|
||||
|
||||
gfx::Size FeaturePodsContainerView::CalculatePreferredSize() const {
|
||||
return gfx::Size(
|
||||
kTrayMenuWidth,
|
||||
static_cast<int>(GetCollapsedHeight() * (1.0 - expanded_amount_) +
|
||||
GetExpandedHeight() * expanded_amount_));
|
||||
}
|
||||
|
||||
void FeaturePodsContainerView::ChildVisibilityChanged(View* child) {
|
||||
// ChildVisibilityChanged can change child visibility using
|
||||
// SetVisibleByContainer() in UpdateChildVisibility(), so we have to prevent
|
||||
// reentrancy.
|
||||
if (changing_visibility_)
|
||||
return;
|
||||
|
||||
// Visibility change is caused by the child's SetVisible(), so update actual
|
||||
// visibility and propagate the container size change to the parent.
|
||||
UpdateChildVisibility();
|
||||
PreferredSizeChanged();
|
||||
Layout();
|
||||
SchedulePaint();
|
||||
}
|
||||
|
||||
void FeaturePodsContainerView::ViewHierarchyChanged(
|
||||
const views::ViewHierarchyChangedDetails& details) {
|
||||
UpdateChildVisibility();
|
||||
}
|
||||
|
||||
void FeaturePodsContainerView::Layout() {
|
||||
UpdateCollapsedSidePadding();
|
||||
CalculateIdealBoundsForFeaturePods();
|
||||
for (size_t i = 0; i < visible_buttons_.view_size(); ++i) {
|
||||
auto* button = visible_buttons_.view_at(i);
|
||||
button->SetBoundsRect(visible_buttons_.ideal_bounds(i));
|
||||
}
|
||||
}
|
||||
|
||||
const char* FeaturePodsContainerView::GetClassName() const {
|
||||
return "FeaturePodsContainerView";
|
||||
}
|
||||
|
||||
void FeaturePodsContainerView::UpdateChildVisibility() {
|
||||
DCHECK(!changing_visibility_);
|
||||
changing_visibility_ = true;
|
||||
|
||||
int visible_count = 0;
|
||||
for (auto* view : children()) {
|
||||
auto* child = static_cast<FeaturePodButton*>(view);
|
||||
bool visible = IsButtonVisible(child, visible_count);
|
||||
child->SetVisibleByContainer(visible);
|
||||
if (visible) {
|
||||
if (!visible_buttons_.GetIndexOfView(child).has_value())
|
||||
visible_buttons_.Add(child, visible_count);
|
||||
++visible_count;
|
||||
} else {
|
||||
if (auto index = visible_buttons_.GetIndexOfView(child);
|
||||
index.has_value()) {
|
||||
visible_buttons_.Remove(index.value());
|
||||
}
|
||||
}
|
||||
}
|
||||
UpdateTotalPages();
|
||||
changing_visibility_ = false;
|
||||
}
|
||||
|
||||
bool FeaturePodsContainerView::IsButtonVisible(FeaturePodButton* button,
|
||||
int index) {
|
||||
return button->visible_preferred() &&
|
||||
(expanded_amount_ > 0.0 ||
|
||||
index < kUnifiedFeaturePodMaxItemsInCollapsed);
|
||||
}
|
||||
|
||||
int FeaturePodsContainerView::GetVisibleCount() const {
|
||||
return base::ranges::count_if(children(), [](const auto* v) {
|
||||
return static_cast<const FeaturePodButton*>(v)->visible_preferred();
|
||||
});
|
||||
}
|
||||
|
||||
void FeaturePodsContainerView::EnsurePageWithButton(views::View* button) {
|
||||
auto index = visible_buttons_.GetIndexOfView(button->parent());
|
||||
if (!index.has_value())
|
||||
return;
|
||||
|
||||
int tiles_per_page = GetTilesPerPage();
|
||||
size_t first_index = pagination_model_->selected_page() * tiles_per_page;
|
||||
size_t last_index =
|
||||
((pagination_model_->selected_page() + 1) * tiles_per_page) - 1;
|
||||
if (index.value() < first_index || index.value() > last_index) {
|
||||
int page = ((index.value() + 1) / tiles_per_page) +
|
||||
((index.value() + 1) % tiles_per_page ? 1 : 0) - 1;
|
||||
|
||||
pagination_model_->SelectPage(page, true /*animate*/);
|
||||
}
|
||||
}
|
||||
|
||||
void FeaturePodsContainerView::SelectedPageChanged(int old_selected,
|
||||
int new_selected) {
|
||||
InvalidateLayout();
|
||||
PaginationModelObserver::SelectedPageChanged(old_selected, new_selected);
|
||||
}
|
||||
|
||||
gfx::Point FeaturePodsContainerView::GetButtonPosition(
|
||||
int visible_index) const {
|
||||
int row = visible_index / kUnifiedFeaturePodItemsInRow;
|
||||
int column = visible_index % kUnifiedFeaturePodItemsInRow;
|
||||
int x = kUnifiedFeaturePodHorizontalSidePadding +
|
||||
(kUnifiedFeaturePodSize.width() +
|
||||
kUnifiedFeaturePodHorizontalMiddlePadding) *
|
||||
column;
|
||||
int y = kUnifiedFeaturePodTopPadding + (kUnifiedFeaturePodSize.height() +
|
||||
kUnifiedFeaturePodVerticalPadding) *
|
||||
row;
|
||||
|
||||
// Only feature pods visible in the collapsed state (i.e. the first 5 pods)
|
||||
// move during expansion/collapse. Otherwise, the button position will always
|
||||
// be constant.
|
||||
if (expanded_amount_ == 1.0 ||
|
||||
visible_index > kUnifiedFeaturePodMaxItemsInCollapsed ||
|
||||
(pagination_model_->selected_page() > 0 &&
|
||||
expanded_amount_ >= kCollapseThreshold)) {
|
||||
return gfx::Point(x, y);
|
||||
}
|
||||
|
||||
int collapsed_x =
|
||||
collapsed_side_padding_ + (kUnifiedFeaturePodCollapsedSize.width() +
|
||||
kUnifiedFeaturePodCollapsedHorizontalPadding) *
|
||||
visible_index;
|
||||
int collapsed_y = kUnifiedFeaturePodCollapsedVerticalPadding;
|
||||
|
||||
// When fully collapsed or collapsing from a different page to the first
|
||||
// page, just return the collapsed position.
|
||||
if (expanded_amount_ == 0.0 || (expanded_amount_ < kCollapseThreshold &&
|
||||
pagination_model_->selected_page() > 0))
|
||||
return gfx::Point(collapsed_x, collapsed_y);
|
||||
|
||||
// Button width is different between expanded and collapsed states.
|
||||
// During the transition, expanded width is used, so it should be adjusted.
|
||||
collapsed_x -= (kUnifiedFeaturePodSize.width() -
|
||||
kUnifiedFeaturePodCollapsedSize.width()) /
|
||||
2;
|
||||
|
||||
return gfx::Point(
|
||||
x * expanded_amount_ + collapsed_x * (1.0 - expanded_amount_),
|
||||
y * expanded_amount_ + collapsed_y * (1.0 - expanded_amount_));
|
||||
}
|
||||
|
||||
int FeaturePodsContainerView::CalculateRowsFromHeight(int height) {
|
||||
int available_height =
|
||||
height - kUnifiedFeaturePodBottomPadding - kUnifiedFeaturePodTopPadding;
|
||||
int row_height =
|
||||
kUnifiedFeaturePodSize.height() + kUnifiedFeaturePodVerticalPadding;
|
||||
|
||||
// Only use the max number of rows when there is enough space
|
||||
// to show the fully expanded message center and quick settings.
|
||||
if (available_height > (kUnifiedFeaturePodMaxRows * row_height) &&
|
||||
available_height - (kUnifiedFeaturePodMaxRows * row_height) >
|
||||
kMessageCenterCollapseThreshold) {
|
||||
return kUnifiedFeaturePodMaxRows;
|
||||
}
|
||||
|
||||
// Use 1 less than the max number of rows when there is enough
|
||||
// space to show the message center in the collapsed state along
|
||||
// with the expanded quick settings.
|
||||
int feature_pod_rows = kUnifiedFeaturePodMaxRows - 1;
|
||||
if (available_height > (feature_pod_rows * row_height) &&
|
||||
available_height - (feature_pod_rows * row_height) >
|
||||
kStackedNotificationBarHeight) {
|
||||
return feature_pod_rows;
|
||||
}
|
||||
|
||||
return kUnifiedFeaturePodMinRows;
|
||||
}
|
||||
|
||||
void FeaturePodsContainerView::SetMaxHeight(int max_height) {
|
||||
int feature_pod_rows = CalculateRowsFromHeight(max_height);
|
||||
|
||||
if (feature_pod_rows_ != feature_pod_rows) {
|
||||
feature_pod_rows_ = feature_pod_rows;
|
||||
UpdateTotalPages();
|
||||
}
|
||||
}
|
||||
|
||||
void FeaturePodsContainerView::UpdateCollapsedSidePadding() {
|
||||
const int visible_count =
|
||||
std::min(GetVisibleCount(), kUnifiedFeaturePodMaxItemsInCollapsed);
|
||||
|
||||
int contents_width =
|
||||
visible_count * kUnifiedFeaturePodCollapsedSize.width() +
|
||||
(visible_count - 1) * kUnifiedFeaturePodCollapsedHorizontalPadding;
|
||||
|
||||
collapsed_side_padding_ = (kTrayMenuWidth - contents_width) / 2;
|
||||
DCHECK(collapsed_side_padding_ > 0);
|
||||
}
|
||||
|
||||
void FeaturePodsContainerView::AddFeaturePodButton(FeaturePodButton* button) {
|
||||
size_t view_size = visible_buttons_.view_size();
|
||||
if (IsButtonVisible(button, view_size)) {
|
||||
visible_buttons_.Add(button, view_size);
|
||||
}
|
||||
AddChildView(button);
|
||||
|
||||
UpdateTotalPages();
|
||||
}
|
||||
|
||||
const gfx::Vector2d FeaturePodsContainerView::CalculateTransitionOffset(
|
||||
int page_of_view) const {
|
||||
gfx::Size grid_size = CalculatePreferredSize();
|
||||
|
||||
// If there is a transition, calculates offset for current and target page.
|
||||
const int current_page = pagination_model_->selected_page();
|
||||
const PaginationModel::Transition& transition =
|
||||
pagination_model_->transition();
|
||||
const bool is_valid =
|
||||
pagination_model_->is_valid_page(transition.target_page);
|
||||
|
||||
// Transition to previous page means negative offset.
|
||||
const int direction = transition.target_page > current_page ? -1 : 1;
|
||||
|
||||
int x_offset = 0;
|
||||
int y_offset = 0;
|
||||
|
||||
// Page size including padding pixels. A tile.x + page_width means the same
|
||||
// tile slot in the next page.
|
||||
const int page_width = grid_size.width() + kUnifiedFeaturePodsPageSpacing;
|
||||
if (page_of_view < current_page)
|
||||
x_offset = -page_width;
|
||||
else if (page_of_view > current_page)
|
||||
x_offset = page_width;
|
||||
|
||||
if (is_valid) {
|
||||
if (page_of_view == current_page ||
|
||||
page_of_view == transition.target_page) {
|
||||
x_offset += transition.progress * page_width * direction;
|
||||
}
|
||||
}
|
||||
|
||||
return gfx::Vector2d(x_offset, y_offset);
|
||||
}
|
||||
|
||||
void FeaturePodsContainerView::CalculateIdealBoundsForFeaturePods() {
|
||||
for (size_t i = 0; i < visible_buttons_.view_size(); ++i) {
|
||||
gfx::Rect tile_bounds;
|
||||
gfx::Size child_size;
|
||||
// When we are on the first page we calculate bounds for an expanded tray
|
||||
// when expanded_amount is greater than zero. However, when not on the first
|
||||
// page, we only calculate bounds for an expanded tray until expanded_amount
|
||||
// is above kCollapseThreshold. Below kCollapseThreshold we return collapsed
|
||||
// bounds.
|
||||
if ((expanded_amount_ > 0.0 && pagination_model_->selected_page() == 0) ||
|
||||
expanded_amount_ >= kCollapseThreshold) {
|
||||
child_size = kUnifiedFeaturePodSize;
|
||||
|
||||
// Flexibly give more height if the child view doesn't fit into the
|
||||
// default height, so that label texts won't be broken up in the middle.
|
||||
child_size.set_height(std::max(
|
||||
child_size.height(),
|
||||
visible_buttons_.view_at(i)->GetHeightForWidth(child_size.height())));
|
||||
|
||||
tile_bounds =
|
||||
gfx::Rect(GetButtonPosition(i % GetTilesPerPage()), child_size);
|
||||
// TODO(amehfooz): refactor this logic so that the ideal_bounds are set
|
||||
// once when the transition starts and the actual feature pod bounds are
|
||||
// interpolated using the ideal_bounds as the transition progresses.
|
||||
tile_bounds.Offset(CalculateTransitionOffset(i / GetTilesPerPage()));
|
||||
} else {
|
||||
child_size = kUnifiedFeaturePodCollapsedSize;
|
||||
tile_bounds = gfx::Rect(GetButtonPosition(i), child_size);
|
||||
}
|
||||
|
||||
visible_buttons_.set_ideal_bounds(i, tile_bounds);
|
||||
}
|
||||
}
|
||||
|
||||
int FeaturePodsContainerView::GetTilesPerPage() const {
|
||||
return kUnifiedFeaturePodItemsInRow * feature_pod_rows_;
|
||||
}
|
||||
|
||||
void FeaturePodsContainerView::UpdateTotalPages() {
|
||||
int total_pages = 0;
|
||||
|
||||
size_t total_visible = visible_buttons_.view_size();
|
||||
int tiles_per_page = GetTilesPerPage();
|
||||
|
||||
if (!visible_buttons_.view_size() || !tiles_per_page) {
|
||||
total_pages = 0;
|
||||
} else {
|
||||
total_pages = (total_visible / tiles_per_page) +
|
||||
(total_visible % tiles_per_page ? 1 : 0);
|
||||
}
|
||||
pagination_model_->SetTotalPages(total_pages);
|
||||
}
|
||||
|
||||
void FeaturePodsContainerView::TransitionChanged() {
|
||||
const PaginationModel::Transition& transition =
|
||||
pagination_model_->transition();
|
||||
if (pagination_model_->is_valid_page(transition.target_page))
|
||||
Layout();
|
||||
}
|
||||
|
||||
void FeaturePodsContainerView::OnGestureEvent(ui::GestureEvent* event) {
|
||||
if (controller_->pagination_controller()->OnGestureEvent(*event,
|
||||
GetContentsBounds()))
|
||||
event->SetHandled();
|
||||
}
|
||||
|
||||
void FeaturePodsContainerView::OnScrollEvent(ui::ScrollEvent* event) {
|
||||
controller_->pagination_controller()->OnScroll(
|
||||
gfx::Vector2d(event->x_offset(), event->y_offset()), event->type());
|
||||
event->SetHandled();
|
||||
}
|
||||
|
||||
bool FeaturePodsContainerView::OnMouseWheel(const ui::MouseWheelEvent& event) {
|
||||
return controller_->pagination_controller()->OnScroll(event.offset(),
|
||||
event.type());
|
||||
}
|
||||
|
||||
} // namespace ash
|
@ -1,139 +0,0 @@
|
||||
// Copyright 2018 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ASH_SYSTEM_UNIFIED_FEATURE_PODS_CONTAINER_VIEW_H_
|
||||
#define ASH_SYSTEM_UNIFIED_FEATURE_PODS_CONTAINER_VIEW_H_
|
||||
|
||||
#include "ash/ash_export.h"
|
||||
#include "ash/public/cpp/pagination/pagination_model_observer.h"
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "ui/views/view.h"
|
||||
#include "ui/views/view_model.h"
|
||||
|
||||
namespace ash {
|
||||
|
||||
class FeaturePodButton;
|
||||
class PaginationModel;
|
||||
class UnifiedSystemTrayController;
|
||||
|
||||
// Container of feature pods buttons in the middle of UnifiedSystemTrayView.
|
||||
// The container has number of buttons placed in 3x3 plane at regular distances.
|
||||
// FeaturePodButtons implements these individual buttons.
|
||||
// The container also implements collapsed state where the top 5 buttons are
|
||||
// horizontally placed and others are hidden.
|
||||
class ASH_EXPORT FeaturePodsContainerView : public views::View,
|
||||
public PaginationModelObserver {
|
||||
public:
|
||||
FeaturePodsContainerView(UnifiedSystemTrayController* controller,
|
||||
bool initially_expanded);
|
||||
|
||||
FeaturePodsContainerView(const FeaturePodsContainerView&) = delete;
|
||||
FeaturePodsContainerView& operator=(const FeaturePodsContainerView&) = delete;
|
||||
|
||||
~FeaturePodsContainerView() override;
|
||||
|
||||
// Add a FeaturePodButton as a child view and if it's visible add it to the
|
||||
// view structure and update the pagination model.
|
||||
void AddFeaturePodButton(FeaturePodButton* button);
|
||||
|
||||
// Change the expanded state. 0.0 if collapsed, and 1.0 if expanded.
|
||||
// Otherwise, it shows intermediate state. If collapsed, all the buttons are
|
||||
// horizontally placed.
|
||||
void SetExpandedAmount(double expanded_amount);
|
||||
|
||||
// Set the number of rows of feature pods based on the max height the
|
||||
// container can have.
|
||||
void SetMaxHeight(int max_height);
|
||||
|
||||
// Get height of the view when |expanded_amount| is set to 1.0.
|
||||
int GetExpandedHeight() const;
|
||||
|
||||
// Get the height of the view when |expanded_amount| is set to 0.0.
|
||||
int GetCollapsedHeight() const;
|
||||
|
||||
// Returns the number of children that prefer to be visible.
|
||||
int GetVisibleCount() const;
|
||||
|
||||
// Make sure button is visible by switching page if needed.
|
||||
void EnsurePageWithButton(views::View* button);
|
||||
|
||||
// PaginationModelObserver
|
||||
void SelectedPageChanged(int old_selected, int new_selected) override;
|
||||
|
||||
// views::View:
|
||||
gfx::Size CalculatePreferredSize() const override;
|
||||
void ChildVisibilityChanged(View* child) override;
|
||||
void ViewHierarchyChanged(
|
||||
const views::ViewHierarchyChangedDetails& details) override;
|
||||
void Layout() override;
|
||||
void OnGestureEvent(ui::GestureEvent* event) override;
|
||||
void OnScrollEvent(ui::ScrollEvent* event) override;
|
||||
bool OnMouseWheel(const ui::MouseWheelEvent& event) override;
|
||||
const char* GetClassName() const override;
|
||||
|
||||
int row_count() const { return feature_pod_rows_; }
|
||||
|
||||
private:
|
||||
friend class FeaturePodsContainerViewTest;
|
||||
|
||||
// Calculate the current position of the button from |visible_index| and
|
||||
// |expanded_amount_|.
|
||||
gfx::Point GetButtonPosition(int visible_index) const;
|
||||
|
||||
void UpdateChildVisibility();
|
||||
|
||||
// Update |collapsed_state_padding_|.
|
||||
void UpdateCollapsedSidePadding();
|
||||
|
||||
// Calculates the ideal bounds for all feature pods.
|
||||
void CalculateIdealBoundsForFeaturePods();
|
||||
|
||||
// Calculate the number of feature pod rows based on available height.
|
||||
int CalculateRowsFromHeight(int height);
|
||||
|
||||
// Calculates the offset for |page_of_view| based on current page and
|
||||
// transition target page.
|
||||
const gfx::Vector2d CalculateTransitionOffset(int page_of_view) const;
|
||||
|
||||
// Returns true if button at provided index is visible.
|
||||
bool IsButtonVisible(FeaturePodButton* button, int index);
|
||||
|
||||
// Returns the number of tiles per page.
|
||||
int GetTilesPerPage() const;
|
||||
|
||||
// Updates page splits for feature pod buttons.
|
||||
void UpdateTotalPages();
|
||||
|
||||
// PaginationModelObserver:
|
||||
void TransitionChanged() override;
|
||||
|
||||
const raw_ptr<UnifiedSystemTrayController,
|
||||
DanglingUntriaged | ExperimentalAsh>
|
||||
controller_;
|
||||
|
||||
// Owned by UnifiedSystemTrayModel.
|
||||
const raw_ptr<PaginationModel, ExperimentalAsh> pagination_model_;
|
||||
|
||||
// The last |expanded_amount| passed to SetExpandedAmount().
|
||||
double expanded_amount_;
|
||||
|
||||
// Number of rows of feature pods to display. Updated based on the available
|
||||
// max height for FeaturePodsContainer.
|
||||
int feature_pod_rows_ = 0;
|
||||
|
||||
// Horizontal side padding in dip for collapsed state.
|
||||
int collapsed_side_padding_ = 0;
|
||||
|
||||
// Used for preventing reentrancy issue in ChildVisibilityChanged. Should be
|
||||
// always false if FeaturePodsContainerView is not in the call stack.
|
||||
bool changing_visibility_ = false;
|
||||
|
||||
// A view model that contains all visible feature pod buttons.
|
||||
// Used to calculate required number of pages.
|
||||
views::ViewModelT<FeaturePodButton> visible_buttons_;
|
||||
};
|
||||
|
||||
} // namespace ash
|
||||
|
||||
#endif // ASH_SYSTEM_UNIFIED_FEATURE_PODS_CONTAINER_VIEW_H_
|
@ -1,463 +0,0 @@
|
||||
// Copyright 2018 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "ash/system/unified/feature_pods_container_view.h"
|
||||
|
||||
#include "ash/constants/quick_settings_catalogs.h"
|
||||
#include "ash/public/cpp/pagination/pagination_controller.h"
|
||||
#include "ash/public/cpp/pagination/pagination_model.h"
|
||||
#include "ash/system/tray/tray_constants.h"
|
||||
#include "ash/system/unified/feature_pod_button.h"
|
||||
#include "ash/system/unified/feature_pod_controller_base.h"
|
||||
#include "ash/system/unified/unified_system_tray_controller.h"
|
||||
#include "ash/system/unified/unified_system_tray_model.h"
|
||||
#include "ash/test/ash_test_base.h"
|
||||
#include "base/memory/scoped_refptr.h"
|
||||
#include "ui/accessibility/ax_enums.mojom.h"
|
||||
#include "ui/accessibility/ax_node_data.h"
|
||||
#include "ui/views/test/views_test_utils.h"
|
||||
#include "ui/views/view_observer.h"
|
||||
|
||||
namespace ash {
|
||||
|
||||
class FeaturePodsContainerViewTest : public NoSessionAshTestBase,
|
||||
public FeaturePodControllerBase,
|
||||
public views::ViewObserver {
|
||||
public:
|
||||
FeaturePodsContainerViewTest() = default;
|
||||
|
||||
FeaturePodsContainerViewTest(const FeaturePodsContainerViewTest&) = delete;
|
||||
FeaturePodsContainerViewTest& operator=(const FeaturePodsContainerViewTest&) =
|
||||
delete;
|
||||
|
||||
~FeaturePodsContainerViewTest() override = default;
|
||||
|
||||
// AshTestBase:
|
||||
void SetUp() override {
|
||||
AshTestBase::SetUp();
|
||||
model_ = base::MakeRefCounted<UnifiedSystemTrayModel>(nullptr);
|
||||
controller_ = std::make_unique<UnifiedSystemTrayController>(model_.get());
|
||||
container_ = std::make_unique<FeaturePodsContainerView>(
|
||||
controller_.get(), true /* initially_expanded */);
|
||||
container_->AddObserver(this);
|
||||
preferred_size_changed_count_ = 0;
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
controller_.reset();
|
||||
container_.reset();
|
||||
model_.reset();
|
||||
NoSessionAshTestBase::TearDown();
|
||||
}
|
||||
|
||||
// FeaturePodControllerBase:
|
||||
std::unique_ptr<FeatureTile> CreateTile(bool compact) override {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void OnIconPressed() override {}
|
||||
|
||||
QsFeatureCatalogName GetCatalogName() override {
|
||||
return QsFeatureCatalogName::kUnknown;
|
||||
}
|
||||
|
||||
// views::ViewObserver:
|
||||
void OnViewPreferredSizeChanged(views::View* observed_view) override {
|
||||
++preferred_size_changed_count_;
|
||||
}
|
||||
|
||||
protected:
|
||||
void AddButton(FeaturePodButton* button) {
|
||||
buttons_.push_back(button);
|
||||
container()->AddChildView(button);
|
||||
}
|
||||
|
||||
void AddButtons(int count) {
|
||||
for (int i = 0; i < count; ++i)
|
||||
AddButton(new FeaturePodButton(this));
|
||||
container()->SetBoundsRect(gfx::Rect(container_->GetPreferredSize()));
|
||||
views::test::RunScheduledLayout(container());
|
||||
}
|
||||
|
||||
FeaturePodsContainerView* container() { return container_.get(); }
|
||||
|
||||
PaginationModel* pagination_model() { return model_->pagination_model(); }
|
||||
|
||||
UnifiedSystemTrayController* controller() { return controller_.get(); }
|
||||
|
||||
int preferred_size_changed_count() const {
|
||||
return preferred_size_changed_count_;
|
||||
}
|
||||
|
||||
std::vector<FeaturePodButton*> buttons_;
|
||||
|
||||
private:
|
||||
std::unique_ptr<FeaturePodsContainerView> container_;
|
||||
scoped_refptr<UnifiedSystemTrayModel> model_;
|
||||
std::unique_ptr<UnifiedSystemTrayController> controller_;
|
||||
int preferred_size_changed_count_ = 0;
|
||||
};
|
||||
|
||||
TEST_F(FeaturePodsContainerViewTest, ExpandedAndCollapsed) {
|
||||
const int kNumberOfAddedButtons = kUnifiedFeaturePodItemsInRow * 3;
|
||||
EXPECT_LT(kUnifiedFeaturePodMaxItemsInCollapsed, kNumberOfAddedButtons);
|
||||
|
||||
AddButtons(kNumberOfAddedButtons);
|
||||
|
||||
// In expanded state, buttons are laid out in plane.
|
||||
EXPECT_LT(buttons_[0]->x(), buttons_[1]->x());
|
||||
EXPECT_EQ(buttons_[0]->y(), buttons_[1]->y());
|
||||
// If the row exceeds kUnifiedFeaturePodItemsInRow, the next button is placed
|
||||
// right under the first button.
|
||||
EXPECT_EQ(buttons_[0]->x(), buttons_[kUnifiedFeaturePodItemsInRow]->x());
|
||||
EXPECT_LT(buttons_[0]->y(), buttons_[kUnifiedFeaturePodItemsInRow]->y());
|
||||
// All buttons are visible.
|
||||
for (auto* button : buttons_)
|
||||
EXPECT_TRUE(button->GetVisible());
|
||||
|
||||
container()->SetExpandedAmount(0.0);
|
||||
|
||||
// In collapsed state, all buttons are laid out horizontally.
|
||||
for (int i = 1; i < kUnifiedFeaturePodMaxItemsInCollapsed; ++i)
|
||||
EXPECT_EQ(buttons_[0]->y(), buttons_[i]->y());
|
||||
|
||||
// Buttons exceed kUnifiedFeaturePodMaxItemsInCollapsed are invisible.
|
||||
for (int i = 0; i < kNumberOfAddedButtons; ++i) {
|
||||
EXPECT_EQ(i < kUnifiedFeaturePodMaxItemsInCollapsed,
|
||||
buttons_[i]->GetVisible());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(FeaturePodsContainerViewTest, HiddenButtonRemainsHidden) {
|
||||
AddButtons(kUnifiedFeaturePodMaxItemsInCollapsed);
|
||||
// The button is invisible in expanded state.
|
||||
buttons_.front()->SetVisible(false);
|
||||
container()->SetExpandedAmount(0.0);
|
||||
EXPECT_FALSE(buttons_.front()->GetVisible());
|
||||
container()->SetExpandedAmount(1.0);
|
||||
EXPECT_FALSE(buttons_.front()->GetVisible());
|
||||
}
|
||||
|
||||
TEST_F(FeaturePodsContainerViewTest, BecomeVisibleInCollapsed) {
|
||||
AddButtons(kUnifiedFeaturePodMaxItemsInCollapsed);
|
||||
// The button is invisible in expanded state.
|
||||
buttons_.back()->SetVisible(false);
|
||||
container()->SetExpandedAmount(0.0);
|
||||
// The button becomes visible in collapsed state.
|
||||
buttons_.back()->SetVisible(true);
|
||||
// As the container still has remaining space, the button will be visible.
|
||||
EXPECT_TRUE(buttons_.back()->GetVisible());
|
||||
}
|
||||
|
||||
TEST_F(FeaturePodsContainerViewTest, StillHiddenInCollapsed) {
|
||||
AddButtons(kUnifiedFeaturePodMaxItemsInCollapsed + 1);
|
||||
// The button is invisible in expanded state.
|
||||
buttons_.back()->SetVisible(false);
|
||||
container()->SetExpandedAmount(0.0);
|
||||
// The button becomes visible in collapsed state.
|
||||
buttons_.back()->SetVisible(true);
|
||||
// As the container doesn't have remaining space, the button won't be visible.
|
||||
EXPECT_FALSE(buttons_.back()->GetVisible());
|
||||
|
||||
container()->SetExpandedAmount(1.0);
|
||||
// The button becomes visible in expanded state.
|
||||
EXPECT_TRUE(buttons_.back()->GetVisible());
|
||||
}
|
||||
|
||||
TEST_F(FeaturePodsContainerViewTest, DifferentButtonBecomeVisibleInCollapsed) {
|
||||
AddButtons(kUnifiedFeaturePodMaxItemsInCollapsed + 1);
|
||||
container()->SetExpandedAmount(0.0);
|
||||
// The last button is not visible as it doesn't have enough space.
|
||||
EXPECT_FALSE(buttons_.back()->GetVisible());
|
||||
// The first button becomes invisible.
|
||||
buttons_.front()->SetVisible(false);
|
||||
// The last button now has the space for it.
|
||||
EXPECT_TRUE(buttons_.back()->GetVisible());
|
||||
}
|
||||
|
||||
TEST_F(FeaturePodsContainerViewTest, SizeChangeByExpanding) {
|
||||
// SetExpandedAmount() should not trigger PreferredSizeChanged().
|
||||
AddButtons(kUnifiedFeaturePodItemsInRow * 3 - 1);
|
||||
EXPECT_EQ(0, preferred_size_changed_count());
|
||||
container()->SetExpandedAmount(0.0);
|
||||
container()->SetExpandedAmount(0.5);
|
||||
container()->SetExpandedAmount(1.0);
|
||||
EXPECT_EQ(0, preferred_size_changed_count());
|
||||
}
|
||||
|
||||
TEST_F(FeaturePodsContainerViewTest, SizeChangeByVisibility) {
|
||||
// Visibility change should trigger PreferredSizeChanged().
|
||||
AddButtons(kUnifiedFeaturePodItemsInRow * 2 + 1);
|
||||
EXPECT_EQ(0, preferred_size_changed_count());
|
||||
// The first button becomes invisible.
|
||||
buttons_.front()->SetVisible(false);
|
||||
EXPECT_EQ(1, preferred_size_changed_count());
|
||||
// The first button becomes visible.
|
||||
buttons_.front()->SetVisible(true);
|
||||
EXPECT_EQ(2, preferred_size_changed_count());
|
||||
}
|
||||
|
||||
TEST_F(FeaturePodsContainerViewTest, NumberOfPagesChanged) {
|
||||
const int kNumberOfPages = 8;
|
||||
|
||||
AddButtons(kUnifiedFeaturePodItemsInRow * kUnifiedFeaturePodMaxRows *
|
||||
kNumberOfPages);
|
||||
|
||||
// Adding buttons to fill kNumberOfPages should cause the the same number of
|
||||
// pages to be created.
|
||||
EXPECT_EQ(kNumberOfPages, pagination_model()->total_pages());
|
||||
|
||||
// Adding an additional button causes a new page to be added.
|
||||
AddButtons(1);
|
||||
EXPECT_EQ(pagination_model()->total_pages(), kNumberOfPages + 1);
|
||||
}
|
||||
|
||||
TEST_F(FeaturePodsContainerViewTest, PaginationTransition) {
|
||||
const int kNumberOfPages = 8;
|
||||
|
||||
AddButtons(kUnifiedFeaturePodItemsInRow * kUnifiedFeaturePodMaxRows *
|
||||
kNumberOfPages);
|
||||
|
||||
// Position of a button should slide to the left during a page
|
||||
// transition to the next page.
|
||||
gfx::Rect current_bounds;
|
||||
gfx::Rect initial_bounds = buttons_[0]->bounds();
|
||||
gfx::Rect previous_bounds = initial_bounds;
|
||||
|
||||
PaginationModel::Transition transition(
|
||||
pagination_model()->selected_page() + 1, 0);
|
||||
|
||||
for (double i = 0.1; i <= 1.0; i += 0.1) {
|
||||
transition.progress = i;
|
||||
pagination_model()->SetTransition(transition);
|
||||
|
||||
current_bounds = buttons_[0]->bounds();
|
||||
|
||||
EXPECT_LT(current_bounds.x(), previous_bounds.x());
|
||||
EXPECT_EQ(current_bounds.y(), previous_bounds.y());
|
||||
|
||||
previous_bounds = current_bounds;
|
||||
}
|
||||
|
||||
// Button Position after page switch should move to the left by a page offset.
|
||||
int page_offset = container()->CalculatePreferredSize().width() +
|
||||
kUnifiedFeaturePodsPageSpacing;
|
||||
gfx::Rect final_bounds =
|
||||
gfx::Rect(initial_bounds.x() - page_offset, initial_bounds.y(),
|
||||
initial_bounds.width(), initial_bounds.height());
|
||||
pagination_model()->SelectPage(1, false);
|
||||
views::test::RunScheduledLayout(container());
|
||||
EXPECT_EQ(final_bounds, buttons_[0]->bounds());
|
||||
}
|
||||
|
||||
TEST_F(FeaturePodsContainerViewTest, PaginationDynamicRows) {
|
||||
const int kNumberOfFeaturePods = kUnifiedFeaturePodItemsInRow * 3;
|
||||
const int padding =
|
||||
kUnifiedFeaturePodTopPadding + kUnifiedFeaturePodBottomPadding;
|
||||
int row_height =
|
||||
kUnifiedFeaturePodSize.height() + kUnifiedFeaturePodVerticalPadding;
|
||||
int min_height_for_three_rows = kUnifiedFeaturePodMaxRows * row_height +
|
||||
padding + kMessageCenterCollapseThreshold;
|
||||
|
||||
AddButtons(kNumberOfFeaturePods);
|
||||
|
||||
// Expect 1 row of feature pods even if there is 0 height.
|
||||
container()->SetMaxHeight(0);
|
||||
int expected_number_of_pages =
|
||||
kNumberOfFeaturePods / kUnifiedFeaturePodItemsInRow;
|
||||
if (kNumberOfFeaturePods % kUnifiedFeaturePodItemsInRow)
|
||||
expected_number_of_pages += 1;
|
||||
EXPECT_EQ(expected_number_of_pages, pagination_model()->total_pages());
|
||||
|
||||
// Expect 2 rows of feature pods when there is enough height to display them
|
||||
// but less than enough to display 3 rows.
|
||||
container()->SetMaxHeight(min_height_for_three_rows - 1);
|
||||
expected_number_of_pages =
|
||||
kNumberOfFeaturePods / (2 * kUnifiedFeaturePodItemsInRow);
|
||||
if (kNumberOfFeaturePods % (2 * kUnifiedFeaturePodItemsInRow))
|
||||
expected_number_of_pages += 1;
|
||||
EXPECT_EQ(expected_number_of_pages, pagination_model()->total_pages());
|
||||
|
||||
// Expect 3 rows of feature pods at max even when the max height is very
|
||||
// large.
|
||||
container()->SetMaxHeight(min_height_for_three_rows + 1);
|
||||
expected_number_of_pages =
|
||||
kNumberOfFeaturePods / (3 * kUnifiedFeaturePodItemsInRow);
|
||||
if (kNumberOfFeaturePods % (3 * kUnifiedFeaturePodItemsInRow))
|
||||
expected_number_of_pages += 1;
|
||||
EXPECT_EQ(expected_number_of_pages, pagination_model()->total_pages());
|
||||
}
|
||||
|
||||
TEST_F(FeaturePodsContainerViewTest, PaginationGestureHandling) {
|
||||
const int kNumberOfPages = 8;
|
||||
|
||||
AddButtons(kUnifiedFeaturePodItemsInRow * kUnifiedFeaturePodMaxRows *
|
||||
kNumberOfPages);
|
||||
|
||||
gfx::Point container_origin = container()->GetBoundsInScreen().origin();
|
||||
ui::GestureEvent swipe_left_begin(
|
||||
container_origin.x(), container_origin.y(), 0, base::TimeTicks(),
|
||||
ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_BEGIN, -1, 0));
|
||||
ui::GestureEvent swipe_left_update(
|
||||
container_origin.x(), container_origin.y(), 0, base::TimeTicks(),
|
||||
ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_UPDATE, -1000, 0));
|
||||
ui::GestureEvent swipe_right_begin(
|
||||
container_origin.x(), container_origin.y(), 0, base::TimeTicks(),
|
||||
ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_BEGIN, 1, 0));
|
||||
ui::GestureEvent swipe_right_update(
|
||||
container_origin.x(), container_origin.y(), 0, base::TimeTicks(),
|
||||
ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_UPDATE, 1000, 0));
|
||||
ui::GestureEvent swipe_end(container_origin.x(), container_origin.y(), 0,
|
||||
base::TimeTicks(),
|
||||
ui::GestureEventDetails(ui::ET_GESTURE_END));
|
||||
|
||||
int previous_page = pagination_model()->selected_page();
|
||||
|
||||
// Swipe left takes to next page
|
||||
for (int i = 0; i < kNumberOfPages - 1; i++) {
|
||||
// Simulate swipe left
|
||||
container()->OnGestureEvent(&swipe_left_begin);
|
||||
container()->OnGestureEvent(&swipe_left_update);
|
||||
container()->OnGestureEvent(&swipe_end);
|
||||
|
||||
int current_page = pagination_model()->selected_page();
|
||||
// Expect next page
|
||||
EXPECT_EQ(previous_page + 1, current_page);
|
||||
previous_page = current_page;
|
||||
}
|
||||
|
||||
// Swipe left on last page does nothing
|
||||
container()->OnGestureEvent(&swipe_left_begin);
|
||||
container()->OnGestureEvent(&swipe_left_update);
|
||||
container()->OnGestureEvent(&swipe_end);
|
||||
|
||||
EXPECT_EQ(previous_page, pagination_model()->selected_page());
|
||||
|
||||
// Swipe right takes to previous page
|
||||
for (int i = 0; i < kNumberOfPages - 1; i++) {
|
||||
// Simulate swipe right
|
||||
container()->OnGestureEvent(&swipe_right_begin);
|
||||
container()->OnGestureEvent(&swipe_right_update);
|
||||
container()->OnGestureEvent(&swipe_end);
|
||||
|
||||
int current_page = pagination_model()->selected_page();
|
||||
// Expect previous page
|
||||
EXPECT_EQ(previous_page - 1, current_page);
|
||||
previous_page = current_page;
|
||||
}
|
||||
|
||||
// Swipe right on first page does nothing
|
||||
container()->OnGestureEvent(&swipe_right_begin);
|
||||
container()->OnGestureEvent(&swipe_right_update);
|
||||
container()->OnGestureEvent(&swipe_end);
|
||||
|
||||
EXPECT_EQ(previous_page, pagination_model()->selected_page());
|
||||
}
|
||||
|
||||
TEST_F(FeaturePodsContainerViewTest, PaginationScrollHandling) {
|
||||
const int kNumberOfPages = 8;
|
||||
const int num_fingers = 2;
|
||||
|
||||
AddButtons(kUnifiedFeaturePodItemsInRow * kUnifiedFeaturePodMaxRows *
|
||||
kNumberOfPages);
|
||||
|
||||
EXPECT_EQ(kNumberOfPages, pagination_model()->total_pages());
|
||||
|
||||
gfx::Point container_origin = container()->GetBoundsInScreen().origin();
|
||||
|
||||
ui::ScrollEvent fling_up_start(ui::ET_SCROLL_FLING_START, container_origin,
|
||||
base::TimeTicks(), 0, 0, 100, 0, 10,
|
||||
num_fingers);
|
||||
|
||||
ui::ScrollEvent fling_down_start(ui::ET_SCROLL_FLING_START, container_origin,
|
||||
base::TimeTicks(), 0, 0, -100, 0, 10,
|
||||
num_fingers);
|
||||
|
||||
ui::ScrollEvent fling_cancel(ui::ET_SCROLL_FLING_CANCEL, container_origin,
|
||||
base::TimeTicks(), 0, 0, 0, 0, 0, num_fingers);
|
||||
|
||||
int previous_page = pagination_model()->selected_page();
|
||||
|
||||
// Scroll down takes to next page
|
||||
for (int i = 0; i < kNumberOfPages - 1; i++) {
|
||||
// Simulate Scroll left
|
||||
container()->OnScrollEvent(&fling_down_start);
|
||||
container()->OnScrollEvent(&fling_cancel);
|
||||
pagination_model()->FinishAnimation();
|
||||
|
||||
int current_page = pagination_model()->selected_page();
|
||||
// Expect next page
|
||||
EXPECT_EQ(previous_page + 1, current_page);
|
||||
previous_page = current_page;
|
||||
}
|
||||
|
||||
// Scroll up takes to previous page
|
||||
for (int i = 0; i < kNumberOfPages - 1; i++) {
|
||||
// Simulate Scroll up
|
||||
container()->OnScrollEvent(&fling_up_start);
|
||||
container()->OnScrollEvent(&fling_cancel);
|
||||
pagination_model()->FinishAnimation();
|
||||
|
||||
int current_page = pagination_model()->selected_page();
|
||||
// Expect previous page
|
||||
EXPECT_EQ(previous_page - 1, current_page);
|
||||
previous_page = current_page;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(FeaturePodsContainerViewTest, PaginationMouseWheelHandling) {
|
||||
const int kNumberOfPages = 8;
|
||||
|
||||
AddButtons(kUnifiedFeaturePodItemsInRow * kUnifiedFeaturePodMaxRows *
|
||||
kNumberOfPages);
|
||||
|
||||
gfx::Point container_origin = container()->GetBoundsInScreen().origin();
|
||||
ui::MouseWheelEvent wheel_up(gfx::Vector2d(0, 1000), container_origin,
|
||||
container_origin, base::TimeTicks(), 0, 0);
|
||||
|
||||
ui::MouseWheelEvent wheel_down(gfx::Vector2d(0, -1000), container_origin,
|
||||
container_origin, base::TimeTicks(), 0, 0);
|
||||
|
||||
int previous_page = pagination_model()->selected_page();
|
||||
|
||||
// Mouse wheel down takes to next page
|
||||
for (int i = 0; i < kNumberOfPages - 1; i++) {
|
||||
// Simulate mouse wheel down
|
||||
container()->OnMouseWheel(wheel_down);
|
||||
pagination_model()->FinishAnimation();
|
||||
|
||||
int current_page = pagination_model()->selected_page();
|
||||
// Expect next page
|
||||
EXPECT_EQ(previous_page + 1, current_page);
|
||||
previous_page = current_page;
|
||||
}
|
||||
|
||||
// Mouse wheel up takes to previous page
|
||||
for (int i = 0; i < kNumberOfPages - 1; i++) {
|
||||
// Simulate mouse wheel up
|
||||
container()->OnMouseWheel(wheel_up);
|
||||
pagination_model()->FinishAnimation();
|
||||
|
||||
int current_page = pagination_model()->selected_page();
|
||||
// Expect previous page
|
||||
EXPECT_EQ(previous_page - 1, current_page);
|
||||
previous_page = current_page;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(FeaturePodsContainerViewTest, NonTogglableButton) {
|
||||
// Add one togglable and one non-tobblable button.
|
||||
AddButton(new FeaturePodButton(this, /*is_togglable=*/false));
|
||||
AddButtons(1);
|
||||
|
||||
// Non-togglable buttons should be labelled as a regular button for
|
||||
// accessibility and vice versa.
|
||||
ui::AXNodeData ax_node_data;
|
||||
buttons_[0]->icon_button()->GetAccessibleNodeData(&ax_node_data);
|
||||
EXPECT_EQ(ax_node_data.role, ax::mojom::Role::kButton);
|
||||
buttons_[1]->icon_button()->GetAccessibleNodeData(&ax_node_data);
|
||||
EXPECT_EQ(ax_node_data.role, ax::mojom::Role::kToggleButton);
|
||||
}
|
||||
|
||||
} // namespace ash
|
@ -1,103 +0,0 @@
|
||||
// Copyright 2018 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "ash/system/unified/notification_hidden_view.h"
|
||||
|
||||
#include "ash/bubble/bubble_constants.h"
|
||||
#include "ash/login/login_screen_controller.h"
|
||||
#include "ash/shell.h"
|
||||
#include "ash/strings/grit/ash_strings.h"
|
||||
#include "ash/style/ash_color_provider.h"
|
||||
#include "ash/style/pill_button.h"
|
||||
#include "ash/system/message_center/ash_message_center_lock_screen_controller.h"
|
||||
#include "ash/system/message_center/message_center_constants.h"
|
||||
#include "ash/system/tray/tray_constants.h"
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/functional/callback_helpers.h"
|
||||
#include "ui/base/l10n/l10n_util.h"
|
||||
#include "ui/message_center/lock_screen/lock_screen_controller.h"
|
||||
#include "ui/message_center/message_center.h"
|
||||
#include "ui/message_center/message_center_impl.h"
|
||||
#include "ui/views/background.h"
|
||||
#include "ui/views/border.h"
|
||||
#include "ui/views/controls/label.h"
|
||||
#include "ui/views/layout/box_layout.h"
|
||||
#include "ui/views/layout/fill_layout.h"
|
||||
|
||||
namespace ash {
|
||||
|
||||
namespace {
|
||||
|
||||
void ShowLockScreenNotificationSettings() {
|
||||
ash::Shell::Get()
|
||||
->login_screen_controller()
|
||||
->ShowLockScreenNotificationSettings();
|
||||
}
|
||||
|
||||
SkColor GetBackgroundColor() {
|
||||
return AshColorProvider::Get()->GetControlsLayerColor(
|
||||
AshColorProvider::ControlsLayerType::kControlBackgroundColorInactive);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NotificationHiddenView::NotificationHiddenView()
|
||||
: container_(AddChildView(std::make_unique<views::View>())),
|
||||
label_(container_->AddChildView(std::make_unique<views::Label>())) {
|
||||
label_->SetAutoColorReadabilityEnabled(false);
|
||||
label_->SetText(
|
||||
l10n_util::GetStringUTF16(IDS_ASH_MESSAGE_CENTER_LOCKSCREEN_UNIFIED));
|
||||
label_->SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_LEFT);
|
||||
label_->SetLineHeight(kUnifiedNotificationHiddenLineHeight);
|
||||
label_->SetBorder(
|
||||
views::CreateEmptyBorder(kUnifiedNotificationHiddenPadding));
|
||||
|
||||
container_->SetBackground(views::CreateRoundedRectBackground(
|
||||
GetBackgroundColor(), kBubbleCornerRadius));
|
||||
|
||||
auto* layout =
|
||||
container_->SetLayoutManager(std::make_unique<views::BoxLayout>(
|
||||
views::BoxLayout::Orientation::kHorizontal));
|
||||
layout->SetFlexForView(label_, 1);
|
||||
|
||||
// Shows the "Change" button, unless the locks screen notification is
|
||||
// prohibited by policy or flag.
|
||||
if (AshMessageCenterLockScreenController::IsAllowed()) {
|
||||
change_button_ = container_->AddChildView(std::make_unique<PillButton>(
|
||||
base::BindRepeating(&NotificationHiddenView::ChangeButtonPressed,
|
||||
base::Unretained(this)),
|
||||
l10n_util::GetStringUTF16(IDS_ASH_MESSAGE_CENTER_LOCKSCREEN_CHANGE),
|
||||
PillButton::Type::kDefaultWithoutIcon, /*icon=*/nullptr,
|
||||
kNotificationPillButtonHorizontalSpacing));
|
||||
change_button_->SetTooltipText(l10n_util::GetStringUTF16(
|
||||
IDS_ASH_MESSAGE_CENTER_LOCKSCREEN_CHANGE_TOOLTIP));
|
||||
}
|
||||
|
||||
SetBorder(views::CreateEmptyBorder(kUnifiedNotificationCenterSpacing));
|
||||
SetLayoutManager(std::make_unique<views::FillLayout>());
|
||||
}
|
||||
|
||||
const char* NotificationHiddenView::GetClassName() const {
|
||||
return "NotificationHiddenView";
|
||||
}
|
||||
|
||||
void NotificationHiddenView::OnThemeChanged() {
|
||||
views::View::OnThemeChanged();
|
||||
label_->SetEnabledColor(AshColorProvider::Get()->GetContentLayerColor(
|
||||
AshColorProvider::ContentLayerType::kTextColorPrimary));
|
||||
container_->background()->SetNativeControlColor(GetBackgroundColor());
|
||||
}
|
||||
|
||||
void NotificationHiddenView::ChangeButtonPressed() {
|
||||
// TODO(yoshiki): Refactor LockScreenController and remove the static cast.
|
||||
// TODO(yoshiki): Show the setting after unlocking.
|
||||
static_cast<message_center::MessageCenterImpl*>(
|
||||
message_center::MessageCenter::Get())
|
||||
->lock_screen_controller()
|
||||
->DismissLockScreenThenExecute(
|
||||
base::BindOnce(&ShowLockScreenNotificationSettings),
|
||||
base::DoNothing(), IDS_ASH_MESSAGE_CENTER_UNLOCK_TO_CHANGE_SETTING);
|
||||
}
|
||||
|
||||
} // namespace ash
|
@ -1,46 +0,0 @@
|
||||
// Copyright 2018 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ASH_SYSTEM_UNIFIED_NOTIFICATION_HIDDEN_VIEW_H_
|
||||
#define ASH_SYSTEM_UNIFIED_NOTIFICATION_HIDDEN_VIEW_H_
|
||||
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "ui/views/view.h"
|
||||
|
||||
namespace views {
|
||||
class Button;
|
||||
class Label;
|
||||
}
|
||||
|
||||
namespace ash {
|
||||
|
||||
// A view to show the message that notifications are hidden on the lock screen
|
||||
// by the setting or the flag. This may show the button to encourage the user
|
||||
// to change the lock screen notification setting if the condition permits.
|
||||
class NotificationHiddenView : public views::View {
|
||||
public:
|
||||
NotificationHiddenView();
|
||||
|
||||
NotificationHiddenView(const NotificationHiddenView&) = delete;
|
||||
NotificationHiddenView& operator=(const NotificationHiddenView&) = delete;
|
||||
|
||||
~NotificationHiddenView() override = default;
|
||||
|
||||
// views::View:
|
||||
const char* GetClassName() const override;
|
||||
void OnThemeChanged() override;
|
||||
|
||||
views::Button* change_button_for_testing() { return change_button_; }
|
||||
|
||||
private:
|
||||
void ChangeButtonPressed();
|
||||
|
||||
const raw_ptr<views::View, ExperimentalAsh> container_;
|
||||
const raw_ptr<views::Label, ExperimentalAsh> label_;
|
||||
raw_ptr<views::Button, ExperimentalAsh> change_button_ = nullptr;
|
||||
};
|
||||
|
||||
} // namespace ash
|
||||
|
||||
#endif // ASH_SYSTEM_UNIFIED_NOTIFICATION_HIDDEN_VIEW_H_
|
@ -1,221 +0,0 @@
|
||||
// Copyright 2019 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "ash/system/unified/page_indicator_view.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "ash/app_list/app_list_metrics.h"
|
||||
#include "ash/public/cpp/pagination/pagination_model.h"
|
||||
#include "ash/strings/grit/ash_strings.h"
|
||||
#include "ash/style/ash_color_provider.h"
|
||||
#include "ash/style/color_util.h"
|
||||
#include "ash/style/style_util.h"
|
||||
#include "ash/system/tray/tray_popup_utils.h"
|
||||
#include "ash/system/unified/unified_system_tray_controller.h"
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/i18n/number_formatting.h"
|
||||
#include "base/metrics/histogram_macros.h"
|
||||
#include "third_party/skia/include/core/SkPath.h"
|
||||
#include "ui/accessibility/ax_enums.mojom.h"
|
||||
#include "ui/base/l10n/l10n_util.h"
|
||||
#include "ui/compositor/layer.h"
|
||||
#include "ui/gfx/animation/throb_animation.h"
|
||||
#include "ui/gfx/canvas.h"
|
||||
#include "ui/gfx/geometry/insets.h"
|
||||
#include "ui/gfx/geometry/skia_conversions.h"
|
||||
#include "ui/views/animation/ink_drop.h"
|
||||
#include "ui/views/background.h"
|
||||
#include "ui/views/controls/button/button.h"
|
||||
#include "ui/views/controls/highlight_path_generator.h"
|
||||
#include "ui/views/layout/box_layout.h"
|
||||
|
||||
namespace ash {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr int kUnifiedPageIndicatorButtonRadius = 3;
|
||||
constexpr int kInkDropRadius = 3 * kUnifiedPageIndicatorButtonRadius;
|
||||
|
||||
} // namespace
|
||||
|
||||
// Button internally used in PageIndicatorView. Each button
|
||||
// stores a page number which it switches to if pressed.
|
||||
class PageIndicatorView::PageIndicatorButton : public views::Button {
|
||||
public:
|
||||
PageIndicatorButton(UnifiedSystemTrayController* controller, int page)
|
||||
: views::Button(base::BindRepeating(
|
||||
&UnifiedSystemTrayController::HandlePageSwitchAction,
|
||||
base::Unretained(controller),
|
||||
page)) {
|
||||
SetFocusBehavior(views::View::FocusBehavior::ACCESSIBLE_ONLY);
|
||||
views::InstallFixedSizeCircleHighlightPathGenerator(this, kInkDropRadius);
|
||||
|
||||
const gfx::Point center = GetLocalBounds().CenterPoint();
|
||||
const gfx::Rect bounds(center.x() - kInkDropRadius,
|
||||
center.y() - kInkDropRadius, 2 * kInkDropRadius,
|
||||
2 * kInkDropRadius);
|
||||
StyleUtil::SetUpInkDropForButton(this, GetLocalBounds().InsetsFrom(bounds),
|
||||
/*highlight_on_hover=*/true,
|
||||
/*highlight_on_focus=*/false);
|
||||
}
|
||||
|
||||
PageIndicatorButton(const PageIndicatorButton&) = delete;
|
||||
PageIndicatorButton& operator=(const PageIndicatorButton&) = delete;
|
||||
|
||||
~PageIndicatorButton() override {}
|
||||
|
||||
void SetSelected(bool selected) {
|
||||
if (selected == selected_)
|
||||
return;
|
||||
|
||||
selected_ = selected;
|
||||
SchedulePaint();
|
||||
if (selected)
|
||||
NotifyAccessibilityEvent(ax::mojom::Event::kAlert, true);
|
||||
}
|
||||
|
||||
// views::View:
|
||||
gfx::Size CalculatePreferredSize() const override {
|
||||
return gfx::Size(kInkDropRadius * 2, kInkDropRadius * 2);
|
||||
}
|
||||
|
||||
// views::Button:
|
||||
const char* GetClassName() const override { return "PageIndicatorView"; }
|
||||
|
||||
// views::Button:
|
||||
void PaintButtonContents(gfx::Canvas* canvas) override {
|
||||
gfx::Rect rect(GetContentsBounds());
|
||||
|
||||
const SkColor selected_color =
|
||||
AshColorProvider::Get()->GetContentLayerColor(
|
||||
AshColorProvider::ContentLayerType::kIconColorPrimary);
|
||||
cc::PaintFlags flags;
|
||||
flags.setAntiAlias(true);
|
||||
flags.setStyle(cc::PaintFlags::kFill_Style);
|
||||
flags.setColor(selected_ ? selected_color
|
||||
: ColorUtil::GetDisabledColor(selected_color));
|
||||
canvas->DrawCircle(rect.CenterPoint(), kUnifiedPageIndicatorButtonRadius,
|
||||
flags);
|
||||
}
|
||||
|
||||
// views::Button:
|
||||
void OnThemeChanged() override {
|
||||
views::Button::OnThemeChanged();
|
||||
StyleUtil::ConfigureInkDropAttributes(
|
||||
this, StyleUtil::kBaseColor | StyleUtil::kInkDropOpacity |
|
||||
StyleUtil::kHighlightOpacity);
|
||||
SchedulePaint();
|
||||
}
|
||||
|
||||
bool selected() const { return selected_; }
|
||||
|
||||
protected:
|
||||
// views::Button:
|
||||
void NotifyClick(const ui::Event& event) override {
|
||||
Button::NotifyClick(event);
|
||||
views::InkDrop::Get(this)->GetInkDrop()->AnimateToState(
|
||||
views::InkDropState::ACTION_TRIGGERED);
|
||||
}
|
||||
|
||||
private:
|
||||
bool selected_ = false;
|
||||
};
|
||||
|
||||
PageIndicatorView::PageIndicatorView(UnifiedSystemTrayController* controller,
|
||||
bool initially_expanded)
|
||||
: controller_(controller),
|
||||
model_(controller->model()->pagination_model()),
|
||||
expanded_amount_(initially_expanded ? 1 : 0),
|
||||
buttons_container_(new views::View) {
|
||||
SetVisible(initially_expanded);
|
||||
|
||||
buttons_container_->SetLayoutManager(std::make_unique<views::BoxLayout>(
|
||||
views::BoxLayout::Orientation::kHorizontal, gfx::Insets()));
|
||||
buttons_container_->SetPaintToLayer();
|
||||
buttons_container_->layer()->SetFillsBoundsOpaquely(false);
|
||||
|
||||
AddChildView(buttons_container_.get());
|
||||
|
||||
TotalPagesChanged(0, model_->total_pages());
|
||||
|
||||
DCHECK(model_);
|
||||
model_->AddObserver(this);
|
||||
}
|
||||
|
||||
PageIndicatorView::~PageIndicatorView() {
|
||||
model_->RemoveObserver(this);
|
||||
}
|
||||
|
||||
gfx::Size PageIndicatorView::CalculatePreferredSize() const {
|
||||
return gfx::Size(kTrayMenuWidth, kPageIndicatorViewMaxHeight);
|
||||
}
|
||||
|
||||
void PageIndicatorView::Layout() {
|
||||
gfx::Rect rect(GetContentsBounds());
|
||||
|
||||
gfx::Size buttons_container_size(buttons_container_->GetPreferredSize());
|
||||
rect.ClampToCenteredSize(buttons_container_size);
|
||||
buttons_container_->SetBoundsRect(rect);
|
||||
}
|
||||
|
||||
const char* PageIndicatorView::GetClassName() const {
|
||||
return "PageIndicatorView";
|
||||
}
|
||||
|
||||
void PageIndicatorView::SetExpandedAmount(double expanded_amount) {
|
||||
DCHECK(0.0 <= expanded_amount && expanded_amount <= 1.0);
|
||||
SetVisible(expanded_amount > 0.0);
|
||||
expanded_amount_ = expanded_amount;
|
||||
// TODO(amehfooz): Confirm animation curve with UX.
|
||||
buttons_container_->layer()->SetOpacity(
|
||||
std::max(0., 6 * expanded_amount_ - 5.));
|
||||
if (CalculatePreferredSize() != size())
|
||||
InvalidateLayout();
|
||||
}
|
||||
|
||||
int PageIndicatorView::GetExpandedHeight() {
|
||||
return buttons_container_->GetPreferredSize().height();
|
||||
}
|
||||
|
||||
void PageIndicatorView::TotalPagesChanged(int previous_page_count,
|
||||
int new_page_count) {
|
||||
DCHECK(model_);
|
||||
|
||||
buttons_container_->RemoveAllChildViews();
|
||||
for (int i = 0; i < model_->total_pages(); ++i) {
|
||||
PageIndicatorButton* button = new PageIndicatorButton(controller_, i);
|
||||
button->SetAccessibleName(l10n_util::GetStringFUTF16(
|
||||
IDS_APP_LIST_PAGE_SWITCHER, base::FormatNumber(i + 1),
|
||||
base::FormatNumber(model_->total_pages())));
|
||||
button->SetSelected(i == model_->selected_page());
|
||||
buttons_container_->AddChildView(button);
|
||||
}
|
||||
buttons_container_->SetVisible(model_->total_pages() > 1);
|
||||
Layout();
|
||||
}
|
||||
|
||||
PageIndicatorView::PageIndicatorButton* PageIndicatorView::GetButtonByIndex(
|
||||
int index) {
|
||||
return static_cast<PageIndicatorButton*>(
|
||||
buttons_container_->children().at(index));
|
||||
}
|
||||
|
||||
void PageIndicatorView::SelectedPageChanged(int old_selected,
|
||||
int new_selected) {
|
||||
size_t total_children = buttons_container_->children().size();
|
||||
|
||||
if (old_selected >= 0 && static_cast<size_t>(old_selected) < total_children)
|
||||
GetButtonByIndex(old_selected)->SetSelected(false);
|
||||
if (new_selected >= 0 && static_cast<size_t>(new_selected) < total_children)
|
||||
GetButtonByIndex(new_selected)->SetSelected(true);
|
||||
}
|
||||
|
||||
bool PageIndicatorView::IsPageSelectedForTesting(int index) {
|
||||
return GetButtonByIndex(index)->selected();
|
||||
}
|
||||
|
||||
} // namespace ash
|
@ -1,73 +0,0 @@
|
||||
// Copyright 2019 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ASH_SYSTEM_UNIFIED_PAGE_INDICATOR_VIEW_H_
|
||||
#define ASH_SYSTEM_UNIFIED_PAGE_INDICATOR_VIEW_H_
|
||||
|
||||
#include "ash/ash_export.h"
|
||||
#include "ash/public/cpp/pagination/pagination_model_observer.h"
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "ui/views/view.h"
|
||||
|
||||
namespace ash {
|
||||
|
||||
class PaginationModel;
|
||||
class UnifiedSystemTrayController;
|
||||
|
||||
// PageIndicatorView represents its underlying PaginationModel with a button
|
||||
// strip. Each page in the PaginationModel has a button in the strip and
|
||||
// when the button is clicked, the corresponding page becomes selected.
|
||||
class ASH_EXPORT PageIndicatorView : public views::View,
|
||||
public PaginationModelObserver {
|
||||
public:
|
||||
PageIndicatorView(UnifiedSystemTrayController* controller,
|
||||
bool initially_expanded);
|
||||
|
||||
PageIndicatorView(const PageIndicatorView&) = delete;
|
||||
PageIndicatorView& operator=(const PageIndicatorView&) = delete;
|
||||
|
||||
~PageIndicatorView() override;
|
||||
|
||||
// Change the expanded state. 0.0 if collapsed, and 1.0 if expanded.
|
||||
// Otherwise, it shows an intermediate state while animating.
|
||||
void SetExpandedAmount(double expanded_amount);
|
||||
|
||||
// Returns the height of this view when the tray is fully expanded.
|
||||
int GetExpandedHeight();
|
||||
|
||||
// views::View:
|
||||
gfx::Size CalculatePreferredSize() const override;
|
||||
void Layout() override;
|
||||
const char* GetClassName() const override;
|
||||
|
||||
private:
|
||||
friend class PageIndicatorViewTest;
|
||||
|
||||
class PageIndicatorButton;
|
||||
|
||||
// PaginationModelObserver:
|
||||
void TotalPagesChanged(int previous_page_count, int new_page_count) override;
|
||||
void SelectedPageChanged(int old_selected, int new_selected) override;
|
||||
|
||||
bool IsPageSelectedForTesting(int index);
|
||||
views::View* buttons_container() { return buttons_container_; }
|
||||
|
||||
PageIndicatorButton* GetButtonByIndex(int index);
|
||||
|
||||
const raw_ptr<UnifiedSystemTrayController,
|
||||
DanglingUntriaged | ExperimentalAsh>
|
||||
controller_;
|
||||
|
||||
// Owned by UnifiedSystemTrayModel.
|
||||
const raw_ptr<PaginationModel, ExperimentalAsh> model_;
|
||||
|
||||
double expanded_amount_;
|
||||
|
||||
// Owned by views hierarchy.
|
||||
raw_ptr<views::View, ExperimentalAsh> buttons_container_;
|
||||
};
|
||||
|
||||
} // namespace ash
|
||||
|
||||
#endif // ASH_SYSTEM_UNIFIED_PAGE_INDICATOR_VIEW_H_
|
@ -1,114 +0,0 @@
|
||||
// Copyright 2019 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "ash/system/unified/page_indicator_view.h"
|
||||
|
||||
#include "ash/public/cpp/pagination/pagination_model.h"
|
||||
#include "ash/session/test_session_controller_client.h"
|
||||
#include "ash/system/unified/unified_system_tray_controller.h"
|
||||
#include "ash/system/unified/unified_system_tray_model.h"
|
||||
#include "ash/system/unified/unified_system_tray_view.h"
|
||||
#include "ash/test/ash_test_base.h"
|
||||
#include "base/memory/scoped_refptr.h"
|
||||
|
||||
namespace ash {
|
||||
|
||||
namespace {
|
||||
int kPageCount = 10;
|
||||
}
|
||||
|
||||
class PageIndicatorViewTest : public NoSessionAshTestBase {
|
||||
public:
|
||||
PageIndicatorViewTest() = default;
|
||||
|
||||
PageIndicatorViewTest(const PageIndicatorViewTest&) = delete;
|
||||
PageIndicatorViewTest& operator=(const PageIndicatorViewTest&) = delete;
|
||||
|
||||
~PageIndicatorViewTest() override = default;
|
||||
|
||||
void SetUp() override {
|
||||
NoSessionAshTestBase::SetUp();
|
||||
|
||||
model_ = base::MakeRefCounted<UnifiedSystemTrayModel>(nullptr);
|
||||
controller_ = std::make_unique<UnifiedSystemTrayController>(model_.get());
|
||||
|
||||
unified_view_ = std::make_unique<UnifiedSystemTrayView>(
|
||||
controller_.get(), true /* initially_expanded */);
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
controller_.reset();
|
||||
unified_view_.reset();
|
||||
model_.reset();
|
||||
NoSessionAshTestBase::TearDown();
|
||||
}
|
||||
|
||||
protected:
|
||||
int GetButtonCount() {
|
||||
return page_indicator_view()->buttons_container()->children().size();
|
||||
}
|
||||
|
||||
bool IsPageSelected(int index) {
|
||||
return page_indicator_view()->IsPageSelectedForTesting(index);
|
||||
}
|
||||
|
||||
PaginationModel* pagination_model() { return model_->pagination_model(); }
|
||||
PageIndicatorView* page_indicator_view() {
|
||||
return unified_view_->page_indicator_view_for_test();
|
||||
}
|
||||
UnifiedSystemTrayView* unified_view() { return unified_view_.get(); }
|
||||
|
||||
private:
|
||||
scoped_refptr<UnifiedSystemTrayModel> model_;
|
||||
std::unique_ptr<UnifiedSystemTrayController> controller_;
|
||||
std::unique_ptr<UnifiedSystemTrayView> unified_view_;
|
||||
};
|
||||
|
||||
// Number of buttons is equal to total pages in PaginationModel.
|
||||
TEST_F(PageIndicatorViewTest, ButtonForEachPage) {
|
||||
for (int i = 0; i < kPageCount; i++) {
|
||||
pagination_model()->SetTotalPages(i);
|
||||
EXPECT_EQ(i, GetButtonCount());
|
||||
}
|
||||
}
|
||||
|
||||
// Single button corresponding to page in PaginationModel is set to selected.
|
||||
TEST_F(PageIndicatorViewTest, SelectPage) {
|
||||
pagination_model()->SetTotalPages(kPageCount);
|
||||
|
||||
for (int i = 0; i < kPageCount; i++) {
|
||||
pagination_model()->SelectPage(i, false /* animate */);
|
||||
EXPECT_TRUE(IsPageSelected(i));
|
||||
for (int j = 0; j < kPageCount; j++) {
|
||||
if (i == j)
|
||||
continue;
|
||||
|
||||
EXPECT_FALSE(IsPageSelected(j));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(PageIndicatorViewTest, ExpandAndCollapse) {
|
||||
int cur_height;
|
||||
int prev_height;
|
||||
double expanded_increments[] = {0.90, 0.75, 0.5, 0.25, 0.10};
|
||||
|
||||
pagination_model()->SetTotalPages(kPageCount);
|
||||
|
||||
// PageIndicatorView has decreasing height as the expanded amount is
|
||||
// decreased.
|
||||
prev_height = page_indicator_view()->GetContentsBounds().height();
|
||||
for (double i : expanded_increments) {
|
||||
unified_view()->SetExpandedAmount(i);
|
||||
cur_height = page_indicator_view()->GetContentsBounds().height();
|
||||
EXPECT_GE(prev_height, cur_height);
|
||||
prev_height = cur_height;
|
||||
}
|
||||
|
||||
// PageIndicatorView has zero height when collapsed.
|
||||
unified_view()->SetExpandedAmount(0.00);
|
||||
EXPECT_EQ(page_indicator_view()->GetContentsBounds().height(), 0);
|
||||
}
|
||||
|
||||
} // namespace ash
|
@ -14,13 +14,10 @@
|
||||
#include "ash/system/tray/tray_constants.h"
|
||||
#include "ash/system/tray/tray_detailed_view.h"
|
||||
#include "ash/system/unified/detailed_view_controller.h"
|
||||
#include "ash/system/unified/feature_pod_button.h"
|
||||
#include "ash/system/unified/feature_tile.h"
|
||||
#include "ash/system/unified/feature_tiles_container_view.h"
|
||||
#include "ash/system/unified/page_indicator_view.h"
|
||||
#include "ash/system/unified/quick_settings_footer.h"
|
||||
#include "ash/system/unified/quick_settings_header.h"
|
||||
#include "ash/system/unified/unified_system_info_view.h"
|
||||
#include "ash/system/unified/unified_system_tray_controller.h"
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/memory/raw_ptr.h"
|
||||
@ -302,12 +299,6 @@ void QuickSettingsView::TotalPagesChanged(int previous_page_count,
|
||||
pagination_view_->SetVisible(new_page_count > 1);
|
||||
}
|
||||
|
||||
void QuickSettingsView::OnGestureEvent(ui::GestureEvent* event) {
|
||||
if (event->type() == ui::ET_SCROLL_FLING_START) {
|
||||
controller_->Fling(event->details().velocity_y());
|
||||
}
|
||||
}
|
||||
|
||||
BEGIN_METADATA(QuickSettingsView, views::View)
|
||||
END_METADATA
|
||||
|
||||
|
@ -100,9 +100,6 @@ class ASH_EXPORT QuickSettingsView : public views::View,
|
||||
// PaginationModelObserver:
|
||||
void TotalPagesChanged(int previous_page_count, int new_page_count) override;
|
||||
|
||||
// views::View:
|
||||
void OnGestureEvent(ui::GestureEvent* event) override;
|
||||
|
||||
FeatureTilesContainerView* feature_tiles_container() {
|
||||
return feature_tiles_container_;
|
||||
}
|
||||
|
@ -59,10 +59,6 @@ bool SystemTrayTestApi::IsTrayBubbleOpen() {
|
||||
return GetTray()->IsBubbleShown();
|
||||
}
|
||||
|
||||
bool SystemTrayTestApi::IsTrayBubbleExpanded() {
|
||||
return GetTray()->bubble_->controller_->IsExpanded();
|
||||
}
|
||||
|
||||
void SystemTrayTestApi::ShowBubble() {
|
||||
GetTray()->ShowBubble();
|
||||
}
|
||||
@ -71,14 +67,6 @@ void SystemTrayTestApi::CloseBubble() {
|
||||
GetTray()->CloseBubble();
|
||||
}
|
||||
|
||||
void SystemTrayTestApi::CollapseBubble() {
|
||||
GetTray()->EnsureQuickSettingsCollapsed(true /*animate*/);
|
||||
}
|
||||
|
||||
void SystemTrayTestApi::ExpandBubble() {
|
||||
GetTray()->EnsureBubbleExpanded();
|
||||
}
|
||||
|
||||
void SystemTrayTestApi::ShowAccessibilityDetailedView() {
|
||||
GetTray()->ShowBubble();
|
||||
GetTray()->bubble_->controller_->ShowAccessibilityDetailedView();
|
||||
@ -86,7 +74,7 @@ void SystemTrayTestApi::ShowAccessibilityDetailedView() {
|
||||
|
||||
void SystemTrayTestApi::ShowNetworkDetailedView() {
|
||||
GetTray()->ShowBubble();
|
||||
GetTray()->bubble_->controller_->ShowNetworkDetailedView(true /* force */);
|
||||
GetTray()->bubble_->controller_->ShowNetworkDetailedView();
|
||||
}
|
||||
|
||||
AccessibilityDetailedView* SystemTrayTestApi::GetAccessibilityDetailedView() {
|
||||
|
@ -1,330 +0,0 @@
|
||||
// Copyright 2018 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "ash/system/unified/top_shortcuts_view.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <numeric>
|
||||
|
||||
#include "ash/constants/ash_features.h"
|
||||
#include "ash/constants/ash_pref_names.h"
|
||||
#include "ash/constants/quick_settings_catalogs.h"
|
||||
#include "ash/public/cpp/ash_view_ids.h"
|
||||
#include "ash/resources/vector_icons/vector_icons.h"
|
||||
#include "ash/session/session_controller_impl.h"
|
||||
#include "ash/shell.h"
|
||||
#include "ash/shutdown_controller_impl.h"
|
||||
#include "ash/strings/grit/ash_strings.h"
|
||||
#include "ash/style/icon_button.h"
|
||||
#include "ash/style/pill_button.h"
|
||||
#include "ash/system/tray/tray_constants.h"
|
||||
#include "ash/system/tray/tray_popup_utils.h"
|
||||
#include "ash/system/unified/buttons.h"
|
||||
#include "ash/system/unified/collapse_button.h"
|
||||
#include "ash/system/unified/quick_settings_metrics_util.h"
|
||||
#include "ash/system/unified/unified_system_tray_controller.h"
|
||||
#include "ash/system/unified/user_chooser_detailed_view_controller.h"
|
||||
#include "ash/system/unified/user_chooser_view.h"
|
||||
#include "ash/system/user/login_status.h"
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/ranges/algorithm.h"
|
||||
#include "components/prefs/pref_registry_simple.h"
|
||||
#include "components/prefs/pref_service.h"
|
||||
#include "components/vector_icons/vector_icons.h"
|
||||
#include "ui/color/color_id.h"
|
||||
#include "ui/gfx/paint_vector_icon.h"
|
||||
#include "ui/views/controls/button/button.h"
|
||||
#include "ui/views/controls/highlight_path_generator.h"
|
||||
#include "ui/views/layout/box_layout.h"
|
||||
#include "ui/views/layout/fill_layout.h"
|
||||
|
||||
namespace ash {
|
||||
|
||||
TopShortcutButtonContainer::TopShortcutButtonContainer() = default;
|
||||
|
||||
TopShortcutButtonContainer::~TopShortcutButtonContainer() = default;
|
||||
|
||||
// Buttons are equally spaced by the default value, but the gap will be
|
||||
// narrowed evenly when the parent view is not large enough.
|
||||
void TopShortcutButtonContainer::Layout() {
|
||||
const gfx::Rect child_area = GetContentsBounds();
|
||||
|
||||
views::View::Views visible_children;
|
||||
base::ranges::copy_if(
|
||||
children(), std::back_inserter(visible_children), [](const auto* v) {
|
||||
return v->GetVisible() && (v->GetPreferredSize().width() > 0);
|
||||
});
|
||||
if (visible_children.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const int visible_child_width =
|
||||
std::accumulate(visible_children.cbegin(), visible_children.cend(), 0,
|
||||
[](int width, const auto* v) {
|
||||
return width + v->GetPreferredSize().width();
|
||||
});
|
||||
|
||||
int spacing = 0;
|
||||
if (visible_children.size() > 1) {
|
||||
spacing = (child_area.width() - visible_child_width) /
|
||||
(static_cast<int>(visible_children.size()) - 1);
|
||||
spacing = std::clamp(spacing, kUnifiedTopShortcutButtonMinSpacing,
|
||||
kUnifiedTopShortcutButtonDefaultSpacing);
|
||||
}
|
||||
|
||||
int x = child_area.x();
|
||||
int y = child_area.y() + kUnifiedTopShortcutContainerTopPadding +
|
||||
kUnifiedCircularButtonFocusPadding.bottom();
|
||||
for (auto* child : visible_children) {
|
||||
int child_y = y;
|
||||
int width = child->GetPreferredSize().width();
|
||||
if (child == user_avatar_button_) {
|
||||
x -= kUnifiedCircularButtonFocusPadding.left();
|
||||
child_y -= kUnifiedCircularButtonFocusPadding.bottom();
|
||||
} else if (child == sign_out_button_) {
|
||||
// When there's not enough space, shrink the sign-out button.
|
||||
const int remainder =
|
||||
child_area.width() -
|
||||
(static_cast<int>(visible_children.size()) - 1) * spacing -
|
||||
(visible_child_width - width);
|
||||
width = std::clamp(width, 0, std::max(0, remainder));
|
||||
}
|
||||
|
||||
child->SetBounds(x, child_y, width, child->GetHeightForWidth(width));
|
||||
x += width + spacing;
|
||||
|
||||
if (child == user_avatar_button_) {
|
||||
x -= kUnifiedCircularButtonFocusPadding.right();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gfx::Size TopShortcutButtonContainer::CalculatePreferredSize() const {
|
||||
int total_horizontal_size = 0;
|
||||
int num_visible = 0;
|
||||
for (const auto* child : children()) {
|
||||
if (!child->GetVisible()) {
|
||||
continue;
|
||||
}
|
||||
int child_horizontal_size = child->GetPreferredSize().width();
|
||||
if (child_horizontal_size == 0) {
|
||||
continue;
|
||||
}
|
||||
total_horizontal_size += child_horizontal_size;
|
||||
num_visible++;
|
||||
}
|
||||
int width =
|
||||
(num_visible == 0)
|
||||
? 0
|
||||
: total_horizontal_size +
|
||||
(num_visible - 1) * kUnifiedTopShortcutButtonDefaultSpacing;
|
||||
int height = kTrayItemSize + kUnifiedCircularButtonFocusPadding.height() +
|
||||
kUnifiedTopShortcutContainerTopPadding;
|
||||
return gfx::Size(width, height);
|
||||
}
|
||||
|
||||
const char* TopShortcutButtonContainer::GetClassName() const {
|
||||
return "TopShortcutButtonContainer";
|
||||
}
|
||||
|
||||
views::View* TopShortcutButtonContainer::AddUserAvatarButton(
|
||||
std::unique_ptr<views::View> user_avatar_button) {
|
||||
user_avatar_button_ = AddChildView(std::move(user_avatar_button));
|
||||
return user_avatar_button_;
|
||||
}
|
||||
|
||||
views::Button* TopShortcutButtonContainer::AddSignOutButton(
|
||||
std::unique_ptr<views::Button> sign_out_button) {
|
||||
sign_out_button_ = AddChildView(std::move(sign_out_button));
|
||||
return sign_out_button_;
|
||||
}
|
||||
|
||||
TopShortcutsView::TopShortcutsView(UnifiedSystemTrayController* controller) {
|
||||
DCHECK(controller);
|
||||
|
||||
#if DCHECK_IS_ON()
|
||||
// Only need it for `DCHECK` in `OnChildViewAdded`.
|
||||
AddObserver(this);
|
||||
#endif // DCHECK_IS_ON()
|
||||
|
||||
auto* layout = SetLayoutManager(std::make_unique<views::BoxLayout>(
|
||||
views::BoxLayout::Orientation::kHorizontal, kUnifiedTopShortcutPadding,
|
||||
kUnifiedTopShortcutSpacing));
|
||||
layout->set_cross_axis_alignment(
|
||||
views::BoxLayout::CrossAxisAlignment::kStart);
|
||||
auto button_container = std::make_unique<TopShortcutButtonContainer>();
|
||||
|
||||
Shell* shell = Shell::Get();
|
||||
|
||||
bool is_on_login_screen =
|
||||
shell->session_controller()->login_status() == LoginStatus::NOT_LOGGED_IN;
|
||||
bool can_show_settings = TrayPopupUtils::CanOpenWebUISettings();
|
||||
bool can_lock_screen = shell->session_controller()->CanLockScreen();
|
||||
|
||||
if (!is_on_login_screen) {
|
||||
user_avatar_button_ = button_container->AddUserAvatarButton(
|
||||
std::make_unique<UserAvatarButton>(base::BindRepeating(
|
||||
[](UnifiedSystemTrayController* controller) {
|
||||
quick_settings_metrics_util::RecordQsButtonActivated(
|
||||
QsButtonCatalogName::kAvatarButton);
|
||||
controller->ShowUserChooserView();
|
||||
},
|
||||
base::Unretained(controller))));
|
||||
user_avatar_button_->SetEnabled(
|
||||
UserChooserDetailedViewController::IsUserChooserEnabled());
|
||||
user_avatar_button_->SetID(VIEW_ID_QS_USER_AVATAR_BUTTON);
|
||||
|
||||
sign_out_button_ =
|
||||
button_container->AddSignOutButton(std::make_unique<PillButton>(
|
||||
base::BindRepeating(
|
||||
[](UnifiedSystemTrayController* controller) {
|
||||
quick_settings_metrics_util::RecordQsButtonActivated(
|
||||
QsButtonCatalogName::kSignOutButton);
|
||||
controller->HandleSignOutAction();
|
||||
},
|
||||
base::Unretained(controller)),
|
||||
user::GetLocalizedSignOutStringForStatus(
|
||||
Shell::Get()->session_controller()->login_status(),
|
||||
/*multiline=*/false),
|
||||
PillButton::Type::kDefaultWithoutIcon,
|
||||
/*icon=*/nullptr));
|
||||
sign_out_button_->SetID(VIEW_ID_QS_SIGN_OUT_BUTTON);
|
||||
}
|
||||
bool reboot = shell->shutdown_controller()->reboot_on_shutdown();
|
||||
power_button_ = button_container->AddChildView(std::make_unique<IconButton>(
|
||||
base::BindRepeating(
|
||||
[](UnifiedSystemTrayController* controller) {
|
||||
quick_settings_metrics_util::RecordQsButtonActivated(
|
||||
QsButtonCatalogName::kPowerButton);
|
||||
controller->HandlePowerAction();
|
||||
},
|
||||
base::Unretained(controller)),
|
||||
IconButton::Type::kMedium, &kUnifiedMenuPowerIcon,
|
||||
reboot ? IDS_ASH_STATUS_TRAY_REBOOT : IDS_ASH_STATUS_TRAY_SHUTDOWN));
|
||||
power_button_->SetID(VIEW_ID_QS_POWER_BUTTON);
|
||||
|
||||
if (can_show_settings && can_lock_screen) {
|
||||
lock_button_ = button_container->AddChildView(std::make_unique<IconButton>(
|
||||
base::BindRepeating(
|
||||
[](UnifiedSystemTrayController* controller) {
|
||||
quick_settings_metrics_util::RecordQsButtonActivated(
|
||||
QsButtonCatalogName::kLockButton);
|
||||
controller->HandleLockAction();
|
||||
},
|
||||
base::Unretained(controller)),
|
||||
IconButton::Type::kMedium, &kUnifiedMenuLockIcon,
|
||||
IDS_ASH_STATUS_TRAY_LOCK));
|
||||
lock_button_->SetID(VIEW_ID_QS_LOCK_BUTTON);
|
||||
}
|
||||
|
||||
if (can_show_settings) {
|
||||
settings_button_ =
|
||||
button_container->AddChildView(std::make_unique<IconButton>(
|
||||
base::BindRepeating(
|
||||
[](UnifiedSystemTrayController* controller) {
|
||||
quick_settings_metrics_util::RecordQsButtonActivated(
|
||||
QsButtonCatalogName::kSettingsButton);
|
||||
controller->HandleSettingsAction();
|
||||
},
|
||||
base::Unretained(controller)),
|
||||
IconButton::Type::kMedium, &vector_icons::kSettingsOutlineIcon,
|
||||
IDS_ASH_STATUS_TRAY_SETTINGS));
|
||||
settings_button_->SetID(VIEW_ID_QS_SETTINGS_BUTTON);
|
||||
|
||||
local_state_pref_change_registrar_.Init(Shell::Get()->local_state());
|
||||
local_state_pref_change_registrar_.Add(
|
||||
prefs::kOsSettingsEnabled,
|
||||
base::BindRepeating(&TopShortcutsView::UpdateSettingsButtonState,
|
||||
base::Unretained(this)));
|
||||
UpdateSettingsButtonState();
|
||||
}
|
||||
|
||||
container_ = AddChildView(std::move(button_container));
|
||||
|
||||
// |collapse_button_| should be right-aligned, so we make the buttons
|
||||
// container flex occupying all remaining space.
|
||||
layout->SetFlexForView(container_, 1);
|
||||
|
||||
if (features::IsQsRevampEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto collapse_button_container = std::make_unique<views::View>();
|
||||
collapse_button_ = collapse_button_container->AddChildView(
|
||||
std::make_unique<CollapseButton>(base::BindRepeating(
|
||||
[](UnifiedSystemTrayController* controller) {
|
||||
quick_settings_metrics_util::RecordQsButtonActivated(
|
||||
QsButtonCatalogName::kCollapseButton);
|
||||
controller->ToggleExpanded();
|
||||
},
|
||||
base::Unretained(controller))));
|
||||
collapse_button_->SetID(VIEW_ID_QS_COLLAPSE_BUTTON);
|
||||
const gfx::Size collapse_button_size = collapse_button_->GetPreferredSize();
|
||||
collapse_button_container->SetPreferredSize(
|
||||
gfx::Size(collapse_button_size.width(),
|
||||
collapse_button_size.height() + kUnifiedTopShortcutSpacing));
|
||||
collapse_button_->SetBoundsRect(gfx::Rect(
|
||||
gfx::Point(0, kUnifiedTopShortcutSpacing), collapse_button_size));
|
||||
|
||||
AddChildView(std::move(collapse_button_container));
|
||||
}
|
||||
|
||||
TopShortcutsView::~TopShortcutsView() {
|
||||
#if DCHECK_IS_ON()
|
||||
// Only need it for `DCHECK` in `OnChildViewAdded`.
|
||||
RemoveObserver(this);
|
||||
#endif // DCHECK_IS_ON()
|
||||
}
|
||||
|
||||
// static
|
||||
void TopShortcutsView::RegisterLocalStatePrefs(PrefRegistrySimple* registry) {
|
||||
registry->RegisterBooleanPref(prefs::kOsSettingsEnabled, true);
|
||||
}
|
||||
|
||||
void TopShortcutsView::SetExpandedAmount(double expanded_amount) {
|
||||
if (features::IsQsRevampEnabled()) {
|
||||
return;
|
||||
}
|
||||
collapse_button_->SetExpandedAmount(expanded_amount);
|
||||
}
|
||||
|
||||
const char* TopShortcutsView::GetClassName() const {
|
||||
return "TopShortcutsView";
|
||||
}
|
||||
|
||||
void TopShortcutsView::OnChildViewAdded(View* observed_view, View* child) {
|
||||
if (observed_view != this) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (child->children().empty()) {
|
||||
DCHECK(child->GetID() >= VIEW_ID_QS_MIN && child->GetID() <= VIEW_ID_QS_MAX)
|
||||
<< "All buttons directly added to this view must have a view ID with "
|
||||
"VIEW_ID_QS_*, and record a metric using QsButtonCatalogName (see "
|
||||
"other usages of the catalog names for an example)";
|
||||
return;
|
||||
}
|
||||
|
||||
for (View* button : child->children()) {
|
||||
DCHECK(button->GetID() >= VIEW_ID_QS_MIN &&
|
||||
button->GetID() <= VIEW_ID_QS_MAX)
|
||||
<< "All buttons directly added to each container must have a view ID "
|
||||
"with VIEW_ID_QS_*, and record a metric using QsButtonCatalogName "
|
||||
"(see other usages of the catalog names for an example)";
|
||||
}
|
||||
}
|
||||
|
||||
void TopShortcutsView::UpdateSettingsButtonState() {
|
||||
PrefService* const local_state = Shell::Get()->local_state();
|
||||
const bool settings_icon_enabled =
|
||||
local_state->GetBoolean(prefs::kOsSettingsEnabled);
|
||||
|
||||
settings_button_->SetState(settings_icon_enabled
|
||||
? views::Button::STATE_NORMAL
|
||||
: views::Button::STATE_DISABLED);
|
||||
}
|
||||
|
||||
} // namespace ash
|
@ -1,98 +0,0 @@
|
||||
// Copyright 2018 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ASH_SYSTEM_UNIFIED_TOP_SHORTCUTS_VIEW_H_
|
||||
#define ASH_SYSTEM_UNIFIED_TOP_SHORTCUTS_VIEW_H_
|
||||
|
||||
#include "ash/accessibility/accessibility_observer.h"
|
||||
#include "ash/ash_export.h"
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "components/prefs/pref_change_registrar.h"
|
||||
#include "ui/views/view.h"
|
||||
#include "ui/views/view_observer.h"
|
||||
|
||||
class PrefRegistrySimple;
|
||||
|
||||
namespace views {
|
||||
class Button;
|
||||
}
|
||||
|
||||
namespace ash {
|
||||
|
||||
class CollapseButton;
|
||||
class IconButton;
|
||||
class TopShortcutsViewTest;
|
||||
class UnifiedSystemTrayController;
|
||||
|
||||
// Container for the top shortcut buttons. The view may narrow gaps between
|
||||
// buttons when there's not enough space. When those doesn't fit in the view
|
||||
// even after that, the sign-out button will be resized.
|
||||
class TopShortcutButtonContainer : public views::View {
|
||||
public:
|
||||
TopShortcutButtonContainer();
|
||||
|
||||
TopShortcutButtonContainer(const TopShortcutButtonContainer&) = delete;
|
||||
TopShortcutButtonContainer& operator=(const TopShortcutButtonContainer&) =
|
||||
delete;
|
||||
|
||||
~TopShortcutButtonContainer() override;
|
||||
|
||||
// views::View:
|
||||
void Layout() override;
|
||||
gfx::Size CalculatePreferredSize() const override;
|
||||
const char* GetClassName() const override;
|
||||
|
||||
views::View* AddUserAvatarButton(
|
||||
std::unique_ptr<views::View> user_avatar_button);
|
||||
// Add the sign-out button, which can be resized upon layout.
|
||||
views::Button* AddSignOutButton(
|
||||
std::unique_ptr<views::Button> sign_out_button);
|
||||
|
||||
private:
|
||||
raw_ptr<views::View, ExperimentalAsh> user_avatar_button_ = nullptr;
|
||||
raw_ptr<views::Button, ExperimentalAsh> sign_out_button_ = nullptr;
|
||||
};
|
||||
|
||||
// Top shortcuts view shown on the top of UnifiedSystemTrayView.
|
||||
class ASH_EXPORT TopShortcutsView : public views::View,
|
||||
public views::ViewObserver {
|
||||
public:
|
||||
explicit TopShortcutsView(UnifiedSystemTrayController* controller);
|
||||
|
||||
TopShortcutsView(const TopShortcutsView&) = delete;
|
||||
TopShortcutsView& operator=(const TopShortcutsView&) = delete;
|
||||
~TopShortcutsView() override;
|
||||
|
||||
static void RegisterLocalStatePrefs(PrefRegistrySimple* registry);
|
||||
|
||||
// Change the expanded state. CollapseButton icon will rotate.
|
||||
void SetExpandedAmount(double expanded_amount);
|
||||
|
||||
// views::View
|
||||
const char* GetClassName() const override;
|
||||
|
||||
private:
|
||||
friend class TopShortcutsViewTest;
|
||||
|
||||
// views::ViewObserver:
|
||||
void OnChildViewAdded(View* observed_view, View* child) override;
|
||||
|
||||
// Disables/Enables the |settings_button_| based on kSettingsIconEnabled pref.
|
||||
void UpdateSettingsButtonState();
|
||||
|
||||
// Owned by views hierarchy.
|
||||
raw_ptr<views::View, ExperimentalAsh> user_avatar_button_ = nullptr;
|
||||
raw_ptr<views::Button, ExperimentalAsh> sign_out_button_ = nullptr;
|
||||
raw_ptr<TopShortcutButtonContainer, ExperimentalAsh> container_ = nullptr;
|
||||
raw_ptr<IconButton, ExperimentalAsh> lock_button_ = nullptr;
|
||||
raw_ptr<IconButton, ExperimentalAsh> settings_button_ = nullptr;
|
||||
raw_ptr<IconButton, ExperimentalAsh> power_button_ = nullptr;
|
||||
raw_ptr<CollapseButton, ExperimentalAsh> collapse_button_ = nullptr;
|
||||
|
||||
PrefChangeRegistrar local_state_pref_change_registrar_;
|
||||
};
|
||||
|
||||
} // namespace ash
|
||||
|
||||
#endif // ASH_SYSTEM_UNIFIED_TOP_SHORTCUTS_VIEW_H_
|
@ -254,7 +254,9 @@ void UnifiedSliderBubbleController::ShowBubble(SliderType slider_type) {
|
||||
}
|
||||
|
||||
if (IsAnyMainBubbleShown()) {
|
||||
tray_->EnsureBubbleExpanded();
|
||||
// If a detailed view is showing, first transit to the main view.
|
||||
tray_->bubble()->unified_system_tray_controller()->TransitionToMainView(
|
||||
false);
|
||||
|
||||
// Unlike VOLUME and BRIGHTNESS, which are shown in the main bubble view,
|
||||
// MIC slider is shown in the audio details view.
|
||||
|
@ -1,530 +0,0 @@
|
||||
// Copyright 2018 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "ash/system/unified/unified_system_info_view.h"
|
||||
|
||||
#include "ash/constants/ash_features.h"
|
||||
#include "ash/constants/quick_settings_catalogs.h"
|
||||
#include "ash/public/cpp/ash_view_ids.h"
|
||||
#include "ash/public/cpp/system_tray_client.h"
|
||||
#include "ash/session/session_controller_impl.h"
|
||||
#include "ash/shell.h"
|
||||
#include "ash/shell_delegate.h"
|
||||
#include "ash/strings/grit/ash_strings.h"
|
||||
#include "ash/style/ash_color_provider.h"
|
||||
#include "ash/system/channel_indicator/channel_indicator_quick_settings_view.h"
|
||||
#include "ash/system/channel_indicator/channel_indicator_utils.h"
|
||||
#include "ash/system/model/clock_model.h"
|
||||
#include "ash/system/model/clock_observer.h"
|
||||
#include "ash/system/model/system_tray_model.h"
|
||||
#include "ash/system/model/update_model.h"
|
||||
#include "ash/system/power/adaptive_charging_controller.h"
|
||||
#include "ash/system/power/power_status.h"
|
||||
#include "ash/system/time/calendar_metrics.h"
|
||||
#include "ash/system/tray/system_tray_notifier.h"
|
||||
#include "ash/system/tray/tray_popup_utils.h"
|
||||
#include "ash/system/unified/buttons.h"
|
||||
#include "ash/system/unified/quick_settings_metrics_util.h"
|
||||
#include "ash/system/update/eol_notice_quick_settings_view.h"
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/functional/callback_helpers.h"
|
||||
#include "base/i18n/time_formatting.h"
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "base/time/time.h"
|
||||
#include "ui/accessibility/ax_enums.mojom.h"
|
||||
#include "ui/base/l10n/l10n_util.h"
|
||||
#include "ui/base/metadata/metadata_header_macros.h"
|
||||
#include "ui/base/metadata/metadata_impl_macros.h"
|
||||
#include "ui/color/color_id.h"
|
||||
#include "ui/compositor/layer.h"
|
||||
#include "ui/views/accessibility/view_accessibility.h"
|
||||
#include "ui/views/animation/ink_drop.h"
|
||||
#include "ui/views/background.h"
|
||||
#include "ui/views/controls/button/button.h"
|
||||
#include "ui/views/controls/focus_ring.h"
|
||||
#include "ui/views/controls/label.h"
|
||||
#include "ui/views/controls/separator.h"
|
||||
#include "ui/views/layout/box_layout.h"
|
||||
#include "ui/views/layout/fill_layout.h"
|
||||
|
||||
namespace ash {
|
||||
|
||||
using ContentLayerType = AshColorProvider::ContentLayerType;
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr auto kBatteryLabelViewInsets = gfx::Insets(2);
|
||||
|
||||
// Helper function for getting the content layer color.
|
||||
inline SkColor GetContentLayerColor(ContentLayerType type) {
|
||||
return AshColorProvider::Get()->GetContentLayerColor(type);
|
||||
}
|
||||
|
||||
// Helper function for configuring label in `BatteryLabelView` and
|
||||
// `BatteryIconView`.
|
||||
void ConfigureLabel(views::Label* label, SkColor color) {
|
||||
label->SetAutoColorReadabilityEnabled(false);
|
||||
label->SetSubpixelRenderingEnabled(false);
|
||||
label->SetEnabledColor(color);
|
||||
label->GetViewAccessibility().OverrideIsIgnored(true);
|
||||
}
|
||||
|
||||
// A base class for both `BatteryLabelView` and `BatteryIconView`. It updates by
|
||||
// observing `PowerStatus`.
|
||||
class BatteryInfoViewBase : public views::Button, public PowerStatus::Observer {
|
||||
public:
|
||||
explicit BatteryInfoViewBase(UnifiedSystemTrayController* controller)
|
||||
: Button(base::BindRepeating(
|
||||
[](UnifiedSystemTrayController* controller) {
|
||||
quick_settings_metrics_util::RecordQsButtonActivated(
|
||||
QsButtonCatalogName::kBatteryButton);
|
||||
controller->HandleOpenPowerSettingsAction();
|
||||
},
|
||||
controller)) {
|
||||
PowerStatus::Get()->AddObserver(this);
|
||||
}
|
||||
BatteryInfoViewBase(const BatteryInfoViewBase&) = delete;
|
||||
BatteryInfoViewBase& operator=(const BatteryInfoViewBase&) = delete;
|
||||
~BatteryInfoViewBase() override { PowerStatus::Get()->RemoveObserver(this); }
|
||||
|
||||
// Updates the subclass view's ui when `OnPowerStatusChanged`.
|
||||
virtual void Update() = 0;
|
||||
|
||||
private:
|
||||
// views::View:
|
||||
void GetAccessibleNodeData(ui::AXNodeData* node_data) override {
|
||||
node_data->role = ax::mojom::Role::kLabelText;
|
||||
node_data->SetName(
|
||||
PowerStatus::Get()->GetAccessibleNameString(/*full_description=*/true));
|
||||
}
|
||||
|
||||
void ChildPreferredSizeChanged(views::View* child) override {
|
||||
PreferredSizeChanged();
|
||||
}
|
||||
|
||||
void ChildVisibilityChanged(views::View* child) override {
|
||||
PreferredSizeChanged();
|
||||
}
|
||||
|
||||
// PowerStatus::Observer:
|
||||
void OnPowerStatusChanged() override { Update(); }
|
||||
};
|
||||
|
||||
// A view that shows battery status.
|
||||
class BatteryLabelView : public BatteryInfoViewBase {
|
||||
public:
|
||||
BatteryLabelView(UnifiedSystemTrayController* controller,
|
||||
bool use_smart_charging_ui)
|
||||
: BatteryInfoViewBase(controller),
|
||||
use_smart_charging_ui_(use_smart_charging_ui) {
|
||||
SetID(VIEW_ID_QS_BATTERY_BUTTON);
|
||||
SetLayoutManager(std::make_unique<views::BoxLayout>(
|
||||
views::BoxLayout::Orientation::kHorizontal, kBatteryLabelViewInsets));
|
||||
views::FocusRing::Get(this)->SetColorId(
|
||||
static_cast<ui::ColorId>(ui::kColorAshFocusRing));
|
||||
|
||||
percentage_ = AddChildView(std::make_unique<views::Label>());
|
||||
auto separator = std::make_unique<views::Label>();
|
||||
separator->SetText(l10n_util::GetStringUTF16(
|
||||
IDS_ASH_STATUS_TRAY_BATTERY_STATUS_SEPARATOR));
|
||||
separator_view_ = AddChildView(std::move(separator));
|
||||
status_ = AddChildView(std::make_unique<views::Label>());
|
||||
Update();
|
||||
}
|
||||
BatteryLabelView(const BatteryLabelView&) = delete;
|
||||
BatteryLabelView& operator=(const BatteryLabelView&) = delete;
|
||||
~BatteryLabelView() override = default;
|
||||
|
||||
private:
|
||||
// views::View:
|
||||
void OnThemeChanged() override {
|
||||
views::View::OnThemeChanged();
|
||||
const auto color =
|
||||
GetContentLayerColor(ContentLayerType::kTextColorSecondary);
|
||||
ConfigureLabel(percentage_, color);
|
||||
ConfigureLabel(separator_view_, color);
|
||||
ConfigureLabel(status_, color);
|
||||
}
|
||||
|
||||
// BatteryInfoViewBase:
|
||||
void Update() override {
|
||||
std::u16string percentage_text;
|
||||
std::u16string status_text;
|
||||
std::tie(percentage_text, status_text) =
|
||||
PowerStatus::Get()->GetStatusStrings();
|
||||
|
||||
percentage_->SetText(percentage_text);
|
||||
status_->SetText(status_text);
|
||||
|
||||
percentage_->SetVisible(!percentage_text.empty() &&
|
||||
!use_smart_charging_ui_);
|
||||
separator_view_->SetVisible(!percentage_text.empty() &&
|
||||
!use_smart_charging_ui_ &&
|
||||
!status_text.empty());
|
||||
status_->SetVisible(!status_text.empty());
|
||||
}
|
||||
|
||||
// Owned by this view, which is owned by views hierarchy.
|
||||
raw_ptr<views::Label, ExperimentalAsh> percentage_ = nullptr;
|
||||
raw_ptr<views::Label, ExperimentalAsh> separator_view_ = nullptr;
|
||||
raw_ptr<views::Label, ExperimentalAsh> status_ = nullptr;
|
||||
|
||||
// If true, this view will only show the status and let the `BatteryIconView`
|
||||
// show the rest. If false, the `percentage_` and separator will be visible.
|
||||
// Smart charging means `ash::features::IsAdaptiveChargingEnabled()` and it
|
||||
// is adaptive delaying charge.
|
||||
const bool use_smart_charging_ui_;
|
||||
};
|
||||
|
||||
// A view that shows battery icon and charging state when smart charging is
|
||||
// enabled.
|
||||
class BatteryIconView : public BatteryInfoViewBase {
|
||||
public:
|
||||
explicit BatteryIconView(UnifiedSystemTrayController* controller)
|
||||
: BatteryInfoViewBase(controller) {
|
||||
SetID(VIEW_ID_QS_BATTERY_BUTTON);
|
||||
auto layout = std::make_unique<views::BoxLayout>(
|
||||
views::BoxLayout::Orientation::kHorizontal);
|
||||
layout->set_inside_border_insets(kUnifiedSystemInfoBatteryIconPadding);
|
||||
SetLayoutManager(std::move(layout));
|
||||
|
||||
battery_image_ = AddChildView(std::make_unique<views::ImageView>());
|
||||
// The battery icon requires its own layer to properly render the masked
|
||||
// outline of the badge within the battery icon.
|
||||
battery_image_->SetPaintToLayer();
|
||||
battery_image_->layer()->SetFillsBoundsOpaquely(false);
|
||||
|
||||
ConfigureIcon();
|
||||
|
||||
percentage_ = AddChildView(std::make_unique<views::Label>());
|
||||
|
||||
SetBackground(views::CreateRoundedRectBackground(
|
||||
GetContentLayerColor(
|
||||
ContentLayerType::kBatterySystemInfoBackgroundColor),
|
||||
GetPreferredSize().height() / 2));
|
||||
|
||||
Update();
|
||||
}
|
||||
BatteryIconView(const BatteryIconView&) = delete;
|
||||
BatteryIconView& operator=(const BatteryIconView&) = delete;
|
||||
~BatteryIconView() override = default;
|
||||
|
||||
private:
|
||||
// views::View:
|
||||
void OnThemeChanged() override {
|
||||
views::View::OnThemeChanged();
|
||||
const auto color =
|
||||
GetContentLayerColor(ContentLayerType::kButtonLabelColorPrimary);
|
||||
ConfigureLabel(percentage_, color);
|
||||
ConfigureIcon();
|
||||
}
|
||||
|
||||
// BatteryInfoViewBase:
|
||||
void Update() override {
|
||||
const std::u16string percentage_text =
|
||||
PowerStatus::Get()->GetStatusStrings().first;
|
||||
|
||||
percentage_->SetText(percentage_text);
|
||||
percentage_->SetVisible(!percentage_text.empty());
|
||||
|
||||
ConfigureIcon();
|
||||
}
|
||||
|
||||
// Builds the battery icon image.
|
||||
void ConfigureIcon() {
|
||||
const SkColor battery_icon_color =
|
||||
GetContentLayerColor(ContentLayerType::kBatterySystemInfoIconColor);
|
||||
|
||||
const SkColor badge_color = GetContentLayerColor(
|
||||
ContentLayerType::kBatterySystemInfoBackgroundColor);
|
||||
|
||||
PowerStatus::BatteryImageInfo info =
|
||||
PowerStatus::Get()->GenerateBatteryImageInfo(battery_icon_color,
|
||||
badge_color);
|
||||
info.alert_if_low = false;
|
||||
|
||||
battery_image_->SetImage(PowerStatus::GetBatteryImage(
|
||||
info, kUnifiedTrayBatteryIconSize, battery_image_->GetColorProvider()));
|
||||
}
|
||||
|
||||
// Owned by this view, which is owned by views hierarchy.
|
||||
raw_ptr<views::Label, ExperimentalAsh> percentage_ = nullptr;
|
||||
raw_ptr<views::ImageView, ExperimentalAsh> battery_image_ = nullptr;
|
||||
};
|
||||
|
||||
std::u16string FormatDate(const base::Time& time) {
|
||||
// Use 'short' month format (e.g., "Oct") followed by non-padded day of
|
||||
// month (e.g., "2", "10").
|
||||
return base::LocalizedTimeFormatWithPattern(time, "LLLd");
|
||||
}
|
||||
|
||||
std::u16string FormatDayOfWeek(const base::Time& time) {
|
||||
// Use 'short' day of week format (e.g., "Wed").
|
||||
return base::LocalizedTimeFormatWithPattern(time, "EEE");
|
||||
}
|
||||
|
||||
// Returns whether SmartChargingUI should be used.
|
||||
bool UseSmartChargingUI() {
|
||||
return ash::features::IsAdaptiveChargingEnabled() &&
|
||||
Shell::Get()
|
||||
->adaptive_charging_controller()
|
||||
->is_adaptive_delaying_charge();
|
||||
}
|
||||
|
||||
// A view that shows current date in short format e.g. "Mon, Mar 12". It updates
|
||||
// by observing `ClockObserver`.
|
||||
class DateView : public views::Button, public ClockObserver {
|
||||
public:
|
||||
explicit DateView(UnifiedSystemTrayController* controller);
|
||||
|
||||
DateView(const DateView&) = delete;
|
||||
DateView& operator=(const DateView&) = delete;
|
||||
|
||||
~DateView() override;
|
||||
|
||||
// views::Button:
|
||||
const char* GetClassName() const override { return "DateView"; }
|
||||
void OnThemeChanged() override;
|
||||
|
||||
private:
|
||||
friend class ash::UnifiedSystemInfoView;
|
||||
|
||||
// Callback called when this is pressed.
|
||||
void OnButtonPressed(const ui::Event& event);
|
||||
|
||||
void Update();
|
||||
|
||||
// views::Button:
|
||||
gfx::Insets GetInsets() const override;
|
||||
|
||||
// ClockObserver:
|
||||
void OnDateFormatChanged() override;
|
||||
void OnSystemClockTimeUpdated() override;
|
||||
void OnSystemClockCanSetTimeChanged(bool can_set_time) override;
|
||||
void Refresh() override;
|
||||
|
||||
// Owned by the views hierarchy.
|
||||
raw_ptr<views::Label, ExperimentalAsh> label_;
|
||||
|
||||
// Unowned.
|
||||
const raw_ptr<UnifiedSystemTrayController,
|
||||
DanglingUntriaged | ExperimentalAsh>
|
||||
controller_;
|
||||
};
|
||||
|
||||
DateView::DateView(UnifiedSystemTrayController* controller)
|
||||
: Button(base::BindRepeating(&DateView::OnButtonPressed,
|
||||
base::Unretained(this))),
|
||||
label_(AddChildView(std::make_unique<views::Label>())),
|
||||
controller_(controller) {
|
||||
SetID(VIEW_ID_QS_DATE_VIEW_BUTTON);
|
||||
SetLayoutManager(std::make_unique<views::FillLayout>());
|
||||
label_->SetAutoColorReadabilityEnabled(false);
|
||||
label_->SetSubpixelRenderingEnabled(false);
|
||||
Update();
|
||||
|
||||
Shell::Get()->system_tray_model()->clock()->AddObserver(this);
|
||||
SetInstallFocusRingOnFocus(true);
|
||||
views::FocusRing::Get(this)->SetColorId(ui::kColorAshFocusRing);
|
||||
views::InkDrop::Get(this)->SetMode(views::InkDropHost::InkDropMode::OFF);
|
||||
}
|
||||
|
||||
DateView::~DateView() {
|
||||
Shell::Get()->system_tray_model()->clock()->RemoveObserver(this);
|
||||
}
|
||||
|
||||
void DateView::OnThemeChanged() {
|
||||
views::Button::OnThemeChanged();
|
||||
auto* color_provider = AshColorProvider::Get();
|
||||
label_->SetEnabledColor(color_provider->GetContentLayerColor(
|
||||
ContentLayerType::kTextColorPrimary));
|
||||
}
|
||||
|
||||
void DateView::OnButtonPressed(const ui::Event& event) {
|
||||
quick_settings_metrics_util::RecordQsButtonActivated(
|
||||
QsButtonCatalogName::kDateViewButton);
|
||||
|
||||
if (controller_->IsExpanded()) {
|
||||
controller_->ShowCalendarView(
|
||||
calendar_metrics::CalendarViewShowSource::kDateView,
|
||||
calendar_metrics::GetEventType(event));
|
||||
return;
|
||||
}
|
||||
|
||||
controller_->HandleOpenDateTimeSettingsAction();
|
||||
}
|
||||
|
||||
void DateView::Update() {
|
||||
base::Time now = base::Time::Now();
|
||||
label_->SetText(l10n_util::GetStringFUTF16(
|
||||
IDS_ASH_STATUS_TRAY_DATE, FormatDayOfWeek(now), FormatDate(now)));
|
||||
|
||||
SetAccessibleName(
|
||||
l10n_util::GetStringFUTF16(IDS_ASH_CALENDAR_ENTRY_ACCESSIBLE_DESCRIPTION,
|
||||
TimeFormatFriendlyDateAndTime(now)));
|
||||
}
|
||||
|
||||
gfx::Insets DateView::GetInsets() const {
|
||||
// This padding provides room to render the focus ring around this button.
|
||||
return kUnifiedSystemInfoDateViewPadding;
|
||||
}
|
||||
|
||||
void DateView::OnDateFormatChanged() {}
|
||||
|
||||
void DateView::OnSystemClockTimeUpdated() {
|
||||
Update();
|
||||
}
|
||||
|
||||
void DateView::OnSystemClockCanSetTimeChanged(bool can_set_time) {}
|
||||
|
||||
void DateView::Refresh() {
|
||||
Update();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// A view that contains date, battery status, and whether the device
|
||||
// is enterprise managed.
|
||||
class ManagementPowerDateComboView : public views::View {
|
||||
public:
|
||||
explicit ManagementPowerDateComboView(
|
||||
UnifiedSystemTrayController* controller) {
|
||||
auto* layout = SetLayoutManager(std::make_unique<views::BoxLayout>(
|
||||
views::BoxLayout::Orientation::kHorizontal, gfx::Insets(),
|
||||
kUnifiedSystemInfoSpacing));
|
||||
layout->set_cross_axis_alignment(
|
||||
views::BoxLayout::CrossAxisAlignment::kCenter);
|
||||
date_view_ = AddChildView(std::make_unique<DateView>(controller));
|
||||
|
||||
if (PowerStatus::Get()->IsBatteryPresent()) {
|
||||
separator_view_ = AddChildView(std::make_unique<views::Separator>());
|
||||
separator_view_->SetColorId(ui::kColorAshSystemUIMenuSeparator);
|
||||
separator_view_->SetPreferredLength(kUnifiedSystemInfoHeight);
|
||||
|
||||
const bool use_smart_charging_ui = UseSmartChargingUI();
|
||||
if (use_smart_charging_ui) {
|
||||
AddChildView(std::make_unique<BatteryIconView>(controller));
|
||||
}
|
||||
AddChildView(std::make_unique<BatteryLabelView>(controller,
|
||||
use_smart_charging_ui));
|
||||
}
|
||||
|
||||
auto* spacing = AddChildView(std::make_unique<views::View>());
|
||||
layout->SetFlexForView(spacing, 1);
|
||||
|
||||
enterprise_managed_view_ =
|
||||
AddChildView(std::make_unique<EnterpriseManagedView>(controller));
|
||||
supervised_view_ = AddChildView(std::make_unique<SupervisedUserView>());
|
||||
}
|
||||
ManagementPowerDateComboView(const ManagementPowerDateComboView&) = delete;
|
||||
ManagementPowerDateComboView& operator=(const ManagementPowerDateComboView&) =
|
||||
delete;
|
||||
~ManagementPowerDateComboView() override = default;
|
||||
|
||||
bool IsSupervisedVisibleForTesting() {
|
||||
return supervised_view_->GetVisible();
|
||||
}
|
||||
|
||||
private:
|
||||
friend class UnifiedSystemInfoView;
|
||||
|
||||
// Pointer to the actual child view is maintained for unit testing, owned by
|
||||
// `ManagementPowerDateComboView`.
|
||||
raw_ptr<EnterpriseManagedView, ExperimentalAsh> enterprise_managed_view_ =
|
||||
nullptr;
|
||||
|
||||
// Pointer to the actual child view is maintained for unit testing, owned by
|
||||
// `ManagementPowerDateComboView`.
|
||||
raw_ptr<SupervisedUserView, ExperimentalAsh> supervised_view_ = nullptr;
|
||||
|
||||
// Separator between date and battery views, owned by
|
||||
// `ManagementPowerDateComboView`.
|
||||
raw_ptr<views::Separator, ExperimentalAsh> separator_view_ = nullptr;
|
||||
|
||||
// Pointer to the actual child view is maintained for unit testing, owned by
|
||||
// `ManagementPowerDateComboView`.
|
||||
raw_ptr<DateView, ExperimentalAsh> date_view_ = nullptr;
|
||||
};
|
||||
|
||||
UnifiedSystemInfoView::UnifiedSystemInfoView(
|
||||
UnifiedSystemTrayController* controller) {
|
||||
// Layout for the overall UnifiedSystemInfoView.
|
||||
auto* layout = SetLayoutManager(std::make_unique<views::BoxLayout>(
|
||||
views::BoxLayout::Orientation::kVertical, kUnifiedSystemInfoViewPadding,
|
||||
kUnifiedSystemInfoSpacing));
|
||||
// Allow children to stretch to fill the whole width of the parent. Some
|
||||
// direct children are kStart aligned, others are kCenter aligned.
|
||||
layout->set_cross_axis_alignment(
|
||||
views::BoxLayout::CrossAxisAlignment::kStretch);
|
||||
|
||||
// Construct a ManagementPowerDateComboView and save off a raw pointer, to
|
||||
// facilitate introspection needed for unit tests.
|
||||
combo_view_ =
|
||||
AddChildView(std::make_unique<ManagementPowerDateComboView>(controller));
|
||||
layout->SetFlexForView(combo_view_, 1);
|
||||
|
||||
if (Shell::Get()->session_controller()->GetSessionState() ==
|
||||
session_manager::SessionState::ACTIVE) {
|
||||
if (Shell::Get()->system_tray_model()->update_model()->show_eol_notice()) {
|
||||
auto* eol_notice_wrapper = AddChildView(std::make_unique<views::View>());
|
||||
auto* eol_notice_layout = eol_notice_wrapper->SetLayoutManager(
|
||||
std::make_unique<views::BoxLayout>(
|
||||
views::BoxLayout::Orientation::kHorizontal, gfx::Insets(),
|
||||
kUnifiedSystemInfoSpacing));
|
||||
eol_notice_layout->set_main_axis_alignment(
|
||||
views::BoxLayout::MainAxisAlignment::kCenter);
|
||||
eol_notice_layout->set_cross_axis_alignment(
|
||||
views::BoxLayout::CrossAxisAlignment::kCenter);
|
||||
|
||||
eol_notice_ = eol_notice_wrapper->AddChildView(
|
||||
std::make_unique<EolNoticeQuickSettingsView>());
|
||||
}
|
||||
|
||||
// If the release track is not "stable" then channel indicator UI for quick
|
||||
// settings is put up.
|
||||
auto channel = Shell::Get()->shell_delegate()->GetChannel();
|
||||
if (!eol_notice_ &&
|
||||
channel_indicator_utils::IsDisplayableChannel(channel)) {
|
||||
channel_view_ =
|
||||
AddChildView(std::make_unique<ChannelIndicatorQuickSettingsView>(
|
||||
channel, Shell::Get()
|
||||
->system_tray_model()
|
||||
->client()
|
||||
->IsUserFeedbackEnabled()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UnifiedSystemInfoView::~UnifiedSystemInfoView() = default;
|
||||
|
||||
void UnifiedSystemInfoView::ChildVisibilityChanged(views::View* child) {
|
||||
Layout();
|
||||
}
|
||||
|
||||
void UnifiedSystemInfoView::ChildPreferredSizeChanged(views::View* child) {
|
||||
Layout();
|
||||
}
|
||||
|
||||
bool UnifiedSystemInfoView::IsSupervisedVisibleForTesting() {
|
||||
return combo_view_->IsSupervisedVisibleForTesting(); // IN-TEST
|
||||
}
|
||||
|
||||
views::View* UnifiedSystemInfoView::GetDateViewForTesting() {
|
||||
return combo_view_->date_view_;
|
||||
}
|
||||
|
||||
views::View* UnifiedSystemInfoView::GetDateViewLabelForTesting() {
|
||||
DCHECK(combo_view_->date_view_);
|
||||
return combo_view_->date_view_->label_;
|
||||
}
|
||||
|
||||
void UnifiedSystemInfoView::UpdateDateViewForTesting() {
|
||||
DCHECK(combo_view_->date_view_);
|
||||
combo_view_->date_view_->Update();
|
||||
}
|
||||
|
||||
BEGIN_METADATA(UnifiedSystemInfoView, views::View)
|
||||
END_METADATA
|
||||
|
||||
} // namespace ash
|
@ -1,69 +0,0 @@
|
||||
// Copyright 2018 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ASH_SYSTEM_UNIFIED_UNIFIED_SYSTEM_INFO_VIEW_H_
|
||||
#define ASH_SYSTEM_UNIFIED_UNIFIED_SYSTEM_INFO_VIEW_H_
|
||||
|
||||
#include "ash/ash_export.h"
|
||||
#include "ash/system/unified/unified_system_tray_controller.h"
|
||||
#include "base/gtest_prod_util.h"
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "ui/base/metadata/metadata_header_macros.h"
|
||||
#include "ui/views/view.h"
|
||||
|
||||
namespace ash {
|
||||
|
||||
class ManagementPowerDateComboView;
|
||||
class ChannelIndicatorQuickSettingsView;
|
||||
|
||||
// A view at the bottom of UnifiedSystemTray bubble that shows system
|
||||
// information.
|
||||
class ASH_EXPORT UnifiedSystemInfoView : public views::View {
|
||||
public:
|
||||
METADATA_HEADER(UnifiedSystemInfoView);
|
||||
explicit UnifiedSystemInfoView(UnifiedSystemTrayController* controller);
|
||||
|
||||
UnifiedSystemInfoView(const UnifiedSystemInfoView&) = delete;
|
||||
UnifiedSystemInfoView& operator=(const UnifiedSystemInfoView&) = delete;
|
||||
|
||||
~UnifiedSystemInfoView() override;
|
||||
|
||||
// views::View:
|
||||
void ChildPreferredSizeChanged(views::View* child) override;
|
||||
void ChildVisibilityChanged(views::View* child) override;
|
||||
|
||||
// Introspection methods needed for unit tests.
|
||||
bool IsSupervisedVisibleForTesting();
|
||||
|
||||
private:
|
||||
FRIEND_TEST_ALL_PREFIXES(UnifiedSystemInfoViewTest, EnterpriseManagedVisible);
|
||||
FRIEND_TEST_ALL_PREFIXES(UnifiedSystemInfoViewTest,
|
||||
EnterpriseManagedVisibleForActiveDirectory);
|
||||
FRIEND_TEST_ALL_PREFIXES(UnifiedSystemInfoViewTest,
|
||||
EnterpriseUserManagedVisible);
|
||||
FRIEND_TEST_ALL_PREFIXES(UnifiedSystemInfoViewTest,
|
||||
UpdateFiresAccessibilityEvents);
|
||||
FRIEND_TEST_ALL_PREFIXES(UnifiedSystemInfoViewNoSessionTest, ChildVisible);
|
||||
|
||||
// Raw pointer to the combo view (owned by `UnifiedSystemInfoView`) that
|
||||
// facilitates introspection needed for unit tests.
|
||||
raw_ptr<ManagementPowerDateComboView, ExperimentalAsh> combo_view_ = nullptr;
|
||||
|
||||
// Raw pointer to the channel indicator quick settings view (owned by
|
||||
// `UnifiedSystemInfoView`) that facilitates introspection needed for unit
|
||||
// tests.
|
||||
raw_ptr<ChannelIndicatorQuickSettingsView, ExperimentalAsh> channel_view_ =
|
||||
nullptr;
|
||||
|
||||
raw_ptr<views::View, ExperimentalAsh> eol_notice_ = nullptr;
|
||||
|
||||
// Introspection methods needed for unit tests.
|
||||
views::View* GetDateViewForTesting();
|
||||
views::View* GetDateViewLabelForTesting();
|
||||
void UpdateDateViewForTesting();
|
||||
};
|
||||
|
||||
} // namespace ash
|
||||
|
||||
#endif // ASH_SYSTEM_UNIFIED_UNIFIED_SYSTEM_INFO_VIEW_H_
|
@ -1,286 +0,0 @@
|
||||
// Copyright 2018 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "ash/system/unified/unified_system_info_view.h"
|
||||
|
||||
#include "ash/public/cpp/ash_view_ids.h"
|
||||
#include "ash/public/cpp/login_types.h"
|
||||
#include "ash/public/cpp/system_tray_client.h"
|
||||
#include "ash/public/cpp/test/test_system_tray_client.h"
|
||||
#include "ash/session/session_controller_impl.h"
|
||||
#include "ash/session/test_session_controller_client.h"
|
||||
#include "ash/shell.h"
|
||||
#include "ash/system/model/enterprise_domain_model.h"
|
||||
#include "ash/system/model/system_tray_model.h"
|
||||
#include "ash/system/unified/unified_system_tray_controller.h"
|
||||
#include "ash/system/unified/unified_system_tray_model.h"
|
||||
#include "ash/test/ash_test_base.h"
|
||||
#include "ash/test_shell_delegate.h"
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "base/memory/scoped_refptr.h"
|
||||
#include "base/test/task_environment.h"
|
||||
#include "base/time/time.h"
|
||||
#include "components/version_info/channel.h"
|
||||
#include "ui/views/test/ax_event_counter.h"
|
||||
|
||||
namespace ash {
|
||||
|
||||
// Tests are parameterized by the release track UI:
|
||||
// - Whether the release track is a value other than "stable"
|
||||
// - Whether EOL notice is expected to be shown.
|
||||
// The release track UI only shows if both conditions are met.
|
||||
//
|
||||
// NOTE: For QsRevamp, see similar tests in QuickSettingsHeaderTest.
|
||||
class UnifiedSystemInfoViewTest
|
||||
: public AshTestBase,
|
||||
public testing::WithParamInterface<std::tuple<bool, bool>> {
|
||||
public:
|
||||
UnifiedSystemInfoViewTest()
|
||||
: AshTestBase(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
|
||||
UnifiedSystemInfoViewTest(const UnifiedSystemInfoViewTest&) = delete;
|
||||
UnifiedSystemInfoViewTest& operator=(const UnifiedSystemInfoViewTest&) =
|
||||
delete;
|
||||
~UnifiedSystemInfoViewTest() override = default;
|
||||
|
||||
void SetUp() override {
|
||||
// Provide our own `TestShellDelegate`, with a non-stable channel set if
|
||||
// the passed-in parameter dictates.
|
||||
std::unique_ptr<TestShellDelegate> shell_delegate =
|
||||
std::make_unique<TestShellDelegate>();
|
||||
if (IsReleaseTrackNotStable())
|
||||
shell_delegate->set_channel(version_info::Channel::BETA);
|
||||
AshTestBase::SetUp(std::move(shell_delegate));
|
||||
|
||||
if (ShouldShowEolNotice()) {
|
||||
Shell::Get()->system_tray_model()->SetShowEolNotice(true);
|
||||
}
|
||||
|
||||
// Instantiate members.
|
||||
model_ = base::MakeRefCounted<UnifiedSystemTrayModel>(nullptr);
|
||||
controller_ = std::make_unique<UnifiedSystemTrayController>(model_.get());
|
||||
auto info_view = std::make_unique<UnifiedSystemInfoView>(controller_.get());
|
||||
info_view_ = info_view.get();
|
||||
|
||||
// Place the view in a large views::Widget so the buttons are clickable.
|
||||
widget_ = CreateFramelessTestWidget();
|
||||
widget_->SetFullscreen(true);
|
||||
widget_->SetContentsView(std::move(info_view));
|
||||
}
|
||||
|
||||
bool IsReleaseTrackNotStable() const { return std::get<0>(GetParam()); }
|
||||
|
||||
bool ShouldShowEolNotice() const { return std::get<1>(GetParam()); }
|
||||
|
||||
views::View* GetDateButton() {
|
||||
return info_view_->GetViewByID(VIEW_ID_QS_DATE_VIEW_BUTTON);
|
||||
}
|
||||
|
||||
views::View* GetBatteryButton() {
|
||||
return info_view_->GetViewByID(VIEW_ID_QS_BATTERY_BUTTON);
|
||||
}
|
||||
|
||||
views::View* GetManagedButton() {
|
||||
return info_view_->GetViewByID(VIEW_ID_QS_MANAGED_BUTTON);
|
||||
}
|
||||
|
||||
views::View* GetVersionButton() {
|
||||
return info_view_->GetViewByID(VIEW_ID_QS_VERSION_BUTTON);
|
||||
}
|
||||
|
||||
views::View* GetFeedbackButton() {
|
||||
return info_view_->GetViewByID(VIEW_ID_QS_FEEDBACK_BUTTON);
|
||||
}
|
||||
|
||||
views::View* GetEolNoticeButton() {
|
||||
return info_view_->GetViewByID(VIEW_ID_QS_EOL_NOTICE_BUTTON);
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
info_view_ = nullptr;
|
||||
widget_.reset();
|
||||
controller_.reset();
|
||||
model_.reset();
|
||||
AshTestBase::TearDown();
|
||||
}
|
||||
|
||||
protected:
|
||||
UnifiedSystemInfoView* info_view() { return info_view_; }
|
||||
EnterpriseDomainModel* enterprise_domain() {
|
||||
return Shell::Get()->system_tray_model()->enterprise_domain();
|
||||
}
|
||||
|
||||
private:
|
||||
scoped_refptr<UnifiedSystemTrayModel> model_;
|
||||
std::unique_ptr<UnifiedSystemTrayController> controller_;
|
||||
raw_ptr<UnifiedSystemInfoView, ExperimentalAsh> info_view_ = nullptr;
|
||||
std::unique_ptr<views::Widget> widget_;
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(All,
|
||||
UnifiedSystemInfoViewTest,
|
||||
testing::Combine(testing::Bool(), testing::Bool()));
|
||||
|
||||
TEST_P(UnifiedSystemInfoViewTest, ButtonNameAndVisibility) {
|
||||
// By default, EnterpriseManagedView is not shown.
|
||||
EXPECT_FALSE(GetManagedButton()->GetVisible());
|
||||
|
||||
// Simulate enterprise information becoming available.
|
||||
enterprise_domain()->SetDeviceEnterpriseInfo(
|
||||
DeviceEnterpriseInfo{"example.com", /*active_directory_managed=*/false,
|
||||
ManagementDeviceMode::kChromeEnterprise});
|
||||
|
||||
// EnterpriseManagedView should be shown.
|
||||
EXPECT_TRUE(GetManagedButton()->GetVisible());
|
||||
|
||||
// `DateView` should be shown.
|
||||
EXPECT_TRUE(GetDateButton()->GetVisible());
|
||||
|
||||
// Battery button should be shown.
|
||||
EXPECT_TRUE(GetBatteryButton()->GetVisible());
|
||||
|
||||
EXPECT_EQ(ShouldShowEolNotice(),
|
||||
GetEolNoticeButton() && GetEolNoticeButton()->GetVisible());
|
||||
if (ShouldShowEolNotice()) {
|
||||
LeftClickOn(GetEolNoticeButton());
|
||||
EXPECT_EQ(1, GetSystemTrayClient()->show_eol_info_count());
|
||||
}
|
||||
|
||||
const bool show_release_track_info =
|
||||
IsReleaseTrackNotStable() && !ShouldShowEolNotice();
|
||||
|
||||
// If the release track UI is enabled AND the release track is non-stable, the
|
||||
// version button is shown.
|
||||
EXPECT_EQ(show_release_track_info,
|
||||
GetVersionButton() && GetVersionButton()->GetVisible());
|
||||
|
||||
// If the release track UI is enabled AND the release track is non-stable AND
|
||||
// the user feedback is enabled, the feedback button is shown.
|
||||
EXPECT_EQ(
|
||||
show_release_track_info &&
|
||||
Shell::Get()->system_tray_model()->client()->IsUserFeedbackEnabled(),
|
||||
GetFeedbackButton() && GetFeedbackButton()->GetVisible());
|
||||
}
|
||||
|
||||
TEST_P(UnifiedSystemInfoViewTest, EnterpriseManagedVisibleForActiveDirectory) {
|
||||
// Active directory information becoming available.
|
||||
const std::string empty_domain;
|
||||
enterprise_domain()->SetDeviceEnterpriseInfo(
|
||||
DeviceEnterpriseInfo{empty_domain, /*active_directory_managed=*/true,
|
||||
ManagementDeviceMode::kChromeEnterprise});
|
||||
|
||||
// EnterpriseManagedView should be shown.
|
||||
EXPECT_TRUE(GetManagedButton()->GetVisible());
|
||||
|
||||
EXPECT_EQ(ShouldShowEolNotice(),
|
||||
GetEolNoticeButton() && GetEolNoticeButton()->GetVisible());
|
||||
|
||||
if (ShouldShowEolNotice()) {
|
||||
LeftClickOn(GetEolNoticeButton());
|
||||
EXPECT_EQ(1, GetSystemTrayClient()->show_eol_info_count());
|
||||
}
|
||||
|
||||
const bool show_release_track_info =
|
||||
IsReleaseTrackNotStable() && !ShouldShowEolNotice();
|
||||
|
||||
// If the release track UI is enabled AND the release track is non-stable, the
|
||||
// version button is shown.
|
||||
EXPECT_EQ(show_release_track_info,
|
||||
GetVersionButton() && GetVersionButton()->GetVisible());
|
||||
|
||||
// If the release track UI is enabled AND the release track is non-stable AND
|
||||
// the user feedback is enabled, the feedback button is shown.
|
||||
EXPECT_EQ(
|
||||
show_release_track_info &&
|
||||
Shell::Get()->system_tray_model()->client()->IsUserFeedbackEnabled(),
|
||||
GetFeedbackButton() && GetFeedbackButton()->GetVisible());
|
||||
}
|
||||
|
||||
TEST_P(UnifiedSystemInfoViewTest, EnterpriseUserManagedVisible) {
|
||||
// By default, EnterpriseManagedView is not shown.
|
||||
EXPECT_FALSE(GetManagedButton()->GetVisible());
|
||||
|
||||
// Simulate enterprise information becoming available.
|
||||
enterprise_domain()->SetEnterpriseAccountDomainInfo("example.com");
|
||||
|
||||
// EnterpriseManagedView should be shown.
|
||||
EXPECT_TRUE(GetManagedButton()->GetVisible());
|
||||
|
||||
EXPECT_EQ(ShouldShowEolNotice(),
|
||||
GetEolNoticeButton() && GetEolNoticeButton()->GetVisible());
|
||||
|
||||
if (ShouldShowEolNotice()) {
|
||||
LeftClickOn(GetEolNoticeButton());
|
||||
EXPECT_EQ(1, GetSystemTrayClient()->show_eol_info_count());
|
||||
}
|
||||
|
||||
const bool show_release_track_info =
|
||||
IsReleaseTrackNotStable() && !ShouldShowEolNotice();
|
||||
|
||||
// If the release track UI is enabled AND the release track is non-stable, the
|
||||
// version button is shown.
|
||||
EXPECT_EQ(show_release_track_info,
|
||||
GetVersionButton() && GetVersionButton()->GetVisible());
|
||||
|
||||
// If the release track UI is enabled AND the release track is non-stable AND
|
||||
// the user feedback is enabled, the feedback button is shown.
|
||||
EXPECT_EQ(
|
||||
show_release_track_info &&
|
||||
Shell::Get()->system_tray_model()->client()->IsUserFeedbackEnabled(),
|
||||
GetFeedbackButton() && GetFeedbackButton()->GetVisible());
|
||||
}
|
||||
|
||||
TEST_P(UnifiedSystemInfoViewTest, UpdateFiresAccessibilityEvents) {
|
||||
// Set the current time to 08:00 for testing.
|
||||
task_environment()->AdvanceClock(base::Time::Now().LocalMidnight() +
|
||||
base::Hours(32) - base::Time::Now());
|
||||
views::test::AXEventCounter counter(views::AXEventManager::Get());
|
||||
auto* date_view = info_view()->GetDateViewForTesting();
|
||||
auto* date_view_label = info_view()->GetDateViewLabelForTesting();
|
||||
EXPECT_EQ(0, counter.GetCount(ax::mojom::Event::kTextChanged, date_view));
|
||||
EXPECT_EQ(0,
|
||||
counter.GetCount(ax::mojom::Event::kTextChanged, date_view_label));
|
||||
|
||||
// `DateView::Update` sets the accessible name of both itself and its label.
|
||||
// This will result in text-changed events being emitted, but only if the
|
||||
// accessible name has actually changed. Therefore advance the clock by a
|
||||
// minute before calling `Update`.
|
||||
task_environment()->FastForwardBy(base::Minutes(1));
|
||||
info_view()->UpdateDateViewForTesting();
|
||||
EXPECT_EQ(1, counter.GetCount(ax::mojom::Event::kTextChanged, date_view));
|
||||
EXPECT_EQ(1,
|
||||
counter.GetCount(ax::mojom::Event::kTextChanged, date_view_label));
|
||||
}
|
||||
|
||||
using UnifiedSystemInfoViewNoSessionTest = NoSessionAshTestBase;
|
||||
|
||||
TEST_F(UnifiedSystemInfoViewNoSessionTest, ChildVisible) {
|
||||
auto model = base::MakeRefCounted<UnifiedSystemTrayModel>(nullptr);
|
||||
auto controller = std::make_unique<UnifiedSystemTrayController>(model.get());
|
||||
|
||||
SessionControllerImpl* session = Shell::Get()->session_controller();
|
||||
ASSERT_FALSE(session->IsActiveUserSessionStarted());
|
||||
|
||||
// Before login the supervised user view is invisible.
|
||||
{
|
||||
auto info_view = std::make_unique<UnifiedSystemInfoView>(controller.get());
|
||||
EXPECT_FALSE(info_view->IsSupervisedVisibleForTesting());
|
||||
}
|
||||
|
||||
// Simulate a supervised user logging in.
|
||||
TestSessionControllerClient* client = GetSessionControllerClient();
|
||||
client->Reset();
|
||||
client->AddUserSession("child@test.com", user_manager::USER_TYPE_CHILD);
|
||||
client->SetSessionState(session_manager::SessionState::ACTIVE);
|
||||
UserSession user_session = *session->GetUserSession(0);
|
||||
user_session.custodian_email = "parent@test.com";
|
||||
session->UpdateUserSession(std::move(user_session));
|
||||
|
||||
// Now the supervised user view is visible.
|
||||
{
|
||||
auto info_view = std::make_unique<UnifiedSystemInfoView>(controller.get());
|
||||
EXPECT_TRUE(info_view->IsSupervisedVisibleForTesting());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ash
|
@ -44,7 +44,6 @@
|
||||
#include "ash/system/unified/unified_slider_view.h"
|
||||
#include "ash/system/unified/unified_system_tray_bubble.h"
|
||||
#include "ash/system/unified/unified_system_tray_model.h"
|
||||
#include "ash/system/unified/unified_system_tray_view.h"
|
||||
#include "ash/user_education/user_education_class_properties.h"
|
||||
#include "ash/user_education/welcome_tour/welcome_tour_metrics.h"
|
||||
#include "base/memory/raw_ptr.h"
|
||||
@ -245,30 +244,6 @@ void UnifiedSystemTray::CloseSecondaryBubbles() {
|
||||
}
|
||||
}
|
||||
|
||||
void UnifiedSystemTray::CollapseMessageCenter() {
|
||||
}
|
||||
|
||||
void UnifiedSystemTray::ExpandMessageCenter() {
|
||||
}
|
||||
|
||||
void UnifiedSystemTray::EnsureQuickSettingsCollapsed(bool animate) {
|
||||
if (!bubble_) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (animate) {
|
||||
bubble_->EnsureCollapsed();
|
||||
} else {
|
||||
bubble_->CollapseWithoutAnimating();
|
||||
}
|
||||
}
|
||||
|
||||
void UnifiedSystemTray::EnsureBubbleExpanded() {
|
||||
if (bubble_) {
|
||||
bubble_->EnsureExpanded();
|
||||
}
|
||||
}
|
||||
|
||||
void UnifiedSystemTray::ShowVolumeSliderBubble() {
|
||||
slider_bubble_controller_->ShowBubble(
|
||||
UnifiedSliderBubbleController::SLIDER_TYPE_VOLUME);
|
||||
@ -306,7 +281,7 @@ void UnifiedSystemTray::ShowNetworkDetailedViewBubble() {
|
||||
// `bubble_` is still uninitialized). Only show detailed view if `bubble_` is
|
||||
// not null.
|
||||
if (bubble_) {
|
||||
bubble_->ShowNetworkDetailedView(/*force=*/true);
|
||||
bubble_->ShowNetworkDetailedView();
|
||||
}
|
||||
}
|
||||
|
||||
@ -331,12 +306,6 @@ bool UnifiedSystemTray::FocusQuickSettings(bool reverse) {
|
||||
|
||||
Shell::Get()->focus_cycler()->FocusWidget(quick_settings_widget);
|
||||
|
||||
// Focus an individual element in quick settings if chrome vox is
|
||||
// disabled.
|
||||
if (!ShouldEnableExtraKeyboardAccessibility()) {
|
||||
bubble_->FocusEntered(reverse);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -495,21 +464,12 @@ std::u16string UnifiedSystemTray::GetAccessibleNameForBubble() {
|
||||
}
|
||||
|
||||
std::u16string UnifiedSystemTray::GetAccessibleNameForQuickSettingsBubble() {
|
||||
if (features::IsQsRevampEnabled()) {
|
||||
if (bubble_->quick_settings_view()->IsDetailedViewShown()) {
|
||||
return bubble_->quick_settings_view()->GetDetailedViewAccessibleName();
|
||||
}
|
||||
|
||||
return l10n_util::GetStringUTF16(
|
||||
IDS_ASH_REVAMPED_QUICK_SETTINGS_BUBBLE_ACCESSIBLE_DESCRIPTION);
|
||||
}
|
||||
|
||||
if (bubble_->unified_view()->IsDetailedViewShown()) {
|
||||
return bubble_->unified_view()->GetDetailedViewAccessibleName();
|
||||
}
|
||||
|
||||
return l10n_util::GetStringUTF16(
|
||||
IDS_ASH_QUICK_SETTINGS_BUBBLE_ACCESSIBLE_DESCRIPTION);
|
||||
IDS_ASH_QUICK_SETTINGS_BUBBLE_ACCESSIBLE_DESCRIPTION);
|
||||
}
|
||||
|
||||
void UnifiedSystemTray::HandleLocaleChange() {
|
||||
|
@ -119,18 +119,6 @@ class ASH_EXPORT UnifiedSystemTray
|
||||
// Activates the system tray bubble.
|
||||
void ActivateBubble();
|
||||
|
||||
// Collapse the message center bubble.
|
||||
void CollapseMessageCenter();
|
||||
|
||||
// Expand the message center bubble.
|
||||
void ExpandMessageCenter();
|
||||
|
||||
// Ensure the quick settings bubble is collapsed.
|
||||
void EnsureQuickSettingsCollapsed(bool animate);
|
||||
|
||||
// Ensure the system tray bubble is expanded.
|
||||
void EnsureBubbleExpanded();
|
||||
|
||||
// Shows volume slider bubble shown at the right bottom of screen. The bubble
|
||||
// is same as one shown when volume buttons on keyboard are pressed.
|
||||
void ShowVolumeSliderBubble();
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include "ash/system/unified/quick_settings_metrics_util.h"
|
||||
#include "ash/system/unified/unified_system_tray.h"
|
||||
#include "ash/system/unified/unified_system_tray_controller.h"
|
||||
#include "ash/system/unified/unified_system_tray_view.h"
|
||||
#include "ash/wm/container_finder.h"
|
||||
#include "ash/wm/tablet_mode/tablet_mode_controller.h"
|
||||
#include "base/debug/crash_logging.h"
|
||||
@ -39,15 +38,12 @@ UnifiedSystemTrayBubble::UnifiedSystemTrayBubble(UnifiedSystemTray* tray)
|
||||
: controller_(std::make_unique<UnifiedSystemTrayController>(tray->model(),
|
||||
this,
|
||||
tray)),
|
||||
unified_system_tray_(tray),
|
||||
is_qs_revamp_enabled_(features::IsQsRevampEnabled()) {
|
||||
unified_system_tray_(tray) {
|
||||
time_opened_ = base::TimeTicks::Now();
|
||||
|
||||
TrayBubbleView::InitParams init_params =
|
||||
CreateInitParamsForTrayBubble(tray, /*anchor_to_shelf_corner=*/true);
|
||||
if (is_qs_revamp_enabled_) {
|
||||
init_params.preferred_width = kRevampedTrayMenuWidth;
|
||||
}
|
||||
init_params.preferred_width = kRevampedTrayMenuWidth;
|
||||
init_params.close_on_deactivate = false;
|
||||
|
||||
bubble_view_ = new TrayBubbleView(init_params);
|
||||
@ -56,23 +52,12 @@ UnifiedSystemTrayBubble::UnifiedSystemTrayBubble(UnifiedSystemTray* tray)
|
||||
int max_height = CalculateMaxTrayBubbleHeight(
|
||||
unified_system_tray_->GetBubbleWindowContainer());
|
||||
|
||||
if (is_qs_revamp_enabled_) {
|
||||
auto quick_settings_view = controller_->CreateQuickSettingsView(max_height);
|
||||
bubble_view_->SetMaxHeight(max_height);
|
||||
quick_settings_view_ =
|
||||
bubble_view_->AddChildView(std::move(quick_settings_view));
|
||||
time_to_click_recorder_ = std::make_unique<TimeToClickRecorder>(
|
||||
/*delegate=*/this, /*target_view=*/quick_settings_view_);
|
||||
} else {
|
||||
DCHECK(!is_qs_revamp_enabled_);
|
||||
auto unified_view = controller_->CreateUnifiedQuickSettingsView();
|
||||
unified_view->SetMaxHeight(max_height);
|
||||
bubble_view_->SetMaxHeight(max_height);
|
||||
controller_->ResetToCollapsedIfRequired();
|
||||
unified_view_ = bubble_view_->AddChildView(std::move(unified_view));
|
||||
time_to_click_recorder_ = std::make_unique<TimeToClickRecorder>(
|
||||
/*delegate=*/this, /*target_view=*/unified_view_);
|
||||
}
|
||||
auto quick_settings_view = controller_->CreateQuickSettingsView(max_height);
|
||||
bubble_view_->SetMaxHeight(max_height);
|
||||
quick_settings_view_ =
|
||||
bubble_view_->AddChildView(std::move(quick_settings_view));
|
||||
time_to_click_recorder_ = std::make_unique<TimeToClickRecorder>(
|
||||
/*delegate=*/this, /*target_view=*/quick_settings_view_);
|
||||
|
||||
bubble_widget_ = views::BubbleDialogDelegateView::CreateBubble(bubble_view_);
|
||||
bubble_widget_->AddObserver(this);
|
||||
@ -91,14 +76,12 @@ UnifiedSystemTrayBubble::UnifiedSystemTrayBubble(UnifiedSystemTray* tray)
|
||||
|
||||
UnifiedSystemTrayBubble::~UnifiedSystemTrayBubble() {
|
||||
// Record the number of quick settings pages.
|
||||
if (is_qs_revamp_enabled_) {
|
||||
auto page_count = unified_system_tray_controller()
|
||||
->model()
|
||||
->pagination_model()
|
||||
->total_pages();
|
||||
DCHECK_GT(page_count, 0);
|
||||
quick_settings_metrics_util::RecordQsPageCountOnClose(page_count);
|
||||
}
|
||||
auto page_count = unified_system_tray_controller()
|
||||
->model()
|
||||
->pagination_model()
|
||||
->total_pages();
|
||||
DCHECK_GT(page_count, 0);
|
||||
quick_settings_metrics_util::RecordQsPageCountOnClose(page_count);
|
||||
|
||||
if (controller_->showing_calendar_view()) {
|
||||
unified_system_tray_->NotifyLeavingCalendarView();
|
||||
@ -115,7 +98,6 @@ UnifiedSystemTrayBubble::~UnifiedSystemTrayBubble() {
|
||||
if (bubble_view_) {
|
||||
bubble_view_->RemoveAllChildViews();
|
||||
quick_settings_view_ = nullptr;
|
||||
unified_view_ = nullptr;
|
||||
bubble_view_->ResetDelegate();
|
||||
bubble_view_ = nullptr;
|
||||
}
|
||||
@ -148,57 +130,12 @@ bool UnifiedSystemTrayBubble::IsBubbleActive() const {
|
||||
return bubble_widget_ && bubble_widget_->IsActive();
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayBubble::EnsureCollapsed() {
|
||||
if (!bubble_widget_ || is_qs_revamp_enabled_) {
|
||||
return;
|
||||
}
|
||||
|
||||
DCHECK(unified_view_);
|
||||
DCHECK(controller_);
|
||||
controller_->EnsureCollapsed();
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayBubble::EnsureExpanded() {
|
||||
if (!bubble_widget_) {
|
||||
return;
|
||||
}
|
||||
|
||||
DCHECK(unified_view_ || quick_settings_view_);
|
||||
DCHECK(controller_);
|
||||
controller_->EnsureExpanded();
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayBubble::CollapseWithoutAnimating() {
|
||||
if (!bubble_widget_ || is_qs_revamp_enabled_) {
|
||||
return;
|
||||
}
|
||||
|
||||
DCHECK(unified_view_);
|
||||
DCHECK(controller_);
|
||||
|
||||
controller_->CollapseWithoutAnimating();
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayBubble::CollapseMessageCenter() {
|
||||
if (is_qs_revamp_enabled_) {
|
||||
return;
|
||||
}
|
||||
unified_system_tray_->CollapseMessageCenter();
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayBubble::ExpandMessageCenter() {
|
||||
if (is_qs_revamp_enabled_) {
|
||||
return;
|
||||
}
|
||||
unified_system_tray_->ExpandMessageCenter();
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayBubble::ShowAudioDetailedView() {
|
||||
if (!bubble_widget_) {
|
||||
return;
|
||||
}
|
||||
|
||||
DCHECK(unified_view_ || quick_settings_view_);
|
||||
DCHECK(quick_settings_view_);
|
||||
DCHECK(controller_);
|
||||
controller_->ShowAudioDetailedView();
|
||||
}
|
||||
@ -208,7 +145,7 @@ void UnifiedSystemTrayBubble::ShowDisplayDetailedView() {
|
||||
return;
|
||||
}
|
||||
|
||||
DCHECK(unified_view_ || quick_settings_view_);
|
||||
DCHECK(quick_settings_view_);
|
||||
DCHECK(controller_);
|
||||
controller_->ShowDisplayDetailedView();
|
||||
}
|
||||
@ -231,19 +168,19 @@ void UnifiedSystemTrayBubble::ShowCalendarView(
|
||||
}
|
||||
}
|
||||
|
||||
DCHECK(unified_view_ || quick_settings_view_);
|
||||
DCHECK(quick_settings_view_);
|
||||
DCHECK(controller_);
|
||||
controller_->ShowCalendarView(show_source, event_source);
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayBubble::ShowNetworkDetailedView(bool force) {
|
||||
void UnifiedSystemTrayBubble::ShowNetworkDetailedView() {
|
||||
if (!bubble_widget_) {
|
||||
return;
|
||||
}
|
||||
|
||||
DCHECK(unified_view_ || quick_settings_view_);
|
||||
DCHECK(quick_settings_view_);
|
||||
DCHECK(controller_);
|
||||
controller_->ShowNetworkDetailedView(force);
|
||||
controller_->ShowNetworkDetailedView();
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayBubble::UpdateBubble() {
|
||||
@ -268,37 +205,12 @@ views::Widget* UnifiedSystemTrayBubble::GetBubbleWidget() const {
|
||||
}
|
||||
|
||||
int UnifiedSystemTrayBubble::GetCurrentTrayHeight() const {
|
||||
if (is_qs_revamp_enabled_) {
|
||||
CHECK(quick_settings_view_);
|
||||
return quick_settings_view_->GetCurrentHeight();
|
||||
}
|
||||
|
||||
return unified_view_->GetCurrentHeight();
|
||||
return quick_settings_view_->GetCurrentHeight();
|
||||
}
|
||||
|
||||
bool UnifiedSystemTrayBubble::FocusOut(bool reverse) {
|
||||
if (is_qs_revamp_enabled_) {
|
||||
return false;
|
||||
}
|
||||
return unified_system_tray_->FocusMessageCenter(reverse);
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayBubble::FocusEntered(bool reverse) {
|
||||
if (is_qs_revamp_enabled_) {
|
||||
return;
|
||||
}
|
||||
|
||||
unified_view_->FocusEntered(reverse);
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayBubble::OnMessageCenterActivated() {
|
||||
if (is_qs_revamp_enabled_) {
|
||||
return;
|
||||
}
|
||||
// When the message center is activated, we no longer need to reroute key
|
||||
// events to this bubble. Otherwise, we interfere with notifications that may
|
||||
// require key input like inline replies. See crbug.com/1040738.
|
||||
bubble_view_->StopReroutingEvents();
|
||||
// TODO(b/309529593) Remove this method and clean up the related code.
|
||||
return false;
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayBubble::OnDisplayConfigurationChanged() {
|
||||
@ -312,7 +224,6 @@ void UnifiedSystemTrayBubble::OnWidgetDestroying(views::Widget* widget) {
|
||||
|
||||
bubble_view_->RemoveAllChildViews();
|
||||
quick_settings_view_ = nullptr;
|
||||
unified_view_ = nullptr;
|
||||
bubble_view_->ResetDelegate();
|
||||
bubble_view_ = nullptr;
|
||||
|
||||
@ -345,7 +256,6 @@ void UnifiedSystemTrayBubble::OnAutoHideStateChanged(
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayBubble::UpdateBubbleHeight(bool is_showing_detiled_view) {
|
||||
DCHECK(is_qs_revamp_enabled_);
|
||||
if (!bubble_view_) {
|
||||
return;
|
||||
}
|
||||
@ -368,8 +278,7 @@ void UnifiedSystemTrayBubble::UpdateBubbleBounds() {
|
||||
!!bubble_widget_ && !!bubble_widget_->IsClosed());
|
||||
|
||||
// `bubble_view_` or `Shelf` may be null, see https://b/293264371,
|
||||
if (!bubble_view_ || (is_qs_revamp_enabled_ && !quick_settings_view_) ||
|
||||
(!is_qs_revamp_enabled_ && !unified_view_)) {
|
||||
if (!bubble_view_ || !quick_settings_view_) {
|
||||
return;
|
||||
}
|
||||
if (!unified_system_tray_->shelf()) {
|
||||
@ -379,18 +288,15 @@ void UnifiedSystemTrayBubble::UpdateBubbleBounds() {
|
||||
int max_height = CalculateMaxTrayBubbleHeight(
|
||||
unified_system_tray_->GetBubbleWindowContainer());
|
||||
if (bubble_view_->ShouldUseFixedHeight()) {
|
||||
DCHECK(is_qs_revamp_enabled_);
|
||||
const int qs_current_height = quick_settings_view_->height();
|
||||
max_height =
|
||||
std::min(max_height, std::max(qs_current_height, kDetailedViewHeight));
|
||||
}
|
||||
if (is_qs_revamp_enabled_) {
|
||||
// Setting the max height can result in the popup baseline being updated,
|
||||
// closing this bubble.
|
||||
quick_settings_view_->SetMaxHeight(max_height);
|
||||
} else {
|
||||
unified_view_->SetMaxHeight(max_height);
|
||||
}
|
||||
|
||||
// Setting the max height can result in the popup baseline being updated,
|
||||
// closing this bubble.
|
||||
quick_settings_view_->SetMaxHeight(max_height);
|
||||
|
||||
if (!bubble_view_) {
|
||||
// Updating the maximum height can result in popup baseline changing. If
|
||||
// there is not enough room for popups, the bubble will be closed, and this
|
||||
|
@ -34,10 +34,9 @@ namespace ash {
|
||||
class TrayEventFilter;
|
||||
class UnifiedSystemTray;
|
||||
class UnifiedSystemTrayController;
|
||||
class UnifiedSystemTrayView;
|
||||
class QuickSettingsView;
|
||||
|
||||
// Manages the bubble that contains UnifiedSystemTrayView.
|
||||
// Manages the bubble that contains 'QuickSettingsView'.
|
||||
// Shows the bubble on the constructor, and closes the bubble on the destructor.
|
||||
// It is possible that the bubble widget is closed on deactivation. In such
|
||||
// case, this class calls UnifiedSystemTray::CloseBubble() to delete itself.
|
||||
@ -65,21 +64,6 @@ class ASH_EXPORT UnifiedSystemTrayBubble : public TrayBubbleBase,
|
||||
// True if the bubble is active.
|
||||
bool IsBubbleActive() const;
|
||||
|
||||
// Collapse the message center bubble.
|
||||
void CollapseMessageCenter();
|
||||
|
||||
// Expand the message center bubble.
|
||||
void ExpandMessageCenter();
|
||||
|
||||
// Ensure the bubble is collapsed.
|
||||
void EnsureCollapsed();
|
||||
|
||||
// Ensure the bubble is expanded.
|
||||
void EnsureExpanded();
|
||||
|
||||
// Set the state to collapsed without animation.
|
||||
void CollapseWithoutAnimating();
|
||||
|
||||
// Show audio settings detailed view.
|
||||
void ShowAudioDetailedView();
|
||||
|
||||
@ -91,7 +75,7 @@ class ASH_EXPORT UnifiedSystemTrayBubble : public TrayBubbleBase,
|
||||
calendar_metrics::CalendarEventSource event_source);
|
||||
|
||||
// Show network settings detailed view.
|
||||
void ShowNetworkDetailedView(bool force);
|
||||
void ShowNetworkDetailedView();
|
||||
|
||||
// Update bubble bounds and focus if necessary.
|
||||
void UpdateBubble();
|
||||
@ -103,12 +87,6 @@ class ASH_EXPORT UnifiedSystemTrayBubble : public TrayBubbleBase,
|
||||
// Relinquish focus and transfer it to the message center widget.
|
||||
bool FocusOut(bool reverse);
|
||||
|
||||
// Inform UnifiedSystemTrayView of focus being acquired.
|
||||
void FocusEntered(bool reverse);
|
||||
|
||||
// Called when the message center widget is activated.
|
||||
void OnMessageCenterActivated();
|
||||
|
||||
// Fire a notification that an accessibility event has occured on this object.
|
||||
void NotifyAccessibilityEvent(ax::mojom::Event event, bool send_native_event);
|
||||
|
||||
@ -142,8 +120,6 @@ class ASH_EXPORT UnifiedSystemTrayBubble : public TrayBubbleBase,
|
||||
// the detailed page.
|
||||
void UpdateBubbleHeight(bool is_showing_detiled_view);
|
||||
|
||||
UnifiedSystemTrayView* unified_view() { return unified_view_; }
|
||||
|
||||
QuickSettingsView* quick_settings_view() { return quick_settings_view_; }
|
||||
|
||||
UnifiedSystemTrayController* unified_system_tray_controller() {
|
||||
@ -155,33 +131,30 @@ class ASH_EXPORT UnifiedSystemTrayBubble : public TrayBubbleBase,
|
||||
|
||||
void UpdateBubbleBounds();
|
||||
|
||||
// Controller of UnifiedSystemTrayView. As the view is owned by views
|
||||
// hierarchy, we have to own the controller here.
|
||||
// Controller of `QuickSettingsView`. As the view is owned by views hierarchy,
|
||||
// we have to own the controller here.
|
||||
std::unique_ptr<UnifiedSystemTrayController> controller_;
|
||||
|
||||
// Owner of this class.
|
||||
raw_ptr<UnifiedSystemTray, ExperimentalAsh> unified_system_tray_;
|
||||
|
||||
// Widget that contains `UnifiedSystemTrayView`. Unowned.
|
||||
// Widget that contains `QuickSettingsView`. Unowned.
|
||||
// When the widget is closed by deactivation, `bubble_widget_` pointer is
|
||||
// invalidated and we have to delete `UnifiedSystemTrayBubble` by calling
|
||||
// `UnifiedSystemTray::CloseBubble()`.
|
||||
// In order to do this, we observe `OnWidgetDestroying()`.
|
||||
raw_ptr<views::Widget, ExperimentalAsh> bubble_widget_ = nullptr;
|
||||
|
||||
// PreTargetHandler of |unified_view_| to record TimeToClick metrics. Owned.
|
||||
// PreTargetHandler of `quick_settings_view_` to record TimeToClick metrics.
|
||||
// Owned.
|
||||
std::unique_ptr<TimeToClickRecorder> time_to_click_recorder_;
|
||||
|
||||
// The time the bubble is created.
|
||||
absl::optional<base::TimeTicks> time_opened_;
|
||||
|
||||
raw_ptr<TrayBubbleView, ExperimentalAsh> bubble_view_ = nullptr;
|
||||
raw_ptr<UnifiedSystemTrayView, DanglingUntriaged> unified_view_ = nullptr;
|
||||
// Only non-null when QsRevamp is enabled.
|
||||
raw_ptr<QuickSettingsView, DanglingUntriaged> quick_settings_view_ = nullptr;
|
||||
|
||||
// Whether the QsRevamp feature is enabled.
|
||||
const bool is_qs_revamp_enabled_;
|
||||
raw_ptr<QuickSettingsView, DanglingUntriaged> quick_settings_view_ = nullptr;
|
||||
|
||||
std::unique_ptr<TrayEventFilter> tray_event_filter_;
|
||||
|
||||
|
@ -57,9 +57,7 @@
|
||||
#include "ash/system/tray/tray_utils.h"
|
||||
#include "ash/system/unified/deferred_update_dialog.h"
|
||||
#include "ash/system/unified/detailed_view_controller.h"
|
||||
#include "ash/system/unified/feature_pod_button.h"
|
||||
#include "ash/system/unified/feature_pod_controller_base.h"
|
||||
#include "ash/system/unified/feature_pods_container_view.h"
|
||||
#include "ash/system/unified/feature_tile.h"
|
||||
#include "ash/system/unified/feature_tiles_container_view.h"
|
||||
#include "ash/system/unified/quick_settings_metrics_util.h"
|
||||
@ -68,7 +66,6 @@
|
||||
#include "ash/system/unified/unified_notifier_settings_controller.h"
|
||||
#include "ash/system/unified/unified_system_tray_bubble.h"
|
||||
#include "ash/system/unified/unified_system_tray_model.h"
|
||||
#include "ash/system/unified/unified_system_tray_view.h"
|
||||
#include "ash/system/unified/user_chooser_detailed_view_controller.h"
|
||||
#include "ash/wm/lock_state_controller.h"
|
||||
#include "ash/wm/tablet_mode/tablet_mode_controller.h"
|
||||
@ -83,8 +80,6 @@
|
||||
#include "ui/compositor/compositor.h"
|
||||
#include "ui/display/screen.h"
|
||||
#include "ui/events/event.h"
|
||||
#include "ui/gfx/animation/slide_animation.h"
|
||||
#include "ui/message_center/message_center.h"
|
||||
#include "ui/views/widget/widget.h"
|
||||
|
||||
namespace ash {
|
||||
@ -110,22 +105,12 @@ UnifiedSystemTrayController::UnifiedSystemTrayController(
|
||||
scoped_refptr<UnifiedSystemTrayModel> model,
|
||||
UnifiedSystemTrayBubble* bubble,
|
||||
views::View* owner_view)
|
||||
: views::AnimationDelegateViews(owner_view),
|
||||
model_(model),
|
||||
: model_(model),
|
||||
bubble_(bubble),
|
||||
active_user_prefs_(
|
||||
Shell::Get()->session_controller()->GetLastActiveUserPrefService()),
|
||||
animation_(std::make_unique<gfx::SlideAnimation>(this)) {
|
||||
Shell::Get()->session_controller()->GetLastActiveUserPrefService()) {
|
||||
LoadIsExpandedPref();
|
||||
|
||||
const float animation_value = features::IsQsRevampEnabled()
|
||||
? 1
|
||||
: (model_->IsExpandedOnOpen() ? 1.0 : 0.0);
|
||||
animation_->Reset(animation_value);
|
||||
animation_->SetSlideDuration(
|
||||
base::Milliseconds(kSystemMenuCollapseExpandAnimationDurationMs));
|
||||
animation_->SetTweenType(gfx::Tween::EASE_IN_OUT);
|
||||
|
||||
model_->pagination_model()->SetTransitionDurations(base::Milliseconds(250),
|
||||
base::Milliseconds(50));
|
||||
|
||||
@ -165,37 +150,6 @@ void UnifiedSystemTrayController::OnActiveUserPrefServiceChanged(
|
||||
active_user_prefs_ = prefs;
|
||||
}
|
||||
|
||||
std::unique_ptr<UnifiedSystemTrayView>
|
||||
UnifiedSystemTrayController::CreateUnifiedQuickSettingsView() {
|
||||
DCHECK(!unified_view_);
|
||||
auto unified_view =
|
||||
std::make_unique<UnifiedSystemTrayView>(this, model_->IsExpandedOnOpen());
|
||||
unified_view_ = unified_view.get();
|
||||
|
||||
InitFeaturePods();
|
||||
|
||||
if (!Shell::Get()->session_controller()->IsScreenLocked() &&
|
||||
!MediaTray::IsPinnedToShelf()) {
|
||||
media_controls_controller_ =
|
||||
std::make_unique<UnifiedMediaControlsController>(this);
|
||||
unified_view->AddMediaControlsView(
|
||||
media_controls_controller_->CreateView());
|
||||
}
|
||||
|
||||
volume_slider_controller_ =
|
||||
std::make_unique<UnifiedVolumeSliderController>(this);
|
||||
unified_view->AddSliderView(volume_slider_controller_->CreateView());
|
||||
|
||||
brightness_slider_controller_ =
|
||||
std::make_unique<UnifiedBrightnessSliderController>(
|
||||
model_, views::Button::PressedCallback(base::BindRepeating(
|
||||
&UnifiedSystemTrayController::ShowDisplayDetailedView,
|
||||
base::Unretained(this))));
|
||||
unified_view->AddSliderView(brightness_slider_controller_->CreateView());
|
||||
|
||||
return unified_view;
|
||||
}
|
||||
|
||||
std::unique_ptr<QuickSettingsView>
|
||||
UnifiedSystemTrayController::CreateQuickSettingsView(int max_height) {
|
||||
DCHECK(!quick_settings_view_);
|
||||
@ -261,17 +215,10 @@ void UnifiedSystemTrayController::HandleLockAction() {
|
||||
|
||||
void UnifiedSystemTrayController::HandleSettingsAction() {
|
||||
base::RecordAction(base::UserMetricsAction("Tray_Settings"));
|
||||
if (features::IsQsRevampEnabled()) {
|
||||
Shell::Get()->system_tray_model()->client()->ShowSettings(
|
||||
display::Screen::GetScreen()
|
||||
->GetDisplayNearestView(
|
||||
quick_settings_view_->GetWidget()->GetNativeView())
|
||||
.id());
|
||||
return;
|
||||
}
|
||||
Shell::Get()->system_tray_model()->client()->ShowSettings(
|
||||
display::Screen::GetScreen()
|
||||
->GetDisplayNearestView(unified_view_->GetWidget()->GetNativeView())
|
||||
->GetDisplayNearestView(
|
||||
quick_settings_view_->GetWidget()->GetNativeView())
|
||||
.id());
|
||||
}
|
||||
|
||||
@ -318,177 +265,23 @@ void UnifiedSystemTrayController::HandleEnterpriseInfoAction() {
|
||||
Shell::Get()->system_tray_model()->client()->ShowEnterpriseInfo();
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayController::ToggleExpanded() {
|
||||
if (features::IsQsRevampEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (animation_->is_animating()) {
|
||||
return;
|
||||
}
|
||||
|
||||
UMA_HISTOGRAM_ENUMERATION("ChromeOS.SystemTray.ToggleExpanded",
|
||||
TOGGLE_EXPANDED_TYPE_BY_BUTTON,
|
||||
TOGGLE_EXPANDED_TYPE_COUNT);
|
||||
if (IsExpanded()) {
|
||||
StartAnimation(/*expand=*/false);
|
||||
// Expand message center when quick settings is collapsed.
|
||||
if (bubble_) {
|
||||
bubble_->ExpandMessageCenter();
|
||||
}
|
||||
} else {
|
||||
// Collapse the message center if screen height is limited after expanding
|
||||
// the quick settings to its full height.
|
||||
if (IsMessageCenterCollapseRequired()) {
|
||||
bubble_->CollapseMessageCenter();
|
||||
}
|
||||
StartAnimation(/*expand=*/true);
|
||||
}
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayController::BeginDrag(const gfx::PointF& location) {
|
||||
if (features::IsQsRevampEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateDragThreshold();
|
||||
// Ignore swipe collapsing when a detailed view is shown as it's confusing.
|
||||
if (detailed_view_controller_) {
|
||||
return;
|
||||
}
|
||||
drag_init_point_ = location;
|
||||
was_expanded_ = IsExpanded();
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayController::UpdateDrag(const gfx::PointF& location) {
|
||||
if (features::IsQsRevampEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Ignore swipe collapsing when a detailed view is shown as it's confusing.
|
||||
if (detailed_view_controller_) {
|
||||
return;
|
||||
}
|
||||
double drag_expanded_amount = GetDragExpandedAmount(location);
|
||||
animation_->Reset(drag_expanded_amount);
|
||||
UpdateExpandedAmount();
|
||||
|
||||
if (was_expanded_ &&
|
||||
drag_expanded_amount < kNotificationCenterDragExpandThreshold) {
|
||||
bubble_->ExpandMessageCenter();
|
||||
} else if (drag_expanded_amount >= kNotificationCenterDragExpandThreshold &&
|
||||
IsMessageCenterCollapseRequired()) {
|
||||
bubble_->CollapseMessageCenter();
|
||||
}
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayController::StartAnimation(bool expand) {
|
||||
// UnifiedSystemTrayControllerTest does not add `unified_view_` to a widget.
|
||||
if (features::IsQsRevampEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (unified_view_->GetWidget()) {
|
||||
animation_tracker_.emplace(unified_view_->GetWidget()
|
||||
->GetCompositor()
|
||||
->RequestNewThroughputTracker());
|
||||
animation_tracker_->Start(metrics_util::ForSmoothness(
|
||||
expand ? base::BindRepeating(&ReportExpandAnimationSmoothness)
|
||||
: base::BindRepeating(&ReportCollapseAnimationSmoothness)));
|
||||
}
|
||||
|
||||
if (expand) {
|
||||
animation_->Show();
|
||||
} else {
|
||||
// To animate to hidden state, first set SlideAnimation::IsShowing() to
|
||||
// true.
|
||||
animation_->Show();
|
||||
animation_->Hide();
|
||||
}
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayController::EndDrag(const gfx::PointF& location) {
|
||||
if (features::IsQsRevampEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Ignore swipe collapsing when a detailed view is shown as it's confusing.
|
||||
if (detailed_view_controller_) {
|
||||
return;
|
||||
}
|
||||
if (animation_->is_animating()) {
|
||||
// Prevent overwriting the state right after fling event
|
||||
return;
|
||||
}
|
||||
bool expanded = GetDragExpandedAmount(location) > 0.5;
|
||||
if (was_expanded_ != expanded) {
|
||||
UMA_HISTOGRAM_ENUMERATION("ChromeOS.SystemTray.ToggleExpanded",
|
||||
TOGGLE_EXPANDED_TYPE_BY_GESTURE,
|
||||
TOGGLE_EXPANDED_TYPE_COUNT);
|
||||
}
|
||||
|
||||
if (expanded && IsMessageCenterCollapseRequired()) {
|
||||
bubble_->CollapseMessageCenter();
|
||||
} else {
|
||||
bubble_->ExpandMessageCenter();
|
||||
}
|
||||
|
||||
// If dragging is finished, animate to closer state.
|
||||
StartAnimation(expanded);
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayController::Fling(int velocity) {
|
||||
if (features::IsQsRevampEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Ignore swipe collapsing when a detailed view is shown as it's confusing.
|
||||
if (detailed_view_controller_) {
|
||||
return;
|
||||
}
|
||||
// Expand when flinging up. Collapse otherwise.
|
||||
bool expand = (velocity < 0);
|
||||
|
||||
if (expand && IsMessageCenterCollapseRequired()) {
|
||||
bubble_->CollapseMessageCenter();
|
||||
} else {
|
||||
bubble_->ExpandMessageCenter();
|
||||
}
|
||||
|
||||
StartAnimation(expand);
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayController::ShowUserChooserView() {
|
||||
if (!UserChooserDetailedViewController::IsUserChooserEnabled()) {
|
||||
return;
|
||||
}
|
||||
animation_->Reset(1.0);
|
||||
UpdateExpandedAmount();
|
||||
ShowDetailedView(std::make_unique<UserChooserDetailedViewController>(this));
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayController::ShowNetworkDetailedView(bool force) {
|
||||
if (!force && !IsExpanded()) {
|
||||
return;
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayController::ShowNetworkDetailedView() {
|
||||
base::RecordAction(base::UserMetricsAction("StatusArea_Network_Detailed"));
|
||||
|
||||
ShowDetailedView(std::make_unique<NetworkDetailedViewController>(this));
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayController::ShowHotspotDetailedView() {
|
||||
DCHECK(features::IsQsRevampEnabled());
|
||||
|
||||
ShowDetailedView(std::make_unique<HotspotDetailedViewController>(this));
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayController::ShowBluetoothDetailedView() {
|
||||
// QSRevamp does not allow expand/collapse of the System Tray.
|
||||
if (!IsExpanded() && !features::IsQsRevampEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
base::RecordAction(base::UserMetricsAction("StatusArea_Bluetooth_Detailed"));
|
||||
ShowDetailedView(std::make_unique<BluetoothDetailedViewController>(this));
|
||||
}
|
||||
@ -582,30 +375,17 @@ void UnifiedSystemTrayController::TransitionToMainView(bool restore_focus) {
|
||||
// reference to its `detailed_view_controller_` which is used in shutdown.
|
||||
auto scoped_detailed_view_controller = std::move(detailed_view_controller_);
|
||||
|
||||
if (features::IsQsRevampEnabled()) {
|
||||
bubble_->UpdateBubbleHeight(/*is_showing_detiled_view=*/false);
|
||||
quick_settings_view_->ResetDetailedView();
|
||||
if (restore_focus) {
|
||||
quick_settings_view_->RestoreFocus();
|
||||
}
|
||||
UpdateBubble();
|
||||
return;
|
||||
}
|
||||
unified_view_->ResetDetailedView();
|
||||
bubble_->UpdateBubbleHeight(/*is_showing_detiled_view=*/false);
|
||||
quick_settings_view_->ResetDetailedView();
|
||||
if (restore_focus) {
|
||||
unified_view_->RestoreFocus();
|
||||
quick_settings_view_->RestoreFocus();
|
||||
}
|
||||
UpdateBubble();
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayController::CloseBubble() {
|
||||
if (features::IsQsRevampEnabled()) {
|
||||
if (quick_settings_view_->GetWidget()) {
|
||||
quick_settings_view_->GetWidget()->CloseNow();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (unified_view_->GetWidget()) {
|
||||
unified_view_->GetWidget()->CloseNow();
|
||||
if (quick_settings_view_->GetWidget()) {
|
||||
quick_settings_view_->GetWidget()->CloseNow();
|
||||
}
|
||||
}
|
||||
|
||||
@ -613,71 +393,12 @@ bool UnifiedSystemTrayController::FocusOut(bool reverse) {
|
||||
return bubble_->FocusOut(reverse);
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayController::EnsureCollapsed() {
|
||||
if (features::IsQsRevampEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsExpanded()) {
|
||||
animation_->Hide();
|
||||
}
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayController::EnsureExpanded() {
|
||||
if (detailed_view_controller_) {
|
||||
// If a detailed view is showing, first transit to the main view.
|
||||
TransitionToMainView(false);
|
||||
}
|
||||
StartAnimation(true /*expand*/);
|
||||
|
||||
if (IsMessageCenterCollapseRequired()) {
|
||||
bubble_->CollapseMessageCenter();
|
||||
}
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayController::AnimationEnded(
|
||||
const gfx::Animation* animation) {
|
||||
if (features::IsQsRevampEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (animation_tracker_) {
|
||||
animation_tracker_->Stop();
|
||||
animation_tracker_.reset();
|
||||
}
|
||||
|
||||
UpdateExpandedAmount();
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayController::AnimationProgressed(
|
||||
const gfx::Animation* animation) {
|
||||
if (features::IsQsRevampEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateExpandedAmount();
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayController::AnimationCanceled(
|
||||
const gfx::Animation* animation) {
|
||||
if (features::IsQsRevampEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
animation_->Reset(std::round(animation_->GetCurrentValue()));
|
||||
UpdateExpandedAmount();
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayController::OnAudioSettingsButtonClicked() {
|
||||
ShowAudioDetailedView();
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayController::ShowMediaControls() {
|
||||
if (features::IsQsRevampEnabled()) {
|
||||
quick_settings_view_->ShowMediaControls();
|
||||
return;
|
||||
}
|
||||
unified_view_->ShowMediaControls();
|
||||
quick_settings_view_->ShowMediaControls();
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayController::OnMediaControlsViewClicked() {
|
||||
@ -698,10 +419,6 @@ void UnifiedSystemTrayController::LoadIsExpandedPref() {
|
||||
}
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayController::InitFeaturePods() {
|
||||
// TODO(b/251724646): remove with `unified_view_`.
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayController::InitFeatureTiles() {
|
||||
std::vector<std::unique_ptr<FeatureTile>> tiles;
|
||||
|
||||
@ -773,23 +490,11 @@ void UnifiedSystemTrayController::InitFeatureTiles() {
|
||||
Shell::Get()->tablet_mode_controller()->InTabletMode());
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayController::AddFeaturePodItem(
|
||||
std::unique_ptr<FeaturePodControllerBase> controller) {
|
||||
// TODO(b/251724646): remove with `unified_view_`.
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayController::ShowDetailedView(
|
||||
std::unique_ptr<DetailedViewController> controller) {
|
||||
animation_->Reset(1.0);
|
||||
UpdateExpandedAmount();
|
||||
views::FocusManager* manager;
|
||||
if (features::IsQsRevampEnabled()) {
|
||||
quick_settings_view_->SaveFocus();
|
||||
manager = quick_settings_view_->GetFocusManager();
|
||||
} else {
|
||||
unified_view_->SaveFocus();
|
||||
manager = unified_view_->GetFocusManager();
|
||||
}
|
||||
quick_settings_view_->SaveFocus();
|
||||
manager = quick_settings_view_->GetFocusManager();
|
||||
|
||||
if (manager && manager->GetFocusedView()) {
|
||||
manager->ClearFocus();
|
||||
@ -797,12 +502,8 @@ void UnifiedSystemTrayController::ShowDetailedView(
|
||||
|
||||
showing_audio_detailed_view_ = false;
|
||||
showing_display_detailed_view_ = false;
|
||||
if (features::IsQsRevampEnabled()) {
|
||||
bubble_->UpdateBubbleHeight(/*is_showing_detiled_view=*/true);
|
||||
quick_settings_view_->SetDetailedView(controller->CreateView());
|
||||
} else {
|
||||
unified_view_->SetDetailedView(controller->CreateView());
|
||||
}
|
||||
bubble_->UpdateBubbleHeight(/*is_showing_detiled_view=*/true);
|
||||
quick_settings_view_->SetDetailedView(controller->CreateView());
|
||||
|
||||
detailed_view_controller_ = std::move(controller);
|
||||
|
||||
@ -814,83 +515,13 @@ void UnifiedSystemTrayController::ShowDetailedView(
|
||||
}
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayController::UpdateExpandedAmount() {
|
||||
if (quick_settings_view_) {
|
||||
return;
|
||||
}
|
||||
double expanded_amount = animation_->GetCurrentValue();
|
||||
unified_view_->SetExpandedAmount(expanded_amount);
|
||||
|
||||
if (expanded_amount == 0.0 || expanded_amount == 1.0) {
|
||||
model_->set_expanded_on_open(
|
||||
expanded_amount == 1.0
|
||||
? UnifiedSystemTrayModel::StateOnOpen::EXPANDED
|
||||
: UnifiedSystemTrayModel::StateOnOpen::COLLAPSED);
|
||||
}
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayController::ResetToCollapsedIfRequired() {
|
||||
if (quick_settings_view_) {
|
||||
return;
|
||||
}
|
||||
if (model_->IsExplicitlyExpanded()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (unified_view_->feature_pods_container()->row_count() ==
|
||||
kUnifiedFeaturePodMinRows) {
|
||||
CollapseWithoutAnimating();
|
||||
}
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayController::CollapseWithoutAnimating() {
|
||||
if (features::IsQsRevampEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
unified_view_->SetExpandedAmount(0.0);
|
||||
animation_->Reset(0);
|
||||
}
|
||||
|
||||
bool UnifiedSystemTrayController::IsDetailedViewShown() const {
|
||||
if (quick_settings_view_) {
|
||||
return quick_settings_view_->IsDetailedViewShown();
|
||||
}
|
||||
if (unified_view_) {
|
||||
return unified_view_->IsDetailedViewShown();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayController::UpdateDragThreshold() {
|
||||
if (features::IsQsRevampEnabled()) {
|
||||
return;
|
||||
}
|
||||
UnifiedSystemTrayView* unified_view = bubble_->unified_view();
|
||||
drag_threshold_ = unified_view->GetExpandedSystemTrayHeight() -
|
||||
unified_view->GetCollapsedSystemTrayHeight();
|
||||
}
|
||||
|
||||
double UnifiedSystemTrayController::GetDragExpandedAmount(
|
||||
const gfx::PointF& location) const {
|
||||
if (features::IsQsRevampEnabled()) {
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
double y_diff = (location - drag_init_point_).y();
|
||||
// If already expanded, only consider swiping down. Otherwise, only consider
|
||||
// swiping up.
|
||||
if (was_expanded_) {
|
||||
return std::clamp(1.0 - std::max(0.0, y_diff) / drag_threshold_, 0.0, 1.0);
|
||||
} else {
|
||||
return std::clamp(std::max(0.0, -y_diff) / drag_threshold_, 0.0, 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
bool UnifiedSystemTrayController::IsExpanded() const {
|
||||
return features::IsQsRevampEnabled() || animation_->IsShowing();
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayController::UpdateBubble() {
|
||||
if (!bubble_) {
|
||||
return;
|
||||
@ -898,29 +529,6 @@ void UnifiedSystemTrayController::UpdateBubble() {
|
||||
bubble_->UpdateBubble();
|
||||
}
|
||||
|
||||
bool UnifiedSystemTrayController::IsMessageCenterCollapseRequired() const {
|
||||
if (quick_settings_view_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!bubble_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Note: This calculaton should be the same as
|
||||
// UnifiedMessageCenterBubble::CalculateAvailableHeight().
|
||||
auto available_height = CalculateMaxTrayBubbleHeight(
|
||||
bubble_->GetTray()->GetBubbleWindowContainer());
|
||||
available_height -= unified_view_->GetExpandedSystemTrayHeight();
|
||||
available_height -= kUnifiedMessageCenterBubbleSpacing;
|
||||
return available_height < kMessageCenterCollapseThreshold;
|
||||
}
|
||||
|
||||
base::TimeDelta UnifiedSystemTrayController::GetAnimationDurationForReporting()
|
||||
const {
|
||||
return base::Milliseconds(kSystemMenuCollapseExpandAnimationDurationMs);
|
||||
}
|
||||
|
||||
bool UnifiedSystemTrayController::ShouldShowDeferredUpdateDialog() const {
|
||||
return Shell::Get()->system_tray_model()->update_model()->update_deferred() ==
|
||||
DeferredUpdateState::kShowDialog;
|
||||
|
@ -13,23 +13,14 @@
|
||||
#include "ash/system/audio/unified_volume_slider_controller.h"
|
||||
#include "ash/system/media/unified_media_controls_controller.h"
|
||||
#include "ash/system/time/calendar_metrics.h"
|
||||
#include "ash/system/time/calendar_model.h"
|
||||
#include "ash/system/unified/quick_settings_view.h"
|
||||
#include "ash/system/unified/unified_system_tray_model.h"
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "base/memory/scoped_refptr.h"
|
||||
#include "third_party/abseil-cpp/absl/types/optional.h"
|
||||
#include "ui/compositor/throughput_tracker.h"
|
||||
#include "ui/gfx/geometry/point.h"
|
||||
#include "ui/views/animation/animation_delegate_views.h"
|
||||
|
||||
class PrefRegistrySimple;
|
||||
class PrefService;
|
||||
|
||||
namespace gfx {
|
||||
class SlideAnimation;
|
||||
} // namespace gfx
|
||||
|
||||
namespace views {
|
||||
class View;
|
||||
} // namespace views
|
||||
@ -45,12 +36,10 @@ class UnifiedBrightnessSliderController;
|
||||
class UnifiedVolumeSliderController;
|
||||
class UnifiedSystemTrayBubble;
|
||||
class UnifiedSystemTrayModel;
|
||||
class UnifiedSystemTrayView;
|
||||
|
||||
// Controller class of UnifiedSystemTrayView. Handles events of the view.
|
||||
// Controller class of `QuickSettingsView`. Handles events of the view.
|
||||
class ASH_EXPORT UnifiedSystemTrayController
|
||||
: public views::AnimationDelegateViews,
|
||||
public SessionObserver,
|
||||
: public SessionObserver,
|
||||
public UnifiedVolumeSliderController::Delegate,
|
||||
public UnifiedMediaControlsController::Delegate {
|
||||
public:
|
||||
@ -81,7 +70,6 @@ class ASH_EXPORT UnifiedSystemTrayController
|
||||
static void RegisterProfilePrefs(PrefRegistrySimple* registry);
|
||||
|
||||
// Create the view in the bubble.
|
||||
std::unique_ptr<UnifiedSystemTrayView> CreateUnifiedQuickSettingsView();
|
||||
std::unique_ptr<QuickSettingsView> CreateQuickSettingsView(int max_height);
|
||||
|
||||
// Sign out from the current user. Called from the view.
|
||||
@ -100,20 +88,11 @@ class ASH_EXPORT UnifiedSystemTrayController
|
||||
void HandleOpenPowerSettingsAction();
|
||||
// Show enterprise managed device info. Called from the view.
|
||||
void HandleEnterpriseInfoAction();
|
||||
// Toggle expanded state of UnifiedSystemTrayView. Called from the view.
|
||||
void ToggleExpanded();
|
||||
|
||||
// Handle finger dragging and expand/collapse the view. Called from view.
|
||||
void BeginDrag(const gfx::PointF& location);
|
||||
void UpdateDrag(const gfx::PointF& location);
|
||||
void EndDrag(const gfx::PointF& location);
|
||||
void Fling(int velocity);
|
||||
|
||||
// Show user selector view. Called from the view.
|
||||
void ShowUserChooserView();
|
||||
// Show the detailed view of network. If |force| is true, it shows the
|
||||
// detailed view even if it's collapsed. Called from the view.
|
||||
void ShowNetworkDetailedView(bool force);
|
||||
// Show the detailed view of network. Called from the view.
|
||||
void ShowNetworkDetailedView();
|
||||
// Show the detailed view of hotspot. Called from the view.
|
||||
void ShowHotspotDetailedView();
|
||||
// Show the detailed view of bluetooth. If collapsed, it doesn't show the
|
||||
@ -154,35 +133,16 @@ class ASH_EXPORT UnifiedSystemTrayController
|
||||
// Close the bubble. Called from a detailed view controller.
|
||||
void CloseBubble();
|
||||
|
||||
// Inform UnifiedSystemTrayBubble that UnifiedSystemTrayView is requesting to
|
||||
// Inform `UnifiedSystemTrayBubble` that `QuickSettingsView` is requesting to
|
||||
// relinquish focus.
|
||||
bool FocusOut(bool reverse);
|
||||
|
||||
// Ensure the main view is collapsed. Called from the slider bubble
|
||||
// controller.
|
||||
void EnsureCollapsed();
|
||||
|
||||
// Ensure the main view is expanded. Called from the slider bubble controller.
|
||||
void EnsureExpanded();
|
||||
|
||||
// Collapse the tray without animating if there isn't sufficient space for the
|
||||
// notifications area.
|
||||
void ResetToCollapsedIfRequired();
|
||||
|
||||
// Collapse the tray without animating.
|
||||
void CollapseWithoutAnimating();
|
||||
|
||||
// Return whether a detailed view is currently being shown.
|
||||
bool IsDetailedViewShown() const;
|
||||
|
||||
// SessionObserver:
|
||||
void OnActiveUserPrefServiceChanged(PrefService* pref_service) override;
|
||||
|
||||
// views::AnimationDelegateViews:
|
||||
void AnimationEnded(const gfx::Animation* animation) override;
|
||||
void AnimationProgressed(const gfx::Animation* animation) override;
|
||||
void AnimationCanceled(const gfx::Animation* animation) override;
|
||||
|
||||
// UnifiedVolumeSliderController::Delegate:
|
||||
void OnAudioSettingsButtonClicked() override;
|
||||
|
||||
@ -193,9 +153,6 @@ class ASH_EXPORT UnifiedSystemTrayController
|
||||
// Sets whether the quick settings view should show the media view.
|
||||
void SetShowMediaView(bool show_media_view);
|
||||
|
||||
// Return true if UnifiedSystemTray is expanded.
|
||||
bool IsExpanded() const;
|
||||
|
||||
// Update the bubble view layout.
|
||||
void UpdateBubble();
|
||||
|
||||
@ -231,14 +188,6 @@ class ASH_EXPORT UnifiedSystemTrayController
|
||||
friend class UnifiedSystemTrayControllerTest;
|
||||
friend class UnifiedVolumeViewTest;
|
||||
|
||||
// How the expanded state is toggled. The enum is used to back an UMA
|
||||
// histogram and should be treated as append-only.
|
||||
enum ToggleExpandedType {
|
||||
TOGGLE_EXPANDED_TYPE_BY_BUTTON = 0,
|
||||
TOGGLE_EXPANDED_TYPE_BY_GESTURE,
|
||||
TOGGLE_EXPANDED_TYPE_COUNT
|
||||
};
|
||||
|
||||
// Type of a help page opened by the "Managed" indicator in the bubble. The
|
||||
// enum is used to back an UMA histogram and should be treated as append-only.
|
||||
enum ManagedType { MANAGED_TYPE_ENTERPRISE = 0, MANAGED_TYPE_COUNT };
|
||||
@ -246,51 +195,18 @@ class ASH_EXPORT UnifiedSystemTrayController
|
||||
// Loads the `kSystemTrayExpanded` pref to the model.
|
||||
void LoadIsExpandedPref();
|
||||
|
||||
// Initialize feature pod controllers and their views.
|
||||
// If you want to add a new feature pod item, you have to add here.
|
||||
void InitFeaturePods();
|
||||
|
||||
// Initialize feature pod controllers and their feature tile views.
|
||||
void InitFeatureTiles();
|
||||
|
||||
// Add the feature pod controller and its view.
|
||||
void AddFeaturePodItem(std::unique_ptr<FeaturePodControllerBase> controller);
|
||||
|
||||
// Show the detailed view.
|
||||
void ShowDetailedView(std::unique_ptr<DetailedViewController> controller);
|
||||
|
||||
// Update how much the view is expanded based on |animation_|.
|
||||
void UpdateExpandedAmount();
|
||||
|
||||
// Update the gesture distance by using the tray's collapsed and expanded
|
||||
// height.
|
||||
void UpdateDragThreshold();
|
||||
|
||||
// Return touch drag amount between 0.0 and 1.0. If expanding, it increases
|
||||
// towards 1.0. If collapsing, it decreases towards 0.0. If the view is
|
||||
// dragged to the same direction as the current state, it does not change the
|
||||
// value. For example, if the view is expanded and it's dragged to the top, it
|
||||
// keeps returning 1.0.
|
||||
double GetDragExpandedAmount(const gfx::PointF& location) const;
|
||||
|
||||
// Return true if message center needs to be collapsed due to limited
|
||||
// screen height.
|
||||
bool IsMessageCenterCollapseRequired() const;
|
||||
|
||||
// Starts animation to expand or collapse the bubble.
|
||||
void StartAnimation(bool expand);
|
||||
|
||||
// views::AnimationDelegateViews:
|
||||
base::TimeDelta GetAnimationDurationForReporting() const override;
|
||||
|
||||
bool ShouldShowDeferredUpdateDialog() const;
|
||||
|
||||
// Model that stores UI specific variables. Unowned.
|
||||
scoped_refptr<UnifiedSystemTrayModel> model_;
|
||||
|
||||
// Unowned. Owned by Views hierarchy.
|
||||
raw_ptr<UnifiedSystemTrayView, DanglingUntriaged | ExperimentalAsh>
|
||||
unified_view_ = nullptr;
|
||||
raw_ptr<QuickSettingsView, DanglingUntriaged | ExperimentalAsh>
|
||||
quick_settings_view_ = nullptr;
|
||||
|
||||
@ -324,24 +240,6 @@ class ASH_EXPORT UnifiedSystemTrayController
|
||||
raw_ptr<views::View, DanglingUntriaged | ExperimentalAsh>
|
||||
unified_brightness_view_ = nullptr;
|
||||
|
||||
// If the previous state is expanded or not. Only valid during dragging (from
|
||||
// BeginDrag to EndDrag).
|
||||
bool was_expanded_ = true;
|
||||
|
||||
// The last |location| passed to BeginDrag(). Only valid during dragging.
|
||||
gfx::PointF drag_init_point_;
|
||||
|
||||
// Threshold in pixel that fully collapses / expands the view through gesture.
|
||||
// Used to calculate the expanded amount that corresponds to gesture location
|
||||
// during drag.
|
||||
double drag_threshold_ = 0;
|
||||
|
||||
// Animation between expanded and collapsed states.
|
||||
std::unique_ptr<gfx::SlideAnimation> animation_;
|
||||
|
||||
// Tracks the smoothness of collapse and expand animation.
|
||||
absl::optional<ui::ThroughputTracker> animation_tracker_;
|
||||
|
||||
bool showing_audio_detailed_view_ = false;
|
||||
|
||||
bool showing_display_detailed_view_ = false;
|
||||
|
@ -5,29 +5,26 @@
|
||||
#include "ash/system/unified/unified_system_tray_controller.h"
|
||||
#include <memory>
|
||||
|
||||
#include "ash/constants/ash_features.h"
|
||||
#include "ash/system/brightness/unified_brightness_slider_controller.h"
|
||||
#include "ash/system/status_area_widget.h"
|
||||
#include "ash/system/unified/unified_system_tray_model.h"
|
||||
#include "ash/test/ash_test_base.h"
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "base/memory/scoped_refptr.h"
|
||||
#include "base/test/scoped_feature_list.h"
|
||||
#include "chromeos/ash/services/network_config/public/cpp/cros_network_config_test_helper.h"
|
||||
#include "ui/views/test/views_test_utils.h"
|
||||
#include "ui/views/view_observer.h"
|
||||
|
||||
namespace ash {
|
||||
|
||||
class QsRevampUnifiedSystemTrayControllerTest : public AshTestBase {
|
||||
class UnifiedSystemTrayControllerTest : public AshTestBase {
|
||||
public:
|
||||
QsRevampUnifiedSystemTrayControllerTest()
|
||||
: scoped_feature_list_(features::kQsRevamp) {}
|
||||
QsRevampUnifiedSystemTrayControllerTest(
|
||||
const QsRevampUnifiedSystemTrayControllerTest&) = delete;
|
||||
QsRevampUnifiedSystemTrayControllerTest& operator=(
|
||||
const QsRevampUnifiedSystemTrayControllerTest&) = delete;
|
||||
~QsRevampUnifiedSystemTrayControllerTest() override = default;
|
||||
UnifiedSystemTrayControllerTest() = default;
|
||||
UnifiedSystemTrayControllerTest(const UnifiedSystemTrayControllerTest&) =
|
||||
delete;
|
||||
UnifiedSystemTrayControllerTest& operator=(
|
||||
const UnifiedSystemTrayControllerTest&) = delete;
|
||||
~UnifiedSystemTrayControllerTest() override = default;
|
||||
|
||||
// AshTestBase:
|
||||
void SetUp() override {
|
||||
@ -67,20 +64,17 @@ class QsRevampUnifiedSystemTrayControllerTest : public AshTestBase {
|
||||
// Owned by `widget_`.
|
||||
raw_ptr<QuickSettingsView, DanglingUntriaged | ExperimentalAsh>
|
||||
quick_settings_view_;
|
||||
|
||||
base::test::ScopedFeatureList scoped_feature_list_;
|
||||
};
|
||||
|
||||
// Tests that setting the `UnifiedSystemTrayModel::StateOnOpen` pref to
|
||||
// collapsed is a no-op with the QSRevamp enabled.
|
||||
TEST_F(QsRevampUnifiedSystemTrayControllerTest, ExpandedPrefIsNoOp) {
|
||||
// collapsed is a no-op.
|
||||
TEST_F(UnifiedSystemTrayControllerTest, ExpandedPrefIsNoOp) {
|
||||
// Set the pref to collapsed, there should be no effect.
|
||||
model_->set_expanded_on_open(UnifiedSystemTrayModel::StateOnOpen::COLLAPSED);
|
||||
|
||||
InitializeQuickSettingsView();
|
||||
|
||||
EXPECT_TRUE(model_->IsExpandedOnOpen());
|
||||
EXPECT_TRUE(controller_->IsExpanded());
|
||||
}
|
||||
|
||||
} // namespace ash
|
||||
|
@ -26,7 +26,6 @@
|
||||
#include "ash/system/unified/ime_mode_view.h"
|
||||
#include "ash/system/unified/unified_slider_bubble_controller.h"
|
||||
#include "ash/system/unified/unified_system_tray_bubble.h"
|
||||
#include "ash/system/unified/unified_system_tray_view.h"
|
||||
#include "ash/system/video_conference/fake_video_conference_tray_controller.h"
|
||||
#include "ash/system/video_conference/video_conference_tray.h"
|
||||
#include "ash/test/ash_test_base.h"
|
||||
@ -59,9 +58,8 @@ constexpr char kQuickSettingsPageCountOnClose[] =
|
||||
using message_center::MessageCenter;
|
||||
using message_center::Notification;
|
||||
|
||||
class UnifiedSystemTrayTest
|
||||
: public AshTestBase,
|
||||
public testing::WithParamInterface<std::tuple<bool, bool>> {
|
||||
class UnifiedSystemTrayTest : public AshTestBase,
|
||||
public testing::WithParamInterface<bool> {
|
||||
public:
|
||||
UnifiedSystemTrayTest()
|
||||
: AshTestBase(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
|
||||
@ -71,20 +69,14 @@ class UnifiedSystemTrayTest
|
||||
|
||||
void SetUp() override {
|
||||
std::vector<base::test::FeatureRef> enabled_features;
|
||||
std::vector<base::test::FeatureRef> disabled_features;
|
||||
|
||||
enabled_features.push_back(features::kCameraEffectsSupportedByHardware);
|
||||
if (IsQsRevampEnabled()) {
|
||||
enabled_features.push_back(features::kQsRevamp);
|
||||
} else {
|
||||
disabled_features.push_back(features::kQsRevamp);
|
||||
}
|
||||
if (IsVcControlsUiEnabled()) {
|
||||
fake_video_conference_tray_controller_ =
|
||||
std::make_unique<FakeVideoConferenceTrayController>();
|
||||
enabled_features.push_back(features::kVideoConference);
|
||||
}
|
||||
feature_list_.InitWithFeatures(enabled_features, disabled_features);
|
||||
feature_list_.InitWithFeatures(enabled_features, {});
|
||||
AshTestBase::SetUp();
|
||||
}
|
||||
|
||||
@ -96,10 +88,7 @@ class UnifiedSystemTrayTest
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(b/305075031) clean up after the flag is removed.
|
||||
bool IsQsRevampEnabled() { return true; }
|
||||
|
||||
bool IsVcControlsUiEnabled() { return std::get<1>(GetParam()); }
|
||||
bool IsVcControlsUiEnabled() { return GetParam(); }
|
||||
|
||||
protected:
|
||||
const std::string AddNotification() {
|
||||
@ -120,10 +109,8 @@ class UnifiedSystemTrayTest
|
||||
}
|
||||
|
||||
// Show the notification center bubble. This assumes that there is at least
|
||||
// one notification in the notification list. This should only be called
|
||||
// when QsRevamp is enabled.
|
||||
// one notification in the notification list.
|
||||
void ShowNotificationBubble() {
|
||||
DCHECK(IsQsRevampEnabled());
|
||||
Shell::Get()
|
||||
->GetPrimaryRootWindowController()
|
||||
->shelf()
|
||||
@ -133,9 +120,8 @@ class UnifiedSystemTrayTest
|
||||
}
|
||||
|
||||
// Hide the notification center bubble. This assumes that it is already
|
||||
// shown. This should only be called when QsRevamp is enabled.
|
||||
// shown.
|
||||
void HideNotificationBubble() {
|
||||
DCHECK(IsQsRevampEnabled());
|
||||
Shell::Get()
|
||||
->GetPrimaryRootWindowController()
|
||||
->shelf()
|
||||
@ -187,17 +173,13 @@ class UnifiedSystemTrayTest
|
||||
// `DateTray` becomes inactive.
|
||||
EXPECT_TRUE(tray->is_active());
|
||||
EXPECT_FALSE(date_tray()->is_active());
|
||||
// For QsRevamp: the main bubble is shorter than the detailed view bubble.
|
||||
// The main bubble is shorter than the detailed view bubble.
|
||||
EXPECT_GT(kQsDetailedViewHeight, bubble_view->height());
|
||||
}
|
||||
|
||||
void CheckDetailedViewHeight(TrayBubbleView* bubble_view) {
|
||||
if (IsQsRevampEnabled()) {
|
||||
// The bubble height should be fixed to the detailed view height.
|
||||
EXPECT_EQ(kQsDetailedViewHeight, bubble_view->height());
|
||||
} else {
|
||||
EXPECT_GT(kQsDetailedViewHeight, bubble_view->height());
|
||||
}
|
||||
// The bubble height should be fixed to the detailed view height.
|
||||
EXPECT_EQ(kQsDetailedViewHeight, bubble_view->height());
|
||||
}
|
||||
|
||||
TimeTrayItemView* time_view() {
|
||||
@ -227,23 +209,18 @@ class UnifiedSystemTrayTest
|
||||
base::test::ScopedFeatureList feature_list_;
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
All,
|
||||
UnifiedSystemTrayTest,
|
||||
testing::Combine(testing::Bool() /* IsQsRevampEnabled() */,
|
||||
testing::Bool() /* IsVcControlsUiEnabled() */));
|
||||
INSTANTIATE_TEST_SUITE_P(All,
|
||||
UnifiedSystemTrayTest,
|
||||
testing::Bool() /*IsVcControlsUiEnabled()*/);
|
||||
|
||||
// Regression test for crbug/1360579
|
||||
TEST_P(UnifiedSystemTrayTest, GetAccessibleNameForQuickSettingsBubble) {
|
||||
auto* tray = GetPrimaryUnifiedSystemTray();
|
||||
tray->ShowBubble();
|
||||
|
||||
EXPECT_EQ(
|
||||
tray->GetAccessibleNameForQuickSettingsBubble(),
|
||||
l10n_util::GetStringUTF16(
|
||||
IsQsRevampEnabled()
|
||||
? IDS_ASH_REVAMPED_QUICK_SETTINGS_BUBBLE_ACCESSIBLE_DESCRIPTION
|
||||
: IDS_ASH_QUICK_SETTINGS_BUBBLE_ACCESSIBLE_DESCRIPTION));
|
||||
EXPECT_EQ(tray->GetAccessibleNameForQuickSettingsBubble(),
|
||||
l10n_util::GetStringUTF16(
|
||||
IDS_ASH_QUICK_SETTINGS_BUBBLE_ACCESSIBLE_DESCRIPTION));
|
||||
}
|
||||
|
||||
TEST_P(UnifiedSystemTrayTest, ShowVolumeSliderBubble) {
|
||||
@ -379,32 +356,15 @@ TEST_P(UnifiedSystemTrayTest, FocusQuickSettings) {
|
||||
auto* tray = GetPrimaryUnifiedSystemTray();
|
||||
tray->ShowBubble();
|
||||
|
||||
if (IsQsRevampEnabled()) {
|
||||
auto* quick_settings_view = tray->bubble()->quick_settings_view();
|
||||
auto* focus_manager = quick_settings_view->GetFocusManager();
|
||||
EXPECT_FALSE(
|
||||
quick_settings_view->Contains(focus_manager->GetFocusedView()));
|
||||
auto* quick_settings_view = tray->bubble()->quick_settings_view();
|
||||
auto* focus_manager = quick_settings_view->GetFocusManager();
|
||||
EXPECT_FALSE(quick_settings_view->Contains(focus_manager->GetFocusedView()));
|
||||
|
||||
// There's no `FocusQuickSettings` method in the new view. Press the tab key
|
||||
// should focus on the first button in the qs bubble.
|
||||
ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
|
||||
generator.PressKey(ui::KeyboardCode::VKEY_TAB, ui::EF_NONE);
|
||||
EXPECT_TRUE(quick_settings_view->Contains(focus_manager->GetFocusedView()));
|
||||
return;
|
||||
}
|
||||
|
||||
auto* unified_system_tray_view = tray->bubble()->unified_view();
|
||||
auto* focus_manager = unified_system_tray_view->GetFocusManager();
|
||||
|
||||
EXPECT_FALSE(
|
||||
unified_system_tray_view->Contains(focus_manager->GetFocusedView()));
|
||||
|
||||
auto did_focus = tray->FocusQuickSettings(false);
|
||||
|
||||
EXPECT_TRUE(did_focus);
|
||||
|
||||
EXPECT_TRUE(
|
||||
unified_system_tray_view->Contains(focus_manager->GetFocusedView()));
|
||||
// There's no `FocusQuickSettings` method in the new view. Press the tab key
|
||||
// should focus on the first button in the qs bubble.
|
||||
ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
|
||||
generator.PressKey(ui::KeyboardCode::VKEY_TAB, ui::EF_NONE);
|
||||
EXPECT_TRUE(quick_settings_view->Contains(focus_manager->GetFocusedView()));
|
||||
}
|
||||
|
||||
TEST_P(UnifiedSystemTrayTest, FocusQuickSettings_BubbleNotShown) {
|
||||
@ -428,21 +388,10 @@ TEST_P(UnifiedSystemTrayTest, FocusQuickSettings_VoxEnabled) {
|
||||
|
||||
EXPECT_TRUE(did_focus);
|
||||
|
||||
if (IsQsRevampEnabled()) {
|
||||
auto* quick_settings_view = tray->bubble()->quick_settings_view();
|
||||
auto* focus_manager = quick_settings_view->GetFocusManager();
|
||||
EXPECT_TRUE(tray_bubble_widget->IsActive());
|
||||
EXPECT_FALSE(
|
||||
quick_settings_view->Contains(focus_manager->GetFocusedView()));
|
||||
return;
|
||||
}
|
||||
|
||||
auto* unified_system_tray_view = tray->bubble()->unified_view();
|
||||
auto* focus_manager = unified_system_tray_view->GetFocusManager();
|
||||
|
||||
auto* quick_settings_view = tray->bubble()->quick_settings_view();
|
||||
auto* focus_manager = quick_settings_view->GetFocusManager();
|
||||
EXPECT_TRUE(tray_bubble_widget->IsActive());
|
||||
EXPECT_FALSE(
|
||||
unified_system_tray_view->Contains(focus_manager->GetFocusedView()));
|
||||
EXPECT_FALSE(quick_settings_view->Contains(focus_manager->GetFocusedView()));
|
||||
}
|
||||
|
||||
TEST_P(UnifiedSystemTrayTest, TimeInQuickSettingsMetric) {
|
||||
@ -480,7 +429,7 @@ TEST_P(UnifiedSystemTrayTest, TimeInQuickSettingsMetric) {
|
||||
}
|
||||
|
||||
// Tests that the number of quick settings pages is recorded when the QS bubble
|
||||
// is closed. Tests that the metric is not recorded when QsRevamp is disabled.
|
||||
// is closed.
|
||||
TEST_P(UnifiedSystemTrayTest, QuickSettingsPageCountMetric) {
|
||||
base::HistogramTester histogram_tester;
|
||||
|
||||
@ -496,12 +445,10 @@ TEST_P(UnifiedSystemTrayTest, QuickSettingsPageCountMetric) {
|
||||
|
||||
// Close the bubble and verify that the metric is recorded.
|
||||
tray->CloseBubble();
|
||||
histogram_tester.ExpectTotalCount(kQuickSettingsPageCountOnClose,
|
||||
IsQsRevampEnabled() ? 1 : 0);
|
||||
histogram_tester.ExpectBucketCount(
|
||||
kQuickSettingsPageCountOnClose,
|
||||
/*sample=*/1,
|
||||
/*expected_count=*/IsQsRevampEnabled() ? 1 : 0);
|
||||
histogram_tester.ExpectTotalCount(kQuickSettingsPageCountOnClose, 1);
|
||||
histogram_tester.ExpectBucketCount(kQuickSettingsPageCountOnClose,
|
||||
/*sample=*/1,
|
||||
/*expected_count=*/1);
|
||||
|
||||
// Show the bubble with two pages, and verify that the metric is recorded when
|
||||
// the bubble is closed.
|
||||
@ -512,16 +459,13 @@ TEST_P(UnifiedSystemTrayTest, QuickSettingsPageCountMetric) {
|
||||
->pagination_model()
|
||||
->SetTotalPages(2);
|
||||
tray->CloseBubble();
|
||||
histogram_tester.ExpectTotalCount(kQuickSettingsPageCountOnClose,
|
||||
IsQsRevampEnabled() ? 2 : 0);
|
||||
histogram_tester.ExpectBucketCount(
|
||||
kQuickSettingsPageCountOnClose,
|
||||
/*sample=*/2,
|
||||
/*expected_count=*/IsQsRevampEnabled() ? 1 : 0);
|
||||
histogram_tester.ExpectBucketCount(
|
||||
kQuickSettingsPageCountOnClose,
|
||||
/*sample=*/1,
|
||||
/*expected_count=*/IsQsRevampEnabled() ? 1 : 0);
|
||||
histogram_tester.ExpectTotalCount(kQuickSettingsPageCountOnClose, 2);
|
||||
histogram_tester.ExpectBucketCount(kQuickSettingsPageCountOnClose,
|
||||
/*sample=*/2,
|
||||
/*expected_count=*/1);
|
||||
histogram_tester.ExpectBucketCount(kQuickSettingsPageCountOnClose,
|
||||
/*sample=*/1,
|
||||
/*expected_count=*/1);
|
||||
}
|
||||
|
||||
// Tests that pressing the TOGGLE_CALENDAR accelerator once results in the
|
||||
@ -559,8 +503,7 @@ TEST_P(UnifiedSystemTrayTest, CalendarAcceleratorFocusesDateCell) {
|
||||
}
|
||||
|
||||
// Tests that using functional keys to change brightness/volume when the
|
||||
// `CalendarView` is open will make ink drop transfer(before and after
|
||||
// QsRevamp) and bubble height change(after QsRevamp).
|
||||
// `CalendarView` is open will make ink drop transfer and bubble height change.
|
||||
TEST_P(UnifiedSystemTrayTest, CalendarGoesToMainViewByFunctionalKeys) {
|
||||
auto* tray = GetPrimaryUnifiedSystemTray();
|
||||
tray->ShowBubble();
|
||||
@ -574,7 +517,7 @@ TEST_P(UnifiedSystemTrayTest, CalendarGoesToMainViewByFunctionalKeys) {
|
||||
// Tests the volume up/down/mute functional keys. It should hide the calendar
|
||||
// view and open the `unified_system_tray_bubble_`. The ink drop should
|
||||
// transfer from `DateTray` to `UnifiedSystemTray` and the `bubble_view`
|
||||
// should shrink for the revamped Qs main page.
|
||||
// should shrink for the Qs main page.
|
||||
TransferFromCalendarViewToMainViewByFuncKeys(tray, bubble_view,
|
||||
ui::VKEY_VOLUME_UP);
|
||||
TransferFromCalendarViewToMainViewByFuncKeys(tray, bubble_view,
|
||||
@ -783,11 +726,6 @@ TEST_P(UnifiedSystemTrayTest, TrayBackgroundColorAfterSwitchToTabletMode) {
|
||||
// Tests that the bubble automatically hides if it is visible when another
|
||||
// bubble becomes visible, and otherwise does not automatically show or hide.
|
||||
TEST_P(UnifiedSystemTrayTest, BubbleHideBehavior) {
|
||||
// This hiding behavior only applies when QsRevamp is enabled.
|
||||
if (!IsQsRevampEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Basic verification test that the unified system tray bubble can show/hide
|
||||
// itself when no other bubbles are visible.
|
||||
auto* tray = GetPrimaryUnifiedSystemTray();
|
||||
@ -860,11 +798,6 @@ TEST_P(UnifiedSystemTrayTest, BubbleViewSizeChangeNoEnoughSpace) {
|
||||
}
|
||||
|
||||
TEST_P(UnifiedSystemTrayTest, BubbleViewSizeChangeWithBigMainPage) {
|
||||
// No QuickSettingsView in the old unified system bubble.
|
||||
if (!IsQsRevampEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Set a large enough screen size.
|
||||
UpdateDisplay("1600x900");
|
||||
|
||||
|
@ -1,508 +0,0 @@
|
||||
// Copyright 2018 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "ash/system/unified/unified_system_tray_view.h"
|
||||
|
||||
#include <numeric>
|
||||
|
||||
#include "ash/public/cpp/shelf_config.h"
|
||||
#include "ash/session/session_controller_impl.h"
|
||||
#include "ash/shell.h"
|
||||
#include "ash/system/media/unified_media_controls_container.h"
|
||||
#include "ash/system/message_center/ash_message_center_lock_screen_controller.h"
|
||||
#include "ash/system/notification_center/notification_center_view.h"
|
||||
#include "ash/system/tray/interacted_by_tap_recorder.h"
|
||||
#include "ash/system/tray/tray_constants.h"
|
||||
#include "ash/system/unified/detailed_view_controller.h"
|
||||
#include "ash/system/unified/feature_pod_button.h"
|
||||
#include "ash/system/unified/feature_pods_container_view.h"
|
||||
#include "ash/system/unified/notification_hidden_view.h"
|
||||
#include "ash/system/unified/page_indicator_view.h"
|
||||
#include "ash/system/unified/top_shortcuts_view.h"
|
||||
#include "ash/system/unified/unified_system_info_view.h"
|
||||
#include "ash/system/unified/unified_system_tray_controller.h"
|
||||
#include "ash/system/unified/unified_system_tray_model.h"
|
||||
#include "ash/wm/tablet_mode/tablet_mode_controller.h"
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "ui/accessibility/ax_enums.mojom.h"
|
||||
#include "ui/accessibility/ax_node_data.h"
|
||||
#include "ui/compositor/layer.h"
|
||||
#include "ui/gfx/canvas.h"
|
||||
#include "ui/gfx/scoped_canvas.h"
|
||||
#include "ui/message_center/message_center.h"
|
||||
#include "ui/message_center/public/cpp/message_center_constants.h"
|
||||
#include "ui/views/background.h"
|
||||
#include "ui/views/border.h"
|
||||
#include "ui/views/focus/focus_search.h"
|
||||
#include "ui/views/layout/box_layout.h"
|
||||
#include "ui/views/painter.h"
|
||||
|
||||
namespace ash {
|
||||
|
||||
namespace {
|
||||
|
||||
// The padding between sliders inside the `UnifiedSlidersContainerView`.
|
||||
const int kSlidersPadding = 8;
|
||||
|
||||
class DetailedViewContainer : public views::View {
|
||||
public:
|
||||
DetailedViewContainer() = default;
|
||||
|
||||
DetailedViewContainer(const DetailedViewContainer&) = delete;
|
||||
DetailedViewContainer& operator=(const DetailedViewContainer&) = delete;
|
||||
|
||||
~DetailedViewContainer() override = default;
|
||||
|
||||
// views::View:
|
||||
void Layout() override {
|
||||
for (auto* child : children()) {
|
||||
child->SetBoundsRect(GetContentsBounds());
|
||||
}
|
||||
views::View::Layout();
|
||||
}
|
||||
|
||||
const char* GetClassName() const override { return "DetailedViewContainer"; }
|
||||
};
|
||||
|
||||
class AccessibilityFocusHelperView : public views::View {
|
||||
public:
|
||||
AccessibilityFocusHelperView(UnifiedSystemTrayController* controller)
|
||||
: controller_(controller) {}
|
||||
|
||||
bool HandleAccessibleAction(const ui::AXActionData& action_data) override {
|
||||
GetFocusManager()->ClearFocus();
|
||||
GetFocusManager()->SetStoredFocusView(nullptr);
|
||||
controller_->FocusOut(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
// views::View:
|
||||
void GetAccessibleNodeData(ui::AXNodeData* node_data) override {
|
||||
node_data->role = ax::mojom::Role::kListItem;
|
||||
}
|
||||
|
||||
private:
|
||||
raw_ptr<UnifiedSystemTrayController, DanglingUntriaged | ExperimentalAsh>
|
||||
controller_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
UnifiedSlidersContainerView::UnifiedSlidersContainerView(
|
||||
bool initially_expanded)
|
||||
: expanded_amount_(initially_expanded ? 1.0 : 0.0) {
|
||||
SetVisible(initially_expanded);
|
||||
}
|
||||
|
||||
UnifiedSlidersContainerView::~UnifiedSlidersContainerView() = default;
|
||||
|
||||
void UnifiedSlidersContainerView::SetExpandedAmount(double expanded_amount) {
|
||||
DCHECK(0.0 <= expanded_amount && expanded_amount <= 1.0);
|
||||
SetVisible(expanded_amount > 0.0);
|
||||
expanded_amount_ = expanded_amount;
|
||||
InvalidateLayout();
|
||||
UpdateOpacity();
|
||||
}
|
||||
|
||||
int UnifiedSlidersContainerView::GetExpandedHeight() const {
|
||||
return std::accumulate(
|
||||
children().cbegin(), children().cend(), 0, [](int height, const auto* v) {
|
||||
return height + v->GetHeightForWidth(kTrayMenuWidth) + kSlidersPadding;
|
||||
});
|
||||
}
|
||||
|
||||
void UnifiedSlidersContainerView::Layout() {
|
||||
int y = 0;
|
||||
for (auto* child : children()) {
|
||||
int height = child->GetHeightForWidth(kTrayMenuWidth);
|
||||
child->SetBounds(0, y, kTrayMenuWidth, height);
|
||||
y += height + kSlidersPadding;
|
||||
}
|
||||
}
|
||||
|
||||
gfx::Size UnifiedSlidersContainerView::CalculatePreferredSize() const {
|
||||
return gfx::Size(kTrayMenuWidth, GetExpandedHeight() * expanded_amount_);
|
||||
}
|
||||
|
||||
const char* UnifiedSlidersContainerView::GetClassName() const {
|
||||
return "UnifiedSlidersContainerView";
|
||||
}
|
||||
|
||||
void UnifiedSlidersContainerView::UpdateOpacity() {
|
||||
const int height = GetPreferredSize().height();
|
||||
for (auto* child : children()) {
|
||||
double opacity = 1.0;
|
||||
if (child->y() > height) {
|
||||
opacity = 0.0;
|
||||
} else if (child->bounds().bottom() < height) {
|
||||
opacity = 1.0;
|
||||
} else {
|
||||
const double ratio =
|
||||
static_cast<double>(height - child->y()) / child->height();
|
||||
// TODO(tetsui): Confirm the animation curve with UX.
|
||||
opacity = std::max(0., 2. * ratio - 1.);
|
||||
}
|
||||
child->layer()->SetOpacity(opacity);
|
||||
}
|
||||
}
|
||||
|
||||
// The container view for the system tray, i.e. the panel containing settings
|
||||
// buttons and sliders (e.g. sign out, lock, volume slider, etc.).
|
||||
class UnifiedSystemTrayView::SystemTrayContainer : public views::View {
|
||||
public:
|
||||
SystemTrayContainer()
|
||||
: layout_manager_(SetLayoutManager(std::make_unique<views::BoxLayout>(
|
||||
views::BoxLayout::Orientation::kVertical))) {}
|
||||
SystemTrayContainer(const SystemTrayContainer&) = delete;
|
||||
SystemTrayContainer& operator=(const SystemTrayContainer&) = delete;
|
||||
|
||||
~SystemTrayContainer() override = default;
|
||||
|
||||
void SetFlexForView(views::View* view) {
|
||||
DCHECK_EQ(view->parent(), this);
|
||||
layout_manager_->SetFlexForView(view, 1);
|
||||
}
|
||||
|
||||
// views::View:
|
||||
void ChildPreferredSizeChanged(views::View* child) override {
|
||||
PreferredSizeChanged();
|
||||
}
|
||||
|
||||
const char* GetClassName() const override { return "SystemTrayContainer"; }
|
||||
|
||||
private:
|
||||
const raw_ptr<views::BoxLayout, ExperimentalAsh> layout_manager_;
|
||||
};
|
||||
|
||||
UnifiedSystemTrayView::UnifiedSystemTrayView(
|
||||
UnifiedSystemTrayController* controller,
|
||||
bool initially_expanded)
|
||||
: expanded_amount_(initially_expanded ? 1.0 : 0.0),
|
||||
controller_(controller),
|
||||
notification_hidden_view_(new NotificationHiddenView()),
|
||||
top_shortcuts_view_(new TopShortcutsView(controller_)),
|
||||
feature_pods_container_(
|
||||
new FeaturePodsContainerView(controller_, initially_expanded)),
|
||||
page_indicator_view_(
|
||||
new PageIndicatorView(controller_, initially_expanded)),
|
||||
sliders_container_(new UnifiedSlidersContainerView(initially_expanded)),
|
||||
system_info_view_(new UnifiedSystemInfoView(controller_)),
|
||||
system_tray_container_(new SystemTrayContainer()),
|
||||
detailed_view_container_(new DetailedViewContainer()),
|
||||
media_controls_container_(new UnifiedMediaControlsContainer()),
|
||||
focus_search_(std::make_unique<views::FocusSearch>(this, false, false)),
|
||||
interacted_by_tap_recorder_(
|
||||
std::make_unique<InteractedByTapRecorder>(this)) {
|
||||
DCHECK(controller_);
|
||||
|
||||
auto add_layered_child = [](views::View* parent, views::View* child) {
|
||||
parent->AddChildView(child);
|
||||
};
|
||||
|
||||
SessionControllerImpl* session_controller =
|
||||
Shell::Get()->session_controller();
|
||||
|
||||
notification_hidden_view_->SetVisible(
|
||||
session_controller->GetUserSession(0) &&
|
||||
session_controller->IsScreenLocked() &&
|
||||
!AshMessageCenterLockScreenController::IsEnabled());
|
||||
add_layered_child(system_tray_container_, notification_hidden_view_);
|
||||
|
||||
AddChildView(system_tray_container_.get());
|
||||
|
||||
add_layered_child(system_tray_container_, top_shortcuts_view_);
|
||||
system_tray_container_->AddChildView(feature_pods_container_.get());
|
||||
system_tray_container_->AddChildView(page_indicator_view_.get());
|
||||
|
||||
system_tray_container_->AddChildView(media_controls_container_.get());
|
||||
media_controls_container_->SetExpandedAmount(expanded_amount_);
|
||||
|
||||
system_tray_container_->AddChildView(sliders_container_.get());
|
||||
|
||||
add_layered_child(system_tray_container_, system_info_view_);
|
||||
|
||||
system_tray_container_->SetFlexForView(page_indicator_view_);
|
||||
|
||||
detailed_view_container_->SetVisible(false);
|
||||
add_layered_child(this, detailed_view_container_);
|
||||
|
||||
top_shortcuts_view_->SetExpandedAmount(expanded_amount_);
|
||||
|
||||
system_tray_container_->AddChildView(
|
||||
new AccessibilityFocusHelperView(controller_));
|
||||
}
|
||||
|
||||
UnifiedSystemTrayView::~UnifiedSystemTrayView() = default;
|
||||
|
||||
void UnifiedSystemTrayView::SetMaxHeight(int max_height) {
|
||||
max_height_ = max_height;
|
||||
|
||||
// FeaturePodsContainer can adjust it's height by reducing the number of rows
|
||||
// it uses. It will calculate how many rows to use based on the max height
|
||||
// passed here.
|
||||
feature_pods_container_->SetMaxHeight(
|
||||
max_height - top_shortcuts_view_->GetPreferredSize().height() -
|
||||
page_indicator_view_->GetPreferredSize().height() -
|
||||
media_controls_container_->GetExpandedHeight() -
|
||||
sliders_container_->GetExpandedHeight() -
|
||||
system_info_view_->GetPreferredSize().height());
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayView::AddFeaturePodButton(FeaturePodButton* button) {
|
||||
feature_pods_container_->AddFeaturePodButton(button);
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayView::AddSliderView(
|
||||
std::unique_ptr<views::View> slider_view) {
|
||||
sliders_container_->AddChildView(std::move(slider_view));
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayView::AddMediaControlsView(views::View* media_controls) {
|
||||
DCHECK(media_controls);
|
||||
|
||||
media_controls->SetPaintToLayer();
|
||||
media_controls->layer()->SetFillsBoundsOpaquely(false);
|
||||
media_controls_container_->AddChildView(media_controls);
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayView::ShowMediaControls() {
|
||||
media_controls_container_->SetShouldShowMediaControls(true);
|
||||
|
||||
if (detailed_view_container_->GetVisible()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (media_controls_container_->MaybeShowMediaControls()) {
|
||||
PreferredSizeChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayView::SetDetailedView(
|
||||
std::unique_ptr<views::View> detailed_view) {
|
||||
auto system_tray_size = system_tray_container_->GetPreferredSize();
|
||||
system_tray_container_->SetVisible(false);
|
||||
|
||||
detailed_view_container_->RemoveAllChildViews();
|
||||
views::View* view =
|
||||
detailed_view_container_->AddChildView(std::move(detailed_view));
|
||||
detailed_view_container_->SetVisible(true);
|
||||
detailed_view_container_->SetPreferredSize(system_tray_size);
|
||||
view->InvalidateLayout();
|
||||
Layout();
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayView::ResetDetailedView() {
|
||||
detailed_view_container_->RemoveAllChildViews();
|
||||
detailed_view_container_->SetVisible(false);
|
||||
media_controls_container_->MaybeShowMediaControls();
|
||||
system_tray_container_->SetVisible(true);
|
||||
sliders_container_->UpdateOpacity();
|
||||
PreferredSizeChanged();
|
||||
Layout();
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayView::SaveFocus() {
|
||||
auto* focus_manager = GetFocusManager();
|
||||
if (!focus_manager) {
|
||||
return;
|
||||
}
|
||||
|
||||
saved_focused_view_ = focus_manager->GetFocusedView();
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayView::RestoreFocus() {
|
||||
if (saved_focused_view_) {
|
||||
saved_focused_view_->RequestFocus();
|
||||
}
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayView::SetExpandedAmount(double expanded_amount) {
|
||||
DCHECK(0.0 <= expanded_amount && expanded_amount <= 1.0);
|
||||
expanded_amount_ = expanded_amount;
|
||||
|
||||
top_shortcuts_view_->SetExpandedAmount(expanded_amount);
|
||||
feature_pods_container_->SetExpandedAmount(expanded_amount);
|
||||
page_indicator_view_->SetExpandedAmount(expanded_amount);
|
||||
media_controls_container_->SetExpandedAmount(expanded_amount);
|
||||
sliders_container_->SetExpandedAmount(expanded_amount);
|
||||
|
||||
PreferredSizeChanged();
|
||||
// It is possible that the ratio between |message_center_view_| and others
|
||||
// can change while the bubble size remain unchanged.
|
||||
Layout();
|
||||
}
|
||||
|
||||
int UnifiedSystemTrayView::GetExpandedSystemTrayHeight() const {
|
||||
return (notification_hidden_view_->GetVisible()
|
||||
? notification_hidden_view_->GetPreferredSize().height()
|
||||
: 0) +
|
||||
top_shortcuts_view_->GetPreferredSize().height() +
|
||||
feature_pods_container_->GetExpandedHeight() +
|
||||
page_indicator_view_->GetExpandedHeight() +
|
||||
sliders_container_->GetExpandedHeight() +
|
||||
media_controls_container_->GetExpandedHeight() +
|
||||
system_info_view_->GetPreferredSize().height();
|
||||
}
|
||||
|
||||
int UnifiedSystemTrayView::GetCollapsedSystemTrayHeight() const {
|
||||
return (notification_hidden_view_->GetVisible()
|
||||
? notification_hidden_view_->GetPreferredSize().height()
|
||||
: 0) +
|
||||
top_shortcuts_view_->GetPreferredSize().height() +
|
||||
feature_pods_container_->GetCollapsedHeight() +
|
||||
system_info_view_->GetPreferredSize().height();
|
||||
}
|
||||
|
||||
int UnifiedSystemTrayView::GetCurrentHeight() const {
|
||||
return GetPreferredSize().height();
|
||||
}
|
||||
|
||||
int UnifiedSystemTrayView::GetVisibleFeaturePodCount() const {
|
||||
return feature_pods_container_->GetVisibleCount();
|
||||
}
|
||||
|
||||
std::u16string UnifiedSystemTrayView::GetDetailedViewAccessibleName() const {
|
||||
return controller_->detailed_view_controller()->GetAccessibleName();
|
||||
}
|
||||
|
||||
bool UnifiedSystemTrayView::IsDetailedViewShown() const {
|
||||
return detailed_view_container_->GetVisible();
|
||||
}
|
||||
|
||||
views::View* UnifiedSystemTrayView::GetFirstFocusableChild() {
|
||||
FocusTraversable* focus_traversable = GetFocusTraversable();
|
||||
views::View* focus_traversable_view = this;
|
||||
return focus_search_->FindNextFocusableView(
|
||||
nullptr, views::FocusSearch::SearchDirection::kForwards,
|
||||
views::FocusSearch::TraversalDirection::kDown,
|
||||
views::FocusSearch::StartingViewPolicy::kSkipStartingView,
|
||||
views::FocusSearch::AnchoredDialogPolicy::kCanGoIntoAnchoredDialog,
|
||||
&focus_traversable, &focus_traversable_view);
|
||||
}
|
||||
|
||||
views::View* UnifiedSystemTrayView::GetLastFocusableChild() {
|
||||
FocusTraversable* focus_traversable = GetFocusTraversable();
|
||||
views::View* focus_traversable_view = this;
|
||||
return focus_search_->FindNextFocusableView(
|
||||
nullptr, views::FocusSearch::SearchDirection::kBackwards,
|
||||
views::FocusSearch::TraversalDirection::kDown,
|
||||
views::FocusSearch::StartingViewPolicy::kSkipStartingView,
|
||||
views::FocusSearch::AnchoredDialogPolicy::kCanGoIntoAnchoredDialog,
|
||||
&focus_traversable, &focus_traversable_view);
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayView::FocusEntered(bool reverse) {
|
||||
views::View* focus_view =
|
||||
reverse ? GetLastFocusableChild() : GetFirstFocusableChild();
|
||||
GetFocusManager()->ClearFocus();
|
||||
GetFocusManager()->SetFocusedView(focus_view);
|
||||
}
|
||||
|
||||
gfx::Size UnifiedSystemTrayView::CalculatePreferredSize() const {
|
||||
int expanded_height = GetExpandedSystemTrayHeight();
|
||||
int collapsed_height = GetCollapsedSystemTrayHeight();
|
||||
|
||||
return gfx::Size(kTrayMenuWidth,
|
||||
collapsed_height + ((expanded_height - collapsed_height) *
|
||||
expanded_amount_));
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayView::OnGestureEvent(ui::GestureEvent* event) {
|
||||
gfx::PointF screen_location = event->root_location_f();
|
||||
switch (event->type()) {
|
||||
case ui::ET_GESTURE_SCROLL_BEGIN:
|
||||
controller_->BeginDrag(screen_location);
|
||||
event->SetHandled();
|
||||
break;
|
||||
case ui::ET_GESTURE_SCROLL_UPDATE:
|
||||
controller_->UpdateDrag(screen_location);
|
||||
event->SetHandled();
|
||||
break;
|
||||
case ui::ET_GESTURE_END:
|
||||
controller_->EndDrag(screen_location);
|
||||
event->SetHandled();
|
||||
break;
|
||||
case ui::ET_SCROLL_FLING_START:
|
||||
controller_->Fling(event->details().velocity_y());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayView::Layout() {
|
||||
if (system_tray_container_->GetVisible()) {
|
||||
system_tray_container_->SetBoundsRect(GetContentsBounds());
|
||||
} else if (detailed_view_container_->GetVisible()) {
|
||||
detailed_view_container_->SetBoundsRect(GetContentsBounds());
|
||||
}
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayView::ChildPreferredSizeChanged(views::View* child) {
|
||||
// The size change is not caused by SetExpandedAmount(), because they don't
|
||||
// trigger PreferredSizeChanged().
|
||||
PreferredSizeChanged();
|
||||
}
|
||||
|
||||
const char* UnifiedSystemTrayView::GetClassName() const {
|
||||
return "UnifiedSystemTrayView";
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayView::AddedToWidget() {
|
||||
focus_manager_ = GetFocusManager();
|
||||
if (focus_manager_) {
|
||||
focus_manager_->AddFocusChangeListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayView::RemovedFromWidget() {
|
||||
if (!focus_manager_) {
|
||||
return;
|
||||
}
|
||||
focus_manager_->RemoveFocusChangeListener(this);
|
||||
focus_manager_ = nullptr;
|
||||
}
|
||||
|
||||
views::FocusTraversable* UnifiedSystemTrayView::GetFocusTraversable() {
|
||||
return this;
|
||||
}
|
||||
|
||||
views::FocusSearch* UnifiedSystemTrayView::GetFocusSearch() {
|
||||
return focus_search_.get();
|
||||
}
|
||||
|
||||
views::FocusTraversable* UnifiedSystemTrayView::GetFocusTraversableParent() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
views::View* UnifiedSystemTrayView::GetFocusTraversableParentView() {
|
||||
return this;
|
||||
}
|
||||
|
||||
void UnifiedSystemTrayView::OnWillChangeFocus(views::View* before,
|
||||
views::View* now) {}
|
||||
|
||||
void UnifiedSystemTrayView::OnDidChangeFocus(views::View* before,
|
||||
views::View* now) {
|
||||
if (feature_pods_container_->Contains(now)) {
|
||||
feature_pods_container_->EnsurePageWithButton(now);
|
||||
}
|
||||
|
||||
views::View* first_view = GetFirstFocusableChild();
|
||||
views::View* last_view = GetLastFocusableChild();
|
||||
|
||||
bool focused_out = false;
|
||||
if (before == last_view && now == first_view) {
|
||||
focused_out = controller_->FocusOut(false);
|
||||
} else if (before == first_view && now == last_view) {
|
||||
focused_out = controller_->FocusOut(true);
|
||||
}
|
||||
|
||||
if (focused_out) {
|
||||
GetFocusManager()->ClearFocus();
|
||||
GetFocusManager()->SetStoredFocusView(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ash
|
@ -1,220 +0,0 @@
|
||||
// Copyright 2018 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ASH_SYSTEM_UNIFIED_UNIFIED_SYSTEM_TRAY_VIEW_H_
|
||||
#define ASH_SYSTEM_UNIFIED_UNIFIED_SYSTEM_TRAY_VIEW_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "ash/ash_export.h"
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "ui/views/focus/focus_manager.h"
|
||||
#include "ui/views/view.h"
|
||||
|
||||
namespace ash {
|
||||
|
||||
class FeaturePodButton;
|
||||
class FeaturePodsContainerView;
|
||||
class TopShortcutsView;
|
||||
class UnifiedMediaControlsContainer;
|
||||
class NotificationHiddenView;
|
||||
class PageIndicatorView;
|
||||
class UnifiedSystemInfoView;
|
||||
class UnifiedSystemTrayController;
|
||||
|
||||
// Container view of slider views. If SetExpandedAmount() is called with 1.0,
|
||||
// the behavior is same as vertiacal BoxLayout, but otherwise it shows
|
||||
// intermediate state during animation.
|
||||
class UnifiedSlidersContainerView : public views::View {
|
||||
public:
|
||||
explicit UnifiedSlidersContainerView(bool initially_expanded);
|
||||
|
||||
UnifiedSlidersContainerView(const UnifiedSlidersContainerView&) = delete;
|
||||
UnifiedSlidersContainerView& operator=(const UnifiedSlidersContainerView&) =
|
||||
delete;
|
||||
|
||||
~UnifiedSlidersContainerView() override;
|
||||
|
||||
// Change the expanded state. 0.0 if collapsed, and 1.0 if expanded.
|
||||
// Otherwise, it shows intermediate state.
|
||||
void SetExpandedAmount(double expanded_amount);
|
||||
|
||||
// Get height of the view when |expanded_amount| is set to 1.0.
|
||||
int GetExpandedHeight() const;
|
||||
|
||||
// Update opacity of each child slider views based on |expanded_amount_|.
|
||||
void UpdateOpacity();
|
||||
|
||||
// views::View:
|
||||
void Layout() override;
|
||||
gfx::Size CalculatePreferredSize() const override;
|
||||
const char* GetClassName() const override;
|
||||
|
||||
private:
|
||||
double expanded_amount_;
|
||||
};
|
||||
|
||||
// View class of the main bubble in UnifiedSystemTray.
|
||||
//
|
||||
// The UnifiedSystemTray contains two sub components:
|
||||
// 1. MessageCenter: contains the list of notifications
|
||||
// 2. SystemTray: contains quick settings controls
|
||||
// Note that the term "UnifiedSystemTray" refers to entire bubble containing
|
||||
// both (1) and (2).
|
||||
class ASH_EXPORT UnifiedSystemTrayView : public views::View,
|
||||
public views::FocusTraversable,
|
||||
public views::FocusChangeListener {
|
||||
public:
|
||||
UnifiedSystemTrayView(UnifiedSystemTrayController* controller,
|
||||
bool initially_expanded);
|
||||
|
||||
UnifiedSystemTrayView(const UnifiedSystemTrayView&) = delete;
|
||||
UnifiedSystemTrayView& operator=(const UnifiedSystemTrayView&) = delete;
|
||||
|
||||
~UnifiedSystemTrayView() override;
|
||||
|
||||
// Set the maximum height that the view can take.
|
||||
void SetMaxHeight(int max_height);
|
||||
|
||||
// Add feature pod button to |feature_pods_|.
|
||||
void AddFeaturePodButton(FeaturePodButton* button);
|
||||
|
||||
// Add slider view.
|
||||
void AddSliderView(std::unique_ptr<views::View> slider_view);
|
||||
|
||||
// Add media controls view to |media_controls_container_|;
|
||||
void AddMediaControlsView(views::View* media_controls);
|
||||
|
||||
// Hide the main view and show the given |detailed_view|.
|
||||
void SetDetailedView(std::unique_ptr<views::View> detailed_view);
|
||||
|
||||
// Remove the detailed view set by SetDetailedView, and show the main view.
|
||||
// It deletes |detailed_view| and children.
|
||||
void ResetDetailedView();
|
||||
|
||||
// Save and restore keyboard focus of the currently focused element. Called
|
||||
// before transitioning into a detailed view.
|
||||
void SaveFocus();
|
||||
void RestoreFocus();
|
||||
|
||||
// Set the first child view to be focused when focus is acquired.
|
||||
// This is the first visible child unless reverse is true, in which case
|
||||
// it is the last visible child.
|
||||
void FocusEntered(bool reverse);
|
||||
|
||||
// Change the expanded state. 0.0 if collapsed, and 1.0 if expanded.
|
||||
// Otherwise, it shows intermediate state. This is triggered during the
|
||||
// progress of expand/collapse animation, updating the children accordingly.
|
||||
void SetExpandedAmount(double expanded_amount);
|
||||
|
||||
// Get height of the system tray (excluding the message center) when
|
||||
// |expanded_amount| is set to 1.0.
|
||||
//
|
||||
// Note that this function is used to calculate the transform-based
|
||||
// collapse/expand animation, which is currently only enabled when there are
|
||||
// no notifications.
|
||||
int GetExpandedSystemTrayHeight() const;
|
||||
|
||||
// Get height of the system menu (excluding the message center) when
|
||||
// |expanded_amount| is set to 0.0.
|
||||
int GetCollapsedSystemTrayHeight() const;
|
||||
|
||||
// Get current height of the view (including the message center).
|
||||
int GetCurrentHeight() const;
|
||||
|
||||
// Returns the number of visible feature pods.
|
||||
int GetVisibleFeaturePodCount() const;
|
||||
|
||||
// Get the accessible name for the currently shown detailed view.
|
||||
std::u16string GetDetailedViewAccessibleName() const;
|
||||
|
||||
// Returns true if a detailed view is being shown in the tray. (e.g Bluetooth
|
||||
// Settings).
|
||||
bool IsDetailedViewShown() const;
|
||||
|
||||
// Show media controls view.
|
||||
void ShowMediaControls();
|
||||
|
||||
// views::View:
|
||||
gfx::Size CalculatePreferredSize() const override;
|
||||
void OnGestureEvent(ui::GestureEvent* event) override;
|
||||
void Layout() override;
|
||||
void ChildPreferredSizeChanged(views::View* child) override;
|
||||
const char* GetClassName() const override;
|
||||
views::FocusTraversable* GetFocusTraversable() override;
|
||||
void AddedToWidget() override;
|
||||
void RemovedFromWidget() override;
|
||||
|
||||
// views::FocusTraversable:
|
||||
views::FocusSearch* GetFocusSearch() override;
|
||||
views::FocusTraversable* GetFocusTraversableParent() override;
|
||||
views::View* GetFocusTraversableParentView() override;
|
||||
|
||||
// views::FocusChangeListener:
|
||||
void OnWillChangeFocus(views::View* before, views::View* now) override;
|
||||
void OnDidChangeFocus(views::View* before, views::View* now) override;
|
||||
|
||||
FeaturePodsContainerView* feature_pods_container() {
|
||||
return feature_pods_container_;
|
||||
}
|
||||
View* detailed_view_container() { return detailed_view_container_; }
|
||||
|
||||
NotificationHiddenView* notification_hidden_view_for_testing() {
|
||||
return notification_hidden_view_;
|
||||
}
|
||||
PageIndicatorView* page_indicator_view_for_test() {
|
||||
return page_indicator_view_;
|
||||
}
|
||||
UnifiedMediaControlsContainer* media_controls_container_for_testing() {
|
||||
return media_controls_container_;
|
||||
}
|
||||
|
||||
private:
|
||||
class SystemTrayContainer;
|
||||
friend class UnifiedMessageCenterBubbleTest;
|
||||
|
||||
// Get first and last focusable child views. These functions are used to
|
||||
// figure out if we need to focus out or to set the correct focused view
|
||||
// when focus is acquired from another widget.
|
||||
View* GetFirstFocusableChild();
|
||||
View* GetLastFocusableChild();
|
||||
|
||||
double expanded_amount_;
|
||||
|
||||
// Unowned.
|
||||
const raw_ptr<UnifiedSystemTrayController,
|
||||
DanglingUntriaged | ExperimentalAsh>
|
||||
controller_;
|
||||
|
||||
// Owned by views hierarchy.
|
||||
const raw_ptr<NotificationHiddenView, ExperimentalAsh>
|
||||
notification_hidden_view_;
|
||||
const raw_ptr<TopShortcutsView, ExperimentalAsh> top_shortcuts_view_;
|
||||
const raw_ptr<FeaturePodsContainerView, ExperimentalAsh>
|
||||
feature_pods_container_;
|
||||
const raw_ptr<PageIndicatorView, ExperimentalAsh> page_indicator_view_;
|
||||
const raw_ptr<UnifiedSlidersContainerView, ExperimentalAsh>
|
||||
sliders_container_;
|
||||
const raw_ptr<UnifiedSystemInfoView, ExperimentalAsh> system_info_view_;
|
||||
const raw_ptr<SystemTrayContainer, ExperimentalAsh> system_tray_container_;
|
||||
const raw_ptr<views::View, ExperimentalAsh> detailed_view_container_;
|
||||
const raw_ptr<UnifiedMediaControlsContainer, ExperimentalAsh>
|
||||
media_controls_container_;
|
||||
|
||||
// The maximum height available to the view.
|
||||
int max_height_ = 0;
|
||||
|
||||
// The view that is saved by calling SaveFocus().
|
||||
raw_ptr<views::View, ExperimentalAsh> saved_focused_view_ = nullptr;
|
||||
|
||||
const std::unique_ptr<views::FocusSearch> focus_search_;
|
||||
|
||||
raw_ptr<views::FocusManager, ExperimentalAsh> focus_manager_ = nullptr;
|
||||
|
||||
const std::unique_ptr<ui::EventHandler> interacted_by_tap_recorder_;
|
||||
};
|
||||
|
||||
} // namespace ash
|
||||
|
||||
#endif // ASH_SYSTEM_UNIFIED_UNIFIED_SYSTEM_TRAY_VIEW_H_
|
@ -22,7 +22,6 @@
|
||||
#include "ash/system/tray/tray_constants.h"
|
||||
#include "ash/system/tray/tray_popup_utils.h"
|
||||
#include "ash/system/tray/tri_view.h"
|
||||
#include "ash/system/unified/top_shortcuts_view.h"
|
||||
#include "ash/system/unified/user_chooser_detailed_view_controller.h"
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
|
@ -17,7 +17,6 @@
|
||||
#include "ash/system/tray/hover_highlight_view.h"
|
||||
#include "ash/system/unified/unified_system_tray.h"
|
||||
#include "ash/system/unified/unified_system_tray_bubble.h"
|
||||
#include "ash/system/unified/unified_system_tray_view.h"
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "chrome/browser/ash/login/login_manager_test.h"
|
||||
#include "chrome/browser/ash/login/session/user_session_manager.h"
|
||||
|
Reference in New Issue
Block a user