| // 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_H_ |
| #define ASH_SYSTEM_UNIFIED_UNIFIED_SYSTEM_TRAY_H_ |
| |
| #include <list> |
| #include <memory> |
| #include <string> |
| |
| #include "ash/ash_export.h" |
| #include "ash/public/cpp/shelf_config.h" |
| #include "ash/public/cpp/tablet_mode_observer.h" |
| #include "ash/system/power/tray_power.h" |
| #include "ash/system/tray/tray_background_view.h" |
| #include "ash/system/unified/unified_system_tray_controller.h" |
| #include "ash/system/unified/unified_system_tray_model.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/memory/scoped_refptr.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/time/time.h" |
| #include "ui/base/metadata/metadata_header_macros.h" |
| #include "ui/display/display_observer.h" |
| |
| namespace display { |
| enum class TabletState; |
| } // namespace display |
| |
| namespace ui { |
| class Event; |
| } // namespace ui |
| |
| namespace views { |
| class Widget; |
| } // namespace views |
| |
| namespace ash { |
| |
| class AutozoomToastController; |
| class CameraMicTrayItemView; |
| class ChannelIndicatorView; |
| class CurrentLocaleView; |
| class HotspotTrayView; |
| class ImeModeView; |
| class ManagedDeviceTrayItemView; |
| class NetworkTrayView; |
| class PrivacyScreenToastController; |
| class Shelf; |
| class TrayBubbleView; |
| class TrayItemView; |
| class TimeTrayItemView; |
| class UnifiedSliderBubbleController; |
| class UnifiedSliderView; |
| class UnifiedSystemTrayBubble; |
| |
| // The UnifiedSystemTray is the system menu of Chromium OS, which is a clickable |
| // rounded rectangle typically located on the bottom right corner of the screen, |
| // (called the Status Area). The system tray shows multiple icons on it to |
| // indicate system status (e.g. time, power, etc.). |
| // |
| // Note that the Status Area refers to the parent container of the |
| // UnifiedSystemTray, which also includes other "trays" such as the ImeMenuTray, |
| // SelectToSpeakTray, VirtualKeyboardTray, etc. |
| // |
| // UnifiedSystemTrayBubble is the actual menu bubble shown above the system tray |
| // after the user clicks on it. The UnifiedSystemTrayBubble is created and owned |
| // by this class. |
| class ASH_EXPORT UnifiedSystemTray |
| : public TrayBackgroundView, |
| public ShelfConfig::Observer, |
| public UnifiedSystemTrayController::Observer, |
| public display::DisplayObserver, |
| public PowerStatus::Observer, |
| public TrayItemView::Observer { |
| METADATA_HEADER(UnifiedSystemTray, TrayBackgroundView) |
| |
| public: |
| class Observer : public base::CheckedObserver { |
| public: |
| // Gets called when showing calendar view. |
| virtual void OnOpeningCalendarView() {} |
| |
| // Gets called when leaving from the calendar view. |
| virtual void OnLeavingCalendarView() {} |
| |
| // Gets called when a slider bubble is shown or closed. |
| virtual void OnSliderBubbleHeightChanged() {} |
| }; |
| |
| explicit UnifiedSystemTray(Shelf* shelf); |
| |
| UnifiedSystemTray(const UnifiedSystemTray&) = delete; |
| UnifiedSystemTray& operator=(const UnifiedSystemTray&) = delete; |
| |
| ~UnifiedSystemTray() override; |
| |
| void AddObserver(Observer* observer); |
| void RemoveObserver(Observer* observer); |
| |
| // Callback called when this is pressed. |
| void OnButtonPressed(const ui::Event& event); |
| |
| // True if the bubble is shown. It does not include slider bubbles, and when |
| // they're shown it still returns false. |
| bool IsBubbleShown() const; |
| |
| // True if a slider bubble e.g. volume slider triggered by keyboard |
| // accelerator is shown. |
| bool IsSliderBubbleShown() const; |
| |
| // Gets the slider view of the slider bubble. |
| UnifiedSliderView* GetSliderView() const; |
| |
| // True if the bubble is active. |
| bool IsBubbleActive() const; |
| |
| // Closes all secondary bubbles (e.g. volume/brightness sliders, autozoom, |
| // privacy screen toast) if any are shown. |
| // TODO(b/279044049): Consider making autozoom and privacy screen slider |
| // bubbles, or have them extend a common class with sliders. |
| void CloseSecondaryBubbles(); |
| |
| // Activates the system tray bubble. |
| void ActivateBubble(); |
| |
| // 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(); |
| |
| // Shows main bubble with audio settings detailed view. |
| void ShowAudioDetailedViewBubble(); |
| |
| // Shows main bubble with display settings detailed view. |
| void ShowDisplayDetailedViewBubble(); |
| |
| // Shows main bubble with network settings detailed view. |
| void ShowNetworkDetailedViewBubble(); |
| |
| // Return the bounds of the bubble in the screen. |
| gfx::Rect GetBubbleBoundsInScreen() const; |
| |
| // Enable / disable UnifiedSystemTray button in status area. If the bubble is |
| // open when disabling, also close it. |
| void SetTrayEnabled(bool enabled); |
| |
| // Notifies the height of the secondary bubble (e.g. Volume/Brightness |
| // sliders, Privacy screen/Autozoom toast) if one is showing so notification |
| // popups or toasts won't overlap with it. Pass 0 if no bubble is shown. |
| void NotifySecondaryBubbleHeight(int height); |
| |
| // Called by `UnifiedSystemTrayBubble` when it is destroyed with the calendar |
| // view in the foreground. |
| void NotifyLeavingCalendarView(); |
| |
| // This enum is for the ChromeOS.SystemTray.FirstInteraction UMA histogram and |
| // should be kept in sync. |
| enum class FirstInteractionType { |
| kQuickSettings = 0, |
| kMessageCenter = 1, |
| kMaxValue = kMessageCenter, |
| }; |
| |
| // Records a metric of the first interaction with the tray bubble, i.e. |
| // whether it was a click/tap on the message center or quick settings. |
| void MaybeRecordFirstInteraction(FirstInteractionType type); |
| |
| // TrayBackgroundView: |
| void ShowBubble() override; |
| void CloseBubbleInternal() override; |
| std::u16string GetAccessibleNameForBubble() override; |
| void HandleLocaleChange() override; |
| void HideBubble(const TrayBubbleView* bubble_view) override; |
| void HideBubbleWithView(const TrayBubbleView* bubble_view) override; |
| void ClickedOutsideBubble(const ui::LocatedEvent& event) override; |
| void UpdateTrayItemColor(bool is_active) override; |
| void UpdateLayout() override; |
| void UpdateAfterLoginStatusChange() override; |
| bool ShouldEnableExtraKeyboardAccessibility() override; |
| views::Widget* GetBubbleWidget() const override; |
| TrayBubbleView* GetBubbleView() override; |
| std::optional<AcceleratorAction> GetAcceleratorAction() const override; |
| |
| // ShelfConfig::Observer: |
| void OnShelfConfigUpdated() override; |
| |
| // PowerStatus::Observer: |
| void OnPowerStatusChanged() override; |
| |
| // UnifiedSystemTrayController::Observer: |
| void OnOpeningCalendarView() override; |
| void OnTransitioningFromCalendarToMainView() override; |
| |
| // display::DisplayObserver: |
| void OnDisplayTabletStateChanged(display::TabletState state) override; |
| |
| // TrayItem::Observer: |
| void OnTrayItemVisibilityAboutToChange(bool target_visibility) override {} |
| void OnTrayItemChildViewChanged() override; |
| |
| // Gets called when an action is performed on the `DateTray`. |
| void OnDateTrayActionPerformed(const ui::Event& event); |
| |
| // Whether the bubble is currently showing the calendar view. |
| bool IsShowingCalendarView() const; |
| |
| // Returns whether the channel indicator should be shown. |
| bool ShouldChannelIndicatorBeShown() const; |
| |
| std::u16string GetAccessibleNameForQuickSettingsBubble(); |
| |
| void UpdateAccessibleName(); |
| |
| scoped_refptr<UnifiedSystemTrayModel> model() { return model_; } |
| UnifiedSystemTrayBubble* bubble() { return bubble_.get(); } |
| |
| ChannelIndicatorView* channel_indicator_view() { |
| return channel_indicator_view_; |
| } |
| |
| UnifiedSliderBubbleController* slider_bubble_controller() { |
| return slider_bubble_controller_.get(); |
| } |
| |
| CameraMicTrayItemView* mic_view() { return mic_view_; } |
| |
| private: |
| friend class NotificationGroupingControllerTest; |
| friend class SystemTrayTestApi; |
| friend class UnifiedSystemTrayTest; |
| friend class PowerTrayViewTest; |
| friend class StatusAreaBatteryPixelTest; |
| friend class UnifiedSystemTrayAccessibilityTest; |
| friend class PrivacyScreenToastControllerTest; |
| |
| // Forwarded from `UiDelegate`. |
| void ShowBubbleInternal(); |
| void HideBubbleInternal(); |
| |
| // Adds the tray item to the the unified system tray container. An unowned |
| // pointer is stored in `tray_items_`. |
| template <typename T> |
| T* AddTrayItemToContainer(std::unique_ptr<T> tray_item_view); |
| |
| // Destroys the `bubble_`, also handles |
| // removing bubble related observers. |
| void DestroyBubble(); |
| |
| // Calculate the accessible name for the tray that will be set in the |
| // ViewAccessibility cache. |
| std::u16string CalculateAccessibleName(); |
| |
| // Callback called when there are changes to the accessible name of child |
| // Views that impact the UnifiedSystemTray's accessible name. |
| void OnChildViewNameChanged(ax::mojom::StringAttribute attribute, |
| const std::optional<std::string>& name); |
| |
| // Registers callbacks for child View properties that impact the tray's |
| // accessible properties. |
| void SubscribeCallbacksForAccessibility(); |
| |
| // The `channel_indicator_view_` can have either an image_view() or a label(), |
| // but not both at the same time. The existence of either impacts the |
| // UnifiedSystemTray's accessible name. As the lifecycle of these objects |
| // change, we will need to update our callbacks. |
| void SubscribeChannelIndicatorImageOrLabelCallbacks(); |
| |
| // Returns the time from `clock_for_testing_` if it is not nullptr, or time |
| // from base::Time::Now() otherwise. |
| void OverrideClockForTesting(base::Clock* test_clock); |
| |
| const base::Time GetTimeNow(); |
| |
| // A clock that can be overridden by tests. |
| raw_ptr<base::Clock> clock_for_testing_ = nullptr; |
| |
| std::unique_ptr<UnifiedSystemTrayBubble> bubble_; |
| |
| // Model class that stores `UnifiedSystemTray`'s UI specific variables. |
| scoped_refptr<UnifiedSystemTrayModel> model_; |
| |
| const std::unique_ptr<UnifiedSliderBubbleController> |
| slider_bubble_controller_; |
| |
| const std::unique_ptr<PrivacyScreenToastController> |
| privacy_screen_toast_controller_; |
| |
| std::unique_ptr<AutozoomToastController> autozoom_toast_controller_; |
| |
| // Owned by the views hierarchy. |
| raw_ptr<CurrentLocaleView> current_locale_view_ = nullptr; |
| raw_ptr<ImeModeView> ime_mode_view_ = nullptr; |
| raw_ptr<ManagedDeviceTrayItemView> managed_device_view_ = nullptr; |
| raw_ptr<CameraMicTrayItemView> camera_view_ = nullptr; |
| raw_ptr<CameraMicTrayItemView> mic_view_ = nullptr; |
| raw_ptr<TimeTrayItemView> time_tray_item_view_ = nullptr; |
| raw_ptr<HotspotTrayView> hotspot_tray_view_ = nullptr; |
| raw_ptr<NetworkTrayView> network_tray_view_ = nullptr; |
| raw_ptr<ChannelIndicatorView> channel_indicator_view_ = nullptr; |
| raw_ptr<PowerTrayView> power_tray_view_ = nullptr; |
| |
| // Contains all tray items views added to tray_container(). |
| std::list<raw_ptr<TrayItemView, CtnExperimental>> tray_items_; |
| |
| bool first_interaction_recorded_ = false; |
| |
| base::ObserverList<Observer> observers_; |
| |
| display::ScopedDisplayObserver display_observer_{this}; |
| |
| // Records time the QS bubble was shown. Used for metrics. |
| base::TimeTicks time_opened_; |
| |
| base::CallbackListSubscription time_view_text_changed_subscription_; |
| base::CallbackListSubscription |
| channel_indicator_visible_changed_subscription_; |
| base::CallbackListSubscription |
| channel_indicator_image_name_changed_subscription_; |
| base::CallbackListSubscription channel_indicator_label_changed_subscription_; |
| base::CallbackListSubscription newtwork_tray_visible_changed_subscription_; |
| base::CallbackListSubscription |
| network_tray_tooltip_text_changed_subscription_; |
| base::CallbackListSubscription hotspot_tray_visible_changed_subscription_; |
| base::CallbackListSubscription |
| hotspot_tray_tooltip_text_changed_subscription_; |
| base::CallbackListSubscription managed_device_visible_changed_subscription_; |
| base::CallbackListSubscription |
| managed_device_image_tooltip_text_changed_subscription_; |
| base::CallbackListSubscription ime_mode_visible_changed_subscription_; |
| base::CallbackListSubscription ime_mode_label_name_changed_subscription_; |
| base::CallbackListSubscription current_locale_visible_changed_subscription_; |
| base::CallbackListSubscription |
| current_locale_label_name_changed_subscription_; |
| |
| base::WeakPtrFactory<UnifiedSystemTray> weak_factory_{this}; |
| }; |
| |
| } // namespace ash |
| |
| #endif // ASH_SYSTEM_UNIFIED_UNIFIED_SYSTEM_TRAY_H_ |